Skip to content

Commit

Permalink
i2c: __must_check fixes (chip drivers)
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Jean Delvare authored and Greg Kroah-Hartman committed Sep 26, 2006
1 parent b32d20d commit 7d9db67
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 27 deletions.
8 changes: 7 additions & 1 deletion drivers/i2c/chips/eeprom.c
Original file line number Diff line number Diff line change
Expand Up @@ -209,10 +209,14 @@ static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind)
}

/* create the sysfs eeprom file */
sysfs_create_bin_file(&new_client->dev.kobj, &eeprom_attr);
err = sysfs_create_bin_file(&new_client->dev.kobj, &eeprom_attr);
if (err)
goto exit_detach;

return 0;

exit_detach:
i2c_detach_client(new_client);
exit_kfree:
kfree(data);
exit:
Expand All @@ -223,6 +227,8 @@ static int eeprom_detach_client(struct i2c_client *client)
{
int err;

sysfs_remove_bin_file(&client->dev.kobj, &eeprom_attr);

err = i2c_detach_client(client);
if (err)
return err;
Expand Down
25 changes: 19 additions & 6 deletions drivers/i2c/chips/max6875.c
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,7 @@ static int max6875_detect(struct i2c_adapter *adapter, int address, int kind)
mutex_init(&data->update_lock);

/* Init fake client data */
/* set the client data to the i2c_client so that it will get freed */
i2c_set_clientdata(fake_client, fake_client);
i2c_set_clientdata(fake_client, NULL);
fake_client->addr = address | 1;
fake_client->adapter = adapter;
fake_client->driver = &max6875_driver;
Expand All @@ -214,13 +213,17 @@ static int max6875_detect(struct i2c_adapter *adapter, int address, int kind)
goto exit_kfree2;

if ((err = i2c_attach_client(fake_client)) != 0)
goto exit_detach;
goto exit_detach1;

sysfs_create_bin_file(&real_client->dev.kobj, &user_eeprom_attr);
err = sysfs_create_bin_file(&real_client->dev.kobj, &user_eeprom_attr);
if (err)
goto exit_detach2;

return 0;

exit_detach:
exit_detach2:
i2c_detach_client(fake_client);
exit_detach1:
i2c_detach_client(real_client);
exit_kfree2:
kfree(fake_client);
Expand All @@ -229,14 +232,24 @@ static int max6875_detect(struct i2c_adapter *adapter, int address, int kind)
return err;
}

/* Will be called for both the real client and the fake client */
static int max6875_detach_client(struct i2c_client *client)
{
int err;
struct max6875_data *data = i2c_get_clientdata(client);

/* data is NULL for the fake client */
if (data)
sysfs_remove_bin_file(&client->dev.kobj, &user_eeprom_attr);

err = i2c_detach_client(client);
if (err)
return err;
kfree(i2c_get_clientdata(client));

if (data) /* real client */
kfree(data);
else /* fake client */
kfree(client);
return 0;
}

Expand Down
11 changes: 9 additions & 2 deletions drivers/i2c/chips/pca9539.c
Original file line number Diff line number Diff line change
Expand Up @@ -148,11 +148,16 @@ static int pca9539_detect(struct i2c_adapter *adapter, int address, int kind)
if ((err = i2c_attach_client(new_client)))
goto exit_kfree;

/* Register sysfs hooks (don't care about failure) */
sysfs_create_group(&new_client->dev.kobj, &pca9539_defattr_group);
/* Register sysfs hooks */
err = sysfs_create_group(&new_client->dev.kobj,
&pca9539_defattr_group);
if (err)
goto exit_detach;

return 0;

