Skip to content

Commit 38e51a3

Browse files
fbarratoohal
authored andcommitted
core/pci: Add missing lock in set_power_timer
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>
1 parent f6f247a commit 38e51a3

File tree

2 files changed

+12
-0
lines changed

2 files changed

+12
-0
lines changed

core/pci-opal.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -674,6 +674,12 @@ static void set_power_timer(struct timer *t __unused, void *data,
674674
struct pci_device *pd = slot->pd;
675675
struct dt_node *dn = pd->dn;
676676
uint8_t link;
677+
struct phb *phb = slot->phb;
678+
679+
if (!phb_try_lock(phb)) {
680+
schedule_timer(&slot->timer, msecs_to_tb(10));
681+
return;
682+
}
677683

678684
switch (slot->state) {
679685
case PCI_SLOT_STATE_SPOWER_START:
@@ -720,6 +726,7 @@ static void set_power_timer(struct timer *t __unused, void *data,
720726
prlog(PR_ERR, "PCI SLOT %016llx: Unexpected state 0x%08x\n",
721727
slot->id, slot->state);
722728
}
729+
phb_unlock(phb);
723730
}
724731

725732
static int64_t opal_pci_set_power_state(uint64_t async_token,

include/pci.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,11 @@ static inline void phb_lock(struct phb *phb)
390390
lock(&phb->lock);
391391
}
392392

393+
static inline bool phb_try_lock(struct phb *phb)
394+
{
395+
return try_lock(&phb->lock);
396+
}
397+
393398
static inline void phb_unlock(struct phb *phb)
394399
{
395400
unlock(&phb->lock);

0 commit comments

Comments
 (0)