diff mbox

[06/16] core/pci: Fix PCIe slot power state

Message ID 1474002323-31380-7-git-send-email-gwshan@linux.vnet.ibm.com
State Superseded
Headers show

Commit Message

Gavin Shan Sept. 16, 2016, 5:05 a.m. UTC
The power state of PCIe slot should be retrieved from the PCIe
Slot Control register (offset: +0x18), instead of having the
fixed state (power-off) wrongly. Otherwise, we have mismatched
states (off in software, on in hardware) after powering off the
slot.

This retrieves the PCIe slot power state from PCIe Slot Control
Register if the power control is supported. Otherwise, the initial
power state of the PCIe slot doesn't matter and it's set to on.

Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com>
---
 core/pcie-slot.c | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

Comments

Stewart Smith Sept. 27, 2016, 7:32 a.m. UTC | #1
Gavin Shan <gwshan@linux.vnet.ibm.com> writes:
> The power state of PCIe slot should be retrieved from the PCIe
> Slot Control register (offset: +0x18), instead of having the
> fixed state (power-off) wrongly. Otherwise, we have mismatched
> states (off in software, on in hardware) after powering off the
> slot.
>
> This retrieves the PCIe slot power state from PCIe Slot Control
> Register if the power control is supported. Otherwise, the initial
> power state of the PCIe slot doesn't matter and it's set to on.
>
> Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com>
> ---
>  core/pcie-slot.c | 15 ++++++++++++++-
>  1 file changed, 14 insertions(+), 1 deletion(-)

Should this also be CC: stable ?
Perhaps also Fixes: bc66fb67aee6f9e6520120c2476d58f3899c9221 ?
diff mbox

Patch

diff --git a/core/pcie-slot.c b/core/pcie-slot.c
index 62933a4..6854ef1 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)