bk://kernel.bkbits.net/gregkh/linux/driver-2.6
dtor_core@ameritech.net|ChangeSet|20040708234647|23132 dtor_core

# This is a BitKeeper generated diff -Nru style patch.
#
# drivers/pci/hotplug/rpaphp_vio.c
#   2004/07/07 17:55:49-07:00 dtor_core@ameritech.net +8 -1
#   Driver core: kset_find_obj should increment refcount of the found object
# 
# lib/kobject.c
#   2004/07/07 17:55:49-07:00 dtor_core@ameritech.net +4 -3
#   Driver core: kset_find_obj should increment refcount of the found object
# 
# ChangeSet
#   2004/07/08 16:46:47-07:00 dtor_core@ameritech.net 
#   [PATCH] Driver core: add driver_find helper to find a driver by its name
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# include/linux/device.h
#   2004/07/07 17:56:21-07:00 dtor_core@ameritech.net +1 -0
#   Driver core: add driver_find helper to find a driver by its name
# 
# drivers/base/driver.c
#   2004/07/07 17:56:21-07:00 dtor_core@ameritech.net +19 -0
#   Driver core: add driver_find helper to find a driver by its name
# 
# ChangeSet
#   2004/07/08 16:46:10-07:00 dtor_core@ameritech.net 
#   [PATCH] Driver core: kset_find_obj should increment refcount of the found object
#   
#   kset_find_obj should increment refcount of the found object so users of
#   the function can safely use returned object
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/base/core.c
#   2004/07/07 17:55:49-07:00 dtor_core@ameritech.net +10 -0
#   Driver core: kset_find_obj should increment refcount of the found object
# 
# drivers/base/bus.c
#   2004/07/07 17:55:49-07:00 dtor_core@ameritech.net +2 -0
#   Driver core: kset_find_obj should increment refcount of the found object
# 
# ChangeSet
#   2004/07/08 16:41:56-07:00 dtor_core@ameritech.net 
#   [PATCH] Driver core: add default driver attributes to struct bus_type
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# include/linux/device.h
#   2004/07/07 16:56:42-07:00 dtor_core@ameritech.net +1 -0
#   Driver core: add default driver attributes to struct bus_type
# 
# drivers/base/bus.c
#   2004/07/07 16:56:42-07:00 dtor_core@ameritech.net +35 -2
#   Driver core: add default driver attributes to struct bus_type
# 
# ChangeSet
#   2004/07/08 16:40:09-07:00 dtor_core@ameritech.net 
#   [PATCH] Driver core: add platform_device_register_simple to register platform
#   
#   Add platform_device_register_simple to register platform devices
#   requiring minimal resource and memory management.  The device
#   will have standard release function that just frees memory
#   occupied by the platform device. By having release function in
#   the driver core modules using such devices can be unloaded
#   without waiting for the last reference to the device to be
#   dropped.
#   
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# include/linux/device.h
#   2004/07/07 16:28:03-07:00 dtor_core@ameritech.net +2 -0
#   Driver core: add platform_device_register_simple to register platform
# 
# drivers/base/platform.c
#   2004/07/07 16:28:03-07:00 dtor_core@ameritech.net +68 -0
#   Driver core: add platform_device_register_simple to register platform
# 
# ChangeSet
#   2004/06/30 09:59:10-07:00 greg@kroah.com 
#   Driver Core: remove extra space in Kconfig file.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/base/Kconfig
#   2004/06/30 09:58:53-07:00 greg@kroah.com +1 -1
#   Driver Core: remove extra space in Kconfig file.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# ChangeSet
#   2004/06/22 16:24:54-07:00 akpm@osdl.org 
#   [PATCH] raw.c cleanups
#   
#   - pass the raw_config_request by reference, not by value.
#   
#   - fix whitespace drainbamage
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/char/raw.c
#   2004/06/22 08:01:30-07:00 akpm@osdl.org +8 -7
#   raw.c cleanups
# 
diff -Nru a/drivers/base/Kconfig b/drivers/base/Kconfig
--- a/drivers/base/Kconfig	2004-07-08 18:13:19 -07:00
+++ b/drivers/base/Kconfig	2004-07-08 18:13:19 -07:00
@@ -18,7 +18,7 @@
 	  the kernel tree does.
 
 config DEBUG_DRIVER
