mirror of
https://github.com/Divested-Mobile/DivestOS-Build.git
synced 2024-12-12 01:14:22 -05:00
264 lines
9.6 KiB
Diff
264 lines
9.6 KiB
Diff
|
From 2c5b488b49d92c02ac28f45e68f366c6a51a8949 Mon Sep 17 00:00:00 2001
|
||
|
From: Douglas Gilbert <dgilbert@interlog.com>
|
||
|
Date: Tue, 03 Jun 2014 13:18:18 -0400
|
||
|
Subject: [PATCH] BACKPORT: 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
|
||
|
|
||
|
Change-Id: Ie8150e5375b3316d5d5206f079c4a50f1c50b755
|
||
|
Signed-off-by: Douglas Gilbert <dgilbert@interlog.com>
|
||
|
Reviewed-by: Mike Christie <michaelc@cs.wisc.edu>
|
||
|
Reviewed-by: Hannes Reinecke <hare@suse.de>
|
||
|
Signed-off-by: Christoph Hellwig <hch@lst.de>
|
||
|
---
|
||
|
|
||
|
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
|
||
|
index 5170506..96d635e 100644
|
||
|
--- a/drivers/scsi/sg.c
|
||
|
+++ b/drivers/scsi/sg.c
|
||
|
@@ -7,9 +7,7 @@
|
||
|
* Original driver (sg.c):
|
||
|
* Copyright (C) 1992 Lawrence Foard
|
||
|
* Version 2 and 3 extensions to driver:
|
||
|
- * Copyright (C) 1998 - 2005 Douglas Gilbert
|
||
|
- *
|
||
|
- * Modified 19-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support
|
||
|
+ * Copyright (C) 1998 - 2014 Douglas Gilbert
|
||
|
*
|
||
|
* 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
|
||
|
@@ -18,11 +16,11 @@
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
-static int sg_version_num = 30534; /* 2 digits for each component */
|
||
|
-#define SG_VERSION_STR "3.5.34"
|
||
|
+static int sg_version_num = 30536; /* 2 digits for each component */
|
||
|
+#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
|
||
|
* the kernel/module needs to be built with CONFIG_SCSI_LOGGING
|
||
|
* (otherwise the macros compile to empty statements).
|
||
|
@@ -64,7 +62,7 @@
|
||
|
|
||
|
#ifdef CONFIG_SCSI_PROC_FS
|
||
|
#include <linux/proc_fs.h>
|
||
|
-static char *sg_version_date = "20061027";
|
||
|
+static char *sg_version_date = "20140603";
|
||
|
|
||
|
static int sg_proc_init(void);
|
||
|
static void sg_proc_cleanup(void);
|
||
|
@@ -73,6 +71,12 @@
|
||
|
#define SG_ALLOW_DIO_DEF 0
|
||
|
|
||
|
#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)
|
||
|
@@ -161,7 +165,7 @@
|
||
|
char low_dma; /* as in parent but possibly overridden to 1 */
|
||
|
char force_packid; /* 1 -> pack_id input to read(), 0 -> ignored */
|
||
|
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 mmap_called; /* 0 -> mmap() never called on this fd */
|
||
|
struct kref f_ref;
|
||
|
@@ -566,7 +570,7 @@
|
||
|
Sg_request *srp;
|
||
|
struct sg_header old_hdr;
|
||
|
sg_io_hdr_t *hp;
|
||
|
- unsigned char cmnd[MAX_COMMAND_SIZE];
|
||
|
+ unsigned char cmnd[SG_MAX_CDB_SIZE];
|
||
|
|
||
|
if (unlikely(segment_eq(get_fs(), KERNEL_DS)))
|
||
|
return -EINVAL;
|
||
|
@@ -601,12 +605,6 @@
|
||
|
buf += SZ_SG_HEADER;
|
||
|
__get_user(opcode, buf);
|
||
|
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;
|
||
|
sfp->next_cmd_len = 0; /* reset so only this write() effected */
|
||
|
} else {
|
||
|
@@ -678,7 +676,7 @@
|
||
|
int k;
|
||
|
Sg_request *srp;
|
||
|
sg_io_hdr_t *hp;
|
||
|
- unsigned char cmnd[MAX_COMMAND_SIZE];
|
||
|
+ unsigned char cmnd[SG_MAX_CDB_SIZE];
|
||
|
int timeout;
|
||
|
unsigned long ul_timeout;
|
||
|
|
||
|
@@ -1648,15 +1646,27 @@
|
||
|
struct request_queue *q = sfp->parentdp->device->request_queue;
|
||
|
struct rq_map_data *md, map_data;
|
||
|
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",
|
||
|
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);
|
||
|
- if (!rq)
|
||
|
+ if (!rq) {
|
||
|
+ kfree(long_cmdp);
|
||
|
return -ENOMEM;
|
||
|
+ }
|
||
|
|
||
|
blk_rq_set_block_pc(rq);
|
||
|
+
|
||
|
+ if (hp->cmd_len > BLK_MAX_CDB)
|
||
|
+ rq->cmd = long_cmdp;
|
||
|
memcpy(rq->cmd, cmd, hp->cmd_len);
|
||
|
rq->cmd_len = hp->cmd_len;
|
||
|
|
||
|
@@ -1741,6 +1751,8 @@
|
||
|
if (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);
|
||
|
}
|
||
|
|
||
|
diff --git a/include/uapi/scsi/sg.h b/include/uapi/scsi/sg.h
|
||
|
index a9f3c6f..d8c0c43 100644
|
||
|
--- a/include/uapi/scsi/sg.h
|
||
|
+++ b/include/uapi/scsi/sg.h
|
||
|
@@ -4,77 +4,34 @@
|
||
|
#include <linux/compiler.h>
|
||
|
|
||
|
/*
|
||
|
- History:
|
||
|
- Started: Aug 9 by Lawrence Foard (entropy@world.std.com), to allow user
|
||
|
- process control of SCSI devices.
|
||
|
- Development Sponsored by Killy Corp. NY NY
|
||
|
-Original driver (sg.h):
|
||
|
-* Copyright (C) 1992 Lawrence Foard
|
||
|
-Version 2 and 3 extensions to driver:
|
||
|
-* Copyright (C) 1998 - 2006 Douglas Gilbert
|
||
|
-
|
||
|
- Version: 3.5.34 (20060920)
|
||
|
- This version is for 2.6 series kernels.
|
||
|
-
|
||
|
- For a full changelog see http://www.torque.net/sg
|
||
|
-
|
||
|
-Map of SG verions to the Linux kernels in which they appear:
|
||
|
- ---------- ----------------------------------
|
||
|
- original all kernels < 2.2.6
|
||
|
- 2.1.40 2.2.20
|
||
|
- 3.0.x optional version 3 sg driver for 2.2 series
|
||
|
- 3.1.17++ 2.4.0++
|
||
|
- 3.5.30++ 2.6.0++
|
||
|
-
|
||
|
-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).
|
||
|
-*/
|
||
|
+ * History:
|
||
|
+ * Started: Aug 9 by Lawrence Foard (entropy@world.std.com), to allow user
|
||
|
+ * process control of SCSI devices.
|
||
|
+ * Development Sponsored by Killy Corp. NY NY
|
||
|
+ *
|
||
|
+ * Original driver (sg.h):
|
||
|
+ * Copyright (C) 1992 Lawrence Foard
|
||
|
+ * Version 2 and 3 extensions to driver:
|
||
|
+ * Copyright (C) 1998 - 2014 Douglas Gilbert
|
||
|
+ *
|
||
|
+ * Version: 3.5.36 (20140603)
|
||
|
+ * This version is for 2.6 and 3 series kernels.
|
||
|
+ *
|
||
|
+ * Documentation
|
||
|
+ * =============
|
||
|
+ * A web site for the SG device driver can be found at:
|
||
|
+ * http://sg.danny.cz/sg [alternatively check the MAINTAINERS file]
|
||
|
+ * The documentation for the sg version 3 driver can be found at:
|
||
|
+ * http://sg.danny.cz/sg/p/sg_v3_ho.html
|
||
|
+ * Also see: <kernel_source>/Documentation/scsi/scsi-generic.txt
|
||
|
+ *
|
||
|
+ * For utility and test programs see: http://sg.danny.cz/sg/sg3_utils.html
|
||
|
+ */
|
||
|
|
||
|
#ifdef __KERNEL__
|
||
|
extern int sg_big_buff; /* for sysctl */
|
||
|
#endif
|
||
|
|
||
|
-/* New interface introduced in the 3.x SG drivers follows */
|
||
|
|
||
|
typedef struct sg_iovec /* same structure as used by readv() Linux system */
|
||
|
{ /* call. It defines one scatter-gather element. */
|
||
|
@@ -87,7 +44,7 @@
|
||
|
{
|
||
|
int interface_id; /* [i] 'S' for SCSI generic (required) */
|
||
|
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 short iovec_count; /* [i] 0 implies no scatter gather */
|
||
|
unsigned int dxfer_len; /* [i] byte count of data transfer */
|