diff options
| author | Linus Torvalds <torvalds@home.transmeta.com> | 2002-06-17 20:44:40 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@home.transmeta.com> | 2002-06-17 20:44:40 -0700 |
| commit | 67aa39887934bb4c2dfce580dd43b0bc065867a4 (patch) | |
| tree | e73b5aca059056b00d89f9bc8e45eb10666b1667 | |
| parent | 94173f6818a6a2816f4104f698f56d304a397405 (diff) | |
| parent | f179b6ce3a03a6ee60c821766691488a6f461c52 (diff) | |
Merge home.transmeta.com:/home/torvalds/v2.5/scsi-tape
into home.transmeta.com:/home/torvalds/v2.5/linux
| -rw-r--r-- | drivers/scsi/README.st | 46 | ||||
| -rw-r--r-- | drivers/scsi/st.c | 429 | ||||
| -rw-r--r-- | drivers/scsi/st_options.h | 15 |
3 files changed, 152 insertions, 338 deletions
diff --git a/drivers/scsi/README.st b/drivers/scsi/README.st index e06a21597910..702a5b178b61 100644 --- a/drivers/scsi/README.st +++ b/drivers/scsi/README.st @@ -2,7 +2,7 @@ This file contains brief information about the SCSI tape driver. The driver is currently maintained by Kai M{kisara (email Kai.Makisara@metla.fi) -Last modified: Tue Jan 22 21:08:57 2002 by makisara +Last modified: Tue Jun 18 18:13:50 2002 by makisara BASICS @@ -105,15 +105,19 @@ The default is BSD semantics. BUFFERING -The driver uses tape buffers allocated either at system initialization -or at run-time when needed. One buffer is used for each open tape -device. The size of the buffers is selectable at compile and/or boot -time. The buffers are used to store the data being transferred to/from -the SCSI adapter. The following buffering options are selectable at -compile time and/or at run time (via ioctl): +The driver uses tape buffers allocated at run-time when needed and it +is freed when the device file is closed. One buffer is used for each +open tape device. + +The size of the buffers is always at least one tape block. In fixed +block mode, the minimum buffer size is defined (in 1024 byte units) by +ST_FIXED_BUFFER_BLOCKS. With small block size this allows buffering of +several blocks and using one SCSI read or write to transfer all of the +blocks. Buffering of data across write calls in fixed block mode is +allowed if ST_BUFFER_WRITES is non-zero. Buffer allocation uses chunks of +memory having sizes 2^n * (page size). Because of this the actual +buffer size may be larger than the minimum allowable buffer size. -Buffering of data across write calls in fixed block mode (define -ST_BUFFER_WRITES). Asynchronous writing. Writing the buffer contents to the tape is started and the write call returns immediately. The status is checked @@ -128,30 +132,6 @@ attempted even if the user does not want to get all of the data at this read command. Should be disabled for those drives that don't like a filemark to truncate a read request or that don't like backspacing. -The buffer size is defined (in 1024 byte units) by ST_BUFFER_BLOCKS or -at boot time. If this size is not large enough, the driver tries to -temporarily enlarge the buffer. Buffer allocation uses chunks of -memory having sizes 2^n * (page size). Because of this the actual -buffer size may be larger than the buffer size specified with -ST_BUFFER_BLOCKS. - -A small number of buffers are allocated at driver initialisation. The -maximum number of these buffers is defined by ST_MAX_BUFFERS. The -maximum can be changed with kernel or module startup options. One -buffer is allocated for each drive detected when the driver is -initialized up to the maximum. - -The driver tries to allocate new buffers at run-time if -necessary. These buffers are freed after use. If the maximum number of -initial buffers is set to zero, all buffer allocation is done at -run-time. The advantage of run-time allocation is that memory is not -wasted for buffers not being used. The disadvantage is that there may -not be memory available at the time when a buffer is needed for the -first time (once a buffer is allocated, it is not released). This risk -should not be big if the tape drive is connected to a PCI adapter that -supports scatter/gather (the allocation is not limited to "DMA memory" -and the buffer can be composed of several fragments). - The threshold for triggering asynchronous write in fixed block mode is defined by ST_WRITE_THRESHOLD. This may be optimized for each use pattern. The default triggers asynchronous write after three diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index f48ac845bc08..7342c3e661f3 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -12,13 +12,13 @@ Copyright 1992 - 2002 Kai Makisara email Kai.Makisara@metla.fi - Last modified: Tue Feb 5 21:25:55 2002 by makisara + Last modified: Sat Jun 15 13:01:56 2002 by makisara Some small formal changes - aeb, 950809 Last modified: 18-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support */ -static char *verstr = "20020205"; +static char *verstr = "20020615"; #include <linux/module.h> @@ -69,7 +69,6 @@ static char *verstr = "20020205"; static int buffer_kbs; static int write_threshold_kbs; -static int max_buffers = (-1); static int max_sg_segs; MODULE_AUTHOR("Kai Makisara"); @@ -80,8 +79,6 @@ MODULE_PARM(buffer_kbs, "i"); MODULE_PARM_DESC(buffer_kbs, "Default driver buffer size (KB; 32)"); MODULE_PARM(write_threshold_kbs, "i"); MODULE_PARM_DESC(write_threshold_kbs, "Asynchronous write threshold (KB; 30)"); -MODULE_PARM(max_buffers, "i"); -MODULE_PARM_DESC(max_buffers, "Maximum number of buffer allocated at initialisation (4)"); MODULE_PARM(max_sg_segs, "i"); MODULE_PARM_DESC(max_sg_segs, "Maximum number of scatter/gather segments to use (32)"); @@ -97,9 +94,6 @@ static struct st_dev_parm { "write_threshold_kbs", &write_threshold_kbs }, { - "max_buffers", &max_buffers - }, - { "max_sg_segs", &max_sg_segs } }; @@ -108,12 +102,12 @@ static struct st_dev_parm { /* The default definitions have been moved to st_options.h */ -#define ST_BUFFER_SIZE (ST_BUFFER_BLOCKS * ST_KILOBYTE) +#define ST_FIXED_BUFFER_SIZE (ST_FIXED_BUFFER_BLOCKS * ST_KILOBYTE) #define ST_WRITE_THRESHOLD (ST_WRITE_THRESHOLD_BLOCKS * ST_KILOBYTE) /* The buffer size should fit into the 24 bits for length in the 6-byte SCSI read and write commands. */ -#if ST_BUFFER_SIZE >= (2 << 24 - 1) +#if ST_FIXED_BUFFER_SIZE >= (2 << 24 - 1) #error "Buffer size should not exceed (2 << 24 - 1) bytes!" #endif @@ -121,7 +115,7 @@ DEB( static int debugging = DEBUG; ) #define MAX_RETRIES 0 #define MAX_WRITE_RETRIES 0 -#define MAX_READY_RETRIES 5 +#define MAX_READY_RETRIES 0 #define NO_TAPE NOT_READY #define ST_TIMEOUT (900 * HZ) @@ -137,18 +131,15 @@ DEB( static int debugging = DEBUG; ) #define ST_DEV_ARR_LUMP 6 static rwlock_t st_dev_arr_lock = RW_LOCK_UNLOCKED; -static int st_nbr_buffers; -static ST_buffer **st_buffers = NULL; -static int st_buffer_size = ST_BUFFER_SIZE; +static int st_fixed_buffer_size = ST_FIXED_BUFFER_SIZE; static int st_write_threshold = ST_WRITE_THRESHOLD; -static int st_max_buffers = ST_MAX_BUFFERS; static int st_max_sg_segs = ST_MAX_SG; static Scsi_Tape **scsi_tapes = NULL; static int modes_defined; -static ST_buffer *new_tape_buffer(int, int, int); +static ST_buffer *new_tape_buffer(int, int); static int enlarge_buffer(ST_buffer *, int, int); static void normalize_buffer(ST_buffer *); static int append_to_buffer(const char *, ST_buffer *, int); @@ -914,8 +905,7 @@ static int check_tape(Scsi_Tape *STp, struct file *filp) module count. */ static int st_open(struct inode *inode, struct file *filp) { - int i, need_dma_buffer; - int retval = (-EIO); + int i, retval = (-EIO); Scsi_Tape *STp; ST_partstat *STps; int dev = TAPE_NR(inode->i_rdev); @@ -945,38 +935,15 @@ static int st_open(struct inode *inode, struct file *filp) goto err_out; } - /* Allocate a buffer for this user */ - need_dma_buffer = STp->restr_dma; - write_lock(&st_dev_arr_lock); - for (i = 0; i < st_nbr_buffers; i++) - if (!st_buffers[i]->in_use && - (!need_dma_buffer || st_buffers[i]->dma)) { - STp->buffer = st_buffers[i]; - (STp->buffer)->in_use = 1; - break; - } - write_unlock(&st_dev_arr_lock); - if (i >= st_nbr_buffers) { - STp->buffer = new_tape_buffer(FALSE, need_dma_buffer, TRUE); - if (STp->buffer == NULL) { - printk(KERN_WARNING "st%d: Can't allocate tape buffer.\n", dev); - retval = (-EBUSY); - goto err_out; - } + /* See that we have at least a one page buffer available */ + if (!enlarge_buffer(STp->buffer, PAGE_SIZE, STp->restr_dma)) { + printk(KERN_WARNING "st%d: Can't allocate tape buffer.\n", dev); + retval = (-EOVERFLOW); + goto err_out; } (STp->buffer)->writing = 0; (STp->buffer)->syscall_result = 0; - (STp->buffer)->use_sg = STp->device->host->sg_tablesize; - - /* Compute the usable buffer size for this SCSI adapter */ - if (!(STp->buffer)->use_sg) - (STp->buffer)->buffer_size = (STp->buffer)->sg[0].length; - else { - for (i = 0, (STp->buffer)->buffer_size = 0; i < (STp->buffer)->use_sg && - i < (STp->buffer)->sg_segs; i++) - (STp->buffer)->buffer_size += (STp->buffer)->sg[i].length; - } STp->write_prot = ((filp->f_flags & O_ACCMODE) == O_RDONLY); @@ -999,10 +966,7 @@ static int st_open(struct inode *inode, struct file *filp) return 0; err_out: - if (STp->buffer != NULL) { - (STp->buffer)->in_use = 0; - STp->buffer = NULL; - } + normalize_buffer(STp->buffer); STp->in_use = 0; STp->device->access_count--; if (STp->device->host->hostt->module) @@ -1149,16 +1113,8 @@ static int st_release(struct inode *inode, struct file *filp) if (STp->door_locked == ST_LOCKED_AUTO) st_int_ioctl(STp, MTUNLOCK, 0); - if (STp->buffer != NULL) { - normalize_buffer(STp->buffer); - write_lock(&st_dev_arr_lock); - (STp->buffer)->in_use = 0; - STp->buffer = NULL; - } - else { - write_lock(&st_dev_arr_lock); - } - + normalize_buffer(STp->buffer); + write_lock(&st_dev_arr_lock); STp->in_use = 0; write_unlock(&st_dev_arr_lock); STp->device->access_count--; @@ -1168,31 +1124,11 @@ static int st_release(struct inode *inode, struct file *filp) return result; } - -/* Write command */ -static ssize_t - st_write(struct file *filp, const char *buf, size_t count, loff_t * ppos) +/* The checks common to both reading and writing */ +static ssize_t rw_checks(Scsi_Tape *STp, struct file *filp, size_t count, loff_t *ppos) { - struct inode *inode = filp->f_dentry->d_inode; - ssize_t total; - ssize_t i, do_count, blks, transfer; + int bufsize; ssize_t retval = 0; - int write_threshold; - int doing_write = 0; - unsigned char cmd[MAX_COMMAND_SIZE]; - const char *b_point; - Scsi_Request *SRpnt = NULL; - Scsi_Tape *STp; - ST_mode *STm; - ST_partstat *STps; - int dev = TAPE_NR(inode->i_rdev); - - read_lock(&st_dev_arr_lock); - STp = scsi_tapes[dev]; - read_unlock(&st_dev_arr_lock); - - if (down_interruptible(&STp->lock)) - return -ERESTARTSYS; /* * If we are in the middle of error recovery, don't let anyone @@ -1219,13 +1155,11 @@ static ssize_t goto out; } - STm = &(STp->modes[STp->current_mode]); - if (!STm->defined) { + if (! STp->modes[STp->current_mode].defined) { retval = (-ENXIO); goto out; } - if (count == 0) - goto out; + /* * If there was a bus reset, block further access @@ -1236,30 +1170,20 @@ static ssize_t goto out; } + if (count == 0) + goto out; + DEB( if (!STp->in_use) { + int dev = TAPE_NR(filp->f_dentry->d_inode->i_rdev); printk(ST_DEB_MSG "st%d: Incorrect device.\n", dev); retval = (-EIO); goto out; } ) /* end DEB */ - /* Write must be integral number of blocks */ - if (STp->block_size != 0 && (count % STp->block_size) != 0) { - printk(KERN_WARNING "st%d: Write not multiple of tape block size.\n", - dev); - retval = (-EINVAL); - goto out; - } - if (STp->can_partitions && (retval = update_partition(STp)) < 0) goto out; - STps = &(STp->ps[STp->partition]); - - if (STp->write_prot) { - retval = (-EACCES); - goto out; - } if (STp->block_size == 0) { if (STp->max_block > 0 && @@ -1273,19 +1197,73 @@ static ssize_t goto out; } } - if ((STp->buffer)->buffer_blocks < 1) { - /* Fixed block mode with too small buffer */ - if (!enlarge_buffer(STp->buffer, STp->block_size, STp->restr_dma)) { + else { + /* Fixed block mode with too small buffer? */ + bufsize = STp->block_size > st_fixed_buffer_size ? + STp->block_size : st_fixed_buffer_size; + if ((STp->buffer)->buffer_size < bufsize && + !enlarge_buffer(STp->buffer, bufsize, STp->restr_dma)) { retval = (-EOVERFLOW); goto out; } - (STp->buffer)->buffer_blocks = 1; + (STp->buffer)->buffer_blocks = bufsize / STp->block_size; } if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED && !st_int_ioctl(STp, MTLOCK, 0)) STp->door_locked = ST_LOCKED_AUTO; + out: + return retval; +} + + +/* Write command */ +static ssize_t + st_write(struct file *filp, const char *buf, size_t count, loff_t * ppos) +{ + struct inode *inode = filp->f_dentry->d_inode; + ssize_t total; + ssize_t i, do_count, blks, transfer; + ssize_t retval; + int write_threshold; + int doing_write = 0; + unsigned char cmd[MAX_COMMAND_SIZE]; + const char *b_point; + Scsi_Request *SRpnt = NULL; + Scsi_Tape *STp; + ST_mode *STm; + ST_partstat *STps; + int dev = TAPE_NR(inode->i_rdev); + + read_lock(&st_dev_arr_lock); + STp = scsi_tapes[dev]; + read_unlock(&st_dev_arr_lock); + + if (down_interruptible(&STp->lock)) + return -ERESTARTSYS; + + retval = rw_checks(STp, filp, count, ppos); + if (retval || count == 0) + goto out; + + /* Write must be integral number of blocks */ + if (STp->block_size != 0 && (count % STp->block_size) != 0) { + printk(KERN_WARNING "st%d: Write not multiple of tape block size.\n", + dev); + retval = (-EINVAL); + goto out; + } + + STm = &(STp->modes[STp->current_mode]); + STps = &(STp->ps[STp->partition]); + + if (STp->write_prot) { + retval = (-EACCES); + goto out; + } + + if (STps->rw == ST_READING) { retval = flush_buffer(STp, 0); if (retval) @@ -1718,77 +1696,17 @@ static ssize_t if (down_interruptible(&STp->lock)) return -ERESTARTSYS; - /* - * If we are in the middle of error recovery, don't let anyone - * else try and use this device. Also, if error recovery fails, it - * may try and take the device offline, in which case all further - * access to the device is prohibited. - */ - if (!scsi_block_when_processing_errors(STp->device)) { - retval = (-ENXIO); - goto out; - } - - if (ppos != &filp->f_pos) { - /* "A request was outside the capabilities of the device." */ - retval = (-ENXIO); + retval = rw_checks(STp, filp, count, ppos); + if (retval || count == 0) goto out; - } - if (STp->ready != ST_READY) { - if (STp->ready == ST_NO_TAPE) - retval = (-ENOMEDIUM); - else - retval = (-EIO); - goto out; - } STm = &(STp->modes[STp->current_mode]); - if (!STm->defined) { - retval = (-ENXIO); - goto out; - } - DEB( - if (!STp->in_use) { - printk(ST_DEB_MSG "st%d: Incorrect device.\n", dev); - retval = (-EIO); - goto out; - } ) /* end DEB */ - - if (STp->can_partitions && - (retval = update_partition(STp)) < 0) - goto out; - - if (STp->block_size == 0) { - if (STp->max_block > 0 && - (count < STp->min_block || count > STp->max_block)) { - retval = (-EINVAL); - goto out; - } - if (count > (STp->buffer)->buffer_size && - !enlarge_buffer(STp->buffer, count, STp->restr_dma)) { - retval = (-EOVERFLOW); - goto out; - } - } - if ((STp->buffer)->buffer_blocks < 1) { - /* Fixed block mode with too small buffer */ - if (!enlarge_buffer(STp->buffer, STp->block_size, STp->restr_dma)) { - retval = (-EOVERFLOW); - goto out; - } - (STp->buffer)->buffer_blocks = 1; - } - if (!(STm->do_read_ahead) && STp->block_size != 0 && (count % STp->block_size) != 0) { retval = (-EINVAL); /* Read must be integral number of blocks */ goto out; } - if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED && - !st_int_ioctl(STp, MTLOCK, 0)) - STp->door_locked = ST_LOCKED_AUTO; - STps = &(STp->ps[STp->partition]); if (STps->rw == ST_WRITING) { retval = flush_buffer(STp, 0); @@ -1986,7 +1904,7 @@ static int st_set_options(Scsi_Tape *STp, long options) st_log_options(STp, STm, dev); } else if (code == MT_ST_WRITE_THRESHOLD) { value = (options & ~MT_ST_OPTIONS) * ST_KILOBYTE; - if (value < 1 || value > st_buffer_size) { + if (value < 1 || value > st_fixed_buffer_size) { printk(KERN_WARNING "st%d: Write threshold %d too small or too large.\n", dev, value); @@ -2289,8 +2207,10 @@ static int do_load_unload(Scsi_Tape *STp, struct file *filp, int load_code) if (!retval) { /* SCSI command successful */ - if (!load_code) + if (!load_code) { STp->rew_at_close = 0; + STp->ready = ST_NO_TAPE; + } else { STp->rew_at_close = STp->autorew_dev; retval = check_tape(STp, filp); @@ -2619,10 +2539,14 @@ static int st_int_ioctl(Scsi_Tape *STp, unsigned int cmd_in, unsigned long arg) ioctl_result = st_int_ioctl(STp, MTBSF, 1); if (cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) { + int old_block_size = STp->block_size; STp->block_size = arg & MT_ST_BLKSIZE_MASK; - if (STp->block_size != 0) + if (STp->block_size != 0) { + if (old_block_size == 0) + normalize_buffer(STp->buffer); (STp->buffer)->buffer_blocks = (STp->buffer)->buffer_size / STp->block_size; + } (STp->buffer)->buffer_bytes = (STp->buffer)->read_pointer = 0; if (cmd_in == SET_DENS_AND_BLK) STp->density = arg >> MT_ST_DENSITY_SHIFT; @@ -3372,18 +3296,11 @@ static int st_ioctl(struct inode *inode, struct file *file, /* Try to allocate a new tape buffer. Calling function must not hold dev_arr_lock. */ static ST_buffer * - new_tape_buffer(int from_initialization, int need_dma, int in_use) + new_tape_buffer(int from_initialization, int need_dma) { - int i, priority, b_size, order, got = 0, segs = 0; + int i, priority, got = 0, segs = 0; ST_buffer *tb; - read_lock(&st_dev_arr_lock); - if (st_nbr_buffers >= st_template.dev_max) { - read_unlock(&st_dev_arr_lock); - return NULL; /* Should never happen */ - } - read_unlock(&st_dev_arr_lock); - if (from_initialization) priority = GFP_ATOMIC; else @@ -3391,85 +3308,19 @@ static ST_buffer * i = sizeof(ST_buffer) + (st_max_sg_segs - 1) * sizeof(struct scatterlist); tb = kmalloc(i, priority); - if (tb) { - if (need_dma) - priority |= GFP_DMA; - - /* Try to allocate the first segment up to ST_FIRST_ORDER and the - others big enough to reach the goal */ - for (b_size = PAGE_SIZE, order=0; - b_size < st_buffer_size && order < ST_FIRST_ORDER; - order++, b_size *= 2) - ; - for ( ; b_size >= PAGE_SIZE; order--, b_size /= 2) { - tb->sg[0].page = alloc_pages(priority, order); - tb->sg[0].offset = 0; - if (tb->sg[0].page != NULL) { - tb->sg[0].length = b_size; - break; - } - } - if (tb->sg[segs].page == NULL) { - kfree(tb); - tb = NULL; - } else { /* Got something, continue */ - - for (b_size = PAGE_SIZE, order=0; - st_buffer_size > - tb->sg[0].length + (ST_FIRST_SG - 1) * b_size; - order++, b_size *= 2) - ; - for (segs = 1, got = tb->sg[0].length; - got < st_buffer_size && segs < ST_FIRST_SG;) { - tb->sg[segs].page = alloc_pages(priority, order); - tb->sg[segs].offset = 0; - if (tb->sg[segs].page == NULL) { - if (st_buffer_size - got <= - (ST_FIRST_SG - segs) * b_size / 2) { - b_size /= 2; /* Large enough for the - rest of the buffers */ - order--; - continue; - } - tb->sg_segs = segs; - tb->orig_sg_segs = 0; - DEB(tb->buffer_size = got); - normalize_buffer(tb); - kfree(tb); - tb = NULL; - break; - } - tb->sg[segs].length = b_size; - got += b_size; - segs++; - } - } - } - if (!tb) { - printk(KERN_NOTICE "st: Can't allocate new tape buffer (nbr %d).\n", - st_nbr_buffers); + printk(KERN_NOTICE "st: Can't allocate new tape buffer.\n"); return NULL; } tb->sg_segs = tb->orig_sg_segs = segs; - tb->b_data = page_address(tb->sg[0].page); + if (segs > 0) + tb->b_data = page_address(tb->sg[0].page); - DEBC(printk(ST_DEB_MSG - "st: Allocated tape buffer %d (%d bytes, %d segments, dma: %d, a: %p).\n", - st_nbr_buffers, got, tb->sg_segs, need_dma, tb->b_data); - printk(ST_DEB_MSG - "st: segment sizes: first %d, last %d bytes.\n", - tb->sg[0].length, tb->sg[segs - 1].length); - ) - tb->in_use = in_use; + tb->in_use = TRUE; tb->dma = need_dma; tb->buffer_size = got; tb->writing = 0; - write_lock(&st_dev_arr_lock); - st_buffers[st_nbr_buffers++] = tb; - write_unlock(&st_dev_arr_lock); - return tb; } @@ -3479,6 +3330,9 @@ static int enlarge_buffer(ST_buffer * STbuffer, int new_size, int need_dma) { int segs, nbr, max_segs, b_size, priority, order, got; + if (new_size <= STbuffer->buffer_size) + return TRUE; + normalize_buffer(STbuffer); max_segs = STbuffer->use_sg; @@ -3492,13 +3346,14 @@ static int enlarge_buffer(ST_buffer * STbuffer, int new_size, int need_dma) if (need_dma) priority |= GFP_DMA; for (b_size = PAGE_SIZE, order=0; - b_size * nbr < new_size - STbuffer->buffer_size; + b_size < new_size - STbuffer->buffer_size; order++, b_size *= 2) ; /* empty */ for (segs = STbuffer->sg_segs, got = STbuffer->buffer_size; segs < max_segs && got < new_size;) { STbuffer->sg[segs].page = alloc_pages(priority, order); + /* printk("st: allocated %x, order %d\n", STbuffer->sg[segs].page, order); */ STbuffer->sg[segs].offset = 0; if (STbuffer->sg[segs].page == NULL) { if (new_size - got <= (max_segs - segs) * b_size / 2) { @@ -3518,9 +3373,10 @@ static int enlarge_buffer(ST_buffer * STbuffer, int new_size, int need_dma) STbuffer->buffer_size = got; segs++; } + STbuffer->b_data = page_address(STbuffer->sg[0].page); DEBC(printk(ST_DEB_MSG - "st: Succeeded to enlarge buffer to %d bytes (segs %d->%d, %d).\n", - got, STbuffer->orig_sg_segs, STbuffer->sg_segs, b_size)); + "st: Succeeded to enlarge buffer at %p to %d bytes (segs %d->%d, %d).\n", + STbuffer, got, STbuffer->orig_sg_segs, STbuffer->sg_segs, b_size)); return TRUE; } @@ -3535,14 +3391,14 @@ static void normalize_buffer(ST_buffer * STbuffer) for (b_size=PAGE_SIZE, order=0; b_size < STbuffer->sg[i].length; order++, b_size *= 2) ; /* empty */ + /* printk("st: freeing %x, order %d\n", STbuffer->sg[i].page, order); */ __free_pages(STbuffer->sg[i].page, order); STbuffer->buffer_size -= STbuffer->sg[i].length; } DEB( if (debugging && STbuffer->orig_sg_segs < STbuffer->sg_segs) printk(ST_DEB_MSG "st: Buffer at %p normalized to %d bytes (segs %d).\n", - page_address(STbuffer->sg[0].page), STbuffer->buffer_size, - STbuffer->sg_segs); + STbuffer, STbuffer->buffer_size, STbuffer->sg_segs); ) /* end DEB */ STbuffer->sg_segs = STbuffer->orig_sg_segs; } @@ -3619,18 +3475,16 @@ static int from_buffer(ST_buffer * st_bp, char *ubp, int do_count) static void validate_options(void) { if (buffer_kbs > 0) - st_buffer_size = buffer_kbs * ST_KILOBYTE; + st_fixed_buffer_size = buffer_kbs * ST_KILOBYTE; if (write_threshold_kbs > 0) st_write_threshold = write_threshold_kbs * ST_KILOBYTE; else if (buffer_kbs > 0) - st_write_threshold = st_buffer_size - 2048; - if (st_write_threshold > st_buffer_size) { - st_write_threshold = st_buffer_size; + st_write_threshold = st_fixed_buffer_size - 2048; + if (st_write_threshold > st_fixed_buffer_size) { + st_write_threshold = st_fixed_buffer_size; printk(KERN_WARNING "st: write_threshold limited to %d bytes.\n", st_write_threshold); } - if (max_buffers >= 0) - st_max_buffers = max_buffers; if (max_sg_segs >= ST_FIRST_SG) st_max_sg_segs = max_sg_segs; } @@ -3694,7 +3548,8 @@ static int st_attach(Scsi_Device * SDp) Scsi_Tape *tpnt; ST_mode *STm; ST_partstat *STps; - int i, mode, target_nbr, dev_num; + ST_buffer *buffer; + int i, mode, dev_num; char *stp; if (SDp->type != TYPE_TAPE) @@ -3707,6 +3562,12 @@ static int st_attach(Scsi_Device * SDp) return 1; } + buffer = new_tape_buffer(TRUE, (SDp->host)->unchecked_isa_dma); + if (buffer == NULL) { + printk(KERN_ERR "st: Can't allocate new tape buffer. Device not attached.\n"); + return 1; + } + write_lock(&st_dev_arr_lock); if (st_template.nr_dev >= st_template.dev_max) { Scsi_Tape **tmp_da; @@ -3745,14 +3606,6 @@ static int st_attach(Scsi_Device * SDp) } scsi_tapes = tmp_da; - memset(tmp_ba, 0, tmp_dev_max * sizeof(ST_buffer *)); - if (st_buffers != NULL) { - memcpy(tmp_ba, st_buffers, - st_template.dev_max * sizeof(ST_buffer *)); - kfree(st_buffers); - } - st_buffers = tmp_ba; - st_template.dev_max = tmp_dev_max; } @@ -3799,6 +3652,9 @@ static int st_attach(Scsi_Device * SDp) else tpnt->tape_type = MT_ISSCSI2; + buffer->use_sg = tpnt->device->host->sg_tablesize; + tpnt->buffer = buffer; + tpnt->inited = 0; tpnt->devt = mk_kdev(SCSI_TAPE_MAJOR, i); tpnt->dirty = 0; @@ -3858,18 +3714,6 @@ static int st_attach(Scsi_Device * SDp) "Attached scsi tape st%d at scsi%d, channel %d, id %d, lun %d\n", dev_num, SDp->host->host_no, SDp->channel, SDp->id, SDp->lun); - /* See if we need to allocate more static buffers */ - target_nbr = st_template.nr_dev; - if (target_nbr > st_max_buffers) - target_nbr = st_max_buffers; - for (i=st_nbr_buffers; i < target_nbr; i++) - if (!new_tape_buffer(TRUE, TRUE, FALSE)) { - printk(KERN_INFO "st: Unable to allocate new static buffer.\n"); - break; - } - /* If the previous allocation fails, we will try again when the buffer is - really needed. */ - return 0; }; @@ -3897,6 +3741,11 @@ static void st_detach(Scsi_Device * SDp) devfs_unregister (tpnt->de_n[mode]); tpnt->de_n[mode] = NULL; } + if (tpnt->buffer) { + tpnt->buffer->orig_sg_segs = 0; + normalize_buffer(tpnt->buffer); + kfree(tpnt->buffer); + } kfree(tpnt); scsi_tapes[i] = 0; SDp->attached--; @@ -3916,10 +3765,10 @@ static int __init init_st(void) validate_options(); printk(KERN_INFO - "st: Version %s, bufsize %d, wrt %d, " - "max init. bufs %d, s/g segs %d\n", - verstr, st_buffer_size, st_write_threshold, - st_max_buffers, st_max_sg_segs); + "st: Version %s, fixed bufsize %d, wrt %d, " + "s/g segs %d\n", + verstr, st_fixed_buffer_size, st_write_threshold, + st_max_sg_segs); if (devfs_register_chrdev(SCSI_TAPE_MAJOR, "st", &st_fops) >= 0) return scsi_register_device(&st_template); @@ -3939,16 +3788,6 @@ static void __exit exit_st(void) if (scsi_tapes[i]) kfree(scsi_tapes[i]); kfree(scsi_tapes); - if (st_buffers != NULL) { - for (i = 0; i < st_nbr_buffers; i++) { - if (st_buffers[i] != NULL) { - st_buffers[i]->orig_sg_segs = 0; - normalize_buffer(st_buffers[i]); - kfree(st_buffers[i]); - } - } - kfree(st_buffers); - } } st_template.dev_max = 0; printk(KERN_INFO "st: Unloaded.\n"); diff --git a/drivers/scsi/st_options.h b/drivers/scsi/st_options.h index 325bd3cb5c1e..2c412f72be13 100644 --- a/drivers/scsi/st_options.h +++ b/drivers/scsi/st_options.h @@ -3,7 +3,7 @@ Copyright 1995-2000 Kai Makisara. - Last modified: Tue Jan 22 21:52:34 2002 by makisara + Last modified: Sun May 5 15:09:56 2002 by makisara */ #ifndef _ST_OPTIONS_H @@ -30,22 +30,17 @@ SENSE. */ #define ST_DEFAULT_BLOCK 0 -/* The tape driver buffer size in kilobytes. Must be non-zero. */ -#define ST_BUFFER_BLOCKS 32 +/* The minimum tape driver buffer size in kilobytes in fixed block mode. + Must be non-zero. */ +#define ST_FIXED_BUFFER_BLOCKS 32 /* The number of kilobytes of data in the buffer that triggers an asynchronous write in fixed block mode. See also ST_ASYNC_WRITES below. */ #define ST_WRITE_THRESHOLD_BLOCKS 30 -/* The maximum number of tape buffers the driver tries to allocate at - driver initialisation. The number is also constrained by the number - of drives detected. If more buffers are needed, they are allocated - at run time and freed after use. */ -#define ST_MAX_BUFFERS 4 - /* Maximum number of scatter/gather segments */ -#define ST_MAX_SG 16 +#define ST_MAX_SG 64 /* The number of scatter/gather segments to allocate at first try (must be smaller or equal to the maximum). */ |
