aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/base/core.c')
-rw-r--r--drivers/base/core.c230
1 files changed, 211 insertions, 19 deletions
diff --git a/drivers/base/core.c b/drivers/base/core.c
index be6b5bc0677d..b224bb43ff63 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -3,6 +3,8 @@
3 * 3 *
4 * Copyright (c) 2002-3 Patrick Mochel 4 * Copyright (c) 2002-3 Patrick Mochel
5 * Copyright (c) 2002-3 Open Source Development Labs 5 * Copyright (c) 2002-3 Open Source Development Labs
6 * Copyright (c) 2006 Greg Kroah-Hartman <gregkh@suse.de>
7 * Copyright (c) 2006 Novell, Inc.
6 * 8 *
7 * This file is released under the GPLv2 9 * This file is released under the GPLv2
8 * 10 *
@@ -92,6 +94,8 @@ static void device_release(struct kobject * kobj)
92 94
93 if (dev->release) 95 if (dev->release)
94 dev->release(dev); 96 dev->release(dev);
97 else if (dev->class && dev->class->dev_release)
98 dev->class->dev_release(dev);
95 else { 99 else {
96 printk(KERN_ERR "Device '%s' does not have a release() function, " 100 printk(KERN_ERR "Device '%s' does not have a release() function, "
97 "it is broken and must be fixed.\n", 101 "it is broken and must be fixed.\n",
@@ -149,17 +153,21 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj, char **envp,
149 "MINOR=%u", MINOR(dev->devt)); 153 "MINOR=%u", MINOR(dev->devt));
150 } 154 }
151 155
152 /* add bus name of physical device */ 156 /* add bus name (same as SUBSYSTEM, deprecated) */
153 if (dev->bus) 157 if (dev->bus)
154 add_uevent_var(envp, num_envp, &i, 158 add_uevent_var(envp, num_envp, &i,
155 buffer, buffer_size, &length, 159 buffer, buffer_size, &length,
156 "PHYSDEVBUS=%s", dev->bus->name); 160 "PHYSDEVBUS=%s", dev->bus->name);
157 161
158 /* add driver name of physical device */ 162 /* add driver name (PHYSDEV* values are deprecated)*/
159 if (dev->driver) 163 if (dev->driver) {
164 add_uevent_var(envp, num_envp, &i,
165 buffer, buffer_size, &length,
166 "DRIVER=%s", dev->driver->name);
160 add_uevent_var(envp, num_envp, &i, 167 add_uevent_var(envp, num_envp, &i,
161 buffer, buffer_size, &length, 168 buffer, buffer_size, &length,
162 "PHYSDEVDRIVER=%s", dev->driver->name); 169 "PHYSDEVDRIVER=%s", dev->driver->name);
170 }
163 171
164 /* terminate, set to next free slot, shrink available space */ 172 /* terminate, set to next free slot, shrink available space */
165 envp[i] = NULL; 173 envp[i] = NULL;
@@ -177,6 +185,15 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj, char **envp,
177 } 185 }
178 } 186 }
179 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
180 return retval; 197 return retval;
181} 198}
182 199
@@ -193,6 +210,72 @@ static ssize_t store_uevent(struct device *dev, struct device_attribute *attr,
193 return count; 210 return count;
194} 211}
195 212
213static int device_add_groups(struct device *dev)
214{
215 int i;
216 int error = 0;
217
218 if (dev->groups) {
219 for (i = 0; dev->groups[i]; i++) {
220 error = sysfs_create_group(&dev->kobj, dev->groups[i]);
221 if (error) {
222 while (--i >= 0)
223 sysfs_remove_group(&dev->kobj, dev->groups[i]);
224 goto out;
225 }
226 }
227 }
228out:
229 return error;
230}
231
232static void device_remove_groups(struct device *dev)
233{
234 int i;
235 if (dev->groups) {
236 for (i = 0; dev->groups[i]; i++) {
237 sysfs_remove_group(&dev->kobj, dev->groups[i]);
238 }
239 }
240}
241
242static 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
264static 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
196static ssize_t show_dev(struct device *dev, struct device_attribute *attr, 279static ssize_t show_dev(struct device *dev, struct device_attribute *attr,
197 char *buf) 280 char *buf)
198{ 281{
@@ -236,6 +319,32 @@ void device_remove_file(struct device * dev, struct device_attribute * attr)
236 } 319 }
237} 320}
238 321
322/**
323 * device_create_bin_file - create sysfs binary attribute file for device.
324 * @dev: device.
325 * @attr: device binary attribute descriptor.
326 */
327int device_create_bin_file(struct device *dev, struct bin_attribute *attr)
328{
329 int error = -EINVAL;
330 if (dev)
331 error = sysfs_create_bin_file(&dev->kobj, attr);
332 return error;
333}
334EXPORT_SYMBOL_GPL(device_create_bin_file);
335
336/**
337 * device_remove_bin_file - remove sysfs binary attribute file
338 * @dev: device.
339 * @attr: device binary attribute descriptor.
340 */
341void device_remove_bin_file(struct device *dev, struct bin_attribute *attr)
342{
343 if (dev)
344 sysfs_remove_bin_file(&dev->kobj, attr);
345}
346EXPORT_SYMBOL_GPL(device_remove_bin_file);
347
239static void klist_children_get(struct klist_node *n) 348static void klist_children_get(struct klist_node *n)
240{ 349{
241 struct device *dev = container_of(n, struct device, knode_parent); 350 struct device *dev = container_of(n, struct device, knode_parent);
@@ -289,12 +398,20 @@ int device_add(struct device *dev)
289{ 398{
290 struct device *parent = NULL; 399 struct device *parent = NULL;
291 char *class_name = NULL; 400 char *class_name = NULL;
401 struct class_interface *class_intf;
292 int error = -EINVAL; 402 int error = -EINVAL;
293 403
294 dev = get_device(dev); 404 dev = get_device(dev);
295 if (!dev || !strlen(dev->bus_id)) 405 if (!dev || !strlen(dev->bus_id))
296 goto Error; 406 goto Error;
297 407
408 /* if this is a class device, and has no parent, create one */
409 if ((dev->class) && (dev->parent == NULL)) {
410 error = virtual_device_parent(dev);
411 if (error)
412 goto Error;
413 }
414
298 parent = get_device(dev->parent); 415 parent = get_device(dev->parent);
299 416
300 pr_debug("DEV: registering device: ID = '%s'\n", dev->bus_id); 417 pr_debug("DEV: registering device: ID = '%s'\n", dev->bus_id);
@@ -307,6 +424,10 @@ int device_add(struct device *dev)
307 if ((error = kobject_add(&dev->kobj))) 424 if ((error = kobject_add(&dev->kobj)))
308 goto Error; 425 goto Error;
309 426
427 /* notify platform of device entry */
428 if (platform_notify)
429 platform_notify(dev);
430
310 dev->uevent_attr.attr.name = "uevent"; 431 dev->uevent_attr.attr.name = "uevent";
311 dev->uevent_attr.attr.mode = S_IWUSR; 432 dev->uevent_attr.attr.mode = S_IWUSR;
312 if (dev->driver) 433 if (dev->driver)
@@ -340,12 +461,17 @@ int device_add(struct device *dev)
340 "subsystem"); 461 "subsystem");
341 sysfs_create_link(&dev->class->subsys.kset.kobj, &dev->kobj, 462 sysfs_create_link(&dev->class->subsys.kset.kobj, &dev->kobj,
342 dev->bus_id); 463 dev->bus_id);
343 464 if (parent) {
344 sysfs_create_link(&dev->kobj, &dev->parent->kobj, "device"); 465 sysfs_create_link(&dev->kobj, &dev->parent->kobj, "device");
345 class_name = make_class_name(dev->class->name, &dev->kobj); 466 class_name = make_class_name(dev->class->name, &dev->kobj);
346 sysfs_create_link(&dev->parent->kobj, &dev->kobj, class_name); 467 sysfs_create_link(&dev->parent->kobj, &dev->kobj, class_name);
468 }
347 } 469 }
348 470
471 if ((error = device_add_attrs(dev)))
472 goto AttrsError;
473 if ((error = device_add_groups(dev)))
474 goto GroupError;
349 if ((error = device_pm_add(dev))) 475 if ((error = device_pm_add(dev)))
350 goto PMError; 476 goto PMError;
351 if ((error = bus_add_device(dev))) 477 if ((error = bus_add_device(dev)))
@@ -356,15 +482,16 @@ int device_add(struct device *dev)
356 klist_add_tail(&dev->knode_parent, &parent->klist_children); 482 klist_add_tail(&dev->knode_parent, &parent->klist_children);
357 483
358 if (dev->class) { 484 if (dev->class) {
359 /* tie the class to the device */
360 down(&dev->class->sem); 485 down(&dev->class->sem);
486 /* tie the class to the device */
361 list_add_tail(&dev->node, &dev->class->devices); 487 list_add_tail(&dev->node, &dev->class->devices);
488
489 /* notify any interfaces that the device is here */
490 list_for_each_entry(class_intf, &dev->class->interfaces, node)
491 if (class_intf->add_dev)
492 class_intf->add_dev(dev, class_intf);
362 up(&dev->class->sem); 493 up(&dev->class->sem);
363 } 494 }
364
365 /* notify platform of device entry */
366 if (platform_notify)
367 platform_notify(dev);
368 Done: 495 Done:
369 kfree(class_name); 496 kfree(class_name);
370 put_device(dev); 497 put_device(dev);
@@ -372,6 +499,10 @@ int device_add(struct device *dev)
372 BusError: 499 BusError:
373 device_pm_remove(dev); 500 device_pm_remove(dev);
374 PMError: 501 PMError:
502 device_remove_groups(dev);
503 GroupError:
504 device_remove_attrs(dev);
505 AttrsError:
375 if (dev->devt_attr) { 506 if (dev->devt_attr) {
376 device_remove_file(dev, dev->devt_attr); 507 device_remove_file(dev, dev->devt_attr);
377 kfree(dev->devt_attr); 508 kfree(dev->devt_attr);
@@ -449,6 +580,7 @@ void device_del(struct device * dev)
449{ 580{
450 struct device * parent = dev->parent; 581 struct device * parent = dev->parent;
451 char *class_name = NULL; 582 char *class_name = NULL;
583 struct class_interface *class_intf;
452 584
453 if (parent) 585 if (parent)
454 klist_del(&dev->knode_parent); 586 klist_del(&dev->knode_parent);
@@ -458,14 +590,23 @@ void device_del(struct device * dev)
458 sysfs_remove_link(&dev->kobj, "subsystem"); 590 sysfs_remove_link(&dev->kobj, "subsystem");
459 sysfs_remove_link(&dev->class->subsys.kset.kobj, dev->bus_id); 591 sysfs_remove_link(&dev->class->subsys.kset.kobj, dev->bus_id);
460 class_name = make_class_name(dev->class->name, &dev->kobj); 592 class_name = make_class_name(dev->class->name, &dev->kobj);
461 sysfs_remove_link(&dev->kobj, "device"); 593 if (parent) {
462 sysfs_remove_link(&dev->parent->kobj, class_name); 594 sysfs_remove_link(&dev->kobj, "device");
595 sysfs_remove_link(&dev->parent->kobj, class_name);
596 }
463 kfree(class_name); 597 kfree(class_name);
464 down(&dev->class->sem); 598 down(&dev->class->sem);
599 /* notify any interfaces that the device is now gone */
600 list_for_each_entry(class_intf, &dev->class->interfaces, node)
601 if (class_intf->remove_dev)
602 class_intf->remove_dev(dev, class_intf);
603 /* remove the device from the class list */
465 list_del_init(&dev->node); 604 list_del_init(&dev->node);
466 up(&dev->class->sem); 605 up(&dev->class->sem);
467 } 606 }
468 device_remove_file(dev, &dev->uevent_attr); 607 device_remove_file(dev, &dev->uevent_attr);
608 device_remove_groups(dev);
609 device_remove_attrs(dev);
469 610
470 /* Notify the platform of the removal, in case they 611 /* Notify the platform of the removal, in case they
471 * need to do anything... 612 * need to do anything...
@@ -579,7 +720,7 @@ static void device_create_release(struct device *dev)
579 * been created with a call to class_create(). 720 * been created with a call to class_create().
580 */ 721 */
581struct device *device_create(struct class *class, struct device *parent, 722struct device *device_create(struct class *class, struct device *parent,
582 dev_t devt, char *fmt, ...) 723 dev_t devt, const char *fmt, ...)
583{ 724{
584 va_list args; 725 va_list args;
585 struct device *dev = NULL; 726 struct device *dev = NULL;
@@ -587,10 +728,6 @@ struct device *device_create(struct class *class, struct device *parent,
587 728
588 if (class == NULL || IS_ERR(class)) 729 if (class == NULL || IS_ERR(class))
589 goto error; 730 goto error;
590 if (parent == NULL) {
591 printk(KERN_WARNING "%s does not work yet for NULL parents\n", __FUNCTION__);
592 goto error;
593 }
594 731
595 dev = kzalloc(sizeof(*dev), GFP_KERNEL); 732 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
596 if (!dev) { 733 if (!dev) {
@@ -644,3 +781,58 @@ void device_destroy(struct class *class, dev_t devt)
644 device_unregister(dev); 781 device_unregister(dev);
645} 782}
646EXPORT_SYMBOL_GPL(device_destroy); 783EXPORT_SYMBOL_GPL(device_destroy);
784
785/**
786 * device_rename - renames a device
787 * @dev: the pointer to the struct device to be renamed
788 * @new_name: the new name of the device
789 */
790int device_rename(struct device *dev, char *new_name)
791{
792 char *old_class_name = NULL;
793 char *new_class_name = NULL;
794 char *old_symlink_name = NULL;
795 int error;
796
797 dev = get_device(dev);
798 if (!dev)
799 return -EINVAL;
800
801 pr_debug("DEVICE: renaming '%s' to '%s'\n", dev->bus_id, new_name);
802
803 if ((dev->class) && (dev->parent))
804 old_class_name = make_class_name(dev->class->name, &dev->kobj);
805
806 if (dev->class) {
807 old_symlink_name = kmalloc(BUS_ID_SIZE, GFP_KERNEL);
808 if (!old_symlink_name)
809 return -ENOMEM;
810 strlcpy(old_symlink_name, dev->bus_id, BUS_ID_SIZE);
811 }
812
813 strlcpy(dev->bus_id, new_name, BUS_ID_SIZE);
814
815 error = kobject_rename(&dev->kobj, new_name);
816
817 if (old_class_name) {
818 new_class_name = make_class_name(dev->class->name, &dev->kobj);
819 if (new_class_name) {
820 sysfs_create_link(&dev->parent->kobj, &dev->kobj,
821 new_class_name);
822 sysfs_remove_link(&dev->parent->kobj, old_class_name);
823 }
824 }
825 if (dev->class) {
826 sysfs_remove_link(&dev->class->subsys.kset.kobj,
827 old_symlink_name);
828 sysfs_create_link(&dev->class->subsys.kset.kobj, &dev->kobj,
829 dev->bus_id);
830 }
831 put_device(dev);
832
833 kfree(old_class_name);
834 kfree(new_class_name);
835 kfree(old_symlink_name);
836
837 return error;
838}