===================================================================
@@ -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;
}
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@jp.fujitsu.com> --- drivers/acpi/pci_root.c | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html