-	 bool "Driver Core verbose debug messages"
+	bool "Driver Core verbose debug messages"
 	depends on DEBUG_KERNEL
 	help
 	  Say Y here if you want the Driver core to produce a bunch of
diff -Nru a/drivers/base/bus.c b/drivers/base/bus.c
--- a/drivers/base/bus.c	2004-07-08 18:13:19 -07:00
+++ b/drivers/base/bus.c	2004-07-08 18:13:19 -07:00
@@ -415,7 +415,7 @@
 static void device_remove_attrs(struct bus_type * bus, struct device * dev)
 {
 	int i;
-	
+
 	if (bus->dev_attrs) {
 		for (i = 0; attr_name(bus->dev_attrs[i]); i++)
 			device_remove_file(dev,&bus->dev_attrs[i]);
@@ -471,6 +471,37 @@
 	}
 }
 
+static int driver_add_attrs(struct bus_type * bus, struct device_driver * drv)
+{
+	int error = 0;
+	int i;
+
+	if (bus->drv_attrs) {
+		for (i = 0; attr_name(bus->drv_attrs[i]); i++) {
+			error = driver_create_file(drv, &bus->drv_attrs[i]);
+			if (error)
+				goto Err;
+		}
+	}
+ Done:
+	return error;
+ Err:
+	while (--i >= 0)
+		driver_remove_file(drv, &bus->drv_attrs[i]);
+	goto Done;
+}
+
+
+static void driver_remove_attrs(struct bus_type * bus, struct device_driver * drv)
+{
+	int i;
+
+	if (bus->drv_attrs) {
+		for (i = 0; attr_name(bus->drv_attrs[i]); i++)
+			driver_remove_file(drv, &bus->drv_attrs[i]);
+	}
+}
+
 
 /**
  *	bus_add_driver - Add a driver to the bus.
@@ -499,6 +530,7 @@
 		driver_attach(drv);
 		up_write(&bus->subsys.rwsem);
 
+		driver_add_attrs(bus, drv);
 	}
 	return error;
 }
@@ -516,6 +548,7 @@
 void bus_remove_driver(struct device_driver * drv)
 {
 	if (drv->bus) {
+		driver_remove_attrs(drv->bus, drv);
 		down_write(&drv->bus->subsys.rwsem);
 		pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name);
 		driver_detach(drv);
@@ -574,6 +607,8 @@
  *
  *	Call kset_find_obj() to iterate over list of buses to
  *	find a bus by name. Return bus if found.
+ *
+ *	Note that kset_find_obj increments bus' reference count.
  */
 
 struct bus_type * find_bus(char * name)
@@ -610,7 +645,7 @@
 static void bus_remove_attrs(struct bus_type * bus)
 {
 	int i;
-	
+
 	if (bus->bus_attrs) {
 		for (i = 0; attr_name(bus->bus_attrs[i]); i++)
 			bus_remove_file(bus,&bus->bus_attrs[i]);
diff -Nru a/drivers/base/core.c b/drivers/base/core.c
--- a/drivers/base/core.c	2004-07-08 18:13:19 -07:00
+++ b/drivers/base/core.c	2004-07-08 18:13:19 -07:00
@@ -378,6 +378,16 @@
 	return error;
 }
 
+/**
+ *	device_find - locate device on a bus by name.
+ *	@name:	name of the device.
+ *	@bus:	bus to scan for the device.
+ *
+ *	Call kset_find_obj() to iterate over list of devices on
+ *	a bus to find device by name. Return device if found.
+ *
+ *	Note that kset_find_obj increments device's reference count.
+ */
 struct device *device_find(const char *name, struct bus_type *bus)
 {
 	struct kobject *k = kset_find_obj(&bus->devices, name);
diff -Nru a/drivers/base/driver.c b/drivers/base/driver.c
--- a/drivers/base/driver.c	2004-07-08 18:13:19 -07:00
+++ b/drivers/base/driver.c	2004-07-08 18:13:19 -07:00
@@ -111,10 +111,29 @@
 	up(&drv->unload_sem);
 }
 
+/**
+ *	driver_find - locate driver on a bus by its name.
+ *	@name:	name of the driver.
+ *	@bus:	bus to scan for the driver.
+ *
+ *	Call kset_find_obj() to iterate over list of drivers on
+ *	a bus to find driver by name. Return driver if found.
+ *
+ *	Note that kset_find_obj increments driver's reference count.
+ */
+struct device_driver *driver_find(const char *name, struct bus_type *bus)
+{
+	struct kobject *k = kset_find_obj(&bus->drivers, name);
+	if (k)
+		return to_drv(k);
+	return NULL;
+}
+
 EXPORT_SYMBOL(driver_register);
 EXPORT_SYMBOL(driver_unregister);
 EXPORT_SYMBOL(get_driver);
 EXPORT_SYMBOL(put_driver);
+EXPORT_SYMBOL(driver_find);
 
 EXPORT_SYMBOL(driver_create_file);
 EXPORT_SYMBOL(driver_remove_file);
diff -Nru a/drivers/base/platform.c b/drivers/base/platform.c
--- a/drivers/base/platform.c	2004-07-08 18:13:19 -07:00
+++ b/drivers/base/platform.c	2004-07-08 18:13:19 -07:00
@@ -15,6 +15,7 @@
 #include <linux/init.h>
 #include <linux/dma-mapping.h>
 #include <linux/bootmem.h>
+#include <linux/err.h>
 
 struct device platform_bus = {
 	.bus_id		= "platform",
@@ -133,6 +134,13 @@
 	return ret;
 }
 
+/**
+ *	platform_device_unregister - remove a platform-level device
+ *	@dev:	platform device we're removing
+ *
+ *	Note that this function will also release all memory- and port-based
+ *	resources owned by the device (@dev->resource).
+ */
 void platform_device_unregister(struct platform_device * pdev)
 {
 	int i;
@@ -148,6 +156,65 @@
 	}
 }
 
