From: Martin Schwidefsky <schwidefsky@de.ibm.com>

DASD driver fixes:
 - Fix generic_set_online if diag discipline is not availab.e
 - Fix reserve on already reserved device.
 - Use default-erp for unit check without sence information.
 - Revert dasd naming scheme change from dasd<xyz> to dasd_<busid>_. This
   breaks too many user space packages.
 - Extend dasd naming scheme to four letters dasd<aaaa>-dasd<zzzz>.
 - Fix formatting of dasds.


---

 25-akpm/drivers/s390/block/dasd.c          |   43 +++++++++++++++++------------
 25-akpm/drivers/s390/block/dasd_3990_erp.c |   13 +++-----
 25-akpm/drivers/s390/block/dasd_eckd.c     |    5 ++-
 25-akpm/drivers/s390/block/dasd_genhd.c    |   27 ++++++++++++++++--
 25-akpm/drivers/s390/block/dasd_int.h      |    8 ++++-
 25-akpm/drivers/s390/block/dasd_ioctl.c    |   22 +++++++++++++-
 25-akpm/drivers/s390/block/dasd_proc.c     |   11 +++++--
 7 files changed, 94 insertions(+), 35 deletions(-)

diff -puN drivers/s390/block/dasd_3990_erp.c~s390-08-dasd-driver drivers/s390/block/dasd_3990_erp.c
--- 25/drivers/s390/block/dasd_3990_erp.c~s390-08-dasd-driver	Fri Feb 20 16:00:47 2004
+++ 25-akpm/drivers/s390/block/dasd_3990_erp.c	Fri Feb 20 16:00:47 2004
@@ -5,7 +5,7 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000, 2001
  *
- * $Revision: 1.26 $
+ * $Revision: 1.27 $
  */
 
 #include <linux/timer.h>
