diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-07 22:22:26 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-07 22:22:26 -0500 |
commit | f2aca47dc3c2d0c2d5dbd972558557e74232bbce (patch) | |
tree | eae58f599a25a1f3ab41bf616a2b7c4b3c6e2277 /drivers/base | |
parent | 7677ced48e2bbbb8d847d34f37e5d96d2b0e41e4 (diff) | |
parent | b592fcfe7f06c15ec11774b5be7ce0de3aa86e73 (diff) |
Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/driver-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/gregkh/driver-2.6: (28 commits)
sysfs: Shadow directory support
Driver Core: Increase the default timeout value of the firmware subsystem
Driver core: allow to delay the uevent at device creation time
Driver core: add device_type to struct device
Driver core: add uevent vars for devices of a class
SYSFS: Fix missing include of list.h in sysfs.h
HOWTO: Add a reference to Harbison and Steele
sysfs: error handling in sysfs, fill_read_buffer()
kobject: kobject_put cleanup
sysfs: kobject_put cleanup
sysfs: suppress lockdep warnings
Driver core: fix race in sysfs between sysfs_remove_file() and read()/write()
driver core: Change function call order in device_bind_driver().
driver core: Don't stop probing on ->probe errors.
driver core fixes: device_register() retval check in platform.c
driver core fixes: make_class_name() retval checks
/sys/modules/*/holders
USB: add the sysfs driver name to all modules
SERIO: add the sysfs driver name to all modules
PCI: add the sysfs driver name to all modules
...
Diffstat (limited to 'drivers/base')
-rw-r--r-- | drivers/base/class.c | 21 | ||||
-rw-r--r-- | drivers/base/core.c | 203 | ||||
-rw-r--r-- | drivers/base/dd.c | 21 | ||||
-rw-r--r-- | drivers/base/firmware_class.c | 2 | ||||
-rw-r--r-- | drivers/base/platform.c | 11 |
5 files changed, 169 insertions, 89 deletions
diff --git a/drivers/base/class.c b/drivers/base/class.c index 8bf2ca2e56b5..96def1ddba19 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c | |||
@@ -364,7 +364,7 @@ char *make_class_name(const char *name, struct kobject *kobj) | |||
364 | 364 | ||
365 | class_name = kmalloc(size, GFP_KERNEL); | 365 | class_name = kmalloc(size, GFP_KERNEL); |
366 | if (!class_name) | 366 | if (!class_name) |
367 | return ERR_PTR(-ENOMEM); | 367 | return NULL; |
368 | 368 | ||
369 | strcpy(class_name, name); | 369 | strcpy(class_name, name); |
370 | strcat(class_name, ":"); | 370 | strcat(class_name, ":"); |
@@ -411,8 +411,11 @@ static int make_deprecated_class_device_links(struct class_device *class_dev) | |||
411 | return 0; | 411 | return 0; |
412 | 412 | ||
413 | class_name = make_class_name(class_dev->class->name, &class_dev->kobj); | 413 | class_name = make_class_name(class_dev->class->name, &class_dev->kobj); |
414 | error = sysfs_create_link(&class_dev->dev->kobj, &class_dev->kobj, | 414 | if (class_name) |
415 | class_name); | 415 | error = sysfs_create_link(&class_dev->dev->kobj, |
416 | &class_dev->kobj, class_name); | ||
417 | else | ||
418 | error = -ENOMEM; | ||
416 | kfree(class_name); | 419 | kfree(class_name); |
417 | return error; | 420 | return error; |
418 | } | 421 | } |
@@ -425,7 +428,8 @@ static void remove_deprecated_class_device_links(struct class_device *class_dev) | |||
425 | return; | 428 | return; |
426 | 429 | ||
427 | class_name = make_class_name(class_dev->class->name, &class_dev->kobj); | 430 | class_name = make_class_name(class_dev->class->name, &class_dev->kobj); |
428 | sysfs_remove_link(&class_dev->dev->kobj, class_name); | 431 | if (class_name) |
432 | sysfs_remove_link(&class_dev->dev->kobj, class_name); | ||
429 | kfree(class_name); | 433 | kfree(class_name); |
430 | } | 434 | } |
431 | #else | 435 | #else |
@@ -863,9 +867,12 @@ int class_device_rename(struct class_device *class_dev, char *new_name) | |||
863 | if (class_dev->dev) { | 867 | if (class_dev->dev) { |
864 | new_class_name = make_class_name(class_dev->class->name, | 868 | new_class_name = make_class_name(class_dev->class->name, |
865 | &class_dev->kobj); | 869 | &class_dev->kobj); |
866 | sysfs_create_link(&class_dev->dev->kobj, &class_dev->kobj, | 870 | if (new_class_name) |
867 | new_class_name); | 871 | sysfs_create_link(&class_dev->dev->kobj, |
868 | sysfs_remove_link(&class_dev->dev->kobj, old_class_name); | 872 | &class_dev->kobj, new_class_name); |
873 | if (old_class_name) | ||
874 | sysfs_remove_link(&class_dev->dev->kobj, | ||
875 | old_class_name); | ||
869 | } | 876 | } |
870 | #endif | 877 | #endif |
871 | class_device_put(class_dev); | 878 | class_device_put(class_dev); |
diff --git a/drivers/base/core.c b/drivers/base/core.c index 67b79a7592a9..e13614241c9e 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c | |||
@@ -95,6 +95,8 @@ static void device_release(struct kobject * kobj) | |||
95 | 95 | ||
96 | if (dev->release) | 96 | if (dev->release) |
97 | dev->release(dev); | 97 | dev->release(dev); |
98 | else if (dev->type && dev->type->release) | ||
99 | dev->type->release(dev); | ||
98 | else if (dev->class && dev->class->dev_release) | 100 | else if (dev->class && dev->class->dev_release) |
99 | dev->class->dev_release(dev); | 101 | dev->class->dev_release(dev); |
100 | else { | 102 | else { |
@@ -154,25 +156,47 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj, char **envp, | |||
154 | "MINOR=%u", MINOR(dev->devt)); | 156 | "MINOR=%u", MINOR(dev->devt)); |
155 | } | 157 | } |
156 | 158 | ||
157 | #ifdef CONFIG_SYSFS_DEPRECATED | 159 | if (dev->driver) |
158 | /* add bus name (same as SUBSYSTEM, deprecated) */ | ||
159 | if (dev->bus) | ||
160 | add_uevent_var(envp, num_envp, &i, | ||
161 | buffer, buffer_size, &length, | ||
162 | "PHYSDEVBUS=%s", dev->bus->name); | ||
163 | #endif | ||
164 | |||
165 | /* add driver name (PHYSDEV* values are deprecated)*/ | ||
166 | if (dev->driver) { | ||
167 | add_uevent_var(envp, num_envp, &i, | 160 | add_uevent_var(envp, num_envp, &i, |
168 | buffer, buffer_size, &length, | 161 | buffer, buffer_size, &length, |
169 | "DRIVER=%s", dev->driver->name); | 162 | "DRIVER=%s", dev->driver->name); |
163 | |||
170 | #ifdef CONFIG_SYSFS_DEPRECATED | 164 | #ifdef CONFIG_SYSFS_DEPRECATED |
165 | if (dev->class) { | ||
166 | struct device *parent = dev->parent; | ||
167 | |||
168 | /* find first bus device in parent chain */ | ||
169 | while (parent && !parent->bus) | ||
170 | parent = parent->parent; | ||
171 | if (parent && parent->bus) { | ||
172 | const char *path; | ||
173 | |||
174 | path = kobject_get_path(&parent->kobj, GFP_KERNEL); | ||
175 | add_uevent_var(envp, num_envp, &i, | ||
176 | buffer, buffer_size, &length, | ||
177 | "PHYSDEVPATH=%s", path); | ||
178 | kfree(path); | ||
179 | |||
180 | add_uevent_var(envp, num_envp, &i, | ||
181 | buffer, buffer_size, &length, | ||
182 | "PHYSDEVBUS=%s", parent->bus->name); | ||
183 | |||
184 | if (parent->driver) | ||
185 | add_uevent_var(envp, num_envp, &i, | ||
186 | buffer, buffer_size, &length, | ||
187 | "PHYSDEVDRIVER=%s", parent->driver->name); | ||
188 | } | ||
189 | } else if (dev->bus) { | ||
171 | add_uevent_var(envp, num_envp, &i, | 190 | add_uevent_var(envp, num_envp, &i, |
172 | buffer, buffer_size, &length, | 191 | buffer, buffer_size, &length, |
173 | "PHYSDEVDRIVER=%s", dev->driver->name); | 192 | "PHYSDEVBUS=%s", dev->bus->name); |
174 | #endif | 193 | |
194 | if (dev->driver) | ||
195 | add_uevent_var(envp, num_envp, &i, | ||
196 | buffer, buffer_size, &length, | ||
197 | "PHYSDEVDRIVER=%s", dev->driver->name); | ||
175 | } | 198 | } |
199 | #endif | ||
176 | 200 | ||
177 | /* terminate, set to next free slot, shrink available space */ | 201 | /* terminate, set to next free slot, shrink available space */ |
178 | envp[i] = NULL; | 202 | envp[i] = NULL; |
@@ -184,19 +208,25 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj, char **envp, | |||
184 | if (dev->bus && dev->bus->uevent) { | 208 | if (dev->bus && dev->bus->uevent) { |
185 | /* have the bus specific function add its stuff */ | 209 | /* have the bus specific function add its stuff */ |
186 | retval = dev->bus->uevent(dev, envp, num_envp, buffer, buffer_size); | 210 | retval = dev->bus->uevent(dev, envp, num_envp, buffer, buffer_size); |
187 | if (retval) { | 211 | if (retval) |
188 | pr_debug ("%s - uevent() returned %d\n", | 212 | pr_debug ("%s: bus uevent() returned %d\n", |
189 | __FUNCTION__, retval); | 213 | __FUNCTION__, retval); |
190 | } | ||
191 | } | 214 | } |
192 | 215 | ||
193 | if (dev->class && dev->class->dev_uevent) { | 216 | if (dev->class && dev->class->dev_uevent) { |
194 | /* have the class specific function add its stuff */ | 217 | /* have the class specific function add its stuff */ |
195 | retval = dev->class->dev_uevent(dev, envp, num_envp, buffer, buffer_size); | 218 | retval = dev->class->dev_uevent(dev, envp, num_envp, buffer, buffer_size); |
196 | if (retval) { | 219 | if (retval) |
197 | pr_debug("%s - dev_uevent() returned %d\n", | 220 | pr_debug("%s: class uevent() returned %d\n", |
198 | __FUNCTION__, retval); | 221 | __FUNCTION__, retval); |
199 | } | 222 | } |
223 | |||
224 | if (dev->type && dev->type->uevent) { | ||
225 | /* have the device type specific fuction add its stuff */ | ||
226 | retval = dev->type->uevent(dev, envp, num_envp, buffer, buffer_size); | ||
227 | if (retval) | ||
228 | pr_debug("%s: dev_type uevent() returned %d\n", | ||
229 | __FUNCTION__, retval); | ||
200 | } | 230 | } |
201 | 231 | ||
202 | return retval; | 232 | return retval; |
@@ -247,37 +277,50 @@ static void device_remove_groups(struct device *dev) | |||
247 | static int device_add_attrs(struct device *dev) | 277 | static int device_add_attrs(struct device *dev) |
248 | { | 278 | { |
249 | struct class *class = dev->class; | 279 | struct class *class = dev->class; |
280 | struct device_type *type = dev->type; | ||
250 | int error = 0; | 281 | int error = 0; |
251 | int i; | 282 | int i; |
252 | 283 | ||
253 | if (!class) | 284 | if (class && class->dev_attrs) { |
254 | return 0; | ||
255 | |||
256 | if (class->dev_attrs) { | ||
257 | for (i = 0; attr_name(class->dev_attrs[i]); i++) { | 285 | for (i = 0; attr_name(class->dev_attrs[i]); i++) { |
258 | error = device_create_file(dev, &class->dev_attrs[i]); | 286 | error = device_create_file(dev, &class->dev_attrs[i]); |
259 | if (error) | 287 | if (error) |
260 | break; | 288 | break; |
261 | } | 289 | } |
290 | if (error) | ||
291 | while (--i >= 0) | ||
292 | device_remove_file(dev, &class->dev_attrs[i]); | ||
262 | } | 293 | } |
263 | if (error) | 294 | |
264 | while (--i >= 0) | 295 | if (type && type->attrs) { |
265 | device_remove_file(dev, &class->dev_attrs[i]); | 296 | for (i = 0; attr_name(type->attrs[i]); i++) { |
297 | error = device_create_file(dev, &type->attrs[i]); | ||
298 | if (error) | ||
299 | break; | ||
300 | } | ||
301 | if (error) | ||
302 | while (--i >= 0) | ||
303 | device_remove_file(dev, &type->attrs[i]); | ||
304 | } | ||
305 | |||
266 | return error; | 306 | return error; |
267 | } | 307 | } |
268 | 308 | ||
269 | static void device_remove_attrs(struct device *dev) | 309 | static void device_remove_attrs(struct device *dev) |
270 | { | 310 | { |
271 | struct class *class = dev->class; | 311 | struct class *class = dev->class; |
312 | struct device_type *type = dev->type; | ||
272 | int i; | 313 | int i; |
273 | 314 | ||
274 | if (!class) | 315 | if (class && class->dev_attrs) { |
275 | return; | ||
276 | |||
277 | if (class->dev_attrs) { | ||
278 | for (i = 0; attr_name(class->dev_attrs[i]); i++) | 316 | for (i = 0; attr_name(class->dev_attrs[i]); i++) |
279 | device_remove_file(dev, &class->dev_attrs[i]); | 317 | device_remove_file(dev, &class->dev_attrs[i]); |
280 | } | 318 | } |
319 | |||
320 | if (type && type->attrs) { | ||
321 | for (i = 0; attr_name(type->attrs[i]); i++) | ||
322 | device_remove_file(dev, &type->attrs[i]); | ||
323 | } | ||
281 | } | 324 | } |
282 | 325 | ||
283 | 326 | ||
@@ -390,22 +433,23 @@ void device_initialize(struct device *dev) | |||
390 | } | 433 | } |
391 | 434 | ||
392 | #ifdef CONFIG_SYSFS_DEPRECATED | 435 | #ifdef CONFIG_SYSFS_DEPRECATED |
393 | static int setup_parent(struct device *dev, struct device *parent) | 436 | static struct kobject * get_device_parent(struct device *dev, |
437 | struct device *parent) | ||
394 | { | 438 | { |
395 | /* Set the parent to the class, not the parent device */ | 439 | /* Set the parent to the class, not the parent device */ |
396 | /* this keeps sysfs from having a symlink to make old udevs happy */ | 440 | /* this keeps sysfs from having a symlink to make old udevs happy */ |
397 | if (dev->class) | 441 | if (dev->class) |
398 | dev->kobj.parent = &dev->class->subsys.kset.kobj; | 442 | return &dev->class->subsys.kset.kobj; |
399 | else if (parent) | 443 | else if (parent) |
400 | dev->kobj.parent = &parent->kobj; | 444 | return &parent->kobj; |
401 | 445 | ||
402 | return 0; | 446 | return NULL; |
403 | } | 447 | } |
404 | #else | 448 | #else |
405 | static int virtual_device_parent(struct device *dev) | 449 | static struct kobject * virtual_device_parent(struct device *dev) |
406 | { | 450 | { |
407 | if (!dev->class) | 451 | if (!dev->class) |
408 | return -ENODEV; | 452 | return ERR_PTR(-ENODEV); |
409 | 453 | ||
410 | if (!dev->class->virtual_dir) { | 454 | if (!dev->class->virtual_dir) { |
411 | static struct kobject *virtual_dir = NULL; | 455 | static struct kobject *virtual_dir = NULL; |
@@ -415,25 +459,31 @@ static int virtual_device_parent(struct device *dev) | |||
415 | dev->class->virtual_dir = kobject_add_dir(virtual_dir, dev->class->name); | 459 | dev->class->virtual_dir = kobject_add_dir(virtual_dir, dev->class->name); |
416 | } | 460 | } |
417 | 461 | ||
418 | dev->kobj.parent = dev->class->virtual_dir; | 462 | return dev->class->virtual_dir; |
419 | return 0; | ||
420 | } | 463 | } |
421 | 464 | ||
422 | static int setup_parent(struct device *dev, struct device *parent) | 465 | static struct kobject * get_device_parent(struct device *dev, |
466 | struct device *parent) | ||
423 | { | 467 | { |
424 | int error; | ||
425 | |||
426 | /* if this is a class device, and has no parent, create one */ | 468 | /* if this is a class device, and has no parent, create one */ |
427 | if ((dev->class) && (parent == NULL)) { | 469 | if ((dev->class) && (parent == NULL)) { |
428 | error = virtual_device_parent(dev); | 470 | return virtual_device_parent(dev); |
429 | if (error) | ||
430 | return error; | ||
431 | } else if (parent) | 471 | } else if (parent) |
432 | dev->kobj.parent = &parent->kobj; | 472 | return &parent->kobj; |
473 | return NULL; | ||
474 | } | ||
433 | 475 | ||
476 | #endif | ||
477 | static int setup_parent(struct device *dev, struct device *parent) | ||
478 | { | ||
479 | struct kobject *kobj; | ||
480 | kobj = get_device_parent(dev, parent); | ||
481 | if (IS_ERR(kobj)) | ||
482 | return PTR_ERR(kobj); | ||
483 | if (kobj) | ||
484 | dev->kobj.parent = kobj; | ||
434 | return 0; | 485 | return 0; |
435 | } | 486 | } |
436 | #endif | ||
437 | 487 | ||
438 | /** | 488 | /** |
439 | * device_add - add device to device hierarchy. | 489 | * device_add - add device to device hierarchy. |
@@ -520,9 +570,13 @@ int device_add(struct device *dev) | |||
520 | &dev->kobj, dev->bus_id); | 570 | &dev->kobj, dev->bus_id); |
521 | #ifdef CONFIG_SYSFS_DEPRECATED | 571 | #ifdef CONFIG_SYSFS_DEPRECATED |
522 | if (parent) { | 572 | if (parent) { |
523 | sysfs_create_link(&dev->kobj, &dev->parent->kobj, "device"); | 573 | sysfs_create_link(&dev->kobj, &dev->parent->kobj, |
524 | class_name = make_class_name(dev->class->name, &dev->kobj); | 574 | "device"); |
525 | sysfs_create_link(&dev->parent->kobj, &dev->kobj, class_name); | 575 | class_name = make_class_name(dev->class->name, |
576 | &dev->kobj); | ||
577 | if (class_name) | ||
578 | sysfs_create_link(&dev->parent->kobj, | ||
579 | &dev->kobj, class_name); | ||
526 | } | 580 | } |
527 | #endif | 581 | #endif |
528 | } | 582 | } |
@@ -535,7 +589,8 @@ int device_add(struct device *dev) | |||
535 | goto PMError; | 589 | goto PMError; |
536 | if ((error = bus_add_device(dev))) | 590 | if ((error = bus_add_device(dev))) |
537 | goto BusError; | 591 | goto BusError; |
538 | kobject_uevent(&dev->kobj, KOBJ_ADD); | 592 | if (!dev->uevent_suppress) |
593 | kobject_uevent(&dev->kobj, KOBJ_ADD); | ||
539 | if ((error = bus_attach_device(dev))) | 594 | if ((error = bus_attach_device(dev))) |
540 | goto AttachError; | 595 | goto AttachError; |
541 | if (parent) | 596 | if (parent) |
@@ -665,7 +720,9 @@ void device_del(struct device * dev) | |||
665 | if (parent) { | 720 | if (parent) { |
666 | char *class_name = make_class_name(dev->class->name, | 721 | char *class_name = make_class_name(dev->class->name, |
667 | &dev->kobj); | 722 | &dev->kobj); |
668 | sysfs_remove_link(&dev->parent->kobj, class_name); | 723 | if (class_name) |
724 | sysfs_remove_link(&dev->parent->kobj, | ||
725 | class_name); | ||
669 | kfree(class_name); | 726 | kfree(class_name); |
670 | sysfs_remove_link(&dev->kobj, "device"); | 727 | sysfs_remove_link(&dev->kobj, "device"); |
671 | } | 728 | } |
@@ -968,20 +1025,25 @@ static int device_move_class_links(struct device *dev, | |||
968 | 1025 | ||
969 | class_name = make_class_name(dev->class->name, &dev->kobj); | 1026 | class_name = make_class_name(dev->class->name, &dev->kobj); |
970 | if (!class_name) { | 1027 | if (!class_name) { |
971 | error = PTR_ERR(class_name); | 1028 | error = -ENOMEM; |
972 | class_name = NULL; | ||
973 | goto out; | 1029 | goto out; |
974 | } | 1030 | } |
975 | if (old_parent) { | 1031 | if (old_parent) { |
976 | sysfs_remove_link(&dev->kobj, "device"); | 1032 | sysfs_remove_link(&dev->kobj, "device"); |
977 | sysfs_remove_link(&old_parent->kobj, class_name); | 1033 | sysfs_remove_link(&old_parent->kobj, class_name); |
978 | } | 1034 | } |
979 | error = sysfs_create_link(&dev->kobj, &new_parent->kobj, "device"); | 1035 | if (new_parent) { |
980 | if (error) | 1036 | error = sysfs_create_link(&dev->kobj, &new_parent->kobj, |
981 | goto out; | 1037 | "device"); |
982 | error = sysfs_create_link(&new_parent->kobj, &dev->kobj, class_name); | 1038 | if (error) |
983 | if (error) | 1039 | goto out; |
984 | sysfs_remove_link(&dev->kobj, "device"); | 1040 | error = sysfs_create_link(&new_parent->kobj, &dev->kobj, |
1041 | class_name); | ||
1042 | if (error) | ||
1043 | sysfs_remove_link(&dev->kobj, "device"); | ||
1044 | } | ||
1045 | else | ||
1046 | error = 0; | ||
985 | out: | 1047 | out: |
986 | kfree(class_name); | 1048 | kfree(class_name); |
987 | return error; | 1049 | return error; |
@@ -993,29 +1055,28 @@ out: | |||
993 | /** | 1055 | /** |
994 | * device_move - moves a device to a new parent | 1056 | * device_move - moves a device to a new parent |
995 | * @dev: the pointer to the struct device to be moved | 1057 | * @dev: the pointer to the struct device to be moved |
996 | * @new_parent: the new parent of the device | 1058 | * @new_parent: the new parent of the device (can by NULL) |
997 | */ | 1059 | */ |
998 | int device_move(struct device *dev, struct device *new_parent) | 1060 | int device_move(struct device *dev, struct device *new_parent) |
999 | { | 1061 | { |
1000 | int error; | 1062 | int error; |
1001 | struct device *old_parent; | 1063 | struct device *old_parent; |
1064 | struct kobject *new_parent_kobj; | ||
1002 | 1065 | ||
1003 | dev = get_device(dev); | 1066 | dev = get_device(dev); |
1004 | if (!dev) | 1067 | if (!dev) |
1005 | return -EINVAL; | 1068 | return -EINVAL; |
1006 | 1069 | ||
1007 | if (!device_is_registered(dev)) { | ||
1008 | error = -EINVAL; | ||
1009 | goto out; | ||
1010 | } | ||
1011 | new_parent = get_device(new_parent); | 1070 | new_parent = get_device(new_parent); |
1012 | if (!new_parent) { | 1071 | new_parent_kobj = get_device_parent (dev, new_parent); |
1013 | error = -EINVAL; | 1072 | if (IS_ERR(new_parent_kobj)) { |
1073 | error = PTR_ERR(new_parent_kobj); | ||
1074 | put_device(new_parent); | ||
1014 | goto out; | 1075 | goto out; |
1015 | } | 1076 | } |
1016 | pr_debug("DEVICE: moving '%s' to '%s'\n", dev->bus_id, | 1077 | pr_debug("DEVICE: moving '%s' to '%s'\n", dev->bus_id, |
1017 | new_parent->bus_id); | 1078 | new_parent ? new_parent->bus_id : "<NULL>"); |
1018 | error = kobject_move(&dev->kobj, &new_parent->kobj); | 1079 | error = kobject_move(&dev->kobj, new_parent_kobj); |
1019 | if (error) { | 1080 | if (error) { |
1020 | put_device(new_parent); | 1081 | put_device(new_parent); |
1021 | goto out; | 1082 | goto out; |
@@ -1024,7 +1085,8 @@ int device_move(struct device *dev, struct device *new_parent) | |||
1024 | dev->parent = new_parent; | 1085 | dev->parent = new_parent; |
1025 | if (old_parent) | 1086 | if (old_parent) |
1026 | klist_remove(&dev->knode_parent); | 1087 | klist_remove(&dev->knode_parent); |
1027 | klist_add_tail(&dev->knode_parent, &new_parent->klist_children); | 1088 | if (new_parent) |
1089 | klist_add_tail(&dev->knode_parent, &new_parent->klist_children); | ||
1028 | if (!dev->class) | 1090 | if (!dev->class) |
1029 | goto out_put; | 1091 | goto out_put; |
1030 | error = device_move_class_links(dev, old_parent, new_parent); | 1092 | error = device_move_class_links(dev, old_parent, new_parent); |
@@ -1032,7 +1094,8 @@ int device_move(struct device *dev, struct device *new_parent) | |||
1032 | /* We ignore errors on cleanup since we're hosed anyway... */ | 1094 | /* We ignore errors on cleanup since we're hosed anyway... */ |
1033 | device_move_class_links(dev, new_parent, old_parent); | 1095 | device_move_class_links(dev, new_parent, old_parent); |
1034 | if (!kobject_move(&dev->kobj, &old_parent->kobj)) { | 1096 | if (!kobject_move(&dev->kobj, &old_parent->kobj)) { |
1035 | klist_remove(&dev->knode_parent); | 1097 | if (new_parent) |
1098 | klist_remove(&dev->knode_parent); | ||
1036 | if (old_parent) | 1099 | if (old_parent) |
1037 | klist_add_tail(&dev->knode_parent, | 1100 | klist_add_tail(&dev->knode_parent, |
1038 | &old_parent->klist_children); | 1101 | &old_parent->klist_children); |
diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 510e7884975f..b5bf243d9cd6 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c | |||
@@ -86,8 +86,12 @@ static void driver_sysfs_remove(struct device *dev) | |||
86 | */ | 86 | */ |
87 | int device_bind_driver(struct device *dev) | 87 | int device_bind_driver(struct device *dev) |
88 | { | 88 | { |
89 | driver_bound(dev); | 89 | int ret; |
90 | return driver_sysfs_add(dev); | 90 | |
91 | ret = driver_sysfs_add(dev); | ||
92 | if (!ret) | ||
93 | driver_bound(dev); | ||
94 | return ret; | ||
91 | } | 95 | } |
92 | 96 | ||
93 | struct stupid_thread_structure { | 97 | struct stupid_thread_structure { |
@@ -136,18 +140,17 @@ probe_failed: | |||
136 | driver_sysfs_remove(dev); | 140 | driver_sysfs_remove(dev); |
137 | dev->driver = NULL; | 141 | dev->driver = NULL; |
138 | 142 | ||
139 | if (ret == -ENODEV || ret == -ENXIO) { | 143 | if (ret != -ENODEV && ret != -ENXIO) { |
140 | /* Driver matched, but didn't support device | ||
141 | * or device not found. | ||
142 | * Not an error; keep going. | ||
143 | */ | ||
144 | ret = 0; | ||
145 | } else { | ||
146 | /* driver matched but the probe failed */ | 144 | /* driver matched but the probe failed */ |
147 | printk(KERN_WARNING | 145 | printk(KERN_WARNING |
148 | "%s: probe of %s failed with error %d\n", | 146 | "%s: probe of %s failed with error %d\n", |
149 | drv->name, dev->bus_id, ret); | 147 | drv->name, dev->bus_id, ret); |
150 | } | 148 | } |
149 | /* | ||
150 | * Ignore errors returned by ->probe so that the next driver can try | ||
151 | * its luck. | ||
152 | */ | ||
153 | ret = 0; | ||
151 | done: | 154 | done: |
152 | kfree(data); | 155 | kfree(data); |
153 | atomic_dec(&probe_count); | 156 | atomic_dec(&probe_count); |
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 64558f45e6bc..c0a979a5074b 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c | |||
@@ -35,7 +35,7 @@ enum { | |||
35 | FW_STATUS_READY_NOHOTPLUG, | 35 | FW_STATUS_READY_NOHOTPLUG, |
36 | }; | 36 | }; |
37 | 37 | ||
38 | static int loading_timeout = 10; /* In seconds */ | 38 | static int loading_timeout = 60; /* In seconds */ |
39 | 39 | ||
40 | /* fw_lock could be moved to 'struct firmware_priv' but since it is just | 40 | /* fw_lock could be moved to 'struct firmware_priv' but since it is just |
41 | * guarding for corner cases a global lock should be OK */ | 41 | * guarding for corner cases a global lock should be OK */ |
diff --git a/drivers/base/platform.c b/drivers/base/platform.c index f9c903ba9fcd..30480f6f2af2 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c | |||
@@ -611,8 +611,15 @@ EXPORT_SYMBOL_GPL(platform_bus_type); | |||
611 | 611 | ||
612 | int __init platform_bus_init(void) | 612 | int __init platform_bus_init(void) |
613 | { | 613 | { |
614 | device_register(&platform_bus); | 614 | int error; |
615 | return bus_register(&platform_bus_type); | 615 | |
616 | error = device_register(&platform_bus); | ||
617 | if (error) | ||
618 | return error; | ||
619 | error = bus_register(&platform_bus_type); | ||
620 | if (error) | ||
621 | device_unregister(&platform_bus); | ||
622 | return error; | ||
616 | } | 623 | } |
617 | 624 | ||
618 | #ifndef ARCH_HAS_DMA_GET_REQUIRED_MASK | 625 | #ifndef ARCH_HAS_DMA_GET_REQUIRED_MASK |