diff options
Diffstat (limited to 'drivers/s390/cio/device.c')
| -rw-r--r-- | drivers/s390/cio/device.c | 47 |
1 files changed, 43 insertions, 4 deletions
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 6d229f3523a0..51bd3687d163 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c | |||
| @@ -36,6 +36,7 @@ | |||
| 36 | #include "ioasm.h" | 36 | #include "ioasm.h" |
| 37 | #include "io_sch.h" | 37 | #include "io_sch.h" |
| 38 | #include "blacklist.h" | 38 | #include "blacklist.h" |
| 39 | #include "chsc.h" | ||
| 39 | 40 | ||
| 40 | static struct timer_list recovery_timer; | 41 | static struct timer_list recovery_timer; |
| 41 | static DEFINE_SPINLOCK(recovery_lock); | 42 | static DEFINE_SPINLOCK(recovery_lock); |
| @@ -486,9 +487,11 @@ static int online_store_handle_offline(struct ccw_device *cdev) | |||
| 486 | spin_lock_irq(cdev->ccwlock); | 487 | spin_lock_irq(cdev->ccwlock); |
| 487 | ccw_device_sched_todo(cdev, CDEV_TODO_UNREG_EVAL); | 488 | ccw_device_sched_todo(cdev, CDEV_TODO_UNREG_EVAL); |
| 488 | spin_unlock_irq(cdev->ccwlock); | 489 | spin_unlock_irq(cdev->ccwlock); |
| 489 | } else if (cdev->online && cdev->drv && cdev->drv->set_offline) | 490 | return 0; |
| 491 | } | ||
| 492 | if (cdev->drv && cdev->drv->set_offline) | ||
| 490 | return ccw_device_set_offline(cdev); | 493 | return ccw_device_set_offline(cdev); |
| 491 | return 0; | 494 | return -EINVAL; |
| 492 | } | 495 | } |
| 493 | 496 | ||
| 494 | static int online_store_recog_and_online(struct ccw_device *cdev) | 497 | static int online_store_recog_and_online(struct ccw_device *cdev) |
| @@ -505,8 +508,8 @@ static int online_store_recog_and_online(struct ccw_device *cdev) | |||
| 505 | return -EAGAIN; | 508 | return -EAGAIN; |
| 506 | } | 509 | } |
| 507 | if (cdev->drv && cdev->drv->set_online) | 510 | if (cdev->drv && cdev->drv->set_online) |
| 508 | ccw_device_set_online(cdev); | 511 | return ccw_device_set_online(cdev); |
| 509 | return 0; | 512 | return -EINVAL; |
| 510 | } | 513 | } |
| 511 | 514 | ||
| 512 | static int online_store_handle_online(struct ccw_device *cdev, int force) | 515 | static int online_store_handle_online(struct ccw_device *cdev, int force) |
| @@ -598,6 +601,25 @@ available_show (struct device *dev, struct device_attribute *attr, char *buf) | |||
| 598 | } | 601 | } |
| 599 | } | 602 | } |
| 600 | 603 | ||
| 604 | static ssize_t | ||
| 605 | initiate_logging(struct device *dev, struct device_attribute *attr, | ||
| 606 | const char *buf, size_t count) | ||
| 607 | { | ||
| 608 | struct subchannel *sch = to_subchannel(dev); | ||
| 609 | int rc; | ||
| 610 | |||
| 611 | rc = chsc_siosl(sch->schid); | ||
| 612 | if (rc < 0) { | ||
| 613 | pr_warning("Logging for subchannel 0.%x.%04x failed with " | ||
| 614 | "errno=%d\n", | ||
| 615 | sch->schid.ssid, sch->schid.sch_no, rc); | ||
| 616 | return rc; | ||
| 617 | } | ||
| 618 | pr_notice("Logging for subchannel 0.%x.%04x was triggered\n", | ||
| 619 | sch->schid.ssid, sch->schid.sch_no); | ||
| 620 | return count; | ||
| 621 | } | ||
| 622 | |||
| 601 | static DEVICE_ATTR(chpids, 0444, chpids_show, NULL); | 623 | static DEVICE_ATTR(chpids, 0444, chpids_show, NULL); |
| 602 | static DEVICE_ATTR(pimpampom, 0444, pimpampom_show, NULL); | 624 | static DEVICE_ATTR(pimpampom, 0444, pimpampom_show, NULL); |
| 603 | static DEVICE_ATTR(devtype, 0444, devtype_show, NULL); | 625 | static DEVICE_ATTR(devtype, 0444, devtype_show, NULL); |
| @@ -605,10 +627,12 @@ static DEVICE_ATTR(cutype, 0444, cutype_show, NULL); | |||
| 605 | static DEVICE_ATTR(modalias, 0444, modalias_show, NULL); | 627 | static DEVICE_ATTR(modalias, 0444, modalias_show, NULL); |
| 606 | static DEVICE_ATTR(online, 0644, online_show, online_store); | 628 | static DEVICE_ATTR(online, 0644, online_show, online_store); |
| 607 | static DEVICE_ATTR(availability, 0444, available_show, NULL); | 629 | static DEVICE_ATTR(availability, 0444, available_show, NULL); |
| 630 | static DEVICE_ATTR(logging, 0200, NULL, initiate_logging); | ||
| 608 | 631 | ||
| 609 | static struct attribute *io_subchannel_attrs[] = { | 632 | static struct attribute *io_subchannel_attrs[] = { |
| 610 | &dev_attr_chpids.attr, | 633 | &dev_attr_chpids.attr, |
| 611 | &dev_attr_pimpampom.attr, | 634 | &dev_attr_pimpampom.attr, |
| 635 | &dev_attr_logging.attr, | ||
| 612 | NULL, | 636 | NULL, |
| 613 | }; | 637 | }; |
| 614 | 638 | ||
| @@ -2036,6 +2060,21 @@ void ccw_device_sched_todo(struct ccw_device *cdev, enum cdev_todo todo) | |||
| 2036 | } | 2060 | } |
| 2037 | } | 2061 | } |
| 2038 | 2062 | ||
| 2063 | /** | ||
| 2064 | * ccw_device_siosl() - initiate logging | ||
| 2065 | * @cdev: ccw device | ||
| 2066 | * | ||
| 2067 | * This function is used to invoke model-dependent logging within the channel | ||
| 2068 | * subsystem. | ||
| 2069 | */ | ||
| 2070 | int ccw_device_siosl(struct ccw_device *cdev) | ||
| 2071 | { | ||
| 2072 | struct subchannel *sch = to_subchannel(cdev->dev.parent); | ||
| 2073 | |||
| 2074 | return chsc_siosl(sch->schid); | ||
| 2075 | } | ||
| 2076 | EXPORT_SYMBOL_GPL(ccw_device_siosl); | ||
| 2077 | |||
| 2039 | MODULE_LICENSE("GPL"); | 2078 | MODULE_LICENSE("GPL"); |
| 2040 | EXPORT_SYMBOL(ccw_device_set_online); | 2079 | EXPORT_SYMBOL(ccw_device_set_online); |
| 2041 | EXPORT_SYMBOL(ccw_device_set_offline); | 2080 | EXPORT_SYMBOL(ccw_device_set_offline); |
