Skip to content

Commit 7475f93

Browse files
committed
Merge branch 'pci/hotplug'
- Fix infinite loop in pciehp IRQ handler on power fault (Lukas Wunner) - Removed commented-out ibmphp functions (Vihas Mak) - Fix pciehp lockdep errors on Thunderbolt undock (Hans de Goede) * pci/hotplug: PCI: pciehp: Use down_read/write_nested(reset_lock) to fix lockdep errors PCI: ibmphp: Remove commented-out functions PCI: pciehp: Fix infinite loop in IRQ handler upon power fault
2 parents fb6c451 + 085a9f4 commit 7475f93

5 files changed

Lines changed: 26 additions & 86 deletions

File tree

drivers/pci/hotplug/TODO

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,6 @@ ibmphp:
3030
or ibmphp should store a pointer to its bus in struct slot. Probably the
3131
former.
3232

33-
* The functions get_max_adapter_speed() and get_bus_name() are commented out.
34-
Can they be deleted? There are also forward declarations at the top of
35-
ibmphp_core.c as well as pointers in ibmphp_hotplug_slot_ops, likewise
36-
commented out.
37-
3833
* ibmphp_init_devno() takes a struct slot **, it could instead take a
3934
struct slot *.
4035

drivers/pci/hotplug/ibmphp_core.c

Lines changed: 0 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,6 @@ static int irqs[16]; /* PIC mode IRQs we're using so far (in case MPS
5050

5151
static int init_flag;
5252

53-
/*
54-
static int get_max_adapter_speed_1 (struct hotplug_slot *, u8 *, u8);
55-
56-
static inline int get_max_adapter_speed (struct hotplug_slot *hs, u8 *value)
57-
{
58-
return get_max_adapter_speed_1 (hs, value, 1);
59-
}
60-
*/
6153
static inline int get_cur_bus_info(struct slot **sl)
6254
{
6355
int rc = 1;
@@ -401,69 +393,6 @@ static int get_max_bus_speed(struct slot *slot)
401393
return rc;
402394
}
403395

404-
/*
405-
static int get_max_adapter_speed_1(struct hotplug_slot *hotplug_slot, u8 *value, u8 flag)
406-
{
407-
int rc = -ENODEV;
408-
struct slot *pslot;
409-
struct slot myslot;
410-
411-
debug("get_max_adapter_speed_1 - Entry hotplug_slot[%lx] pvalue[%lx]\n",
412-
(ulong)hotplug_slot, (ulong) value);
413-
414-
if (flag)
415-
ibmphp_lock_operations();
416-
417-
if (hotplug_slot && value) {
418-
pslot = hotplug_slot->private;
419-
if (pslot) {
420-
memcpy(&myslot, pslot, sizeof(struct slot));
421-
rc = ibmphp_hpc_readslot(pslot, READ_SLOTSTATUS,
422-
&(myslot.status));
423-
424-
if (!(SLOT_LATCH (myslot.status)) &&
425-
(SLOT_PRESENT (myslot.status))) {
426-
rc = ibmphp_hpc_readslot(pslot,
427-
READ_EXTSLOTSTATUS,
428-
&(myslot.ext_status));
429-
if (!rc)
430-
*value = SLOT_SPEED(myslot.ext_status);
431-
} else
432-
*value = MAX_ADAPTER_NONE;
433-
}
434-
}
435-
436-
if (flag)
437-
ibmphp_unlock_operations();
438-
439-
debug("get_max_adapter_speed_1 - Exit rc[%d] value[%x]\n", rc, *value);
440-
return rc;
441-
}
442-
443-
static int get_bus_name(struct hotplug_slot *hotplug_slot, char *value)
444-
{
445-
int rc = -ENODEV;
446-
struct slot *pslot = NULL;
447-
448-
debug("get_bus_name - Entry hotplug_slot[%lx]\n", (ulong)hotplug_slot);
449-
450-
ibmphp_lock_operations();
451-
452-
if (hotplug_slot) {
453-
pslot = hotplug_slot->private;
454-
if (pslot) {
455-
rc = 0;
456-
snprintf(value, 100, "Bus %x", pslot->bus);
457-
}
458-
} else
459-
rc = -ENODEV;
460-
461-
ibmphp_unlock_operations();
462-
debug("get_bus_name - Exit rc[%d] value[%x]\n", rc, *value);
463-
return rc;
464-
}
465-
*/
466-
467396
/****************************************************************************
468397
* This routine will initialize the ops data structure used in the validate
469398
* function. It will also power off empty slots that are powered on since BIOS
@@ -1231,9 +1160,6 @@ const struct hotplug_slot_ops ibmphp_hotplug_slot_ops = {
12311160
.get_attention_status = get_attention_status,
12321161
.get_latch_status = get_latch_status,
12331162
.get_adapter_status = get_adapter_present,
1234-
/* .get_max_adapter_speed = get_max_adapter_speed,
1235-
.get_bus_name_status = get_bus_name,
1236-
*/
12371163
};
12381164

12391165
static void ibmphp_unload(void)

