aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Ernst <mernst@de.ibm.com>2010-05-26 17:27:08 -0400
committerMartin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com>2010-05-26 17:27:09 -0400
commit094f2100d6bb16ef0c4f82167cc55173ca22ee93 (patch)
tree5e6540cc332b1b83216d3dfa037ea9ac50b9aacc
parentc560d105a197464603247bf55962fc7f23c8cb62 (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.h10
-rw-r--r--drivers/s390/cio/ccwreq.c15
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 */
97enum 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 }