diff options
-rw-r--r-- | drivers/base/core.c | 53 | ||||
-rw-r--r-- | include/linux/device.h | 4 |
2 files changed, 57 insertions, 0 deletions
diff --git a/drivers/base/core.c b/drivers/base/core.c index 5c91d0d81e78..f1228f25efe0 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c | |||
@@ -94,6 +94,8 @@ static void device_release(struct kobject * kobj) | |||
94 | 94 | ||
95 | if (dev->release) | 95 | if (dev->release) |
96 | dev->release(dev); | 96 | dev->release(dev); |
97 | else if (dev->class && dev->class->dev_release) | ||
98 | dev->class->dev_release(dev); | ||
97 | else { | 99 | else { |
98 | printk(KERN_ERR "Device '%s' does not have a release() function, " | 100 | printk(KERN_ERR "Device '%s' does not have a release() function, " |
99 | "it is broken and must be fixed.\n", | 101 | "it is broken and must be fixed.\n", |
@@ -183,6 +185,15 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj, char **envp, | |||
183 | } | 185 | } |
184 | } | 186 | } |
185 | 187 | ||
188 | if (dev->class && dev->class->dev_uevent) { | ||
189 | /* have the class specific function add its stuff */ | ||
190 | retval = dev->class->dev_uevent(dev, envp, num_envp, buffer, buffer_size); | ||
191 | if (retval) { | ||
192 | pr_debug("%s - dev_uevent() returned %d\n", | ||
193 | __FUNCTION__, retval); | ||
194 | } | ||
195 | } | ||
196 | |||
186 | return retval; | 197 | return retval; |
187 | } | 198 | } |
188 | 199 | ||
@@ -228,6 +239,43 @@ static void device_remove_groups(struct device *dev) | |||
228 | } | 239 | } |
229 | } | 240 | } |
230 | 241 | ||
242 | static int device_add_attrs(struct device *dev) | ||
243 | { | ||
244 | struct class *class = dev->class; | ||
245 | int error = 0; | ||
246 | int i; | ||
247 | |||
248 | if (!class) | ||
249 | return 0; | ||
250 | |||
251 | if (class->dev_attrs) { | ||
252 | for (i = 0; attr_name(class->dev_attrs[i]); i++) { | ||
253 | error = device_create_file(dev, &class->dev_attrs[i]); | ||
254 | if (error) | ||
255 | break; | ||
256 | } | ||
257 | } | ||
258 | if (error) | ||
259 | while (--i >= 0) | ||
260 | device_remove_file(dev, &class->dev_attrs[i]); | ||
261 | return error; | ||
262 | } | ||
263 | |||
264 | static void device_remove_attrs(struct device *dev) | ||
265 | { | ||
266 | struct class *class = dev->class; | ||
267 | int i; | ||
268 | |||
269 | if (!class) | ||
270 | return; | ||
271 | |||
272 | if (class->dev_attrs) { | ||
273 | for (i = 0; attr_name(class->dev_attrs[i]); i++) | ||
274 | device_remove_file(dev, &class->dev_attrs[i]); | ||
275 | } | ||
276 | } | ||
277 | |||
278 | |||
231 | static ssize_t show_dev(struct device *dev, struct device_attribute *attr, | 279 | static ssize_t show_dev(struct device *dev, struct device_attribute *attr, |
232 | char *buf) | 280 | char *buf) |
233 | { | 281 | { |
@@ -382,6 +430,8 @@ int device_add(struct device *dev) | |||
382 | } | 430 | } |
383 | } | 431 | } |
384 | 432 | ||
433 | if ((error = device_add_attrs(dev))) | ||
434 | goto AttrsError; | ||
385 | if ((error = device_add_groups(dev))) | 435 | if ((error = device_add_groups(dev))) |
386 | goto GroupError; | 436 | goto GroupError; |
387 | if ((error = device_pm_add(dev))) | 437 | if ((error = device_pm_add(dev))) |
@@ -412,6 +462,8 @@ int device_add(struct device *dev) | |||
412 | PMError: | 462 | PMError: |
413 | device_remove_groups(dev); | 463 | device_remove_groups(dev); |
414 | GroupError: | 464 | GroupError: |
465 | device_remove_attrs(dev); | ||
466 | AttrsError: | ||
415 | if (dev->devt_attr) { | 467 | if (dev->devt_attr) { |
416 | device_remove_file(dev, dev->devt_attr); | 468 | device_remove_file(dev, dev->devt_attr); |
417 | kfree(dev->devt_attr); | 469 | kfree(dev->devt_attr); |
@@ -509,6 +561,7 @@ void device_del(struct device * dev) | |||
509 | } | 561 | } |
510 | device_remove_file(dev, &dev->uevent_attr); | 562 | device_remove_file(dev, &dev->uevent_attr); |
511 | device_remove_groups(dev); | 563 | device_remove_groups(dev); |
564 | device_remove_attrs(dev); | ||
512 | 565 | ||
513 | /* Notify the platform of the removal, in case they | 566 | /* Notify the platform of the removal, in case they |
514 | * need to do anything... | 567 | * need to do anything... |
diff --git a/include/linux/device.h b/include/linux/device.h index 994d3ebd53f4..3122bd25ce42 100644 --- a/include/linux/device.h +++ b/include/linux/device.h | |||
@@ -151,12 +151,16 @@ struct class { | |||
151 | 151 | ||
152 | struct class_attribute * class_attrs; | 152 | struct class_attribute * class_attrs; |
153 | struct class_device_attribute * class_dev_attrs; | 153 | struct class_device_attribute * class_dev_attrs; |
154 | struct device_attribute * dev_attrs; | ||
154 | 155 | ||
155 | int (*uevent)(struct class_device *dev, char **envp, | 156 | int (*uevent)(struct class_device *dev, char **envp, |
156 | int num_envp, char *buffer, int buffer_size); | 157 | int num_envp, char *buffer, int buffer_size); |
158 | int (*dev_uevent)(struct device *dev, char **envp, int num_envp, | ||
159 | char *buffer, int buffer_size); | ||
157 | 160 | ||
158 | void (*release)(struct class_device *dev); | 161 | void (*release)(struct class_device *dev); |
159 | void (*class_release)(struct class *class); | 162 | void (*class_release)(struct class *class); |
163 | void (*dev_release)(struct device *dev); | ||
160 | 164 | ||
161 | int (*suspend)(struct device *, pm_message_t state); | 165 | int (*suspend)(struct device *, pm_message_t state); |
162 | int (*resume)(struct device *); | 166 | int (*resume)(struct device *); |