W1: Drop control thread from w1 core, whatever it does can
    also be done in the context of w1_remove_master_device.
    Also, pin the module when registering new master device
    to make sure that w1 core is not unloaded until last
    device is gone. This simplifies logic a lot.

Signed-off-by: Dmitry Torokhov <[EMAIL PROTECTED]>
---

 w1.c |  157 +++++++++++++++----------------------------------------------------
 w1.h |    1 
 2 files changed, 36 insertions(+), 122 deletions(-)

Index: dtor/drivers/w1/w1.c
===================================================================
--- dtor.orig/drivers/w1/w1.c
+++ dtor/drivers/w1/w1.c
@@ -50,14 +50,8 @@ module_param_named(timeout, w1_timeout, 
 module_param_named(max_slave_count, w1_max_slave_count, int, 0);
 module_param_named(slave_ttl, w1_max_slave_ttl, int, 0);
 
-static DEFINE_SPINLOCK(w1_mlock);
-static LIST_HEAD(w1_masters);
 static u32 w1_ids = 1;
 
-static pid_t control_thread;
-static int control_needs_exit;
-static DECLARE_COMPLETION(w1_control_complete);
-
 static int w1_master_match(struct device *dev, struct device_driver *drv)
 {
        return 1;
@@ -582,66 +576,6 @@ void w1_search(struct w1_master *dev)
 }
 
 
-static int w1_control(void *data)
-{
-       struct w1_slave *slave, *nexts;
-       struct w1_master *master, *nextm;
-       int err, have_to_wait = 0;
-
-       daemonize("w1_control");
-       allow_signal(SIGTERM);
-
-       while (!control_needs_exit || have_to_wait) {
-               have_to_wait = 0;
-
-               try_to_freeze(PF_FREEZE);
-               msleep_interruptible(w1_timeout * 1000);
-
-               if (signal_pending(current))
-                       flush_signals(current);
-
-               list_for_each_entry_safe(master, nextm, &w1_masters, node) {
-
-                       if (!control_needs_exit && !master->need_exit)
-                               continue;
-                       /*
-                        * Little race: we can create thread but not set the 
flag.
-                        * Get a chance for external process to set flag up.
-                        */
-                       if (!master->initialized) {
-                               have_to_wait = 1;
-                               continue;
-                       }
-
-                       spin_lock(&w1_mlock);
-                       list_del(&master->node);
-                       spin_unlock(&w1_mlock);
-
-                       if (control_needs_exit) {
-                               master->need_exit = 1;
-
-                               err = kill_proc(master->kpid, SIGTERM, 1);
-                               if (err)
-                                       dev_err(&master->dev,
-                                                "Failed to send signal to w1 
kernel thread %d.\n",
-                                                master->kpid);
-                       }
-
-                       wait_for_completion(&master->dev_exited);
-
-                       list_for_each_entry_safe(slave, nexts, &master->slist, 
node) {
-                               list_del(&slave->node);
-                               w1_slave_detach(slave);
-                               kfree(slave);
-                       }
-                       w1_destroy_master_attributes(master);
-                       atomic_dec(&master->refcnt);
-               }
-       }
-
-       complete_and_exit(&w1_control_complete, 0);
-}
-
 static int w1_process(void *data)
 {
        struct w1_master *dev = (struct w1_master *) data;
@@ -731,12 +665,22 @@ struct w1_master *w1_allocate_master_dev
        return dev;
 }
 
-static void w1_free_dev(struct w1_master *dev)
+static void w1_free_master_dev(struct w1_master *dev)
 {
        device_unregister(&dev->dev);
        kfree(dev);
 }
 
+static void w1_stop_master_device(struct w1_master *dev)
+{
+       dev->need_exit = 1;
+       if (kill_proc(dev->kpid, SIGTERM, 1))
+               dev_err(&dev->dev,
+                        "Failed to send signal to w1 kernel thread %d.\n",
+                        dev->kpid);
+       wait_for_completion(&dev->dev_exited);
+}
+
 int w1_add_master_device(struct w1_master *dev)
 {
        int error;
@@ -762,36 +706,32 @@ int w1_add_master_device(struct w1_maste
 
        dev->initialized = 1;
 
-       spin_lock(&w1_mlock);
-       list_add(&dev->node, &w1_masters);
-       spin_unlock(&w1_mlock);
+       __module_get(THIS_MODULE);
 
        return 0;
 
 err_out_kill_thread:
-       dev->need_exit = 1;
-       if (kill_proc(dev->kpid, SIGTERM, 1))
-               dev_err(&dev->dev,
-                        "Failed to send signal to w1 kernel thread %d.\n",
-                        dev->kpid);
-       wait_for_completion(&dev->dev_exited);
+       w1_stop_master_device(dev);
 
 err_out_free_dev:
-       w1_free_dev(dev);
+       w1_free_master_dev(dev);
 
        return error;
 }
 
 void w1_remove_master_device(struct w1_master *dev)
 {
-       int err;
+       struct w1_slave *slave, *next;
 
-       dev->need_exit = 1;
-       err = kill_proc(dev->kpid, SIGTERM, 1);
-       if (err)
-               dev_err(&dev->dev,
-                        "%s: Failed to send signal to w1 kernel thread %d.\n",
-                        __func__, dev->kpid);
+       w1_stop_master_device(dev);
+
+       list_for_each_entry_safe(slave, next, &dev->slist, node) {
+               list_del(&slave->node);
+               w1_slave_detach(slave);
+               kfree(slave);
+       }
+
+       w1_destroy_master_attributes(dev);
 
        while (atomic_read(&dev->refcnt)) {
                printk(KERN_INFO "Waiting for %s to become free: refcnt=%d.\n",
@@ -801,61 +741,36 @@ void w1_remove_master_device(struct w1_m
                        flush_signals(current);
        }
 
-       w1_free_dev(dev);
+       w1_free_master_dev(dev);
+       module_put(THIS_MODULE);
 }
 
 
 int w1_init(void)
 {
-       int retval;
+       int error;
 
        printk(KERN_INFO "Driver for 1-wire Dallas network protocol.\n");
 
-       retval = bus_register(&w1_bus_type);
-       if (retval) {
-               printk(KERN_ERR "Failed to register bus. err=%d.\n", retval);
-               goto err_out_exit_init;
+       error = bus_register(&w1_bus_type);
+       if (error) {
+               printk(KERN_ERR "Failed to register bus. err=%d.\n", error);
+               return error;
        }
 
-       retval = driver_register(&w1_driver);
-       if (retval) {
+       error = driver_register(&w1_driver);
+       if (error) {
                printk(KERN_ERR
-                       "Failed to register master driver. err=%d.\n",
-                       retval);
-               goto err_out_bus_unregister;
-       }
-
-       control_thread = kernel_thread(&w1_control, NULL, 0);
-       if (control_thread < 0) {
-               printk(KERN_ERR "Failed to create control thread. err=%d\n",
-                       control_thread);
-               retval = control_thread;
-               goto err_out_driver_unregister;
+                       "Failed to register master driver. err=%d.\n", error);
+               bus_unregister(&w1_bus_type);
+               return error;
        }
 
        return 0;
-
-err_out_driver_unregister:
-       driver_unregister(&w1_driver);
-
-err_out_bus_unregister:
-       bus_unregister(&w1_bus_type);
-
-err_out_exit_init:
-       return retval;
 }
 
 void w1_fini(void)
 {
-       struct w1_master *master, *next;
-
-       list_for_each_entry_safe(master, next, &w1_masters, node)
-               w1_remove_master_device(master);
-
-       control_needs_exit = 1;
-
-       wait_for_completion(&w1_control_complete);
-
        driver_unregister(&w1_driver);
        bus_unregister(&w1_bus_type);
 }
Index: dtor/drivers/w1/w1.h
===================================================================
--- dtor.orig/drivers/w1/w1.h
+++ dtor/drivers/w1/w1.h
@@ -103,7 +103,6 @@ struct w1_bus_ops
 
 struct w1_master
 {
-       struct list_head        node;
        unsigned char           name[W1_MAXNAMELEN];
        struct list_head        slist;
        int                     max_slave_count, slave_count;
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to