+struct platform_object {
+        struct platform_device pdev;
+        struct resource resources[0];
+};
+
+static void platform_device_release_simple(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+
+	kfree(container_of(pdev, struct platform_object, pdev));
+}
+
+/**
+ *	platform_device_register_simple
+ *	@name:  base name of the device we're adding
+ *	@id:    instance id
+ *	@res:   set of resources that needs to be allocated for the device
+ *	@num:	number of resources
+ *
+ *	This function creates a simple platform device that requires minimal
+ *	resource and memory management. Canned release function freeing
+ *	memory allocated for the device allows drivers using such devices
+ *	to be unloaded iwithout waiting for the last reference to the device
+ *	to be dropped.
+ */
+struct platform_device *platform_device_register_simple(char *name, unsigned int id,
+							struct resource *res, unsigned int num)
+{
+	struct platform_object *pobj;
+	int retval;
+
+	pobj = kmalloc(sizeof(struct platform_object) + sizeof(struct resource) * num, GFP_KERNEL);
+	if (!pobj) {
+		retval = -ENOMEM;
+		goto error;
+	}
+
+	memset(pobj, 0, sizeof(*pobj));
+	pobj->pdev.name = name;
+	pobj->pdev.id = id;
+	pobj->pdev.dev.release = platform_device_release_simple;
+
+	if (num) {
+		memcpy(pobj->resources, res, sizeof(struct resource) * num);
+		pobj->pdev.resource = pobj->resources;
+		pobj->pdev.num_resources = num;
+	}
+
+	retval = platform_device_register(&pobj->pdev);
+	if (retval)
+		goto error;
+
+	return &pobj->pdev;
+
+error:
+	kfree(pobj);
+	return ERR_PTR(retval);
+}
+
 
 /**
  *	platform_match - bind platform device to platform driver.
@@ -237,6 +304,7 @@
 EXPORT_SYMBOL(platform_bus);
 EXPORT_SYMBOL(platform_bus_type);
 EXPORT_SYMBOL(platform_device_register);
+EXPORT_SYMBOL(platform_device_register_simple);
 EXPORT_SYMBOL(platform_device_unregister);
 EXPORT_SYMBOL(platform_get_irq);
 EXPORT_SYMBOL(platform_get_resource);
diff -Nru a/drivers/char/raw.c b/drivers/char/raw.c
--- a/drivers/char/raw.c	2004-07-08 18:13:19 -07:00
+++ b/drivers/char/raw.c	2004-07-08 18:13:19 -07:00
@@ -125,11 +125,11 @@
 	return ioctl_by_bdev(bdev, command, arg);
 }
 
-static void bind_device(struct raw_config_request rq)
+static void bind_device(struct raw_config_request *rq)
 {
-	class_simple_device_remove(MKDEV(RAW_MAJOR, rq.raw_minor));
-	class_simple_device_add(raw_class, MKDEV(RAW_MAJOR, rq.raw_minor),
-				      NULL, "raw%d", rq.raw_minor);
+	class_simple_device_remove(MKDEV(RAW_MAJOR, rq->raw_minor));
+	class_simple_device_add(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor),
+				      NULL, "raw%d", rq->raw_minor);
 }
 
 /*
@@ -200,15 +200,16 @@
 			if (rq.block_major == 0 && rq.block_minor == 0) {
 				/* unbind */
 				rawdev->binding = NULL;
