aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/w1
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/w1')
-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,