| .. | .. |
|---|
| 485 | 485 | gdrv->shutdown(gdev); |
|---|
| 486 | 486 | } |
|---|
| 487 | 487 | |
|---|
| 488 | | -static int ccwgroup_pm_prepare(struct device *dev) |
|---|
| 489 | | -{ |
|---|
| 490 | | - struct ccwgroup_device *gdev = to_ccwgroupdev(dev); |
|---|
| 491 | | - struct ccwgroup_driver *gdrv = to_ccwgroupdrv(gdev->dev.driver); |
|---|
| 492 | | - |
|---|
| 493 | | - /* Fail while device is being set online/offline. */ |
|---|
| 494 | | - if (atomic_read(&gdev->onoff)) |
|---|
| 495 | | - return -EAGAIN; |
|---|
| 496 | | - |
|---|
| 497 | | - if (!gdev->dev.driver || gdev->state != CCWGROUP_ONLINE) |
|---|
| 498 | | - return 0; |
|---|
| 499 | | - |
|---|
| 500 | | - return gdrv->prepare ? gdrv->prepare(gdev) : 0; |
|---|
| 501 | | -} |
|---|
| 502 | | - |
|---|
| 503 | | -static void ccwgroup_pm_complete(struct device *dev) |
|---|
| 504 | | -{ |
|---|
| 505 | | - struct ccwgroup_device *gdev = to_ccwgroupdev(dev); |
|---|
| 506 | | - struct ccwgroup_driver *gdrv = to_ccwgroupdrv(dev->driver); |
|---|
| 507 | | - |
|---|
| 508 | | - if (!gdev->dev.driver || gdev->state != CCWGROUP_ONLINE) |
|---|
| 509 | | - return; |
|---|
| 510 | | - |
|---|
| 511 | | - if (gdrv->complete) |
|---|
| 512 | | - gdrv->complete(gdev); |
|---|
| 513 | | -} |
|---|
| 514 | | - |
|---|
| 515 | | -static int ccwgroup_pm_freeze(struct device *dev) |
|---|
| 516 | | -{ |
|---|
| 517 | | - struct ccwgroup_device *gdev = to_ccwgroupdev(dev); |
|---|
| 518 | | - struct ccwgroup_driver *gdrv = to_ccwgroupdrv(gdev->dev.driver); |
|---|
| 519 | | - |
|---|
| 520 | | - if (!gdev->dev.driver || gdev->state != CCWGROUP_ONLINE) |
|---|
| 521 | | - return 0; |
|---|
| 522 | | - |
|---|
| 523 | | - return gdrv->freeze ? gdrv->freeze(gdev) : 0; |
|---|
| 524 | | -} |
|---|
| 525 | | - |
|---|
| 526 | | -static int ccwgroup_pm_thaw(struct device *dev) |
|---|
| 527 | | -{ |
|---|
| 528 | | - struct ccwgroup_device *gdev = to_ccwgroupdev(dev); |
|---|
| 529 | | - struct ccwgroup_driver *gdrv = to_ccwgroupdrv(gdev->dev.driver); |
|---|
| 530 | | - |
|---|
| 531 | | - if (!gdev->dev.driver || gdev->state != CCWGROUP_ONLINE) |
|---|
| 532 | | - return 0; |
|---|
| 533 | | - |
|---|
| 534 | | - return gdrv->thaw ? gdrv->thaw(gdev) : 0; |
|---|
| 535 | | -} |
|---|
| 536 | | - |
|---|
| 537 | | -static int ccwgroup_pm_restore(struct device *dev) |
|---|
| 538 | | -{ |
|---|
| 539 | | - struct ccwgroup_device *gdev = to_ccwgroupdev(dev); |
|---|
| 540 | | - struct ccwgroup_driver *gdrv = to_ccwgroupdrv(gdev->dev.driver); |
|---|
| 541 | | - |
|---|
| 542 | | - if (!gdev->dev.driver || gdev->state != CCWGROUP_ONLINE) |
|---|
| 543 | | - return 0; |
|---|
| 544 | | - |
|---|
| 545 | | - return gdrv->restore ? gdrv->restore(gdev) : 0; |
|---|
| 546 | | -} |
|---|
| 547 | | - |
|---|
| 548 | | -static const struct dev_pm_ops ccwgroup_pm_ops = { |
|---|
| 549 | | - .prepare = ccwgroup_pm_prepare, |
|---|
| 550 | | - .complete = ccwgroup_pm_complete, |
|---|
| 551 | | - .freeze = ccwgroup_pm_freeze, |
|---|
| 552 | | - .thaw = ccwgroup_pm_thaw, |
|---|
| 553 | | - .restore = ccwgroup_pm_restore, |
|---|
| 554 | | -}; |
|---|
| 555 | | - |
|---|
| 556 | 488 | static struct bus_type ccwgroup_bus_type = { |
|---|
| 557 | 489 | .name = "ccwgroup", |
|---|
| 558 | 490 | .remove = ccwgroup_remove, |
|---|
| 559 | 491 | .shutdown = ccwgroup_shutdown, |
|---|
| 560 | | - .pm = &ccwgroup_pm_ops, |
|---|
| 561 | 492 | }; |
|---|
| 562 | 493 | |
|---|
| 563 | 494 | bool dev_is_ccwgroup(struct device *dev) |
|---|
| .. | .. |
|---|
| 581 | 512 | } |
|---|
| 582 | 513 | EXPORT_SYMBOL(ccwgroup_driver_register); |
|---|
| 583 | 514 | |
|---|
| 584 | | -static int __ccwgroup_match_all(struct device *dev, void *data) |
|---|
| 585 | | -{ |
|---|
| 586 | | - return 1; |
|---|
| 587 | | -} |
|---|
| 588 | | - |
|---|
| 589 | 515 | /** |
|---|
| 590 | 516 | * ccwgroup_driver_unregister() - deregister a ccw group driver |
|---|
| 591 | 517 | * @cdriver: driver to be deregistered |
|---|
| .. | .. |
|---|
| 597 | 523 | struct device *dev; |
|---|
| 598 | 524 | |
|---|
| 599 | 525 | /* We don't want ccwgroup devices to live longer than their driver. */ |
|---|
| 600 | | - while ((dev = driver_find_device(&cdriver->driver, NULL, NULL, |
|---|
| 601 | | - __ccwgroup_match_all))) { |
|---|
| 526 | + while ((dev = driver_find_next_device(&cdriver->driver, NULL))) { |
|---|
| 602 | 527 | struct ccwgroup_device *gdev = to_ccwgroupdev(dev); |
|---|
| 603 | 528 | |
|---|
| 604 | 529 | ccwgroup_ungroup(gdev); |
|---|
| .. | .. |
|---|
| 609 | 534 | EXPORT_SYMBOL(ccwgroup_driver_unregister); |
|---|
| 610 | 535 | |
|---|
| 611 | 536 | /** |
|---|
| 537 | + * get_ccwgroupdev_by_busid() - obtain device from a bus id |
|---|
| 538 | + * @gdrv: driver the device is owned by |
|---|
| 539 | + * @bus_id: bus id of the device to be searched |
|---|
| 540 | + * |
|---|
| 541 | + * This function searches all devices owned by @gdrv for a device with a bus |
|---|
| 542 | + * id matching @bus_id. |
|---|
| 543 | + * Returns: |
|---|
| 544 | + * If a match is found, its reference count of the found device is increased |
|---|
| 545 | + * and it is returned; else %NULL is returned. |
|---|
| 546 | + */ |
|---|
| 547 | +struct ccwgroup_device *get_ccwgroupdev_by_busid(struct ccwgroup_driver *gdrv, |
|---|
| 548 | + char *bus_id) |
|---|
| 549 | +{ |
|---|
| 550 | + struct device *dev; |
|---|
| 551 | + |
|---|
| 552 | + dev = driver_find_device_by_name(&gdrv->driver, bus_id); |
|---|
| 553 | + |
|---|
| 554 | + return dev ? to_ccwgroupdev(dev) : NULL; |
|---|
| 555 | +} |
|---|
| 556 | +EXPORT_SYMBOL_GPL(get_ccwgroupdev_by_busid); |
|---|
| 557 | + |
|---|
| 558 | +/** |
|---|
| 612 | 559 | * ccwgroup_probe_ccwdev() - probe function for slave devices |
|---|
| 613 | 560 | * @cdev: ccw device to be probed |
|---|
| 614 | 561 | * |
|---|