summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Ott <sebott@linux.vnet.ibm.com>2012-05-15 17:49:12 +0200
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2012-05-16 14:42:46 +0200
commitf2962dae0efd81fed06d0687f300725ab063587a (patch)
tree35ffb7fcbc9466e80e29da10e52ca82ab06dd3df
parenteda0c6d6b04d3cf72f5e8d656e39bffe3568e6db (diff)
downloadlinux-3.10-f2962dae0efd81fed06d0687f300725ab063587a.tar.gz
linux-3.10-f2962dae0efd81fed06d0687f300725ab063587a.tar.bz2
linux-3.10-f2962dae0efd81fed06d0687f300725ab063587a.zip
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.h5
-rw-r--r--drivers/s390/cio/ccwgroup.c54
2 files changed, 50 insertions, 9 deletions
diff --git a/arch/s390/include/asm/ccwgroup.h b/arch/s390/include/asm/ccwgroup.h
index f2ea2c56a7e..f5cfb792586 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 5f1dc6fb570..0c7ed30ac87 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,