Skip to content

Commit a03b3ce

Browse files
Sam Bobroffgregkh
authored andcommitted
powerpc/eeh: Fix deadlock handling dead PHB
commit d4f194e upstream. 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 Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 9e1fab4 commit a03b3ce

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
@@ -1200,6 +1200,17 @@ void eeh_handle_special_event(void)
12001200
eeh_pe_state_mark(pe, EEH_PE_RECOVERING);
12011201
eeh_handle_normal_event(pe);
12021202
} else {
1203+
eeh_for_each_pe(pe, tmp_pe)
1204+
eeh_pe_for_each_dev(tmp_pe, edev, tmp_edev)
1205+
edev->mode &= ~EEH_DEV_NO_HANDLER;
1206+
1207+
/* Notify all devices to be down */
1208+
eeh_pe_state_clear(pe, EEH_PE_PRI_BUS, true);
1209+
eeh_set_channel_state(pe, pci_channel_io_perm_failure);
1210+
eeh_pe_report(
1211+
"error_detected(permanent failure)", pe,
1212+
eeh_report_failure, NULL);
1213+
12031214
pci_lock_rescan_remove();
12041215
list_for_each_entry(hose, &hose_list, list_node) {
12051216
phb_pe = eeh_phb_pe_get(hose);
@@ -1208,16 +1219,6 @@ void eeh_handle_special_event(void)
12081219
(phb_pe->state & EEH_PE_RECOVERING))
12091220
continue;
12101221

1211-
eeh_for_each_pe(pe, tmp_pe)
1212-
eeh_pe_for_each_dev(tmp_pe, edev, tmp_edev)
1213-
edev->mode &= ~EEH_DEV_NO_HANDLER;
1214-
1215-
/* Notify all devices to be down */
1216-
eeh_pe_state_clear(pe, EEH_PE_PRI_BUS, true);
1217-
eeh_set_channel_state(pe, pci_channel_io_perm_failure);
1218-
eeh_pe_report(
1219-
"error_detected(permanent failure)", pe,
1220-
eeh_report_failure, NULL);
12211222
bus = eeh_pe_bus_get(phb_pe);
12221223
if (!bus) {
12231224
pr_err("%s: Cannot find PCI bus for "

0 commit comments

Comments
 (0)