diff mbox

[2/4] acpi, pci: introduce acpi_root_sem for list manipulation

Message ID 20120621183803.8b9bd8c0.izumi.taku@jp.fujitsu.com
State Superseded
Headers show

Commit Message

Taku Izumi June 21, 2012, 9:38 a.m. UTC
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
diff mbox

Patch

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;
 }