aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio/device_pgid.c
diff options
context:
space:
mode:
authorPeter Oberparleiter <peter.oberparleiter@de.ibm.com>2009-12-07 06:51:30 -0500
committerMartin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com>2009-12-07 06:51:31 -0500
commit454e1fa1ebae7cff707b2e3f12b775c263c8408b (patch)
treeeab290fcacd6faaf7e01e3a637cb9678bb367c66 /drivers/s390/cio/device_pgid.c
parent4257aaecffab77bad43e12057f56a5590b360f9f (diff)
[S390] cio: split PGID settings and status
Split setting (driver wants feature enabled) and status (feature setup was successful) for PGID related ccw device features so that setup errors can be detected. Previously, incorrectly handled setup errors could in rare cases lead to erratic I/O behavior and permanently unusuable devices. Signed-off-by: Peter Oberparleiter <peter.oberparleiter@de.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.c33
1 files changed, 20 insertions, 13 deletions
diff --git a/drivers/s390/cio/device_pgid.c b/drivers/s390/cio/device_pgid.c
index ce493144b054..3323042ba755 100644
--- a/drivers/s390/cio/device_pgid.c
+++ b/drivers/s390/cio/device_pgid.c
@@ -30,8 +30,8 @@ static void verify_done(struct ccw_device *cdev, int rc)
30{ 30{
31 struct subchannel *sch = to_subchannel(cdev->dev.parent); 31 struct subchannel *sch = to_subchannel(cdev->dev.parent);
32 struct ccw_dev_id *id = &cdev->private->dev_id; 32 struct ccw_dev_id *id = &cdev->private->dev_id;
33 int mpath = !cdev->private->flags.pgid_single; 33 int mpath = cdev->private->flags.mpath;
34 int pgroup = cdev->private->options.pgroup; 34 int pgroup = cdev->private->flags.pgroup;
35 35
36 if (rc) 36 if (rc)
37 goto out; 37 goto out;
@@ -150,7 +150,7 @@ static void spid_do(struct ccw_device *cdev)
150 fn = SPID_FUNC_ESTABLISH; 150 fn = SPID_FUNC_ESTABLISH;
151 else 151 else
152 fn = SPID_FUNC_RESIGN; 152 fn = SPID_FUNC_RESIGN;
153 if (!cdev->private->flags.pgid_single) 153 if (cdev->private->flags.mpath)
154 fn |= SPID_FUNC_MULTI_PATH; 154 fn |= SPID_FUNC_MULTI_PATH;
155 spid_build_cp(cdev, fn); 155 spid_build_cp(cdev, fn);
156 ccw_request_start(cdev); 156 ccw_request_start(cdev);
@@ -177,13 +177,13 @@ static void spid_callback(struct ccw_device *cdev, void *data, int rc)
177 case -EACCES: 177 case -EACCES:
178 break; 178 break;
179 case -EOPNOTSUPP: 179 case -EOPNOTSUPP:
180 if (!cdev->private->flags.pgid_single) { 180 if (cdev->private->flags.mpath) {
181 /* Try without multipathing. */ 181 /* Try without multipathing. */
182 cdev->private->flags.pgid_single = 1; 182 cdev->private->flags.mpath = 0;
183 goto out_restart; 183 goto out_restart;
184 } 184 }
185 /* Try without pathgrouping. */ 185 /* Try without pathgrouping. */
186 cdev->private->options.pgroup = 0; 186 cdev->private->flags.pgroup = 0;
187 goto out_restart; 187 goto out_restart;
188 default: 188 default:
189 goto err; 189 goto err;
@@ -374,7 +374,7 @@ static void verify_start(struct ccw_device *cdev)
374 req->timeout = PGID_TIMEOUT; 374 req->timeout = PGID_TIMEOUT;
375 req->maxretries = PGID_RETRIES; 375 req->maxretries = PGID_RETRIES;
376 req->lpm = 0x80; 376 req->lpm = 0x80;
377 if (cdev->private->options.pgroup) { 377 if (cdev->private->flags.pgroup) {
378 req->callback = spid_callback; 378 req->callback = spid_callback;
379 spid_do(cdev); 379 spid_do(cdev);
380 } else { 380 } else {
@@ -400,10 +400,17 @@ void ccw_device_verify_start(struct ccw_device *cdev)
400 CIO_HEX_EVENT(4, &cdev->private->dev_id, sizeof(cdev->private->dev_id)); 400 CIO_HEX_EVENT(4, &cdev->private->dev_id, sizeof(cdev->private->dev_id));
401 if (!cdev->private->flags.pgid_rdy) { 401 if (!cdev->private->flags.pgid_rdy) {
402 /* No pathgrouping possible. */ 402 /* No pathgrouping possible. */
403 cdev->private->options.pgroup = 0; 403 cdev->private->flags.pgroup = 0;
404 cdev->private->flags.pgid_single = 1; 404 cdev->private->flags.mpath = 0;
405 } else 405 } else {
406 cdev->private->flags.pgid_single = 0; 406 /*
407 * Initialize pathgroup and multipath state with target values.
408 * They may change in the course of path verification.
409 */
410 cdev->private->flags.pgroup = cdev->private->options.pgroup;
411 cdev->private->flags.mpath = cdev->private->options.mpath;
412
413 }
407 cdev->private->flags.doverify = 0; 414 cdev->private->flags.doverify = 0;
408 verify_start(cdev); 415 verify_start(cdev);
409} 416}
@@ -419,7 +426,7 @@ static void disband_callback(struct ccw_device *cdev, void *data, int rc)
419 if (rc) 426 if (rc)
420 goto out; 427 goto out;
421 /* Ensure consistent multipathing state at device and channel. */ 428 /* Ensure consistent multipathing state at device and channel. */
422 cdev->private->flags.pgid_single = 1; 429 cdev->private->flags.mpath = 0;
423 if (sch->config.mp) { 430 if (sch->config.mp) {
424 sch->config.mp = 0; 431 sch->config.mp = 0;
425 rc = cio_commit_config(sch); 432 rc = cio_commit_config(sch);
@@ -453,7 +460,7 @@ void ccw_device_disband_start(struct ccw_device *cdev)
453 req->lpm = sch->schib.pmcw.pam & sch->opm; 460 req->lpm = sch->schib.pmcw.pam & sch->opm;
454 req->callback = disband_callback; 461 req->callback = disband_callback;
455 fn = SPID_FUNC_DISBAND; 462 fn = SPID_FUNC_DISBAND;
456 if (!cdev->private->flags.pgid_single) 463 if (cdev->private->flags.mpath)
457 fn |= SPID_FUNC_MULTI_PATH; 464 fn |= SPID_FUNC_MULTI_PATH;
458 spid_build_cp(cdev, fn); 465 spid_build_cp(cdev, fn);
459 ccw_request_start(cdev); 466 ccw_request_start(cdev);