aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/s390/block/dasd.c22
-rw-r--r--drivers/s390/block/dasd_eckd.c26
-rw-r--r--drivers/s390/block/dasd_int.h3
-rw-r--r--drivers/s390/block/dasd_ioctl.c33
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
2062static struct dasd_ccw_req * 2062static struct dasd_ccw_req *
2063dasd_eckd_build_format(struct dasd_device *base, 2063dasd_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
2320static int 2324static int
2321dasd_eckd_format_device(struct dasd_device *base, 2325dasd_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
2405sleep: 2410sleep:
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
203dasd_format(struct dasd_block *block, struct format_data_t *fdata) 203dasd_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/*