summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/dev/pci/pci_pci.c64
-rw-r--r--sys/dev/pci/pcib_private.h2
2 files changed, 21 insertions, 45 deletions
diff --git a/sys/dev/pci/pci_pci.c b/sys/dev/pci/pci_pci.c
index 5e14e95..afc0a08 100644
--- a/sys/dev/pci/pci_pci.c
+++ b/sys/dev/pci/pci_pci.c
@@ -874,8 +874,11 @@ pcib_probe_hotplug(struct pcib_softc *sc)
/*
* 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)
@@ -884,28 +887,20 @@ pcib_pcie_hotplug_command(struct pcib_softc *sc, uint16_t val, uint16_t mask)
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);
}
}
@@ -913,7 +908,6 @@ static void
pcib_pcie_hotplug_command_completed(struct pcib_softc *sc)
{
device_t dev;
- uint16_t ctl, new;
dev = sc->dev;
@@ -921,23 +915,8 @@ pcib_pcie_hotplug_command_completed(struct pcib_softc *sc)
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;
}
/*
@@ -1041,11 +1020,10 @@ pcib_pcie_hotplug_update(struct pcib_softc *sc, uint16_t val, uint16_t mask,
* 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;
- }
}
/*
diff --git a/sys/dev/pci/pcib_private.h b/sys/dev/pci/pcib_private.h
index 7d43e60..2d805a9 100644
--- a/sys/dev/pci/pcib_private.h
+++ b/sys/dev/pci/pcib_private.h
@@ -134,8 +134,6 @@ struct pcib_softc
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;
OpenPOWER on IntegriCloud