aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
authorSebastian Ott <sebott@linux.vnet.ibm.com>2013-01-28 13:29:43 -0500
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2013-02-14 09:55:07 -0500
commit69f5576f6c8c9d0f0b3670ee7c807a194b4c40f4 (patch)
tree0872aa245fb0c5b0a4decb14e7bd71726baa995e /drivers/s390
parentb4b3d128c821d70112ac0096d5c1440f5ed9f718 (diff)
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: Peter Oberparleiter <peter.oberparleiter@de.ibm.com> Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/cio/device_pgid.c48
-rw-r--r--drivers/s390/cio/io_sch.h5
2 files changed, 43 insertions, 10 deletions
diff --git a/drivers/s390/cio/device_pgid.c b/drivers/s390/cio/device_pgid.c
index 908d287f66c1..6f2987d8da99 100644
--- a/drivers/s390/cio/device_pgid.c
+++ b/drivers/s390/cio/device_pgid.c
@@ -102,10 +102,20 @@ static void nop_callback(struct ccw_device *cdev, void *data, int rc)
102 struct subchannel *sch = to_subchannel(cdev->dev.parent); 102 struct subchannel *sch = to_subchannel(cdev->dev.parent);
103 struct ccw_request *req = &cdev->private->req; 103 struct ccw_request *req = &cdev->private->req;
104 104
105 if (rc == 0) 105 switch (rc) {
106 case 0:
106 sch->vpm |= req->lpm; 107 sch->vpm |= req->lpm;
107 else if (rc != -EACCES) 108 break;
109 case -ETIME:
110 cdev->private->path_noirq_mask |= req->lpm;
111 break;
112 case -EACCES:
113 cdev->private->path_notoper_mask |= req->lpm;
114 break;
115 default:
108 goto err; 116 goto err;
117 }
118 /* Continue on the next path. */
109 req->lpm >>= 1; 119 req->lpm >>= 1;
110 nop_do(cdev); 120 nop_do(cdev);
111 return; 121 return;
@@ -174,7 +184,12 @@ static void spid_callback(struct ccw_device *cdev, void *data, int rc)
174 case 0: 184 case 0:
175 sch->vpm |= req->lpm & sch->opm; 185 sch->vpm |= req->lpm & sch->opm;
176 break; 186 break;
187 case -ETIME:
188 cdev->private->flags.pgid_unknown = 1;
189 cdev->private->path_noirq_mask |= req->lpm;
190 break;
177 case -EACCES: 191 case -EACCES:
192 cdev->private->path_notoper_mask |= req->lpm;
178 break; 193 break;
179 case -EOPNOTSUPP: 194 case -EOPNOTSUPP:
180 if (cdev->private->flags.mpath) { 195 if (cdev->private->flags.mpath) {
@@ -404,10 +419,21 @@ static void snid_callback(struct ccw_device *cdev, void *data, int rc)
404{ 419{
405 struct ccw_request *req = &cdev->private->req; 420 struct ccw_request *req = &cdev->private->req;
406 421
407 if (rc == 0) 422 switch (rc) {
423 case 0:
408 cdev->private->pgid_valid_mask |= req->lpm; 424 cdev->private->pgid_valid_mask |= req->lpm;
409 else if (rc != -EACCES) 425 break;
426 case -ETIME:
427 cdev->private->flags.pgid_unknown = 1;
428 cdev->private->path_noirq_mask |= req->lpm;
429 break;
430 case -EACCES:
431 cdev->private->path_notoper_mask |= req->lpm;
432 break;
433 default:
410 goto err; 434 goto err;
435 }
436 /* Continue on the next path. */
411 req->lpm >>= 1; 437 req->lpm >>= 1;
412 snid_do(cdev); 438 snid_do(cdev);
413 return; 439 return;
@@ -427,6 +453,13 @@ static void verify_start(struct ccw_device *cdev)
427 453
428 sch->vpm = 0; 454 sch->vpm = 0;
429 sch->lpm = sch->schib.pmcw.pam; 455 sch->lpm = sch->schib.pmcw.pam;
456
457 /* Initialize PGID data. */
458 memset(cdev->private->pgid, 0, sizeof(cdev->private->pgid));
459 cdev->private->pgid_valid_mask = 0;
460 cdev->private->pgid_todo_mask = sch->schib.pmcw.pam;
461 cdev->private->path_notoper_mask = 0;
462
430 /* Initialize request data. */ 463 /* Initialize request data. */
431 memset(req, 0, sizeof(*req)); 464 memset(req, 0, sizeof(*req));
432 req->timeout = PGID_TIMEOUT; 465 req->timeout = PGID_TIMEOUT;
@@ -459,14 +492,8 @@ static void verify_start(struct ccw_device *cdev)
459 */ 492 */
460void ccw_device_verify_start(struct ccw_device *cdev) 493void ccw_device_verify_start(struct ccw_device *cdev)
461{ 494{
462 struct subchannel *sch = to_subchannel(cdev->dev.parent);
463
464 CIO_TRACE_EVENT(4, "vrfy"); 495 CIO_TRACE_EVENT(4, "vrfy");
465 CIO_HEX_EVENT(4, &cdev->private->dev_id, sizeof(cdev->private->dev_id)); 496 CIO_HEX_EVENT(4, &cdev->private->dev_id, sizeof(cdev->private->dev_id));
466 /* Initialize PGID data. */
467 memset(cdev->private->pgid, 0, sizeof(cdev->private->pgid));
468 cdev->private->pgid_valid_mask = 0;
469 cdev->private->pgid_todo_mask = sch->schib.pmcw.pam;
470 /* 497 /*
471 * Initialize pathgroup and multipath state with target values. 498 * Initialize pathgroup and multipath state with target values.
472 * They may change in the course of path verification. 499 * They may change in the course of path verification.
@@ -474,6 +501,7 @@ void ccw_device_verify_start(struct ccw_device *cdev)
474 cdev->private->flags.pgroup = cdev->private->options.pgroup; 501 cdev->private->flags.pgroup = cdev->private->options.pgroup;
475 cdev->private->flags.mpath = cdev->private->options.mpath; 502 cdev->private->flags.mpath = cdev->private->options.mpath;
476 cdev->private->flags.doverify = 0; 503 cdev->private->flags.doverify = 0;
504 cdev->private->path_noirq_mask = 0;
477 verify_start(cdev); 505 verify_start(cdev);
478} 506}
479 507
diff --git a/drivers/s390/cio/io_sch.h b/drivers/s390/cio/io_sch.h
index 76253dfcc1be..b108f4a5c7dd 100644
--- a/drivers/s390/cio/io_sch.h
+++ b/drivers/s390/cio/io_sch.h
@@ -126,6 +126,10 @@ struct ccw_device_private {
126 u8 pgid_valid_mask; /* mask of valid PGIDs */ 126 u8 pgid_valid_mask; /* mask of valid PGIDs */
127 u8 pgid_todo_mask; /* mask of PGIDs to be adjusted */ 127 u8 pgid_todo_mask; /* mask of PGIDs to be adjusted */
128 u8 pgid_reset_mask; /* mask of PGIDs which were reset */ 128 u8 pgid_reset_mask; /* mask of PGIDs which were reset */
129 u8 path_noirq_mask; /* mask of paths for which no irq was
130 received */
131 u8 path_notoper_mask; /* mask of paths which were found
132 not operable */
129 u8 path_gone_mask; /* mask of paths, that became unavailable */ 133 u8 path_gone_mask; /* mask of paths, that became unavailable */
130 u8 path_new_mask; /* mask of paths, that became available */ 134 u8 path_new_mask; /* mask of paths, that became available */
131 struct { 135 struct {
@@ -145,6 +149,7 @@ struct ccw_device_private {
145 unsigned int resuming:1; /* recognition while resume */ 149 unsigned int resuming:1; /* recognition while resume */
146 unsigned int pgroup:1; /* pathgroup is set up */ 150 unsigned int pgroup:1; /* pathgroup is set up */
147 unsigned int mpath:1; /* multipathing is set up */ 151 unsigned int mpath:1; /* multipathing is set up */
152 unsigned int pgid_unknown:1;/* unknown pgid state */
148 unsigned int initialized:1; /* set if initial reference held */ 153 unsigned int initialized:1; /* set if initial reference held */
149 } __attribute__((packed)) flags; 154 } __attribute__((packed)) flags;
150 unsigned long intparm; /* user interruption parameter */ 155 unsigned long intparm; /* user interruption parameter */