[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>

authored by Michael Ernst and committed by Martin Schwidefsky 094f2100 c560d105

+25
+10
arch/s390/include/asm/ccwdev.h
··· 91 void (*handler) (struct ccw_device *, unsigned long, struct irb *); 92 }; 93 94 95 /** 96 * struct ccw driver - device driver for channel attached devices ··· 115 * @freeze: callback for freezing during hibernation snapshotting 116 * @thaw: undo work done in @freeze 117 * @restore: callback for restoring after hibernation 118 * @driver: embedded device driver structure 119 * @name: device driver name 120 */ ··· 133 int (*freeze)(struct ccw_device *); 134 int (*thaw) (struct ccw_device *); 135 int (*restore)(struct ccw_device *); 136 struct device_driver driver; 137 char *name; 138 };
··· 91 void (*handler) (struct ccw_device *, unsigned long, struct irb *); 92 }; 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 + }; 102 103 /** 104 * struct ccw driver - device driver for channel attached devices ··· 107 * @freeze: callback for freezing during hibernation snapshotting 108 * @thaw: undo work done in @freeze 109 * @restore: callback for restoring after hibernation 110 + * @uc_handler: callback for unit check handler 111 * @driver: embedded device driver structure 112 * @name: device driver name 113 */ ··· 124 int (*freeze)(struct ccw_device *); 125 int (*thaw) (struct ccw_device *); 126 int (*restore)(struct ccw_device *); 127 + enum uc_todo (*uc_handler) (struct ccw_device *, struct irb *); 128 struct device_driver driver; 129 char *name; 130 };
+15
drivers/s390/cio/ccwreq.c
··· 159 { 160 struct irb *irb = &cdev->private->irb; 161 struct cmd_scsw *scsw = &irb->scsw.cmd; 162 163 /* Perform BASIC SENSE if needed. */ 164 if (ccw_device_accumulate_and_sense(cdev, lcirb)) ··· 179 /* Check for command reject. */ 180 if (irb->ecw[0] & SNS0_CMD_REJECT) 181 return IO_REJECTED; 182 /* Assume that unexpected SENSE data implies an error. */ 183 return IO_STATUS_ERROR; 184 }
··· 159 { 160 struct irb *irb = &cdev->private->irb; 161 struct cmd_scsw *scsw = &irb->scsw.cmd; 162 + enum uc_todo todo; 163 164 /* Perform BASIC SENSE if needed. */ 165 if (ccw_device_accumulate_and_sense(cdev, lcirb)) ··· 178 /* Check for command reject. */ 179 if (irb->ecw[0] & SNS0_CMD_REJECT) 180 return IO_REJECTED; 181 + /* Ask the driver what to do */ 182 + if (cdev->drv && cdev->drv->uc_handler) { 183 + todo = cdev->drv->uc_handler(cdev, lcirb); 184 + switch (todo) { 185 + case UC_TODO_RETRY: 186 + return IO_STATUS_ERROR; 187 + case UC_TODO_RETRY_ON_NEW_PATH: 188 + return IO_PATH_ERROR; 189 + case UC_TODO_STOP: 190 + return IO_REJECTED; 191 + default: 192 + return IO_STATUS_ERROR; 193 + } 194 + } 195 /* Assume that unexpected SENSE data implies an error. */ 196 return IO_STATUS_ERROR; 197 }