From: Martin Schwidefsky 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 to dasd__. This breaks too many user space packages. - Extend dasd naming scheme to four letters dasd-dasd. - 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..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000, 2001 * - * $Revision: 1.26 $ + * $Revision: 1.27 $ */ #include @@ -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..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001 * - * $Revision: 1.123 $ + * $Revision: 1.129 $ */ #include @@ -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..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 * - * $Revision: 1.49 $ + * $Revision: 1.50 $ */ #include @@ -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 @@ -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..: * (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 @@ -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); _