Browse Source

[PATCH] driver core: fix built-in drivers sysfs links

built-in drivers had broken sysfs links that caused bootup hangs for
certain driver unregistry sequences.

Signed-off-by: Ingo Molnar <mingo@elte.hu>
Acked-by: Kay Sievers <kay.sievers@vrfy.org>
Signed-off-by: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Kay Sievers 18 years ago
parent
commit
0c84ce268b
2 changed files with 15 additions and 4 deletions
  1. 1 0
      include/linux/device.h
  2. 14 4
      kernel/module.c

+ 1 - 0
include/linux/device.h

@@ -128,6 +128,7 @@ struct device_driver {
 
 
 	struct module		* owner;
 	struct module		* owner;
 	const char 		* mod_name;	/* used for built-in modules */
 	const char 		* mod_name;	/* used for built-in modules */
+	struct module_kobject	* mkobj;
 
 
 	int	(*probe)	(struct device * dev);
 	int	(*probe)	(struct device * dev);
 	int	(*remove)	(struct device * dev);
 	int	(*remove)	(struct device * dev);

+ 14 - 4
kernel/module.c

@@ -2384,8 +2384,13 @@ void module_add_driver(struct module *mod, struct device_driver *drv)
 
 
 		/* Lookup built-in module entry in /sys/modules */
 		/* Lookup built-in module entry in /sys/modules */
 		mkobj = kset_find_obj(&module_subsys.kset, drv->mod_name);
 		mkobj = kset_find_obj(&module_subsys.kset, drv->mod_name);
-		if (mkobj)
+		if (mkobj) {
 			mk = container_of(mkobj, struct module_kobject, kobj);
 			mk = container_of(mkobj, struct module_kobject, kobj);
+			/* remember our module structure */
+			drv->mkobj = mk;
+			/* kset_find_obj took a reference */
+			kobject_put(mkobj);
+		}
 	}
 	}
 
 
 	if (!mk)
 	if (!mk)
@@ -2405,17 +2410,22 @@ EXPORT_SYMBOL(module_add_driver);
 
 
 void module_remove_driver(struct device_driver *drv)
 void module_remove_driver(struct device_driver *drv)
 {
 {
+	struct module_kobject *mk = NULL;
 	char *driver_name;
 	char *driver_name;
 
 
 	if (!drv)
 	if (!drv)
 		return;
 		return;
 
 
 	sysfs_remove_link(&drv->kobj, "module");
 	sysfs_remove_link(&drv->kobj, "module");
-	if (drv->owner && drv->owner->mkobj.drivers_dir) {
+
+	if (drv->owner)
+		mk = &drv->owner->mkobj;
+	else if (drv->mkobj)
+		mk = drv->mkobj;
+	if (mk && mk->drivers_dir) {
 		driver_name = make_driver_name(drv);
 		driver_name = make_driver_name(drv);
 		if (driver_name) {
 		if (driver_name) {
-			sysfs_remove_link(drv->owner->mkobj.drivers_dir,
-					  driver_name);
+			sysfs_remove_link(mk->drivers_dir, driver_name);
 			kfree(driver_name);
 			kfree(driver_name);
 		}
 		}
 	}
 	}