Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Jean Delvare and committed by
Greg Kroah-Hartman
7d9db67f b32d20dc

+99 -29
+7 -1
drivers/i2c/chips/eeprom.c
··· 209 209 } 210 210 211 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 216 return 0; 215 217 218 + exit_detach: 219 + i2c_detach_client(new_client); 216 220 exit_kfree: 217 221 kfree(data); 218 222 exit: ··· 226 222 static int eeprom_detach_client(struct i2c_client *client) 227 223 { 228 224 int err; 225 + 226 + sysfs_remove_bin_file(&client->dev.kobj, &eeprom_attr); 229 227 230 228 err = i2c_detach_client(client); 231 229 if (err)
+19 -6
drivers/i2c/chips/max6875.c
··· 199 199 mutex_init(&data->update_lock); 200 200 201 201 /* Init fake client data */ 202 - /* set the client data to the i2c_client so that it will get freed */ 203 - i2c_set_clientdata(fake_client, fake_client); 202 + i2c_set_clientdata(fake_client, NULL); 204 203 fake_client->addr = address | 1; 205 204 fake_client->adapter = adapter; 206 205 fake_client->driver = &max6875_driver; ··· 213 214 goto exit_kfree2; 214 215 215 216 if ((err = i2c_attach_client(fake_client)) != 0) 216 - goto exit_detach; 217 + goto exit_detach1; 217 218 218 - sysfs_create_bin_file(&real_client->dev.kobj, &user_eeprom_attr); 219 + err = sysfs_create_bin_file(&real_client->dev.kobj, &user_eeprom_attr); 220 + if (err) 221 + goto exit_detach2; 219 222 220 223 return 0; 221 224 222 - exit_detach: 225 + exit_detach2: 226 + i2c_detach_client(fake_client); 227 + exit_detach1: 223 228 i2c_detach_client(real_client); 224 229 exit_kfree2: 225 230 kfree(fake_client); ··· 232 229 return err; 233 230 } 234 231 232 + /* Will be called for both the real client and the fake client */ 235 233 static int max6875_detach_client(struct i2c_client *client) 236 234 { 237 235 int err; 236 + struct max6875_data *data = i2c_get_clientdata(client); 237 + 238 + /* data is NULL for the fake client */ 239 + if (data) 240 + sysfs_remove_bin_file(&client->dev.kobj, &user_eeprom_attr); 238 241 239 242 err = i2c_detach_client(client); 240 243 if (err) 241 244 return err; 242 - kfree(i2c_get_clientdata(client)); 245 + 246 + if (data) /* real client */ 247 + kfree(data); 248 + else /* fake client */ 249 + kfree(client); 243 250 return 0; 244 251 } 245 252
+9 -2
drivers/i2c/chips/pca9539.c
··· 148 148 if ((err = i2c_attach_client(new_client))) 149 149 goto exit_kfree; 150 150 151 - /* Register sysfs hooks (don't care about failure) */ 152 - sysfs_create_group(&new_client->dev.kobj, &pca9539_defattr_group); 151 + /* Register sysfs hooks */ 152 + err = sysfs_create_group(&new_client->dev.kobj, 153 + &pca9539_defattr_group); 154 + if (err) 155 + goto exit_detach; 153 156 154 157 return 0; 155 158 159 + exit_detach: 160 + i2c_detach_client(new_client); 156 161 exit_kfree: 157 162 kfree(data); 158 163 exit: ··· 167 162 static int pca9539_detach_client(struct i2c_client *client) 168 163 { 169 164 int err; 165 + 166 + sysfs_remove_group(&client->dev.kobj, &pca9539_defattr_group); 170 167 171 168 if ((err = i2c_detach_client(client))) 172 169 return err;
+17 -5
drivers/i2c/chips/pcf8574.c
··· 105 105 106 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 119 * Real code 110 120 */ ··· 176 166 pcf8574_init_client(new_client); 177 167 178 168 /* Register sysfs hooks */ 179 - device_create_file(&new_client->dev, &dev_attr_read); 180 - device_create_file(&new_client->dev, &dev_attr_write); 169 + err = sysfs_create_group(&new_client->dev.kobj, &pcf8574_attr_group); 170 + if (err) 171 + goto exit_detach; 181 172 return 0; 182 173 183 - /* OK, this is not exactly good programming practice, usually. But it is 184 - very code-efficient in this case. */ 185 - 174 + exit_detach: 175 + i2c_detach_client(new_client); 186 176 exit_free: 187 177 kfree(data); 188 178 exit: ··· 192 182 static int pcf8574_detach_client(struct i2c_client *client) 193 183 { 194 184 int err; 185 + 186 + sysfs_remove_group(&client->dev.kobj, &pcf8574_attr_group); 195 187 196 188 if ((err = i2c_detach_client(client))) 197 189 return err;
+47 -15
drivers/i2c/chips/pcf8591.c
··· 158 158 static DEVICE_ATTR(out0_enable, S_IWUSR | S_IRUGO, 159 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 184 * Real code 163 185 */ ··· 233 211 pcf8591_init_client(new_client); 234 212 235 213 /* Register sysfs hooks */ 236 - device_create_file(&new_client->dev, &dev_attr_out0_enable); 237 - device_create_file(&new_client->dev, &dev_attr_out0_output); 238 - device_create_file(&new_client->dev, &dev_attr_in0_input); 239 - device_create_file(&new_client->dev, &dev_attr_in1_input); 214 + err = sysfs_create_group(&new_client->dev.kobj, &pcf8591_attr_group); 215 + if (err) 216 + goto exit_detach; 240 217 241 218 /* Register input2 if not in "two differential inputs" mode */ 242 - if (input_mode != 3 ) 243 - device_create_file(&new_client->dev, &dev_attr_in2_input); 244 - 245 - /* Register input3 only in "four single ended inputs" mode */ 246 - if (input_mode == 0) 247 - device_create_file(&new_client->dev, &dev_attr_in3_input); 248 - 249 - return 0; 250 - 251 - /* OK, this is not exactly good programming practice, usually. But it is 252 - very code-efficient in this case. */ 219 + if (input_mode != 3) { 220 + if ((err = device_create_file(&new_client->dev, 221 + &dev_attr_in2_input))) 222 + goto exit_sysfs_remove; 223 + } 253 224 225 + /* Register input3 only in "four single ended inputs" mode */ 226 + if (input_mode == 0) { 227 + if ((err = device_create_file(&new_client->dev, 228 + &dev_attr_in3_input))) 229 + goto exit_sysfs_remove; 230 + } 231 + 232 + return 0; 233 + 234 + exit_sysfs_remove: 235 + sysfs_remove_group(&new_client->dev.kobj, &pcf8591_attr_group_opt); 236 + sysfs_remove_group(&new_client->dev.kobj, &pcf8591_attr_group); 237 + exit_detach: 238 + i2c_detach_client(new_client); 254 239 exit_kfree: 255 240 kfree(data); 256 241 exit: ··· 267 238 static int pcf8591_detach_client(struct i2c_client *client) 268 239 { 269 240 int err; 241 + 242 + sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group_opt); 243 + sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group); 270 244 271 245 if ((err = i2c_detach_client(client))) 272 246 return err;