diff options
Diffstat (limited to 'usr/src/uts/common/io/hotplug/pciehpc/pciehpc.c')
-rw-r--r-- | usr/src/uts/common/io/hotplug/pciehpc/pciehpc.c | 62 |
1 files changed, 57 insertions, 5 deletions
diff --git a/usr/src/uts/common/io/hotplug/pciehpc/pciehpc.c b/usr/src/uts/common/io/hotplug/pciehpc/pciehpc.c index 41435779fa..737a83ea7c 100644 --- a/usr/src/uts/common/io/hotplug/pciehpc/pciehpc.c +++ b/usr/src/uts/common/io/hotplug/pciehpc/pciehpc.c @@ -746,9 +746,14 @@ pciehpc_enable_intr(pciehpc_t *ctrl_p) reg = pciehpc_reg_get16(ctrl_p, ctrl_p->pcie_caps_reg_offset + PCIE_SLOTCTL); - /* enable all interrupts */ - pciehpc_reg_put16(ctrl_p, ctrl_p->pcie_caps_reg_offset + - PCIE_SLOTCTL, reg | SLOTCTL_SUPPORTED_INTRS_MASK); + /* enable interrupts */ + if (ctrl_p->slot.slot_state == HPC_SLOT_CONNECTED) + pciehpc_reg_put16(ctrl_p, ctrl_p->pcie_caps_reg_offset + + PCIE_SLOTCTL, reg | SLOTCTL_SUPPORTED_INTRS_MASK); + else + pciehpc_reg_put16(ctrl_p, ctrl_p->pcie_caps_reg_offset + + PCIE_SLOTCTL, reg | (SLOTCTL_SUPPORTED_INTRS_MASK & + ~PCIE_SLOTCTL_PWR_FAULT_EN)); return (DDI_SUCCESS); } @@ -1075,9 +1080,45 @@ pciehpc_slot_connect(caddr_t ops_arg, hpc_slot_t slot_hdl, control &= ~PCIE_SLOTCTL_PWR_CONTROL; pciehpc_issue_hpc_command(ctrl_p, control); - /* NOTE - any check to make sure power is really turned ON? */ + /* check power is really turned ON? */ + control = pciehpc_reg_get16(ctrl_p, + ctrl_p->pcie_caps_reg_offset + PCIE_SLOTCTL); + if (control & PCIE_SLOTCTL_PWR_CONTROL) { + PCIEHPC_DEBUG((CE_NOTE, + "slot %d fails to turn on power on connect\n", + ctrl_p->slot.slotNum)); + + goto cleanup1; + } + + /* check power-fault on the slot? */ + status = pciehpc_reg_get16(ctrl_p, + ctrl_p->pcie_caps_reg_offset + PCIE_SLOTSTS); + if (status & PCIE_SLOTSTS_PWR_FAULT_DETECTED) { + PCIEHPC_DEBUG((CE_NOTE, + "slot %d detects power fault on connect\n", + ctrl_p->slot.slotNum)); - /* NOTE - what about power-fault on the slot? */ + /* set power control to OFF */ + control = pciehpc_reg_get16(ctrl_p, + ctrl_p->pcie_caps_reg_offset + PCIE_SLOTCTL); + control |= PCIE_SLOTCTL_PWR_CONTROL; + pciehpc_issue_hpc_command(ctrl_p, control); + + /* clear the status */ + pciehpc_reg_put16(ctrl_p, + ctrl_p->pcie_caps_reg_offset + PCIE_SLOTSTS, status); + goto cleanup1; + } + + /* enable all interrupts */ + pciehpc_reg_put16(ctrl_p, + ctrl_p->pcie_caps_reg_offset + PCIE_SLOTSTS, status); + + control = pciehpc_reg_get16(ctrl_p, + ctrl_p->pcie_caps_reg_offset + PCIE_SLOTCTL); + pciehpc_reg_put16(ctrl_p, ctrl_p->pcie_caps_reg_offset + + PCIE_SLOTCTL, control | SLOTCTL_SUPPORTED_INTRS_MASK); /* 3. Set power LED to be ON */ pciehpc_set_led_state(ctrl_p, HPC_POWER_LED, HPC_LED_ON); @@ -1093,6 +1134,10 @@ pciehpc_slot_connect(caddr_t ops_arg, hpc_slot_t slot_hdl, mutex_exit(&ctrl_p->pciehpc_mutex); return (HPC_SUCCESS); +cleanup1: + /* set power led to OFF */ + pciehpc_set_led_state(ctrl_p, HPC_POWER_LED, HPC_LED_OFF); + cleanup: mutex_exit(&ctrl_p->pciehpc_mutex); return (HPC_ERR_FAILED); @@ -1177,6 +1222,13 @@ pciehpc_slot_disconnect(caddr_t ops_arg, hpc_slot_t slot_hdl, pciehpc_set_led_state(ctrl_p, HPC_POWER_LED, HPC_LED_OFF); pciehpc_set_led_state(ctrl_p, HPC_ATTN_LED, HPC_LED_OFF); + /* disable interrupt of power fault detection */ + control = pciehpc_reg_get16(ctrl_p, + ctrl_p->pcie_caps_reg_offset + PCIE_SLOTCTL); + pciehpc_reg_put16(ctrl_p, ctrl_p->pcie_caps_reg_offset + + PCIE_SLOTCTL, control | (SLOTCTL_SUPPORTED_INTRS_MASK & + ~PCIE_SLOTCTL_PWR_FAULT_EN)); + ctrl_p->slot.slot_state = HPC_SLOT_DISCONNECTED; mutex_exit(&ctrl_p->pciehpc_mutex); return (HPC_SUCCESS); |