[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>
This commit is contained in:
Michael Ernst 2010-05-26 23:27:08 +02:00 committed by Martin Schwidefsky
parent c560d105a1
commit 094f2100d6
2 changed files with 25 additions and 0 deletions

View File

@ -91,6 +91,14 @@ struct ccw_device {
void (*handler) (struct ccw_device *, unsigned long, struct irb *); void (*handler) (struct ccw_device *, unsigned long, struct irb *);
}; };
/*
* Possible CIO actions triggered by the unit check handler.
*/
enum uc_todo {
UC_TODO_RETRY,
UC_TODO_RETRY_ON_NEW_PATH,
UC_TODO_STOP
};
/** /**
* struct ccw driver - device driver for channel attached devices * struct ccw driver - device driver for channel attached devices
@ -107,6 +115,7 @@ struct ccw_device {
* @freeze: callback for freezing during hibernation snapshotting * @freeze: callback for freezing during hibernation snapshotting
* @thaw: undo work done in @freeze * @thaw: undo work done in @freeze
* @restore: callback for restoring after hibernation * @restore: callback for restoring after hibernation
* @uc_handler: callback for unit check handler
* @driver: embedded device driver structure * @driver: embedded device driver structure
* @name: device driver name * @name: device driver name
*/ */
@ -124,6 +133,7 @@ struct ccw_driver {
int (*freeze)(struct ccw_device *); int (*freeze)(struct ccw_device *);
int (*thaw) (struct ccw_device *); int (*thaw) (struct ccw_device *);
int (*restore)(struct ccw_device *); int (*restore)(struct ccw_device *);
enum uc_todo (*uc_handler) (struct ccw_device *, struct irb *);
struct device_driver driver; struct device_driver driver;
char *name; char *name;
}; };

View File

@ -159,6 +159,7 @@ static enum io_status ccwreq_status(struct ccw_device *cdev, struct irb *lcirb)
{ {
struct irb *irb = &cdev->private->irb; struct irb *irb = &cdev->private->irb;
struct cmd_scsw *scsw = &irb->scsw.cmd; struct cmd_scsw *scsw = &irb->scsw.cmd;
enum uc_todo todo;
/* Perform BASIC SENSE if needed. */ /* Perform BASIC SENSE if needed. */
if (ccw_device_accumulate_and_sense(cdev, lcirb)) 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)
/* Check for command reject. */ /* Check for command reject. */
if (irb->ecw[0] & SNS0_CMD_REJECT) if (irb->ecw[0] & SNS0_CMD_REJECT)
return IO_REJECTED; return IO_REJECTED;
/* Ask the driver what to do */
if (cdev->drv && cdev->drv->uc_handler) {
todo = cdev->drv->uc_handler(cdev, lcirb);
switch (todo) {
case UC_TODO_RETRY:
return IO_STATUS_ERROR;
case UC_TODO_RETRY_ON_NEW_PATH:
return IO_PATH_ERROR;
case UC_TODO_STOP:
return IO_REJECTED;
default:
return IO_STATUS_ERROR;
}
}
/* Assume that unexpected SENSE data implies an error. */ /* Assume that unexpected SENSE data implies an error. */
return IO_STATUS_ERROR; return IO_STATUS_ERROR;
} }