Driver core updates (needed for serio)
Subsystems (5)
PATCH RESEND 1/4 Driver core updates (needed for serio)
Hi Greg,
Could you please take a look at the 4 patches below. I would like to finish synching up my serio sysfs patches with Vojtech and the rest of my stuff depends on these patches, so I would like to know if they are acceptable or I need to redo some of these.
The patches are:
01-platform-device-simple.patch
- Add platform_device_register_simple() that would register platform device that needs minimal resource management. The device will have release function in driver core so unloading is not a concern.
02-bus-driver-attr.patch
- Add default driver's attributes, similar to device's default attributes to make driver's and device's API in balance.
03-kset-find-obj-refcount.patch
- kset_find_obj should increment refcount of the found object, otherwise the object can disappear before caller has a chance to pin it down. Also document that find_bus and device_find now return respective objectw with refcount incremented. Adjust rpaphp_vio to drip the extra reference as it is not needed there.
04-driver-find.patch
- implement driver_find() function - the same as device_find but iterates over drivers registered on given bus. It is used by serio core to allow user manually rebind a driver to a port.
Everyhting has been rediffed against today's pull from Linus' tree.
Thanks!
Signature · 139 lines
Dmitry =================================================================== [email protected], 2004-07-07 18:08:36-05:00, [email protected] Driver core: 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. Suggested by Russell King Signed-off-by: Dmitry Torokhov <[email protected]> drivers/base/platform.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/device.h | 2 + 2 files changed, 70 insertions(+) =================================================================== diff -Nru a/drivers/base/platform.c b/drivers/base/platform.c --- a/drivers/base/platform.c 2004-07-07 18:28:03 -05:00 +++ b/drivers/base/platform.c 2004-07-07 18:28:03 -05: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/include/linux/device.h b/include/linux/device.h --- a/include/linux/device.h 2004-07-07 18:28:03 -05:00 +++ b/include/linux/device.h 2004-07-07 18:28:03 -05:00 @@ -381,6 +381,8 @@ 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);
PATCH RESEND 2/4 Driver core updates (needed for serio)
===================================================================
[email protected], 2004-07-07 18:15:23-05:00, [email protected]
Driver core: add default driver attributes to struct bus_type
drivers/base/bus.c | 37 +++++++++++++++++++++++++++++++++++-- include/linux/device.h | 1 + 2 files changed, 36 insertions(+), 2 deletions(-)
===================================================================
drivers/base/bus.c +35 -2
@@ -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);
@@ -610,7 +643,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]);
include/linux/device.h +1 -0
@@ -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);
PATCH RESEND 3/4 Driver core updates (needed for serio)
===================================================================
[email protected], 2004-07-07 18:16:59-05:00, [email protected]
Driver core: kset_find_obj should increment refcount of the found object
so users of the function can safely use returned object
drivers/base/bus.c | 2 ++ drivers/base/core.c | 10 ++++++++++ drivers/pci/hotplug/rpaphp_vio.c | 9 ++++++++- lib/kobject.c | 7 ++++--- 4 files changed, 24 insertions(+), 4 deletions(-)
===================================================================
drivers/base/bus.c +2 -0
@@ -607,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)
drivers/base/core.c +10 -0
@@ -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);
drivers/pci/hotplug/rpaphp_vio.c +8 -1
@@ -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 ;
lib/kobject.c +4 -3
@@ -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 ; } }
PATCH RESEND 4/4 Driver core updates (needed for serio)
===================================================================
[email protected], 2004-07-07 18:18:04-05:00, [email protected]
Driver core: add driver_find helper to find a driver by its name
drivers/base/driver.c | 19 +++++++++++++++++++ include/linux/device.h | 1 + 2 files changed, 20 insertions(+)
===================================================================
drivers/base/driver.c +19 -0
@@ -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);
include/linux/device.h +1 -0
@@ -120,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 */
Quoted 8 lines · Dmitry Torokhov
Hi Greg,
Could you please take a look at the 4 patches below. I would like to finish synching up my serio sysfs patches with Vojtech and the rest of my stuff depends on these patches, so I would like to know if they are acceptable or I need to redo some of these.
The patches are:
<snip>
All 4 of these patches look fine, and I've applied them to my trees, and they will show up in the next -mm tree, and in my next push of stuff to Linus.
thanks,
greg k-h