diff options
Diffstat (limited to 'drivers/w1/slaves/w1_ds2780.c')
-rw-r--r-- | drivers/w1/slaves/w1_ds2780.c | 96 |
1 files changed, 41 insertions, 55 deletions
diff --git a/drivers/w1/slaves/w1_ds2780.c b/drivers/w1/slaves/w1_ds2780.c index 274c8f38303f..39f78c0b143c 100644 --- a/drivers/w1/slaves/w1_ds2780.c +++ b/drivers/w1/slaves/w1_ds2780.c | |||
@@ -26,20 +26,14 @@ | |||
26 | #include "../w1_family.h" | 26 | #include "../w1_family.h" |
27 | #include "w1_ds2780.h" | 27 | #include "w1_ds2780.h" |
28 | 28 | ||
29 | int w1_ds2780_io(struct device *dev, char *buf, int addr, size_t count, | 29 | static int w1_ds2780_do_io(struct device *dev, char *buf, int addr, |
30 | int io) | 30 | size_t count, int io) |
31 | { | 31 | { |
32 | struct w1_slave *sl = container_of(dev, struct w1_slave, dev); | 32 | struct w1_slave *sl = container_of(dev, struct w1_slave, dev); |
33 | 33 | ||
34 | if (!dev) | 34 | if (addr > DS2780_DATA_SIZE || addr < 0) |
35 | return -ENODEV; | 35 | return 0; |
36 | 36 | ||
37 | mutex_lock(&sl->master->mutex); | ||
38 | |||
39 | if (addr > DS2780_DATA_SIZE || addr < 0) { | ||
40 | count = 0; | ||
41 | goto out; | ||
42 | } | ||
43 | count = min_t(int, count, DS2780_DATA_SIZE - addr); | 37 | count = min_t(int, count, DS2780_DATA_SIZE - addr); |
44 | 38 | ||
45 | if (w1_reset_select_slave(sl) == 0) { | 39 | if (w1_reset_select_slave(sl) == 0) { |
@@ -47,7 +41,6 @@ int w1_ds2780_io(struct device *dev, char *buf, int addr, size_t count, | |||
47 | w1_write_8(sl->master, W1_DS2780_WRITE_DATA); | 41 | w1_write_8(sl->master, W1_DS2780_WRITE_DATA); |
48 | w1_write_8(sl->master, addr); | 42 | w1_write_8(sl->master, addr); |
49 | w1_write_block(sl->master, buf, count); | 43 | w1_write_block(sl->master, buf, count); |
50 | /* XXX w1_write_block returns void, not n_written */ | ||
51 | } else { | 44 | } else { |
52 | w1_write_8(sl->master, W1_DS2780_READ_DATA); | 45 | w1_write_8(sl->master, W1_DS2780_READ_DATA); |
53 | w1_write_8(sl->master, addr); | 46 | w1_write_8(sl->master, addr); |
@@ -55,13 +48,42 @@ int w1_ds2780_io(struct device *dev, char *buf, int addr, size_t count, | |||
55 | } | 48 | } |
56 | } | 49 | } |
57 | 50 | ||
58 | out: | 51 | return count; |
52 | } | ||
53 | |||
54 | int w1_ds2780_io(struct device *dev, char *buf, int addr, size_t count, | ||
55 | int io) | ||
56 | { | ||
57 | struct w1_slave *sl = container_of(dev, struct w1_slave, dev); | ||
58 | int ret; | ||
59 | |||
60 | if (!dev) | ||
61 | return -ENODEV; | ||
62 | |||
63 | mutex_lock(&sl->master->mutex); | ||
64 | |||
65 | ret = w1_ds2780_do_io(dev, buf, addr, count, io); | ||
66 | |||
59 | mutex_unlock(&sl->master->mutex); | 67 | mutex_unlock(&sl->master->mutex); |
60 | 68 | ||
61 | return count; | 69 | return ret; |
62 | } | 70 | } |
63 | EXPORT_SYMBOL(w1_ds2780_io); | 71 | EXPORT_SYMBOL(w1_ds2780_io); |
64 | 72 | ||
73 | int w1_ds2780_io_nolock(struct device *dev, char *buf, int addr, size_t count, | ||
74 | int io) | ||
75 | { | ||
76 | int ret; | ||
77 | |||
78 | if (!dev) | ||
79 | return -ENODEV; | ||
80 | |||
81 | ret = w1_ds2780_do_io(dev, buf, addr, count, io); | ||
82 | |||
83 | return ret; | ||
84 | } | ||
85 | EXPORT_SYMBOL(w1_ds2780_io_nolock); | ||
86 | |||
65 | int w1_ds2780_eeprom_cmd(struct device *dev, int addr, int cmd) | 87 | int w1_ds2780_eeprom_cmd(struct device *dev, int addr, int cmd) |
66 | { | 88 | { |
67 | struct w1_slave *sl = container_of(dev, struct w1_slave, dev); | 89 | struct w1_slave *sl = container_of(dev, struct w1_slave, dev); |
@@ -99,43 +121,7 @@ static struct bin_attribute w1_ds2780_bin_attr = { | |||
99 | .read = w1_ds2780_read_bin, | 121 | .read = w1_ds2780_read_bin, |
100 | }; | 122 | }; |
101 | 123 | ||
102 | static DEFINE_IDR(bat_idr); | 124 | static DEFINE_IDA(bat_ida); |
103 | static DEFINE_MUTEX(bat_idr_lock); | ||
104 | |||
105 | static int new_bat_id(void) | ||
106 | { | ||
107 | int ret; | ||
108 | |||
109 | while (1) { | ||
110 | int id; | ||
111 | |||
112 | ret = idr_pre_get(&bat_idr, GFP_KERNEL); | ||
113 | if (ret == 0) | ||
114 | return -ENOMEM; | ||
115 | |||
116 | mutex_lock(&bat_idr_lock); | ||
117 | ret = idr_get_new(&bat_idr, NULL, &id); | ||
118 | mutex_unlock(&bat_idr_lock); | ||
119 | |||
120 | if (ret == 0) { | ||
121 | ret = id & MAX_ID_MASK; | ||
122 | break; | ||
123 | } else if (ret == -EAGAIN) { | ||
124 | continue; | ||
125 | } else { | ||
126 | break; | ||
127 | } | ||
128 | } | ||
129 | |||
130 | return ret; | ||
131 | } | ||
132 | |||
133 | static void release_bat_id(int id) | ||
134 | { | ||
135 | mutex_lock(&bat_idr_lock); | ||
136 | idr_remove(&bat_idr, id); | ||
137 | mutex_unlock(&bat_idr_lock); | ||
138 | } | ||
139 | 125 | ||
140 | static int w1_ds2780_add_slave(struct w1_slave *sl) | 126 | static int w1_ds2780_add_slave(struct w1_slave *sl) |
141 | { | 127 | { |
@@ -143,7 +129,7 @@ static int w1_ds2780_add_slave(struct w1_slave *sl) | |||
143 | int id; | 129 | int id; |
144 | struct platform_device *pdev; | 130 | struct platform_device *pdev; |
145 | 131 | ||
146 | id = new_bat_id(); | 132 | id = ida_simple_get(&bat_ida, 0, 0, GFP_KERNEL); |
147 | if (id < 0) { | 133 | if (id < 0) { |
148 | ret = id; | 134 | ret = id; |
149 | goto noid; | 135 | goto noid; |
@@ -172,7 +158,7 @@ bin_attr_failed: | |||
172 | pdev_add_failed: | 158 | pdev_add_failed: |
173 | platform_device_unregister(pdev); | 159 | platform_device_unregister(pdev); |
174 | pdev_alloc_failed: | 160 | pdev_alloc_failed: |
175 | release_bat_id(id); | 161 | ida_simple_remove(&bat_ida, id); |
176 | noid: | 162 | noid: |
177 | return ret; | 163 | return ret; |
178 | } | 164 | } |
@@ -183,7 +169,7 @@ static void w1_ds2780_remove_slave(struct w1_slave *sl) | |||
183 | int id = pdev->id; | 169 | int id = pdev->id; |
184 | 170 | ||
185 | platform_device_unregister(pdev); | 171 | platform_device_unregister(pdev); |
186 | release_bat_id(id); | 172 | ida_simple_remove(&bat_ida, id); |
187 | sysfs_remove_bin_file(&sl->dev.kobj, &w1_ds2780_bin_attr); | 173 | sysfs_remove_bin_file(&sl->dev.kobj, &w1_ds2780_bin_attr); |
188 | } | 174 | } |
189 | 175 | ||
@@ -199,14 +185,14 @@ static struct w1_family w1_ds2780_family = { | |||
199 | 185 | ||
200 | static int __init w1_ds2780_init(void) | 186 | static int __init w1_ds2780_init(void) |
201 | { | 187 | { |
202 | idr_init(&bat_idr); | 188 | ida_init(&bat_ida); |
203 | return w1_register_family(&w1_ds2780_family); | 189 | return w1_register_family(&w1_ds2780_family); |
204 | } | 190 | } |
205 | 191 | ||
206 | static void __exit w1_ds2780_exit(void) | 192 | static void __exit w1_ds2780_exit(void) |
207 | { | 193 | { |
208 | w1_unregister_family(&w1_ds2780_family); | 194 | w1_unregister_family(&w1_ds2780_family); |
209 | idr_destroy(&bat_idr); | 195 | ida_destroy(&bat_ida); |
210 | } | 196 | } |
211 | 197 | ||
212 | module_init(w1_ds2780_init); | 198 | module_init(w1_ds2780_init); |