aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEvgeniy Polyakov <johnpol@2ka.mipt.ru>2005-06-03 17:29:25 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2005-06-22 00:43:12 -0400
commit6adf87bd7b7832105b9c6bc08adf6a4d229f1e79 (patch)
tree1c6d17df3c4f4d753021e970a7bb898c1aabeb82
parent4754639d88e922af451b399af09ac1bb442c35e5 (diff)
[PATCH] w1: reconnect feature.
I've created reconnect feature - if on start there are no registered families all new devices will have defailt family, later when driver for appropriate family is loaded, slaves, which were faound earlier, will still have defult family instead of right one. Reconnect feature will force control thread to run through all master devices and all slaves found and search for slaves with default family id and try to reconnect them. It does not store newly registered family and does not check only those slaves which have reg_num.family the same as being registered one - all slaves with default family are reconnected. Signed-off-by: Evgeniy Polyakov <johnpol@2ka.mipt.ru> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/w1/ds_w1_bridge.c4
-rw-r--r--drivers/w1/w1.c68
-rw-r--r--drivers/w1/w1.h6
-rw-r--r--drivers/w1/w1_family.c3
-rw-r--r--drivers/w1/w1_int.c11
5 files changed, 67 insertions, 25 deletions
diff --git a/drivers/w1/ds_w1_bridge.c b/drivers/w1/ds_w1_bridge.c
index 0baaeb5fd630..7bddd8ac7d7f 100644
--- a/drivers/w1/ds_w1_bridge.c
+++ b/drivers/w1/ds_w1_bridge.c
@@ -83,11 +83,11 @@ static u8 ds9490r_read_byte(unsigned long data)
83 return byte; 83 return byte;
84} 84}
85 85
86static void ds9490r_write_block(unsigned long data, u8 *buf, int len) 86static void ds9490r_write_block(unsigned long data, const u8 *buf, int len)
87{ 87{
88 struct ds_device *dev = (struct ds_device *)data; 88 struct ds_device *dev = (struct ds_device *)data;
89 89
90 ds_write_block(dev, buf, len); 90 ds_write_block(dev, (u8 *)buf, len);
91} 91}
92 92
93static u8 ds9490r_read_block(unsigned long data, u8 *buf, int len) 93static u8 ds9490r_read_block(unsigned long data, u8 *buf, int len)
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c
index 0e6ccd46af0e..b460927ec32a 100644
--- a/drivers/w1/w1.c
+++ b/drivers/w1/w1.c
@@ -469,6 +469,8 @@ static void w1_slave_detach(struct w1_slave *sl)
469 device_unregister(&sl->dev); 469 device_unregister(&sl->dev);
470 w1_family_put(sl->family); 470 w1_family_put(sl->family);
471 471
472 sl->master->slave_count--;
473
472 memcpy(&msg.id.id, &sl->reg_num, sizeof(msg.id.id)); 474 memcpy(&msg.id.id, &sl->reg_num, sizeof(msg.id.id));
473 msg.type = W1_SLAVE_REMOVE; 475 msg.type = W1_SLAVE_REMOVE;
474 w1_netlink_send(sl->master, &msg); 476 w1_netlink_send(sl->master, &msg);
@@ -492,6 +494,20 @@ static struct w1_master *w1_search_master(unsigned long data)
492 return (found)?dev:NULL; 494 return (found)?dev:NULL;
493} 495}
494 496
497void w1_reconnect_slaves(struct w1_family *f)
498{
499 struct w1_master *dev;
500
501 spin_lock_bh(&w1_mlock);
502 list_for_each_entry(dev, &w1_masters, w1_master_entry) {
503 dev_info(&dev->dev, "Reconnecting slaves in %s into new family %02x.\n",
504 dev->name, f->fid);
505 set_bit(W1_MASTER_NEED_RECONNECT, &dev->flags);
506 }
507 spin_unlock_bh(&w1_mlock);
508}
509
510
495static void w1_slave_found(unsigned long data, u64 rn) 511static void w1_slave_found(unsigned long data, u64 rn)
496{ 512{
497 int slave_count; 513 int slave_count;
@@ -637,7 +653,7 @@ static int w1_control(void *data)
637 flush_signals(current); 653 flush_signals(current);
638 654
639 list_for_each_entry_safe(dev, n, &w1_masters, w1_master_entry) { 655 list_for_each_entry_safe(dev, n, &w1_masters, w1_master_entry) {
640 if (!control_needs_exit && !dev->need_exit) 656 if (!control_needs_exit && !dev->flags)
641 continue; 657 continue;
642 /* 658 /*
643 * Little race: we can create thread but not set the flag. 659 * Little race: we can create thread but not set the flag.
@@ -648,12 +664,8 @@ static int w1_control(void *data)
648 continue; 664 continue;
649 } 665 }
650 666
651 spin_lock_bh(&w1_mlock);
652 list_del(&dev->w1_master_entry);
653 spin_unlock_bh(&w1_mlock);
654
655 if (control_needs_exit) { 667 if (control_needs_exit) {
656 dev->need_exit = 1; 668 set_bit(W1_MASTER_NEED_EXIT, &dev->flags);
657 669
658 err = kill_proc(dev->kpid, SIGTERM, 1); 670 err = kill_proc(dev->kpid, SIGTERM, 1);
659 if (err) 671 if (err)
@@ -662,16 +674,42 @@ static int w1_control(void *data)
662 dev->kpid); 674 dev->kpid);
663 } 675 }
664 676
665 wait_for_completion(&dev->dev_exited); 677 if (test_bit(W1_MASTER_NEED_EXIT, &dev->flags)) {
678 wait_for_completion(&dev->dev_exited);
679 spin_lock_bh(&w1_mlock);
680 list_del(&dev->w1_master_entry);
681 spin_unlock_bh(&w1_mlock);
682
683 list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) {
684 list_del(&sl->w1_slave_entry);
685
686 w1_slave_detach(sl);
687 kfree(sl);
688 }
689 w1_destroy_master_attributes(dev);
690 atomic_dec(&dev->refcnt);
691 continue;
692 }
693
694 if (test_bit(W1_MASTER_NEED_RECONNECT, &dev->flags)) {
695 dev_info(&dev->dev, "Reconnecting slaves in device %s.\n", dev->name);
696 down(&dev->mutex);
697 list_for_each_entry(sl, &dev->slist, w1_slave_entry) {
698 if (sl->family->fid == W1_FAMILY_DEFAULT) {
699 struct w1_reg_num rn;
700 list_del(&sl->w1_slave_entry);
701 w1_slave_detach(sl);
702
703 memcpy(&rn, &sl->reg_num, sizeof(rn));
666 704
667 list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) { 705 kfree(sl);
668 list_del(&sl->w1_slave_entry);
669 706
670 w1_slave_detach(sl); 707 w1_attach_slave_device(dev, &rn);
671 kfree(sl); 708 }
709 }
710 clear_bit(W1_MASTER_NEED_RECONNECT, &dev->flags);
711 up(&dev->mutex);
672 } 712 }
673 w1_destroy_master_attributes(dev);
674 atomic_dec(&dev->refcnt);
675 } 713 }
676 } 714 }
677 715
@@ -686,14 +724,14 @@ int w1_process(void *data)
686 daemonize("%s", dev->name); 724 daemonize("%s", dev->name);
687 allow_signal(SIGTERM); 725 allow_signal(SIGTERM);
688 726
689 while (!dev->need_exit) { 727 while (!test_bit(W1_MASTER_NEED_EXIT, &dev->flags)) {
690 try_to_freeze(PF_FREEZE); 728 try_to_freeze(PF_FREEZE);
691 msleep_interruptible(w1_timeout * 1000); 729 msleep_interruptible(w1_timeout * 1000);
692 730
693 if (signal_pending(current)) 731 if (signal_pending(current))
694 flush_signals(current); 732 flush_signals(current);
695 733
696 if (dev->need_exit) 734 if (test_bit(W1_MASTER_NEED_EXIT, &dev->flags))
697 break; 735 break;
698 736
699 if (!dev->initialized) 737 if (!dev->initialized)
diff --git a/drivers/w1/w1.h b/drivers/w1/w1.h
index 6b5f7be50b8a..4f0a986e33e3 100644
--- a/drivers/w1/w1.h
+++ b/drivers/w1/w1.h
@@ -151,6 +151,9 @@ struct w1_bus_master
151 void (*search)(unsigned long, w1_slave_found_callback); 151 void (*search)(unsigned long, w1_slave_found_callback);
152}; 152};
153 153
154#define W1_MASTER_NEED_EXIT 0
155#define W1_MASTER_NEED_RECONNECT 1
156
154struct w1_master 157struct w1_master
155{ 158{
156 struct list_head w1_master_entry; 159 struct list_head w1_master_entry;
@@ -169,7 +172,8 @@ struct w1_master
169 void *priv; 172 void *priv;
170 int priv_size; 173 int priv_size;
171 174
172 int need_exit; 175 long flags;
176
173 pid_t kpid; 177 pid_t kpid;
174 struct semaphore mutex; 178 struct semaphore mutex;
175 179
diff --git a/drivers/w1/w1_family.c b/drivers/w1/w1_family.c
index b8502d910c50..73e73f6be48a 100644
--- a/drivers/w1/w1_family.c
+++ b/drivers/w1/w1_family.c
@@ -60,9 +60,10 @@ int w1_register_family(struct w1_family *newf)
60 newf->need_exit = 0; 60 newf->need_exit = 0;
61 list_add_tail(&newf->family_entry, &w1_families); 61 list_add_tail(&newf->family_entry, &w1_families);
62 } 62 }
63
64 spin_unlock(&w1_flock); 63 spin_unlock(&w1_flock);
65 64
65 w1_reconnect_slaves(newf);
66
66 return ret; 67 return ret;
67} 68}
68 69
diff --git a/drivers/w1/w1_int.c b/drivers/w1/w1_int.c
index cf18f1324f03..35e85d961702 100644
--- a/drivers/w1/w1_int.c
+++ b/drivers/w1/w1_int.c
@@ -124,10 +124,9 @@ int w1_add_master_device(struct w1_bus_master *master)
124 124
125 /* validate minimum functionality */ 125 /* validate minimum functionality */
126 if (!(master->touch_bit && master->reset_bus) && 126 if (!(master->touch_bit && master->reset_bus) &&
127 !(master->write_bit && master->read_bit)) 127 !(master->write_bit && master->read_bit)) {
128 { 128 printk(KERN_ERR "w1_add_master_device: invalid function set\n");
129 printk(KERN_ERR "w1_add_master_device: invalid function set\n"); 129 return(-EINVAL);
130 return(-EINVAL);
131 } 130 }
132 131
133 dev = w1_alloc_dev(w1_ids++, w1_max_slave_count, w1_max_slave_ttl, &w1_driver, &w1_device); 132 dev = w1_alloc_dev(w1_ids++, w1_max_slave_count, w1_max_slave_ttl, &w1_driver, &w1_device);
@@ -163,7 +162,7 @@ int w1_add_master_device(struct w1_bus_master *master)
163 return 0; 162 return 0;
164 163
165err_out_kill_thread: 164err_out_kill_thread:
166 dev->need_exit = 1; 165 set_bit(W1_MASTER_NEED_EXIT, &dev->flags);
167 if (kill_proc(dev->kpid, SIGTERM, 1)) 166 if (kill_proc(dev->kpid, SIGTERM, 1))
168 dev_err(&dev->dev, 167 dev_err(&dev->dev,
169 "Failed to send signal to w1 kernel thread %d.\n", 168 "Failed to send signal to w1 kernel thread %d.\n",
@@ -181,7 +180,7 @@ void __w1_remove_master_device(struct w1_master *dev)
181 int err; 180 int err;
182 struct w1_netlink_msg msg; 181 struct w1_netlink_msg msg;
183 182
184 dev->need_exit = 1; 183 set_bit(W1_MASTER_NEED_EXIT, &dev->flags);
185 err = kill_proc(dev->kpid, SIGTERM, 1); 184 err = kill_proc(dev->kpid, SIGTERM, 1);
186 if (err) 185 if (err)
187 dev_err(&dev->dev, 186 dev_err(&dev->dev,