exit_detach:
i2c_detach_client(new_client);
exit_kfree:
kfree(data);
exit:
Expand All @@ -163,6 +168,8 @@ static int pca9539_detach_client(struct i2c_client *client)
{
int err;

sysfs_remove_group(&client->dev.kobj, &pca9539_defattr_group);

if ((err = i2c_detach_client(client)))
return err;

Expand Down
22 changes: 17 additions & 5 deletions drivers/i2c/chips/pcf8574.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,16 @@ static ssize_t set_write(struct device *dev, struct device_attribute *attr, cons

static DEVICE_ATTR(write, S_IWUSR | S_IRUGO, show_write, set_write);

static struct attribute *pcf8574_attributes[] = {
&dev_attr_read.attr,
&dev_attr_write.attr,
NULL
};

static const struct attribute_group pcf8574_attr_group = {
.attrs = pcf8574_attributes,
};

/*
* Real code
*/
Expand Down Expand Up @@ -166,13 +176,13 @@ static int pcf8574_detect(struct i2c_adapter *adapter, int address, int kind)
pcf8574_init_client(new_client);

/* Register sysfs hooks */
device_create_file(&new_client->dev, &dev_attr_read);
device_create_file(&new_client->dev, &dev_attr_write);
err = sysfs_create_group(&new_client->dev.kobj, &pcf8574_attr_group);
if (err)
goto exit_detach;
return 0;

/* OK, this is not exactly good programming practice, usually. But it is
very code-efficient in this case. */

exit_detach:
i2c_detach_client(new_client);
exit_free:
kfree(data);
exit:
Expand All @@ -183,6 +193,8 @@ static int pcf8574_detach_client(struct i2c_client *client)
{
int err;

sysfs_remove_group(&client->dev.kobj, &pcf8574_attr_group);

if ((err = i2c_detach_client(client)))
return err;

Expand Down
58 changes: 45 additions & 13 deletions drivers/i2c/chips/pcf8591.c
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,28 @@ static ssize_t set_out0_enable(struct device *dev, struct device_attribute *attr
static DEVICE_ATTR(out0_enable, S_IWUSR | S_IRUGO,
show_out0_enable, set_out0_enable);

static struct attribute *pcf8591_attributes[] = {
&dev_attr_out0_enable.attr,
&dev_attr_out0_output.attr,
&dev_attr_in0_input.attr,
&dev_attr_in1_input.attr,
NULL
};

static const struct attribute_group pcf8591_attr_group = {
.attrs = pcf8591_attributes,
};

static struct attribute *pcf8591_attributes_opt[] = {
&dev_attr_in2_input.attr,
&dev_attr_in3_input.attr,
NULL
};

static const struct attribute_group pcf8591_attr_group_opt = {
.attrs = pcf8591_attributes_opt,
};

/*
* Real code
*/
Expand Down Expand Up @@ -211,24 +233,31 @@ static int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind)
pcf8591_init_client(new_client);

/* Register sysfs hooks */
device_create_file(&new_client->dev, &dev_attr_out0_enable);
device_create_file(&new_client->dev, &dev_attr_out0_output);
device_create_file(&new_client->dev, &dev_attr_in0_input);
device_create_file(&new_client->dev, &dev_attr_in1_input);
err = sysfs_create_group(&new_client->dev.kobj, &pcf8591_attr_group);
if (err)
goto exit_detach;

/* Register input2 if not in "two differential inputs" mode */
if (input_mode != 3 )
device_create_file(&new_client->dev, &dev_attr_in2_input);

if (input_mode != 3) {
if ((err = device_create_file(&new_client->dev,
&dev_attr_in2_input)))
goto exit_sysfs_remove;
}

/* Register input3 only in "four single ended inputs" mode */
if (input_mode == 0)
device_create_file(&new_client->dev, &dev_attr_in3_input);

if (input_mode == 0) {
if ((err = device_create_file(&new_client->dev,
&dev_attr_in3_input)))
goto exit_sysfs_remove;
}

return 0;

/* OK, this is not exactly good programming practice, usually. But it is
very code-efficient in this case. */

exit_sysfs_remove:
sysfs_remove_group(&new_client->dev.kobj, &pcf8591_attr_group_opt);
sysfs_remove_group(&new_client->dev.kobj, &pcf8591_attr_group);
exit_detach:
i2c_detach_client(new_client);
exit_kfree:
kfree(data);
exit:
Expand All @@ -239,6 +268,9 @@ static int pcf8591_detach_client(struct i2c_client *client)
{
int err;

sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group_opt);
sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group);

if ((err = i2c_detach_client(client)))
return err;

Expand Down

0 comments on commit 7d9db67

Please sign in to comment.