@@ -2129,13 +2129,10 @@ dasd_3990_erp_inspect_32(struct dasd_ccw
 		/* single program action codes (byte25 bit 0 == '0') */
 		switch (sense[25]) {
 
-		case 0x00:	/* success */
-			DEV_MESSAGE(KERN_DEBUG, device,
-				    "ERP called for successful request %p"
-				    " - NO ERP necessary", erp);
-
-			erp = dasd_3990_erp_cleanup(erp, DASD_CQR_DONE);
-
+		case 0x00:	/* success - use default ERP for retries */
+		        DEV_MESSAGE(KERN_DEBUG, device, "%s",
+				    "ERP called for successful request"
+				    " - just retry");
 			break;
 
 		case 0x01:	/* fatal error */
diff -puN drivers/s390/block/dasd.c~s390-08-dasd-driver drivers/s390/block/dasd.c
--- 25/drivers/s390/block/dasd.c~s390-08-dasd-driver	Fri Feb 20 16:00:47 2004
+++ 25-akpm/drivers/s390/block/dasd.c	Fri Feb 20 16:00:47 2004
@@ -7,7 +7,7 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001
  *
- * $Revision: 1.123 $
+ * $Revision: 1.129 $
  */
 
 #include <linux/config.h>
@@ -668,7 +668,7 @@ dasd_check_cqr(struct dasd_ccw_req *cqr)
 
 /*
  * Terminate the current i/o and set the request to failed.
- * ccw_device_halt/ccw_device_clear can fail if the i/o subsystem 
+ * ccw_device_clear can fail if the i/o subsystem
  * is in a bad mood.
  */
 int
@@ -684,10 +684,7 @@ dasd_term_IO(struct dasd_ccw_req * cqr)
 	retries = 0;
 	device = (struct dasd_device *) cqr->device;
 	while ((retries < 5) && (cqr->status == DASD_CQR_IN_IO)) {
-		if (retries < 2)
-			rc = ccw_device_halt(device->cdev, (long) cqr);
-		else
-			rc = ccw_device_clear(device->cdev, (long) cqr);
+		rc = ccw_device_clear(device->cdev, (long) cqr);
 		switch (rc) {
 		case 0:	/* termination successful */
 			cqr->status = DASD_CQR_FAILED;
@@ -736,6 +733,7 @@ dasd_start_IO(struct dasd_ccw_req * cqr)
 		return rc;
 	device = (struct dasd_device *) cqr->device;
 	cqr->startclk = get_clock();
+	cqr->starttime = jiffies;
 	rc = ccw_device_start(device->cdev, cqr->cpaddr, (long) cqr,
 			      cqr->lpm, 0);
 	switch (rc) {
@@ -788,14 +786,11 @@ dasd_timeout_device(unsigned long ptr)
 }
 
 /*
- * Setup timeout for a device.
+ * Setup timeout for a device in jiffies.
  */
 void
 dasd_set_timer(struct dasd_device *device, int expires)
 {
-	/* FIXME: timeouts are based on jiffies but the timeout
-	 * comparision in __dasd_check_expire is based on the
-	 * TOD clock. */
 	if (expires == 0) {
 		if (timer_pending(&device->timer))
 			del_timer(&device->timer);
@@ -1002,8 +997,7 @@ dasd_int_handler(struct ccw_device *cdev
 				"no memory for dstat...ignoring");
 #ifdef ERP_DEBUG
 		/* dump sense data */
-		if (device->discipline && device->discipline->dump_sense)
-			device->discipline->dump_sense(device, cqr);
+		dasd_log_sense(cqr, irb);
 #endif
 		switch (era) {
 		case dasd_era_fatal:
@@ -1078,9 +1072,12 @@ restart:
 			if (cqr->dstat->scsw.fctl & SCSW_FCTL_HALT_FUNC) {
 				cqr->status = DASD_CQR_FAILED;
 				cqr->stopclk = get_clock();
-			} else {
-				erp_fn = device->discipline->erp_action(cqr);
-				erp_fn(cqr);
+			} else {
+				if (cqr->dstat->esw.esw0.erw.cons) {
+					erp_fn = device->discipline->erp_action(cqr);
+					erp_fn(cqr);
+				} else
+					dasd_default_erp_action(cqr);
 			}
 			goto restart;
 		}
@@ -1196,7 +1193,7 @@ __dasd_check_expire(struct dasd_device *
 	cqr = list_entry(device->ccw_queue.next, struct dasd_ccw_req, list);
 	if (cqr->status == DASD_CQR_IN_IO && cqr->expires != 0) {
 		now = get_clock();
-		if (cqr->expires * (TOD_SEC / HZ) + cqr->startclk < now) {
+		if (time_after_eq(jiffies, cqr->expires + cqr->starttime)) {
 			if (device->discipline->term_IO(cqr) != 0)
 				/* Hmpf, try again in 1/100 sec */
 				dasd_set_timer(device, 1);
@@ -1476,6 +1473,7 @@ _dasd_term_running_cqr(struct dasd_devic
 		/* termination successful */
 		cqr->status = DASD_CQR_QUEUED;
 		cqr->startclk = cqr->stopclk = 0;
+		cqr->starttime = 0;
 	}
 	return rc;
 }
@@ -1782,9 +1780,19 @@ dasd_generic_set_online (struct ccw_devi
 	if (IS_ERR(device))
 		return PTR_ERR(device);
 
-	if (device->use_diag_flag)
+	if (device->use_diag_flag) {
+	  	if (!dasd_diag_discipline_pointer) {
+		        printk (KERN_WARNING
+				"dasd_generic couldn't online device %s "
+				"- discipline DIAG not available\n",
+				cdev->dev.bus_id);
+			dasd_delete_device(device);
+			return -ENODEV;
+		}
 		discipline = dasd_diag_discipline_pointer;
+	}
 	device->discipline = discipline;
+
 	rc = discipline->check_device(device);
 	if (rc) {
 		printk (KERN_WARNING
@@ -1980,6 +1988,7 @@ EXPORT_SYMBOL(dasd_term_IO);
 
 EXPORT_SYMBOL_GPL(dasd_generic_probe);
 EXPORT_SYMBOL_GPL(dasd_generic_remove);
+EXPORT_SYMBOL_GPL(dasd_generic_notify);
 EXPORT_SYMBOL_GPL(dasd_generic_set_online);
 EXPORT_SYMBOL_GPL(dasd_generic_set_offline);
 EXPORT_SYMBOL_GPL(dasd_generic_auto_online);
diff -puN drivers/s390/block/dasd_eckd.c~s390-08-dasd-driver drivers/s390/block/dasd_eckd.c
--- 25/drivers/s390/block/dasd_eckd.c~s390-08-dasd-driver	Fri Feb 20 16:00:47 2004
+++ 25-akpm/drivers/s390/block/dasd_eckd.c	Fri Feb 20 16:00:47 2004
@@ -7,7 +7,7 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
  *
- * $Revision: 1.49 $
+ * $Revision: 1.50 $
  */
 
 #include <linux/config.h>
@@ -1420,6 +1420,9 @@ dasd_eckd_dump_sense(struct dasd_device 
 				       "Exception class %x\n",
 				       irb->ecw[6] & 0x0f, irb->ecw[22] >> 4);
 		}
+	} else {
+	        len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+			       "SORRY - NO VALID SENSE AVAILABLE\n");
 	}
 
 	MESSAGE(KERN_ERR, "Sense data:\n%s", page);
diff -puN drivers/s390/block/dasd_genhd.c~s390-08-dasd-driver drivers/s390/block/dasd_genhd.c
--- 25/drivers/s390/block/dasd_genhd.c~s390-08-dasd-driver	Fri Feb 20 16:00:47 2004
+++ 25-akpm/drivers/s390/block/dasd_genhd.c	Fri Feb 20 16:00:47 2004
@@ -9,7 +9,7 @@
  *
  * gendisk related functions for the dasd driver.
  *
- * $Revision: 1.42 $
+ * $Revision: 1.44 $
  */
 
 #include <linux/config.h>
@@ -31,6 +31,7 @@ int
 dasd_gendisk_alloc(struct dasd_device *device)
 {
 	struct gendisk *gdp;
+	int len;
 
 	/* Make sure the minor for this device exists. */
 	if (device->devindex >= DASD_PER_MAJOR)
@@ -46,8 +47,28 @@ dasd_gendisk_alloc(struct dasd_device *d
 	gdp->fops = &dasd_device_operations;
 	gdp->driverfs_dev = &device->cdev->dev;
 
-	/* Set device name */
- 	sprintf(gdp->disk_name, "dasd_%s_", device->cdev->dev.bus_id);
+	/*
+	 * Set device name.
+	 *   dasda - dasdz : 26 devices
+	 *   dasdaa - dasdzz : 676 devices, added up = 702
+	 *   dasdaaa - dasdzzz : 17576 devices, added up = 18278
+	 *   dasdaaaa - dasdzzzz : 456976 devices, added up = 475252
+	 */
+	len = sprintf(gdp->disk_name, "dasd");
+	if (device->devindex > 25) {
+	        if (device->devindex > 701) {
+		        if (device->devindex > 18277)
+			        len += sprintf(gdp->disk_name + len, "%c",
+					       'a'+(((device->devindex-18278)
+						     /17576)%26));
+			len += sprintf(gdp->disk_name + len, "%c",
+				       'a'+(((device->devindex-702)/676)%26));
+		}
+		len += sprintf(gdp->disk_name + len, "%c",
+			       'a'+(((device->devindex-26)/26)%26));
+	}
+	len += sprintf(gdp->disk_name + len, "%c", 'a'+(device->devindex%26));
+
  	sprintf(gdp->devfs_name, "dasd/%s", device->cdev->dev.bus_id);
 
 	if (device->ro_flag)
diff -puN drivers/s390/block/dasd_int.h~s390-08-dasd-driver drivers/s390/block/dasd_int.h
--- 25/drivers/s390/block/dasd_int.h~s390-08-dasd-driver	Fri Feb 20 16:00:47 2004
+++ 25-akpm/drivers/s390/block/dasd_int.h	Fri Feb 20 16:00:47 2004
@@ -6,7 +6,7 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
  *
- * $Revision: 1.52 $
+ * $Revision: 1.54 $
  */
 
 #ifndef DASD_INT_H
@@ -14,6 +14,10 @@
 
 #ifdef __KERNEL__
 
+/* erp debugging in dasd.c and dasd_3990_erp.c */
+#define ERP_DEBUG
+
+
 /* we keep old device allocation scheme; IOW, minors are still in 0..255 */
 #define DASD_PER_MAJOR (1U << (MINORBITS - DASD_PARTN_BITS))
 #define DASD_PARTN_MASK ((1 << DASD_PARTN_BITS) - 1)
@@ -157,6 +161,7 @@ struct dasd_ccw_req {
 	short retries;			/* A retry counter */
 
 	/* ... and how */
+	unsigned long starttime;	/* jiffies time of request start */
 	int expires;			/* expiration period in jiffies */
 	char lpm;               	/* logical path mask */
 	void *data;			/* pointer to data area */
@@ -166,6 +171,7 @@ struct dasd_ccw_req {
 	struct dasd_ccw_req *refers;	/* ERP-chain queueing. */
 	void *function; 		/* originating ERP action */
 
+	/* these are for statistics only */
 	unsigned long long buildclk;	/* TOD-clock of request generation */
 	unsigned long long startclk;	/* TOD-clock of request start */
 	unsigned long long stopclk;	/* TOD-clock of request interrupt */
diff -puN drivers/s390/block/dasd_ioctl.c~s390-08-dasd-driver drivers/s390/block/dasd_ioctl.c
--- 25/drivers/s390/block/dasd_ioctl.c~s390-08-dasd-driver	Fri Feb 20 16:00:47 2004
+++ 25-akpm/drivers/s390/block/dasd_ioctl.c	Fri Feb 20 16:00:47 2004
@@ -147,6 +147,7 @@ dasd_ioctl_enable(struct block_device *b
 
 /*
  * Disable device.
+ * Used by dasdfmt. Disable I/O operations but allow ioctls.
  */
 static int
 dasd_ioctl_disable(struct block_device *bdev, int no, long args)
@@ -167,6 +168,13 @@ dasd_ioctl_disable(struct block_device *
 	 * device is DASD_STATE_BASIC that allows to do basic i/o.
 	 */
 	dasd_set_target_state(device, DASD_STATE_BASIC);
+	/*
+	 * Set i_size to zero, since read, write, etc. check against this
+	 * value.
+	 */
+	down(&bdev->bd_sem);
+	i_size_write(bdev->bd_inode, 0);
+	up(&bdev->bd_sem);
 	return 0;
 }
 
@@ -237,9 +245,9 @@ dasd_format(struct dasd_device * device,
 	if (device->discipline->format_device == NULL)
 		return -EPERM;
 
-	if (atomic_read(&device->open_count) > 1) {
+	if (device->state != DASD_STATE_BASIC) {
 		DEV_MESSAGE(KERN_WARNING, device, "%s",
-			    "dasd_format: device is open! ");
+			    "dasd_format: device is not disabled! ");
 		return -EBUSY;
 	}
 
@@ -248,6 +256,16 @@ dasd_format(struct dasd_device * device,
 		      fdata->start_unit,
 		      fdata->stop_unit, fdata->blksize, fdata->intensity);
 
+	/* Since dasdfmt keeps the device open after it was disabled,
+	 * there still exists an inode for this device. We must update i_blkbits,
+	 * otherwise we might get errors when enabling the device later.
+	 */
+	if (fdata->start_unit == 0) {
+		struct block_device *bdev = bdget_disk(device->gdp, 0);
+		bdev->bd_inode->i_blkbits = blksize_bits(fdata->blksize);
+		bdput(bdev);
+	}
+
 	while (fdata->start_unit <= fdata->stop_unit) {
 		cqr = device->discipline->format_device(device, fdata);
 		if (IS_ERR(cqr))
diff -puN drivers/s390/block/dasd_proc.c~s390-08-dasd-driver drivers/s390/block/dasd_proc.c
--- 25/drivers/s390/block/dasd_proc.c~s390-08-dasd-driver	Fri Feb 20 16:00:47 2004
+++ 25-akpm/drivers/s390/block/dasd_proc.c	Fri Feb 20 16:00:47 2004
@@ -9,7 +9,7 @@
  *
  * /proc interface for the dasd driver.
  *
- * $Revision: 1.24 $
+ * $Revision: 1.26 $
  */
 
 #include <linux/config.h>
@@ -67,10 +67,15 @@ dasd_devices_show(struct seq_file *m, vo
 		seq_printf(m, "(none)");
 	/* Print kdev. */
 	if (device->gdp)
-		seq_printf(m, " at (%3d:%7d)",
+		seq_printf(m, " at (%3d:%6d)",
 			   device->gdp->major, device->gdp->first_minor);
 	else
-		seq_printf(m, "  at (???:???????)");
+		seq_printf(m, "  at (???:??????)");
+	/* Print device name. */
+	if (device->gdp)
+		seq_printf(m, " is %-8s", device->gdp->disk_name);
+	else
+		seq_printf(m, " is ????????");
 	/* Print devices features. */
 	substr = device->ro_flag ? "(ro)" : " ";
 	seq_printf(m, "%4s: ", substr);

_