W1: fix deadlocks and remove w1_control_thread
[pandora-kernel.git] / drivers / w1 / w1_int.c
index 2fbd8dd..ed32280 100644 (file)
@@ -148,10 +148,22 @@ err_out_free_dev:
 void __w1_remove_master_device(struct w1_master *dev)
 {
        struct w1_netlink_msg msg;
+       struct w1_slave *sl, *sln;
 
        set_bit(W1_MASTER_NEED_EXIT, &dev->flags);
        kthread_stop(dev->thread);
 
+       mutex_lock(&w1_mlock);
+       list_del(&dev->w1_master_entry);
+       mutex_unlock(&w1_mlock);
+
+       mutex_lock(&dev->mutex);
+       list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry)
+               w1_slave_detach(sl);
+       w1_destroy_master_attributes(dev);
+       mutex_unlock(&dev->mutex);
+       atomic_dec(&dev->refcnt);
+
        while (atomic_read(&dev->refcnt)) {
                dev_info(&dev->dev, "Waiting for %s to become free: refcnt=%d.\n",
                                dev->name, atomic_read(&dev->refcnt));
@@ -170,22 +182,24 @@ void __w1_remove_master_device(struct w1_master *dev)
 
 void w1_remove_master_device(struct w1_bus_master *bm)
 {
-       struct w1_master *dev = NULL;
+       struct w1_master *dev, *found = NULL;
 
        list_for_each_entry(dev, &w1_masters, w1_master_entry) {
                if (!dev->initialized)
                        continue;
 
-               if (dev->bus_master->data == bm->data)
+               if (dev->bus_master->data == bm->data) {
+                       found = dev;
                        break;
+               }
        }
 
-       if (!dev) {
+       if (!found) {
                printk(KERN_ERR "Device doesn't exist.\n");
                return;
        }
 
-       __w1_remove_master_device(dev);
+       __w1_remove_master_device(found);
 }
 
 EXPORT_SYMBOL(w1_add_master_device);