diff options
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/st.c | 40 | ||||
-rw-r--r-- | drivers/scsi/st.h | 3 | ||||
-rw-r--r-- | drivers/scsi/st_options.h | 6 |
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 | ||
20 | static const char *verstr = "20080221"; | 20 | static 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 | ||
184 | static struct st_buffer *new_tape_buffer(int, int, int); | 184 | static struct st_buffer *new_tape_buffer(int, int, int); |
185 | static int enlarge_buffer(struct st_buffer *, int, int); | 185 | static int enlarge_buffer(struct st_buffer *, int, int); |
186 | static void clear_buffer(struct st_buffer *); | ||
186 | static void normalize_buffer(struct st_buffer *); | 187 | static void normalize_buffer(struct st_buffer *); |
187 | static int append_to_buffer(const char __user *, struct st_buffer *, int); | 188 | static int append_to_buffer(const char __user *, struct st_buffer *, int); |
188 | static int from_buffer(struct st_buffer *, char __user *, int); | 189 | static 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 */ | ||
3687 | static 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 */ |
3667 | static void normalize_buffer(struct st_buffer * STbuffer) | 3698 | static 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 { | |||
34 | struct st_buffer { | 35 | struct 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 | ||