diff options
Diffstat (limited to 'drivers/w1')
-rw-r--r-- | drivers/w1/ds_w1_bridge.c | 4 | ||||
-rw-r--r-- | drivers/w1/w1.c | 68 | ||||
-rw-r--r-- | drivers/w1/w1.h | 6 | ||||
-rw-r--r-- | drivers/w1/w1_family.c | 3 | ||||
-rw-r--r-- | drivers/w1/w1_int.c | 11 |
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 | ||
86 | static void ds9490r_write_block(unsigned long data, u8 *buf, int len) | 86 | static 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 | ||
93 | static u8 ds9490r_read_block(unsigned long data, u8 *buf, int len) | 93 | static 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 | ||
497 | void 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 | |||
495 | static void w1_slave_found(unsigned long data, u64 rn) | 511 | static 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 | |||
154 | struct w1_master | 157 | struct 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 | ||
165 | err_out_kill_thread: | 164 | err_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, |