Index: sys/dev/pci/pci_pci.c =================================================================== --- sys/dev/pci/pci_pci.c +++ sys/dev/pci/pci_pci.c @@ -873,8 +873,11 @@ /* * Send a HotPlug command to the slot control register. If this slot - * uses command completion interrupts, these updates will be buffered - * while a previous command is completing. + * uses command completion interrupts and a previous command is still + * in progress, then the command is dropped. Once the previous + * command completes or times out, pcib_pcie_hotplug_update() will be + * invoked to post a new command based on the slot's state at that + * time. */ static void pcib_pcie_hotplug_command(struct pcib_softc *sc, uint16_t val, uint16_t mask) @@ -883,28 +886,20 @@ uint16_t ctl, new; dev = sc->dev; - if (sc->pcie_slot_cap & PCIEM_SLOT_CAP_NCCS) { - ctl = pcie_read_config(dev, PCIER_SLOT_CTL, 2); - new = (ctl & ~mask) | val; - if (new != ctl) - pcie_write_config(dev, PCIER_SLOT_CTL, new, 2); + + if (sc->flags & PCIB_HOTPLUG_CMD_PENDING) return; - } - if (sc->flags & PCIB_HOTPLUG_CMD_PENDING) { - sc->pcie_pending_link_ctl_val &= ~mask; - sc->pcie_pending_link_ctl_val |= val; - sc->pcie_pending_link_ctl_mask |= mask; - } else { - ctl = pcie_read_config(dev, PCIER_SLOT_CTL, 2); - new = (ctl & ~mask) | val; - if (new != ctl) { - pcie_write_config(dev, PCIER_SLOT_CTL, ctl, 2); - sc->flags |= PCIB_HOTPLUG_CMD_PENDING; - if (!cold) - callout_reset(&sc->pcie_cc_timer, hz, - pcib_pcie_cc_timeout, sc); - } + ctl = pcie_read_config(dev, PCIER_SLOT_CTL, 2); + new = (ctl & ~mask) | val; + if (new == ctl) + return; + pcie_write_config(dev, PCIER_SLOT_CTL, new, 2); + if (!(sc->pcie_slot_cap & PCIEM_SLOT_CAP_NCCS)) { + sc->flags |= PCIB_HOTPLUG_CMD_PENDING; + if (!cold) + callout_reset(&sc->pcie_cc_timer, hz, + pcib_pcie_cc_timeout, sc); } } @@ -912,7 +907,6 @@ pcib_pcie_hotplug_command_completed(struct pcib_softc *sc) { device_t dev; - uint16_t ctl, new; dev = sc->dev; @@ -920,23 +914,8 @@ device_printf(dev, "Command Completed\n"); if (!(sc->flags & PCIB_HOTPLUG_CMD_PENDING)) return; - if (sc->pcie_pending_link_ctl_mask != 0) { - ctl = pcie_read_config(dev, PCIER_SLOT_CTL, 2); - new = ctl & ~sc->pcie_pending_link_ctl_mask; - new |= sc->pcie_pending_link_ctl_val; - if (new != ctl) { - pcie_write_config(dev, PCIER_SLOT_CTL, ctl, 2); - if (!cold) - callout_reset(&sc->pcie_cc_timer, hz, - pcib_pcie_cc_timeout, sc); - } else - sc->flags &= ~PCIB_HOTPLUG_CMD_PENDING; - sc->pcie_pending_link_ctl_mask = 0; - sc->pcie_pending_link_ctl_val = 0; - } else { - callout_stop(&sc->pcie_cc_timer); - sc->flags &= ~PCIB_HOTPLUG_CMD_PENDING; - } + callout_stop(&sc->pcie_cc_timer); + sc->flags &= ~PCIB_HOTPLUG_CMD_PENDING; } /* @@ -1040,11 +1019,10 @@ * Interlock. */ if (sc->pcie_slot_cap & PCIEM_SLOT_CAP_EIP) { + mask |= PCIEM_SLOT_CTL_EIC; if (card_inserted != - !(sc->pcie_slot_sta & PCIEM_SLOT_STA_EIS)) { - mask |= PCIEM_SLOT_CTL_EIC; + !(sc->pcie_slot_sta & PCIEM_SLOT_STA_EIS)) val |= PCIEM_SLOT_CTL_EIC; - } } /* Index: sys/dev/pci/pcib_private.h =================================================================== --- sys/dev/pci/pcib_private.h +++ sys/dev/pci/pcib_private.h @@ -134,8 +134,6 @@ uint16_t pcie_slot_sta; uint32_t pcie_link_cap; uint32_t pcie_slot_cap; - uint16_t pcie_pending_link_ctl_mask; - uint16_t pcie_pending_link_ctl_val; struct resource *pcie_irq; void *pcie_ihand; struct task pcie_hp_task;