summaryrefslogtreecommitdiffstats
path: root/core/pcie-slot.c
diff options
context:
space:
mode:
authorGavin Shan <gwshan@linux.vnet.ibm.com>2016-08-11 14:55:15 +1000
committerStewart Smith <stewart@linux.vnet.ibm.com>2016-10-11 15:03:54 +1100
commitafadf2e4ddfd548cd6664aa32064d45402c75d08 (patch)
tree6ea39089346071ebf910ec5e47b09c3fd39b8843 /core/pcie-slot.c
parent4295424a6ecfebc683106cf9d2c68007f10620d7 (diff)
downloadtalos-skiboot-afadf2e4ddfd548cd6664aa32064d45402c75d08.tar.gz
talos-skiboot-afadf2e4ddfd548cd6664aa32064d45402c75d08.zip
core/pci: Fix initial PCIe slot power state
The initial PCIe slot power state should be retrieved from the PCIe Slot Control register (offset: +0x18), instead of having the fixed state (power-off) wrongly. Otherwise, we possibly have mismatched states by software and hardware. One side-effect is PCIe slot can not be powered off from hardware for the first time. This fixes above issue by fetching the initial PCIe slot power state from hardware (PCIe Slot Control register) if the power control is supported on the slot. Otherwise, it doesn't matter on what we have for the initial PCIe slot power state. Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com> [stewart@linux.vnet.ibm.com: use PCI_SLOT_POWER_ON|OFF rather than 1/0] Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'core/pcie-slot.c')
-rw-r--r--core/pcie-slot.c15
1 files changed, 14 insertions, 1 deletions
diff --git a/core/pcie-slot.c b/core/pcie-slot.c
index 62933a40..6854ef1d 100644
--- a/core/pcie-slot.c
+++ b/core/pcie-slot.c
@@ -404,6 +404,7 @@ struct pci_slot *pcie_slot_create(struct phb *phb, struct pci_device *pd)
{
struct pci_slot *slot;
uint32_t ecap;
+ uint16_t slot_ctl;
/* Allocate PCI slot */
slot = pci_slot_alloc(phb, pd);
@@ -422,8 +423,20 @@ struct pci_slot *pcie_slot_create(struct phb *phb, struct pci_device *pd)
if ((slot->slot_cap & PCICAP_EXP_SLOTCAP_HPLUG_SURP) &&
(slot->slot_cap & PCICAP_EXP_SLOTCAP_HPLUG_CAP))
slot->pluggable = 1;
- if (slot->slot_cap & PCICAP_EXP_SLOTCAP_PWCTRL)
+
+ if (slot->slot_cap & PCICAP_EXP_SLOTCAP_PWCTRL) {
slot->power_ctl = 1;
+
+ /* The power is on by default */
+ slot->power_state = PCI_SLOT_POWER_ON;
+ if (pd && ecap) {
+ pci_cfg_read16(phb, pd->bdfn,
+ ecap + PCICAP_EXP_SLOTCTL, &slot_ctl);
+ if (slot_ctl & PCICAP_EXP_SLOTCTL_PWRCTLR)
+ slot->power_state = PCI_SLOT_POWER_OFF;
+ }
+ }
+
if (slot->slot_cap & PCICAP_EXP_SLOTCAP_PWRI)
slot->power_led_ctl = PCI_SLOT_PWR_LED_CTL_KERNEL;
if (slot->slot_cap & PCICAP_EXP_SLOTCAP_ATTNI)
OpenPOWER on IntegriCloud