aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio/ccwgroup.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/cio/ccwgroup.c')
-rw-r--r--drivers/s390/cio/ccwgroup.c73
1 files changed, 56 insertions, 17 deletions
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c
index b91c1719b075..22ce765d537e 100644
--- a/drivers/s390/cio/ccwgroup.c
+++ b/drivers/s390/cio/ccwgroup.c
@@ -315,16 +315,32 @@ error:
315} 315}
316EXPORT_SYMBOL(ccwgroup_create_from_string); 316EXPORT_SYMBOL(ccwgroup_create_from_string);
317 317
318static int __init 318static int ccwgroup_notifier(struct notifier_block *nb, unsigned long action,
319init_ccwgroup (void) 319 void *data);
320
321static struct notifier_block ccwgroup_nb = {
322 .notifier_call = ccwgroup_notifier
323};
324
325static int __init init_ccwgroup(void)
320{ 326{
321 return bus_register (&ccwgroup_bus_type); 327 int ret;
328
329 ret = bus_register(&ccwgroup_bus_type);
330 if (ret)
331 return ret;
332
333 ret = bus_register_notifier(&ccwgroup_bus_type, &ccwgroup_nb);
334 if (ret)
335 bus_unregister(&ccwgroup_bus_type);
336
337 return ret;
322} 338}
323 339
324static void __exit 340static void __exit cleanup_ccwgroup(void)
325cleanup_ccwgroup (void)
326{ 341{
327 bus_unregister (&ccwgroup_bus_type); 342 bus_unregister_notifier(&ccwgroup_bus_type, &ccwgroup_nb);
343 bus_unregister(&ccwgroup_bus_type);
328} 344}
329 345
330module_init(init_ccwgroup); 346module_init(init_ccwgroup);
@@ -392,27 +408,28 @@ ccwgroup_online_store (struct device *dev, struct device_attribute *attr, const
392 unsigned long value; 408 unsigned long value;
393 int ret; 409 int ret;
394 410
395 gdev = to_ccwgroupdev(dev);
396 if (!dev->driver) 411 if (!dev->driver)
397 return count; 412 return -ENODEV;
413
414 gdev = to_ccwgroupdev(dev);
415 gdrv = to_ccwgroupdrv(dev->driver);
398 416
399 gdrv = to_ccwgroupdrv (gdev->dev.driver);
400 if (!try_module_get(gdrv->owner)) 417 if (!try_module_get(gdrv->owner))
401 return -EINVAL; 418 return -EINVAL;
402 419
403 ret = strict_strtoul(buf, 0, &value); 420 ret = strict_strtoul(buf, 0, &value);
404 if (ret) 421 if (ret)
405 goto out; 422 goto out;
406 ret = count; 423
407 if (value == 1) 424 if (value == 1)
408 ccwgroup_set_online(gdev); 425 ret = ccwgroup_set_online(gdev);
409 else if (value == 0) 426 else if (value == 0)
410 ccwgroup_set_offline(gdev); 427 ret = ccwgroup_set_offline(gdev);
411 else 428 else
412 ret = -EINVAL; 429 ret = -EINVAL;
413out: 430out:
414 module_put(gdrv->owner); 431 module_put(gdrv->owner);
415 return ret; 432 return (ret == 0) ? count : ret;
416} 433}
417 434
418static ssize_t 435static ssize_t
@@ -454,13 +471,18 @@ ccwgroup_remove (struct device *dev)
454 struct ccwgroup_device *gdev; 471 struct ccwgroup_device *gdev;
455 struct ccwgroup_driver *gdrv; 472 struct ccwgroup_driver *gdrv;
456 473
474 device_remove_file(dev, &dev_attr_online);
475 device_remove_file(dev, &dev_attr_ungroup);
476
477 if (!dev->driver)
478 return 0;
479
457 gdev = to_ccwgroupdev(dev); 480 gdev = to_ccwgroupdev(dev);
458 gdrv = to_ccwgroupdrv(dev->driver); 481 gdrv = to_ccwgroupdrv(dev->driver);
459 482
460 device_remove_file(dev, &dev_attr_online); 483 if (gdrv->remove)
461
462 if (gdrv && gdrv->remove)
463 gdrv->remove(gdev); 484 gdrv->remove(gdev);
485
464 return 0; 486 return 0;
465} 487}
466 488
@@ -469,9 +491,13 @@ static void ccwgroup_shutdown(struct device *dev)
469 struct ccwgroup_device *gdev; 491 struct ccwgroup_device *gdev;
470 struct ccwgroup_driver *gdrv; 492 struct ccwgroup_driver *gdrv;
471 493
494 if (!dev->driver)
495 return;
496
472 gdev = to_ccwgroupdev(dev); 497 gdev = to_ccwgroupdev(dev);
473 gdrv = to_ccwgroupdrv(dev->driver); 498 gdrv = to_ccwgroupdrv(dev->driver);
474 if (gdrv && gdrv->shutdown) 499
500 if (gdrv->shutdown)
475 gdrv->shutdown(gdev); 501 gdrv->shutdown(gdev);
476} 502}
477 503
@@ -484,6 +510,19 @@ static struct bus_type ccwgroup_bus_type = {
484 .shutdown = ccwgroup_shutdown, 510 .shutdown = ccwgroup_shutdown,
485}; 511};
486 512
513
514static int ccwgroup_notifier(struct notifier_block *nb, unsigned long action,
515 void *data)
516{
517 struct device *dev = data;
518
519 if (action == BUS_NOTIFY_UNBIND_DRIVER)
520 device_schedule_callback(dev, ccwgroup_ungroup_callback);
521
522 return NOTIFY_OK;
523}
524
525
487/** 526/**
488 * ccwgroup_driver_register() - register a ccw group driver 527 * ccwgroup_driver_register() - register a ccw group driver
489 * @cdriver: driver to be registered 528 * @cdriver: driver to be registered