aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/s390/include/asm/ccwdev.h4
-rw-r--r--drivers/s390/block/dasd.c7
-rw-r--r--drivers/s390/block/dasd_eckd.c12
-rw-r--r--drivers/s390/char/tape_core.c3
-rw-r--r--drivers/s390/cio/device_fsm.c2
-rw-r--r--drivers/s390/cio/device_ops.c27
-rw-r--r--drivers/s390/cio/device_pgid.c33
-rw-r--r--drivers/s390/cio/io_sch.h4
8 files changed, 68 insertions, 24 deletions
diff --git a/arch/s390/include/asm/ccwdev.h b/arch/s390/include/asm/ccwdev.h
index 2a5419551176..f4bd346a52d3 100644
--- a/arch/s390/include/asm/ccwdev.h
+++ b/arch/s390/include/asm/ccwdev.h
@@ -142,6 +142,8 @@ struct ccw1;
142extern int ccw_device_set_options_mask(struct ccw_device *, unsigned long); 142extern int ccw_device_set_options_mask(struct ccw_device *, unsigned long);
143extern int ccw_device_set_options(struct ccw_device *, unsigned long); 143extern int ccw_device_set_options(struct ccw_device *, unsigned long);
144extern void ccw_device_clear_options(struct ccw_device *, unsigned long); 144extern void ccw_device_clear_options(struct ccw_device *, unsigned long);
145int ccw_device_is_pathgroup(struct ccw_device *cdev);
146int ccw_device_is_multipath(struct ccw_device *cdev);
145 147
146/* Allow for i/o completion notification after primary interrupt status. */ 148/* Allow for i/o completion notification after primary interrupt status. */
147#define CCWDEV_EARLY_NOTIFICATION 0x0001 149#define CCWDEV_EARLY_NOTIFICATION 0x0001
@@ -151,6 +153,8 @@ extern void ccw_device_clear_options(struct ccw_device *, unsigned long);
151#define CCWDEV_DO_PATHGROUP 0x0004 153#define CCWDEV_DO_PATHGROUP 0x0004
152/* Allow forced onlining of boxed devices. */ 154/* Allow forced onlining of boxed devices. */
153#define CCWDEV_ALLOW_FORCE 0x0008 155#define CCWDEV_ALLOW_FORCE 0x0008
156/* Try to use multipath mode. */
157#define CCWDEV_DO_MULTIPATH 0x0010
154 158
155extern int ccw_device_start(struct ccw_device *, struct ccw1 *, 159extern int ccw_device_start(struct ccw_device *, struct ccw1 *,
156 unsigned long, __u8, unsigned long); 160 unsigned long, __u8, unsigned long);
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index aaccc8ecfa8f..58ffbd1d04a1 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -2208,13 +2208,6 @@ int dasd_generic_probe(struct ccw_device *cdev,
2208{ 2208{
2209 int ret; 2209 int ret;
2210 2210
2211 ret = ccw_device_set_options(cdev, CCWDEV_DO_PATHGROUP);
2212 if (ret) {
2213 DBF_EVENT(DBF_WARNING,
2214 "dasd_generic_probe: could not set ccw-device options "
2215 "for %s\n", dev_name(&cdev->dev));
2216 return ret;
2217 }
2218 ret = dasd_add_sysfs_files(cdev); 2211 ret = dasd_add_sysfs_files(cdev);
2219 if (ret) { 2212 if (ret) {
2220 DBF_EVENT(DBF_WARNING, 2213 DBF_EVENT(DBF_WARNING,
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index 417b97cd3f94..a8ec0731609e 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -86,7 +86,8 @@ dasd_eckd_probe (struct ccw_device *cdev)
86 int ret; 86 int ret;
87 87
88 /* set ECKD specific ccw-device options */ 88 /* set ECKD specific ccw-device options */
89 ret = ccw_device_set_options(cdev, CCWDEV_ALLOW_FORCE); 89 ret = ccw_device_set_options(cdev, CCWDEV_ALLOW_FORCE |
90 CCWDEV_DO_PATHGROUP | CCWDEV_DO_MULTIPATH);
90 if (ret) { 91 if (ret) {
91 DBF_EVENT(DBF_WARNING, 92 DBF_EVENT(DBF_WARNING,
92 "dasd_eckd_probe: could not set ccw-device options " 93 "dasd_eckd_probe: could not set ccw-device options "
@@ -1090,6 +1091,15 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
1090 struct dasd_block *block; 1091 struct dasd_block *block;
1091 int is_known, rc; 1092 int is_known, rc;
1092 1093
1094 if (!ccw_device_is_pathgroup(device->cdev)) {
1095 dev_warn(&device->cdev->dev,
1096 "A channel path group could not be established\n");
1097 return -EIO;
1098 }
1099 if (!ccw_device_is_multipath(device->cdev)) {
1100 dev_info(&device->cdev->dev,
1101 "The DASD is not operating in multipath mode\n");
1102 }
1093 private = (struct dasd_eckd_private *) device->private; 1103 private = (struct dasd_eckd_private *) device->private;
1094 if (!private) { 1104 if (!private) {
1095 private = kzalloc(sizeof(*private), GFP_KERNEL | GFP_DMA); 1105 private = kzalloc(sizeof(*private), GFP_KERNEL | GFP_DMA);
diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c
index 5cd31e071647..27503a778fcb 100644
--- a/drivers/s390/char/tape_core.c
+++ b/drivers/s390/char/tape_core.c
@@ -579,7 +579,8 @@ tape_generic_probe(struct ccw_device *cdev)
579 device = tape_alloc_device(); 579 device = tape_alloc_device();
580 if (IS_ERR(device)) 580 if (IS_ERR(device))
581 return -ENODEV; 581 return -ENODEV;
582 ccw_device_set_options(cdev, CCWDEV_DO_PATHGROUP); 582 ccw_device_set_options(cdev, CCWDEV_DO_PATHGROUP |
583 CCWDEV_DO_MULTIPATH);
583 ret = sysfs_create_group(&cdev->dev.kobj, &tape_attr_group); 584 ret = sysfs_create_group(&cdev->dev.kobj, &tape_attr_group);
584 if (ret) { 585 if (ret) {
585 tape_put_device(device); 586 tape_put_device(device);
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index 349d8c52c0d0..d6e315dc0f98 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -601,7 +601,7 @@ ccw_device_offline(struct ccw_device *cdev)
601 if (cdev->private->state != DEV_STATE_ONLINE) 601 if (cdev->private->state != DEV_STATE_ONLINE)
602 return -EINVAL; 602 return -EINVAL;
603 /* Are we doing path grouping? */ 603 /* Are we doing path grouping? */
604 if (!cdev->private->options.pgroup) { 604 if (!cdev->private->flags.pgroup) {
605 /* No, set state offline immediately. */ 605 /* No, set state offline immediately. */
606 ccw_device_done(cdev, DEV_STATE_OFFLINE); 606 ccw_device_done(cdev, DEV_STATE_OFFLINE);
607 return 0; 607 return 0;
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c
index 5ab90ec42318..d4be16acebe4 100644
--- a/drivers/s390/cio/device_ops.c
+++ b/drivers/s390/cio/device_ops.c
@@ -46,6 +46,7 @@ int ccw_device_set_options_mask(struct ccw_device *cdev, unsigned long flags)
46 cdev->private->options.repall = (flags & CCWDEV_REPORT_ALL) != 0; 46 cdev->private->options.repall = (flags & CCWDEV_REPORT_ALL) != 0;
47 cdev->private->options.pgroup = (flags & CCWDEV_DO_PATHGROUP) != 0; 47 cdev->private->options.pgroup = (flags & CCWDEV_DO_PATHGROUP) != 0;
48 cdev->private->options.force = (flags & CCWDEV_ALLOW_FORCE) != 0; 48 cdev->private->options.force = (flags & CCWDEV_ALLOW_FORCE) != 0;
49 cdev->private->options.mpath = (flags & CCWDEV_DO_MULTIPATH) != 0;
49 return 0; 50 return 0;
50} 51}
51 52
@@ -74,6 +75,7 @@ int ccw_device_set_options(struct ccw_device *cdev, unsigned long flags)
74 cdev->private->options.repall |= (flags & CCWDEV_REPORT_ALL) != 0; 75 cdev->private->options.repall |= (flags & CCWDEV_REPORT_ALL) != 0;
75 cdev->private->options.pgroup |= (flags & CCWDEV_DO_PATHGROUP) != 0; 76 cdev->private->options.pgroup |= (flags & CCWDEV_DO_PATHGROUP) != 0;
76 cdev->private->options.force |= (flags & CCWDEV_ALLOW_FORCE) != 0; 77 cdev->private->options.force |= (flags & CCWDEV_ALLOW_FORCE) != 0;
78 cdev->private->options.mpath |= (flags & CCWDEV_DO_MULTIPATH) != 0;
77 return 0; 79 return 0;
78} 80}
79 81
@@ -90,9 +92,34 @@ void ccw_device_clear_options(struct ccw_device *cdev, unsigned long flags)
90 cdev->private->options.repall &= (flags & CCWDEV_REPORT_ALL) == 0; 92 cdev->private->options.repall &= (flags & CCWDEV_REPORT_ALL) == 0;
91 cdev->private->options.pgroup &= (flags & CCWDEV_DO_PATHGROUP) == 0; 93 cdev->private->options.pgroup &= (flags & CCWDEV_DO_PATHGROUP) == 0;
92 cdev->private->options.force &= (flags & CCWDEV_ALLOW_FORCE) == 0; 94 cdev->private->options.force &= (flags & CCWDEV_ALLOW_FORCE) == 0;
95 cdev->private->options.mpath &= (flags & CCWDEV_DO_MULTIPATH) == 0;
93} 96}
94 97
95/** 98/**
99 * ccw_device_is_pathgroup - determine if paths to this device are grouped
100 * @cdev: ccw device
101 *
102 * Return non-zero if there is a path group, zero otherwise.
103 */
104int ccw_device_is_pathgroup(struct ccw_device *cdev)
105{
106 return cdev->private->flags.pgroup;
107}
108EXPORT_SYMBOL(ccw_device_is_pathgroup);
109
110/**
111 * ccw_device_is_multipath - determine if device is operating in multipath mode
112 * @cdev: ccw device
113 *
114 * Return non-zero if device is operating in multipath mode, zero otherwise.
115 */
116int ccw_device_is_multipath(struct ccw_device *cdev)
117{
118 return cdev->private->flags.mpath;
119}
120EXPORT_SYMBOL(ccw_device_is_multipath);
121
122/**
96 * ccw_device_clear() - terminate I/O request processing 123 * ccw_device_clear() - terminate I/O request processing
97 * @cdev: target ccw device 124 * @cdev: target ccw device
98 * @intparm: interruption parameter; value is only used if no I/O is 125 * @intparm: interruption parameter; value is only used if no I/O is
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);
diff --git a/drivers/s390/cio/io_sch.h b/drivers/s390/cio/io_sch.h
index 8942dc092d0a..b387c80d1888 100644
--- a/drivers/s390/cio/io_sch.h
+++ b/drivers/s390/cio/io_sch.h
@@ -156,9 +156,9 @@ struct ccw_device_private {
156 unsigned int repall:1; /* report every interrupt status */ 156 unsigned int repall:1; /* report every interrupt status */
157 unsigned int pgroup:1; /* do path grouping */ 157 unsigned int pgroup:1; /* do path grouping */
158 unsigned int force:1; /* allow forced online */ 158 unsigned int force:1; /* allow forced online */
159 unsigned int mpath:1; /* do multipathing */
159 } __attribute__ ((packed)) options; 160 } __attribute__ ((packed)) options;
160 struct { 161 struct {
161 unsigned int pgid_single:1; /* use single path for Set PGID */
162 unsigned int esid:1; /* Ext. SenseID supported by HW */ 162 unsigned int esid:1; /* Ext. SenseID supported by HW */
163 unsigned int dosense:1; /* delayed SENSE required */ 163 unsigned int dosense:1; /* delayed SENSE required */
164 unsigned int doverify:1; /* delayed path verification */ 164 unsigned int doverify:1; /* delayed path verification */
@@ -167,6 +167,8 @@ struct ccw_device_private {
167 unsigned int fake_irb:1; /* deliver faked irb */ 167 unsigned int fake_irb:1; /* deliver faked irb */
168 unsigned int resuming:1; /* recognition while resume */ 168 unsigned int resuming:1; /* recognition while resume */
169 unsigned int pgid_rdy:1; /* pgids are ready */ 169 unsigned int pgid_rdy:1; /* pgids are ready */
170 unsigned int pgroup:1; /* pathgroup is set up */
171 unsigned int mpath:1; /* multipathing is set up */
170 } __attribute__((packed)) flags; 172 } __attribute__((packed)) flags;
171 unsigned long intparm; /* user interruption parameter */ 173 unsigned long intparm; /* user interruption parameter */
172 struct qdio_irq *qdio_data; 174 struct qdio_irq *qdio_data;