diff options
| -rw-r--r-- | drivers/s390/block/dasd.c | 22 | ||||
| -rw-r--r-- | drivers/s390/block/dasd_eckd.c | 26 | ||||
| -rw-r--r-- | drivers/s390/block/dasd_int.h | 3 | ||||
| -rw-r--r-- | drivers/s390/block/dasd_ioctl.c | 33 |
4 files changed, 62 insertions, 22 deletions
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 925b056dc2b3..5df05f26b7d9 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c | |||
| @@ -2307,17 +2307,27 @@ retry: | |||
| 2307 | 2307 | ||
| 2308 | rc = 0; | 2308 | rc = 0; |
| 2309 | list_for_each_entry_safe(cqr, n, ccw_queue, blocklist) { | 2309 | list_for_each_entry_safe(cqr, n, ccw_queue, blocklist) { |
| 2310 | if (__dasd_sleep_on_erp(cqr)) { | 2310 | /* |
| 2311 | if (!cqr->status == DASD_CQR_TERMINATED && | 2311 | * for alias devices simplify error recovery and |
| 2312 | !cqr->status == DASD_CQR_NEED_ERP) | 2312 | * return to upper layer |
| 2313 | break; | 2313 | */ |
| 2314 | rc = 1; | 2314 | if (cqr->startdev != cqr->basedev && |
| 2315 | (cqr->status == DASD_CQR_TERMINATED || | ||
| 2316 | cqr->status == DASD_CQR_NEED_ERP)) | ||
| 2317 | return -EAGAIN; | ||
| 2318 | else { | ||
| 2319 | /* normal recovery for basedev IO */ | ||
| 2320 | if (__dasd_sleep_on_erp(cqr)) { | ||
| 2321 | if (!cqr->status == DASD_CQR_TERMINATED && | ||
| 2322 | !cqr->status == DASD_CQR_NEED_ERP) | ||
| 2323 | break; | ||
| 2324 | rc = 1; | ||
| 2325 | } | ||
| 2315 | } | 2326 | } |
| 2316 | } | 2327 | } |
| 2317 | if (rc) | 2328 | if (rc) |
| 2318 | goto retry; | 2329 | goto retry; |
| 2319 | 2330 | ||
| 2320 | |||
| 2321 | return 0; | 2331 | return 0; |
| 2322 | } | 2332 | } |
| 2323 | 2333 | ||
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 39748fda6e1f..e74e5f7b431d 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c | |||
| @@ -2061,11 +2061,12 @@ dasd_eckd_fill_geometry(struct dasd_block *block, struct hd_geometry *geo) | |||
| 2061 | 2061 | ||
| 2062 | static struct dasd_ccw_req * | 2062 | static struct dasd_ccw_req * |
| 2063 | dasd_eckd_build_format(struct dasd_device *base, | 2063 | dasd_eckd_build_format(struct dasd_device *base, |
| 2064 | struct format_data_t *fdata) | 2064 | struct format_data_t *fdata, |
| 2065 | int enable_PAV) | ||
| 2065 | { | 2066 | { |
| 2066 | struct dasd_eckd_private *base_priv; | 2067 | struct dasd_eckd_private *base_priv; |
| 2067 | struct dasd_eckd_private *start_priv; | 2068 | struct dasd_eckd_private *start_priv; |
| 2068 | struct dasd_device *startdev; | 2069 | struct dasd_device *startdev = NULL; |
| 2069 | struct dasd_ccw_req *fcp; | 2070 | struct dasd_ccw_req *fcp; |
| 2070 | struct eckd_count *ect; | 2071 | struct eckd_count *ect; |
| 2071 | struct ch_t address; | 2072 | struct ch_t address; |
| @@ -2079,7 +2080,9 @@ dasd_eckd_build_format(struct dasd_device *base, | |||
| 2079 | int nr_tracks; | 2080 | int nr_tracks; |
| 2080 | int use_prefix; | 2081 | int use_prefix; |
| 2081 | 2082 | ||
| 2082 | startdev = dasd_alias_get_start_dev(base); | 2083 | if (enable_PAV) |
| 2084 | startdev = dasd_alias_get_start_dev(base); | ||
| 2085 | |||
| 2083 | if (!startdev) | 2086 | if (!startdev) |
| 2084 | startdev = base; | 2087 | startdev = base; |
| 2085 | 2088 | ||
| @@ -2309,6 +2312,7 @@ dasd_eckd_build_format(struct dasd_device *base, | |||
| 2309 | 2312 | ||
| 2310 | fcp->startdev = startdev; | 2313 | fcp->startdev = startdev; |
| 2311 | fcp->memdev = startdev; | 2314 | fcp->memdev = startdev; |
| 2315 | fcp->basedev = base; | ||
| 2312 | fcp->retries = 256; | 2316 | fcp->retries = 256; |
| 2313 | fcp->expires = startdev->default_expires * HZ; | 2317 | fcp->expires = startdev->default_expires * HZ; |
| 2314 | fcp->buildclk = get_tod_clock(); | 2318 | fcp->buildclk = get_tod_clock(); |
| @@ -2319,7 +2323,8 @@ dasd_eckd_build_format(struct dasd_device *base, | |||
| 2319 | 2323 | ||
| 2320 | static int | 2324 | static int |
| 2321 | dasd_eckd_format_device(struct dasd_device *base, | 2325 | dasd_eckd_format_device(struct dasd_device *base, |
| 2322 | struct format_data_t *fdata) | 2326 | struct format_data_t *fdata, |
| 2327 | int enable_PAV) | ||
| 2323 | { | 2328 | { |
| 2324 | struct dasd_ccw_req *cqr, *n; | 2329 | struct dasd_ccw_req *cqr, *n; |
| 2325 | struct dasd_block *block; | 2330 | struct dasd_block *block; |
| @@ -2327,7 +2332,7 @@ dasd_eckd_format_device(struct dasd_device *base, | |||
| 2327 | struct list_head format_queue; | 2332 | struct list_head format_queue; |
| 2328 | struct dasd_device *device; | 2333 | struct dasd_device *device; |
| 2329 | int old_stop, format_step; | 2334 | int old_stop, format_step; |
| 2330 | int step, rc = 0; | 2335 | int step, rc = 0, sleep_rc; |
| 2331 | 2336 | ||
| 2332 | block = base->block; | 2337 | block = base->block; |
| 2333 | private = (struct dasd_eckd_private *) base->private; | 2338 | private = (struct dasd_eckd_private *) base->private; |
| @@ -2361,11 +2366,11 @@ dasd_eckd_format_device(struct dasd_device *base, | |||
| 2361 | } | 2366 | } |
| 2362 | 2367 | ||
| 2363 | INIT_LIST_HEAD(&format_queue); | 2368 | INIT_LIST_HEAD(&format_queue); |
| 2364 | old_stop = fdata->stop_unit; | ||
| 2365 | 2369 | ||
| 2370 | old_stop = fdata->stop_unit; | ||
| 2366 | while (fdata->start_unit <= 1) { | 2371 | while (fdata->start_unit <= 1) { |
| 2367 | fdata->stop_unit = fdata->start_unit; | 2372 | fdata->stop_unit = fdata->start_unit; |
| 2368 | cqr = dasd_eckd_build_format(base, fdata); | 2373 | cqr = dasd_eckd_build_format(base, fdata, enable_PAV); |
| 2369 | list_add(&cqr->blocklist, &format_queue); | 2374 | list_add(&cqr->blocklist, &format_queue); |
| 2370 | 2375 | ||
| 2371 | fdata->stop_unit = old_stop; | 2376 | fdata->stop_unit = old_stop; |
| @@ -2383,7 +2388,7 @@ retry: | |||
| 2383 | if (step > format_step) | 2388 | if (step > format_step) |
| 2384 | fdata->stop_unit = fdata->start_unit + format_step - 1; | 2389 | fdata->stop_unit = fdata->start_unit + format_step - 1; |
| 2385 | 2390 | ||
| 2386 | cqr = dasd_eckd_build_format(base, fdata); | 2391 | cqr = dasd_eckd_build_format(base, fdata, enable_PAV); |
| 2387 | if (IS_ERR(cqr)) { | 2392 | if (IS_ERR(cqr)) { |
| 2388 | if (PTR_ERR(cqr) == -ENOMEM) { | 2393 | if (PTR_ERR(cqr) == -ENOMEM) { |
| 2389 | /* | 2394 | /* |
| @@ -2403,7 +2408,7 @@ retry: | |||
| 2403 | } | 2408 | } |
| 2404 | 2409 | ||
| 2405 | sleep: | 2410 | sleep: |
| 2406 | dasd_sleep_on_queue(&format_queue); | 2411 | sleep_rc = dasd_sleep_on_queue(&format_queue); |
| 2407 | 2412 | ||
| 2408 | list_for_each_entry_safe(cqr, n, &format_queue, blocklist) { | 2413 | list_for_each_entry_safe(cqr, n, &format_queue, blocklist) { |
| 2409 | device = cqr->startdev; | 2414 | device = cqr->startdev; |
| @@ -2415,6 +2420,9 @@ sleep: | |||
| 2415 | private->count--; | 2420 | private->count--; |
| 2416 | } | 2421 | } |
| 2417 | 2422 | ||
| 2423 | if (sleep_rc) | ||
| 2424 | return sleep_rc; | ||
| 2425 | |||
| 2418 | /* | 2426 | /* |
| 2419 | * in case of ENOMEM we need to retry after | 2427 | * in case of ENOMEM we need to retry after |
| 2420 | * first requests are finished | 2428 | * first requests are finished |
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index 7a14582dc8a4..2cc188c8203f 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h | |||
| @@ -175,6 +175,7 @@ struct dasd_ccw_req { | |||
| 175 | struct dasd_block *block; /* the originating block device */ | 175 | struct dasd_block *block; /* the originating block device */ |
| 176 | struct dasd_device *memdev; /* the device used to allocate this */ | 176 | struct dasd_device *memdev; /* the device used to allocate this */ |
| 177 | struct dasd_device *startdev; /* device the request is started on */ | 177 | struct dasd_device *startdev; /* device the request is started on */ |
| 178 | struct dasd_device *basedev; /* base device if no block->base */ | ||
| 178 | void *cpaddr; /* address of ccw or tcw */ | 179 | void *cpaddr; /* address of ccw or tcw */ |
| 179 | unsigned char cpmode; /* 0 = cmd mode, 1 = itcw */ | 180 | unsigned char cpmode; /* 0 = cmd mode, 1 = itcw */ |
| 180 | char status; /* status of this request */ | 181 | char status; /* status of this request */ |
| @@ -321,7 +322,7 @@ struct dasd_discipline { | |||
| 321 | int (*term_IO) (struct dasd_ccw_req *); | 322 | int (*term_IO) (struct dasd_ccw_req *); |
| 322 | void (*handle_terminated_request) (struct dasd_ccw_req *); | 323 | void (*handle_terminated_request) (struct dasd_ccw_req *); |
| 323 | int (*format_device) (struct dasd_device *, | 324 | int (*format_device) (struct dasd_device *, |
| 324 | struct format_data_t *); | 325 | struct format_data_t *, int enable_PAV); |
| 325 | int (*free_cp) (struct dasd_ccw_req *, struct request *); | 326 | int (*free_cp) (struct dasd_ccw_req *, struct request *); |
| 326 | 327 | ||
| 327 | /* | 328 | /* |
diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c index 25a0f2f8b0b9..ad62608e4175 100644 --- a/drivers/s390/block/dasd_ioctl.c +++ b/drivers/s390/block/dasd_ioctl.c | |||
| @@ -203,7 +203,9 @@ static int | |||
| 203 | dasd_format(struct dasd_block *block, struct format_data_t *fdata) | 203 | dasd_format(struct dasd_block *block, struct format_data_t *fdata) |
| 204 | { | 204 | { |
| 205 | struct dasd_device *base; | 205 | struct dasd_device *base; |
| 206 | int rc; | 206 | int enable_PAV = 1; |
| 207 | int rc, retries; | ||
| 208 | int start, stop; | ||
| 207 | 209 | ||
| 208 | base = block->base; | 210 | base = block->base; |
| 209 | if (base->discipline->format_device == NULL) | 211 | if (base->discipline->format_device == NULL) |
| @@ -231,11 +233,30 @@ dasd_format(struct dasd_block *block, struct format_data_t *fdata) | |||
| 231 | bdput(bdev); | 233 | bdput(bdev); |
| 232 | } | 234 | } |
| 233 | 235 | ||
| 234 | rc = base->discipline->format_device(base, fdata); | 236 | retries = 255; |
| 235 | if (rc) | 237 | /* backup start- and endtrack for retries */ |
| 236 | return rc; | 238 | start = fdata->start_unit; |
| 237 | 239 | stop = fdata->stop_unit; | |
| 238 | return 0; | 240 | do { |
| 241 | rc = base->discipline->format_device(base, fdata, enable_PAV); | ||
| 242 | if (rc) { | ||
| 243 | if (rc == -EAGAIN) { | ||
| 244 | retries--; | ||
| 245 | /* disable PAV in case of errors */ | ||
| 246 | enable_PAV = 0; | ||
| 247 | fdata->start_unit = start; | ||
| 248 | fdata->stop_unit = stop; | ||
| 249 | } else | ||
| 250 | return rc; | ||
| 251 | } else | ||
| 252 | /* success */ | ||
| 253 | break; | ||
| 254 | } while (retries); | ||
| 255 | |||
| 256 | if (!retries) | ||
| 257 | return -EIO; | ||
| 258 | else | ||
| 259 | return 0; | ||
| 239 | } | 260 | } |
| 240 | 261 | ||
| 241 | /* | 262 | /* |
