* 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>
/*
* 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
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;
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) {
}
/*
- * 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);
"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:
cqr->status = DASD_CQR_FAILED;
cqr->stopclk = get_clock();
} else {
- erp_fn = device->discipline->erp_action(cqr);
- erp_fn(cqr);
+ 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;
}
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);
/* termination successful */
cqr->status = DASD_CQR_QUEUED;
cqr->startclk = cqr->stopclk = 0;
+ cqr->starttime = 0;
}
return rc;
}
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
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);
* 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>
/* 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 */
* 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>
"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);
*
* gendisk related functions for the dasd driver.
*
- * $Revision: 1.42 $
+ * $Revision: 1.44 $
*/
#include <linux/config.h>
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)
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)
* 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
#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)
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 */
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 */
/*
* 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)
* 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;
}
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;
}
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))
*
* /proc interface for the dasd driver.
*
- * $Revision: 1.24 $
+ * $Revision: 1.26 $
*/
#include <linux/config.h>
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);