diff options
author | Sebastian Ott <sebott@linux.vnet.ibm.com> | 2012-05-15 17:49:12 +0200 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2012-05-16 14:42:46 +0200 |
commit | f2962dae0efd81fed06d0687f300725ab063587a (patch) | |
tree | 35ffb7fcbc9466e80e29da10e52ca82ab06dd3df | |
parent | eda0c6d6b04d3cf72f5e8d656e39bffe3568e6db (diff) | |
download | op-kernel-dev-f2962dae0efd81fed06d0687f300725ab063587a.zip op-kernel-dev-f2962dae0efd81fed06d0687f300725ab063587a.tar.gz |
s390/ccwgroup: introduce ccwgroup_create_dev
Add a new interface for drivers to create a group device. Via the old
interface ccwgroup_create_from_string we would create a virtual device
in a way that only the caller of this function would match and bind to.
Via the new ccwgroup_create_dev we stop playing games with the driver
core and directly set the driver of the new group device. For drivers
which have todo additional setup steps (like setting driver_data)
provide a new setup driver callback.
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r-- | arch/s390/include/asm/ccwgroup.h | 5 | ||||
-rw-r--r-- | drivers/s390/cio/ccwgroup.c | 54 |
2 files changed, 50 insertions, 9 deletions
diff --git a/arch/s390/include/asm/ccwgroup.h b/arch/s390/include/asm/ccwgroup.h index f2ea2c5..f5cfb79 100644 --- a/arch/s390/include/asm/ccwgroup.h +++ b/arch/s390/include/asm/ccwgroup.h @@ -31,6 +31,7 @@ struct ccwgroup_device { * struct ccwgroup_driver - driver for ccw group devices * @max_slaves: maximum number of slave devices * @driver_id: unique id + * @setup: function called during device creation to setup the device * @probe: function called on probe * @remove: function called on remove * @set_online: function called when device is set online @@ -47,6 +48,7 @@ struct ccwgroup_driver { int max_slaves; unsigned long driver_id; + int (*setup) (struct ccwgroup_device *); int (*probe) (struct ccwgroup_device *); void (*remove) (struct ccwgroup_device *); int (*set_online) (struct ccwgroup_device *); @@ -63,6 +65,9 @@ struct ccwgroup_driver { extern int ccwgroup_driver_register (struct ccwgroup_driver *cdriver); extern void ccwgroup_driver_unregister (struct ccwgroup_driver *cdriver); +int ccwgroup_create_dev(struct device *root, unsigned int creator_id, + struct ccw_driver *cdrv, struct ccwgroup_driver *gdrv, + int num_devices, const char *buf); int ccwgroup_create_from_string(struct device *root, unsigned int creator_id, struct ccw_driver *cdrv, int num_devices, const char *buf); diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index 5f1dc6f..0c7ed30 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c @@ -1,7 +1,7 @@ /* * bus driver for ccwgroup * - * Copyright IBM Corp. 2002, 2009 + * Copyright IBM Corp. 2002, 2012 * * Author(s): Arnd Bergmann (arndb@de.ibm.com) * Cornelia Huck (cornelia.huck@de.ibm.com) @@ -291,14 +291,15 @@ static int __is_valid_bus_id(char bus_id[CCW_BUS_ID_SIZE]) } /** - * ccwgroup_create_from_string() - create and register a ccw group device - * @root: parent device for the new device + * ccwgroup_create_dev() - create and register a ccw group device + * @parent: parent device for the new device * @creator_id: identifier of creating driver * @cdrv: ccw driver of slave devices + * @gdrv: driver for the new group device * @num_devices: number of slave devices * @buf: buffer containing comma separated bus ids of slave devices * - * Create and register a new ccw group device as a child of @root. Slave + * Create and register a new ccw group device as a child of @parent. Slave * devices are obtained from the list of bus ids given in @buf and must all * belong to @cdrv. * Returns: @@ -306,9 +307,9 @@ static int __is_valid_bus_id(char bus_id[CCW_BUS_ID_SIZE]) * Context: * non-atomic */ -int ccwgroup_create_from_string(struct device *root, unsigned int creator_id, - struct ccw_driver *cdrv, int num_devices, - const char *buf) +int ccwgroup_create_dev(struct device *parent, unsigned int creator_id, + struct ccw_driver *cdrv, struct ccwgroup_driver *gdrv, + int num_devices, const char *buf) { struct ccwgroup_device *gdev; int rc, i; @@ -323,10 +324,13 @@ int ccwgroup_create_from_string(struct device *root, unsigned int creator_id, atomic_set(&gdev->onoff, 0); mutex_init(&gdev->reg_mutex); mutex_lock(&gdev->reg_mutex); - gdev->creator_id = creator_id; + if (gdrv) + gdev->creator_id = gdrv->driver_id; + else + gdev->creator_id = creator_id; gdev->count = num_devices; gdev->dev.bus = &ccwgroup_bus_type; - gdev->dev.parent = root; + gdev->dev.parent = parent; gdev->dev.release = ccwgroup_release; device_initialize(&gdev->dev); @@ -373,6 +377,13 @@ int ccwgroup_create_from_string(struct device *root, unsigned int creator_id, dev_set_name(&gdev->dev, "%s", dev_name(&gdev->cdev[0]->dev)); gdev->dev.groups = ccwgroup_attr_groups; + + if (gdrv) { + gdev->dev.driver = &gdrv->driver; + rc = gdrv->setup ? gdrv->setup(gdev) : 0; + if (rc) + goto error; + } rc = device_add(&gdev->dev); if (rc) goto error; @@ -397,6 +408,31 @@ error: put_device(&gdev->dev); return rc; } +EXPORT_SYMBOL(ccwgroup_create_dev); + +/** + * ccwgroup_create_from_string() - create and register a ccw group device + * @root: parent device for the new device + * @creator_id: identifier of creating driver + * @cdrv: ccw driver of slave devices + * @num_devices: number of slave devices + * @buf: buffer containing comma separated bus ids of slave devices + * + * Create and register a new ccw group device as a child of @root. Slave + * devices are obtained from the list of bus ids given in @buf and must all + * belong to @cdrv. + * Returns: + * %0 on success and an error code on failure. + * Context: + * non-atomic + */ +int ccwgroup_create_from_string(struct device *root, unsigned int creator_id, + struct ccw_driver *cdrv, int num_devices, + const char *buf) +{ + return ccwgroup_create_dev(root, creator_id, cdrv, NULL, + num_devices, buf); +} EXPORT_SYMBOL(ccwgroup_create_from_string); static int ccwgroup_notifier(struct notifier_block *nb, unsigned long action, |