diff options
author | Sebastian Ott <sebott@linux.vnet.ibm.com> | 2013-01-28 13:29:43 -0500 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2013-02-14 09:55:07 -0500 |
commit | 69f5576f6c8c9d0f0b3670ee7c807a194b4c40f4 (patch) | |
tree | 0872aa245fb0c5b0a4decb14e7bd71726baa995e /drivers/s390/cio/device_pgid.c | |
parent | b4b3d128c821d70112ac0096d5c1440f5ed9f718 (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/cio/device_pgid.c')
-rw-r--r-- | drivers/s390/cio/device_pgid.c | 48 |
1 files changed, 38 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 | */ |
460 | void ccw_device_verify_start(struct ccw_device *cdev) | 493 | void 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 | ||