aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStewart Smith <stewart@linux.ibm.com>2018-04-27 15:59:53 +1000
committerStewart Smith <stewart@linux.ibm.com>2018-04-29 19:52:30 -0500
commitb5f8695e8983afc18caab65003cffe6b5bf4d5ec (patch)
tree7884775ad2a08cc4ec6b3634dbfa9fc1e7faa971
parent4acd876d21b71d15b9eca2ddf741f7f5aea0c7b8 (diff)
downloadskiboot-b5f8695e8983afc18caab65003cffe6b5bf4d5ec.zip
skiboot-b5f8695e8983afc18caab65003cffe6b5bf4d5ec.tar.gz
skiboot-b5f8695e8983afc18caab65003cffe6b5bf4d5ec.tar.bz2
OPAL_PCI_SET_POWER_STATE: fix locking in error paths
Otherwise we could exit OPAL holding locks, potentially leading to all sorts of problems later on. Cc: stable # 5.3+ Fixes: 7a3e2c4ee3aa0 Signed-off-by: Stewart Smith <stewart@linux.ibm.com> (cherry picked from commit a22ba4576ad35dccb86622e71442794d09e62bce) Signed-off-by: Stewart Smith <stewart@linux.ibm.com>
-rw-r--r--core/pci-opal.c16
1 files changed, 12 insertions, 4 deletions
diff --git a/core/pci-opal.c b/core/pci-opal.c
index 27872aa..5dc05fc 100644
--- a/core/pci-opal.c
+++ b/core/pci-opal.c
@@ -785,8 +785,10 @@ static int64_t opal_pci_set_power_state(uint64_t async_token,
switch (*state) {
case OPAL_PCI_SLOT_POWER_OFF:
if (!slot->ops.prepare_link_change ||
- !slot->ops.set_power_state)
+ !slot->ops.set_power_state) {
+ phb_unlock(phb);
return OPAL_UNSUPPORTED;
+ }
slot->async_token = async_token;
slot->ops.prepare_link_change(slot, false);
@@ -794,22 +796,28 @@ static int64_t opal_pci_set_power_state(uint64_t async_token,
break;
case OPAL_PCI_SLOT_POWER_ON:
if (!slot->ops.set_power_state ||
- !slot->ops.get_link_state)
+ !slot->ops.get_link_state) {
+ phb_unlock(phb);
return OPAL_UNSUPPORTED;
+ }
slot->async_token = async_token;
rc = slot->ops.set_power_state(slot, PCI_SLOT_POWER_ON);
break;
case OPAL_PCI_SLOT_OFFLINE:
- if (!pd)
+ if (!pd) {
+ phb_unlock(phb);
return OPAL_PARAMETER;
+ }
pci_remove_bus(phb, &pd->children);
phb_unlock(phb);
return OPAL_SUCCESS;
case OPAL_PCI_SLOT_ONLINE:
- if (!pd)
+ if (!pd) {
+ phb_unlock(phb);
return OPAL_PARAMETER;
+ }
pci_scan_bus(phb, pd->secondary_bus, pd->subordinate_bus,
&pd->children, pd, true);
pci_add_device_nodes(phb, &pd->children, pd->dn,