Skip to content

Commit 1c2042c

Browse files
rafaeljwbjorn-helgaas
authored andcommitted
powerpc/eeh: Use global PCI rescan-remove locking
Race conditions are theoretically possible between the PCI device addition and removal in the PPC64 PCI error recovery driver and the generic PCI bus rescan and device removal that can be triggered via sysfs. To avoid those race conditions make PPC64 PCI error recovery driver use global PCI rescan-remove locking around PCI device addition and removal. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
1 parent 64cdb41 commit 1c2042c

File tree

1 file changed

+16
-3
lines changed

1 file changed

+16
-3
lines changed

arch/powerpc/kernel/eeh_driver.c

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,9 @@ static void *eeh_rmv_device(void *data, void *userdata)
369369
edev->mode |= EEH_DEV_DISCONNECTED;
370370
(*removed)++;
371371

372+
pci_lock_rescan_remove();
372373
pci_stop_and_remove_bus_device(dev);
374+
pci_unlock_rescan_remove();
373375

374376
return NULL;
375377
}
@@ -416,10 +418,13 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus)
416418
* into pcibios_add_pci_devices().
417419
*/
418420
eeh_pe_state_mark(pe, EEH_PE_KEEP);
419-
if (bus)
421+
if (bus) {
422+
pci_lock_rescan_remove();
420423
pcibios_remove_pci_devices(bus);
421-
else if (frozen_bus)
424+
pci_unlock_rescan_remove();
425+
} else if (frozen_bus) {
422426
eeh_pe_dev_traverse(pe, eeh_rmv_device, &removed);
427+
}
423428

424429
/* Reset the pci controller. (Asserts RST#; resets config space).
425430
* Reconfigure bridges and devices. Don't try to bring the system
@@ -429,6 +434,8 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus)
429434
if (rc)
430435
return rc;
431436

437+
pci_lock_rescan_remove();
438+
432439
/* Restore PE */
433440
eeh_ops->configure_bridge(pe);
434441
eeh_pe_restore_bars(pe);
@@ -462,6 +469,7 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus)
462469
pe->tstamp = tstamp;
463470
pe->freeze_count = cnt;
464471

472+
pci_unlock_rescan_remove();
465473
return 0;
466474
}
467475

@@ -618,8 +626,11 @@ static void eeh_handle_normal_event(struct eeh_pe *pe)
618626
eeh_pe_dev_traverse(pe, eeh_report_failure, NULL);
619627

620628
/* Shut down the device drivers for good. */
621-
if (frozen_bus)
629+
if (frozen_bus) {
630+
pci_lock_rescan_remove();
622631
pcibios_remove_pci_devices(frozen_bus);
632+
pci_unlock_rescan_remove();
633+
}
623634
}
624635

625636
static void eeh_handle_special_event(void)
@@ -692,6 +703,7 @@ static void eeh_handle_special_event(void)
692703
if (rc == 2 || rc == 1)
693704
eeh_handle_normal_event(pe);
694705
else {
706+
pci_lock_rescan_remove();
695707
list_for_each_entry_safe(hose, tmp,
696708
&hose_list, list_node) {
697709
phb_pe = eeh_phb_pe_get(hose);
@@ -703,6 +715,7 @@ static void eeh_handle_special_event(void)
703715
eeh_pe_dev_traverse(pe, eeh_report_failure, NULL);
704716
pcibios_remove_pci_devices(bus);
705717
}
718+
pci_unlock_rescan_remove();
706719
}
707720
}
708721

0 commit comments

Comments
 (0)