diff options
-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 f2ea2c56a7e1..f5cfb7925867 100644 --- a/arch/s390/include/asm/ccwgroup.h +++ b/arch/s390/include/asm/ccwgroup.h | |||
@@ -31,6 +31,7 @@ struct ccwgroup_device { | |||
31 | * struct ccwgroup_driver - driver for ccw group devices | 31 | * struct ccwgroup_driver - driver for ccw group devices |
32 | * @max_slaves: maximum number of slave devices | 32 | * @max_slaves: maximum number of slave devices |
33 | * @driver_id: unique id | 33 | * @driver_id: unique id |
34 | * @setup: function called during device creation to setup the device | ||
34 | * @probe: function called on probe | 35 | * @probe: function called on probe |
35 | * @remove: function called on remove | 36 | * @remove: function called on remove |
36 | * @set_online: function called when device is set online | 37 | * @set_online: function called when device is set online |
@@ -47,6 +48,7 @@ struct ccwgroup_driver { | |||
47 | int max_slaves; | 48 | int max_slaves; |
48 | unsigned long driver_id; | 49 | unsigned long driver_id; |
49 | 50 | ||
51 | int (*setup) (struct ccwgroup_device *); | ||
50 | int (*probe) (struct ccwgroup_device *); | 52 | int (*probe) (struct ccwgroup_device *); |
51 | void (*remove) (struct ccwgroup_device *); | 53 | void (*remove) (struct ccwgroup_device *); |
52 | int (*set_online) (struct ccwgroup_device *); | 54 | int (*set_online) (struct ccwgroup_device *); |
@@ -63,6 +65,9 @@ struct ccwgroup_driver { | |||
63 | 65 | ||
64 | extern int ccwgroup_driver_register (struct ccwgroup_driver *cdriver); | 66 | extern int ccwgroup_driver_register (struct ccwgroup_driver *cdriver); |
65 | extern void ccwgroup_driver_unregister (struct ccwgroup_driver *cdriver); | 67 | extern void ccwgroup_driver_unregister (struct ccwgroup_driver *cdriver); |
68 | int ccwgroup_create_dev(struct device *root, unsigned int creator_id, | ||
69 | struct ccw_driver *cdrv, struct ccwgroup_driver *gdrv, | ||
70 | int num_devices, const char *buf); | ||
66 | int ccwgroup_create_from_string(struct device *root, unsigned int creator_id, | 71 | int ccwgroup_create_from_string(struct device *root, unsigned int creator_id, |
67 | struct ccw_driver *cdrv, int num_devices, | 72 | struct ccw_driver *cdrv, int num_devices, |
68 | const char *buf); | 73 | const char *buf); |
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index 5f1dc6fb5708..0c7ed30ac87e 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * bus driver for ccwgroup | 2 | * bus driver for ccwgroup |
3 | * | 3 | * |
4 | * Copyright IBM Corp. 2002, 2009 | 4 | * Copyright IBM Corp. 2002, 2012 |
5 | * | 5 | * |
6 | * Author(s): Arnd Bergmann (arndb@de.ibm.com) | 6 | * Author(s): Arnd Bergmann (arndb@de.ibm.com) |
7 | * Cornelia Huck (cornelia.huck@de.ibm.com) | 7 | * Cornelia Huck (cornelia.huck@de.ibm.com) |
@@ -291,14 +291,15 @@ static int __is_valid_bus_id(char bus_id[CCW_BUS_ID_SIZE]) | |||
291 | } | 291 | } |
292 | 292 | ||
293 | /** | 293 | /** |
294 | * ccwgroup_create_from_string() - create and register a ccw group device | 294 | * ccwgroup_create_dev() - create and register a ccw group device |
295 | * @root: parent device for the new device | 295 | * @parent: parent device for the new device |
296 | * @creator_id: identifier of creating driver | 296 | * @creator_id: identifier of creating driver |
297 | * @cdrv: ccw driver of slave devices | 297 | * @cdrv: ccw driver of slave devices |
298 | * @gdrv: driver for the new group device | ||
298 | * @num_devices: number of slave devices | 299 | * @num_devices: number of slave devices |
299 | * @buf: buffer containing comma separated bus ids of slave devices | 300 | * @buf: buffer containing comma separated bus ids of slave devices |
300 | * | 301 | * |
301 | * Create and register a new ccw group device as a child of @root. Slave | 302 | * Create and register a new ccw group device as a child of @parent. Slave |
302 | * devices are obtained from the list of bus ids given in @buf and must all | 303 | * devices are obtained from the list of bus ids given in @buf and must all |
303 | * belong to @cdrv. | 304 | * belong to @cdrv. |
304 | * Returns: | 305 | * Returns: |
@@ -306,9 +307,9 @@ static int __is_valid_bus_id(char bus_id[CCW_BUS_ID_SIZE]) | |||
306 | * Context: | 307 | * Context: |
307 | * non-atomic | 308 | * non-atomic |
308 | */ | 309 | */ |
309 | int ccwgroup_create_from_string(struct device *root, unsigned int creator_id, | 310 | int ccwgroup_create_dev(struct device *parent, unsigned int creator_id, |
310 | struct ccw_driver *cdrv, int num_devices, | 311 | struct ccw_driver *cdrv, struct ccwgroup_driver *gdrv, |
311 | const char *buf) | 312 | int num_devices, const char *buf) |
312 | { | 313 | { |
313 | struct ccwgroup_device *gdev; | 314 | struct ccwgroup_device *gdev; |
314 | int rc, i; | 315 | int rc, i; |
@@ -323,10 +324,13 @@ int ccwgroup_create_from_string(struct device *root, unsigned int creator_id, | |||
323 | atomic_set(&gdev->onoff, 0); | 324 | atomic_set(&gdev->onoff, 0); |
324 | mutex_init(&gdev->reg_mutex); | 325 | mutex_init(&gdev->reg_mutex); |
325 | mutex_lock(&gdev->reg_mutex); | 326 | mutex_lock(&gdev->reg_mutex); |
326 | gdev->creator_id = creator_id; | 327 | if (gdrv) |
328 | gdev->creator_id = gdrv->driver_id; | ||
329 | else | ||
330 | gdev->creator_id = creator_id; | ||
327 | gdev->count = num_devices; | 331 | gdev->count = num_devices; |
328 | gdev->dev.bus = &ccwgroup_bus_type; | 332 | gdev->dev.bus = &ccwgroup_bus_type; |
329 | gdev->dev.parent = root; | 333 | gdev->dev.parent = parent; |
330 | gdev->dev.release = ccwgroup_release; | 334 | gdev->dev.release = ccwgroup_release; |
331 | device_initialize(&gdev->dev); | 335 | device_initialize(&gdev->dev); |
332 | 336 | ||
@@ -373,6 +377,13 @@ int ccwgroup_create_from_string(struct device *root, unsigned int creator_id, | |||
373 | 377 | ||
374 | dev_set_name(&gdev->dev, "%s", dev_name(&gdev->cdev[0]->dev)); | 378 | dev_set_name(&gdev->dev, "%s", dev_name(&gdev->cdev[0]->dev)); |
375 | gdev->dev.groups = ccwgroup_attr_groups; | 379 | gdev->dev.groups = ccwgroup_attr_groups; |
380 | |||
381 | if (gdrv) { | ||
382 | gdev->dev.driver = &gdrv->driver; | ||
383 | rc = gdrv->setup ? gdrv->setup(gdev) : 0; | ||
384 | if (rc) | ||
385 | goto error; | ||
386 | } | ||
376 | rc = device_add(&gdev->dev); | 387 | rc = device_add(&gdev->dev); |
377 | if (rc) | 388 | if (rc) |
378 | goto error; | 389 | goto error; |
@@ -397,6 +408,31 @@ error: | |||
397 | put_device(&gdev->dev); | 408 | put_device(&gdev->dev); |
398 | return rc; | 409 | return rc; |
399 | } | 410 | } |
411 | EXPORT_SYMBOL(ccwgroup_create_dev); | ||
412 | |||
413 | /** | ||
414 | * ccwgroup_create_from_string() - create and register a ccw group device | ||
415 | * @root: parent device for the new device | ||
416 | * @creator_id: identifier of creating driver | ||
417 | * @cdrv: ccw driver of slave devices | ||
418 | * @num_devices: number of slave devices | ||
419 | * @buf: buffer containing comma separated bus ids of slave devices | ||
420 | * | ||
421 | * Create and register a new ccw group device as a child of @root. Slave | ||
422 | * devices are obtained from the list of bus ids given in @buf and must all | ||
423 | * belong to @cdrv. | ||
424 | * Returns: | ||
425 | * %0 on success and an error code on failure. | ||
426 | * Context: | ||
427 | * non-atomic | ||
428 | */ | ||
429 | int ccwgroup_create_from_string(struct device *root, unsigned int creator_id, | ||
430 | struct ccw_driver *cdrv, int num_devices, | ||
431 | const char *buf) | ||
432 | { | ||
433 | return ccwgroup_create_dev(root, creator_id, cdrv, NULL, | ||
434 | num_devices, buf); | ||
435 | } | ||
400 | EXPORT_SYMBOL(ccwgroup_create_from_string); | 436 | EXPORT_SYMBOL(ccwgroup_create_from_string); |
401 | 437 | ||
402 | static int ccwgroup_notifier(struct notifier_block *nb, unsigned long action, | 438 | static int ccwgroup_notifier(struct notifier_block *nb, unsigned long action, |