* [PATCHSET 0/3] varlen extended and vendor-specific cdbs
@ 2007-12-18 13:33 Boaz Harrosh
2007-12-18 13:38 ` [PATCH 1/3] Let scsi_cmnd->cmnd use request->cmd buffer Boaz Harrosh
` (3 more replies)
0 siblings, 4 replies; 7+ messages in thread
From: Boaz Harrosh @ 2007-12-18 13:33 UTC (permalink / raw)
To: James Bottomley, Jens Axboe, Mike Christie, linux-scsi
Cc: Benny Halevy, Matthew Wilcox
Submitted is a patchset for adding support for variable-length, extended, and
vendor specific CDBs. It should now cover the entire range of the
SCSI standard.
They are based on scsi-misc + the submitted bidi patches.
Difference from last time, is at struct request. I did a smallish
hack to save the extra pointer space. The pointer now shares it's
space with the request->cmd, as they are mutual exclusive. The
flag to switch between them is when cmd_len == 0 and varlen_cdb_len != 0
I've added 2 accessors to hide the mess. I think this approach
should be safe. I can easily go back to the separate pointer,
but I figured a little hack is better then a bloat.
This is on top of the size shrink to struct scsi_cmnd gained
in the first patch. We save upto 12 bytes on 32 bit ARCHs
So over all, this cleans things up, and add fixtures with out
any extra cost.
[1/4] Let scsi_cmnd->cmnd use request->cmd buffer
Here I let scsi_cmnd->cmnd point to the space allocated by
request->cmd, instead of copying the data. The scsi_cmnd->cmd_len
is guaranteed to contain the right length of the command.
I have tried to go over every single place in the kernel that uses
scsi_cmnd->cmnd and make sure it looks sane. Surprisingly to me,
that was not at all bad. I hope I did not miss anything.
I've tested on an x86_64 machine booting from a sata disk and
ran the iscsi regression tests as well as my bidi and varlen tests
on top of the complete patchset and all tests passed.
[2/4] block layer varlen-cd
Here I added an option to use a user supplied buffer for an arbitrary
large command. Buffer must be kept valid until execution of request
ends. The pointer to the buffer shares it's space with the fixed
length command, so the size of struct request does not change.
[3/4] scsi: varlen extended and vendor-specific cdbs
Adds support for variable length, extended, and vendor-specific
cdbs at the scsi mid-layer.
I will send a patch to iscsi once the pending iscsi patchset gets
committed into scsi-misc.
Boaz
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 1/3] Let scsi_cmnd->cmnd use request->cmd buffer
2007-12-18 13:33 [PATCHSET 0/3] varlen extended and vendor-specific cdbs Boaz Harrosh
@ 2007-12-18 13:38 ` Boaz Harrosh
2007-12-18 13:42 ` [PATCH 2/2] block layer varlen-cdb Boaz Harrosh
` (2 subsequent siblings)
3 siblings, 0 replies; 7+ messages in thread
From: Boaz Harrosh @ 2007-12-18 13:38 UTC (permalink / raw)
To: James Bottomley, Jens Axboe, Mike Christie, linux-scsi
Cc: Benny Halevy, Matthew Wilcox
- struct scsi_cmnd had a 16 bytes command buffer of its own.
This is an unnecessary duplication and copy of request's
cmd. It is probably leftovers from the time that scsi_cmnd
could function without a request attached. So clean that up.
- Once above is done, few places, apart from scsi-ml, needed
adjustments due to changing the data type of scsi_cmnd->cmnd.
- Lots of drivers still use MAX_COMMAND_SIZE. So I have left
that #define but equate it to BLK_MAX_CDB. The way I see it
and is reflected in the patch below is.
MAX_COMMAND_SIZE - means: The longest fixed-length (*) SCSI CDB
as per the SCSI standard and is not related
to the implementation.
BLK_MAX_CDB. - The allocated space at the request level
(*)fixed-length here means commands that their size can be determined
by their opcode and the CDB does not carry a length specifier, like
the VARIABLE_LENGTH_CMD(0x7f) command. This is actually not exactly
true and the SCSI standard also defines extended commands and
vendor specific commands that can be bigger than 16 bytes. The kernel
will support these using the same infrastructure used for VARLEN CDB's.
So in effect MAX_COMMAND_SIZE means the maximum size command
scsi-ml supports without specifying a cmd_len by ULD's
Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
---
drivers/firewire/fw-sbp2.c | 2 +-
drivers/s390/scsi/zfcp_dbf.c | 2 +-
drivers/s390/scsi/zfcp_fsf.c | 2 +-
drivers/scsi/53c700.c | 6 +++---
drivers/scsi/a100u2w.c | 2 +-
drivers/scsi/hptiop.c | 6 +++---
drivers/scsi/ibmvscsi/ibmvscsi.c | 2 +-
drivers/scsi/initio.c | 2 +-
drivers/scsi/scsi_error.c | 14 ++++++++------
drivers/scsi/scsi_lib.c | 5 +++--
drivers/scsi/scsi_tgt_lib.c | 2 ++
drivers/usb/storage/isd200.c | 2 ++
include/scsi/scsi_cmnd.h | 9 +++++++--
include/scsi/scsi_eh.h | 4 ++--
14 files changed, 36 insertions(+), 24 deletions(-)
diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c
index 624ff3e..06b4306 100644
--- a/drivers/firewire/fw-sbp2.c
+++ b/drivers/firewire/fw-sbp2.c
@@ -1215,7 +1215,7 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
memset(orb->request.command_block,
0, sizeof(orb->request.command_block));
- memcpy(orb->request.command_block, cmd->cmnd, COMMAND_SIZE(*cmd->cmnd));
+ memcpy(orb->request.command_block, cmd->cmnd, cmd->cmd_len);
orb->base.callback = complete_command_orb;
orb->base.request_bus =
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
index 701046c..7a7f619 100644
--- a/drivers/s390/scsi/zfcp_dbf.c
+++ b/drivers/s390/scsi/zfcp_dbf.c
@@ -724,7 +724,7 @@ _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level,
rec->scsi_result = scsi_cmnd->result;
rec->scsi_cmnd = (unsigned long)scsi_cmnd;
rec->scsi_serial = scsi_cmnd->serial_number;
- memcpy(rec->scsi_opcode, &scsi_cmnd->cmnd,
+ memcpy(rec->scsi_opcode, scsi_cmnd->cmnd,
min((int)scsi_cmnd->cmd_len,
ZFCP_DBF_SCSI_OPCODE));
rec->scsi_retries = scsi_cmnd->retries;
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index ff866eb..e9ead12 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -4220,7 +4220,7 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req)
ZFCP_LOG_TRACE("scpnt->result =0x%x, command was:\n",
scpnt->result);
ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE,
- (void *) &scpnt->cmnd, scpnt->cmd_len);
+ scpnt->cmnd, scpnt->cmd_len);
ZFCP_LOG_TRACE("%i bytes sense data provided by FCP\n",
fcp_rsp_iu->fcp_sns_len);
diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c
index 71ff3fb..85460f8 100644
--- a/drivers/scsi/53c700.c
+++ b/drivers/scsi/53c700.c
@@ -599,7 +599,7 @@ NCR_700_scsi_done(struct NCR_700_Host_Parameters *hostdata,
(struct NCR_700_command_slot *)SCp->host_scribble;
dma_unmap_single(hostdata->dev, slot->pCmd,
- sizeof(SCp->cmnd), DMA_TO_DEVICE);
+ MAX_COMMAND_SIZE, DMA_TO_DEVICE);
if (slot->flags == NCR_700_FLAG_AUTOSENSE) {
char *cmnd = NCR_700_get_sense_cmnd(SCp->device);
#ifdef NCR_700_DEBUG
@@ -1003,7 +1003,7 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp,
* here */
NCR_700_unmap(hostdata, SCp, slot);
dma_unmap_single(hostdata->dev, slot->pCmd,
- sizeof(SCp->cmnd),
+ MAX_COMMAND_SIZE,
DMA_TO_DEVICE);
cmnd[0] = REQUEST_SENSE;
@@ -1900,7 +1900,7 @@ NCR_700_queuecommand(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *))
}
slot->resume_offset = 0;
slot->pCmd = dma_map_single(hostdata->dev, SCp->cmnd,
- sizeof(SCp->cmnd), DMA_TO_DEVICE);
+ MAX_COMMAND_SIZE, DMA_TO_DEVICE);
NCR_700_start_command(SCp);
return 0;
}
diff --git a/drivers/scsi/a100u2w.c b/drivers/scsi/a100u2w.c
index d3a6d15..b38a9e7 100644
--- a/drivers/scsi/a100u2w.c
+++ b/drivers/scsi/a100u2w.c
@@ -894,7 +894,7 @@ static void inia100_build_scb(struct orc_host * host, struct orc_scb * scb, stru
} else {
scb->tag_msg = 0; /* No tag support */
}
- memcpy(&scb->cdb[0], &cmd->cmnd, scb->cdb_len);
+ memcpy(scb->cdb, cmd->cmnd, scb->cdb_len);
}
/**
diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c
index df1a764..604640d 100644
--- a/drivers/scsi/hptiop.c
+++ b/drivers/scsi/hptiop.c
@@ -761,9 +761,9 @@ static int hptiop_queuecommand(struct scsi_cmnd *scp,
scp,
host->host_no, scp->device->channel,
scp->device->id, scp->device->lun,
- *((u32 *)&scp->cmnd),
- *((u32 *)&scp->cmnd + 1),
- *((u32 *)&scp->cmnd + 2),
+ ((u32 *)scp->cmnd)[0],
+ ((u32 *)scp->cmnd)[1],
+ ((u32 *)scp->cmnd)[2],
_req->index, _req->req_virt);
scp->result = 0;
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index 3081901..4323f96 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -738,7 +738,7 @@ static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd,
srp_cmd = &evt_struct->iu.srp.cmd;
memset(srp_cmd, 0x00, SRP_MAX_IU_LEN);
srp_cmd->opcode = SRP_CMD;
- memcpy(srp_cmd->cdb, cmnd->cmnd, sizeof(cmnd->cmnd));
+ memcpy(srp_cmd->cdb, cmnd->cmnd, sizeof(srp_cmd->cdb));
srp_cmd->lun = ((u64) lun) << 48;
if (!map_data_for_srp_cmd(cmnd, evt_struct, srp_cmd, hostdata->dev)) {
diff --git a/drivers/scsi/initio.c b/drivers/scsi/initio.c
index 769a7a8..d61abf4 100644
--- a/drivers/scsi/initio.c
+++ b/drivers/scsi/initio.c
@@ -2590,7 +2590,7 @@ static void initio_build_scb(struct initio_host * host, struct scsi_ctrl_blk * c
cblk->hastat = 0;
cblk->tastat = 0;
/* Command the command */
- memcpy(&cblk->cdb[0], &cmnd->cmnd, cmnd->cmd_len);
+ memcpy(cblk->cdb, cmnd->cmnd, cmnd->cmd_len);
/* Set up tags */
if (cmnd->device->tagged_supported) { /* Tag Support */
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 5c8ba6a..2a285ef 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -593,7 +593,7 @@ static void scsi_abort_eh_cmnd(struct scsi_cmnd *scmd)
* @scmd: SCSI command structure to hijack
* @ses: structure to save restore information
* @cmnd: CDB to send. Can be NULL if no new cmnd is needed
- * @cmnd_size: size in bytes of @cmnd
+ * @cmnd_size: size in bytes of @cmnd (must be <= BLK_MAX_CDB)
* @sense_bytes: size of sense data to copy. or 0 (if != 0 @cmnd is ignored)
*
* This function is used to save a scsi command information before re-execution
@@ -615,12 +615,14 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses,
* command.
*/
ses->cmd_len = scmd->cmd_len;
- memcpy(ses->cmnd, scmd->cmnd, sizeof(scmd->cmnd));
+ ses->cmnd = scmd->cmnd;
ses->data_direction = scmd->sc_data_direction;
ses->sdb = scmd->sdb;
ses->next_rq = scmd->request->next_rq;
ses->result = scmd->result;
+ scmd->cmnd = ses->eh_cmnd;
+ memset(scmd->cmnd, 0, BLK_MAX_CDB);
memset(&scmd->sdb, 0, sizeof(scmd->sdb));
scmd->request->next_rq = NULL;
@@ -632,14 +634,13 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses,
scmd->sdb.sglist = &ses->sense_sgl;
scmd->sc_data_direction = DMA_FROM_DEVICE;
scmd->sdb.sg_count = 1;
- memset(scmd->cmnd, 0, sizeof(scmd->cmnd));
scmd->cmnd[0] = REQUEST_SENSE;
scmd->cmnd[4] = scmd->sdb.length;
scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
} else {
scmd->sc_data_direction = DMA_NONE;
if (cmnd) {
- memset(scmd->cmnd, 0, sizeof(scmd->cmnd));
+ BUG_ON(cmnd_size > BLK_MAX_CDB);
memcpy(scmd->cmnd, cmnd, cmnd_size);
scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
}
@@ -672,7 +673,7 @@ void scsi_eh_restore_cmnd(struct scsi_cmnd* scmd, struct scsi_eh_save *ses)
* Restore original data
*/
scmd->cmd_len = ses->cmd_len;
- memcpy(scmd->cmnd, ses->cmnd, sizeof(scmd->cmnd));
+ scmd->cmnd = ses->cmnd;
scmd->sc_data_direction = ses->data_direction;
scmd->sdb = ses->sdb;
scmd->request->next_rq = ses->next_rq;
@@ -1693,7 +1694,8 @@ scsi_reset_provider(struct scsi_device *dev, int flag)
scmd->request = &req;
memset(&scmd->eh_timeout, 0, sizeof(scmd->eh_timeout));
- memset(&scmd->cmnd, '\0', sizeof(scmd->cmnd));
+ scmd->cmnd = req.cmd;
+ memset(scmd->cmnd, 0, BLK_MAX_CDB);
scmd->scsi_done = scsi_reset_provider_done_command;
memset(&scmd->sdb, 0, sizeof(scmd->sdb));
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index a6aae56..51168f0 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -1220,6 +1220,8 @@ static struct scsi_cmnd *scsi_get_cmd_from_req(struct scsi_device *sdev,
cmd->tag = req->tag;
cmd->request = req;
+ cmd->cmnd = req->cmd;
+
return cmd;
}
@@ -1257,8 +1259,6 @@ int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req)
req->buffer = NULL;
}
- BUILD_BUG_ON(sizeof(req->cmd) > sizeof(cmd->cmnd));
- memcpy(cmd->cmnd, req->cmd, sizeof(cmd->cmnd));
cmd->cmd_len = req->cmd_len;
if (!req->data_len)
cmd->sc_data_direction = DMA_NONE;
@@ -1295,6 +1295,7 @@ int scsi_setup_fs_cmnd(struct scsi_device *sdev, struct request *req)
if (unlikely(!cmd))
return BLKPREP_DEFER;
+ memset(cmd->cmnd, 0, BLK_MAX_CDB);
return scsi_init_io(cmd, GFP_ATOMIC);
}
EXPORT_SYMBOL(scsi_setup_fs_cmnd);
diff --git a/drivers/scsi/scsi_tgt_lib.c b/drivers/scsi/scsi_tgt_lib.c
index 91630ba..e01a985 100644
--- a/drivers/scsi/scsi_tgt_lib.c
+++ b/drivers/scsi/scsi_tgt_lib.c
@@ -108,6 +108,8 @@ struct scsi_cmnd *scsi_host_get_command(struct Scsi_Host *shost,
cmd->jiffies_at_alloc = jiffies;
cmd->request = rq;
+ cmd->cmnd = rq->cmd;
+
rq->special = cmd;
rq->cmd_type = REQ_TYPE_SPECIAL;
rq->cmd_flags |= REQ_TYPE_BLOCK_PC;
diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c
index 2d9a32b..50db42a 100644
--- a/drivers/usb/storage/isd200.c
+++ b/drivers/usb/storage/isd200.c
@@ -287,6 +287,7 @@ struct isd200_info {
/* maximum number of LUNs supported */
unsigned char MaxLUNs;
+ unsigned char cmnd[BLK_MAX_CDB];
struct scsi_cmnd srb;
struct scatterlist sg;
};
@@ -445,6 +446,7 @@ static int isd200_action( struct us_data *us, int action,
memset(&ata, 0, sizeof(ata));
memset(&srb_dev, 0, sizeof(srb_dev));
+ srb->cmnd = info->cmnd;
srb->device = &srb_dev;
++srb->serial_number;
diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
index cd2851a..f09c02d 100644
--- a/include/scsi/scsi_cmnd.h
+++ b/include/scsi/scsi_cmnd.h
@@ -7,11 +7,17 @@
#include <linux/types.h>
#include <linux/timer.h>
#include <linux/scatterlist.h>
+#include <linux/blkdev.h>
struct scatterlist;
struct Scsi_Host;
struct scsi_device;
+#define MAX_COMMAND_SIZE 16
+#if (MAX_COMMAND_SIZE > BLK_MAX_CDB)
+# error MAX_COMMAND_SIZE can not be smaller than BLK_MAX_CDB
+#endif
+
struct scsi_data_buffer {
struct scatterlist *sglist;
unsigned length;
@@ -67,8 +73,7 @@ struct scsi_cmnd {
enum dma_data_direction sc_data_direction;
/* These elements define the operation we are about to perform */
-#define MAX_COMMAND_SIZE 16
- unsigned char cmnd[MAX_COMMAND_SIZE];
+ unsigned char *cmnd;
struct timer_list eh_timeout; /* Used to time out the command. */
diff --git a/include/scsi/scsi_eh.h b/include/scsi/scsi_eh.h
index 25071d5..9438ea1 100644
--- a/include/scsi/scsi_eh.h
+++ b/include/scsi/scsi_eh.h
@@ -72,11 +72,11 @@ struct scsi_eh_save {
int result;
enum dma_data_direction data_direction;
unsigned char cmd_len;
- unsigned char cmnd[MAX_COMMAND_SIZE];
+ unsigned char *cmnd;
struct scsi_data_buffer sdb;
struct request *next_rq;
-
/* new command support */
+ unsigned char eh_cmnd[BLK_MAX_CDB];
struct scatterlist sense_sgl;
};
--
1.5.3.3
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 2/2] block layer varlen-cdb
2007-12-18 13:33 [PATCHSET 0/3] varlen extended and vendor-specific cdbs Boaz Harrosh
2007-12-18 13:38 ` [PATCH 1/3] Let scsi_cmnd->cmnd use request->cmd buffer Boaz Harrosh
@ 2007-12-18 13:42 ` Boaz Harrosh
2007-12-18 13:45 ` [PATCH 3/3] scsi: varlen extended and vendor-specific cdbs Boaz Harrosh
2007-12-20 19:39 ` [PATCHSET 0/3] " Boaz Harrosh
3 siblings, 0 replies; 7+ messages in thread
From: Boaz Harrosh @ 2007-12-18 13:42 UTC (permalink / raw)
To: James Bottomley, Jens Axboe, Mike Christie, linux-scsi
Cc: Benny Halevy, Matthew Wilcox
- add varlen_cdb and varlen_cdb_len to hold a large user cdb
if needed. They start as empty. Allocation of buffer must
be done by user and held until request execution is done.
- Since there can be either a fix_length command up to 16 bytes
or a variable_length, larger then 16 bytes, commands but never
both, we hold the two types in a union to save space. The
presence of varlen_cdb_len and cmd_len==0 signals a varlen_cdb
mode.
- Please use added rq_{set,get}_varlen_cdb() to set every thing
up in a way that will not confuse drivers that do not support
varlen_cdb's.
- Note that this patch does not add any size to struct request
since the unsigned cmd_len is split here to 2 ushorts, which
is more then enough.
Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
---
block/ll_rw_blk.c | 2 ++
include/linux/blkdev.h | 27 +++++++++++++++++++++++++--
2 files changed, 27 insertions(+), 2 deletions(-)
diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c
index 8b91994..e80179b 100644
--- a/block/ll_rw_blk.c
+++ b/block/ll_rw_blk.c
@@ -261,6 +261,8 @@ static void rq_init(struct request_queue *q, struct request *rq)
rq->end_io_data = NULL;
rq->completion_data = NULL;
rq->next_rq = NULL;
+ rq->varlen_cdb_len = 0;
+ rq->varlen_cdb = NULL;
}
/**
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index d18ee67..aa3090c 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -287,8 +287,15 @@ struct request {
/*
* when request is used as a packet command carrier
*/
- unsigned int cmd_len;
- unsigned char cmd[BLK_MAX_CDB];
+ unsigned short cmd_len;
+ unsigned short varlen_cdb_len; /* length of varlen_cdb buffer */
+ union {
+ unsigned char cmd[BLK_MAX_CDB];
+ unsigned char *varlen_cdb;/* an optional variable-length cdb.
+ * points to a user buffer that must
+ * be valid until end of request
+ */
+ };
unsigned int data_len;
unsigned int sense_len;
@@ -550,6 +557,22 @@ enum {
#define rq_is_sync(rq) (rq_data_dir((rq)) == READ || (rq)->cmd_flags & REQ_RW_SYNC)
#define rq_is_meta(rq) ((rq)->cmd_flags & REQ_RW_META)
+static inline void rq_set_varlen_cdb(struct request *rq, u8 *cdb, short cdb_len)
+{
+ rq->cmd_len = 0; /* Make sure legacy drivers don't get confused */
+ rq->varlen_cdb_len = cdb_len;
+ rq->varlen_cdb = cdb;
+}
+
+/* If ! a varlen_cdb than return NULL */
+static inline u8 *rq_get_varlen_cdb(struct request *rq)
+{
+ if (!rq->cmd_len && rq->varlen_cdb_len)
+ return rq->varlen_cdb;
+ else
+ return NULL;
+}
+
static inline int blk_queue_full(struct request_queue *q, int rw)
{
if (rw == READ)
--
1.5.3.3
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 3/3] scsi: varlen extended and vendor-specific cdbs
2007-12-18 13:33 [PATCHSET 0/3] varlen extended and vendor-specific cdbs Boaz Harrosh
2007-12-18 13:38 ` [PATCH 1/3] Let scsi_cmnd->cmnd use request->cmd buffer Boaz Harrosh
2007-12-18 13:42 ` [PATCH 2/2] block layer varlen-cdb Boaz Harrosh
@ 2007-12-18 13:45 ` Boaz Harrosh
2007-12-20 19:39 ` [PATCHSET 0/3] " Boaz Harrosh
3 siblings, 0 replies; 7+ messages in thread
From: Boaz Harrosh @ 2007-12-18 13:45 UTC (permalink / raw)
To: James Bottomley, Jens Axboe, Mike Christie, linux-scsi
Cc: Benny Halevy, Matthew Wilcox
Add support for variable-length, extended, and vendor specific
CDBs to scsi-ml. It is now possible for initiators and ULD's
to issue these types of commands. LLDs need not change much.
All they need is to raise the .max_cmd_len to the longest command
they support (see iscsi patches).
- clean-up some code paths that did not expect commands to be
larger than 16, and change cmd_len members' type to short as
char is not enough.
- Add support for varlen_cdb in scsi_execute.
Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
block/scsi_ioctl.c | 4 ++--
drivers/scsi/constants.c | 10 +++-------
drivers/scsi/scsi.c | 22 +++++++++++-----------
drivers/scsi/scsi_lib.c | 27 ++++++++++++++++++++++-----
include/scsi/scsi.h | 40 +++++++++++++++++++++++++++++++++-------
include/scsi/scsi_cmnd.h | 2 +-
include/scsi/scsi_host.h | 8 +++-----
7 files changed, 75 insertions(+), 38 deletions(-)
diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
index 91c7322..f08e196 100644
--- a/block/scsi_ioctl.c
+++ b/block/scsi_ioctl.c
@@ -33,13 +33,13 @@
#include <scsi/scsi_cmnd.h>
/* Command group 3 is reserved and should never be used. */
-const unsigned char scsi_command_size[8] =
+const unsigned char scsi_command_size_tbl[8] =
{
6, 10, 10, 12,
16, 12, 10, 10
};
-EXPORT_SYMBOL(scsi_command_size);
+EXPORT_SYMBOL(scsi_command_size_tbl);
#include <scsi/sg.h>
diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c
index 403a7f2..9785d73 100644
--- a/drivers/scsi/constants.c
+++ b/drivers/scsi/constants.c
@@ -28,7 +28,6 @@
#define SERVICE_ACTION_OUT_12 0xa9
#define SERVICE_ACTION_IN_16 0x9e
#define SERVICE_ACTION_OUT_16 0x9f
-#define VARIABLE_LENGTH_CMD 0x7f
@@ -210,7 +209,7 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len)
cdb0 = cdbp[0];
switch(cdb0) {
case VARIABLE_LENGTH_CMD:
- len = cdbp[7] + 8;
+ len = scsi_varlen_cdb_length(cdbp);
if (len < 10) {
printk("short variable length command, "
"len=%d ext_len=%d", len, cdb_len);
@@ -300,7 +299,7 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len)
cdb0 = cdbp[0];
switch(cdb0) {
case VARIABLE_LENGTH_CMD:
- len = cdbp[7] + 8;
+ len = scsi_varlen_cdb_length(cdbp);
if (len < 10) {
printk("short opcode=0x%x command, len=%d "
"ext_len=%d", cdb0, len, cdb_len);
@@ -335,10 +334,7 @@ void __scsi_print_command(unsigned char *cdb)
int k, len;
print_opcode_name(cdb, 0);
- if (VARIABLE_LENGTH_CMD == cdb[0])
- len = cdb[7] + 8;
- else
- len = COMMAND_SIZE(cdb[0]);
+ len = scsi_command_size(cdb);
/* print out all bytes in cdb */
for (k = 0; k < len; ++k)
printk(" %02x", cdb[k]);
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index a0fd785..5846bb6 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -79,15 +79,6 @@ static void scsi_done(struct scsi_cmnd *cmd);
#define MIN_RESET_PERIOD (15*HZ)
/*
- * Macro to determine the size of SCSI command. This macro takes vendor
- * unique commands into account. SCSI commands in groups 6 and 7 are
- * vendor unique and we will depend upon the command length being
- * supplied correctly in cmd_len.
- */
-#define CDB_SIZE(cmd) (((((cmd)->cmnd[0] >> 5) & 7) < 6) ? \
- COMMAND_SIZE((cmd)->cmnd[0]) : (cmd)->cmd_len)
-
-/*
* Note - the initial logging level can be set here to log events at boot time.
* After the system is up, you may enable logging via the /proc interface.
*/
@@ -480,6 +471,7 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
unsigned long flags = 0;
unsigned long timeout;
int rtn = 0;
+ unsigned cmd_len;
/* check if the device is still usable */
if (unlikely(cmd->device->sdev_state == SDEV_DEL)) {
@@ -561,9 +553,17 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
* Before we queue this command, check if the command
* length exceeds what the host adapter can handle.
*/
- if (CDB_SIZE(cmd) > cmd->device->host->max_cmd_len) {
+ cmd_len = cmd->cmd_len;
+ if (!cmd_len) {
+ BUG_ON(cmd->cmnd[0] == VARIABLE_LENGTH_CMD);
+ cmd_len = COMMAND_SIZE((cmd)->cmnd[0]);
+ }
+
+ if (cmd_len > cmd->device->host->max_cmd_len) {
SCSI_LOG_MLQUEUE(3,
- printk("queuecommand : command too long.\n"));
+ printk("queuecommand : command too long. "
+ "cdb_size=%d host->max_cmd_len=%d\n",
+ cmd->cmd_len, cmd->device->host->max_cmd_len));
cmd->result = (DID_ABORT << 16);
scsi_done(cmd);
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 51168f0..19dc03e 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -192,8 +192,16 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
buffer, bufflen, __GFP_WAIT))
goto out;
- req->cmd_len = COMMAND_SIZE(cmd[0]);
- memcpy(req->cmd, cmd, req->cmd_len);
+ if (cmd[0] == VARIABLE_LENGTH_CMD)
+ rq_set_varlen_cdb(req, (u8 *)cmd, scsi_varlen_cdb_length(cmd));
+ else {
+ req->cmd_len = COMMAND_SIZE(cmd[0]);
+ memcpy(req->cmd, cmd, req->cmd_len);
+ if (req->cmd_len < MAX_COMMAND_SIZE)
+ memset(&req->cmd[req->cmd_len], 0,
+ MAX_COMMAND_SIZE - req->cmd_len);
+ }
+
req->sense = sense;
req->sense_len = 0;
req->retries = retries;
@@ -445,7 +453,7 @@ static void scsi_init_cmd_errh(struct scsi_cmnd *cmd)
scsi_set_resid(cmd, 0);
memset(cmd->sense_buffer, 0, sizeof cmd->sense_buffer);
if (cmd->cmd_len == 0)
- cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]);
+ cmd->cmd_len = scsi_command_size(cmd->cmnd);
}
void scsi_device_unbusy(struct scsi_device *sdev)
@@ -1228,6 +1236,7 @@ static struct scsi_cmnd *scsi_get_cmd_from_req(struct scsi_device *sdev,
int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req)
{
struct scsi_cmnd *cmd;
+ u8 *varlen_cdb;
int ret = scsi_prep_state_check(sdev, req);
if (ret != BLKPREP_OK)
@@ -1259,14 +1268,22 @@ int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req)
req->buffer = NULL;
}
- cmd->cmd_len = req->cmd_len;
+ varlen_cdb = rq_get_varlen_cdb(req);
+ if (varlen_cdb) {
+ cmd->cmnd = varlen_cdb;
+ cmd->cmd_len = req->varlen_cdb_len;
+ } else if (req->cmd_len)
+ cmd->cmd_len = req->cmd_len;
+ else
+ cmd->cmd_len = scsi_command_size(cmd->cmnd);
+
if (!req->data_len)
cmd->sc_data_direction = DMA_NONE;
else if (rq_data_dir(req) == WRITE)
cmd->sc_data_direction = DMA_TO_DEVICE;
else
cmd->sc_data_direction = DMA_FROM_DEVICE;
-
+
cmd->transfersize = req->data_len;
cmd->allowed = req->retries;
cmd->timeout_per_command = req->timeout;
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
index 702fcfe..320249f 100644
--- a/include/scsi/scsi.h
+++ b/include/scsi/scsi.h
@@ -11,13 +11,6 @@
#include <linux/types.h>
/*
- * SCSI command lengths
- */
-
-extern const unsigned char scsi_command_size[8];
-#define COMMAND_SIZE(opcode) scsi_command_size[((opcode) >> 5) & 7]
-
-/*
* Special value for scanning to specify scanning or rescanning of all
* possible channels, (target) ids, or luns on a given shost.
*/
@@ -89,6 +82,7 @@ extern const unsigned char scsi_command_size[8];
#define MODE_SENSE_10 0x5a
#define PERSISTENT_RESERVE_IN 0x5e
#define PERSISTENT_RESERVE_OUT 0x5f
+#define VARIABLE_LENGTH_CMD 0x7f
#define REPORT_LUNS 0xa0
#define MAINTENANCE_IN 0xa3
#define MOVE_MEDIUM 0xa5
@@ -116,6 +110,38 @@ extern const unsigned char scsi_command_size[8];
#define ATA_12 0xa1 /* 12-byte pass-thru */
/*
+ * SCSI command lengths
+ */
+
+#define SCSI_MAX_VARLEN_CDB_SIZE 260
+
+/* defined in T10 SCSI Primary Commands-2 (SPC2) */
+struct scsi_varlen_cdb_hdr {
+ u8 opcode; /* opcode always == VARIABLE_LENGTH_CMD */
+ u8 control;
+ u8 misc[5];
+ u8 additional_cdb_length; /* total cdb length - 8 */
+ __be16 service_action;
+ /* service specific data follows */
+};
+
+static inline unsigned
+scsi_varlen_cdb_length(const void *hdr)
+{
+ return ((struct scsi_varlen_cdb_hdr*)hdr)->additional_cdb_length + 8;
+}
+
+extern const unsigned char scsi_command_size_tbl[8];
+#define COMMAND_SIZE(opcode) scsi_command_size_tbl[((opcode) >> 5) & 7]
+
+static inline unsigned
+scsi_command_size(const unsigned char *cmnd)
+{
+ return (cmnd[0] == VARIABLE_LENGTH_CMD) ? scsi_varlen_cdb_length(cmnd) :
+ COMMAND_SIZE(cmnd[0]);
+}
+
+/*
* SCSI Architecture Model (SAM) Status codes. Taken from SAM-3 draft
* T10/1561-D Revision 4 Draft dated 7th November 2002.
*/
diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
index f09c02d..79656dc 100644
--- a/include/scsi/scsi_cmnd.h
+++ b/include/scsi/scsi_cmnd.h
@@ -69,7 +69,7 @@ struct scsi_cmnd {
int allowed;
int timeout_per_command;
- unsigned char cmd_len;
+ unsigned short cmd_len;
enum dma_data_direction sc_data_direction;
/* These elements define the operation we are about to perform */
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index cb2bcab..35c231c 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -574,13 +574,11 @@ struct Scsi_Host {
/*
* The maximum length of SCSI commands that this host can accept.
* Probably 12 for most host adapters, but could be 16 for others.
+ * or 260 if the driver supports variable length cdbs.
* For drivers that don't set this field, a value of 12 is
- * assumed. I am leaving this as a number rather than a bit
- * because you never know what subsequent SCSI standards might do
- * (i.e. could there be a 20 byte or a 24-byte command a few years
- * down the road?).
+ * assumed.
*/
- unsigned char max_cmd_len;
+ unsigned short max_cmd_len;
int this_id;
int can_queue;
--
1.5.3.3
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCHSET 0/3] varlen extended and vendor-specific cdbs
2007-12-18 13:33 [PATCHSET 0/3] varlen extended and vendor-specific cdbs Boaz Harrosh
` (2 preceding siblings ...)
2007-12-18 13:45 ` [PATCH 3/3] scsi: varlen extended and vendor-specific cdbs Boaz Harrosh
@ 2007-12-20 19:39 ` Boaz Harrosh
3 siblings, 0 replies; 7+ messages in thread
From: Boaz Harrosh @ 2007-12-20 19:39 UTC (permalink / raw)
To: James Bottomley, Jens Axboe, Mike Christie, linux-scsi,
Andrew Morton <akpm>
Cc: Benny Halevy, Matthew Wilcox
On Tue, Dec 18 2007 at 15:33 +0200, Boaz Harrosh <bharrosh@panasas.com> wrote:
> Submitted is a patchset for adding support for variable-length, extended, and
> vendor specific CDBs. It should now cover the entire range of the
> SCSI standard.
>
<snip>
ping James.
I understand that this is the last thing on your mind. But could we at least
agree at the scsi_cmnd API, which is, No API.
That is: scsi_cmnd->cmnd changes to a pointer that can point to a user buffer.
Andrew Hi!
It would be grate if you could put these patches in next -mm for testing.
the first patch in this series has a potential of been dangerous.
Since I changed an embedded array to a pointer, places that did &cmd->cmnd
will no longer work. I have scanned all occurrences of \bcmnd\b but
I might have missed a place.
Thanks
Boaz
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 1/3] Let scsi_cmnd->cmnd use request->cmd buffer
2008-04-15 12:24 ` [PATCH 0/3] scsi: variable-length CDBs support Boaz Harrosh
@ 2008-04-15 12:30 ` Boaz Harrosh
0 siblings, 0 replies; 7+ messages in thread
From: Boaz Harrosh @ 2008-04-15 12:30 UTC (permalink / raw)
To: FUJITA Tomonori, James Bottomley
Cc: linux-scsi, Jens Axboe, Bartlomiej Zolnierkiewicz,
Alasdair G Kergon, Geert Uytterhoeven
- struct scsi_cmnd had a 16 bytes command buffer of its own.
This is an unnecessary duplication and copy of request's
cmd. It is probably left overs from the time that scsi_cmnd
could function without a request attached. So clean that up.
- Once above is done, few places, apart from scsi-ml, needed
adjustments due to changing the data type of scsi_cmnd->cmnd.
- Lots of drivers still use MAX_COMMAND_SIZE. So I have left
that #define but equate it to BLK_MAX_CDB. The way I see it
and is reflected in the patch below is.
MAX_COMMAND_SIZE - means: The longest fixed-length (*) SCSI CDB
as per the SCSI standard and is not related
to the implementation.
BLK_MAX_CDB. - The allocated space at the request level
- I have audit all ISA drivers and made sure none use ->cmnd in a DMA
Operation. Same audit was done by Andi Kleen.
(*)fixed-length here means commands that their size can be determined
by their opcode and the CDB does not carry a length specifier, (unlike
the VARIABLE_LENGTH_CMD(0x7f) command). This is actually not exactly
true and the SCSI standard also defines extended commands and
vendor specific commands that can be bigger than 16 bytes. The kernel
will support these using the same infrastructure used for VARLEN CDB's.
So in effect MAX_COMMAND_SIZE means the maximum size command
scsi-ml supports without specifying a cmd_len by ULD's
Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
---
drivers/firewire/fw-sbp2.c | 2 +-
drivers/s390/scsi/zfcp_dbf.c | 2 +-
drivers/s390/scsi/zfcp_fsf.c | 2 +-
drivers/scsi/53c700.c | 6 +++---
drivers/scsi/a100u2w.c | 2 +-
drivers/scsi/gdth.c | 2 +-
drivers/scsi/hptiop.c | 6 +++---
drivers/scsi/ibmvscsi/ibmvscsi.c | 2 +-
drivers/scsi/initio.c | 2 +-
drivers/scsi/qla1280.c | 4 ++--
drivers/scsi/scsi_error.c | 14 ++++++++------
drivers/scsi/scsi_lib.c | 5 +++--
drivers/scsi/scsi_tgt_lib.c | 2 ++
drivers/usb/storage/isd200.c | 2 ++
include/scsi/scsi_cmnd.h | 21 +++++++++++++++++++--
include/scsi/scsi_eh.h | 4 ++--
16 files changed, 51 insertions(+), 27 deletions(-)
diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c
index 62b4e47..2260e56 100644
--- a/drivers/firewire/fw-sbp2.c
+++ b/drivers/firewire/fw-sbp2.c
@@ -1492,7 +1492,7 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
memset(orb->request.command_block,
0, sizeof(orb->request.command_block));
- memcpy(orb->request.command_block, cmd->cmnd, COMMAND_SIZE(*cmd->cmnd));
+ memcpy(orb->request.command_block, cmd->cmnd, cmd->cmd_len);
orb->base.callback = complete_command_orb;
orb->base.request_bus =
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
index 85ba4cc..1bec0b2 100644
--- a/drivers/s390/scsi/zfcp_dbf.c
+++ b/drivers/s390/scsi/zfcp_dbf.c
@@ -1057,7 +1057,7 @@ static void zfcp_scsi_dbf_event(const char *tag, const char *tag2, int level,
rec->scsi_result = scsi_cmnd->result;
rec->scsi_cmnd = (unsigned long)scsi_cmnd;
rec->scsi_serial = scsi_cmnd->serial_number;
- memcpy(rec->scsi_opcode, &scsi_cmnd->cmnd,
+ memcpy(rec->scsi_opcode, scsi_cmnd->cmnd,
min((int)scsi_cmnd->cmd_len,
ZFCP_DBF_SCSI_OPCODE));
rec->scsi_retries = scsi_cmnd->retries;
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index b7aa969..ea46881 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -4024,7 +4024,7 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req)
ZFCP_LOG_TRACE("scpnt->result =0x%x, command was:\n",
scpnt->result);
ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE,
- (void *) &scpnt->cmnd, scpnt->cmd_len);
+ scpnt->cmnd, scpnt->cmd_len);
ZFCP_LOG_TRACE("%i bytes sense data provided by FCP\n",
fcp_rsp_iu->fcp_sns_len);
diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c
index f4c4fe9..f5a9add 100644
--- a/drivers/scsi/53c700.c
+++ b/drivers/scsi/53c700.c
@@ -599,7 +599,7 @@ NCR_700_scsi_done(struct NCR_700_Host_Parameters *hostdata,
(struct NCR_700_command_slot *)SCp->host_scribble;
dma_unmap_single(hostdata->dev, slot->pCmd,
- sizeof(SCp->cmnd), DMA_TO_DEVICE);
+ MAX_COMMAND_SIZE, DMA_TO_DEVICE);
if (slot->flags == NCR_700_FLAG_AUTOSENSE) {
char *cmnd = NCR_700_get_sense_cmnd(SCp->device);
#ifdef NCR_700_DEBUG
@@ -1004,7 +1004,7 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp,
* here */
NCR_700_unmap(hostdata, SCp, slot);
dma_unmap_single(hostdata->dev, slot->pCmd,
- sizeof(SCp->cmnd),
+ MAX_COMMAND_SIZE,
DMA_TO_DEVICE);
cmnd[0] = REQUEST_SENSE;
@@ -1901,7 +1901,7 @@ NCR_700_queuecommand(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *))
}
slot->resume_offset = 0;
slot->pCmd = dma_map_single(hostdata->dev, SCp->cmnd,
- sizeof(SCp->cmnd), DMA_TO_DEVICE);
+ MAX_COMMAND_SIZE, DMA_TO_DEVICE);
NCR_700_start_command(SCp);
return 0;
}
diff --git a/drivers/scsi/a100u2w.c b/drivers/scsi/a100u2w.c
index 792b2e8..ced3eeb 100644
--- a/drivers/scsi/a100u2w.c
+++ b/drivers/scsi/a100u2w.c
@@ -895,7 +895,7 @@ static void inia100_build_scb(struct orc_host * host, struct orc_scb * scb, stru
} else {
scb->tag_msg = 0; /* No tag support */
}
- memcpy(&scb->cdb[0], &cmd->cmnd, scb->cdb_len);
+ memcpy(scb->cdb, cmd->cmnd, scb->cdb_len);
}
/**
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index c6d6e7c..8e2e964 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -465,7 +465,7 @@ int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd,
scp->request = (struct request *)&wait;
scp->timeout_per_command = timeout*HZ;
scp->cmd_len = 12;
- memcpy(scp->cmnd, cmnd, 12);
+ scp->cmnd = cmnd;
cmndinfo.priority = IOCTL_PRI;
cmndinfo.internal_cmd_str = gdtcmd;
cmndinfo.internal_command = 1;
diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c
index beecda9..a24c5e3 100644
--- a/drivers/scsi/hptiop.c
+++ b/drivers/scsi/hptiop.c
@@ -763,9 +763,9 @@ static int hptiop_queuecommand(struct scsi_cmnd *scp,
scp,
host->host_no, scp->device->channel,
scp->device->id, scp->device->lun,
- *((u32 *)&scp->cmnd),
- *((u32 *)&scp->cmnd + 1),
- *((u32 *)&scp->cmnd + 2),
+ ((u32 *)scp->cmnd)[0],
+ ((u32 *)scp->cmnd)[1],
+ ((u32 *)scp->cmnd)[2],
_req->index, _req->req_virt);
scp->result = 0;
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index 78d46a9..df9b865 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -738,7 +738,7 @@ static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd,
srp_cmd = &evt_struct->iu.srp.cmd;
memset(srp_cmd, 0x00, SRP_MAX_IU_LEN);
srp_cmd->opcode = SRP_CMD;
- memcpy(srp_cmd->cdb, cmnd->cmnd, sizeof(cmnd->cmnd));
+ memcpy(srp_cmd->cdb, cmnd->cmnd, sizeof(srp_cmd->cdb));
srp_cmd->lun = ((u64) lun) << 48;
if (!map_data_for_srp_cmd(cmnd, evt_struct, srp_cmd, hostdata->dev)) {
diff --git a/drivers/scsi/initio.c b/drivers/scsi/initio.c
index dbae3fd..e3f7397 100644
--- a/drivers/scsi/initio.c
+++ b/drivers/scsi/initio.c
@@ -2590,7 +2590,7 @@ static void initio_build_scb(struct initio_host * host, struct scsi_ctrl_blk * c
cblk->hastat = 0;
cblk->tastat = 0;
/* Command the command */
- memcpy(&cblk->cdb[0], &cmnd->cmnd, cmnd->cmd_len);
+ memcpy(cblk->cdb, cmnd->cmnd, cmnd->cmd_len);
/* Set up tags */
if (cmnd->device->tagged_supported) { /* Tag Support */
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
index 68c0d09..b53420b 100644
--- a/drivers/scsi/qla1280.c
+++ b/drivers/scsi/qla1280.c
@@ -2863,7 +2863,7 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
/* Load SCSI command packet. */
pkt->cdb_len = cpu_to_le16(CMD_CDBLEN(cmd));
- memcpy(pkt->scsi_cdb, &(CMD_CDBP(cmd)), CMD_CDBLEN(cmd));
+ memcpy(pkt->scsi_cdb, CMD_CDBP(cmd), CMD_CDBLEN(cmd));
/* dprintk(1, "Build packet for command[0]=0x%x\n",pkt->scsi_cdb[0]); */
/* Set transfer direction. */
@@ -3132,7 +3132,7 @@ qla1280_32bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
/* Load SCSI command packet. */
pkt->cdb_len = cpu_to_le16(CMD_CDBLEN(cmd));
- memcpy(pkt->scsi_cdb, &(CMD_CDBP(cmd)), CMD_CDBLEN(cmd));
+ memcpy(pkt->scsi_cdb, CMD_CDBP(cmd), CMD_CDBLEN(cmd));
/*dprintk(1, "Build packet for command[0]=0x%x\n",pkt->scsi_cdb[0]); */
/* Set transfer direction. */
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 221f31e..8b5748a 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -626,7 +626,7 @@ static void scsi_abort_eh_cmnd(struct scsi_cmnd *scmd)
* @scmd: SCSI command structure to hijack
* @ses: structure to save restore information
* @cmnd: CDB to send. Can be NULL if no new cmnd is needed
- * @cmnd_size: size in bytes of @cmnd
+ * @cmnd_size: size in bytes of @cmnd (must be <= BLK_MAX_CDB)
* @sense_bytes: size of sense data to copy. or 0 (if != 0 @cmnd is ignored)
*
* This function is used to save a scsi command information before re-execution
@@ -648,12 +648,14 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses,
* command.
*/
ses->cmd_len = scmd->cmd_len;
- memcpy(ses->cmnd, scmd->cmnd, sizeof(scmd->cmnd));
+ ses->cmnd = scmd->cmnd;
ses->data_direction = scmd->sc_data_direction;
ses->sdb = scmd->sdb;
ses->next_rq = scmd->request->next_rq;
ses->result = scmd->result;
+ scmd->cmnd = ses->eh_cmnd;
+ memset(scmd->cmnd, 0, BLK_MAX_CDB);
memset(&scmd->sdb, 0, sizeof(scmd->sdb));
scmd->request->next_rq = NULL;
@@ -665,14 +667,13 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses,
scmd->sdb.table.sgl = &ses->sense_sgl;
scmd->sc_data_direction = DMA_FROM_DEVICE;
scmd->sdb.table.nents = 1;
- memset(scmd->cmnd, 0, sizeof(scmd->cmnd));
scmd->cmnd[0] = REQUEST_SENSE;
scmd->cmnd[4] = scmd->sdb.length;
scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
} else {
scmd->sc_data_direction = DMA_NONE;
if (cmnd) {
- memset(scmd->cmnd, 0, sizeof(scmd->cmnd));
+ BUG_ON(cmnd_size > BLK_MAX_CDB);
memcpy(scmd->cmnd, cmnd, cmnd_size);
scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
}
@@ -705,7 +706,7 @@ void scsi_eh_restore_cmnd(struct scsi_cmnd* scmd, struct scsi_eh_save *ses)
* Restore original data
*/
scmd->cmd_len = ses->cmd_len;
- memcpy(scmd->cmnd, ses->cmnd, sizeof(scmd->cmnd));
+ scmd->cmnd = ses->cmnd;
scmd->sc_data_direction = ses->data_direction;
scmd->sdb = ses->sdb;
scmd->request->next_rq = ses->next_rq;
@@ -1774,7 +1775,8 @@ scsi_reset_provider(struct scsi_device *dev, int flag)
scmd->request = &req;
memset(&scmd->eh_timeout, 0, sizeof(scmd->eh_timeout));
- memset(&scmd->cmnd, '\0', sizeof(scmd->cmnd));
+ scmd->cmnd = req.cmd;
+ memset(scmd->cmnd, 0, BLK_MAX_CDB);
scmd->scsi_done = scsi_reset_provider_done_command;
memset(&scmd->sdb, 0, sizeof(scmd->sdb));
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 67f412b..325270b 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -1090,6 +1090,8 @@ static struct scsi_cmnd *scsi_get_cmd_from_req(struct scsi_device *sdev,
cmd->tag = req->tag;
cmd->request = req;
+ cmd->cmnd = req->cmd;
+
return cmd;
}
@@ -1127,8 +1129,6 @@ int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req)
req->buffer = NULL;
}
- BUILD_BUG_ON(sizeof(req->cmd) > sizeof(cmd->cmnd));
- memcpy(cmd->cmnd, req->cmd, sizeof(cmd->cmnd));
cmd->cmd_len = req->cmd_len;
if (!req->data_len)
cmd->sc_data_direction = DMA_NONE;
@@ -1165,6 +1165,7 @@ int scsi_setup_fs_cmnd(struct scsi_device *sdev, struct request *req)
if (unlikely(!cmd))
return BLKPREP_DEFER;
+ memset(cmd->cmnd, 0, BLK_MAX_CDB);
return scsi_init_io(cmd, GFP_ATOMIC);
}
EXPORT_SYMBOL(scsi_setup_fs_cmnd);
diff --git a/drivers/scsi/scsi_tgt_lib.c b/drivers/scsi/scsi_tgt_lib.c
index a0f308b..8c92ef3 100644
--- a/drivers/scsi/scsi_tgt_lib.c
+++ b/drivers/scsi/scsi_tgt_lib.c
@@ -107,6 +107,8 @@ struct scsi_cmnd *scsi_host_get_command(struct Scsi_Host *shost,
cmd->jiffies_at_alloc = jiffies;
cmd->request = rq;
+ cmd->cmnd = rq->cmd;
+
rq->special = cmd;
rq->cmd_type = REQ_TYPE_SPECIAL;
rq->cmd_flags |= REQ_TYPE_BLOCK_PC;
diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c
index 971d13d..3addcd8 100644
--- a/drivers/usb/storage/isd200.c
+++ b/drivers/usb/storage/isd200.c
@@ -292,6 +292,7 @@ struct isd200_info {
/* maximum number of LUNs supported */
unsigned char MaxLUNs;
+ unsigned char cmnd[BLK_MAX_CDB];
struct scsi_cmnd srb;
struct scatterlist sg;
};
@@ -450,6 +451,7 @@ static int isd200_action( struct us_data *us, int action,
memset(&ata, 0, sizeof(ata));
memset(&srb_dev, 0, sizeof(srb_dev));
+ srb->cmnd = info->cmnd;
srb->device = &srb_dev;
++srb->serial_number;
diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
index 8d20e60..dea73e5 100644
--- a/include/scsi/scsi_cmnd.h
+++ b/include/scsi/scsi_cmnd.h
@@ -7,10 +7,28 @@
#include <linux/types.h>
#include <linux/timer.h>
#include <linux/scatterlist.h>
+#include <linux/blkdev.h>
struct Scsi_Host;
struct scsi_device;
+/*
+ * MAX_COMMAND_SIZE is:
+ * The longest fixed-length SCSI CDB as per the SCSI standard.
+ * fixed-length means: commands that their size can be determined
+ * by their opcode and the CDB does not carry a length specifier, (unlike
+ * the VARIABLE_LENGTH_CMD(0x7f) command). This is actually not exactly
+ * true and the SCSI standard also defines extended commands and
+ * vendor specific commands that can be bigger than 16 bytes. The kernel
+ * will support these using the same infrastructure used for VARLEN CDB's.
+ * So in effect MAX_COMMAND_SIZE means the maximum size command scsi-ml
+ * supports without specifying a cmd_len by ULD's
+ */
+#define MAX_COMMAND_SIZE 16
+#if (MAX_COMMAND_SIZE > BLK_MAX_CDB)
+# error MAX_COMMAND_SIZE can not be smaller than BLK_MAX_CDB
+#endif
+
struct scsi_data_buffer {
struct sg_table table;
unsigned length;
@@ -64,8 +82,7 @@ struct scsi_cmnd {
enum dma_data_direction sc_data_direction;
/* These elements define the operation we are about to perform */
-#define MAX_COMMAND_SIZE 16
- unsigned char cmnd[MAX_COMMAND_SIZE];
+ unsigned char *cmnd;
struct timer_list eh_timeout; /* Used to time out the command. */
diff --git a/include/scsi/scsi_eh.h b/include/scsi/scsi_eh.h
index d3a133b..2a9add2 100644
--- a/include/scsi/scsi_eh.h
+++ b/include/scsi/scsi_eh.h
@@ -75,11 +75,11 @@ struct scsi_eh_save {
int result;
enum dma_data_direction data_direction;
unsigned char cmd_len;
- unsigned char cmnd[MAX_COMMAND_SIZE];
+ unsigned char *cmnd;
struct scsi_data_buffer sdb;
struct request *next_rq;
-
/* new command support */
+ unsigned char eh_cmnd[BLK_MAX_CDB];
struct scatterlist sense_sgl;
};
--
1.5.3.3
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 1/3] Let scsi_cmnd->cmnd use request->cmd buffer
2008-04-30 8:13 [PATCH 3/3] scsi support variable length commands Boaz Harrosh
@ 2008-04-30 8:19 ` Boaz Harrosh
0 siblings, 0 replies; 7+ messages in thread
From: Boaz Harrosh @ 2008-04-30 8:19 UTC (permalink / raw)
To: James Bottomley, Mike Christie, linux-scsi
Cc: Matthew Dharm, matthieu castet, FUJITA Tomonori
- struct scsi_cmnd had a 16 bytes command buffer of its own.
This is an unnecessary duplication and copy of request's
cmd. It is probably left overs from the time that scsi_cmnd
could function without a request attached. So clean that up.
- Once above is done, few places, apart from scsi-ml, needed
adjustments due to changing the data type of scsi_cmnd->cmnd.
- Lots of drivers still use MAX_COMMAND_SIZE. So I have left
that #define but equate it to BLK_MAX_CDB. The way I see it
and is reflected in the patch below is.
MAX_COMMAND_SIZE - means: The longest fixed-length (*) SCSI CDB
as per the SCSI standard and is not related
to the implementation.
BLK_MAX_CDB. - The allocated space at the request level
- I have audit all ISA drivers and made sure none use ->cmnd in a DMA
Operation. Same audit was done by Andi Kleen.
(*)fixed-length here means commands that their size can be determined
by their opcode and the CDB does not carry a length specifier, (unlike
the VARIABLE_LENGTH_CMD(0x7f) command). This is actually not exactly
true and the SCSI standard also defines extended commands and
vendor specific commands that can be bigger than 16 bytes. The kernel
will support these using the same infrastructure used for VARLEN CDB's.
So in effect MAX_COMMAND_SIZE means the maximum size command
scsi-ml supports without specifying a cmd_len by ULD's
Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
---
drivers/firewire/fw-sbp2.c | 2 +-
drivers/s390/scsi/zfcp_dbf.c | 2 +-
drivers/s390/scsi/zfcp_fsf.c | 2 +-
drivers/scsi/53c700.c | 6 +++---
drivers/scsi/a100u2w.c | 2 +-
drivers/scsi/gdth.c | 2 +-
drivers/scsi/hptiop.c | 6 +++---
drivers/scsi/ibmvscsi/ibmvscsi.c | 2 +-
drivers/scsi/initio.c | 2 +-
drivers/scsi/qla1280.c | 4 ++--
drivers/scsi/scsi_error.c | 15 ++++++++-------
drivers/scsi/scsi_lib.c | 5 +++--
drivers/scsi/scsi_tgt_lib.c | 2 ++
drivers/usb/storage/cypress_atacb.c | 2 +-
drivers/usb/storage/isd200.c | 2 ++
include/scsi/scsi_cmnd.h | 21 +++++++++++++++++++--
include/scsi/scsi_eh.h | 4 ++--
17 files changed, 52 insertions(+), 29 deletions(-)
diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c
index 2a99937..dda82f3 100644
--- a/drivers/firewire/fw-sbp2.c
+++ b/drivers/firewire/fw-sbp2.c
@@ -1487,7 +1487,7 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
if (scsi_sg_count(cmd) && sbp2_map_scatterlist(orb, device, lu) < 0)
goto out;
- memcpy(orb->request.command_block, cmd->cmnd, COMMAND_SIZE(*cmd->cmnd));
+ memcpy(orb->request.command_block, cmd->cmnd, cmd->cmd_len);
orb->base.callback = complete_command_orb;
orb->base.request_bus =
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
index 37b85c6..c8bad67 100644
--- a/drivers/s390/scsi/zfcp_dbf.c
+++ b/drivers/s390/scsi/zfcp_dbf.c
@@ -1055,7 +1055,7 @@ static void zfcp_scsi_dbf_event(const char *tag, const char *tag2, int level,
rec->scsi_result = scsi_cmnd->result;
rec->scsi_cmnd = (unsigned long)scsi_cmnd;
rec->scsi_serial = scsi_cmnd->serial_number;
- memcpy(rec->scsi_opcode, &scsi_cmnd->cmnd,
+ memcpy(rec->scsi_opcode, scsi_cmnd->cmnd,
min((int)scsi_cmnd->cmd_len,
ZFCP_DBF_SCSI_OPCODE));
rec->scsi_retries = scsi_cmnd->retries;
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 9af2330..b2ea4ea 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -4014,7 +4014,7 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req)
ZFCP_LOG_TRACE("scpnt->result =0x%x, command was:\n",
scpnt->result);
ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE,
- (void *) &scpnt->cmnd, scpnt->cmd_len);
+ scpnt->cmnd, scpnt->cmd_len);
ZFCP_LOG_TRACE("%i bytes sense data provided by FCP\n",
fcp_rsp_iu->fcp_sns_len);
diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c
index f4c4fe9..f5a9add 100644
--- a/drivers/scsi/53c700.c
+++ b/drivers/scsi/53c700.c
@@ -599,7 +599,7 @@ NCR_700_scsi_done(struct NCR_700_Host_Parameters *hostdata,
(struct NCR_700_command_slot *)SCp->host_scribble;
dma_unmap_single(hostdata->dev, slot->pCmd,
- sizeof(SCp->cmnd), DMA_TO_DEVICE);
+ MAX_COMMAND_SIZE, DMA_TO_DEVICE);
if (slot->flags == NCR_700_FLAG_AUTOSENSE) {
char *cmnd = NCR_700_get_sense_cmnd(SCp->device);
#ifdef NCR_700_DEBUG
@@ -1004,7 +1004,7 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp,
* here */
NCR_700_unmap(hostdata, SCp, slot);
dma_unmap_single(hostdata->dev, slot->pCmd,
- sizeof(SCp->cmnd),
+ MAX_COMMAND_SIZE,
DMA_TO_DEVICE);
cmnd[0] = REQUEST_SENSE;
@@ -1901,7 +1901,7 @@ NCR_700_queuecommand(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *))
}
slot->resume_offset = 0;
slot->pCmd = dma_map_single(hostdata->dev, SCp->cmnd,
- sizeof(SCp->cmnd), DMA_TO_DEVICE);
+ MAX_COMMAND_SIZE, DMA_TO_DEVICE);
NCR_700_start_command(SCp);
return 0;
}
diff --git a/drivers/scsi/a100u2w.c b/drivers/scsi/a100u2w.c
index 792b2e8..ced3eeb 100644
--- a/drivers/scsi/a100u2w.c
+++ b/drivers/scsi/a100u2w.c
@@ -895,7 +895,7 @@ static void inia100_build_scb(struct orc_host * host, struct orc_scb * scb, stru
} else {
scb->tag_msg = 0; /* No tag support */
}
- memcpy(&scb->cdb[0], &cmd->cmnd, scb->cdb_len);
+ memcpy(scb->cdb, cmd->cmnd, scb->cdb_len);
}
/**
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index c6d6e7c..8e2e964 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -465,7 +465,7 @@ int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd,
scp->request = (struct request *)&wait;
scp->timeout_per_command = timeout*HZ;
scp->cmd_len = 12;
- memcpy(scp->cmnd, cmnd, 12);
+ scp->cmnd = cmnd;
cmndinfo.priority = IOCTL_PRI;
cmndinfo.internal_cmd_str = gdtcmd;
cmndinfo.internal_command = 1;
diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c
index 5b7be1e..aaa48e0 100644
--- a/drivers/scsi/hptiop.c
+++ b/drivers/scsi/hptiop.c
@@ -763,9 +763,9 @@ static int hptiop_queuecommand(struct scsi_cmnd *scp,
scp,
host->host_no, scp->device->channel,
scp->device->id, scp->device->lun,
- *((u32 *)&scp->cmnd),
- *((u32 *)&scp->cmnd + 1),
- *((u32 *)&scp->cmnd + 2),
+ ((u32 *)scp->cmnd)[0],
+ ((u32 *)scp->cmnd)[1],
+ ((u32 *)scp->cmnd)[2],
_req->index, _req->req_virt);
scp->result = 0;
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index 4a922c5..dd8c716 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -738,7 +738,7 @@ static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd,
srp_cmd = &evt_struct->iu.srp.cmd;
memset(srp_cmd, 0x00, SRP_MAX_IU_LEN);
srp_cmd->opcode = SRP_CMD;
- memcpy(srp_cmd->cdb, cmnd->cmnd, sizeof(cmnd->cmnd));
+ memcpy(srp_cmd->cdb, cmnd->cmnd, sizeof(srp_cmd->cdb));
srp_cmd->lun = ((u64) lun) << 48;
if (!map_data_for_srp_cmd(cmnd, evt_struct, srp_cmd, hostdata->dev)) {
diff --git a/drivers/scsi/initio.c b/drivers/scsi/initio.c
index dbae3fd..e3f7397 100644
--- a/drivers/scsi/initio.c
+++ b/drivers/scsi/initio.c
@@ -2590,7 +2590,7 @@ static void initio_build_scb(struct initio_host * host, struct scsi_ctrl_blk * c
cblk->hastat = 0;
cblk->tastat = 0;
/* Command the command */
- memcpy(&cblk->cdb[0], &cmnd->cmnd, cmnd->cmd_len);
+ memcpy(cblk->cdb, cmnd->cmnd, cmnd->cmd_len);
/* Set up tags */
if (cmnd->device->tagged_supported) { /* Tag Support */
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
index 09ab3ea..fa06093 100644
--- a/drivers/scsi/qla1280.c
+++ b/drivers/scsi/qla1280.c
@@ -2858,7 +2858,7 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
/* Load SCSI command packet. */
pkt->cdb_len = cpu_to_le16(CMD_CDBLEN(cmd));
- memcpy(pkt->scsi_cdb, &(CMD_CDBP(cmd)), CMD_CDBLEN(cmd));
+ memcpy(pkt->scsi_cdb, CMD_CDBP(cmd), CMD_CDBLEN(cmd));
/* dprintk(1, "Build packet for command[0]=0x%x\n",pkt->scsi_cdb[0]); */
/* Set transfer direction. */
@@ -3127,7 +3127,7 @@ qla1280_32bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
/* Load SCSI command packet. */
pkt->cdb_len = cpu_to_le16(CMD_CDBLEN(cmd));
- memcpy(pkt->scsi_cdb, &(CMD_CDBP(cmd)), CMD_CDBLEN(cmd));
+ memcpy(pkt->scsi_cdb, CMD_CDBP(cmd), CMD_CDBLEN(cmd));
/*dprintk(1, "Build packet for command[0]=0x%x\n",pkt->scsi_cdb[0]); */
/* Set transfer direction. */
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 1eaba6c..eaf5a8a 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -626,7 +626,7 @@ static void scsi_abort_eh_cmnd(struct scsi_cmnd *scmd)
* @scmd: SCSI command structure to hijack
* @ses: structure to save restore information
* @cmnd: CDB to send. Can be NULL if no new cmnd is needed
- * @cmnd_size: size in bytes of @cmnd
+ * @cmnd_size: size in bytes of @cmnd (must be <= BLK_MAX_CDB)
* @sense_bytes: size of sense data to copy. or 0 (if != 0 @cmnd is ignored)
*
* This function is used to save a scsi command information before re-execution
@@ -648,12 +648,14 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses,
* command.
*/
ses->cmd_len = scmd->cmd_len;
- memcpy(ses->cmnd, scmd->cmnd, sizeof(scmd->cmnd));
+ ses->cmnd = scmd->cmnd;
ses->data_direction = scmd->sc_data_direction;
ses->sdb = scmd->sdb;
ses->next_rq = scmd->request->next_rq;
ses->result = scmd->result;
+ scmd->cmnd = ses->eh_cmnd;
+ memset(scmd->cmnd, 0, BLK_MAX_CDB);
memset(&scmd->sdb, 0, sizeof(scmd->sdb));
scmd->request->next_rq = NULL;
@@ -665,14 +667,13 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses,
scmd->sdb.table.sgl = &ses->sense_sgl;
scmd->sc_data_direction = DMA_FROM_DEVICE;
scmd->sdb.table.nents = 1;
- memset(scmd->cmnd, 0, sizeof(scmd->cmnd));
scmd->cmnd[0] = REQUEST_SENSE;
scmd->cmnd[4] = scmd->sdb.length;
scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
} else {
scmd->sc_data_direction = DMA_NONE;
if (cmnd) {
- memset(scmd->cmnd, 0, sizeof(scmd->cmnd));
+ BUG_ON(cmnd_size > BLK_MAX_CDB);
memcpy(scmd->cmnd, cmnd, cmnd_size);
scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
}
@@ -705,7 +706,7 @@ void scsi_eh_restore_cmnd(struct scsi_cmnd* scmd, struct scsi_eh_save *ses)
* Restore original data
*/
scmd->cmd_len = ses->cmd_len;
- memcpy(scmd->cmnd, ses->cmnd, sizeof(scmd->cmnd));
+ scmd->cmnd = ses->cmnd;
scmd->sc_data_direction = ses->data_direction;
scmd->sdb = ses->sdb;
scmd->request->next_rq = ses->next_rq;
@@ -1775,8 +1776,8 @@ scsi_reset_provider(struct scsi_device *dev, int flag)
scmd->request = &req;
memset(&scmd->eh_timeout, 0, sizeof(scmd->eh_timeout));
- memset(&scmd->cmnd, '\0', sizeof(scmd->cmnd));
-
+ scmd->cmnd = req.cmd;
+
scmd->scsi_done = scsi_reset_provider_done_command;
memset(&scmd->sdb, 0, sizeof(scmd->sdb));
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index d545ad1..a709849 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -1094,6 +1094,8 @@ static struct scsi_cmnd *scsi_get_cmd_from_req(struct scsi_device *sdev,
cmd->tag = req->tag;
cmd->request = req;
+ cmd->cmnd = req->cmd;
+
return cmd;
}
@@ -1131,8 +1133,6 @@ int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req)
req->buffer = NULL;
}
- BUILD_BUG_ON(sizeof(req->cmd) > sizeof(cmd->cmnd));
- memcpy(cmd->cmnd, req->cmd, sizeof(cmd->cmnd));
cmd->cmd_len = req->cmd_len;
if (!req->data_len)
cmd->sc_data_direction = DMA_NONE;
@@ -1169,6 +1169,7 @@ int scsi_setup_fs_cmnd(struct scsi_device *sdev, struct request *req)
if (unlikely(!cmd))
return BLKPREP_DEFER;
+ memset(cmd->cmnd, 0, BLK_MAX_CDB);
return scsi_init_io(cmd, GFP_ATOMIC);
}
EXPORT_SYMBOL(scsi_setup_fs_cmnd);
diff --git a/drivers/scsi/scsi_tgt_lib.c b/drivers/scsi/scsi_tgt_lib.c
index ee8496a..257e097 100644
--- a/drivers/scsi/scsi_tgt_lib.c
+++ b/drivers/scsi/scsi_tgt_lib.c
@@ -107,6 +107,8 @@ struct scsi_cmnd *scsi_host_get_command(struct Scsi_Host *shost,
cmd->jiffies_at_alloc = jiffies;
cmd->request = rq;
+ cmd->cmnd = rq->cmd;
+
rq->special = cmd;
rq->cmd_type = REQ_TYPE_SPECIAL;
rq->cmd_flags |= REQ_TYPE_BLOCK_PC;
diff --git a/drivers/usb/storage/cypress_atacb.c b/drivers/usb/storage/cypress_atacb.c
index d88824b..898e67d 100644
--- a/drivers/usb/storage/cypress_atacb.c
+++ b/drivers/usb/storage/cypress_atacb.c
@@ -46,7 +46,7 @@ void cypress_atacb_passthrough(struct scsi_cmnd *srb, struct us_data *us)
}
memcpy(save_cmnd, srb->cmnd, sizeof(save_cmnd));
- memset(srb->cmnd, 0, sizeof(srb->cmnd));
+ memset(srb->cmnd, 0, MAX_COMMAND_SIZE);
/* check if we support the command */
if (save_cmnd[1] >> 5) /* MULTIPLE_COUNT */
diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c
index 971d13d..3addcd8 100644
--- a/drivers/usb/storage/isd200.c
+++ b/drivers/usb/storage/isd200.c
@@ -292,6 +292,7 @@ struct isd200_info {
/* maximum number of LUNs supported */
unsigned char MaxLUNs;
+ unsigned char cmnd[BLK_MAX_CDB];
struct scsi_cmnd srb;
struct scatterlist sg;
};
@@ -450,6 +451,7 @@ static int isd200_action( struct us_data *us, int action,
memset(&ata, 0, sizeof(ata));
memset(&srb_dev, 0, sizeof(srb_dev));
+ srb->cmnd = info->cmnd;
srb->device = &srb_dev;
++srb->serial_number;
diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
index 8d20e60..7ed883c 100644
--- a/include/scsi/scsi_cmnd.h
+++ b/include/scsi/scsi_cmnd.h
@@ -7,10 +7,28 @@
#include <linux/types.h>
#include <linux/timer.h>
#include <linux/scatterlist.h>
+#include <linux/blkdev.h>
struct Scsi_Host;
struct scsi_device;
+/*
+ * MAX_COMMAND_SIZE is:
+ * The longest fixed-length SCSI CDB as per the SCSI standard.
+ * fixed-length means: commands that their size can be determined
+ * by their opcode and the CDB does not carry a length specifier, (unlike
+ * the VARIABLE_LENGTH_CMD(0x7f) command). This is actually not exactly
+ * true and the SCSI standard also defines extended commands and
+ * vendor specific commands that can be bigger than 16 bytes. The kernel
+ * will support these using the same infrastructure used for VARLEN CDB's.
+ * So in effect MAX_COMMAND_SIZE means the maximum size command scsi-ml
+ * supports without specifying a cmd_len by ULD's
+ */
+#define MAX_COMMAND_SIZE 16
+#if (MAX_COMMAND_SIZE > BLK_MAX_CDB)
+# error MAX_COMMAND_SIZE can not be bigger than BLK_MAX_CDB
+#endif
+
struct scsi_data_buffer {
struct sg_table table;
unsigned length;
@@ -64,8 +82,7 @@ struct scsi_cmnd {
enum dma_data_direction sc_data_direction;
/* These elements define the operation we are about to perform */
-#define MAX_COMMAND_SIZE 16
- unsigned char cmnd[MAX_COMMAND_SIZE];
+ unsigned char *cmnd;
struct timer_list eh_timeout; /* Used to time out the command. */
diff --git a/include/scsi/scsi_eh.h b/include/scsi/scsi_eh.h
index d3a133b..2a9add2 100644
--- a/include/scsi/scsi_eh.h
+++ b/include/scsi/scsi_eh.h
@@ -75,11 +75,11 @@ struct scsi_eh_save {
int result;
enum dma_data_direction data_direction;
unsigned char cmd_len;
- unsigned char cmnd[MAX_COMMAND_SIZE];
+ unsigned char *cmnd;
struct scsi_data_buffer sdb;
struct request *next_rq;
-
/* new command support */
+ unsigned char eh_cmnd[BLK_MAX_CDB];
struct scatterlist sense_sgl;
};
--
1.5.3.3
^ permalink raw reply related [flat|nested] 7+ messages in thread
end of thread, other threads:[~2008-04-30 8:24 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-12-18 13:33 [PATCHSET 0/3] varlen extended and vendor-specific cdbs Boaz Harrosh
2007-12-18 13:38 ` [PATCH 1/3] Let scsi_cmnd->cmnd use request->cmd buffer Boaz Harrosh
2007-12-18 13:42 ` [PATCH 2/2] block layer varlen-cdb Boaz Harrosh
2007-12-18 13:45 ` [PATCH 3/3] scsi: varlen extended and vendor-specific cdbs Boaz Harrosh
2007-12-20 19:39 ` [PATCHSET 0/3] " Boaz Harrosh
-- strict thread matches above, loose matches on Subject: below --
2008-04-13 16:17 [PATCH 2/3 ver2] block layer extended-cdb support FUJITA Tomonori
2008-04-14 10:50 ` [PATCH 0/4] add large command support to the block layer FUJITA Tomonori
2008-04-15 12:24 ` [PATCH 0/3] scsi: variable-length CDBs support Boaz Harrosh
2008-04-15 12:30 ` [PATCH 1/3] Let scsi_cmnd->cmnd use request->cmd buffer Boaz Harrosh
2008-04-30 8:13 [PATCH 3/3] scsi support variable length commands Boaz Harrosh
2008-04-30 8:19 ` [PATCH 1/3] Let scsi_cmnd->cmnd use request->cmd buffer Boaz Harrosh
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).