diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/s390/block/dasd_eer.c | 1 | ||||
| -rw-r--r-- | drivers/s390/char/tape_std.c | 5 | ||||
| -rw-r--r-- | drivers/s390/cio/device_fsm.c | 117 |
3 files changed, 60 insertions, 63 deletions
diff --git a/drivers/s390/block/dasd_eer.c b/drivers/s390/block/dasd_eer.c index 4b8a95fba1e5..a1dc8c466ec9 100644 --- a/drivers/s390/block/dasd_eer.c +++ b/drivers/s390/block/dasd_eer.c | |||
| @@ -461,6 +461,7 @@ int dasd_eer_enable(struct dasd_device *device) | |||
| 461 | cqr->device = device; | 461 | cqr->device = device; |
| 462 | cqr->retries = 255; | 462 | cqr->retries = 255; |
| 463 | cqr->expires = 10 * HZ; | 463 | cqr->expires = 10 * HZ; |
| 464 | clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); | ||
| 464 | 465 | ||
| 465 | cqr->cpaddr->cmd_code = DASD_ECKD_CCW_SNSS; | 466 | cqr->cpaddr->cmd_code = DASD_ECKD_CCW_SNSS; |
| 466 | cqr->cpaddr->count = SNSS_DATA_SIZE; | 467 | cqr->cpaddr->count = SNSS_DATA_SIZE; |
diff --git a/drivers/s390/char/tape_std.c b/drivers/s390/char/tape_std.c index 7a76ec413a3a..2a1af4e60be0 100644 --- a/drivers/s390/char/tape_std.c +++ b/drivers/s390/char/tape_std.c | |||
| @@ -647,7 +647,10 @@ tape_std_mtcompression(struct tape_device *device, int mt_count) | |||
| 647 | return PTR_ERR(request); | 647 | return PTR_ERR(request); |
| 648 | request->op = TO_NOP; | 648 | request->op = TO_NOP; |
| 649 | /* setup ccws */ | 649 | /* setup ccws */ |
| 650 | *device->modeset_byte = (mt_count == 0) ? 0x00 : 0x08; | 650 | if (mt_count == 0) |
| 651 | *device->modeset_byte &= ~0x08; | ||
| 652 | else | ||
| 653 | *device->modeset_byte |= 0x08; | ||
| 651 | tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte); | 654 | tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte); |
| 652 | tape_ccw_end(request->cpaddr + 1, NOP, 0, NULL); | 655 | tape_ccw_end(request->cpaddr + 1, NOP, 0, NULL); |
| 653 | /* execute it */ | 656 | /* execute it */ |
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index 51238e7555bb..089a3ddd6265 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c | |||
| @@ -144,8 +144,8 @@ ccw_device_cancel_halt_clear(struct ccw_device *cdev) | |||
| 144 | ret = stsch(sch->schid, &sch->schib); | 144 | ret = stsch(sch->schid, &sch->schib); |
| 145 | if (ret || !sch->schib.pmcw.dnv) | 145 | if (ret || !sch->schib.pmcw.dnv) |
| 146 | return -ENODEV; | 146 | return -ENODEV; |
| 147 | if (!sch->schib.pmcw.ena || sch->schib.scsw.actl == 0) | 147 | if (!sch->schib.pmcw.ena) |
| 148 | /* Not operational or no activity -> done. */ | 148 | /* Not operational -> done. */ |
| 149 | return 0; | 149 | return 0; |
| 150 | /* Stage 1: cancel io. */ | 150 | /* Stage 1: cancel io. */ |
| 151 | if (!(sch->schib.scsw.actl & SCSW_ACTL_HALT_PEND) && | 151 | if (!(sch->schib.scsw.actl & SCSW_ACTL_HALT_PEND) && |
| @@ -334,20 +334,29 @@ ccw_device_oper_notify(struct work_struct *work) | |||
| 334 | struct ccw_device *cdev; | 334 | struct ccw_device *cdev; |
| 335 | struct subchannel *sch; | 335 | struct subchannel *sch; |
| 336 | int ret; | 336 | int ret; |
| 337 | unsigned long flags; | ||
| 337 | 338 | ||
| 338 | priv = container_of(work, struct ccw_device_private, kick_work); | 339 | priv = container_of(work, struct ccw_device_private, kick_work); |
| 339 | cdev = priv->cdev; | 340 | cdev = priv->cdev; |
| 341 | spin_lock_irqsave(cdev->ccwlock, flags); | ||
| 340 | sch = to_subchannel(cdev->dev.parent); | 342 | sch = to_subchannel(cdev->dev.parent); |
| 341 | ret = (sch->driver && sch->driver->notify) ? | 343 | if (sch->driver && sch->driver->notify) { |
| 342 | sch->driver->notify(&sch->dev, CIO_OPER) : 0; | 344 | spin_unlock_irqrestore(cdev->ccwlock, flags); |
| 343 | if (!ret) | 345 | ret = sch->driver->notify(&sch->dev, CIO_OPER); |
| 344 | /* Driver doesn't want device back. */ | 346 | spin_lock_irqsave(cdev->ccwlock, flags); |
| 345 | ccw_device_do_unreg_rereg(work); | 347 | } else |
| 346 | else { | 348 | ret = 0; |
| 349 | if (ret) { | ||
| 347 | /* Reenable channel measurements, if needed. */ | 350 | /* Reenable channel measurements, if needed. */ |
| 351 | spin_unlock_irqrestore(cdev->ccwlock, flags); | ||
| 348 | cmf_reenable(cdev); | 352 | cmf_reenable(cdev); |
| 353 | spin_lock_irqsave(cdev->ccwlock, flags); | ||
| 349 | wake_up(&cdev->private->wait_q); | 354 | wake_up(&cdev->private->wait_q); |
| 350 | } | 355 | } |
| 356 | spin_unlock_irqrestore(cdev->ccwlock, flags); | ||
| 357 | if (!ret) | ||
| 358 | /* Driver doesn't want device back. */ | ||
| 359 | ccw_device_do_unreg_rereg(work); | ||
| 351 | } | 360 | } |
| 352 | 361 | ||
| 353 | /* | 362 | /* |
| @@ -534,15 +543,21 @@ ccw_device_nopath_notify(struct work_struct *work) | |||
| 534 | struct ccw_device *cdev; | 543 | struct ccw_device *cdev; |
| 535 | struct subchannel *sch; | 544 | struct subchannel *sch; |
| 536 | int ret; | 545 | int ret; |
| 546 | unsigned long flags; | ||
| 537 | 547 | ||
| 538 | priv = container_of(work, struct ccw_device_private, kick_work); | 548 | priv = container_of(work, struct ccw_device_private, kick_work); |
| 539 | cdev = priv->cdev; | 549 | cdev = priv->cdev; |
| 550 | spin_lock_irqsave(cdev->ccwlock, flags); | ||
| 540 | sch = to_subchannel(cdev->dev.parent); | 551 | sch = to_subchannel(cdev->dev.parent); |
| 541 | /* Extra sanity. */ | 552 | /* Extra sanity. */ |
| 542 | if (sch->lpm) | 553 | if (sch->lpm) |
| 543 | return; | 554 | goto out_unlock; |
| 544 | ret = (sch->driver && sch->driver->notify) ? | 555 | if (sch->driver && sch->driver->notify) { |
| 545 | sch->driver->notify(&sch->dev, CIO_NO_PATH) : 0; | 556 | spin_unlock_irqrestore(cdev->ccwlock, flags); |
| 557 | ret = sch->driver->notify(&sch->dev, CIO_NO_PATH); | ||
| 558 | spin_lock_irqsave(cdev->ccwlock, flags); | ||
| 559 | } else | ||
| 560 | ret = 0; | ||
| 546 | if (!ret) { | 561 | if (!ret) { |
| 547 | if (get_device(&sch->dev)) { | 562 | if (get_device(&sch->dev)) { |
| 548 | /* Driver doesn't want to keep device. */ | 563 | /* Driver doesn't want to keep device. */ |
| @@ -562,6 +577,8 @@ ccw_device_nopath_notify(struct work_struct *work) | |||
| 562 | cdev->private->state = DEV_STATE_DISCONNECTED; | 577 | cdev->private->state = DEV_STATE_DISCONNECTED; |
| 563 | wake_up(&cdev->private->wait_q); | 578 | wake_up(&cdev->private->wait_q); |
| 564 | } | 579 | } |
| 580 | out_unlock: | ||
| 581 | spin_unlock_irqrestore(cdev->ccwlock, flags); | ||
| 565 | } | 582 | } |
| 566 | 583 | ||
| 567 | void | 584 | void |
| @@ -607,10 +624,13 @@ ccw_device_verify_done(struct ccw_device *cdev, int err) | |||
| 607 | default: | 624 | default: |
| 608 | /* Reset oper notify indication after verify error. */ | 625 | /* Reset oper notify indication after verify error. */ |
| 609 | cdev->private->flags.donotify = 0; | 626 | cdev->private->flags.donotify = 0; |
| 610 | PREPARE_WORK(&cdev->private->kick_work, | 627 | if (cdev->online) { |
| 611 | ccw_device_nopath_notify); | 628 | PREPARE_WORK(&cdev->private->kick_work, |
| 612 | queue_work(ccw_device_notify_work, &cdev->private->kick_work); | 629 | ccw_device_nopath_notify); |
| 613 | ccw_device_done(cdev, DEV_STATE_NOT_OPER); | 630 | queue_work(ccw_device_notify_work, |
| 631 | &cdev->private->kick_work); | ||
| 632 | } else | ||
| 633 | ccw_device_done(cdev, DEV_STATE_NOT_OPER); | ||
| 614 | break; | 634 | break; |
| 615 | } | 635 | } |
| 616 | } | 636 | } |
| @@ -756,15 +776,22 @@ static void | |||
| 756 | ccw_device_online_notoper(struct ccw_device *cdev, enum dev_event dev_event) | 776 | ccw_device_online_notoper(struct ccw_device *cdev, enum dev_event dev_event) |
| 757 | { | 777 | { |
| 758 | struct subchannel *sch; | 778 | struct subchannel *sch; |
| 779 | int ret; | ||
| 759 | 780 | ||
| 760 | sch = to_subchannel(cdev->dev.parent); | 781 | sch = to_subchannel(cdev->dev.parent); |
| 761 | if (sch->driver->notify && | 782 | if (sch->driver->notify) { |
| 762 | sch->driver->notify(&sch->dev, sch->lpm ? CIO_GONE : CIO_NO_PATH)) { | 783 | spin_unlock_irq(cdev->ccwlock); |
| 763 | ccw_device_set_timeout(cdev, 0); | 784 | ret = sch->driver->notify(&sch->dev, |
| 764 | cdev->private->flags.fake_irb = 0; | 785 | sch->lpm ? CIO_GONE : CIO_NO_PATH); |
| 765 | cdev->private->state = DEV_STATE_DISCONNECTED; | 786 | spin_lock_irq(cdev->ccwlock); |
| 766 | wake_up(&cdev->private->wait_q); | 787 | } else |
| 767 | return; | 788 | ret = 0; |
| 789 | if (ret) { | ||
| 790 | ccw_device_set_timeout(cdev, 0); | ||
| 791 | cdev->private->flags.fake_irb = 0; | ||
| 792 | cdev->private->state = DEV_STATE_DISCONNECTED; | ||
| 793 | wake_up(&cdev->private->wait_q); | ||
| 794 | return; | ||
| 768 | } | 795 | } |
| 769 | cdev->private->state = DEV_STATE_NOT_OPER; | 796 | cdev->private->state = DEV_STATE_NOT_OPER; |
| 770 | cio_disable_subchannel(sch); | 797 | cio_disable_subchannel(sch); |
| @@ -969,18 +996,12 @@ ccw_device_killing_irq(struct ccw_device *cdev, enum dev_event dev_event) | |||
| 969 | 996 | ||
| 970 | sch = to_subchannel(cdev->dev.parent); | 997 | sch = to_subchannel(cdev->dev.parent); |
| 971 | ccw_device_set_timeout(cdev, 0); | 998 | ccw_device_set_timeout(cdev, 0); |
| 999 | /* Start delayed path verification. */ | ||
| 1000 | ccw_device_online_verify(cdev, 0); | ||
| 972 | /* OK, i/o is dead now. Call interrupt handler. */ | 1001 | /* OK, i/o is dead now. Call interrupt handler. */ |
| 973 | cdev->private->state = DEV_STATE_ONLINE; | ||
| 974 | if (cdev->handler) | 1002 | if (cdev->handler) |
| 975 | cdev->handler(cdev, cdev->private->intparm, | 1003 | cdev->handler(cdev, cdev->private->intparm, |
| 976 | ERR_PTR(-EIO)); | 1004 | ERR_PTR(-EIO)); |
| 977 | if (!sch->lpm) { | ||
| 978 | PREPARE_WORK(&cdev->private->kick_work, | ||
| 979 | ccw_device_nopath_notify); | ||
| 980 | queue_work(ccw_device_notify_work, &cdev->private->kick_work); | ||
| 981 | } else if (cdev->private->flags.doverify) | ||
| 982 | /* Start delayed path verification. */ | ||
| 983 | ccw_device_online_verify(cdev, 0); | ||
| 984 | } | 1005 | } |
| 985 | 1006 | ||
| 986 | static void | 1007 | static void |
| @@ -993,21 +1014,8 @@ ccw_device_killing_timeout(struct ccw_device *cdev, enum dev_event dev_event) | |||
| 993 | ccw_device_set_timeout(cdev, 3*HZ); | 1014 | ccw_device_set_timeout(cdev, 3*HZ); |
| 994 | return; | 1015 | return; |
| 995 | } | 1016 | } |
| 996 | if (ret == -ENODEV) { | 1017 | /* Start delayed path verification. */ |
| 997 | struct subchannel *sch; | 1018 | ccw_device_online_verify(cdev, 0); |
| 998 | |||
| 999 | sch = to_subchannel(cdev->dev.parent); | ||
| 1000 | if (!sch->lpm) { | ||
| 1001 | PREPARE_WORK(&cdev->private->kick_work, | ||
| 1002 | ccw_device_nopath_notify); | ||
| 1003 | queue_work(ccw_device_notify_work, | ||
| 1004 | &cdev->private->kick_work); | ||
| 1005 | } else | ||
| 1006 | dev_fsm_event(cdev, DEV_EVENT_NOTOPER); | ||
| 1007 | return; | ||
| 1008 | } | ||
| 1009 | //FIXME: Can we get here? | ||
| 1010 | cdev->private->state = DEV_STATE_ONLINE; | ||
| 1011 | if (cdev->handler) | 1019 | if (cdev->handler) |
| 1012 | cdev->handler(cdev, cdev->private->intparm, | 1020 | cdev->handler(cdev, cdev->private->intparm, |
| 1013 | ERR_PTR(-EIO)); | 1021 | ERR_PTR(-EIO)); |
| @@ -1025,26 +1033,11 @@ void device_kill_io(struct subchannel *sch) | |||
| 1025 | cdev->private->state = DEV_STATE_TIMEOUT_KILL; | 1033 | cdev->private->state = DEV_STATE_TIMEOUT_KILL; |
| 1026 | return; | 1034 | return; |
| 1027 | } | 1035 | } |
| 1028 | if (ret == -ENODEV) { | 1036 | /* Start delayed path verification. */ |
| 1029 | if (!sch->lpm) { | 1037 | ccw_device_online_verify(cdev, 0); |
| 1030 | PREPARE_WORK(&cdev->private->kick_work, | ||
| 1031 | ccw_device_nopath_notify); | ||
| 1032 | queue_work(ccw_device_notify_work, | ||
| 1033 | &cdev->private->kick_work); | ||
| 1034 | } else | ||
| 1035 | dev_fsm_event(cdev, DEV_EVENT_NOTOPER); | ||
| 1036 | return; | ||
| 1037 | } | ||
| 1038 | if (cdev->handler) | 1038 | if (cdev->handler) |
| 1039 | cdev->handler(cdev, cdev->private->intparm, | 1039 | cdev->handler(cdev, cdev->private->intparm, |
| 1040 | ERR_PTR(-EIO)); | 1040 | ERR_PTR(-EIO)); |
| 1041 | if (!sch->lpm) { | ||
| 1042 | PREPARE_WORK(&cdev->private->kick_work, | ||
| 1043 | ccw_device_nopath_notify); | ||
| 1044 | queue_work(ccw_device_notify_work, &cdev->private->kick_work); | ||
| 1045 | } else | ||
| 1046 | /* Start delayed path verification. */ | ||
| 1047 | ccw_device_online_verify(cdev, 0); | ||
| 1048 | } | 1041 | } |
| 1049 | 1042 | ||
| 1050 | static void | 1043 | static void |
