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; |
