diff options
| -rw-r--r-- | drivers/w1/w1.c | 93 | ||||
| -rw-r--r-- | drivers/w1/w1.h | 3 | ||||
| -rw-r--r-- | drivers/w1/w1_int.c | 6 |
3 files changed, 51 insertions, 51 deletions
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index e592ca2edd49..4e98ab1aa2f2 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c | |||
| @@ -45,10 +45,12 @@ MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>"); | |||
| 45 | MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol."); | 45 | MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol."); |
| 46 | 46 | ||
| 47 | static int w1_timeout = 10; | 47 | static int w1_timeout = 10; |
| 48 | static int w1_control_timeout = 1; | ||
| 48 | int w1_max_slave_count = 10; | 49 | int w1_max_slave_count = 10; |
| 49 | int w1_max_slave_ttl = 10; | 50 | int w1_max_slave_ttl = 10; |
| 50 | 51 | ||
| 51 | module_param_named(timeout, w1_timeout, int, 0); | 52 | module_param_named(timeout, w1_timeout, int, 0); |
| 53 | module_param_named(control_timeout, w1_control_timeout, int, 0); | ||
| 52 | module_param_named(max_slave_count, w1_max_slave_count, int, 0); | 54 | module_param_named(max_slave_count, w1_max_slave_count, int, 0); |
| 53 | module_param_named(slave_ttl, w1_max_slave_ttl, int, 0); | 55 | module_param_named(slave_ttl, w1_max_slave_ttl, int, 0); |
| 54 | 56 | ||
| @@ -69,37 +71,51 @@ static int w1_master_probe(struct device *dev) | |||
| 69 | return -ENODEV; | 71 | return -ENODEV; |
| 70 | } | 72 | } |
| 71 | 73 | ||
| 72 | static int w1_master_remove(struct device *dev) | ||
| 73 | { | ||
| 74 | return 0; | ||
| 75 | } | ||
| 76 | |||
| 77 | static void w1_master_release(struct device *dev) | 74 | static void w1_master_release(struct device *dev) |
| 78 | { | 75 | { |
| 79 | struct w1_master *md = dev_to_w1_master(dev); | 76 | struct w1_master *md = dev_to_w1_master(dev); |
| 80 | complete(&md->dev_released); | 77 | |
| 78 | dev_dbg(dev, "%s: Releasing %s.\n", __func__, md->name); | ||
| 79 | |||
| 80 | if (md->nls && md->nls->sk_socket) | ||
| 81 | sock_release(md->nls->sk_socket); | ||
| 82 | memset(md, 0, sizeof(struct w1_master) + sizeof(struct w1_bus_master)); | ||
| 83 | kfree(md); | ||
| 81 | } | 84 | } |
| 82 | 85 | ||
| 83 | static void w1_slave_release(struct device *dev) | 86 | static void w1_slave_release(struct device *dev) |
| 84 | { | 87 | { |
| 85 | struct w1_slave *sl = dev_to_w1_slave(dev); | 88 | struct w1_slave *sl = dev_to_w1_slave(dev); |
| 86 | complete(&sl->dev_released); | 89 | |
| 90 | dev_dbg(dev, "%s: Releasing %s.\n", __func__, sl->name); | ||
| 91 | |||
| 92 | while (atomic_read(&sl->refcnt)) { | ||
| 93 | dev_dbg(dev, "Waiting for %s to become free: refcnt=%d.\n", | ||
| 94 | sl->name, atomic_read(&sl->refcnt)); | ||
| 95 | if (msleep_interruptible(1000)) | ||
| 96 | flush_signals(current); | ||
| 97 | } | ||
| 98 | |||
| 99 | w1_family_put(sl->family); | ||
| 100 | sl->master->slave_count--; | ||
| 101 | |||
| 102 | complete(&sl->released); | ||
| 87 | } | 103 | } |
| 88 | 104 | ||
| 89 | static ssize_t w1_slave_read_name(struct device *dev, struct device_attribute *attr, char *buf) | 105 | static ssize_t w1_slave_read_name(struct device *dev, struct device_attribute *attr, char *buf) |
| 90 | { | 106 | { |
| 91 | struct w1_slave *sl = dev_to_w1_slave(dev); | 107 | struct w1_slave *sl = dev_to_w1_slave(dev); |
| 92 | 108 | ||
| 93 | return sprintf(buf, "%s\n", sl->name); | 109 | return sprintf(buf, "%s\n", sl->name); |
| 94 | } | 110 | } |
| 95 | 111 | ||
| 96 | static ssize_t w1_slave_read_id(struct kobject *kobj, char *buf, loff_t off, size_t count) | 112 | static ssize_t w1_slave_read_id(struct kobject *kobj, char *buf, loff_t off, size_t count) |
| 97 | { | 113 | { |
| 98 | struct w1_slave *sl = kobj_to_w1_slave(kobj); | 114 | struct w1_slave *sl = kobj_to_w1_slave(kobj); |
| 99 | 115 | ||
| 100 | atomic_inc(&sl->refcnt); | 116 | atomic_inc(&sl->refcnt); |
| 101 | if (off > 8) { | 117 | if (off > 8) { |
| 102 | count = 0; | 118 | count = 0; |
| 103 | } else { | 119 | } else { |
| 104 | if (off + count > 8) | 120 | if (off + count > 8) |
| 105 | count = 8 - off; | 121 | count = 8 - off; |
| @@ -109,7 +125,7 @@ static ssize_t w1_slave_read_id(struct kobject *kobj, char *buf, loff_t off, siz | |||
| 109 | atomic_dec(&sl->refcnt); | 125 | atomic_dec(&sl->refcnt); |
| 110 | 126 | ||
| 111 | return count; | 127 | return count; |
| 112 | } | 128 | } |
| 113 | 129 | ||
| 114 | static struct device_attribute w1_slave_attr_name = | 130 | static struct device_attribute w1_slave_attr_name = |
| 115 | __ATTR(name, S_IRUGO, w1_slave_read_name, NULL); | 131 | __ATTR(name, S_IRUGO, w1_slave_read_name, NULL); |
| @@ -139,7 +155,6 @@ struct device_driver w1_master_driver = { | |||
| 139 | .name = "w1_master_driver", | 155 | .name = "w1_master_driver", |
| 140 | .bus = &w1_bus_type, | 156 | .bus = &w1_bus_type, |
| 141 | .probe = w1_master_probe, | 157 | .probe = w1_master_probe, |
| 142 | .remove = w1_master_remove, | ||
| 143 | }; | 158 | }; |
| 144 | 159 | ||
| 145 | struct device w1_master_device = { | 160 | struct device w1_master_device = { |
| @@ -160,6 +175,7 @@ struct device w1_slave_device = { | |||
| 160 | .bus = &w1_bus_type, | 175 | .bus = &w1_bus_type, |
| 161 | .bus_id = "w1 bus slave", | 176 | .bus_id = "w1 bus slave", |
| 162 | .driver = &w1_slave_driver, | 177 | .driver = &w1_slave_driver, |
| 178 | .release = &w1_slave_release | ||
| 163 | }; | 179 | }; |
| 164 | 180 | ||
| 165 | static ssize_t w1_master_attribute_show_name(struct device *dev, struct device_attribute *attr, char *buf) | 181 | static ssize_t w1_master_attribute_show_name(struct device *dev, struct device_attribute *attr, char *buf) |
| @@ -406,8 +422,7 @@ static int __w1_attach_slave_device(struct w1_slave *sl) | |||
| 406 | (unsigned int) sl->reg_num.family, | 422 | (unsigned int) sl->reg_num.family, |
| 407 | (unsigned long long) sl->reg_num.id); | 423 | (unsigned long long) sl->reg_num.id); |
| 408 | 424 | ||
| 409 | dev_dbg(&sl->dev, "%s: registering %s.\n", __func__, | 425 | dev_dbg(&sl->dev, "%s: registering %s as %p.\n", __func__, &sl->dev.bus_id[0]); |
| 410 | &sl->dev.bus_id[0]); | ||
| 411 | 426 | ||
| 412 | err = device_register(&sl->dev); | 427 | err = device_register(&sl->dev); |
| 413 | if (err < 0) { | 428 | if (err < 0) { |
| @@ -480,7 +495,7 @@ static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn) | |||
| 480 | 495 | ||
| 481 | memcpy(&sl->reg_num, rn, sizeof(sl->reg_num)); | 496 | memcpy(&sl->reg_num, rn, sizeof(sl->reg_num)); |
| 482 | atomic_set(&sl->refcnt, 0); | 497 | atomic_set(&sl->refcnt, 0); |
| 483 | init_completion(&sl->dev_released); | 498 | init_completion(&sl->released); |
| 484 | 499 | ||
| 485 | spin_lock(&w1_flock); | 500 | spin_lock(&w1_flock); |
| 486 | f = w1_family_registered(rn->family); | 501 | f = w1_family_registered(rn->family); |
| @@ -512,6 +527,8 @@ static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn) | |||
| 512 | msg.type = W1_SLAVE_ADD; | 527 | msg.type = W1_SLAVE_ADD; |
| 513 | w1_netlink_send(dev, &msg); | 528 | w1_netlink_send(dev, &msg); |
| 514 | 529 | ||
| 530 | dev_info(&dev->dev, "Finished %s for sl=%p.\n", __func__, sl); | ||
| 531 | |||
| 515 | return 0; | 532 | return 0; |
| 516 | } | 533 | } |
| 517 | 534 | ||
| @@ -519,29 +536,23 @@ static void w1_slave_detach(struct w1_slave *sl) | |||
| 519 | { | 536 | { |
| 520 | struct w1_netlink_msg msg; | 537 | struct w1_netlink_msg msg; |
| 521 | 538 | ||
| 522 | dev_info(&sl->dev, "%s: detaching %s.\n", __func__, sl->name); | 539 | dev_info(&sl->dev, "%s: detaching %s [%p].\n", __func__, sl->name, sl); |
| 523 | 540 | ||
| 524 | while (atomic_read(&sl->refcnt)) { | 541 | list_del(&sl->w1_slave_entry); |
| 525 | printk(KERN_INFO "Waiting for %s to become free: refcnt=%d.\n", | ||
| 526 | sl->name, atomic_read(&sl->refcnt)); | ||
| 527 | |||
| 528 | if (msleep_interruptible(1000)) | ||
| 529 | flush_signals(current); | ||
| 530 | } | ||
| 531 | 542 | ||
| 532 | if (sl->family->fops && sl->family->fops->remove_slave) | 543 | if (sl->family->fops && sl->family->fops->remove_slave) |
| 533 | sl->family->fops->remove_slave(sl); | 544 | sl->family->fops->remove_slave(sl); |
| 534 | 545 | ||
| 546 | memcpy(&msg.id.id, &sl->reg_num, sizeof(msg.id.id)); | ||
| 547 | msg.type = W1_SLAVE_REMOVE; | ||
| 548 | w1_netlink_send(sl->master, &msg); | ||
| 549 | |||
| 535 | sysfs_remove_bin_file(&sl->dev.kobj, &w1_slave_attr_bin_id); | 550 | sysfs_remove_bin_file(&sl->dev.kobj, &w1_slave_attr_bin_id); |
| 536 | device_remove_file(&sl->dev, &w1_slave_attr_name); | 551 | device_remove_file(&sl->dev, &w1_slave_attr_name); |
| 537 | device_unregister(&sl->dev); | 552 | device_unregister(&sl->dev); |
| 538 | w1_family_put(sl->family); | ||
| 539 | 553 | ||
| 540 | sl->master->slave_count--; | 554 | wait_for_completion(&sl->released); |
| 541 | 555 | kfree(sl); | |
| 542 | memcpy(&msg.id.id, &sl->reg_num, sizeof(msg.id.id)); | ||
| 543 | msg.type = W1_SLAVE_REMOVE; | ||
| 544 | w1_netlink_send(sl->master, &msg); | ||
| 545 | } | 556 | } |
| 546 | 557 | ||
| 547 | static struct w1_master *w1_search_master(unsigned long data) | 558 | static struct w1_master *w1_search_master(unsigned long data) |
| @@ -713,7 +724,7 @@ static int w1_control(void *data) | |||
| 713 | have_to_wait = 0; | 724 | have_to_wait = 0; |
| 714 | 725 | ||
| 715 | try_to_freeze(); | 726 | try_to_freeze(); |
| 716 | msleep_interruptible(w1_timeout * 1000); | 727 | msleep_interruptible(w1_control_timeout * 1000); |
| 717 | 728 | ||
| 718 | if (signal_pending(current)) | 729 | if (signal_pending(current)) |
| 719 | flush_signals(current); | 730 | flush_signals(current); |
| @@ -746,13 +757,12 @@ static int w1_control(void *data) | |||
| 746 | list_del(&dev->w1_master_entry); | 757 | list_del(&dev->w1_master_entry); |
| 747 | spin_unlock_bh(&w1_mlock); | 758 | spin_unlock_bh(&w1_mlock); |
| 748 | 759 | ||
| 760 | down(&dev->mutex); | ||
| 749 | list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) { | 761 | list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) { |
| 750 | list_del(&sl->w1_slave_entry); | ||
| 751 | |||
| 752 | w1_slave_detach(sl); | 762 | w1_slave_detach(sl); |
| 753 | kfree(sl); | ||
| 754 | } | 763 | } |
| 755 | w1_destroy_master_attributes(dev); | 764 | w1_destroy_master_attributes(dev); |
| 765 | up(&dev->mutex); | ||
| 756 | atomic_dec(&dev->refcnt); | 766 | atomic_dec(&dev->refcnt); |
| 757 | continue; | 767 | continue; |
| 758 | } | 768 | } |
| @@ -760,19 +770,17 @@ static int w1_control(void *data) | |||
| 760 | if (test_bit(W1_MASTER_NEED_RECONNECT, &dev->flags)) { | 770 | if (test_bit(W1_MASTER_NEED_RECONNECT, &dev->flags)) { |
| 761 | dev_info(&dev->dev, "Reconnecting slaves in device %s.\n", dev->name); | 771 | dev_info(&dev->dev, "Reconnecting slaves in device %s.\n", dev->name); |
| 762 | down(&dev->mutex); | 772 | down(&dev->mutex); |
| 763 | list_for_each_entry(sl, &dev->slist, w1_slave_entry) { | 773 | list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) { |
| 764 | if (sl->family->fid == W1_FAMILY_DEFAULT) { | 774 | if (sl->family->fid == W1_FAMILY_DEFAULT) { |
| 765 | struct w1_reg_num rn; | 775 | struct w1_reg_num rn; |
| 766 | list_del(&sl->w1_slave_entry); | ||
| 767 | w1_slave_detach(sl); | ||
| 768 | 776 | ||
| 769 | memcpy(&rn, &sl->reg_num, sizeof(rn)); | 777 | memcpy(&rn, &sl->reg_num, sizeof(rn)); |
| 770 | 778 | w1_slave_detach(sl); | |
| 771 | kfree(sl); | ||
| 772 | 779 | ||
| 773 | w1_attach_slave_device(dev, &rn); | 780 | w1_attach_slave_device(dev, &rn); |
| 774 | } | 781 | } |
| 775 | } | 782 | } |
| 783 | dev_info(&dev->dev, "Reconnecting slaves in device %s has been finished.\n", dev->name); | ||
| 776 | clear_bit(W1_MASTER_NEED_RECONNECT, &dev->flags); | 784 | clear_bit(W1_MASTER_NEED_RECONNECT, &dev->flags); |
| 777 | up(&dev->mutex); | 785 | up(&dev->mutex); |
| 778 | } | 786 | } |
| @@ -816,10 +824,7 @@ int w1_process(void *data) | |||
| 816 | 824 | ||
| 817 | list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) { | 825 | list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) { |
| 818 | if (!test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags) && !--sl->ttl) { | 826 | if (!test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags) && !--sl->ttl) { |
| 819 | list_del (&sl->w1_slave_entry); | ||
| 820 | |||
| 821 | w1_slave_detach(sl); | 827 | w1_slave_detach(sl); |
| 822 | kfree(sl); | ||
| 823 | 828 | ||
| 824 | dev->slave_count--; | 829 | dev->slave_count--; |
| 825 | } else if (test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags)) | 830 | } else if (test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags)) |
diff --git a/drivers/w1/w1.h b/drivers/w1/w1.h index 13edc82bc7de..6cc7f0c5d434 100644 --- a/drivers/w1/w1.h +++ b/drivers/w1/w1.h | |||
| @@ -76,7 +76,7 @@ struct w1_slave | |||
| 76 | struct w1_master *master; | 76 | struct w1_master *master; |
| 77 | struct w1_family *family; | 77 | struct w1_family *family; |
| 78 | struct device dev; | 78 | struct device dev; |
| 79 | struct completion dev_released; | 79 | struct completion released; |
| 80 | }; | 80 | }; |
| 81 | 81 | ||
| 82 | typedef void (* w1_slave_found_callback)(unsigned long, u64); | 82 | typedef void (* w1_slave_found_callback)(unsigned long, u64); |
| @@ -176,7 +176,6 @@ struct w1_master | |||
| 176 | 176 | ||
| 177 | struct device_driver *driver; | 177 | struct device_driver *driver; |
| 178 | struct device dev; | 178 | struct device dev; |
| 179 | struct completion dev_released; | ||
| 180 | struct completion dev_exited; | 179 | struct completion dev_exited; |
| 181 | 180 | ||
| 182 | struct w1_bus_master *bus_master; | 181 | struct w1_bus_master *bus_master; |
diff --git a/drivers/w1/w1_int.c b/drivers/w1/w1_int.c index c13724fd0971..c3f67eafc7ec 100644 --- a/drivers/w1/w1_int.c +++ b/drivers/w1/w1_int.c | |||
| @@ -76,7 +76,6 @@ static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl, | |||
| 76 | INIT_LIST_HEAD(&dev->slist); | 76 | INIT_LIST_HEAD(&dev->slist); |
| 77 | init_MUTEX(&dev->mutex); | 77 | init_MUTEX(&dev->mutex); |
| 78 | 78 | ||
| 79 | init_completion(&dev->dev_released); | ||
| 80 | init_completion(&dev->dev_exited); | 79 | init_completion(&dev->dev_exited); |
| 81 | 80 | ||
| 82 | memcpy(&dev->dev, device, sizeof(struct device)); | 81 | memcpy(&dev->dev, device, sizeof(struct device)); |
| @@ -107,9 +106,6 @@ static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl, | |||
| 107 | void w1_free_dev(struct w1_master *dev) | 106 | void w1_free_dev(struct w1_master *dev) |
| 108 | { | 107 | { |
| 109 | device_unregister(&dev->dev); | 108 | device_unregister(&dev->dev); |
| 110 | dev_fini_netlink(dev); | ||
| 111 | memset(dev, 0, sizeof(struct w1_master) + sizeof(struct w1_bus_master)); | ||
| 112 | kfree(dev); | ||
| 113 | } | 109 | } |
| 114 | 110 | ||
| 115 | int w1_add_master_device(struct w1_bus_master *master) | 111 | int w1_add_master_device(struct w1_bus_master *master) |
| @@ -184,7 +180,7 @@ void __w1_remove_master_device(struct w1_master *dev) | |||
| 184 | __func__, dev->kpid); | 180 | __func__, dev->kpid); |
| 185 | 181 | ||
| 186 | while (atomic_read(&dev->refcnt)) { | 182 | while (atomic_read(&dev->refcnt)) { |
| 187 | printk(KERN_INFO "Waiting for %s to become free: refcnt=%d.\n", | 183 | dev_dbg(&dev->dev, "Waiting for %s to become free: refcnt=%d.\n", |
| 188 | dev->name, atomic_read(&dev->refcnt)); | 184 | dev->name, atomic_read(&dev->refcnt)); |
| 189 | 185 | ||
| 190 | if (msleep_interruptible(1000)) | 186 | if (msleep_interruptible(1000)) |
