patch-2.2.18 linux/drivers/scsi/st.c
Next file: linux/drivers/scsi/sun3x_esp.c
Previous file: linux/drivers/scsi/sr_ioctl.c
Back to the patch index
Back to the overall index
- Lines: 254
- Date:
Sat Nov 18 00:54:14 2000
- Orig file:
v2.2.17/drivers/scsi/st.c
- Orig date:
Sat Sep 9 18:42:41 2000
diff -u --new-file --recursive --exclude-from /usr/src/exclude v2.2.17/drivers/scsi/st.c linux/drivers/scsi/st.c
@@ -11,7 +11,7 @@
Copyright 1992 - 2000 Kai Makisara
email Kai.Makisara@metla.fi
- Last modified: Sat Jun 17 17:29:35 2000 by makisara@kai.makisara.local
+ Last modified: Tue Sep 5 23:17:08 2000 by makisara@kai.makisara.local
Some small formal changes - aeb, 950809
*/
@@ -957,7 +957,7 @@
((SCpnt->sense_buffer[0] & 0x80) != 0 &&
(SCpnt->sense_buffer[3] | SCpnt->sense_buffer[4] |
SCpnt->sense_buffer[5] |
- SCpnt->sense_buffer[6]) == 0))) {
+ SCpnt->sense_buffer[6]) != 0))) {
/* Filter out successful write at EOM */
scsi_release_command(SCpnt);
SCpnt = NULL;
@@ -1459,8 +1459,11 @@
if (SCpnt->sense_buffer[2] & 0x20) { /* ILI */
if (STp->block_size == 0) {
- if (transfer <= 0)
- transfer = 0;
+ if (transfer < 0) {
+ if (STps->drv_block >= 0)
+ STps->drv_block += 1;
+ return (-ENOMEM);
+ }
(STp->buffer)->buffer_bytes = bytes - transfer;
}
else {
@@ -2457,7 +2460,7 @@
STps->eof = ST_NOEOF;
}
else if ( (cmd_in == MTBSF) || (cmd_in == MTBSFM) ) {
- if (fileno >= 0)
+ if (STps->drv_file >= 0)
STps->drv_file = fileno + undone ;
else
STps->drv_file = fileno;
@@ -2485,7 +2488,7 @@
STps->drv_block = (-1);
}
else {
- if (blkno >= 0)
+ if (STps->drv_block >= 0)
STps->drv_block = blkno + undone;
else
STps->drv_block = (-1);
@@ -2932,6 +2935,8 @@
i = mtc.mt_op == MTREW || mtc.mt_op == MTOFFL ||
mtc.mt_op == MTRETEN || mtc.mt_op == MTEOM ||
mtc.mt_op == MTLOCK || mtc.mt_op == MTLOAD ||
+ mtc.mt_op == MTFSF || mtc.mt_op == MTFSFM ||
+ mtc.mt_op == MTBSF || mtc.mt_op == MTBSFM ||
mtc.mt_op == MTCOMPRESSION;
}
i = flush_buffer(inode, file, i);
@@ -3099,6 +3104,51 @@
}
+/* The following two functions are nearly identical to scsi_init_malloc and
+ scsi_init_free. The only difference is that the GFP_DMA flag is not set
+ by default. */
+static void * st_malloc(unsigned int size, int gfp_mask)
+{
+ void * retval;
+
+ /*
+ * For buffers used by the DMA pool, we assume page aligned
+ * structures.
+ */
+ if ((size % PAGE_SIZE) == 0) {
+ int order, a_size;
+ for (order = 0, a_size = PAGE_SIZE;
+ a_size < size; order++, a_size <<= 1)
+ ;
+ retval = (void *) __get_free_pages(gfp_mask, order);
+ } else
+ retval = kmalloc(size, gfp_mask);
+
+ if (retval)
+ memset(retval, 0, size);
+ return retval;
+}
+
+
+static void st_free(char * ptr, unsigned int size)
+{
+ /*
+ * We need this special code here because the DMA pool assumes
+ * page aligned data. Besides, it is wasteful to allocate
+ * page sized chunks with kmalloc.
+ */
+ if ((size % PAGE_SIZE) == 0) {
+ int order, a_size;
+
+ for (order = 0, a_size = PAGE_SIZE;
+ a_size < size; order++, a_size <<= 1)
+ ;
+ free_pages((unsigned long)ptr, order);
+ } else
+ kfree(ptr);
+}
+
+
/* Try to allocate a new tape buffer */
static ST_buffer *
new_tape_buffer( int from_initialization, int need_dma )
@@ -3115,7 +3165,7 @@
priority = GFP_KERNEL;
i = sizeof(ST_buffer) + (st_max_sg_segs - 1) * sizeof(struct scatterlist);
- tb = (ST_buffer *)scsi_init_malloc(i, priority);
+ tb = (ST_buffer *)st_malloc(i, priority);
if (tb) {
tb->this_size = i;
if (need_dma)
@@ -3128,7 +3178,7 @@
b_size /= 2;
for ( ; b_size >= PAGE_SIZE; b_size /= 2) {
tb->sg[0].address =
- (unsigned char *)scsi_init_malloc(b_size, priority);
+ (unsigned char *)st_malloc(b_size, priority);
if (tb->sg[0].address != NULL) {
tb->sg[0].alt_address = NULL;
tb->sg[0].length = b_size;
@@ -3136,7 +3186,7 @@
}
}
if (tb->sg[segs].address == NULL) {
- scsi_init_free((char *)tb, tb->this_size);
+ st_free((char *)tb, tb->this_size);
tb = NULL;
}
else { /* Got something, continue */
@@ -3148,7 +3198,7 @@
for (segs=1, got=tb->sg[0].length;
got < st_buffer_size && segs < ST_FIRST_SG; ) {
tb->sg[segs].address =
- (unsigned char *)scsi_init_malloc(b_size, priority);
+ (unsigned char *)st_malloc(b_size, priority);
if (tb->sg[segs].address == NULL) {
if (st_buffer_size - got <=
(ST_FIRST_SG - segs) * b_size / 2) {
@@ -3156,8 +3206,8 @@
continue;
}
for (i=0; i < segs - 1; i++)
- scsi_init_free(tb->sg[i].address, tb->sg[i].length);
- scsi_init_free((char *)tb, tb->this_size);
+ st_free(tb->sg[i].address, tb->sg[i].length);
+ st_free((char *)tb, tb->this_size);
tb = NULL;
break;
}
@@ -3220,7 +3270,7 @@
for (segs=STbuffer->sg_segs, got=STbuffer->buffer_size;
segs < max_segs && got < new_size; ) {
STbuffer->sg[segs].address =
- (unsigned char *)scsi_init_malloc(b_size, priority);
+ (unsigned char *)st_malloc(b_size, priority);
if (STbuffer->sg[segs].address == NULL) {
if (new_size - got <= (max_segs - segs) * b_size / 2) {
b_size /= 2; /* Large enough for the rest of the buffers */
@@ -3256,7 +3306,7 @@
int i;
for (i=STbuffer->orig_sg_segs; i < STbuffer->sg_segs; i++) {
- scsi_init_free(STbuffer->sg[i].address, STbuffer->sg[i].length);
+ st_free(STbuffer->sg[i].address, STbuffer->sg[i].length);
STbuffer->buffer_size -= STbuffer->sg[i].length;
}
#if DEBUG
@@ -3489,7 +3539,7 @@
if (st_template.dev_max > 128 / ST_NBR_MODES)
printk(KERN_INFO "st: Only %d tapes accessible.\n", 128 / ST_NBR_MODES);
scsi_tapes =
- (Scsi_Tape *) scsi_init_malloc(st_template.dev_max * sizeof(Scsi_Tape),
+ (Scsi_Tape *) st_malloc(st_template.dev_max * sizeof(Scsi_Tape),
GFP_ATOMIC);
if (scsi_tapes == NULL) {
printk(KERN_ERR "Unable to allocate descriptors for SCSI tapes.\n");
@@ -3506,7 +3556,7 @@
for (i=0; i < st_template.dev_max; ++i) {
STp = &(scsi_tapes[i]);
STp->capacity = 0xfffff;
- STp->mt_status = (struct mtget *) scsi_init_malloc(sizeof(struct mtget),
+ STp->mt_status = (struct mtget *) st_malloc(sizeof(struct mtget),
GFP_ATOMIC);
/* Initialize status */
memset((void *) scsi_tapes[i].mt_status, 0, sizeof(struct mtget));
@@ -3514,12 +3564,12 @@
/* Allocate the buffers */
st_buffers =
- (ST_buffer **) scsi_init_malloc(st_template.dev_max * sizeof(ST_buffer *),
+ (ST_buffer **) st_malloc(st_template.dev_max * sizeof(ST_buffer *),
GFP_ATOMIC);
if (st_buffers == NULL) {
printk(KERN_ERR "Unable to allocate tape buffer pointers.\n");
unregister_chrdev(SCSI_TAPE_MAJOR, "st");
- scsi_init_free((char *) scsi_tapes,
+ st_free((char *) scsi_tapes,
st_template.dev_max * sizeof(Scsi_Tape));
return 1;
}
@@ -3532,6 +3582,8 @@
target_nbr = ST_EXTRA_DEVS;
if (target_nbr > st_max_buffers)
target_nbr = st_max_buffers;
+ if (target_nbr > st_template.dev_noticed)
+ target_nbr = st_template.dev_noticed;
for (i=st_nbr_buffers=0; i < target_nbr; i++) {
if (!new_tape_buffer(TRUE, TRUE)) {
@@ -3539,9 +3591,9 @@
#if 0
printk(KERN_ERR "Can't continue without at least one tape buffer.\n");
unregister_chrdev(SCSI_TAPE_MAJOR, "st");
- scsi_init_free((char *) st_buffers,
+ st_free((char *) st_buffers,
st_template.dev_max * sizeof(ST_buffer *));
- scsi_init_free((char *) scsi_tapes,
+ st_free((char *) scsi_tapes,
st_template.dev_max * sizeof(Scsi_Tape));
return 1;
#else
@@ -3608,19 +3660,19 @@
unregister_chrdev(SCSI_TAPE_MAJOR, "st");
st_registered--;
if(scsi_tapes != NULL) {
- scsi_init_free((char *) scsi_tapes,
+ st_free((char *) scsi_tapes,
st_template.dev_max * sizeof(Scsi_Tape));
if (st_buffers != NULL) {
for (i=0; i < st_nbr_buffers; i++)
if (st_buffers[i] != NULL) {
for (j=0; j < st_buffers[i]->sg_segs; j++)
- scsi_init_free((char *) st_buffers[i]->sg[j].address,
+ st_free((char *) st_buffers[i]->sg[j].address,
st_buffers[i]->sg[j].length);
- scsi_init_free((char *) st_buffers[i], st_buffers[i]->this_size);
+ st_free((char *) st_buffers[i], st_buffers[i]->this_size);
}
- scsi_init_free((char *) st_buffers,
+ st_free((char *) st_buffers,
st_template.dev_max * sizeof(ST_buffer *));
}
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)