-				class_simple_device_remove(MKDEV(RAW_MAJOR, rq.raw_minor));
+				class_simple_device_remove(MKDEV(RAW_MAJOR,
+								rq.raw_minor));
 			} else {
 				rawdev->binding = bdget(dev);
 				if (rawdev->binding == NULL)
 					err = -ENOMEM;
 				else {
 					__module_get(THIS_MODULE);
-					bind_device(rq);
-					}
+					bind_device(&rq);
+				}
 			}
 			up(&raw_mutex);
 		} else {
diff -Nru a/drivers/pci/hotplug/rpaphp_vio.c b/drivers/pci/hotplug/rpaphp_vio.c
--- a/drivers/pci/hotplug/rpaphp_vio.c	2004-07-08 18:13:19 -07:00
+++ b/drivers/pci/hotplug/rpaphp_vio.c	2004-07-08 18:13:19 -07:00
@@ -86,7 +86,14 @@
 	}
 	slot->dev_type = VIO_DEV;
 	slot->dev.vio_dev = vio_find_node(dn);
-	if (!slot->dev.vio_dev)
+	if (slot->dev.vio_dev) {
+		/*
+		 * rpaphp is the only owner of vio devices and
+		 * does not need extra reference taken by
+		 * vio_find_node
+		 */
+		put_device(&slot->dev.vio_dev->dev);
+	} else
 		slot->dev.vio_dev = vio_register_device_node(dn);
 	if (slot->dev.vio_dev)
 		slot->state = CONFIGURED;
diff -Nru a/include/linux/device.h b/include/linux/device.h
--- a/include/linux/device.h	2004-07-08 18:13:19 -07:00
+++ b/include/linux/device.h	2004-07-08 18:13:19 -07:00
@@ -56,6 +56,7 @@
 
 	struct bus_attribute	* bus_attrs;
 	struct device_attribute	* dev_attrs;
+	struct driver_attribute	* drv_attrs;
 
 	int		(*match)(struct device * dev, struct device_driver * drv);
 	struct device * (*add)	(struct device * parent, char * bus_id);
@@ -119,6 +120,7 @@
 
 extern struct device_driver * get_driver(struct device_driver * drv);
 extern void put_driver(struct device_driver * drv);
+extern struct device_driver *driver_find(const char *name, struct bus_type *bus);
 
 
 /* driverfs interface for exporting driver attributes */
@@ -380,6 +382,8 @@
 extern struct resource *platform_get_resource(struct platform_device *, unsigned int, unsigned int);
 extern int platform_get_irq(struct platform_device *, unsigned int);
 extern int platform_add_devices(struct platform_device **, int);
+
+extern struct platform_device *platform_device_register_simple(char *, unsigned int, struct resource *, unsigned int);
 
 /* drivers/base/power.c */
 extern void device_shutdown(void);
diff -Nru a/lib/kobject.c b/lib/kobject.c
--- a/lib/kobject.c	2004-07-08 18:13:19 -07:00
+++ b/lib/kobject.c	2004-07-08 18:13:19 -07:00
@@ -537,7 +537,8 @@
  *	@name:	object's name.
  *
  *	Lock kset via @kset->subsys, and iterate over @kset->list,
- *	looking for a matching kobject. Return object if found.
+ *	looking for a matching kobject. If matching object is found
+ *	take a reference and return the object.
  */
 
 struct kobject * kset_find_obj(struct kset * kset, const char * name)
@@ -548,8 +549,8 @@
 	down_read(&kset->subsys->rwsem);
 	list_for_each(entry,&kset->list) {
 		struct kobject * k = to_kobj(entry);
-		if (kobject_name(k) && (!strcmp(kobject_name(k),name))) {
-			ret = k;
+		if (kobject_name(k) && !strcmp(kobject_name(k),name)) {
+			ret = kobject_get(k);
 			break;
 		}
 	}