Skip to content

Commit d4f194e

Browse files
Sam Bobroffmpe
authored andcommitted
powerpc/eeh: Fix deadlock handling dead PHB
Recovering a dead PHB can currently cause a deadlock as the PCI rescan/remove lock is taken twice. This is caused as part of an existing bug in eeh_handle_special_event(). The pe is processed while traversing the PHBs even though the pe is unrelated to the loop. This causes the pe to be, incorrectly, processed more than once. Untangling this section can move the pe processing out of the loop and also outside the locked section, correcting both problems. Fixes: 2e25505 ("powerpc/eeh: Fix crash when edev->pdev changes") Cc: [email protected] # 5.4+ Signed-off-by: Sam Bobroff <[email protected]> Reviewed-by: Frederic Barrat <[email protected]> Tested-by: Frederic Barrat <[email protected]> Signed-off-by: Michael Ellerman <[email protected]> Link: https://lore.kernel.org/r/0547e82dbf90ee0729a2979a8cac5c91665c621f.1581051445.git.sbobroff@linux.ibm.com
1 parent 11a48a5 commit d4f194e

File tree

1 file changed

+11
-10
lines changed

1 file changed

+11
-10
lines changed

arch/powerpc/kernel/eeh_driver.c

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1184,6 +1184,17 @@ void eeh_handle_special_event(void)
11841184
eeh_pe_state_mark(pe, EEH_PE_RECOVERING);
11851185
eeh_handle_normal_event(pe);
11861186
} else {
1187+
eeh_for_each_pe(pe, tmp_pe)
1188+
eeh_pe_for_each_dev(tmp_pe, edev, tmp_edev)
1189+
edev->mode &= ~EEH_DEV_NO_HANDLER;
1190+
1191+
/* Notify all devices to be down */
1192+
eeh_pe_state_clear(pe, EEH_PE_PRI_BUS, true);
1193+
eeh_set_channel_state(pe, pci_channel_io_perm_failure);
1194+
eeh_pe_report(
1195+
"error_detected(permanent failure)", pe,
1196+
eeh_report_failure, NULL);
1197+
11871198
pci_lock_rescan_remove();
11881199
list_for_each_entry(hose, &hose_list, list_node) {
11891200
phb_pe = eeh_phb_pe_get(hose);
@@ -1192,16 +1203,6 @@ void eeh_handle_special_event(void)
11921203
(phb_pe->state & EEH_PE_RECOVERING))
11931204
continue;
11941205

1195-
eeh_for_each_pe(pe, tmp_pe)
1196-
eeh_pe_for_each_dev(tmp_pe, edev, tmp_edev)
1197-
edev->mode &= ~EEH_DEV_NO_HANDLER;
1198-
1199-
/* Notify all devices to be down */
1200-
eeh_pe_state_clear(pe, EEH_PE_PRI_BUS, true);
1201-
eeh_set_channel_state(pe, pci_channel_io_perm_failure);
1202-
eeh_pe_report(
1203-
"error_detected(permanent failure)", pe,
1204-
eeh_report_failure, NULL);
12051206
bus = eeh_pe_bus_get(phb_pe);
12061207
if (!bus) {
12071208
pr_err("%s: Cannot find PCI bus for "

0 commit comments

Comments
 (0)