diff options
-rw-r--r-- | arch/s390/include/asm/ccwdev.h | 4 | ||||
-rw-r--r-- | drivers/s390/block/dasd.c | 7 | ||||
-rw-r--r-- | drivers/s390/block/dasd_eckd.c | 12 | ||||
-rw-r--r-- | drivers/s390/char/tape_core.c | 3 | ||||
-rw-r--r-- | drivers/s390/cio/device_fsm.c | 2 | ||||
-rw-r--r-- | drivers/s390/cio/device_ops.c | 27 | ||||
-rw-r--r-- | drivers/s390/cio/device_pgid.c | 33 | ||||
-rw-r--r-- | drivers/s390/cio/io_sch.h | 4 |
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; | |||
142 | extern int ccw_device_set_options_mask(struct ccw_device *, unsigned long); | 142 | extern int ccw_device_set_options_mask(struct ccw_device *, unsigned long); |
143 | extern int ccw_device_set_options(struct ccw_device *, unsigned long); | 143 | extern int ccw_device_set_options(struct ccw_device *, unsigned long); |
144 | extern void ccw_device_clear_options(struct ccw_device *, unsigned long); | 144 | extern void ccw_device_clear_options(struct ccw_device *, unsigned long); |
145 | int ccw_device_is_pathgroup(struct ccw_device *cdev); | ||
146 | int 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 | ||
155 | extern int ccw_device_start(struct ccw_device *, struct ccw1 *, | 159 | extern 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 | */ | ||
104 | int ccw_device_is_pathgroup(struct ccw_device *cdev) | ||
105 | { | ||
106 | return cdev->private->flags.pgroup; | ||
107 | } | ||
108 | EXPORT_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 | */ | ||
116 | int ccw_device_is_multipath(struct ccw_device *cdev) | ||
117 | { | ||
118 | return cdev->private->flags.mpath; | ||
119 | } | ||
120 | EXPORT_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; |