diff options
author | Evgeniy Polyakov <johnpol@2ka.mipt.ru> | 2005-08-11 09:27:50 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2005-09-08 17:41:26 -0400 |
commit | d2a4ef6a0ce4d841293b49bf2cdc17a0ebfaaf9d (patch) | |
tree | 2d49373e06fd65aae5217aad864fafb849c8cda2 | |
parent | ea7d8f65c865ebfa1d7cd67c360a87333ff013c1 (diff) |
[PATCH] w1: Added add/remove slave callbacks.
Patch is based on work from Ben Gardner <bgardner@wabtec.com>
Signed-off-by: Evgeniy Polyakov <johnpol@2ka.mipt.ru>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/w1/w1.c | 121 | ||||
-rw-r--r-- | drivers/w1/w1.h | 3 | ||||
-rw-r--r-- | drivers/w1/w1_family.c | 11 | ||||
-rw-r--r-- | drivers/w1/w1_family.h | 6 | ||||
-rw-r--r-- | drivers/w1/w1_smem.c | 47 | ||||
-rw-r--r-- | drivers/w1/w1_therm.c | 32 |
6 files changed, 94 insertions, 126 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)) |
diff --git a/drivers/w1/w1.h b/drivers/w1/w1.h index f8308266d8d6..13edc82bc7de 100644 --- a/drivers/w1/w1.h +++ b/drivers/w1/w1.h | |||
@@ -77,9 +77,6 @@ struct w1_slave | |||
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 dev_released; |
80 | |||
81 | struct bin_attribute attr_bin; | ||
82 | struct device_attribute attr_name; | ||
83 | }; | 80 | }; |
84 | 81 | ||
85 | typedef void (* w1_slave_found_callback)(unsigned long, u64); | 82 | typedef void (* w1_slave_found_callback)(unsigned long, u64); |
diff --git a/drivers/w1/w1_family.c b/drivers/w1/w1_family.c index 02eee57d3c0c..88c517a4c178 100644 --- a/drivers/w1/w1_family.c +++ b/drivers/w1/w1_family.c | |||
@@ -29,23 +29,12 @@ DEFINE_SPINLOCK(w1_flock); | |||
29 | static LIST_HEAD(w1_families); | 29 | static LIST_HEAD(w1_families); |
30 | extern void w1_reconnect_slaves(struct w1_family *f); | 30 | extern void w1_reconnect_slaves(struct w1_family *f); |
31 | 31 | ||
32 | static int w1_check_family(struct w1_family *f) | ||
33 | { | ||
34 | if (!f->fops->rname || !f->fops->rbin) | ||
35 | return -EINVAL; | ||
36 | |||
37 | return 0; | ||
38 | } | ||
39 | |||
40 | int w1_register_family(struct w1_family *newf) | 32 | int w1_register_family(struct w1_family *newf) |
41 | { | 33 | { |
42 | struct list_head *ent, *n; | 34 | struct list_head *ent, *n; |
43 | struct w1_family *f; | 35 | struct w1_family *f; |
44 | int ret = 0; | 36 | int ret = 0; |
45 | 37 | ||
46 | if (w1_check_family(newf)) | ||
47 | return -EINVAL; | ||
48 | |||
49 | spin_lock(&w1_flock); | 38 | spin_lock(&w1_flock); |
50 | list_for_each_safe(ent, n, &w1_families) { | 39 | list_for_each_safe(ent, n, &w1_families) { |
51 | f = list_entry(ent, struct w1_family, family_entry); | 40 | f = list_entry(ent, struct w1_family, family_entry); |
diff --git a/drivers/w1/w1_family.h b/drivers/w1/w1_family.h index b26da01bbc38..0a564a0a69a0 100644 --- a/drivers/w1/w1_family.h +++ b/drivers/w1/w1_family.h | |||
@@ -35,10 +35,12 @@ | |||
35 | 35 | ||
36 | #define MAXNAMELEN 32 | 36 | #define MAXNAMELEN 32 |
37 | 37 | ||
38 | struct w1_slave; | ||
39 | |||
38 | struct w1_family_ops | 40 | struct w1_family_ops |
39 | { | 41 | { |
40 | ssize_t (* rname)(struct device *, struct device_attribute *, char *); | 42 | int (* add_slave)(struct w1_slave *); |
41 | ssize_t (* rbin)(struct kobject *, char *, loff_t, size_t); | 43 | void (* remove_slave)(struct w1_slave *); |
42 | }; | 44 | }; |
43 | 45 | ||
44 | struct w1_family | 46 | struct w1_family |
diff --git a/drivers/w1/w1_smem.c b/drivers/w1/w1_smem.c index 2b6580c7e953..e3209d0aca9b 100644 --- a/drivers/w1/w1_smem.c +++ b/drivers/w1/w1_smem.c | |||
@@ -36,59 +36,12 @@ MODULE_LICENSE("GPL"); | |||
36 | MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>"); | 36 | MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>"); |
37 | MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol, 64bit memory family."); | 37 | MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol, 64bit memory family."); |
38 | 38 | ||
39 | static ssize_t w1_smem_read_name(struct device *, struct device_attribute *attr, char *); | ||
40 | static ssize_t w1_smem_read_bin(struct kobject *, char *, loff_t, size_t); | ||
41 | |||
42 | static struct w1_family_ops w1_smem_fops = { | ||
43 | .rname = &w1_smem_read_name, | ||
44 | .rbin = &w1_smem_read_bin, | ||
45 | }; | ||
46 | |||
47 | static ssize_t w1_smem_read_name(struct device *dev, struct device_attribute *attr, char *buf) | ||
48 | { | ||
49 | struct w1_slave *sl = dev_to_w1_slave(dev); | ||
50 | return sprintf(buf, "%s\n", sl->name); | ||
51 | } | ||
52 | |||
53 | static ssize_t w1_smem_read_bin(struct kobject *kobj, char *buf, loff_t off, size_t count) | ||
54 | { | ||
55 | struct w1_slave *sl = kobj_to_w1_slave(kobj); | ||
56 | int i; | ||
57 | |||
58 | atomic_inc(&sl->refcnt); | ||
59 | if (down_interruptible(&sl->master->mutex)) { | ||
60 | count = 0; | ||
61 | goto out_dec; | ||
62 | } | ||
63 | |||
64 | if (off > W1_SLAVE_DATA_SIZE) { | ||
65 | count = 0; | ||
66 | goto out; | ||
67 | } | ||
68 | if (off + count > W1_SLAVE_DATA_SIZE) { | ||
69 | count = 0; | ||
70 | goto out; | ||
71 | } | ||
72 | for (i = 0; i < 8; ++i) | ||
73 | count += sprintf(buf + count, "%02x ", ((u8 *)&sl->reg_num)[i]); | ||
74 | count += sprintf(buf + count, "\n"); | ||
75 | |||
76 | out: | ||
77 | up(&sl->master->mutex); | ||
78 | out_dec: | ||
79 | atomic_dec(&sl->refcnt); | ||
80 | |||
81 | return count; | ||
82 | } | ||
83 | |||
84 | static struct w1_family w1_smem_family_01 = { | 39 | static struct w1_family w1_smem_family_01 = { |
85 | .fid = W1_FAMILY_SMEM_01, | 40 | .fid = W1_FAMILY_SMEM_01, |
86 | .fops = &w1_smem_fops, | ||
87 | }; | 41 | }; |
88 | 42 | ||
89 | static struct w1_family w1_smem_family_81 = { | 43 | static struct w1_family w1_smem_family_81 = { |
90 | .fid = W1_FAMILY_SMEM_81, | 44 | .fid = W1_FAMILY_SMEM_81, |
91 | .fops = &w1_smem_fops, | ||
92 | }; | 45 | }; |
93 | 46 | ||
94 | static int __init w1_smem_init(void) | 47 | static int __init w1_smem_init(void) |
diff --git a/drivers/w1/w1_therm.c b/drivers/w1/w1_therm.c index 2ed0e0f48268..4577df3cfc48 100644 --- a/drivers/w1/w1_therm.c +++ b/drivers/w1/w1_therm.c | |||
@@ -42,12 +42,31 @@ static u8 bad_roms[][9] = { | |||
42 | {} | 42 | {} |
43 | }; | 43 | }; |
44 | 44 | ||
45 | static ssize_t w1_therm_read_name(struct device *, struct device_attribute *attr, char *); | ||
46 | static ssize_t w1_therm_read_bin(struct kobject *, char *, loff_t, size_t); | 45 | static ssize_t w1_therm_read_bin(struct kobject *, char *, loff_t, size_t); |
47 | 46 | ||
47 | static struct bin_attribute w1_therm_bin_attr = { | ||
48 | .attr = { | ||
49 | .name = "w1_slave", | ||
50 | .mode = S_IRUGO, | ||
51 | .owner = THIS_MODULE, | ||
52 | }, | ||
53 | .size = W1_SLAVE_DATA_SIZE, | ||
54 | .read = w1_therm_read_bin, | ||
55 | }; | ||
56 | |||
57 | static int w1_therm_add_slave(struct w1_slave *sl) | ||
58 | { | ||
59 | return sysfs_create_bin_file(&sl->dev.kobj, &w1_therm_bin_attr); | ||
60 | } | ||
61 | |||
62 | static void w1_therm_remove_slave(struct w1_slave *sl) | ||
63 | { | ||
64 | sysfs_remove_bin_file(&sl->dev.kobj, &w1_therm_bin_attr); | ||
65 | } | ||
66 | |||
48 | static struct w1_family_ops w1_therm_fops = { | 67 | static struct w1_family_ops w1_therm_fops = { |
49 | .rname = &w1_therm_read_name, | 68 | .add_slave = w1_therm_add_slave, |
50 | .rbin = &w1_therm_read_bin, | 69 | .remove_slave = w1_therm_remove_slave, |
51 | }; | 70 | }; |
52 | 71 | ||
53 | static struct w1_family w1_therm_family_DS18S20 = { | 72 | static struct w1_family w1_therm_family_DS18S20 = { |
@@ -59,6 +78,7 @@ static struct w1_family w1_therm_family_DS18B20 = { | |||
59 | .fid = W1_THERM_DS18B20, | 78 | .fid = W1_THERM_DS18B20, |
60 | .fops = &w1_therm_fops, | 79 | .fops = &w1_therm_fops, |
61 | }; | 80 | }; |
81 | |||
62 | static struct w1_family w1_therm_family_DS1822 = { | 82 | static struct w1_family w1_therm_family_DS1822 = { |
63 | .fid = W1_THERM_DS1822, | 83 | .fid = W1_THERM_DS1822, |
64 | .fops = &w1_therm_fops, | 84 | .fops = &w1_therm_fops, |
@@ -90,12 +110,6 @@ static struct w1_therm_family_converter w1_therm_families[] = { | |||
90 | }, | 110 | }, |
91 | }; | 111 | }; |
92 | 112 | ||
93 | static ssize_t w1_therm_read_name(struct device *dev, struct device_attribute *attr, char *buf) | ||
94 | { | ||
95 | struct w1_slave *sl = dev_to_w1_slave(dev); | ||
96 | return sprintf(buf, "%s\n", sl->name); | ||
97 | } | ||
98 | |||
99 | static inline int w1_DS18B20_convert_temp(u8 rom[9]) | 113 | static inline int w1_DS18B20_convert_temp(u8 rom[9]) |
100 | { | 114 | { |
101 | int t = (rom[1] << 8) | rom[0]; | 115 | int t = (rom[1] << 8) | rom[0]; |