dasd: fix error recovery for alias devices during format

Kernel panic or a hanging device during format if an alias device is
set offline or I/O errors occur.

Omit the error recovery procedure for alias devices and do retries on
the base device with full erp.

Signed-off-by: Stefan Haberland <stefan.haberland@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index 39748fd..e74e5f7 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -2061,11 +2061,12 @@
 
 static struct dasd_ccw_req *
 dasd_eckd_build_format(struct dasd_device *base,
-		       struct format_data_t *fdata)
+		       struct format_data_t *fdata,
+		       int enable_PAV)
 {
 	struct dasd_eckd_private *base_priv;
 	struct dasd_eckd_private *start_priv;
-	struct dasd_device *startdev;
+	struct dasd_device *startdev = NULL;
 	struct dasd_ccw_req *fcp;
 	struct eckd_count *ect;
 	struct ch_t address;
@@ -2079,7 +2080,9 @@
 	int nr_tracks;
 	int use_prefix;
 
-	startdev = dasd_alias_get_start_dev(base);
+	if (enable_PAV)
+		startdev = dasd_alias_get_start_dev(base);
+
 	if (!startdev)
 		startdev = base;
 
@@ -2309,6 +2312,7 @@
 
 	fcp->startdev = startdev;
 	fcp->memdev = startdev;
+	fcp->basedev = base;
 	fcp->retries = 256;
 	fcp->expires = startdev->default_expires * HZ;
 	fcp->buildclk = get_tod_clock();
@@ -2319,7 +2323,8 @@
 
 static int
 dasd_eckd_format_device(struct dasd_device *base,
-			struct format_data_t *fdata)
+			struct format_data_t *fdata,
+			int enable_PAV)
 {
 	struct dasd_ccw_req *cqr, *n;
 	struct dasd_block *block;
@@ -2327,7 +2332,7 @@
 	struct list_head format_queue;
 	struct dasd_device *device;
 	int old_stop, format_step;
-	int step, rc = 0;
+	int step, rc = 0, sleep_rc;
 
 	block = base->block;
 	private = (struct dasd_eckd_private *) base->private;
@@ -2361,11 +2366,11 @@
 	}
 
 	INIT_LIST_HEAD(&format_queue);
-	old_stop = fdata->stop_unit;
 
+	old_stop = fdata->stop_unit;
 	while (fdata->start_unit <= 1) {
 		fdata->stop_unit = fdata->start_unit;
-		cqr = dasd_eckd_build_format(base, fdata);
+		cqr = dasd_eckd_build_format(base, fdata, enable_PAV);
 		list_add(&cqr->blocklist, &format_queue);
 
 		fdata->stop_unit = old_stop;
@@ -2383,7 +2388,7 @@
 		if (step > format_step)
 			fdata->stop_unit = fdata->start_unit + format_step - 1;
 
-		cqr = dasd_eckd_build_format(base, fdata);
+		cqr = dasd_eckd_build_format(base, fdata, enable_PAV);
 		if (IS_ERR(cqr)) {
 			if (PTR_ERR(cqr) == -ENOMEM) {
 				/*
@@ -2403,7 +2408,7 @@
 	}
 
 sleep:
-	dasd_sleep_on_queue(&format_queue);
+	sleep_rc = dasd_sleep_on_queue(&format_queue);
 
 	list_for_each_entry_safe(cqr, n, &format_queue, blocklist) {
 		device = cqr->startdev;
@@ -2415,6 +2420,9 @@
 		private->count--;
 	}
 
+	if (sleep_rc)
+		return sleep_rc;
+
 	/*
 	 * in case of ENOMEM we need to retry after
 	 * first requests are finished