]> err.no Git - linux-2.6/blobdiff - drivers/w1/w1.c
[PATCH] pipe: remove redundant fifo_poll abstraction
[linux-2.6] / drivers / w1 / w1.c
index 0e6ccd46af0e37508fdaf989a8f9177e4630c84e..0bbf029b1ef1658f99b537fa690a10186275b486 100644 (file)
@@ -469,6 +469,8 @@ static void w1_slave_detach(struct w1_slave *sl)
        device_unregister(&sl->dev);
        w1_family_put(sl->family);
 
+       sl->master->slave_count--;
+
        memcpy(&msg.id.id, &sl->reg_num, sizeof(msg.id.id));
        msg.type = W1_SLAVE_REMOVE;
        w1_netlink_send(sl->master, &msg);
@@ -492,6 +494,20 @@ static struct w1_master *w1_search_master(unsigned long data)
        return (found)?dev:NULL;
 }
 
+void w1_reconnect_slaves(struct w1_family *f)
+{
+       struct w1_master *dev;
+
+       spin_lock_bh(&w1_mlock);
+       list_for_each_entry(dev, &w1_masters, w1_master_entry) {
+               dev_info(&dev->dev, "Reconnecting slaves in %s into new family %02x.\n",
+                               dev->name, f->fid);
+               set_bit(W1_MASTER_NEED_RECONNECT, &dev->flags);
+       }
+       spin_unlock_bh(&w1_mlock);
+}
+
+
 static void w1_slave_found(unsigned long data, u64 rn)
 {
        int slave_count;
@@ -500,6 +516,7 @@ static void w1_slave_found(unsigned long data, u64 rn)
        struct w1_reg_num *tmp;
        int family_found = 0;
        struct w1_master *dev;
+       u64 rn_le = cpu_to_le64(rn);
 
        dev = w1_search_master(data);
        if (!dev) {
@@ -528,10 +545,8 @@ static void w1_slave_found(unsigned long data, u64 rn)
                slave_count++;
        }
 
-       rn = cpu_to_le64(rn);
-
        if (slave_count == dev->slave_count &&
-               rn && ((le64_to_cpu(rn) >> 56) & 0xff) == w1_calc_crc8((u8 *)&rn, 7)) {
+               rn && ((rn >> 56) & 0xff) == w1_calc_crc8((u8 *)&rn_le, 7)) {
                w1_attach_slave_device(dev, tmp);
        }
 
@@ -578,7 +593,7 @@ void w1_search(struct w1_master *dev, w1_slave_found_callback cb)
                 * Return 0 - device(s) present, 1 - no devices present.
                 */
                if (w1_reset_bus(dev)) {
-                       dev_info(&dev->dev, "No devices present on the wire.\n");
+                       dev_dbg(&dev->dev, "No devices present on the wire.\n");
                        break;
                }
 
@@ -630,14 +645,14 @@ static int w1_control(void *data)
        while (!control_needs_exit || have_to_wait) {
                have_to_wait = 0;
 
-               try_to_freeze(PF_FREEZE);
+               try_to_freeze();
                msleep_interruptible(w1_timeout * 1000);
 
                if (signal_pending(current))
                        flush_signals(current);
 
                list_for_each_entry_safe(dev, n, &w1_masters, w1_master_entry) {
-                       if (!control_needs_exit && !dev->need_exit)
+                       if (!control_needs_exit && !dev->flags)
                                continue;
                        /*
                         * Little race: we can create thread but not set the flag.
@@ -648,12 +663,8 @@ static int w1_control(void *data)
                                continue;
                        }
 
-                       spin_lock_bh(&w1_mlock);
-                       list_del(&dev->w1_master_entry);
-                       spin_unlock_bh(&w1_mlock);
-
                        if (control_needs_exit) {
-                               dev->need_exit = 1;
+                               set_bit(W1_MASTER_NEED_EXIT, &dev->flags);
 
                                err = kill_proc(dev->kpid, SIGTERM, 1);
                                if (err)
@@ -662,16 +673,42 @@ static int w1_control(void *data)
                                                 dev->kpid);
                        }
 
-                       wait_for_completion(&dev->dev_exited);
+                       if (test_bit(W1_MASTER_NEED_EXIT, &dev->flags)) {
+                               wait_for_completion(&dev->dev_exited);
+                               spin_lock_bh(&w1_mlock);
+                               list_del(&dev->w1_master_entry);
+                               spin_unlock_bh(&w1_mlock);
+
+                               list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) {
+                                       list_del(&sl->w1_slave_entry);
+
+                                       w1_slave_detach(sl);
+                                       kfree(sl);
+                               }
+                               w1_destroy_master_attributes(dev);
+                               atomic_dec(&dev->refcnt);
+                               continue;
+                       }
+
+                       if (test_bit(W1_MASTER_NEED_RECONNECT, &dev->flags)) {
+                               dev_info(&dev->dev, "Reconnecting slaves in device %s.\n", dev->name);
+                               down(&dev->mutex);
+                               list_for_each_entry(sl, &dev->slist, w1_slave_entry) {
+                                       if (sl->family->fid == W1_FAMILY_DEFAULT) {
+                                               struct w1_reg_num rn;
+                                               list_del(&sl->w1_slave_entry);
+                                               w1_slave_detach(sl);
+
+                                               memcpy(&rn, &sl->reg_num, sizeof(rn));
 
-                       list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) {
-                               list_del(&sl->w1_slave_entry);
+                                               kfree(sl);
 
-                               w1_slave_detach(sl);
-                               kfree(sl);
+                                               w1_attach_slave_device(dev, &rn);
+                                       }
+                               }
+                               clear_bit(W1_MASTER_NEED_RECONNECT, &dev->flags);
+                               up(&dev->mutex);
                        }
-                       w1_destroy_master_attributes(dev);
-                       atomic_dec(&dev->refcnt);
                }
        }
 
@@ -686,14 +723,14 @@ int w1_process(void *data)
        daemonize("%s", dev->name);
        allow_signal(SIGTERM);
 
-       while (!dev->need_exit) {
-               try_to_freeze(PF_FREEZE);
+       while (!test_bit(W1_MASTER_NEED_EXIT, &dev->flags)) {
+               try_to_freeze();
                msleep_interruptible(w1_timeout * 1000);
 
                if (signal_pending(current))
                        flush_signals(current);
 
-               if (dev->need_exit)
+               if (test_bit(W1_MASTER_NEED_EXIT, &dev->flags))
                        break;
 
                if (!dev->initialized)