diff options
Diffstat (limited to 'drivers/w1/w1.c')
-rw-r--r-- | drivers/w1/w1.c | 423 |
1 files changed, 251 insertions, 172 deletions
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index 7293c9b11f91..3b615d4022ee 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c | |||
@@ -46,19 +46,17 @@ MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>"); | |||
46 | MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol."); | 46 | MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol."); |
47 | 47 | ||
48 | static int w1_timeout = 10; | 48 | static int w1_timeout = 10; |
49 | static int w1_control_timeout = 1; | ||
50 | int w1_max_slave_count = 10; | 49 | int w1_max_slave_count = 10; |
51 | int w1_max_slave_ttl = 10; | 50 | int w1_max_slave_ttl = 10; |
52 | 51 | ||
53 | module_param_named(timeout, w1_timeout, int, 0); | 52 | module_param_named(timeout, w1_timeout, int, 0); |
54 | module_param_named(control_timeout, w1_control_timeout, int, 0); | ||
55 | module_param_named(max_slave_count, w1_max_slave_count, int, 0); | 53 | module_param_named(max_slave_count, w1_max_slave_count, int, 0); |
56 | module_param_named(slave_ttl, w1_max_slave_ttl, int, 0); | 54 | module_param_named(slave_ttl, w1_max_slave_ttl, int, 0); |
57 | 55 | ||
58 | DEFINE_MUTEX(w1_mlock); | 56 | DEFINE_MUTEX(w1_mlock); |
59 | LIST_HEAD(w1_masters); | 57 | LIST_HEAD(w1_masters); |
60 | 58 | ||
61 | static struct task_struct *w1_control_thread; | 59 | static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn); |
62 | 60 | ||
63 | static int w1_master_match(struct device *dev, struct device_driver *drv) | 61 | static int w1_master_match(struct device *dev, struct device_driver *drv) |
64 | { | 62 | { |
@@ -83,10 +81,10 @@ static void w1_slave_release(struct device *dev) | |||
83 | { | 81 | { |
84 | struct w1_slave *sl = dev_to_w1_slave(dev); | 82 | struct w1_slave *sl = dev_to_w1_slave(dev); |
85 | 83 | ||
86 | printk("%s: Releasing %s.\n", __func__, sl->name); | 84 | dev_dbg(dev, "%s: Releasing %s.\n", __func__, sl->name); |
87 | 85 | ||
88 | while (atomic_read(&sl->refcnt)) { | 86 | while (atomic_read(&sl->refcnt)) { |
89 | printk("Waiting for %s to become free: refcnt=%d.\n", | 87 | dev_dbg(dev, "Waiting for %s to become free: refcnt=%d.\n", |
90 | sl->name, atomic_read(&sl->refcnt)); | 88 | sl->name, atomic_read(&sl->refcnt)); |
91 | if (msleep_interruptible(1000)) | 89 | if (msleep_interruptible(1000)) |
92 | flush_signals(current); | 90 | flush_signals(current); |
@@ -105,35 +103,20 @@ static ssize_t w1_slave_read_name(struct device *dev, struct device_attribute *a | |||
105 | return sprintf(buf, "%s\n", sl->name); | 103 | return sprintf(buf, "%s\n", sl->name); |
106 | } | 104 | } |
107 | 105 | ||
108 | static ssize_t w1_slave_read_id(struct kobject *kobj, | 106 | static ssize_t w1_slave_read_id(struct device *dev, |
109 | struct bin_attribute *bin_attr, | 107 | struct device_attribute *attr, char *buf) |
110 | char *buf, loff_t off, size_t count) | ||
111 | { | 108 | { |
112 | struct w1_slave *sl = kobj_to_w1_slave(kobj); | 109 | struct w1_slave *sl = dev_to_w1_slave(dev); |
113 | 110 | ssize_t count = sizeof(sl->reg_num); | |
114 | if (off > 8) { | ||
115 | count = 0; | ||
116 | } else { | ||
117 | if (off + count > 8) | ||
118 | count = 8 - off; | ||
119 | |||
120 | memcpy(buf, (u8 *)&sl->reg_num, count); | ||
121 | } | ||
122 | 111 | ||
112 | memcpy(buf, (u8 *)&sl->reg_num, count); | ||
123 | return count; | 113 | return count; |
124 | } | 114 | } |
125 | 115 | ||
126 | static struct device_attribute w1_slave_attr_name = | 116 | static struct device_attribute w1_slave_attr_name = |
127 | __ATTR(name, S_IRUGO, w1_slave_read_name, NULL); | 117 | __ATTR(name, S_IRUGO, w1_slave_read_name, NULL); |
128 | 118 | static struct device_attribute w1_slave_attr_id = | |
129 | static struct bin_attribute w1_slave_attr_bin_id = { | 119 | __ATTR(id, S_IRUGO, w1_slave_read_id, NULL); |
130 | .attr = { | ||
131 | .name = "id", | ||
132 | .mode = S_IRUGO, | ||
133 | }, | ||
134 | .size = 8, | ||
135 | .read = w1_slave_read_id, | ||
136 | }; | ||
137 | 120 | ||
138 | /* Default family */ | 121 | /* Default family */ |
139 | 122 | ||
@@ -250,11 +233,16 @@ static ssize_t w1_master_attribute_store_search(struct device * dev, | |||
250 | struct device_attribute *attr, | 233 | struct device_attribute *attr, |
251 | const char * buf, size_t count) | 234 | const char * buf, size_t count) |
252 | { | 235 | { |
236 | long tmp; | ||
253 | struct w1_master *md = dev_to_w1_master(dev); | 237 | struct w1_master *md = dev_to_w1_master(dev); |
254 | 238 | ||
239 | if (strict_strtol(buf, 0, &tmp) == -EINVAL) | ||
240 | return -EINVAL; | ||
241 | |||
255 | mutex_lock(&md->mutex); | 242 | mutex_lock(&md->mutex); |
256 | md->search_count = simple_strtol(buf, NULL, 0); | 243 | md->search_count = tmp; |
257 | mutex_unlock(&md->mutex); | 244 | mutex_unlock(&md->mutex); |
245 | wake_up_process(md->thread); | ||
258 | 246 | ||
259 | return count; | 247 | return count; |
260 | } | 248 | } |
@@ -273,6 +261,38 @@ static ssize_t w1_master_attribute_show_search(struct device *dev, | |||
273 | return count; | 261 | return count; |
274 | } | 262 | } |
275 | 263 | ||
264 | static ssize_t w1_master_attribute_store_pullup(struct device *dev, | ||
265 | struct device_attribute *attr, | ||
266 | const char *buf, size_t count) | ||
267 | { | ||
268 | long tmp; | ||
269 | struct w1_master *md = dev_to_w1_master(dev); | ||
270 | |||
271 | if (strict_strtol(buf, 0, &tmp) == -EINVAL) | ||
272 | return -EINVAL; | ||
273 | |||
274 | mutex_lock(&md->mutex); | ||
275 | md->enable_pullup = tmp; | ||
276 | mutex_unlock(&md->mutex); | ||
277 | wake_up_process(md->thread); | ||
278 | |||
279 | return count; | ||
280 | } | ||
281 | |||
282 | static ssize_t w1_master_attribute_show_pullup(struct device *dev, | ||
283 | struct device_attribute *attr, | ||
284 | char *buf) | ||
285 | { | ||
286 | struct w1_master *md = dev_to_w1_master(dev); | ||
287 | ssize_t count; | ||
288 | |||
289 | mutex_lock(&md->mutex); | ||
290 | count = sprintf(buf, "%d\n", md->enable_pullup); | ||
291 | mutex_unlock(&md->mutex); | ||
292 | |||
293 | return count; | ||
294 | } | ||
295 | |||
276 | static ssize_t w1_master_attribute_show_pointer(struct device *dev, struct device_attribute *attr, char *buf) | 296 | static ssize_t w1_master_attribute_show_pointer(struct device *dev, struct device_attribute *attr, char *buf) |
277 | { | 297 | { |
278 | struct w1_master *md = dev_to_w1_master(dev); | 298 | struct w1_master *md = dev_to_w1_master(dev); |
@@ -324,7 +344,8 @@ static ssize_t w1_master_attribute_show_slave_count(struct device *dev, struct d | |||
324 | return count; | 344 | return count; |
325 | } | 345 | } |
326 | 346 | ||
327 | static ssize_t w1_master_attribute_show_slaves(struct device *dev, struct device_attribute *attr, char *buf) | 347 | static ssize_t w1_master_attribute_show_slaves(struct device *dev, |
348 | struct device_attribute *attr, char *buf) | ||
328 | { | 349 | { |
329 | struct w1_master *md = dev_to_w1_master(dev); | 350 | struct w1_master *md = dev_to_w1_master(dev); |
330 | int c = PAGE_SIZE; | 351 | int c = PAGE_SIZE; |
@@ -349,6 +370,135 @@ static ssize_t w1_master_attribute_show_slaves(struct device *dev, struct device | |||
349 | return PAGE_SIZE - c; | 370 | return PAGE_SIZE - c; |
350 | } | 371 | } |
351 | 372 | ||
373 | static ssize_t w1_master_attribute_show_add(struct device *dev, | ||
374 | struct device_attribute *attr, char *buf) | ||
375 | { | ||
376 | int c = PAGE_SIZE; | ||
377 | c -= snprintf(buf+PAGE_SIZE - c, c, | ||
378 | "write device id xx-xxxxxxxxxxxx to add slave\n"); | ||
379 | return PAGE_SIZE - c; | ||
380 | } | ||
381 | |||
382 | static int w1_atoreg_num(struct device *dev, const char *buf, size_t count, | ||
383 | struct w1_reg_num *rn) | ||
384 | { | ||
385 | unsigned int family; | ||
386 | unsigned long long id; | ||
387 | int i; | ||
388 | u64 rn64_le; | ||
389 | |||
390 | /* The CRC value isn't read from the user because the sysfs directory | ||
391 | * doesn't include it and most messages from the bus search don't | ||
392 | * print it either. It would be unreasonable for the user to then | ||
393 | * provide it. | ||
394 | */ | ||
395 | const char *error_msg = "bad slave string format, expecting " | ||
396 | "ff-dddddddddddd\n"; | ||
397 | |||
398 | if (buf[2] != '-') { | ||
399 | dev_err(dev, "%s", error_msg); | ||
400 | return -EINVAL; | ||
401 | } | ||
402 | i = sscanf(buf, "%02x-%012llx", &family, &id); | ||
403 | if (i != 2) { | ||
404 | dev_err(dev, "%s", error_msg); | ||
405 | return -EINVAL; | ||
406 | } | ||
407 | rn->family = family; | ||
408 | rn->id = id; | ||
409 | |||
410 | rn64_le = cpu_to_le64(*(u64 *)rn); | ||
411 | rn->crc = w1_calc_crc8((u8 *)&rn64_le, 7); | ||
412 | |||
413 | #if 0 | ||
414 | dev_info(dev, "With CRC device is %02x.%012llx.%02x.\n", | ||
415 | rn->family, (unsigned long long)rn->id, rn->crc); | ||
416 | #endif | ||
417 | |||
418 | return 0; | ||
419 | } | ||
420 | |||
421 | /* Searches the slaves in the w1_master and returns a pointer or NULL. | ||
422 | * Note: must hold the mutex | ||
423 | */ | ||
424 | static struct w1_slave *w1_slave_search_device(struct w1_master *dev, | ||
425 | struct w1_reg_num *rn) | ||
426 | { | ||
427 | struct w1_slave *sl; | ||
428 | list_for_each_entry(sl, &dev->slist, w1_slave_entry) { | ||
429 | if (sl->reg_num.family == rn->family && | ||
430 | sl->reg_num.id == rn->id && | ||
431 | sl->reg_num.crc == rn->crc) { | ||
432 | return sl; | ||
433 | } | ||
434 | } | ||
435 | return NULL; | ||
436 | } | ||
437 | |||
438 | static ssize_t w1_master_attribute_store_add(struct device *dev, | ||
439 | struct device_attribute *attr, | ||
440 | const char *buf, size_t count) | ||
441 | { | ||
442 | struct w1_master *md = dev_to_w1_master(dev); | ||
443 | struct w1_reg_num rn; | ||
444 | struct w1_slave *sl; | ||
445 | ssize_t result = count; | ||
446 | |||
447 | if (w1_atoreg_num(dev, buf, count, &rn)) | ||
448 | return -EINVAL; | ||
449 | |||
450 | mutex_lock(&md->mutex); | ||
451 | sl = w1_slave_search_device(md, &rn); | ||
452 | /* It would be nice to do a targeted search one the one-wire bus | ||
453 | * for the new device to see if it is out there or not. But the | ||
454 | * current search doesn't support that. | ||
455 | */ | ||
456 | if (sl) { | ||
457 | dev_info(dev, "Device %s already exists\n", sl->name); | ||
458 | result = -EINVAL; | ||
459 | } else { | ||
460 | w1_attach_slave_device(md, &rn); | ||
461 | } | ||
462 | mutex_unlock(&md->mutex); | ||
463 | |||
464 | return result; | ||
465 | } | ||
466 | |||
467 | static ssize_t w1_master_attribute_show_remove(struct device *dev, | ||
468 | struct device_attribute *attr, char *buf) | ||
469 | { | ||
470 | int c = PAGE_SIZE; | ||
471 | c -= snprintf(buf+PAGE_SIZE - c, c, | ||
472 | "write device id xx-xxxxxxxxxxxx to remove slave\n"); | ||
473 | return PAGE_SIZE - c; | ||
474 | } | ||
475 | |||
476 | static ssize_t w1_master_attribute_store_remove(struct device *dev, | ||
477 | struct device_attribute *attr, | ||
478 | const char *buf, size_t count) | ||
479 | { | ||
480 | struct w1_master *md = dev_to_w1_master(dev); | ||
481 | struct w1_reg_num rn; | ||
482 | struct w1_slave *sl; | ||
483 | ssize_t result = count; | ||
484 | |||
485 | if (w1_atoreg_num(dev, buf, count, &rn)) | ||
486 | return -EINVAL; | ||
487 | |||
488 | mutex_lock(&md->mutex); | ||
489 | sl = w1_slave_search_device(md, &rn); | ||
490 | if (sl) { | ||
491 | w1_slave_detach(sl); | ||
492 | } else { | ||
493 | dev_info(dev, "Device %02x-%012llx doesn't exists\n", rn.family, | ||
494 | (unsigned long long)rn.id); | ||
495 | result = -EINVAL; | ||
496 | } | ||
497 | mutex_unlock(&md->mutex); | ||
498 | |||
499 | return result; | ||
500 | } | ||
501 | |||
352 | #define W1_MASTER_ATTR_RO(_name, _mode) \ | 502 | #define W1_MASTER_ATTR_RO(_name, _mode) \ |
353 | struct device_attribute w1_master_attribute_##_name = \ | 503 | struct device_attribute w1_master_attribute_##_name = \ |
354 | __ATTR(w1_master_##_name, _mode, \ | 504 | __ATTR(w1_master_##_name, _mode, \ |
@@ -368,6 +518,9 @@ static W1_MASTER_ATTR_RO(attempts, S_IRUGO); | |||
368 | static W1_MASTER_ATTR_RO(timeout, S_IRUGO); | 518 | static W1_MASTER_ATTR_RO(timeout, S_IRUGO); |
369 | static W1_MASTER_ATTR_RO(pointer, S_IRUGO); | 519 | static W1_MASTER_ATTR_RO(pointer, S_IRUGO); |
370 | static W1_MASTER_ATTR_RW(search, S_IRUGO | S_IWUGO); | 520 | static W1_MASTER_ATTR_RW(search, S_IRUGO | S_IWUGO); |
521 | static W1_MASTER_ATTR_RW(pullup, S_IRUGO | S_IWUGO); | ||
522 | static W1_MASTER_ATTR_RW(add, S_IRUGO | S_IWUGO); | ||
523 | static W1_MASTER_ATTR_RW(remove, S_IRUGO | S_IWUGO); | ||
371 | 524 | ||
372 | static struct attribute *w1_master_default_attrs[] = { | 525 | static struct attribute *w1_master_default_attrs[] = { |
373 | &w1_master_attribute_name.attr, | 526 | &w1_master_attribute_name.attr, |
@@ -378,6 +531,9 @@ static struct attribute *w1_master_default_attrs[] = { | |||
378 | &w1_master_attribute_timeout.attr, | 531 | &w1_master_attribute_timeout.attr, |
379 | &w1_master_attribute_pointer.attr, | 532 | &w1_master_attribute_pointer.attr, |
380 | &w1_master_attribute_search.attr, | 533 | &w1_master_attribute_search.attr, |
534 | &w1_master_attribute_pullup.attr, | ||
535 | &w1_master_attribute_add.attr, | ||
536 | &w1_master_attribute_remove.attr, | ||
381 | NULL | 537 | NULL |
382 | }; | 538 | }; |
383 | 539 | ||
@@ -390,7 +546,7 @@ int w1_create_master_attributes(struct w1_master *master) | |||
390 | return sysfs_create_group(&master->dev.kobj, &w1_master_defattr_group); | 546 | return sysfs_create_group(&master->dev.kobj, &w1_master_defattr_group); |
391 | } | 547 | } |
392 | 548 | ||
393 | static void w1_destroy_master_attributes(struct w1_master *master) | 549 | void w1_destroy_master_attributes(struct w1_master *master) |
394 | { | 550 | { |
395 | sysfs_remove_group(&master->dev.kobj, &w1_master_defattr_group); | 551 | sysfs_remove_group(&master->dev.kobj, &w1_master_defattr_group); |
396 | } | 552 | } |
@@ -479,7 +635,7 @@ static int __w1_attach_slave_device(struct w1_slave *sl) | |||
479 | } | 635 | } |
480 | 636 | ||
481 | /* Create "id" entry */ | 637 | /* Create "id" entry */ |
482 | err = sysfs_create_bin_file(&sl->dev.kobj, &w1_slave_attr_bin_id); | 638 | err = device_create_file(&sl->dev, &w1_slave_attr_id); |
483 | if (err < 0) { | 639 | if (err < 0) { |
484 | dev_err(&sl->dev, | 640 | dev_err(&sl->dev, |
485 | "sysfs file creation for [%s] failed. err=%d\n", | 641 | "sysfs file creation for [%s] failed. err=%d\n", |
@@ -501,7 +657,7 @@ static int __w1_attach_slave_device(struct w1_slave *sl) | |||
501 | return 0; | 657 | return 0; |
502 | 658 | ||
503 | out_rem2: | 659 | out_rem2: |
504 | sysfs_remove_bin_file(&sl->dev.kobj, &w1_slave_attr_bin_id); | 660 | device_remove_file(&sl->dev, &w1_slave_attr_id); |
505 | out_rem1: | 661 | out_rem1: |
506 | device_remove_file(&sl->dev, &w1_slave_attr_name); | 662 | device_remove_file(&sl->dev, &w1_slave_attr_name); |
507 | out_unreg: | 663 | out_unreg: |
@@ -567,7 +723,7 @@ static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn) | |||
567 | return 0; | 723 | return 0; |
568 | } | 724 | } |
569 | 725 | ||
570 | static void w1_slave_detach(struct w1_slave *sl) | 726 | void w1_slave_detach(struct w1_slave *sl) |
571 | { | 727 | { |
572 | struct w1_netlink_msg msg; | 728 | struct w1_netlink_msg msg; |
573 | 729 | ||
@@ -583,7 +739,7 @@ static void w1_slave_detach(struct w1_slave *sl) | |||
583 | msg.type = W1_SLAVE_REMOVE; | 739 | msg.type = W1_SLAVE_REMOVE; |
584 | w1_netlink_send(sl->master, &msg); | 740 | w1_netlink_send(sl->master, &msg); |
585 | 741 | ||
586 | sysfs_remove_bin_file(&sl->dev.kobj, &w1_slave_attr_bin_id); | 742 | device_remove_file(&sl->dev, &w1_slave_attr_id); |
587 | device_remove_file(&sl->dev, &w1_slave_attr_name); | 743 | device_remove_file(&sl->dev, &w1_slave_attr_name); |
588 | device_unregister(&sl->dev); | 744 | device_unregister(&sl->dev); |
589 | 745 | ||
@@ -591,24 +747,6 @@ static void w1_slave_detach(struct w1_slave *sl) | |||
591 | kfree(sl); | 747 | kfree(sl); |
592 | } | 748 | } |
593 | 749 | ||
594 | static struct w1_master *w1_search_master(void *data) | ||
595 | { | ||
596 | struct w1_master *dev; | ||
597 | int found = 0; | ||
598 | |||
599 | mutex_lock(&w1_mlock); | ||
600 | list_for_each_entry(dev, &w1_masters, w1_master_entry) { | ||
601 | if (dev->bus_master->data == data) { | ||
602 | found = 1; | ||
603 | atomic_inc(&dev->refcnt); | ||
604 | break; | ||
605 | } | ||
606 | } | ||
607 | mutex_unlock(&w1_mlock); | ||
608 | |||
609 | return (found)?dev:NULL; | ||
610 | } | ||
611 | |||
612 | struct w1_master *w1_search_master_id(u32 id) | 750 | struct w1_master *w1_search_master_id(u32 id) |
613 | { | 751 | { |
614 | struct w1_master *dev; | 752 | struct w1_master *dev; |
@@ -656,55 +794,56 @@ struct w1_slave *w1_search_slave(struct w1_reg_num *id) | |||
656 | return (found)?sl:NULL; | 794 | return (found)?sl:NULL; |
657 | } | 795 | } |
658 | 796 | ||
659 | void w1_reconnect_slaves(struct w1_family *f) | 797 | void w1_reconnect_slaves(struct w1_family *f, int attach) |
660 | { | 798 | { |
799 | struct w1_slave *sl, *sln; | ||
661 | struct w1_master *dev; | 800 | struct w1_master *dev; |
662 | 801 | ||
663 | mutex_lock(&w1_mlock); | 802 | mutex_lock(&w1_mlock); |
664 | list_for_each_entry(dev, &w1_masters, w1_master_entry) { | 803 | list_for_each_entry(dev, &w1_masters, w1_master_entry) { |
665 | dev_dbg(&dev->dev, "Reconnecting slaves in %s into new family %02x.\n", | 804 | dev_dbg(&dev->dev, "Reconnecting slaves in device %s " |
666 | dev->name, f->fid); | 805 | "for family %02x.\n", dev->name, f->fid); |
667 | set_bit(W1_MASTER_NEED_RECONNECT, &dev->flags); | 806 | mutex_lock(&dev->mutex); |
807 | list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) { | ||
808 | /* If it is a new family, slaves with the default | ||
809 | * family driver and are that family will be | ||
810 | * connected. If the family is going away, devices | ||
811 | * matching that family are reconneced. | ||
812 | */ | ||
813 | if ((attach && sl->family->fid == W1_FAMILY_DEFAULT | ||
814 | && sl->reg_num.family == f->fid) || | ||
815 | (!attach && sl->family->fid == f->fid)) { | ||
816 | struct w1_reg_num rn; | ||
817 | |||
818 | memcpy(&rn, &sl->reg_num, sizeof(rn)); | ||
819 | w1_slave_detach(sl); | ||
820 | |||
821 | w1_attach_slave_device(dev, &rn); | ||
822 | } | ||
823 | } | ||
824 | dev_dbg(&dev->dev, "Reconnecting slaves in device %s " | ||
825 | "has been finished.\n", dev->name); | ||
826 | mutex_unlock(&dev->mutex); | ||
668 | } | 827 | } |
669 | mutex_unlock(&w1_mlock); | 828 | mutex_unlock(&w1_mlock); |
670 | } | 829 | } |
671 | 830 | ||
672 | static void w1_slave_found(void *data, u64 rn) | 831 | static void w1_slave_found(struct w1_master *dev, u64 rn) |
673 | { | 832 | { |
674 | int slave_count; | ||
675 | struct w1_slave *sl; | 833 | struct w1_slave *sl; |
676 | struct list_head *ent; | ||
677 | struct w1_reg_num *tmp; | 834 | struct w1_reg_num *tmp; |
678 | struct w1_master *dev; | ||
679 | u64 rn_le = cpu_to_le64(rn); | 835 | u64 rn_le = cpu_to_le64(rn); |
680 | 836 | ||
681 | dev = w1_search_master(data); | 837 | atomic_inc(&dev->refcnt); |
682 | if (!dev) { | ||
683 | printk(KERN_ERR "Failed to find w1 master device for data %p, " | ||
684 | "it is impossible.\n", data); | ||
685 | return; | ||
686 | } | ||
687 | 838 | ||
688 | tmp = (struct w1_reg_num *) &rn; | 839 | tmp = (struct w1_reg_num *) &rn; |
689 | 840 | ||
690 | slave_count = 0; | 841 | sl = w1_slave_search_device(dev, tmp); |
691 | list_for_each(ent, &dev->slist) { | 842 | if (sl) { |
692 | 843 | set_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags); | |
693 | sl = list_entry(ent, struct w1_slave, w1_slave_entry); | 844 | } else { |
694 | 845 | if (rn && tmp->crc == w1_calc_crc8((u8 *)&rn_le, 7)) | |
695 | if (sl->reg_num.family == tmp->family && | 846 | w1_attach_slave_device(dev, tmp); |
696 | sl->reg_num.id == tmp->id && | ||
697 | sl->reg_num.crc == tmp->crc) { | ||
698 | set_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags); | ||
699 | break; | ||
700 | } | ||
701 | |||
702 | slave_count++; | ||
703 | } | ||
704 | |||
705 | if (slave_count == dev->slave_count && | ||
706 | rn && ((rn >> 56) & 0xff) == w1_calc_crc8((u8 *)&rn_le, 7)) { | ||
707 | w1_attach_slave_device(dev, tmp); | ||
708 | } | 847 | } |
709 | 848 | ||
710 | atomic_dec(&dev->refcnt); | 849 | atomic_dec(&dev->refcnt); |
@@ -779,80 +918,20 @@ void w1_search(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb | |||
779 | /* extract the direction taken & update the device number */ | 918 | /* extract the direction taken & update the device number */ |
780 | tmp64 = (triplet_ret >> 2); | 919 | tmp64 = (triplet_ret >> 2); |
781 | rn |= (tmp64 << i); | 920 | rn |= (tmp64 << i); |
921 | |||
922 | if (kthread_should_stop()) { | ||
923 | dev_dbg(&dev->dev, "Abort w1_search\n"); | ||
924 | return; | ||
925 | } | ||
782 | } | 926 | } |
783 | 927 | ||
784 | if ( (triplet_ret & 0x03) != 0x03 ) { | 928 | if ( (triplet_ret & 0x03) != 0x03 ) { |
785 | if ( (desc_bit == last_zero) || (last_zero < 0)) | 929 | if ( (desc_bit == last_zero) || (last_zero < 0)) |
786 | last_device = 1; | 930 | last_device = 1; |
787 | desc_bit = last_zero; | 931 | desc_bit = last_zero; |
788 | cb(dev->bus_master->data, rn); | 932 | cb(dev, rn); |
789 | } | ||
790 | } | ||
791 | } | ||
792 | |||
793 | static int w1_control(void *data) | ||
794 | { | ||
795 | struct w1_slave *sl, *sln; | ||
796 | struct w1_master *dev, *n; | ||
797 | int have_to_wait = 0; | ||
798 | |||
799 | set_freezable(); | ||
800 | while (!kthread_should_stop() || have_to_wait) { | ||
801 | have_to_wait = 0; | ||
802 | |||
803 | try_to_freeze(); | ||
804 | msleep_interruptible(w1_control_timeout * 1000); | ||
805 | |||
806 | list_for_each_entry_safe(dev, n, &w1_masters, w1_master_entry) { | ||
807 | if (!kthread_should_stop() && !dev->flags) | ||
808 | continue; | ||
809 | /* | ||
810 | * Little race: we can create thread but not set the flag. | ||
811 | * Get a chance for external process to set flag up. | ||
812 | */ | ||
813 | if (!dev->initialized) { | ||
814 | have_to_wait = 1; | ||
815 | continue; | ||
816 | } | ||
817 | |||
818 | if (kthread_should_stop() || test_bit(W1_MASTER_NEED_EXIT, &dev->flags)) { | ||
819 | set_bit(W1_MASTER_NEED_EXIT, &dev->flags); | ||
820 | |||
821 | mutex_lock(&w1_mlock); | ||
822 | list_del(&dev->w1_master_entry); | ||
823 | mutex_unlock(&w1_mlock); | ||
824 | |||
825 | mutex_lock(&dev->mutex); | ||
826 | list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) { | ||
827 | w1_slave_detach(sl); | ||
828 | } | ||
829 | w1_destroy_master_attributes(dev); | ||
830 | mutex_unlock(&dev->mutex); | ||
831 | atomic_dec(&dev->refcnt); | ||
832 | continue; | ||
833 | } | ||
834 | |||
835 | if (test_bit(W1_MASTER_NEED_RECONNECT, &dev->flags)) { | ||
836 | dev_dbg(&dev->dev, "Reconnecting slaves in device %s.\n", dev->name); | ||
837 | mutex_lock(&dev->mutex); | ||
838 | list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) { | ||
839 | if (sl->family->fid == W1_FAMILY_DEFAULT) { | ||
840 | struct w1_reg_num rn; | ||
841 | |||
842 | memcpy(&rn, &sl->reg_num, sizeof(rn)); | ||
843 | w1_slave_detach(sl); | ||
844 | |||
845 | w1_attach_slave_device(dev, &rn); | ||
846 | } | ||
847 | } | ||
848 | dev_dbg(&dev->dev, "Reconnecting slaves in device %s has been finished.\n", dev->name); | ||
849 | clear_bit(W1_MASTER_NEED_RECONNECT, &dev->flags); | ||
850 | mutex_unlock(&dev->mutex); | ||
851 | } | ||
852 | } | 933 | } |
853 | } | 934 | } |
854 | |||
855 | return 0; | ||
856 | } | 935 | } |
857 | 936 | ||
858 | void w1_search_process(struct w1_master *dev, u8 search_type) | 937 | void w1_search_process(struct w1_master *dev, u8 search_type) |
@@ -878,23 +957,29 @@ void w1_search_process(struct w1_master *dev, u8 search_type) | |||
878 | int w1_process(void *data) | 957 | int w1_process(void *data) |
879 | { | 958 | { |
880 | struct w1_master *dev = (struct w1_master *) data; | 959 | struct w1_master *dev = (struct w1_master *) data; |
960 | /* As long as w1_timeout is only set by a module parameter the sleep | ||
961 | * time can be calculated in jiffies once. | ||
962 | */ | ||
963 | const unsigned long jtime = msecs_to_jiffies(w1_timeout * 1000); | ||
964 | |||
965 | while (!kthread_should_stop()) { | ||
966 | if (dev->search_count) { | ||
967 | mutex_lock(&dev->mutex); | ||
968 | w1_search_process(dev, W1_SEARCH); | ||
969 | mutex_unlock(&dev->mutex); | ||
970 | } | ||
881 | 971 | ||
882 | while (!kthread_should_stop() && !test_bit(W1_MASTER_NEED_EXIT, &dev->flags)) { | ||
883 | try_to_freeze(); | 972 | try_to_freeze(); |
884 | msleep_interruptible(w1_timeout * 1000); | 973 | __set_current_state(TASK_INTERRUPTIBLE); |
885 | 974 | ||
886 | if (kthread_should_stop() || test_bit(W1_MASTER_NEED_EXIT, &dev->flags)) | 975 | if (kthread_should_stop()) |
887 | break; | 976 | break; |
888 | 977 | ||
889 | if (!dev->initialized) | 978 | /* Only sleep when the search is active. */ |
890 | continue; | 979 | if (dev->search_count) |
891 | 980 | schedule_timeout(jtime); | |
892 | if (dev->search_count == 0) | 981 | else |
893 | continue; | 982 | schedule(); |
894 | |||
895 | mutex_lock(&dev->mutex); | ||
896 | w1_search_process(dev, W1_SEARCH); | ||
897 | mutex_unlock(&dev->mutex); | ||
898 | } | 983 | } |
899 | 984 | ||
900 | atomic_dec(&dev->refcnt); | 985 | atomic_dec(&dev->refcnt); |
@@ -932,18 +1017,13 @@ static int w1_init(void) | |||
932 | goto err_out_master_unregister; | 1017 | goto err_out_master_unregister; |
933 | } | 1018 | } |
934 | 1019 | ||
935 | w1_control_thread = kthread_run(w1_control, NULL, "w1_control"); | ||
936 | if (IS_ERR(w1_control_thread)) { | ||
937 | retval = PTR_ERR(w1_control_thread); | ||
938 | printk(KERN_ERR "Failed to create control thread. err=%d\n", | ||
939 | retval); | ||
940 | goto err_out_slave_unregister; | ||
941 | } | ||
942 | |||
943 | return 0; | 1020 | return 0; |
944 | 1021 | ||
1022 | #if 0 | ||
1023 | /* For undoing the slave register if there was a step after it. */ | ||
945 | err_out_slave_unregister: | 1024 | err_out_slave_unregister: |
946 | driver_unregister(&w1_slave_driver); | 1025 | driver_unregister(&w1_slave_driver); |
1026 | #endif | ||
947 | 1027 | ||
948 | err_out_master_unregister: | 1028 | err_out_master_unregister: |
949 | driver_unregister(&w1_master_driver); | 1029 | driver_unregister(&w1_master_driver); |
@@ -959,13 +1039,12 @@ static void w1_fini(void) | |||
959 | { | 1039 | { |
960 | struct w1_master *dev; | 1040 | struct w1_master *dev; |
961 | 1041 | ||
1042 | /* Set netlink removal messages and some cleanup */ | ||
962 | list_for_each_entry(dev, &w1_masters, w1_master_entry) | 1043 | list_for_each_entry(dev, &w1_masters, w1_master_entry) |
963 | __w1_remove_master_device(dev); | 1044 | __w1_remove_master_device(dev); |
964 | 1045 | ||
965 | w1_fini_netlink(); | 1046 | w1_fini_netlink(); |
966 | 1047 | ||
967 | kthread_stop(w1_control_thread); | ||
968 | |||
969 | driver_unregister(&w1_slave_driver); | 1048 | driver_unregister(&w1_slave_driver); |
970 | driver_unregister(&w1_master_driver); | 1049 | driver_unregister(&w1_master_driver); |
971 | bus_unregister(&w1_bus_type); | 1050 | bus_unregister(&w1_bus_type); |