public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* Re: device model update 2/2
@ 2002-06-06  8:56 Amici Alessandro
  2002-06-06 15:14 ` Patrick Mochel
  0 siblings, 1 reply; 5+ messages in thread
From: Amici Alessandro @ 2002-06-06  8:56 UTC (permalink / raw)
  To: mochel; +Cc: linux-kernel


hi,

+		lock_device(dev);
+		dev->driver = NULL;
+		unlock_device(dev);
+
+		/* detach from driver */
+		if (dev->driver->remove)
+			dev->driver->remove(dev);
+		put_driver(dev->driver);

you might want to exchange these two blocks :)

regards,
alessandro

^ permalink raw reply	[flat|nested] 5+ messages in thread
* device model update 2/2
@ 2002-06-05 23:20 Patrick Mochel
  0 siblings, 0 replies; 5+ messages in thread
From: Patrick Mochel @ 2002-06-05 23:20 UTC (permalink / raw)
  To: torvalds; +Cc: linux-kernel


This is an attempt to better locking for both device and driver removal. 
Comments gladly welcomed.

Pull from bk://ldm.bkbits.net/linux-2.5

	-pat

ChangeSet@1.456, 2002-06-05 15:59:32-07:00, mochel@osdl.org
  Attempt to better locking in device model core: 
  
  - remove device from driver's list on device_detach 
  - set device's driver to NULL
  - decrement reference count on driver on device_detach
  - remove devices from driver's list in driver_detach
  - use a write_lock instead of read_lock
  - don't lock around initialization of device fields
  
  - assume we have a bus in __remove_driver (we enforce this in driver_register)
  - do put_bus last in __remove_driver
  - lock bus around atomic_set in remove_driver and atomic_dec_and_test in put_driver
  - remove from bus's list while we have it locked

 drivers/base/bus.c    |    5 +++--
 drivers/base/core.c   |   30 +++++++++++++++++++++---------
 drivers/base/driver.c |   29 +++++++++++++----------------
 3 files changed, 37 insertions, 27 deletions



diff -Nru a/drivers/base/bus.c b/drivers/base/bus.c
--- a/drivers/base/bus.c	Wed Jun  5 16:02:11 2002
+++ b/drivers/base/bus.c	Wed Jun  5 16:02:11 2002
@@ -167,12 +167,13 @@
 
 int bus_register(struct bus_type * bus)
 {
-	spin_lock(&device_lock);
 	rwlock_init(&bus->lock);
 	INIT_LIST_HEAD(&bus->devices);
 	INIT_LIST_HEAD(&bus->drivers);
-	list_add_tail(&bus->node,&bus_driver_list);
 	atomic_set(&bus->refcount,2);
+
+	spin_lock(&device_lock);
+	list_add_tail(&bus->node,&bus_driver_list);
 	spin_unlock(&device_lock);
 
 	pr_debug("bus type '%s' registered\n",bus->name);
diff -Nru a/drivers/base/core.c b/drivers/base/core.c
--- a/drivers/base/core.c	Wed Jun  5 16:02:11 2002
+++ b/drivers/base/core.c	Wed Jun  5 16:02:11 2002
@@ -98,9 +98,20 @@
 
 static void device_detach(struct device * dev)
 {
-	/* detach from driver */
-	if (dev->driver && dev->driver->remove)
-		dev->driver->remove(dev);
+	if (dev->driver) {
+		write_lock(&dev->driver->lock);
+		list_del_init(&dev->driver_list);
+		write_unlock(&dev->driver->lock);
+
+		lock_device(dev);
+		dev->driver = NULL;
+		unlock_device(dev);
+
+		/* detach from driver */
+		if (dev->driver->remove)
+			dev->driver->remove(dev);
+		put_driver(dev->driver);
+	}
 }
 
 static int do_driver_attach(struct device * dev, void * data)
@@ -140,12 +151,13 @@
 	struct list_head * node;
 	int error = 0;
 
-	read_lock(&drv->lock);
+	write_lock(&drv->lock);
 	node = drv->devices.next;
 	while (node != &drv->devices) {
 		next = list_entry(node,struct device,driver_list);
 		get_device(next);
-		read_unlock(&drv->lock);
+		list_del_init(&next->driver_list);
+		write_unlock(&drv->lock);
 
 		if (dev)
 			put_device(dev);
@@ -154,10 +166,10 @@
 			put_device(dev);
 			break;
 		}
-		read_lock(&drv->lock);
-		node = dev->driver_list.next;
+		write_lock(&drv->lock);
+		node = drv->devices.next;
 	}
-	read_unlock(&drv->lock);
+	write_unlock(&drv->lock);
 	if (dev)
 		put_device(dev);
 }
@@ -181,13 +193,13 @@
 	if (!dev || !strlen(dev->bus_id))
 		return -EINVAL;
 
-	spin_lock(&device_lock);
 	INIT_LIST_HEAD(&dev->node);
 	INIT_LIST_HEAD(&dev->children);
 	INIT_LIST_HEAD(&dev->g_list);
 	spin_lock_init(&dev->lock);
 	atomic_set(&dev->refcount,2);
 
+	spin_lock(&device_lock);
 	if (dev != &device_root) {
 		if (!dev->parent)
 			dev->parent = &device_root;
diff -Nru a/drivers/base/driver.c b/drivers/base/driver.c
--- a/drivers/base/driver.c	Wed Jun  5 16:02:11 2002
+++ b/drivers/base/driver.c	Wed Jun  5 16:02:11 2002
@@ -81,26 +81,20 @@
 
 static void __remove_driver(struct device_driver * drv)
 {
-	if (drv->bus) {
-		pr_debug("Unregistering driver '%s' from bus '%s'\n",drv->name,drv->bus->name);
-
-		driver_detach(drv);
-		write_lock(&drv->bus->lock);
-		list_del_init(&drv->bus_list);
-		write_unlock(&drv->bus->lock);
-
-		driverfs_remove_dir(&drv->dir);
-		put_bus(drv->bus);
-	}
+	pr_debug("Unregistering driver '%s' from bus '%s'\n",drv->name,drv->bus->name);
+	driver_detach(drv);
+	driverfs_remove_dir(&drv->dir);
 	if (drv->release)
 		drv->release(drv);
+	put_bus(drv->bus);
 }
 
 void remove_driver(struct device_driver * drv)
 {
-	spin_lock(&device_lock);
+	write_lock(&drv->bus->lock);
 	atomic_set(&drv->refcount,0);
-	spin_unlock(&device_lock);
+	list_del_init(&drv->bus_list);
+	write_unlock(&drv->bus->lock);
 	__remove_driver(drv);
 }
 
@@ -110,10 +104,13 @@
  */
 void put_driver(struct device_driver * drv)
 {
-	if (!atomic_dec_and_lock(&drv->refcount,&device_lock))
+	write_lock(&drv->bus->lock);
+	if (!atomic_dec_and_test(&drv->refcount)) {
+		write_unlock(&drv->bus->lock);
 		return;
-	spin_unlock(&device_lock);
-
+	}
+	list_del_init(&drv->bus_list);
+	write_unlock(&drv->bus->lock);
 	__remove_driver(drv);
 }
 



^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2002-06-06 17:00 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-06-06  8:56 device model update 2/2 Amici Alessandro
2002-06-06 15:14 ` Patrick Mochel
2002-06-06 16:45   ` Linus Torvalds
2002-06-06 16:56     ` Patrick Mochel
  -- strict thread matches above, loose matches on Subject: below --
2002-06-05 23:20 Patrick Mochel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox