diff options
Diffstat (limited to 'drivers/s390/cio/device_fsm.c')
-rw-r--r-- | drivers/s390/cio/device_fsm.c | 49 |
1 files changed, 23 insertions, 26 deletions
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index c9b97cbc2203..dc9373031af0 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c | |||
@@ -133,15 +133,15 @@ ccw_device_cancel_halt_clear(struct ccw_device *cdev) | |||
133 | /* Not operational -> done. */ | 133 | /* Not operational -> done. */ |
134 | return 0; | 134 | return 0; |
135 | /* Stage 1: cancel io. */ | 135 | /* Stage 1: cancel io. */ |
136 | if (!(sch->schib.scsw.actl & SCSW_ACTL_HALT_PEND) && | 136 | if (!(scsw_actl(&sch->schib.scsw) & SCSW_ACTL_HALT_PEND) && |
137 | !(sch->schib.scsw.actl & SCSW_ACTL_CLEAR_PEND)) { | 137 | !(scsw_actl(&sch->schib.scsw) & SCSW_ACTL_CLEAR_PEND)) { |
138 | ret = cio_cancel(sch); | 138 | ret = cio_cancel(sch); |
139 | if (ret != -EINVAL) | 139 | if (ret != -EINVAL) |
140 | return ret; | 140 | return ret; |
141 | /* cancel io unsuccessful. From now on it is asynchronous. */ | 141 | /* cancel io unsuccessful. From now on it is asynchronous. */ |
142 | cdev->private->iretry = 3; /* 3 halt retries. */ | 142 | cdev->private->iretry = 3; /* 3 halt retries. */ |
143 | } | 143 | } |
144 | if (!(sch->schib.scsw.actl & SCSW_ACTL_CLEAR_PEND)) { | 144 | if (!(scsw_actl(&sch->schib.scsw) & SCSW_ACTL_CLEAR_PEND)) { |
145 | /* Stage 2: halt io. */ | 145 | /* Stage 2: halt io. */ |
146 | if (cdev->private->iretry) { | 146 | if (cdev->private->iretry) { |
147 | cdev->private->iretry--; | 147 | cdev->private->iretry--; |
@@ -551,10 +551,11 @@ ccw_device_verify_done(struct ccw_device *cdev, int err) | |||
551 | /* Deliver fake irb to device driver, if needed. */ | 551 | /* Deliver fake irb to device driver, if needed. */ |
552 | if (cdev->private->flags.fake_irb) { | 552 | if (cdev->private->flags.fake_irb) { |
553 | memset(&cdev->private->irb, 0, sizeof(struct irb)); | 553 | memset(&cdev->private->irb, 0, sizeof(struct irb)); |
554 | cdev->private->irb.scsw.cc = 1; | 554 | cdev->private->irb.scsw.cmd.cc = 1; |
555 | cdev->private->irb.scsw.fctl = SCSW_FCTL_START_FUNC; | 555 | cdev->private->irb.scsw.cmd.fctl = SCSW_FCTL_START_FUNC; |
556 | cdev->private->irb.scsw.actl = SCSW_ACTL_START_PEND; | 556 | cdev->private->irb.scsw.cmd.actl = SCSW_ACTL_START_PEND; |
557 | cdev->private->irb.scsw.stctl = SCSW_STCTL_STATUS_PEND; | 557 | cdev->private->irb.scsw.cmd.stctl = |
558 | SCSW_STCTL_STATUS_PEND; | ||
558 | cdev->private->flags.fake_irb = 0; | 559 | cdev->private->flags.fake_irb = 0; |
559 | if (cdev->handler) | 560 | if (cdev->handler) |
560 | cdev->handler(cdev, cdev->private->intparm, | 561 | cdev->handler(cdev, cdev->private->intparm, |
@@ -648,13 +649,10 @@ ccw_device_offline(struct ccw_device *cdev) | |||
648 | sch = to_subchannel(cdev->dev.parent); | 649 | sch = to_subchannel(cdev->dev.parent); |
649 | if (stsch(sch->schid, &sch->schib) || !sch->schib.pmcw.dnv) | 650 | if (stsch(sch->schid, &sch->schib) || !sch->schib.pmcw.dnv) |
650 | return -ENODEV; | 651 | return -ENODEV; |
651 | if (cdev->private->state != DEV_STATE_ONLINE) { | 652 | if (scsw_actl(&sch->schib.scsw) != 0) |
652 | if (sch->schib.scsw.actl != 0) | ||
653 | return -EBUSY; | ||
654 | return -EINVAL; | ||
655 | } | ||
656 | if (sch->schib.scsw.actl != 0) | ||
657 | return -EBUSY; | 653 | return -EBUSY; |
654 | if (cdev->private->state != DEV_STATE_ONLINE) | ||
655 | return -EINVAL; | ||
658 | /* Are we doing path grouping? */ | 656 | /* Are we doing path grouping? */ |
659 | if (!cdev->private->options.pgroup) { | 657 | if (!cdev->private->options.pgroup) { |
660 | /* No, set state offline immediately. */ | 658 | /* No, set state offline immediately. */ |
@@ -729,9 +727,9 @@ ccw_device_online_verify(struct ccw_device *cdev, enum dev_event dev_event) | |||
729 | */ | 727 | */ |
730 | stsch(sch->schid, &sch->schib); | 728 | stsch(sch->schid, &sch->schib); |
731 | 729 | ||
732 | if (sch->schib.scsw.actl != 0 || | 730 | if (scsw_actl(&sch->schib.scsw) != 0 || |
733 | (sch->schib.scsw.stctl & SCSW_STCTL_STATUS_PEND) || | 731 | (scsw_stctl(&sch->schib.scsw) & SCSW_STCTL_STATUS_PEND) || |
734 | (cdev->private->irb.scsw.stctl & SCSW_STCTL_STATUS_PEND)) { | 732 | (scsw_stctl(&cdev->private->irb.scsw) & SCSW_STCTL_STATUS_PEND)) { |
735 | /* | 733 | /* |
736 | * No final status yet or final status not yet delivered | 734 | * No final status yet or final status not yet delivered |
737 | * to the device driver. Can't do path verfication now, | 735 | * to the device driver. Can't do path verfication now, |
@@ -756,10 +754,8 @@ ccw_device_irq(struct ccw_device *cdev, enum dev_event dev_event) | |||
756 | 754 | ||
757 | irb = (struct irb *) __LC_IRB; | 755 | irb = (struct irb *) __LC_IRB; |
758 | /* Check for unsolicited interrupt. */ | 756 | /* Check for unsolicited interrupt. */ |
759 | if ((irb->scsw.stctl == | 757 | if (!scsw_is_solicited(&irb->scsw)) { |
760 | (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) | 758 | if ((irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) && |
761 | && (!irb->scsw.cc)) { | ||
762 | if ((irb->scsw.dstat & DEV_STAT_UNIT_CHECK) && | ||
763 | !irb->esw.esw0.erw.cons) { | 759 | !irb->esw.esw0.erw.cons) { |
764 | /* Unit check but no sense data. Need basic sense. */ | 760 | /* Unit check but no sense data. Need basic sense. */ |
765 | if (ccw_device_do_sense(cdev, irb) != 0) | 761 | if (ccw_device_do_sense(cdev, irb) != 0) |
@@ -822,9 +818,9 @@ ccw_device_w4sense(struct ccw_device *cdev, enum dev_event dev_event) | |||
822 | 818 | ||
823 | irb = (struct irb *) __LC_IRB; | 819 | irb = (struct irb *) __LC_IRB; |
824 | /* Check for unsolicited interrupt. */ | 820 | /* Check for unsolicited interrupt. */ |
825 | if (irb->scsw.stctl == | 821 | if (scsw_stctl(&irb->scsw) == |
826 | (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) { | 822 | (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) { |
827 | if (irb->scsw.cc == 1) | 823 | if (scsw_cc(&irb->scsw) == 1) |
828 | /* Basic sense hasn't started. Try again. */ | 824 | /* Basic sense hasn't started. Try again. */ |
829 | ccw_device_do_sense(cdev, irb); | 825 | ccw_device_do_sense(cdev, irb); |
830 | else { | 826 | else { |
@@ -842,7 +838,8 @@ ccw_device_w4sense(struct ccw_device *cdev, enum dev_event dev_event) | |||
842 | * only deliver the halt/clear interrupt to the device driver as if it | 838 | * only deliver the halt/clear interrupt to the device driver as if it |
843 | * had killed the original request. | 839 | * had killed the original request. |
844 | */ | 840 | */ |
845 | if (irb->scsw.fctl & (SCSW_FCTL_CLEAR_FUNC | SCSW_FCTL_HALT_FUNC)) { | 841 | if (scsw_fctl(&irb->scsw) & |
842 | (SCSW_FCTL_CLEAR_FUNC | SCSW_FCTL_HALT_FUNC)) { | ||
846 | /* Retry Basic Sense if requested. */ | 843 | /* Retry Basic Sense if requested. */ |
847 | if (cdev->private->flags.intretry) { | 844 | if (cdev->private->flags.intretry) { |
848 | cdev->private->flags.intretry = 0; | 845 | cdev->private->flags.intretry = 0; |
@@ -949,9 +946,9 @@ ccw_device_stlck_done(struct ccw_device *cdev, enum dev_event dev_event) | |||
949 | case DEV_EVENT_INTERRUPT: | 946 | case DEV_EVENT_INTERRUPT: |
950 | irb = (struct irb *) __LC_IRB; | 947 | irb = (struct irb *) __LC_IRB; |
951 | /* Check for unsolicited interrupt. */ | 948 | /* Check for unsolicited interrupt. */ |
952 | if ((irb->scsw.stctl == | 949 | if ((scsw_stctl(&irb->scsw) == |
953 | (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) && | 950 | (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) && |
954 | (!irb->scsw.cc)) | 951 | (!scsw_cc(&irb->scsw))) |
955 | /* FIXME: we should restart stlck here, but this | 952 | /* FIXME: we should restart stlck here, but this |
956 | * is extremely unlikely ... */ | 953 | * is extremely unlikely ... */ |
957 | goto out_wakeup; | 954 | goto out_wakeup; |