Commit 0098b69e authored by Linus Torvalds's avatar Linus Torvalds

Merge http://linux-scsi.bkbits.net/scsi-for-linus-2.5

into home.transmeta.com:/home/torvalds/v2.5/linux
parents 43d332b0 e5064e24
......@@ -485,13 +485,6 @@ int scsi_register_host(Scsi_Host_Template *shost_tp)
BUG_ON(!shost_tp->detect);
if (!shost_tp->max_sectors) {
printk(KERN_WARNING
"scsi HBA driver %s didn't set max_sectors, "
"please fix the template\n", shost_tp->name);
shost_tp->max_sectors = 1024;
}
if (!shost_tp->release) {
printk(KERN_WARNING
"scsi HBA driver %s didn't set a release method, "
......
......@@ -24,7 +24,7 @@
*/
static const char * cvsid = "$Id: osst.c,v 1.65 2001/11/11 20:38:56 riede Exp $";
const char * osst_version = "0.99.0p3";
const char * osst_version = "0.99.0p5";
/* The "failure to reconnect" firmware bug */
#define OSST_FW_NEED_POLL_MIN 10601 /*(107A)*/
......@@ -60,7 +60,6 @@ const char * osst_version = "0.99.0p3";
in the drivers are more widely classified, this may be changed to KERN_DEBUG. */
#define OSST_DEB_MSG KERN_NOTICE
#include "scsi.h"
#include "hosts.h"
#include <scsi/scsi_ioctl.h>
......@@ -85,7 +84,7 @@ MODULE_PARM(max_dev, "i");
MODULE_PARM_DESC(max_dev, "Maximum number of OnStream Tape Drives to attach (4)");
MODULE_PARM(write_threshold_kbs, "i");
MODULE_PARM_DESC(write_threshold_kbs, "Asynchronous write threshold (KB; 30)");
MODULE_PARM_DESC(write_threshold_kbs, "Asynchronous write threshold (KB; 32)");
MODULE_PARM(max_sg_segs, "i");
MODULE_PARM_DESC(max_sg_segs, "Maximum number of scatter/gather segments to use (9)");
......@@ -171,7 +170,7 @@ struct Scsi_Device_Template osst_template =
.detach = osst_detach,
.scsi_driverfs_driver = {
.name = "osst",
},
}
};
static int osst_int_ioctl(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt, unsigned int cmd_in,unsigned long arg);
......@@ -221,7 +220,7 @@ static int osst_chk_result(OS_Scsi_Tape * STp, Scsi_Request * SRpnt)
if (scode) printk(OSST_DEB_MSG "%s:D: Sense: %02x, ASC: %02x, ASCQ: %02x\n",
name, scode, sense[12], sense[13]);
if (driver_byte(result) & DRIVER_SENSE)
print_req_sense("osst", SRpnt);
print_req_sense("osst ", SRpnt);
}
// else
#endif
......@@ -543,8 +542,6 @@ static int osst_verify_frame(OS_Scsi_Tape * STp, int frame_seq_number, int quiet
STp->first_frame_position);
goto err_out;
}
// STp->frame_in_buffer = 1;
if (frame_seq_number != -1 && ntohl(aux->frame_seq_num) != frame_seq_number) {
if (!quiet)
#if DEBUG
......@@ -749,7 +746,7 @@ static int osst_flush_drive_buffer(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
Scsi_Request * SRpnt;
int result = 0;
int delay = OSST_WAIT_LONG_WRITE_COMPLETE;
int delay = OSST_WAIT_WRITE_COMPLETE;
#if DEBUG
char *name = tape_name(STp);
......@@ -763,17 +760,14 @@ static int osst_flush_drive_buffer(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_WRITE_RETRIES, TRUE);
*aSRpnt = SRpnt;
if (!SRpnt) return (-EBUSY);
//printk(OSST_DEB_MSG "%s:X: Write filemark returned %x:%02x:%02x:%02x\n",dev,STp->buffer->syscall_result,SRpnt->sr_sense_buffer[2] & 0x0f,SRpnt->sr_sense_buffer[12],SRpnt->sr_sense_buffer[13]);
if (STp->buffer->syscall_result) {
if ((SRpnt->sr_sense_buffer[2] & 0x0f) == 2 && SRpnt->sr_sense_buffer[12] == 4) {
if (SRpnt->sr_sense_buffer[13] == 8) {
//printk(OSST_DEB_MSG "%s:X: Long initial delay\n", dev);
delay = OSST_WAIT_LONG_WRITE_COMPLETE;
}
} else
result = osst_write_error_recovery(STp, aSRpnt, 0);
}
//printk(OSST_DEB_MSG "%s:X: Entering wait ready (%d)\n",dev,delay);
result |= osst_wait_ready(STp, aSRpnt, 5 * 60, delay);
STp->ps[STp->partition].rw = OS_WRITING_COMPLETE;
......@@ -1708,12 +1702,7 @@ static int osst_space_over_filemarks_backward(OS_Scsi_Tape * STp, Scsi_Request *
name, last_mark_ppos);
return (-EIO);
}
if (mt_op == MTBSFM) {
STp->frame_seq_number++;
STp->frame_in_buffer = 0;
STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
}
return 0;
goto found;
}
#if DEBUG
printk(OSST_DEB_MSG "%s:D: Reverting to scan filemark backwards\n", name);
......@@ -1741,9 +1730,12 @@ static int osst_space_over_filemarks_backward(OS_Scsi_Tape * STp, Scsi_Request *
return (-EIO);
}
}
found:
if (mt_op == MTBSFM) {
STp->frame_seq_number++;
STp->frame_in_buffer = 0;
STp->buffer->buffer_bytes = 0;
STp->buffer->read_pointer = 0;
STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
}
return 0;
......@@ -1798,6 +1790,8 @@ static int osst_space_over_filemarks_forward_slow(OS_Scsi_Tape * STp, Scsi_Reque
if (mt_op == MTFSF) {
STp->frame_seq_number++;
STp->frame_in_buffer = 0;
STp->buffer->buffer_bytes = 0;
STp->buffer->read_pointer = 0;
STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
}
return 0;
......@@ -1945,6 +1939,7 @@ static int osst_space_over_filemarks_forward_fast(OS_Scsi_Tape * STp, Scsi_Reque
if (mt_op == MTFSF) {
STp->frame_seq_number++;
STp->frame_in_buffer = 0;
STp->buffer->buffer_bytes = 0;
STp->buffer->read_pointer = 0;
STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
}
......@@ -3215,8 +3210,8 @@ static ssize_t osst_write(struct file * filp, const char * buf, size_t count, lo
/* Write must be integral number of blocks */
if (STp->block_size != 0 && (count % STp->block_size) != 0) {
printk(KERN_ERR "%s:E: Write (%ld bytes) not multiple of tape block size (%d%c).\n",
name, (unsigned long)count, STp->block_size<1024?
printk(KERN_ERR "%s:E: Write (%Zd bytes) not multiple of tape block size (%d%c).\n",
name, count, STp->block_size<1024?
STp->block_size:STp->block_size/1024, STp->block_size<1024?'b':'k');
retval = (-EINVAL);
goto out;
......@@ -4140,8 +4135,14 @@ static int osst_int_ioctl(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsigned i
if (cmd_in == MTEOM)
STps->eof = ST_EOD;
else if ((cmd_in == MTFSFM || cmd_in == MTBSF) && STps->eof == ST_FM_HIT)
ioctl_result = osst_seek_logical_blk(STp, &SRpnt, STp->logical_blk_num - 1);
else if ((cmd_in == MTFSFM || cmd_in == MTBSF) && STps->eof == ST_FM_HIT) {
ioctl_result = osst_seek_logical_blk(STp, &SRpnt, STp->logical_blk_num-1);
STps->drv_block++;
STp->logical_blk_num++;
STp->frame_seq_number++;
STp->frame_in_buffer = 0;
STp->buffer->read_pointer = 0;
}
else if (cmd_in == MTFSF)
STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_FM;
else if (chg_eof)
......@@ -4233,8 +4234,7 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp)
#endif
return (-EBUSY);
}
if (!scsi_device_get(STp->device)) {
if (scsi_device_get(STp->device)) {
write_unlock(&os_scsi_tapes_lock);
#if DEBUG
printk(OSST_DEB_MSG "%s:D: Failed scsi_device_get.\n", name);
......@@ -4856,12 +4856,6 @@ static int osst_ioctl(struct inode * inode,struct file * file,
}
if (mtc.mt_op == MTSETPART) {
/* if (!STp->can_partitions ||
mtc.mt_count < 0 || mtc.mt_count >= ST_NBR_PARTITIONS)
return (-EINVAL);
if (mtc.mt_count >= STp->nbr_partitions &&
(STp->nbr_partitions = nbr_partitions(inode)) < 0)
return (-EIO);*/
if (mtc.mt_count >= STp->nbr_partitions)
retval = -EINVAL;
else {
......@@ -4909,10 +4903,6 @@ static int osst_ioctl(struct inode * inode,struct file * file,
goto out;
}
/* if (STp->can_partitions && STp->ready == ST_READY &&
(i = update_partition(inode)) < 0)
{retval=i;goto out;}*/
if (mtc.mt_op == MTCOMPRESSION)
retval = -EINVAL /*osst_compression(STp, (mtc.mt_count & 1))*/;
else
......@@ -4931,10 +4921,6 @@ static int osst_ioctl(struct inode * inode,struct file * file,
goto out;
}
/* if (STp->can_partitions &&
(i = update_partition(inode)) < 0)
{retval=i;goto out;}*/
if (cmd_type == _IOC_TYPE(MTIOCGET) && cmd_nr == _IOC_NR(MTIOCGET)) {
struct mtget mt_status;
......@@ -5110,9 +5096,7 @@ static int enlarge_buffer(OSST_buffer *STbuffer, int need_dma)
for (segs=STbuffer->sg_segs=1, got=b_size;
segs < max_segs && got < OS_FRAME_SIZE; ) {
STbuffer->sg[segs].page =
(OS_FRAME_SIZE - got <= PAGE_SIZE / 2) ?
kmalloc(OS_FRAME_SIZE - got, priority):
alloc_pages(priority, order);
alloc_pages(priority, (OS_FRAME_SIZE - got <= PAGE_SIZE) ? 0 : order);
STbuffer->sg[segs].offset = 0;
if (STbuffer->sg[segs].page == NULL) {
if (OS_FRAME_SIZE - got <= (max_segs - segs) * b_size / 2 && order) {
......@@ -5320,10 +5304,8 @@ static void validate_options (void)
if (max_sg_segs >= OSST_FIRST_SG)
osst_max_sg_segs = max_sg_segs;
#if DEBUG
printk(OSST_DEB_MSG "osst :D: max tapes %d, write threshold %d, s/g segs %d.\n",
printk(OSST_DEB_MSG "osst :D: max tapes %d, write threshold %d, max s/g segs %d.\n",
osst_max_dev, osst_write_threshold, osst_max_sg_segs);
//printk(OSST_DEB_MSG "osst :D: sizeof(header) = %d (%s)\n",
// sizeof(os_header_t),sizeof(os_header_t)==OS_DATA_SIZE?"ok":"error");
#endif
}
......@@ -5446,7 +5428,7 @@ static int osst_attach(Scsi_Device * SDp)
drive = alloc_disk(1);
if (!drive) {
printk(KERN_ERR "osst :E: Out of memory. Device not attached.\n");
return 1;
goto out_slave_detach;
}
/* if this is the first attach, build the infrastructure */
......@@ -5458,7 +5440,7 @@ static int osst_attach(Scsi_Device * SDp)
if (os_scsi_tapes == NULL) {
write_unlock(&os_scsi_tapes_lock);
printk(KERN_ERR "osst :E: Unable to allocate array for OnStream SCSI tapes.\n");
return 1;
goto out_put_disk;
}
for (i=0; i < osst_max_dev; ++i) os_scsi_tapes[i] = NULL;
}
......@@ -5466,8 +5448,7 @@ static int osst_attach(Scsi_Device * SDp)
if (osst_nr_dev >= osst_max_dev) {
write_unlock(&os_scsi_tapes_lock);
printk(KERN_ERR "osst :E: Too many tape devices (max. %d).\n", osst_max_dev);
put_disk(drive);
return 1;
goto out_put_disk;
}
/* find a free minor number */
......@@ -5480,9 +5461,7 @@ static int osst_attach(Scsi_Device * SDp)
if (tpnt == NULL) {
write_unlock(&os_scsi_tapes_lock);
printk(KERN_ERR "osst :E: Can't allocate device descriptor, device not attached.\n");
put_disk(drive);
scsi_slave_detach(SDp);
return 1;
goto out_put_disk;
}
memset(tpnt, 0, sizeof(OS_Scsi_Tape));
......@@ -5495,9 +5474,7 @@ static int osst_attach(Scsi_Device * SDp)
write_unlock(&os_scsi_tapes_lock);
printk(KERN_ERR "osst :E: Unable to allocate a tape buffer, device not attached.\n");
kfree(tpnt);
put_disk(drive);
scsi_slave_detach(SDp);
return 1;
goto out_put_disk;
}
os_scsi_tapes[dev_num] = tpnt;
tpnt->buffer = buffer;
......@@ -5623,6 +5600,12 @@ static int osst_attach(Scsi_Device * SDp)
SDp->model, SDp->host->host_no, SDp->channel, SDp->id, SDp->lun, tape_name(tpnt));
return 0;
out_put_disk:
put_disk(drive);
out_slave_detach:
scsi_slave_detach(SDp);
return 1;
};
static void osst_detach(Scsi_Device * SDp)
......@@ -5630,11 +5613,12 @@ static void osst_detach(Scsi_Device * SDp)
OS_Scsi_Tape * tpnt;
int i, mode;
if ((SDp->type != TYPE_TAPE) || (osst_nr_dev <= 0))
return;
write_lock(&os_scsi_tapes_lock);
if (os_scsi_tapes != NULL) {
for(i=0; i<osst_max_dev; i++) {
tpnt = os_scsi_tapes[i];
if(tpnt != NULL && tpnt->device == SDp) {
for(i=0; i < osst_max_dev; i++) {
if((tpnt = os_scsi_tapes[i]) && (tpnt->device == SDp)) {
tpnt->device = NULL;
for (mode = 0; mode < ST_NBR_MODES; ++mode) {
devfs_unregister (tpnt->de_r[mode]);
......@@ -5660,18 +5644,15 @@ static void osst_detach(Scsi_Device * SDp)
&dev_attr_kdev);
device_unregister(&tpnt->driverfs_dev_n[mode]);
}
if (tpnt->header_cache != NULL)
vfree(tpnt->header_cache);
if (tpnt->header_cache != NULL) vfree(tpnt->header_cache);
if (tpnt->buffer) {
normalize_buffer(tpnt->buffer);
kfree(tpnt->buffer);
}
kfree(tpnt);
break;
}
return;
}
}
write_unlock(&os_scsi_tapes_lock);
return;
}
......@@ -5681,12 +5662,8 @@ static int __init init_osst(void)
printk(KERN_INFO "osst :I: Tape driver with OnStream support version %s\nosst :I: %s\n", osst_version, cvsid);
validate_options();
#if DEBUG
printk(OSST_DEB_MSG "osst :D: %d s/g segments, write threshold %d bytes.\n",
max_sg_segs, osst_write_threshold);
#endif
if ((register_chrdev(OSST_MAJOR, "osst", &osst_fops) < 0) ||
scsi_register_device(&osst_template)) {
if ((register_chrdev(OSST_MAJOR,"osst", &osst_fops) < 0) || scsi_register_device(&osst_template)) {
printk(KERN_ERR "osst :E: Unable to register major %d for OnStream tapes\n", OSST_MAJOR);
return 1;
}
......
......@@ -177,6 +177,13 @@ void scsi_initialize_queue(Scsi_Device * SDpnt, struct Scsi_Host * SHpnt)
*/
blk_queue_max_phys_segments(q, MAX_PHYS_SEGMENTS);
if(!SHpnt->max_sectors)
/* driver imposes no hard sector transfer limit.
* start at machine infinity initially */
SHpnt->max_sectors = SCSI_DEFAULT_MAX_SECTORS;
/* FIXME: we should also adjust this limit later on
* after we know what the device capabilities are */
blk_queue_max_sectors(q, SHpnt->max_sectors);
if (!SHpnt->use_clustering)
......
......@@ -373,6 +373,14 @@ extern const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE];
#define ASKED_FOR_SENSE 0x20
#define SYNC_RESET 0x40
/*
* This specifies "machine infinity" for host templates which don't
* limit the transfer size. Note this limit represents an absolute
* maximum, and may be over the transfer limits allowed for individual
* devices (e.g. 256 for SCSI-1)
*/
#define SCSI_DEFAULT_MAX_SECTORS 1024
/*
* This is the crap from the old error handling code. We have it in a special
* place so that we can more easily delete it later on.
......
......@@ -172,7 +172,7 @@ static inline struct scsi_disk *scsi_disk(struct gendisk *disk)
**/
static int sd_init_command(struct scsi_cmnd * SCpnt)
{
int this_count, timeout;
unsigned int this_count, timeout;
struct gendisk *disk;
sector_t block;
struct scsi_device *sdp = SCpnt->device;
......@@ -299,7 +299,22 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
SCpnt->cmnd[1] = 0;
if (((this_count > 0xff) || (block > 0x1fffff)) || SCpnt->device->ten) {
if (block > 0xffffffff) {
SCpnt->cmnd[0] += READ_16 - READ_6;
SCpnt->cmnd[2] = (unsigned char) (block >> 56) & 0xff;
SCpnt->cmnd[3] = (unsigned char) (block >> 48) & 0xff;
SCpnt->cmnd[4] = (unsigned char) (block >> 40) & 0xff;
SCpnt->cmnd[5] = (unsigned char) (block >> 32) & 0xff;
SCpnt->cmnd[6] = (unsigned char) (block >> 24) & 0xff;
SCpnt->cmnd[7] = (unsigned char) (block >> 16) & 0xff;
SCpnt->cmnd[8] = (unsigned char) (block >> 8) & 0xff;
SCpnt->cmnd[9] = (unsigned char) block & 0xff;
SCpnt->cmnd[10] = (unsigned char) (this_count >> 24) & 0xff;
SCpnt->cmnd[11] = (unsigned char) (this_count >> 16) & 0xff;
SCpnt->cmnd[12] = (unsigned char) (this_count >> 8) & 0xff;
SCpnt->cmnd[13] = (unsigned char) this_count & 0xff;
SCpnt->cmnd[14] = SCpnt->cmnd[15] = 0;
} else if (((this_count > 0xff) || (block > 0x1fffff)) || SCpnt->device->ten) {
if (this_count > 0xffff)
this_count = 0xffff;
......@@ -904,16 +919,26 @@ sd_read_cache_type(struct scsi_disk *sdkp, char *diskname,
static void
sd_read_capacity(struct scsi_disk *sdkp, char *diskname,
struct scsi_request *SRpnt, unsigned char *buffer) {
unsigned char cmd[10];
unsigned char cmd[16];
struct scsi_device *sdp = sdkp->device;
int the_result, retries;
int sector_size;
int sector_size = 0;
int longrc = 0;
repeat:
retries = 3;
do {
if (longrc) {
memset((void *) cmd, 0, 16);
cmd[0] = SERVICE_ACTION_IN;
cmd[1] = 0x10; /* READ CAPACITY (16) */
cmd[13] = 12;
memset((void *) buffer, 0, 12);
} else {
cmd[0] = READ_CAPACITY;
memset((void *) &cmd[1], 0, 9);
memset((void *) buffer, 0, 8);
}
SRpnt->sr_cmd_len = 0;
SRpnt->sr_sense_buffer[0] = 0;
......@@ -921,7 +946,7 @@ sd_read_capacity(struct scsi_disk *sdkp, char *diskname,
SRpnt->sr_data_direction = SCSI_DATA_READ;
scsi_wait_req(SRpnt, (void *) cmd, (void *) buffer,
8, SD_TIMEOUT, SD_MAX_RETRIES);
longrc ? 12 : 8, SD_TIMEOUT, SD_MAX_RETRIES);
if (media_not_present(sdkp, SRpnt))
return;
......@@ -931,7 +956,7 @@ sd_read_capacity(struct scsi_disk *sdkp, char *diskname,
} while (the_result && retries);
if (the_result) {
if (the_result && !longrc) {
printk(KERN_NOTICE "%s : READ CAPACITY failed.\n"
"%s : status=%x, message=%02x, host=%d, driver=%02x \n",
diskname, diskname,
......@@ -957,16 +982,51 @@ sd_read_capacity(struct scsi_disk *sdkp, char *diskname,
sdkp->capacity = 0x200000; /* 1 GB - random */
return;
} else if (the_result && longrc) {
/* READ CAPACITY(16) has been failed */
printk(KERN_NOTICE "%s : READ CAPACITY(16) failed.\n"
"%s : status=%x, message=%02x, host=%d, driver=%02x \n",
diskname, diskname,
status_byte(the_result),
msg_byte(the_result),
host_byte(the_result),
driver_byte(the_result));
printk(KERN_NOTICE "%s : use 0xffffffff as device size\n",
diskname);
sdkp->capacity = 1 + (sector_t) 0xffffffff;
goto got_data;
}
if (!longrc) {
sector_size = (buffer[4] << 24) |
(buffer[5] << 16) | (buffer[6] << 8) | buffer[7];
if (buffer[0] == 0xff && buffer[1] == 0xff &&
buffer[2] == 0xff && buffer[3] == 0xff) {
printk(KERN_NOTICE "%s : very big device. try to use"
" READ CAPACITY(16).\n", diskname);
longrc = 1;
goto repeat;
}
sdkp->capacity = 1 + (((sector_t)buffer[0] << 24) |
(buffer[1] << 16) |
(buffer[2] << 8) |
buffer[3]);
} else {
sdkp->capacity = 1 + (((sector_t)buffer[0] << 56) |
((sector_t)buffer[1] << 48) |
((sector_t)buffer[2] << 40) |
((sector_t)buffer[3] << 32) |
((sector_t)buffer[4] << 24) |
((sector_t)buffer[5] << 16) |
((sector_t)buffer[6] << 8) |
(sector_t)buffer[7]);
sector_size = (buffer[8] << 24) |
(buffer[9] << 16) | (buffer[10] << 8) | buffer[11];
}
sector_size = (buffer[4] << 24) |
(buffer[5] << 16) | (buffer[6] << 8) | buffer[7];
got_data:
if (sector_size == 0) {
sector_size = 512;
printk(KERN_NOTICE "%s : sector size 0 reported, "
......
......@@ -96,6 +96,10 @@ extern const unsigned char scsi_command_size[8];
#define READ_ELEMENT_STATUS 0xb8
#define SEND_VOLUME_TAG 0xb6
#define WRITE_LONG_2 0xea
#define READ_16 0x88
#define WRITE_16 0x8a
#define SERVICE_ACTION_IN 0x9e
/*
* Status codes
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment