diff mbox

pci: Check power state before powering off slot

Message ID 1477028875-22567-1-git-send-email-gwshan@linux.vnet.ibm.com
State Accepted
Headers show

Commit Message

Gavin Shan Oct. 21, 2016, 5:47 a.m. UTC
I made the inappropriate assumption: PCI slot's power state is
always on from the beginning. We don't check the slot's power
state before turning it off in PCI enumeration path when there
are no PCI adapters behind the slot. The PCI slot's power might
have been turned off and we needn't power it off again. Otherwise,
the below (not harmful) message is raised:

[   47.243635711,5] SkiBoot skiboot-5.4.0-rc1 starting...
       :
[   13.239871630,5] PHB#0001:02:01.0 Error -1 powering off slot

This checks power state and avoid turning it off again if it's
already in off state. Flag PCI_SLOT_FLAG_BOOTUP is also removed
after the requested operation is completed as the flag should
be used at skiboot booting stage.

Cc: stable # 5.3.0+
Reported-by: Pridhiviraj Paidipeddi <ppaidipe@linux.vnet.ibm.com>
Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com>
Tested-by: Pridhiviraj Paidipeddi <ppaidipe@linux.vnet.ibm.com>
---
 core/pci.c | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

Comments

Stewart Smith Oct. 24, 2016, 3:07 a.m. UTC | #1
Gavin Shan <gwshan@linux.vnet.ibm.com> writes:
> I made the inappropriate assumption: PCI slot's power state is
> always on from the beginning. We don't check the slot's power
> state before turning it off in PCI enumeration path when there
> are no PCI adapters behind the slot. The PCI slot's power might
> have been turned off and we needn't power it off again. Otherwise,
> the below (not harmful) message is raised:
>
> [   47.243635711,5] SkiBoot skiboot-5.4.0-rc1 starting...
>        :
> [   13.239871630,5] PHB#0001:02:01.0 Error -1 powering off slot
>
> This checks power state and avoid turning it off again if it's
> already in off state. Flag PCI_SLOT_FLAG_BOOTUP is also removed
> after the requested operation is completed as the flag should
> be used at skiboot booting stage.
>
> Cc: stable # 5.3.0+
> Reported-by: Pridhiviraj Paidipeddi <ppaidipe@linux.vnet.ibm.com>
> Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com>
> Tested-by: Pridhiviraj Paidipeddi <ppaidipe@linux.vnet.ibm.com>

Thanks, merged to
master as of 1408f6f
and skiboot-5.3.x as of 9770dbf
diff mbox

Patch

diff --git a/core/pci.c b/core/pci.c
index ba7cd9d..4160299 100644
--- a/core/pci.c
+++ b/core/pci.c
@@ -501,6 +501,7 @@  void pci_remove_bus(struct phb *phb, struct list_head *list)
 static void pci_slot_power_off(struct phb *phb, struct pci_device *pd)
 {
 	struct pci_slot *slot;
+	uint8_t pstate;
 	int32_t wait = 100;
 	int64_t rc;
 
@@ -508,7 +509,9 @@  static void pci_slot_power_off(struct phb *phb, struct pci_device *pd)
 		return;
 
 	slot = pd->slot;
-	if (!slot->pluggable || !slot->ops.set_power_state)
+	if (!slot->pluggable ||
+	    !slot->ops.get_power_state ||
+	    !slot->ops.set_power_state)
 		return;
 
 	/* Bail if there're something connected */
@@ -516,11 +519,23 @@  static void pci_slot_power_off(struct phb *phb, struct pci_device *pd)
 		return;
 
 	pci_slot_add_flags(slot, PCI_SLOT_FLAG_BOOTUP);
+	rc = slot->ops.get_power_state(slot, &pstate);
+	if (rc != OPAL_SUCCESS) {
+		pci_slot_remove_flags(slot, PCI_SLOT_FLAG_BOOTUP);
+		PCINOTICE(phb, pd->bdfn, "Error %lld getting slot power state\n", rc);
+		return;
+	} else if (pstate == PCI_SLOT_POWER_OFF) {
+		pci_slot_remove_flags(slot, PCI_SLOT_FLAG_BOOTUP);
+		return;
+	}
+
 	rc = slot->ops.set_power_state(slot, PCI_SLOT_POWER_OFF);
 	if (rc == OPAL_SUCCESS) {
+		pci_slot_remove_flags(slot, PCI_SLOT_FLAG_BOOTUP);
 		PCIDBG(phb, pd->bdfn, "Power off hotpluggable slot\n");
 		return;
 	} else if (rc != OPAL_ASYNC_COMPLETION) {
+		pci_slot_remove_flags(slot, PCI_SLOT_FLAG_BOOTUP);
 		pci_slot_set_state(slot, PCI_SLOT_STATE_NORMAL);
 		PCINOTICE(phb, pd->bdfn, "Error %lld powering off slot\n", rc);
 		return;
@@ -534,6 +549,7 @@  static void pci_slot_power_off(struct phb *phb, struct pci_device *pd)
 		time_wait_ms(10);
 	} while (--wait >= 0);
 
+	pci_slot_remove_flags(slot, PCI_SLOT_FLAG_BOOTUP);
 	pci_slot_set_state(slot, PCI_SLOT_STATE_NORMAL);
 	if (wait >= 0)
 		PCIDBG(phb, pd->bdfn, "Power off hotpluggable slot\n");