aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJean Delvare <khali@linux-fr.org>2006-09-03 16:20:24 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2006-09-26 18:38:51 -0400
commit7d9db67febf67dd76329a9dd8f97cf4611a8ac2e (patch)
tree6354fa99b17f89c8f26ccf7c440d0d29096f2dc2
parentb32d20dc8b187e03605f091dbde9a78676a2a642 (diff)
i2c: __must_check fixes (chip drivers)
i2c: __must_check fixes (chip drivers) Check for error on sysfs file creation. Delete sysfs files on device removal. The approach taken for the most complex case (pcf8591) is similar to what Mark M. Hoffman proposed for hardware monitoring chip drivers. Signed-off-by: Jean Delvare <khali@linux-fr.org> Cc: Ben Gardner <bgardner@wabtec.com> Cc: Aurelien Jarno <aurelien@aurel32.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/i2c/chips/eeprom.c8
-rw-r--r--drivers/i2c/chips/max6875.c25
-rw-r--r--drivers/i2c/chips/pca9539.c11
-rw-r--r--drivers/i2c/chips/pcf8574.c22
-rw-r--r--drivers/i2c/chips/pcf8591.c58
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
218exit_detach:
219 i2c_detach_client(new_client);
216exit_kfree: 220exit_kfree:
217 kfree(data); 221 kfree(data);
218exit: 222exit:
@@ -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
223exit_detach: 224exit_detach2:
225 i2c_detach_client(fake_client);
226exit_detach1:
224 i2c_detach_client(real_client); 227 i2c_detach_client(real_client);
225exit_kfree2: 228exit_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 */
232static int max6875_detach_client(struct i2c_client *client) 236static 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
159exit_detach:
160 i2c_detach_client(new_client);
156exit_kfree: 161exit_kfree:
157 kfree(data); 162 kfree(data);
158exit: 163exit:
@@ -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
106static DEVICE_ATTR(write, S_IWUSR | S_IRUGO, show_write, set_write); 106static DEVICE_ATTR(write, S_IWUSR | S_IRUGO, show_write, set_write);
107 107
108static struct attribute *pcf8574_attributes[] = {
109 &dev_attr_read.attr,
110 &dev_attr_write.attr,
111 NULL
112};
113
114static 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
158static DEVICE_ATTR(out0_enable, S_IWUSR | S_IRUGO, 158static DEVICE_ATTR(out0_enable, S_IWUSR | S_IRUGO,
159 show_out0_enable, set_out0_enable); 159 show_out0_enable, set_out0_enable);
160 160
161static 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
169static const struct attribute_group pcf8591_attr_group = {
170 .attrs = pcf8591_attributes,
171};
172
173static struct attribute *pcf8591_attributes_opt[] = {
174 &dev_attr_in2_input.attr,
175 &dev_attr_in3_input.attr,
176 NULL
177};
178
179static 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
256exit_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);
259exit_detach:
260 i2c_detach_client(new_client);
232exit_kfree: 261exit_kfree:
233 kfree(data); 262 kfree(data);
234exit: 263exit:
@@ -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