Commit 69f5576f authored by Sebastian Ott's avatar Sebastian Ott Committed by Martin Schwidefsky

s390/cio: dont abort verification after missing irq

Do not abort path verification when waiting for an interrupt timed out.
Use path_noirq_mask to keep track of the paths used for this (also
maintain a path_notoper_mask for debugging purposes). If the timeout
happend to be during an operation where we query or alter the state of
path groups set the pgid_unknown flag.

With this change we allow usage of devices which have such ill-behaved
paths (if at least one path is operational).
Reviewed-by: default avatarPeter Oberparleiter <peter.oberparleiter@de.ibm.com>
Signed-off-by: default avatarSebastian Ott <sebott@linux.vnet.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent b4b3d128
...@@ -102,10 +102,20 @@ static void nop_callback(struct ccw_device *cdev, void *data, int rc) ...@@ -102,10 +102,20 @@ static void nop_callback(struct ccw_device *cdev, void *data, int rc)
struct subchannel *sch = to_subchannel(cdev->dev.parent); struct subchannel *sch = to_subchannel(cdev->dev.parent);
struct ccw_request *req = &cdev->private->req; struct ccw_request *req = &cdev->private->req;
if (rc == 0) switch (rc) {
case 0:
sch->vpm |= req->lpm; sch->vpm |= req->lpm;
else if (rc != -EACCES) break;
case -ETIME:
cdev->private->path_noirq_mask |= req->lpm;
break;
case -EACCES:
cdev->private->path_notoper_mask |= req->lpm;
break;
default:
goto err; goto err;
}
/* Continue on the next path. */
req->lpm >>= 1; req->lpm >>= 1;
nop_do(cdev); nop_do(cdev);
return; return;
...@@ -174,7 +184,12 @@ static void spid_callback(struct ccw_device *cdev, void *data, int rc) ...@@ -174,7 +184,12 @@ static void spid_callback(struct ccw_device *cdev, void *data, int rc)
case 0: case 0:
sch->vpm |= req->lpm & sch->opm; sch->vpm |= req->lpm & sch->opm;
break; break;
case -ETIME:
cdev->private->flags.pgid_unknown = 1;
cdev->private->path_noirq_mask |= req->lpm;
break;
case -EACCES: case -EACCES:
cdev->private->path_notoper_mask |= req->lpm;
break; break;
case -EOPNOTSUPP: case -EOPNOTSUPP:
if (cdev->private->flags.mpath) { if (cdev->private->flags.mpath) {
...@@ -404,10 +419,21 @@ static void snid_callback(struct ccw_device *cdev, void *data, int rc) ...@@ -404,10 +419,21 @@ static void snid_callback(struct ccw_device *cdev, void *data, int rc)
{ {
struct ccw_request *req = &cdev->private->req; struct ccw_request *req = &cdev->private->req;
if (rc == 0) switch (rc) {
case 0:
cdev->private->pgid_valid_mask |= req->lpm; cdev->private->pgid_valid_mask |= req->lpm;
else if (rc != -EACCES) break;
case -ETIME:
cdev->private->flags.pgid_unknown = 1;
cdev->private->path_noirq_mask |= req->lpm;
break;
case -EACCES:
cdev->private->path_notoper_mask |= req->lpm;
break;
default:
goto err; goto err;
}
/* Continue on the next path. */
req->lpm >>= 1; req->lpm >>= 1;
snid_do(cdev); snid_do(cdev);
return; return;
...@@ -427,6 +453,13 @@ static void verify_start(struct ccw_device *cdev) ...@@ -427,6 +453,13 @@ static void verify_start(struct ccw_device *cdev)
sch->vpm = 0; sch->vpm = 0;
sch->lpm = sch->schib.pmcw.pam; sch->lpm = sch->schib.pmcw.pam;
/* Initialize PGID data. */
memset(cdev->private->pgid, 0, sizeof(cdev->private->pgid));
cdev->private->pgid_valid_mask = 0;
cdev->private->pgid_todo_mask = sch->schib.pmcw.pam;
cdev->private->path_notoper_mask = 0;
/* Initialize request data. */ /* Initialize request data. */
memset(req, 0, sizeof(*req)); memset(req, 0, sizeof(*req));
req->timeout = PGID_TIMEOUT; req->timeout = PGID_TIMEOUT;
...@@ -459,14 +492,8 @@ static void verify_start(struct ccw_device *cdev) ...@@ -459,14 +492,8 @@ static void verify_start(struct ccw_device *cdev)
*/ */
void ccw_device_verify_start(struct ccw_device *cdev) void ccw_device_verify_start(struct ccw_device *cdev)
{ {
struct subchannel *sch = to_subchannel(cdev->dev.parent);
CIO_TRACE_EVENT(4, "vrfy"); CIO_TRACE_EVENT(4, "vrfy");
CIO_HEX_EVENT(4, &cdev->private->dev_id, sizeof(cdev->private->dev_id)); CIO_HEX_EVENT(4, &cdev->private->dev_id, sizeof(cdev->private->dev_id));
/* Initialize PGID data. */
memset(cdev->private->pgid, 0, sizeof(cdev->private->pgid));
cdev->private->pgid_valid_mask = 0;
cdev->private->pgid_todo_mask = sch->schib.pmcw.pam;
/* /*
* Initialize pathgroup and multipath state with target values. * Initialize pathgroup and multipath state with target values.
* They may change in the course of path verification. * They may change in the course of path verification.
...@@ -474,6 +501,7 @@ void ccw_device_verify_start(struct ccw_device *cdev) ...@@ -474,6 +501,7 @@ void ccw_device_verify_start(struct ccw_device *cdev)
cdev->private->flags.pgroup = cdev->private->options.pgroup; cdev->private->flags.pgroup = cdev->private->options.pgroup;
cdev->private->flags.mpath = cdev->private->options.mpath; cdev->private->flags.mpath = cdev->private->options.mpath;
cdev->private->flags.doverify = 0; cdev->private->flags.doverify = 0;
cdev->private->path_noirq_mask = 0;
verify_start(cdev); verify_start(cdev);
} }
......
...@@ -126,6 +126,10 @@ struct ccw_device_private { ...@@ -126,6 +126,10 @@ struct ccw_device_private {
u8 pgid_valid_mask; /* mask of valid PGIDs */ u8 pgid_valid_mask; /* mask of valid PGIDs */
u8 pgid_todo_mask; /* mask of PGIDs to be adjusted */ u8 pgid_todo_mask; /* mask of PGIDs to be adjusted */
u8 pgid_reset_mask; /* mask of PGIDs which were reset */ u8 pgid_reset_mask; /* mask of PGIDs which were reset */
u8 path_noirq_mask; /* mask of paths for which no irq was
received */
u8 path_notoper_mask; /* mask of paths which were found
not operable */
u8 path_gone_mask; /* mask of paths, that became unavailable */ u8 path_gone_mask; /* mask of paths, that became unavailable */
u8 path_new_mask; /* mask of paths, that became available */ u8 path_new_mask; /* mask of paths, that became available */
struct { struct {
...@@ -145,6 +149,7 @@ struct ccw_device_private { ...@@ -145,6 +149,7 @@ struct ccw_device_private {
unsigned int resuming:1; /* recognition while resume */ unsigned int resuming:1; /* recognition while resume */
unsigned int pgroup:1; /* pathgroup is set up */ unsigned int pgroup:1; /* pathgroup is set up */
unsigned int mpath:1; /* multipathing is set up */ unsigned int mpath:1; /* multipathing is set up */
unsigned int pgid_unknown:1;/* unknown pgid state */
unsigned int initialized:1; /* set if initial reference held */ unsigned int initialized:1; /* set if initial reference held */
} __attribute__((packed)) flags; } __attribute__((packed)) flags;
unsigned long intparm; /* user interruption parameter */ unsigned long intparm; /* user interruption parameter */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment