s390/ccwgroup: introduce ccwgroup_create_dev
authorSebastian Ott <sebott@linux.vnet.ibm.com>
Tue, 15 May 2012 15:49:12 +0000 (17:49 +0200)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Wed, 16 May 2012 12:42:46 +0000 (14:42 +0200)
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>
arch/s390/include/asm/ccwgroup.h
drivers/s390/cio/ccwgroup.c

index f2ea2c56a7e18866d2775513df1e2f3f48d5b0e7..f5cfb792586705d0527bad0453d5d4a24a660be2 100644 (file)
@@ -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);
index 5f1dc6fb5708b938765880a12722c3b70e0175a1..0c7ed30ac87e49d442999b196b75f01cb0b8eeed 100644 (file)
@@ -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,