aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorKai Makisara <Kai.Makisara@kolumbus.fi>2008-02-24 15:23:24 -0500
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-04-07 13:15:39 -0400
commit40f6b36c6243462fb95d0343237331c423494b03 (patch)
tree456b78c5647684527e0104463dd45b8e93ea9d81 /drivers/scsi
parentd35055a0f2637f29f95001a67b464fe833b09ebc (diff)
[SCSI] st: add option to use SILI in variable block reads
Add new option MT_ST_SILI to enable setting the SILI bit in reads in variable block mode. If SILI is set, reading a block shorter than the byte count does not result in CHECK CONDITION. The length of the block is determined using the residual count from the HBA. Avoiding the REQUEST SENSE command for every block speeds up some real applications considerably. Signed-off-by: Kai Makisara <kai.makisara@kolumbus.fi> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/st.c40
-rw-r--r--drivers/scsi/st.h3
-rw-r--r--drivers/scsi/st_options.h6
3 files changed, 44 insertions, 5 deletions
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 0a52d9d2da2c..a4361a8c6ac6 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -17,7 +17,7 @@
17 Last modified: 18-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support 17 Last modified: 18-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support
18 */ 18 */
19 19
20static const char *verstr = "20080221"; 20static const char *verstr = "20080224";
21 21
22#include <linux/module.h> 22#include <linux/module.h>
23 23
@@ -183,6 +183,7 @@ static int modes_defined;
183 183
184static struct st_buffer *new_tape_buffer(int, int, int); 184static struct st_buffer *new_tape_buffer(int, int, int);
185static int enlarge_buffer(struct st_buffer *, int, int); 185static int enlarge_buffer(struct st_buffer *, int, int);
186static void clear_buffer(struct st_buffer *);
186static void normalize_buffer(struct st_buffer *); 187static void normalize_buffer(struct st_buffer *);
187static int append_to_buffer(const char __user *, struct st_buffer *, int); 188static int append_to_buffer(const char __user *, struct st_buffer *, int);
188static int from_buffer(struct st_buffer *, char __user *, int); 189static int from_buffer(struct st_buffer *, char __user *, int);
@@ -442,6 +443,7 @@ static void st_sleep_done(void *data, char *sense, int result, int resid)
442 443
443 memcpy(SRpnt->sense, sense, SCSI_SENSE_BUFFERSIZE); 444 memcpy(SRpnt->sense, sense, SCSI_SENSE_BUFFERSIZE);
444 (STp->buffer)->cmdstat.midlevel_result = SRpnt->result = result; 445 (STp->buffer)->cmdstat.midlevel_result = SRpnt->result = result;
446 (STp->buffer)->cmdstat.residual = resid;
445 DEB( STp->write_pending = 0; ) 447 DEB( STp->write_pending = 0; )
446 448
447 if (SRpnt->waiting) 449 if (SRpnt->waiting)
@@ -1159,6 +1161,7 @@ static int st_open(struct inode *inode, struct file *filp)
1159 goto err_out; 1161 goto err_out;
1160 } 1162 }
1161 1163
1164 (STp->buffer)->cleared = 0;
1162 (STp->buffer)->writing = 0; 1165 (STp->buffer)->writing = 0;
1163 (STp->buffer)->syscall_result = 0; 1166 (STp->buffer)->syscall_result = 0;
1164 1167
@@ -1432,8 +1435,14 @@ static int setup_buffering(struct scsi_tape *STp, const char __user *buf,
1432 if (STp->block_size) 1435 if (STp->block_size)
1433 bufsize = STp->block_size > st_fixed_buffer_size ? 1436 bufsize = STp->block_size > st_fixed_buffer_size ?
1434 STp->block_size : st_fixed_buffer_size; 1437 STp->block_size : st_fixed_buffer_size;
1435 else 1438 else {
1436 bufsize = count; 1439 bufsize = count;
1440 /* Make sure that data from previous user is not leaked even if
1441 HBA does not return correct residual */
1442 if (is_read && STp->sili && !STbp->cleared)
1443 clear_buffer(STbp);
1444 }
1445
1437 if (bufsize > STbp->buffer_size && 1446 if (bufsize > STbp->buffer_size &&
1438 !enlarge_buffer(STbp, bufsize, STp->restr_dma)) { 1447 !enlarge_buffer(STbp, bufsize, STp->restr_dma)) {
1439 printk(KERN_WARNING "%s: Can't allocate %d byte tape buffer.\n", 1448 printk(KERN_WARNING "%s: Can't allocate %d byte tape buffer.\n",
@@ -1783,6 +1792,8 @@ static long read_tape(struct scsi_tape *STp, long count,
1783 memset(cmd, 0, MAX_COMMAND_SIZE); 1792 memset(cmd, 0, MAX_COMMAND_SIZE);
1784 cmd[0] = READ_6; 1793 cmd[0] = READ_6;
1785 cmd[1] = (STp->block_size != 0); 1794 cmd[1] = (STp->block_size != 0);
1795 if (!cmd[1] && STp->sili)
1796 cmd[1] |= 2;
1786 cmd[2] = blks >> 16; 1797 cmd[2] = blks >> 16;
1787 cmd[3] = blks >> 8; 1798 cmd[3] = blks >> 8;
1788 cmd[4] = blks; 1799 cmd[4] = blks;
@@ -1911,8 +1922,11 @@ static long read_tape(struct scsi_tape *STp, long count,
1911 1922
1912 } 1923 }
1913 /* End of error handling */ 1924 /* End of error handling */
1914 else /* Read successful */ 1925 else { /* Read successful */
1915 STbp->buffer_bytes = bytes; 1926 STbp->buffer_bytes = bytes;
1927 if (STp->sili) /* In fixed block mode residual is always zero here */
1928 STbp->buffer_bytes -= STp->buffer->cmdstat.residual;
1929 }
1916 1930
1917 if (STps->drv_block >= 0) { 1931 if (STps->drv_block >= 0) {
1918 if (STp->block_size == 0) 1932 if (STp->block_size == 0)
@@ -2090,7 +2104,8 @@ static void st_log_options(struct scsi_tape * STp, struct st_modedef * STm, char
2090 name, STm->defaults_for_writes, STp->omit_blklims, STp->can_partitions, 2104 name, STm->defaults_for_writes, STp->omit_blklims, STp->can_partitions,
2091 STp->scsi2_logical); 2105 STp->scsi2_logical);
2092 printk(KERN_INFO 2106 printk(KERN_INFO
2093 "%s: sysv: %d nowait: %d\n", name, STm->sysv, STp->immediate); 2107 "%s: sysv: %d nowait: %d sili: %d\n", name, STm->sysv, STp->immediate,
2108 STp->sili);
2094 printk(KERN_INFO "%s: debugging: %d\n", 2109 printk(KERN_INFO "%s: debugging: %d\n",
2095 name, debugging); 2110 name, debugging);
2096 } 2111 }
@@ -2133,6 +2148,7 @@ static int st_set_options(struct scsi_tape *STp, long options)
2133 STp->scsi2_logical = (options & MT_ST_SCSI2LOGICAL) != 0; 2148 STp->scsi2_logical = (options & MT_ST_SCSI2LOGICAL) != 0;
2134 STp->immediate = (options & MT_ST_NOWAIT) != 0; 2149 STp->immediate = (options & MT_ST_NOWAIT) != 0;
2135 STm->sysv = (options & MT_ST_SYSV) != 0; 2150 STm->sysv = (options & MT_ST_SYSV) != 0;
2151 STp->sili = (options & MT_ST_SILI) != 0;
2136 DEB( debugging = (options & MT_ST_DEBUGGING) != 0; 2152 DEB( debugging = (options & MT_ST_DEBUGGING) != 0;
2137 st_log_options(STp, STm, name); ) 2153 st_log_options(STp, STm, name); )
2138 } else if (code == MT_ST_SETBOOLEANS || code == MT_ST_CLEARBOOLEANS) { 2154 } else if (code == MT_ST_SETBOOLEANS || code == MT_ST_CLEARBOOLEANS) {
@@ -2164,6 +2180,8 @@ static int st_set_options(struct scsi_tape *STp, long options)
2164 STp->immediate = value; 2180 STp->immediate = value;
2165 if ((options & MT_ST_SYSV) != 0) 2181 if ((options & MT_ST_SYSV) != 0)
2166 STm->sysv = value; 2182 STm->sysv = value;
2183 if ((options & MT_ST_SILI) != 0)
2184 STp->sili = value;
2167 DEB( 2185 DEB(
2168 if ((options & MT_ST_DEBUGGING) != 0) 2186 if ((options & MT_ST_DEBUGGING) != 0)
2169 debugging = value; 2187 debugging = value;
@@ -3655,6 +3673,8 @@ static int enlarge_buffer(struct st_buffer * STbuffer, int new_size, int need_dm
3655 STbuffer->frp_segs += 1; 3673 STbuffer->frp_segs += 1;
3656 got += b_size; 3674 got += b_size;
3657 STbuffer->buffer_size = got; 3675 STbuffer->buffer_size = got;
3676 if (STbuffer->cleared)
3677 memset(page_address(STbuffer->frp[segs].page), 0, b_size);
3658 segs++; 3678 segs++;
3659 } 3679 }
3660 STbuffer->b_data = page_address(STbuffer->frp[0].page); 3680 STbuffer->b_data = page_address(STbuffer->frp[0].page);
@@ -3663,6 +3683,17 @@ static int enlarge_buffer(struct st_buffer * STbuffer, int new_size, int need_dm
3663} 3683}
3664 3684
3665 3685
3686/* Make sure that no data from previous user is in the internal buffer */
3687static void clear_buffer(struct st_buffer * st_bp)
3688{
3689 int i;
3690
3691 for (i=0; i < st_bp->frp_segs; i++)
3692 memset(page_address(st_bp->frp[i].page), 0, st_bp->frp[i].length);
3693 st_bp->cleared = 1;
3694}
3695
3696
3666/* Release the extra buffer */ 3697/* Release the extra buffer */
3667static void normalize_buffer(struct st_buffer * STbuffer) 3698static void normalize_buffer(struct st_buffer * STbuffer)
3668{ 3699{
@@ -3987,6 +4018,7 @@ static int st_probe(struct device *dev)
3987 tpnt->two_fm = ST_TWO_FM; 4018 tpnt->two_fm = ST_TWO_FM;
3988 tpnt->fast_mteom = ST_FAST_MTEOM; 4019 tpnt->fast_mteom = ST_FAST_MTEOM;
3989 tpnt->scsi2_logical = ST_SCSI2LOGICAL; 4020 tpnt->scsi2_logical = ST_SCSI2LOGICAL;
4021 tpnt->sili = ST_SILI;
3990 tpnt->immediate = ST_NOWAIT; 4022 tpnt->immediate = ST_NOWAIT;
3991 tpnt->default_drvbuffer = 0xff; /* No forced buffering */ 4023 tpnt->default_drvbuffer = 0xff; /* No forced buffering */
3992 tpnt->partition = 0; 4024 tpnt->partition = 0;
diff --git a/drivers/scsi/st.h b/drivers/scsi/st.h
index 5931726fcf93..b92712f95931 100644
--- a/drivers/scsi/st.h
+++ b/drivers/scsi/st.h
@@ -12,6 +12,7 @@ struct st_cmdstatus {
12 int midlevel_result; 12 int midlevel_result;
13 struct scsi_sense_hdr sense_hdr; 13 struct scsi_sense_hdr sense_hdr;
14 int have_sense; 14 int have_sense;
15 int residual;
15 u64 uremainder64; 16 u64 uremainder64;
16 u8 flags; 17 u8 flags;
17 u8 remainder_valid; 18 u8 remainder_valid;
@@ -34,6 +35,7 @@ struct st_request {
34struct st_buffer { 35struct st_buffer {
35 unsigned char dma; /* DMA-able buffer */ 36 unsigned char dma; /* DMA-able buffer */
36 unsigned char do_dio; /* direct i/o set up? */ 37 unsigned char do_dio; /* direct i/o set up? */
38 unsigned char cleared; /* internal buffer cleared after open? */
37 int buffer_size; 39 int buffer_size;
38 int buffer_blocks; 40 int buffer_blocks;
39 int buffer_bytes; 41 int buffer_bytes;
@@ -122,6 +124,7 @@ struct scsi_tape {
122 unsigned char try_dio_now; /* try direct i/o before next close? */ 124 unsigned char try_dio_now; /* try direct i/o before next close? */
123 unsigned char c_algo; /* compression algorithm */ 125 unsigned char c_algo; /* compression algorithm */
124 unsigned char pos_unknown; /* after reset position unknown */ 126 unsigned char pos_unknown; /* after reset position unknown */
127 unsigned char sili; /* use SILI when reading in variable b mode */
125 int tape_type; 128 int tape_type;
126 int long_timeout; /* timeout for commands known to take long time */ 129 int long_timeout; /* timeout for commands known to take long time */
127 130
diff --git a/drivers/scsi/st_options.h b/drivers/scsi/st_options.h
index b6b5c9c37677..d2f947935554 100644
--- a/drivers/scsi/st_options.h
+++ b/drivers/scsi/st_options.h
@@ -3,7 +3,7 @@
3 3
4 Copyright 1995-2003 Kai Makisara. 4 Copyright 1995-2003 Kai Makisara.
5 5
6 Last modified: Mon Apr 7 22:49:18 2003 by makisara 6 Last modified: Thu Feb 21 21:47:07 2008 by kai.makisara
7*/ 7*/
8 8
9#ifndef _ST_OPTIONS_H 9#ifndef _ST_OPTIONS_H
@@ -94,6 +94,10 @@
94 The default is BSD semantics. */ 94 The default is BSD semantics. */
95#define ST_SYSV 0 95#define ST_SYSV 0
96 96
97/* If ST_SILI is non-zero, the SILI bit is set when reading in variable block
98 mode and the block size is determined using the residual returned by the HBA. */
99#define ST_SILI 0
100
97/* Time to wait for the drive to become ready if blocking open */ 101/* Time to wait for the drive to become ready if blocking open */
98#define ST_BLOCK_SECONDS 120 102#define ST_BLOCK_SECONDS 120
99 103