aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrederic Barrat <fbarrat@linux.ibm.com>2019-10-09 21:37:57 +0200
committerVasant Hegde <hegdevasant@linux.vnet.ibm.com>2020-03-10 16:29:28 +0530
commite5bf92eb54e97f8e7c78cf235270ecf49f3a4b10 (patch)
tree520a0b303ab0b974f467cd8459e2560a657dbe10
parent9fea39b17d63e64928d4d54f0024aceaada53bfe (diff)
downloadskiboot-e5bf92eb54e97f8e7c78cf235270ecf49f3a4b10.zip
skiboot-e5bf92eb54e97f8e7c78cf235270ecf49f3a4b10.tar.gz
skiboot-e5bf92eb54e97f8e7c78cf235270ecf49f3a4b10.tar.bz2
core/pci: Add missing lock in set_power_timer
[ Upstream commit 38e51a31c815befd9b455fd6896d0753ebeb4a38 ] set_power_timer() was not using any lock, though it alters the slot state and devices found under it. There's a remote possibility that set_power_timer() is called through check_timers() by a thread already holding the phb lock, so we try to take the lock but yield and rearm the timer if somebody else is already owning it. There really shouldn't be any contention here. Signed-off-by: Frederic Barrat <fbarrat@linux.ibm.com> Signed-off-by: Oliver O'Halloran <oohall@gmail.com> Signed-off-by: Vasant Hegde <hegdevasant@linux.vnet.ibm.com>
-rw-r--r--core/pci-opal.c7
-rw-r--r--include/pci.h5
2 files changed, 12 insertions, 0 deletions
diff --git a/core/pci-opal.c b/core/pci-opal.c
index d520960..b63be61 100644
--- a/core/pci-opal.c
+++ b/core/pci-opal.c
@@ -674,6 +674,12 @@ static void set_power_timer(struct timer *t __unused, void *data,
struct pci_device *pd = slot->pd;
struct dt_node *dn = pd->dn;
uint8_t link;
+ struct phb *phb = slot->phb;
+
+ if (!phb_try_lock(phb)) {
+ schedule_timer(&slot->timer, msecs_to_tb(10));
+ return;
+ }
switch (slot->state) {
case PCI_SLOT_STATE_SPOWER_START:
@@ -720,6 +726,7 @@ static void set_power_timer(struct timer *t __unused, void *data,
prlog(PR_ERR, "PCI SLOT %016llx: Unexpected state 0x%08x\n",
slot->id, slot->state);
}
+ phb_unlock(phb);
}
static int64_t opal_pci_set_power_state(uint64_t async_token,
diff --git a/include/pci.h b/include/pci.h
index 220d6b1..3c9544b 100644
--- a/include/pci.h
+++ b/include/pci.h
@@ -387,6 +387,11 @@ static inline void phb_lock(struct phb *phb)
lock(&phb->lock);
}
+static inline bool phb_try_lock(struct phb *phb)
+{
+ return try_lock(&phb->lock);
+}
+
static inline void phb_unlock(struct phb *phb)
{
unlock(&phb->lock);