Currently acpi_pci_root list and acpi_pci_drivers list are manipulated without holding any lock. This patch introduce acpi_pci_lock to manipulate those lists. Signed-off-by: Kenji Kaneshige <kaneshige.kenji@xxxxxxxxxxxxxx> --- drivers/acpi/pci_root.c | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) Index: linux/drivers/acpi/pci_root.c =================================================================== --- linux.orig/drivers/acpi/pci_root.c +++ linux/drivers/acpi/pci_root.c @@ -73,6 +73,7 @@ static struct acpi_driver acpi_pci_root_ static LIST_HEAD(acpi_pci_roots); static LIST_HEAD(acpi_pci_drivers); +DECLARE_RWSEM(acpi_pci_sem); static DEFINE_MUTEX(osc_lock); @@ -81,15 +82,19 @@ int acpi_pci_register_driver(struct acpi int n = 0; struct acpi_pci_root *root; + down_write(&acpi_pci_sem); list_add(&driver->list, &acpi_pci_drivers); + up_write(&acpi_pci_sem); if (!driver->add) return 0; + down_read(&acpi_pci_sem); list_for_each_entry(root, &acpi_pci_roots, node) { driver->add(root->device->handle); n++; } + up_read(&acpi_pci_sem); return n; } @@ -99,13 +104,17 @@ void acpi_pci_unregister_driver(struct a { struct acpi_pci_root *root; + down_write(&acpi_pci_sem); list_del(&driver->list); + up_write(&acpi_pci_sem); if (!driver->remove) return; + down_read(&acpi_pci_sem); list_for_each_entry(root, &acpi_pci_roots, node) driver->remove(root->device->handle); + up_read(&acpi_pci_sem); } EXPORT_SYMBOL(acpi_pci_unregister_driver); @@ -113,11 +122,15 @@ EXPORT_SYMBOL(acpi_pci_unregister_driver acpi_handle acpi_get_pci_rootbridge_handle(unsigned int seg, unsigned int bus) { struct acpi_pci_root *root; - + + down_read(&acpi_pci_sem); list_for_each_entry(root, &acpi_pci_roots, node) - if ((root->segment == (u16) seg) && - (root->secondary.start == (u16) bus)) + if ((root->segment == (u16) seg) || + (root->secondary.start == (u16) bus)) { + up_read(&acpi_pci_sem); return root->device->handle; + } + up_read(&acpi_pci_sem); return NULL; } @@ -267,10 +280,14 @@ struct acpi_pci_root *acpi_pci_find_root { struct acpi_pci_root *root; + down_read(&acpi_pci_sem); list_for_each_entry(root, &acpi_pci_roots, node) { - if (root->device->handle == handle) + if (root->device->handle == handle) { + up_read(&acpi_pci_sem); return root; + } } + up_read(&acpi_pci_sem); return NULL; } EXPORT_SYMBOL_GPL(acpi_pci_find_root); @@ -505,8 +522,9 @@ static int __devinit acpi_pci_root_add(s * TBD: Need PCI interface for enumeration/configuration of roots. */ - /* TBD: Locking */ + down_write(&acpi_pci_sem); list_add_tail(&root->node, &acpi_pci_roots); + up_write(&acpi_pci_sem); printk(KERN_INFO PREFIX "%s [%s] (domain %04x %pR)\n", acpi_device_name(device), acpi_device_bid(device), @@ -614,8 +632,11 @@ static int __devinit acpi_pci_root_add(s return 0; end: - if (!list_empty(&root->node)) + if (!list_empty(&root->node)) { + down_write(&acpi_pci_sem); list_del(&root->node); + up_write(&acpi_pci_sem); + } kfree(root); return result; } -- To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html