diff options
Diffstat (limited to 'drivers/w1/w1.c')
-rw-r--r-- | drivers/w1/w1.c | 121 |
1 files changed, 67 insertions, 54 deletions
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index 39888af6d33d..e592ca2edd49 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c | |||
@@ -59,19 +59,6 @@ static pid_t control_thread; | |||
59 | static int control_needs_exit; | 59 | static int control_needs_exit; |
60 | static DECLARE_COMPLETION(w1_control_complete); | 60 | static DECLARE_COMPLETION(w1_control_complete); |
61 | 61 | ||
62 | /* stuff for the default family */ | ||
63 | static ssize_t w1_famdefault_read_name(struct device *dev, struct device_attribute *attr, char *buf) | ||
64 | { | ||
65 | struct w1_slave *sl = container_of(dev, struct w1_slave, dev); | ||
66 | return(sprintf(buf, "%s\n", sl->name)); | ||
67 | } | ||
68 | static struct w1_family_ops w1_default_fops = { | ||
69 | .rname = &w1_famdefault_read_name, | ||
70 | }; | ||
71 | static struct w1_family w1_default_family = { | ||
72 | .fops = &w1_default_fops, | ||
73 | }; | ||
74 | |||
75 | static int w1_master_match(struct device *dev, struct device_driver *drv) | 62 | static int w1_master_match(struct device *dev, struct device_driver *drv) |
76 | { | 63 | { |
77 | return 1; | 64 | return 1; |
@@ -99,30 +86,47 @@ static void w1_slave_release(struct device *dev) | |||
99 | complete(&sl->dev_released); | 86 | complete(&sl->dev_released); |
100 | } | 87 | } |
101 | 88 | ||
102 | static ssize_t w1_default_read_name(struct device *dev, struct device_attribute *attr, char *buf) | 89 | static ssize_t w1_slave_read_name(struct device *dev, struct device_attribute *attr, char *buf) |
103 | { | 90 | { |
104 | return sprintf(buf, "No family registered.\n"); | 91 | struct w1_slave *sl = dev_to_w1_slave(dev); |
92 | |||
93 | return sprintf(buf, "%s\n", sl->name); | ||
105 | } | 94 | } |
106 | 95 | ||
107 | static ssize_t w1_default_read_bin(struct kobject *kobj, char *buf, loff_t off, | 96 | static ssize_t w1_slave_read_id(struct kobject *kobj, char *buf, loff_t off, size_t count) |
108 | size_t count) | ||
109 | { | 97 | { |
110 | return sprintf(buf, "No family registered.\n"); | 98 | struct w1_slave *sl = kobj_to_w1_slave(kobj); |
111 | } | ||
112 | 99 | ||
113 | static struct device_attribute w1_slave_attribute = | 100 | atomic_inc(&sl->refcnt); |
114 | __ATTR(name, S_IRUGO, w1_default_read_name, NULL); | 101 | if (off > 8) { |
115 | 102 | count = 0; | |
116 | static struct bin_attribute w1_slave_bin_attribute = { | 103 | } else { |
117 | .attr = { | 104 | if (off + count > 8) |
118 | .name = "w1_slave", | 105 | count = 8 - off; |
119 | .mode = S_IRUGO, | 106 | |
120 | .owner = THIS_MODULE, | 107 | memcpy(buf, (u8 *)&sl->reg_num, count); |
121 | }, | 108 | } |
122 | .size = W1_SLAVE_DATA_SIZE, | 109 | atomic_dec(&sl->refcnt); |
123 | .read = &w1_default_read_bin, | 110 | |
111 | return count; | ||
112 | } | ||
113 | |||
114 | static struct device_attribute w1_slave_attr_name = | ||
115 | __ATTR(name, S_IRUGO, w1_slave_read_name, NULL); | ||
116 | |||
117 | static struct bin_attribute w1_slave_attr_bin_id = { | ||
118 | .attr = { | ||
119 | .name = "id", | ||
120 | .mode = S_IRUGO, | ||
121 | .owner = THIS_MODULE, | ||
122 | }, | ||
123 | .size = 8, | ||
124 | .read = w1_slave_read_id, | ||
124 | }; | 125 | }; |
125 | 126 | ||
127 | /* Default family */ | ||
128 | static struct w1_family w1_default_family; | ||
129 | |||
126 | static int w1_hotplug(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size); | 130 | static int w1_hotplug(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size); |
127 | 131 | ||
128 | static struct bus_type w1_bus_type = { | 132 | static struct bus_type w1_bus_type = { |
@@ -413,36 +417,44 @@ static int __w1_attach_slave_device(struct w1_slave *sl) | |||
413 | return err; | 417 | return err; |
414 | } | 418 | } |
415 | 419 | ||
416 | memcpy(&sl->attr_bin, &w1_slave_bin_attribute, sizeof(sl->attr_bin)); | 420 | /* Create "name" entry */ |
417 | memcpy(&sl->attr_name, &w1_slave_attribute, sizeof(sl->attr_name)); | 421 | err = device_create_file(&sl->dev, &w1_slave_attr_name); |
418 | 422 | if (err < 0) { | |
419 | sl->attr_bin.read = sl->family->fops->rbin; | 423 | dev_err(&sl->dev, |
420 | sl->attr_name.show = sl->family->fops->rname; | 424 | "sysfs file creation for [%s] failed. err=%d\n", |
425 | sl->dev.bus_id, err); | ||
426 | goto out_unreg; | ||
427 | } | ||
421 | 428 | ||
422 | err = device_create_file(&sl->dev, &sl->attr_name); | 429 | /* Create "id" entry */ |
430 | err = sysfs_create_bin_file(&sl->dev.kobj, &w1_slave_attr_bin_id); | ||
423 | if (err < 0) { | 431 | if (err < 0) { |
424 | dev_err(&sl->dev, | 432 | dev_err(&sl->dev, |
425 | "sysfs file creation for [%s] failed. err=%d\n", | 433 | "sysfs file creation for [%s] failed. err=%d\n", |
426 | sl->dev.bus_id, err); | 434 | sl->dev.bus_id, err); |
427 | device_unregister(&sl->dev); | 435 | goto out_rem1; |
428 | return err; | ||
429 | } | 436 | } |
430 | 437 | ||
431 | if ( sl->attr_bin.read ) { | 438 | /* if the family driver needs to initialize something... */ |
432 | err = sysfs_create_bin_file(&sl->dev.kobj, &sl->attr_bin); | 439 | if (sl->family->fops && sl->family->fops->add_slave && |
433 | if (err < 0) { | 440 | ((err = sl->family->fops->add_slave(sl)) < 0)) { |
434 | dev_err(&sl->dev, | 441 | dev_err(&sl->dev, |
435 | "sysfs file creation for [%s] failed. err=%d\n", | 442 | "sysfs file creation for [%s] failed. err=%d\n", |
436 | sl->dev.bus_id, err); | 443 | sl->dev.bus_id, err); |
437 | device_remove_file(&sl->dev, &sl->attr_name); | 444 | goto out_rem2; |
438 | device_unregister(&sl->dev); | ||
439 | return err; | ||
440 | } | ||
441 | } | 445 | } |
442 | 446 | ||
443 | list_add_tail(&sl->w1_slave_entry, &sl->master->slist); | 447 | list_add_tail(&sl->w1_slave_entry, &sl->master->slist); |
444 | 448 | ||
445 | return 0; | 449 | return 0; |
450 | |||
451 | out_rem2: | ||
452 | sysfs_remove_bin_file(&sl->dev.kobj, &w1_slave_attr_bin_id); | ||
453 | out_rem1: | ||
454 | device_remove_file(&sl->dev, &w1_slave_attr_name); | ||
455 | out_unreg: | ||
456 | device_unregister(&sl->dev); | ||
457 | return err; | ||
446 | } | 458 | } |
447 | 459 | ||
448 | static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn) | 460 | static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn) |
@@ -517,10 +529,11 @@ static void w1_slave_detach(struct w1_slave *sl) | |||
517 | flush_signals(current); | 529 | flush_signals(current); |
518 | } | 530 | } |
519 | 531 | ||
520 | if ( sl->attr_bin.read ) { | 532 | if (sl->family->fops && sl->family->fops->remove_slave) |
521 | sysfs_remove_bin_file (&sl->dev.kobj, &sl->attr_bin); | 533 | sl->family->fops->remove_slave(sl); |
522 | } | 534 | |
523 | device_remove_file(&sl->dev, &sl->attr_name); | 535 | sysfs_remove_bin_file(&sl->dev.kobj, &w1_slave_attr_bin_id); |
536 | device_remove_file(&sl->dev, &w1_slave_attr_name); | ||
524 | device_unregister(&sl->dev); | 537 | device_unregister(&sl->dev); |
525 | w1_family_put(sl->family); | 538 | w1_family_put(sl->family); |
526 | 539 | ||
@@ -805,8 +818,8 @@ int w1_process(void *data) | |||
805 | if (!test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags) && !--sl->ttl) { | 818 | if (!test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags) && !--sl->ttl) { |
806 | list_del (&sl->w1_slave_entry); | 819 | list_del (&sl->w1_slave_entry); |
807 | 820 | ||
808 | w1_slave_detach (sl); | 821 | w1_slave_detach(sl); |
809 | kfree (sl); | 822 | kfree(sl); |
810 | 823 | ||
811 | dev->slave_count--; | 824 | dev->slave_count--; |
812 | } else if (test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags)) | 825 | } else if (test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags)) |