diff options
| author | Michael Ernst <mernst@de.ibm.com> | 2010-05-26 17:27:08 -0400 |
|---|---|---|
| committer | Martin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com> | 2010-05-26 17:27:09 -0400 |
| commit | 094f2100d6bb16ef0c4f82167cc55173ca22ee93 (patch) | |
| tree | 5e6540cc332b1b83216d3dfa037ea9ac50b9aacc | |
| parent | c560d105a197464603247bf55962fc7f23c8cb62 (diff) | |
[S390] cio: unit check handling during internal I/O
Send unit checks that occur during internal I/O to the device driver
and react according to its return code.
Signed-off-by: Michael Ernst <mernst@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
| -rw-r--r-- | arch/s390/include/asm/ccwdev.h | 10 | ||||
| -rw-r--r-- | drivers/s390/cio/ccwreq.c | 15 |
2 files changed, 25 insertions, 0 deletions
diff --git a/arch/s390/include/asm/ccwdev.h b/arch/s390/include/asm/ccwdev.h index f4bd346a52d3..1c0030f9b890 100644 --- a/arch/s390/include/asm/ccwdev.h +++ b/arch/s390/include/asm/ccwdev.h | |||
| @@ -91,6 +91,14 @@ struct ccw_device { | |||
| 91 | void (*handler) (struct ccw_device *, unsigned long, struct irb *); | 91 | void (*handler) (struct ccw_device *, unsigned long, struct irb *); |
| 92 | }; | 92 | }; |
| 93 | 93 | ||
| 94 | /* | ||
| 95 | * Possible CIO actions triggered by the unit check handler. | ||
| 96 | */ | ||
| 97 | enum uc_todo { | ||
| 98 | UC_TODO_RETRY, | ||
| 99 | UC_TODO_RETRY_ON_NEW_PATH, | ||
| 100 | UC_TODO_STOP | ||
| 101 | }; | ||
| 94 | 102 | ||
| 95 | /** | 103 | /** |
| 96 | * struct ccw driver - device driver for channel attached devices | 104 | * struct ccw driver - device driver for channel attached devices |
| @@ -107,6 +115,7 @@ struct ccw_device { | |||
| 107 | * @freeze: callback for freezing during hibernation snapshotting | 115 | * @freeze: callback for freezing during hibernation snapshotting |
| 108 | * @thaw: undo work done in @freeze | 116 | * @thaw: undo work done in @freeze |
| 109 | * @restore: callback for restoring after hibernation | 117 | * @restore: callback for restoring after hibernation |
| 118 | * @uc_handler: callback for unit check handler | ||
| 110 | * @driver: embedded device driver structure | 119 | * @driver: embedded device driver structure |
| 111 | * @name: device driver name | 120 | * @name: device driver name |
| 112 | */ | 121 | */ |
| @@ -124,6 +133,7 @@ struct ccw_driver { | |||
| 124 | int (*freeze)(struct ccw_device *); | 133 | int (*freeze)(struct ccw_device *); |
| 125 | int (*thaw) (struct ccw_device *); | 134 | int (*thaw) (struct ccw_device *); |
| 126 | int (*restore)(struct ccw_device *); | 135 | int (*restore)(struct ccw_device *); |
| 136 | enum uc_todo (*uc_handler) (struct ccw_device *, struct irb *); | ||
| 127 | struct device_driver driver; | 137 | struct device_driver driver; |
| 128 | char *name; | 138 | char *name; |
| 129 | }; | 139 | }; |
diff --git a/drivers/s390/cio/ccwreq.c b/drivers/s390/cio/ccwreq.c index 37df42af05ec..7f206ed44fdf 100644 --- a/drivers/s390/cio/ccwreq.c +++ b/drivers/s390/cio/ccwreq.c | |||
| @@ -159,6 +159,7 @@ static enum io_status ccwreq_status(struct ccw_device *cdev, struct irb *lcirb) | |||
| 159 | { | 159 | { |
| 160 | struct irb *irb = &cdev->private->irb; | 160 | struct irb *irb = &cdev->private->irb; |
| 161 | struct cmd_scsw *scsw = &irb->scsw.cmd; | 161 | struct cmd_scsw *scsw = &irb->scsw.cmd; |
| 162 | enum uc_todo todo; | ||
| 162 | 163 | ||
| 163 | /* Perform BASIC SENSE if needed. */ | 164 | /* Perform BASIC SENSE if needed. */ |
| 164 | if (ccw_device_accumulate_and_sense(cdev, lcirb)) | 165 | if (ccw_device_accumulate_and_sense(cdev, lcirb)) |
| @@ -178,6 +179,20 @@ static enum io_status ccwreq_status(struct ccw_device *cdev, struct irb *lcirb) | |||
| 178 | /* Check for command reject. */ | 179 | /* Check for command reject. */ |
| 179 | if (irb->ecw[0] & SNS0_CMD_REJECT) | 180 | if (irb->ecw[0] & SNS0_CMD_REJECT) |
| 180 | return IO_REJECTED; | 181 | return IO_REJECTED; |
| 182 | /* Ask the driver what to do */ | ||
| 183 | if (cdev->drv && cdev->drv->uc_handler) { | ||
| 184 | todo = cdev->drv->uc_handler(cdev, lcirb); | ||
| 185 | switch (todo) { | ||
| 186 | case UC_TODO_RETRY: | ||
| 187 | return IO_STATUS_ERROR; | ||
| 188 | case UC_TODO_RETRY_ON_NEW_PATH: | ||
| 189 | return IO_PATH_ERROR; | ||
| 190 | case UC_TODO_STOP: | ||
| 191 | return IO_REJECTED; | ||
| 192 | default: | ||
| 193 | return IO_STATUS_ERROR; | ||
| 194 | } | ||
| 195 | } | ||
| 181 | /* Assume that unexpected SENSE data implies an error. */ | 196 | /* Assume that unexpected SENSE data implies an error. */ |
| 182 | return IO_STATUS_ERROR; | 197 | return IO_STATUS_ERROR; |
| 183 | } | 198 | } |
