diff options
-rw-r--r-- | drivers/i2c/chips/eeprom.c | 8 | ||||
-rw-r--r-- | drivers/i2c/chips/max6875.c | 25 | ||||
-rw-r--r-- | drivers/i2c/chips/pca9539.c | 11 | ||||
-rw-r--r-- | drivers/i2c/chips/pcf8574.c | 22 | ||||
-rw-r--r-- | drivers/i2c/chips/pcf8591.c | 58 |
5 files changed, 97 insertions, 27 deletions
diff --git a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c index 13c108269a6d..cec3a0c3894d 100644 --- a/drivers/i2c/chips/eeprom.c +++ b/drivers/i2c/chips/eeprom.c | |||
@@ -209,10 +209,14 @@ static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind) | |||
209 | } | 209 | } |
210 | 210 | ||
211 | /* create the sysfs eeprom file */ | 211 | /* create the sysfs eeprom file */ |
212 | sysfs_create_bin_file(&new_client->dev.kobj, &eeprom_attr); | 212 | err = sysfs_create_bin_file(&new_client->dev.kobj, &eeprom_attr); |
213 | if (err) | ||
214 | goto exit_detach; | ||
213 | 215 | ||
214 | return 0; | 216 | return 0; |
215 | 217 | ||
218 | exit_detach: | ||
219 | i2c_detach_client(new_client); | ||
216 | exit_kfree: | 220 | exit_kfree: |
217 | kfree(data); | 221 | kfree(data); |
218 | exit: | 222 | exit: |
@@ -223,6 +227,8 @@ static int eeprom_detach_client(struct i2c_client *client) | |||
223 | { | 227 | { |
224 | int err; | 228 | int err; |
225 | 229 | ||
230 | sysfs_remove_bin_file(&client->dev.kobj, &eeprom_attr); | ||
231 | |||
226 | err = i2c_detach_client(client); | 232 | err = i2c_detach_client(client); |
227 | if (err) | 233 | if (err) |
228 | return err; | 234 | return err; |
diff --git a/drivers/i2c/chips/max6875.c b/drivers/i2c/chips/max6875.c index 88d2ddee4490..76645c142977 100644 --- a/drivers/i2c/chips/max6875.c +++ b/drivers/i2c/chips/max6875.c | |||
@@ -199,8 +199,7 @@ static int max6875_detect(struct i2c_adapter *adapter, int address, int kind) | |||
199 | mutex_init(&data->update_lock); | 199 | mutex_init(&data->update_lock); |
200 | 200 | ||
201 | /* Init fake client data */ | 201 | /* Init fake client data */ |
202 | /* set the client data to the i2c_client so that it will get freed */ | 202 | i2c_set_clientdata(fake_client, NULL); |
203 | i2c_set_clientdata(fake_client, fake_client); | ||
204 | fake_client->addr = address | 1; | 203 | fake_client->addr = address | 1; |
205 | fake_client->adapter = adapter; | 204 | fake_client->adapter = adapter; |
206 | fake_client->driver = &max6875_driver; | 205 | fake_client->driver = &max6875_driver; |
@@ -214,13 +213,17 @@ static int max6875_detect(struct i2c_adapter *adapter, int address, int kind) | |||
214 | goto exit_kfree2; | 213 | goto exit_kfree2; |
215 | 214 | ||
216 | if ((err = i2c_attach_client(fake_client)) != 0) | 215 | if ((err = i2c_attach_client(fake_client)) != 0) |
217 | goto exit_detach; | 216 | goto exit_detach1; |
218 | 217 | ||
219 | sysfs_create_bin_file(&real_client->dev.kobj, &user_eeprom_attr); | 218 | err = sysfs_create_bin_file(&real_client->dev.kobj, &user_eeprom_attr); |
219 | if (err) | ||
220 | goto exit_detach2; | ||
220 | 221 | ||
221 | return 0; | 222 | return 0; |
222 | 223 | ||
223 | exit_detach: | 224 | exit_detach2: |
225 | i2c_detach_client(fake_client); | ||
226 | exit_detach1: | ||
224 | i2c_detach_client(real_client); | 227 | i2c_detach_client(real_client); |
225 | exit_kfree2: | 228 | exit_kfree2: |
226 | kfree(fake_client); | 229 | kfree(fake_client); |
@@ -229,14 +232,24 @@ exit_kfree1: | |||
229 | return err; | 232 | return err; |
230 | } | 233 | } |
231 | 234 | ||
235 | /* Will be called for both the real client and the fake client */ | ||
232 | static int max6875_detach_client(struct i2c_client *client) | 236 | static int max6875_detach_client(struct i2c_client *client) |
233 | { | 237 | { |
234 | int err; | 238 | int err; |
239 | struct max6875_data *data = i2c_get_clientdata(client); | ||
240 | |||
241 | /* data is NULL for the fake client */ | ||
242 | if (data) | ||
243 | sysfs_remove_bin_file(&client->dev.kobj, &user_eeprom_attr); | ||
235 | 244 | ||
236 | err = i2c_detach_client(client); | 245 | err = i2c_detach_client(client); |
237 | if (err) | 246 | if (err) |
238 | return err; | 247 | return err; |
239 | kfree(i2c_get_clientdata(client)); | 248 | |
249 | if (data) /* real client */ | ||
250 | kfree(data); | ||
251 | else /* fake client */ | ||
252 | kfree(client); | ||
240 | return 0; | 253 | return 0; |
241 | } | 254 | } |
242 | 255 | ||
diff --git a/drivers/i2c/chips/pca9539.c b/drivers/i2c/chips/pca9539.c index cb22280cdd27..f43c4e79b55e 100644 --- a/drivers/i2c/chips/pca9539.c +++ b/drivers/i2c/chips/pca9539.c | |||
@@ -148,11 +148,16 @@ static int pca9539_detect(struct i2c_adapter *adapter, int address, int kind) | |||
148 | if ((err = i2c_attach_client(new_client))) | 148 | if ((err = i2c_attach_client(new_client))) |
149 | goto exit_kfree; | 149 | goto exit_kfree; |
150 | 150 | ||
151 | /* Register sysfs hooks (don't care about failure) */ | 151 | /* Register sysfs hooks */ |
152 | sysfs_create_group(&new_client->dev.kobj, &pca9539_defattr_group); | 152 | err = sysfs_create_group(&new_client->dev.kobj, |
153 | &pca9539_defattr_group); | ||
154 | if (err) | ||
155 | goto exit_detach; | ||
153 | 156 | ||
154 | return 0; | 157 | return 0; |
155 | 158 | ||
159 | exit_detach: | ||
160 | i2c_detach_client(new_client); | ||
156 | exit_kfree: | 161 | exit_kfree: |
157 | kfree(data); | 162 | kfree(data); |
158 | exit: | 163 | exit: |
@@ -163,6 +168,8 @@ static int pca9539_detach_client(struct i2c_client *client) | |||
163 | { | 168 | { |
164 | int err; | 169 | int err; |
165 | 170 | ||
171 | sysfs_remove_group(&client->dev.kobj, &pca9539_defattr_group); | ||
172 | |||
166 | if ((err = i2c_detach_client(client))) | 173 | if ((err = i2c_detach_client(client))) |
167 | return err; | 174 | return err; |
168 | 175 | ||
diff --git a/drivers/i2c/chips/pcf8574.c b/drivers/i2c/chips/pcf8574.c index c3e6449c4481..32b25427eaba 100644 --- a/drivers/i2c/chips/pcf8574.c +++ b/drivers/i2c/chips/pcf8574.c | |||
@@ -105,6 +105,16 @@ static ssize_t set_write(struct device *dev, struct device_attribute *attr, cons | |||
105 | 105 | ||
106 | static DEVICE_ATTR(write, S_IWUSR | S_IRUGO, show_write, set_write); | 106 | static DEVICE_ATTR(write, S_IWUSR | S_IRUGO, show_write, set_write); |
107 | 107 | ||
108 | static struct attribute *pcf8574_attributes[] = { | ||
109 | &dev_attr_read.attr, | ||
110 | &dev_attr_write.attr, | ||
111 | NULL | ||
112 | }; | ||
113 | |||
114 | static const struct attribute_group pcf8574_attr_group = { | ||
115 | .attrs = pcf8574_attributes, | ||
116 | }; | ||
117 | |||
108 | /* | 118 | /* |
109 | * Real code | 119 | * Real code |
110 | */ | 120 | */ |
@@ -166,13 +176,13 @@ static int pcf8574_detect(struct i2c_adapter *adapter, int address, int kind) | |||
166 | pcf8574_init_client(new_client); | 176 | pcf8574_init_client(new_client); |
167 | 177 | ||
168 | /* Register sysfs hooks */ | 178 | /* Register sysfs hooks */ |
169 | device_create_file(&new_client->dev, &dev_attr_read); | 179 | err = sysfs_create_group(&new_client->dev.kobj, &pcf8574_attr_group); |
170 | device_create_file(&new_client->dev, &dev_attr_write); | 180 | if (err) |
181 | goto exit_detach; | ||
171 | return 0; | 182 | return 0; |
172 | 183 | ||
173 | /* OK, this is not exactly good programming practice, usually. But it is | 184 | exit_detach: |
174 | very code-efficient in this case. */ | 185 | i2c_detach_client(new_client); |
175 | |||
176 | exit_free: | 186 | exit_free: |
177 | kfree(data); | 187 | kfree(data); |
178 | exit: | 188 | exit: |
@@ -183,6 +193,8 @@ static int pcf8574_detach_client(struct i2c_client *client) | |||
183 | { | 193 | { |
184 | int err; | 194 | int err; |
185 | 195 | ||
196 | sysfs_remove_group(&client->dev.kobj, &pcf8574_attr_group); | ||
197 | |||
186 | if ((err = i2c_detach_client(client))) | 198 | if ((err = i2c_detach_client(client))) |
187 | return err; | 199 | return err; |
188 | 200 | ||
diff --git a/drivers/i2c/chips/pcf8591.c b/drivers/i2c/chips/pcf8591.c index 925a6b371fd2..4dc36376eb32 100644 --- a/drivers/i2c/chips/pcf8591.c +++ b/drivers/i2c/chips/pcf8591.c | |||
@@ -158,6 +158,28 @@ static ssize_t set_out0_enable(struct device *dev, struct device_attribute *attr | |||
158 | static DEVICE_ATTR(out0_enable, S_IWUSR | S_IRUGO, | 158 | static DEVICE_ATTR(out0_enable, S_IWUSR | S_IRUGO, |
159 | show_out0_enable, set_out0_enable); | 159 | show_out0_enable, set_out0_enable); |
160 | 160 | ||
161 | static struct attribute *pcf8591_attributes[] = { | ||
162 | &dev_attr_out0_enable.attr, | ||
163 | &dev_attr_out0_output.attr, | ||
164 | &dev_attr_in0_input.attr, | ||
165 | &dev_attr_in1_input.attr, | ||
166 | NULL | ||
167 | }; | ||
168 | |||
169 | static const struct attribute_group pcf8591_attr_group = { | ||
170 | .attrs = pcf8591_attributes, | ||
171 | }; | ||
172 | |||
173 | static struct attribute *pcf8591_attributes_opt[] = { | ||
174 | &dev_attr_in2_input.attr, | ||
175 | &dev_attr_in3_input.attr, | ||
176 | NULL | ||
177 | }; | ||
178 | |||
179 | static const struct attribute_group pcf8591_attr_group_opt = { | ||
180 | .attrs = pcf8591_attributes_opt, | ||
181 | }; | ||
182 | |||
161 | /* | 183 | /* |
162 | * Real code | 184 | * Real code |
163 | */ | 185 | */ |
@@ -211,24 +233,31 @@ static int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind) | |||
211 | pcf8591_init_client(new_client); | 233 | pcf8591_init_client(new_client); |
212 | 234 | ||
213 | /* Register sysfs hooks */ | 235 | /* Register sysfs hooks */ |
214 | device_create_file(&new_client->dev, &dev_attr_out0_enable); | 236 | err = sysfs_create_group(&new_client->dev.kobj, &pcf8591_attr_group); |
215 | device_create_file(&new_client->dev, &dev_attr_out0_output); | 237 | if (err) |
216 | device_create_file(&new_client->dev, &dev_attr_in0_input); | 238 | goto exit_detach; |
217 | device_create_file(&new_client->dev, &dev_attr_in1_input); | ||
218 | 239 | ||
219 | /* Register input2 if not in "two differential inputs" mode */ | 240 | /* Register input2 if not in "two differential inputs" mode */ |
220 | if (input_mode != 3 ) | 241 | if (input_mode != 3) { |
221 | device_create_file(&new_client->dev, &dev_attr_in2_input); | 242 | if ((err = device_create_file(&new_client->dev, |
222 | 243 | &dev_attr_in2_input))) | |
244 | goto exit_sysfs_remove; | ||
245 | } | ||
246 | |||
223 | /* Register input3 only in "four single ended inputs" mode */ | 247 | /* Register input3 only in "four single ended inputs" mode */ |
224 | if (input_mode == 0) | 248 | if (input_mode == 0) { |
225 | device_create_file(&new_client->dev, &dev_attr_in3_input); | 249 | if ((err = device_create_file(&new_client->dev, |
226 | 250 | &dev_attr_in3_input))) | |
251 | goto exit_sysfs_remove; | ||
252 | } | ||
253 | |||
227 | return 0; | 254 | return 0; |
228 | |||
229 | /* OK, this is not exactly good programming practice, usually. But it is | ||
230 | very code-efficient in this case. */ | ||
231 | 255 | ||
256 | exit_sysfs_remove: | ||
257 | sysfs_remove_group(&new_client->dev.kobj, &pcf8591_attr_group_opt); | ||
258 | sysfs_remove_group(&new_client->dev.kobj, &pcf8591_attr_group); | ||
259 | exit_detach: | ||
260 | i2c_detach_client(new_client); | ||
232 | exit_kfree: | 261 | exit_kfree: |
233 | kfree(data); | 262 | kfree(data); |
234 | exit: | 263 | exit: |
@@ -239,6 +268,9 @@ static int pcf8591_detach_client(struct i2c_client *client) | |||
239 | { | 268 | { |
240 | int err; | 269 | int err; |
241 | 270 | ||
271 | sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group_opt); | ||
272 | sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group); | ||
273 | |||
242 | if ((err = i2c_detach_client(client))) | 274 | if ((err = i2c_detach_client(client))) |
243 | return err; | 275 | return err; |
244 | 276 | ||