diff options
Diffstat (limited to 'drivers/i2c/chips/pcf8591.c')
-rw-r--r-- | drivers/i2c/chips/pcf8591.c | 58 |
1 files changed, 45 insertions, 13 deletions
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 | ||