summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr/src/uts/common/io/pciex/hotplug/pciehpc.c39
1 files changed, 26 insertions, 13 deletions
diff --git a/usr/src/uts/common/io/pciex/hotplug/pciehpc.c b/usr/src/uts/common/io/pciex/hotplug/pciehpc.c
index eaf09ee4e6..ce18cec3e2 100644
--- a/usr/src/uts/common/io/pciex/hotplug/pciehpc.c
+++ b/usr/src/uts/common/io/pciex/hotplug/pciehpc.c
@@ -22,6 +22,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2019 Joyent, Inc.
+ * Copyright 2022 Oxide Computer Company
*/
/*
@@ -890,6 +891,27 @@ pciehpc_enable_intr(pcie_hp_ctrl_t *ctrl_p)
pcie_hp_slot_t *slot_p = ctrl_p->hc_slots[0];
pcie_bus_t *bus_p = PCIE_DIP2BUS(ctrl_p->hc_dip);
uint16_t reg;
+ uint16_t intr_mask = PCIE_SLOTCTL_INTR_MASK;
+
+ /*
+ * power fault detection interrupt is enabled only
+ * when the slot is powered ON
+ */
+ if (slot_p->hs_info.cn_state < DDI_HP_CN_STATE_POWERED)
+ intr_mask &= ~PCIE_SLOTCTL_PWR_FAULT_EN;
+
+ /*
+ * enable interrupt sources but leave the top-level
+ * interrupt disabled. some sources may generate a
+ * spurrious event when they are first enabled.
+ * by leaving the top-level interrupt disabled, those
+ * can be cleared first.
+ */
+ reg = pciehpc_reg_get16(ctrl_p,
+ bus_p->bus_pcie_off + PCIE_SLOTCTL);
+ pciehpc_reg_put16(ctrl_p,
+ bus_p->bus_pcie_off + PCIE_SLOTCTL,
+ reg | (intr_mask & ~PCIE_SLOTCTL_HP_INTR_EN));
/* clear any interrupt status bits */
reg = pciehpc_reg_get16(ctrl_p,
@@ -897,21 +919,12 @@ pciehpc_enable_intr(pcie_hp_ctrl_t *ctrl_p)
pciehpc_reg_put16(ctrl_p,
bus_p->bus_pcie_off + PCIE_SLOTSTS, reg);
- /* read the Slot Control Register */
+ /* enable top-level interrupt */
reg = pciehpc_reg_get16(ctrl_p,
bus_p->bus_pcie_off + PCIE_SLOTCTL);
-
- /*
- * enable interrupts: power fault detection interrupt is enabled
- * only when the slot is powered ON
- */
- if (slot_p->hs_info.cn_state >= DDI_HP_CN_STATE_POWERED)
- pciehpc_reg_put16(ctrl_p, bus_p->bus_pcie_off +
- PCIE_SLOTCTL, reg | PCIE_SLOTCTL_INTR_MASK);
- else
- pciehpc_reg_put16(ctrl_p, bus_p->bus_pcie_off +
- PCIE_SLOTCTL, reg | (PCIE_SLOTCTL_INTR_MASK &
- ~PCIE_SLOTCTL_PWR_FAULT_EN));
+ pciehpc_reg_put16(ctrl_p,
+ bus_p->bus_pcie_off + PCIE_SLOTCTL,
+ reg | intr_mask);
return (DDI_SUCCESS);
}