diff options
Diffstat (limited to 'drivers/s390/cio/device_fsm.c')
-rw-r--r-- | drivers/s390/cio/device_fsm.c | 49 |
1 files changed, 33 insertions, 16 deletions
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index dc9373031af0..cd31bb5177e6 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c | |||
@@ -39,31 +39,43 @@ static void ccw_timeout_log(struct ccw_device *cdev) | |||
39 | struct schib schib; | 39 | struct schib schib; |
40 | struct subchannel *sch; | 40 | struct subchannel *sch; |
41 | struct io_subchannel_private *private; | 41 | struct io_subchannel_private *private; |
42 | union orb *orb; | ||
42 | int cc; | 43 | int cc; |
43 | 44 | ||
44 | sch = to_subchannel(cdev->dev.parent); | 45 | sch = to_subchannel(cdev->dev.parent); |
45 | private = to_io_private(sch); | 46 | private = to_io_private(sch); |
47 | orb = &private->orb; | ||
46 | cc = stsch(sch->schid, &schib); | 48 | cc = stsch(sch->schid, &schib); |
47 | 49 | ||
48 | printk(KERN_WARNING "cio: ccw device timeout occurred at %llx, " | 50 | printk(KERN_WARNING "cio: ccw device timeout occurred at %llx, " |
49 | "device information:\n", get_clock()); | 51 | "device information:\n", get_clock()); |
50 | printk(KERN_WARNING "cio: orb:\n"); | 52 | printk(KERN_WARNING "cio: orb:\n"); |
51 | print_hex_dump(KERN_WARNING, "cio: ", DUMP_PREFIX_NONE, 16, 1, | 53 | print_hex_dump(KERN_WARNING, "cio: ", DUMP_PREFIX_NONE, 16, 1, |
52 | &private->orb, sizeof(private->orb), 0); | 54 | orb, sizeof(*orb), 0); |
53 | printk(KERN_WARNING "cio: ccw device bus id: %s\n", cdev->dev.bus_id); | 55 | printk(KERN_WARNING "cio: ccw device bus id: %s\n", cdev->dev.bus_id); |
54 | printk(KERN_WARNING "cio: subchannel bus id: %s\n", sch->dev.bus_id); | 56 | printk(KERN_WARNING "cio: subchannel bus id: %s\n", sch->dev.bus_id); |
55 | printk(KERN_WARNING "cio: subchannel lpm: %02x, opm: %02x, " | 57 | printk(KERN_WARNING "cio: subchannel lpm: %02x, opm: %02x, " |
56 | "vpm: %02x\n", sch->lpm, sch->opm, sch->vpm); | 58 | "vpm: %02x\n", sch->lpm, sch->opm, sch->vpm); |
57 | 59 | ||
58 | if ((void *)(addr_t)private->orb.cpa == &private->sense_ccw || | 60 | if (orb->tm.b) { |
59 | (void *)(addr_t)private->orb.cpa == cdev->private->iccws) | 61 | printk(KERN_WARNING "cio: orb indicates transport mode\n"); |
60 | printk(KERN_WARNING "cio: last channel program (intern):\n"); | 62 | printk(KERN_WARNING "cio: last tcw:\n"); |
61 | else | 63 | print_hex_dump(KERN_WARNING, "cio: ", DUMP_PREFIX_NONE, 16, 1, |
62 | printk(KERN_WARNING "cio: last channel program:\n"); | 64 | (void *)(addr_t)orb->tm.tcw, |
63 | 65 | sizeof(struct tcw), 0); | |
64 | print_hex_dump(KERN_WARNING, "cio: ", DUMP_PREFIX_NONE, 16, 1, | 66 | } else { |
65 | (void *)(addr_t)private->orb.cpa, | 67 | printk(KERN_WARNING "cio: orb indicates command mode\n"); |
66 | sizeof(struct ccw1), 0); | 68 | if ((void *)(addr_t)orb->cmd.cpa == &private->sense_ccw || |
69 | (void *)(addr_t)orb->cmd.cpa == cdev->private->iccws) | ||
70 | printk(KERN_WARNING "cio: last channel program " | ||
71 | "(intern):\n"); | ||
72 | else | ||
73 | printk(KERN_WARNING "cio: last channel program:\n"); | ||
74 | |||
75 | print_hex_dump(KERN_WARNING, "cio: ", DUMP_PREFIX_NONE, 16, 1, | ||
76 | (void *)(addr_t)orb->cmd.cpa, | ||
77 | sizeof(struct ccw1), 0); | ||
78 | } | ||
67 | printk(KERN_WARNING "cio: ccw device state: %d\n", | 79 | printk(KERN_WARNING "cio: ccw device state: %d\n", |
68 | cdev->private->state); | 80 | cdev->private->state); |
69 | printk(KERN_WARNING "cio: store subchannel returned: cc=%d\n", cc); | 81 | printk(KERN_WARNING "cio: store subchannel returned: cc=%d\n", cc); |
@@ -135,10 +147,13 @@ ccw_device_cancel_halt_clear(struct ccw_device *cdev) | |||
135 | /* Stage 1: cancel io. */ | 147 | /* Stage 1: cancel io. */ |
136 | if (!(scsw_actl(&sch->schib.scsw) & SCSW_ACTL_HALT_PEND) && | 148 | if (!(scsw_actl(&sch->schib.scsw) & SCSW_ACTL_HALT_PEND) && |
137 | !(scsw_actl(&sch->schib.scsw) & SCSW_ACTL_CLEAR_PEND)) { | 149 | !(scsw_actl(&sch->schib.scsw) & SCSW_ACTL_CLEAR_PEND)) { |
138 | ret = cio_cancel(sch); | 150 | if (!scsw_is_tm(&sch->schib.scsw)) { |
139 | if (ret != -EINVAL) | 151 | ret = cio_cancel(sch); |
140 | return ret; | 152 | if (ret != -EINVAL) |
141 | /* cancel io unsuccessful. From now on it is asynchronous. */ | 153 | return ret; |
154 | } | ||
155 | /* cancel io unsuccessful or not applicable (transport mode). | ||
156 | * Continue with asynchronous instructions. */ | ||
142 | cdev->private->iretry = 3; /* 3 halt retries. */ | 157 | cdev->private->iretry = 3; /* 3 halt retries. */ |
143 | } | 158 | } |
144 | if (!(scsw_actl(&sch->schib.scsw) & SCSW_ACTL_CLEAR_PEND)) { | 159 | if (!(scsw_actl(&sch->schib.scsw) & SCSW_ACTL_CLEAR_PEND)) { |
@@ -751,11 +766,13 @@ static void | |||
751 | ccw_device_irq(struct ccw_device *cdev, enum dev_event dev_event) | 766 | ccw_device_irq(struct ccw_device *cdev, enum dev_event dev_event) |
752 | { | 767 | { |
753 | struct irb *irb; | 768 | struct irb *irb; |
769 | int is_cmd; | ||
754 | 770 | ||
755 | irb = (struct irb *) __LC_IRB; | 771 | irb = (struct irb *) __LC_IRB; |
772 | is_cmd = !scsw_is_tm(&irb->scsw); | ||
756 | /* Check for unsolicited interrupt. */ | 773 | /* Check for unsolicited interrupt. */ |
757 | if (!scsw_is_solicited(&irb->scsw)) { | 774 | if (!scsw_is_solicited(&irb->scsw)) { |
758 | if ((irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) && | 775 | if (is_cmd && (irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) && |
759 | !irb->esw.esw0.erw.cons) { | 776 | !irb->esw.esw0.erw.cons) { |
760 | /* Unit check but no sense data. Need basic sense. */ | 777 | /* Unit check but no sense data. Need basic sense. */ |
761 | if (ccw_device_do_sense(cdev, irb) != 0) | 778 | if (ccw_device_do_sense(cdev, irb) != 0) |
@@ -774,7 +791,7 @@ call_handler_unsol: | |||
774 | } | 791 | } |
775 | /* Accumulate status and find out if a basic sense is needed. */ | 792 | /* Accumulate status and find out if a basic sense is needed. */ |
776 | ccw_device_accumulate_irb(cdev, irb); | 793 | ccw_device_accumulate_irb(cdev, irb); |
777 | if (cdev->private->flags.dosense) { | 794 | if (is_cmd && cdev->private->flags.dosense) { |
778 | if (ccw_device_do_sense(cdev, irb) == 0) { | 795 | if (ccw_device_do_sense(cdev, irb) == 0) { |
779 | cdev->private->state = DEV_STATE_W4SENSE; | 796 | cdev->private->state = DEV_STATE_W4SENSE; |
780 | } | 797 | } |