Commit 65c26a0f authored by Douglas Gilbert's avatar Douglas Gilbert Committed by Christoph Hellwig

sg: relax 16 byte cdb restriction

 - remove the 16 byte CDB (SCSI command) length limit from the sg driver
   by handling longer CDBs the same way as the bsg driver. Remove comment
   from sg.h public interface about the cmd_len field being limited to 16
   bytes.
 - remove some dead code caused by this change
 - cleanup comment block at the top of sg.h, fix urls
Signed-off-by: default avatarDouglas Gilbert <dgilbert@interlog.com>
Reviewed-by: default avatarMike Christie <michaelc@cs.wisc.edu>
Reviewed-by: default avatarHannes Reinecke <hare@suse.de>
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
parent bcdb247c
...@@ -7,9 +7,7 @@ ...@@ -7,9 +7,7 @@
* Original driver (sg.c): * Original driver (sg.c):
* Copyright (C) 1992 Lawrence Foard * Copyright (C) 1992 Lawrence Foard
* Version 2 and 3 extensions to driver: * Version 2 and 3 extensions to driver:
* Copyright (C) 1998 - 2005 Douglas Gilbert * Copyright (C) 1998 - 2014 Douglas Gilbert
*
* Modified 19-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
...@@ -18,11 +16,11 @@ ...@@ -18,11 +16,11 @@
* *
*/ */
static int sg_version_num = 30534; /* 2 digits for each component */ static int sg_version_num = 30536; /* 2 digits for each component */
#define SG_VERSION_STR "3.5.34" #define SG_VERSION_STR "3.5.36"
/* /*
* D. P. Gilbert (dgilbert@interlog.com, dougg@triode.net.au), notes: * D. P. Gilbert (dgilbert@interlog.com), notes:
* - scsi logging is available via SCSI_LOG_TIMEOUT macros. First * - scsi logging is available via SCSI_LOG_TIMEOUT macros. First
* the kernel/module needs to be built with CONFIG_SCSI_LOGGING * the kernel/module needs to be built with CONFIG_SCSI_LOGGING
* (otherwise the macros compile to empty statements). * (otherwise the macros compile to empty statements).
...@@ -64,7 +62,7 @@ static int sg_version_num = 30534; /* 2 digits for each component */ ...@@ -64,7 +62,7 @@ static int sg_version_num = 30534; /* 2 digits for each component */
#ifdef CONFIG_SCSI_PROC_FS #ifdef CONFIG_SCSI_PROC_FS
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
static char *sg_version_date = "20061027"; static char *sg_version_date = "20140603";
static int sg_proc_init(void); static int sg_proc_init(void);
static void sg_proc_cleanup(void); static void sg_proc_cleanup(void);
...@@ -74,6 +72,12 @@ static void sg_proc_cleanup(void); ...@@ -74,6 +72,12 @@ static void sg_proc_cleanup(void);
#define SG_MAX_DEVS 32768 #define SG_MAX_DEVS 32768
/* SG_MAX_CDB_SIZE should be 260 (spc4r37 section 3.1.30) however the type
* of sg_io_hdr::cmd_len can only represent 255. All SCSI commands greater
* than 16 bytes are "variable length" whose length is a multiple of 4
*/
#define SG_MAX_CDB_SIZE 252
/* /*
* Suppose you want to calculate the formula muldiv(x,m,d)=int(x * m / d) * Suppose you want to calculate the formula muldiv(x,m,d)=int(x * m / d)
* Then when using 32 bit integers x * m may overflow during the calculation. * Then when using 32 bit integers x * m may overflow during the calculation.
...@@ -161,7 +165,7 @@ typedef struct sg_fd { /* holds the state of a file descriptor */ ...@@ -161,7 +165,7 @@ typedef struct sg_fd { /* holds the state of a file descriptor */
char low_dma; /* as in parent but possibly overridden to 1 */ char low_dma; /* as in parent but possibly overridden to 1 */
char force_packid; /* 1 -> pack_id input to read(), 0 -> ignored */ char force_packid; /* 1 -> pack_id input to read(), 0 -> ignored */
char cmd_q; /* 1 -> allow command queuing, 0 -> don't */ char cmd_q; /* 1 -> allow command queuing, 0 -> don't */
char next_cmd_len; /* 0 -> automatic (def), >0 -> use on next write() */ unsigned char next_cmd_len; /* 0: automatic, >0: use on next write() */
char keep_orphan; /* 0 -> drop orphan (def), 1 -> keep for read() */ char keep_orphan; /* 0 -> drop orphan (def), 1 -> keep for read() */
char mmap_called; /* 0 -> mmap() never called on this fd */ char mmap_called; /* 0 -> mmap() never called on this fd */
struct kref f_ref; struct kref f_ref;
...@@ -566,7 +570,7 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) ...@@ -566,7 +570,7 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
Sg_request *srp; Sg_request *srp;
struct sg_header old_hdr; struct sg_header old_hdr;
sg_io_hdr_t *hp; sg_io_hdr_t *hp;
unsigned char cmnd[MAX_COMMAND_SIZE]; unsigned char cmnd[SG_MAX_CDB_SIZE];
if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp))) if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp)))
return -ENXIO; return -ENXIO;
...@@ -598,12 +602,6 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) ...@@ -598,12 +602,6 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
buf += SZ_SG_HEADER; buf += SZ_SG_HEADER;
__get_user(opcode, buf); __get_user(opcode, buf);
if (sfp->next_cmd_len > 0) { if (sfp->next_cmd_len > 0) {
if (sfp->next_cmd_len > MAX_COMMAND_SIZE) {
SCSI_LOG_TIMEOUT(1, printk("sg_write: command length too long\n"));
sfp->next_cmd_len = 0;
sg_remove_request(sfp, srp);
return -EIO;
}
cmd_size = sfp->next_cmd_len; cmd_size = sfp->next_cmd_len;
sfp->next_cmd_len = 0; /* reset so only this write() effected */ sfp->next_cmd_len = 0; /* reset so only this write() effected */
} else { } else {
...@@ -675,7 +673,7 @@ sg_new_write(Sg_fd *sfp, struct file *file, const char __user *buf, ...@@ -675,7 +673,7 @@ sg_new_write(Sg_fd *sfp, struct file *file, const char __user *buf,
int k; int k;
Sg_request *srp; Sg_request *srp;
sg_io_hdr_t *hp; sg_io_hdr_t *hp;
unsigned char cmnd[MAX_COMMAND_SIZE]; unsigned char cmnd[SG_MAX_CDB_SIZE];
int timeout; int timeout;
unsigned long ul_timeout; unsigned long ul_timeout;
...@@ -1654,15 +1652,27 @@ static int sg_start_req(Sg_request *srp, unsigned char *cmd) ...@@ -1654,15 +1652,27 @@ static int sg_start_req(Sg_request *srp, unsigned char *cmd)
struct request_queue *q = sfp->parentdp->device->request_queue; struct request_queue *q = sfp->parentdp->device->request_queue;
struct rq_map_data *md, map_data; struct rq_map_data *md, map_data;
int rw = hp->dxfer_direction == SG_DXFER_TO_DEV ? WRITE : READ; int rw = hp->dxfer_direction == SG_DXFER_TO_DEV ? WRITE : READ;
unsigned char *long_cmdp = NULL;
SCSI_LOG_TIMEOUT(4, printk(KERN_INFO "sg_start_req: dxfer_len=%d\n", SCSI_LOG_TIMEOUT(4, printk(KERN_INFO "sg_start_req: dxfer_len=%d\n",
dxfer_len)); dxfer_len));
if (hp->cmd_len > BLK_MAX_CDB) {
long_cmdp = kzalloc(hp->cmd_len, GFP_KERNEL);
if (!long_cmdp)
return -ENOMEM;
}
rq = blk_get_request(q, rw, GFP_ATOMIC); rq = blk_get_request(q, rw, GFP_ATOMIC);
if (!rq) if (!rq) {
kfree(long_cmdp);
return -ENOMEM; return -ENOMEM;
}
blk_rq_set_block_pc(rq); blk_rq_set_block_pc(rq);
if (hp->cmd_len > BLK_MAX_CDB)
rq->cmd = long_cmdp;
memcpy(rq->cmd, cmd, hp->cmd_len); memcpy(rq->cmd, cmd, hp->cmd_len);
rq->cmd_len = hp->cmd_len; rq->cmd_len = hp->cmd_len;
...@@ -1747,6 +1757,8 @@ static int sg_finish_rem_req(Sg_request * srp) ...@@ -1747,6 +1757,8 @@ static int sg_finish_rem_req(Sg_request * srp)
if (srp->bio) if (srp->bio)
ret = blk_rq_unmap_user(srp->bio); ret = blk_rq_unmap_user(srp->bio);
if (srp->rq->cmd != srp->rq->__cmd)
kfree(srp->rq->cmd);
blk_put_request(srp->rq); blk_put_request(srp->rq);
} }
......
...@@ -4,77 +4,34 @@ ...@@ -4,77 +4,34 @@
#include <linux/compiler.h> #include <linux/compiler.h>
/* /*
History: * History:
Started: Aug 9 by Lawrence Foard (entropy@world.std.com), to allow user * Started: Aug 9 by Lawrence Foard (entropy@world.std.com), to allow user
process control of SCSI devices. * process control of SCSI devices.
Development Sponsored by Killy Corp. NY NY * Development Sponsored by Killy Corp. NY NY
Original driver (sg.h): *
* Copyright (C) 1992 Lawrence Foard * Original driver (sg.h):
Version 2 and 3 extensions to driver: * Copyright (C) 1992 Lawrence Foard
* Copyright (C) 1998 - 2006 Douglas Gilbert * Version 2 and 3 extensions to driver:
* Copyright (C) 1998 - 2014 Douglas Gilbert
Version: 3.5.34 (20060920) *
This version is for 2.6 series kernels. * Version: 3.5.36 (20140603)
* This version is for 2.6 and 3 series kernels.
For a full changelog see http://www.torque.net/sg *
* Documentation
Map of SG verions to the Linux kernels in which they appear: * =============
---------- ---------------------------------- * A web site for the SG device driver can be found at:
original all kernels < 2.2.6 * http://sg.danny.cz/sg [alternatively check the MAINTAINERS file]
2.1.40 2.2.20 * The documentation for the sg version 3 driver can be found at:
3.0.x optional version 3 sg driver for 2.2 series * http://sg.danny.cz/sg/p/sg_v3_ho.html
3.1.17++ 2.4.0++ * Also see: <kernel_source>/Documentation/scsi/scsi-generic.txt
3.5.30++ 2.6.0++ *
* For utility and test programs see: http://sg.danny.cz/sg/sg3_utils.html
Major new features in SG 3.x driver (cf SG 2.x drivers) */
- SG_IO ioctl() combines function if write() and read()
- new interface (sg_io_hdr_t) but still supports old interface
- scatter/gather in user space, direct IO, and mmap supported
The normal action of this driver is to use the adapter (HBA) driver to DMA
data into kernel buffers and then use the CPU to copy the data into the
user space (vice versa for writes). That is called "indirect" IO due to
the double handling of data. There are two methods offered to remove the
redundant copy: 1) direct IO and 2) using the mmap() system call to map
the reserve buffer (this driver has one reserve buffer per fd) into the
user space. Both have their advantages.
In terms of absolute speed mmap() is faster. If speed is not a concern,
indirect IO should be fine. Read the documentation for more information.
** N.B. To use direct IO 'echo 1 > /proc/scsi/sg/allow_dio' or
'echo 1 > /sys/module/sg/parameters/allow_dio' is needed.
That attribute is 0 by default. **
Historical note: this SCSI pass-through driver has been known as "sg" for
a decade. In broader kernel discussions "sg" is used to refer to scatter
gather techniques. The context should clarify which "sg" is referred to.
Documentation
=============
A web site for the SG device driver can be found at:
http://www.torque.net/sg [alternatively check the MAINTAINERS file]
The documentation for the sg version 3 driver can be found at:
http://www.torque.net/sg/p/sg_v3_ho.html
This is a rendering from DocBook source [change the extension to "sgml"
or "xml"]. There are renderings in "ps", "pdf", "rtf" and "txt" (soon).
The SG_IO ioctl is now found in other parts kernel (e.g. the block layer).
For more information see http://www.torque.net/sg/sg_io.html
The older, version 2 documents discuss the original sg interface in detail:
http://www.torque.net/sg/p/scsi-generic.txt
http://www.torque.net/sg/p/scsi-generic_long.txt
Also available: <kernel_source>/Documentation/scsi/scsi-generic.txt
Utility and test programs are available at the sg web site. They are
packaged as sg3_utils (for the lk 2.4 and 2.6 series) and sg_utils
(for the lk 2.2 series).
*/
#ifdef __KERNEL__ #ifdef __KERNEL__
extern int sg_big_buff; /* for sysctl */ extern int sg_big_buff; /* for sysctl */
#endif #endif
/* New interface introduced in the 3.x SG drivers follows */
typedef struct sg_iovec /* same structure as used by readv() Linux system */ typedef struct sg_iovec /* same structure as used by readv() Linux system */
{ /* call. It defines one scatter-gather element. */ { /* call. It defines one scatter-gather element. */
...@@ -87,7 +44,7 @@ typedef struct sg_io_hdr ...@@ -87,7 +44,7 @@ typedef struct sg_io_hdr
{ {
int interface_id; /* [i] 'S' for SCSI generic (required) */ int interface_id; /* [i] 'S' for SCSI generic (required) */
int dxfer_direction; /* [i] data transfer direction */ int dxfer_direction; /* [i] data transfer direction */
unsigned char cmd_len; /* [i] SCSI command length ( <= 16 bytes) */ unsigned char cmd_len; /* [i] SCSI command length */
unsigned char mx_sb_len; /* [i] max length to write to sbp */ unsigned char mx_sb_len; /* [i] max length to write to sbp */
unsigned short iovec_count; /* [i] 0 implies no scatter gather */ unsigned short iovec_count; /* [i] 0 implies no scatter gather */
unsigned int dxfer_len; /* [i] byte count of data transfer */ unsigned int dxfer_len; /* [i] byte count of data transfer */
......
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