drivers/pci/hotplug/pciehp.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ extern int pciehp_poll_time;
7575
* @reset_lock: prevents access to the Data Link Layer Link Active bit in the
7676
* Link Status register and to the Presence Detect State bit in the Slot
7777
* Status register during a slot reset which may cause them to flap
78+
* @depth: Number of additional hotplug ports in the path to the root bus,
79+
* used as lock subclass for @reset_lock
7880
* @ist_running: flag to keep user request waiting while IRQ thread is running
7981
* @request_result: result of last user request submitted to the IRQ thread
8082
* @requester: wait queue to wake up on completion of user request,
@@ -106,6 +108,7 @@ struct controller {
106108

107109
struct hotplug_slot hotplug_slot; /* hotplug core interface */
108110
struct rw_semaphore reset_lock;
111+
unsigned int depth;
109112
unsigned int ist_running;
110113
int request_result;
111114
wait_queue_head_t requester;

drivers/pci/hotplug/pciehp_core.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ static void pciehp_check_presence(struct controller *ctrl)
166166
{
167167
int occupied;
168168

169-
down_read(&ctrl->reset_lock);
169+
down_read_nested(&ctrl->reset_lock, ctrl->depth);
170170
mutex_lock(&ctrl->state_lock);
171171

172172
occupied = pciehp_card_present_or_link_active(ctrl);

drivers/pci/hotplug/pciehp_hpc.c

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -583,7 +583,7 @@ static void pciehp_ignore_dpc_link_change(struct controller *ctrl,
583583
* the corresponding link change may have been ignored above.
584584
* Synthesize it to ensure that it is acted on.
585585
*/
586-
down_read(&ctrl->reset_lock);
586+
down_read_nested(&ctrl->reset_lock, ctrl->depth);
587587
if (!pciehp_check_link_active(ctrl))
588588
pciehp_request(ctrl, PCI_EXP_SLTSTA_DLLSC);
589589
up_read(&ctrl->reset_lock);
@@ -642,6 +642,8 @@ static irqreturn_t pciehp_isr(int irq, void *dev_id)
642642
*/
643643
if (ctrl->power_fault_detected)
644644
status &= ~PCI_EXP_SLTSTA_PFD;
645+
else if (status & PCI_EXP_SLTSTA_PFD)
646+
ctrl->power_fault_detected = true;
645647

646648
events |= status;
647649
if (!events) {
@@ -651,7 +653,7 @@ static irqreturn_t pciehp_isr(int irq, void *dev_id)
651653
}
652654

653655
if (status) {
654-
pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, events);
656+
pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, status);
655657

656658
/*
657659
* In MSI mode, all event bits must be zero before the port
@@ -725,8 +727,7 @@ static irqreturn_t pciehp_ist(int irq, void *dev_id)
725727
}
726728

727729
/* Check Power Fault Detected */
728-
if ((events & PCI_EXP_SLTSTA_PFD) && !ctrl->power_fault_detected) {
729-
ctrl->power_fault_detected = 1;
730+
if (events & PCI_EXP_SLTSTA_PFD) {
730731
ctrl_err(ctrl, "Slot(%s): Power fault\n", slot_name(ctrl));
731732
pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_OFF,
732733
PCI_EXP_SLTCTL_ATTN_IND_ON);
@@ -746,7 +747,7 @@ static irqreturn_t pciehp_ist(int irq, void *dev_id)
746747
* Disable requests have higher priority than Presence Detect Changed
747748
* or Data Link Layer State Changed events.
748749
*/
749-
down_read(&ctrl->reset_lock);
750+
down_read_nested(&ctrl->reset_lock, ctrl->depth);
750751
if (events & DISABLE_SLOT)
751752
pciehp_handle_disable_request(ctrl);
752753
else if (events & (PCI_EXP_SLTSTA_PDC | PCI_EXP_SLTSTA_DLLSC))
@@ -906,7 +907,7 @@ int pciehp_reset_slot(struct hotplug_slot *hotplug_slot, bool probe)
906907
if (probe)
907908
return 0;
908909

909-
down_write(&ctrl->reset_lock);
910+
down_write_nested(&ctrl->reset_lock, ctrl->depth);
910911

911912
if (!ATTN_BUTTN(ctrl)) {
912913
ctrl_mask |= PCI_EXP_SLTCTL_PDCE;
@@ -962,6 +963,20 @@ static inline void dbg_ctrl(struct controller *ctrl)
962963

963964
#define FLAG(x, y) (((x) & (y)) ? '+' : '-')
964965

966+
static inline int pcie_hotplug_depth(struct pci_dev *dev)
967+
{
968+
struct pci_bus *bus = dev->bus;
969+
int depth = 0;
970+
971+
while (bus->parent) {
972+
bus = bus->parent;
973+
if (bus->self && bus->self->is_hotplug_bridge)
974+
depth++;
975+
}
976+
977+
return depth;
978+
}
979+
965980
struct controller *pcie_init(struct pcie_device *dev)
966981
{
967982
struct controller *ctrl;
@@ -975,6 +990,7 @@ struct controller *pcie_init(struct pcie_device *dev)
975990
return NULL;
976991

977992
ctrl->pcie = dev;
993+
ctrl->depth = pcie_hotplug_depth(dev->port);
978994
pcie_capability_read_dword(pdev, PCI_EXP_SLTCAP, &slot_cap);
979995

980996
if (pdev->hotplug_user_indicators)

0 commit comments

Comments
 (0)