diff mbox

[4/7] core/pci: Fix initial PCIe slot power state

Message ID 1470891318-23046-5-git-send-email-gwshan@linux.vnet.ibm.com
State Accepted
Headers show

Commit Message

Gavin Shan Aug. 11, 2016, 4:55 a.m. UTC
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>
---
 core/pcie-slot.c | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

Comments

Andrew Donnellan Aug. 11, 2016, 5:16 a.m. UTC | #1
On 11/08/16 14:55, Gavin Shan wrote:
> +	if (slot->slot_cap & PCICAP_EXP_SLOTCAP_PWCTRL) {
>  		slot->power_ctl = 1;
> +
> +		/* The power is on by default */
> +		slot->power_state = 1;

Can we use PCI_SLOT_POWER_ON rather than 1?

> +		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 = 0;

PCI_SLOT_POWER_OFF?
Gavin Shan Aug. 11, 2016, 5:24 a.m. UTC | #2
On Thu, Aug 11, 2016 at 03:16:43PM +1000, Andrew Donnellan wrote:
>On 11/08/16 14:55, Gavin Shan wrote:
>>+	if (slot->slot_cap & PCICAP_EXP_SLOTCAP_PWCTRL) {
>> 		slot->power_ctl = 1;
>>+
>>+		/* The power is on by default */
>>+		slot->power_state = 1;
>
>Can we use PCI_SLOT_POWER_ON rather than 1?
>
>>+		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 = 0;
>
>PCI_SLOT_POWER_OFF?
>

Yes, PCI_SLOT_POWER_{OFF, ON} should be used in next respin.

Thanks,
Gavin
diff mbox

Patch

diff --git a/core/pcie-slot.c b/core/pcie-slot.c
index 62933a4..358e61a 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 = 1;
+		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 = 0;
+		}
+	}
+
 	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)