diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-03-06 22:52:50 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-03-06 22:52:50 -0500 |
commit | fe1b4ba400193176213f95be3ea711a53518a609 (patch) | |
tree | e60943d4703fca5a291fffc2e0b77a786b6db3f4 /drivers | |
parent | ae5dd8e346efc25a5f9cc9d01bc0915c40eb38d9 (diff) | |
parent | 2470b648e17e0216922bb78c7f05b4668402459a (diff) |
Merge branch 'for-linus' of git://git390.osdl.marist.edu/pub/scm/linux-2.6
* 'for-linus' of git://git390.osdl.marist.edu/pub/scm/linux-2.6:
[S390] cio: Call cancel_halt_clear even when actl == 0.
[S390] cio: Use path verification to check for path state.
[S390] cio: Fix locking when calling notify function.
[S390] Fixed handling of access register mode faults.
[S390] dasd: Use default recovery for SNSS requests
[S390] check_bugs() should be inline.
[S390] tape: Compression overwrites crypto setting
[S390] nss: disable kexec.
[S390] reipl: move dump_prefix_page out of text section.
[S390] smp: disable preemption in smp_call_function/smp_call_function_on
[S390] kprobes breaks BUG_ON
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 |