bidi support: varlen + OSD support
Subsystems (2)
RFC 5/6 bidi support: varlen + OSD support
- Add support for varlen CDBs or large vendor specific commands in struct request.
- Add support for above at SCSI level API's and devices.
- Add the OSD device type.
Signed-off-by Benny Halevy <[email protected]>
Signed-off-by Boaz Harrosh <[email protected]>
--- block/ll_rw_blk.c | 2 ++ drivers/scsi/scsi.c | 11 ++++++++--- drivers/scsi/scsi_debug.c | 6 +++++- drivers/scsi/scsi_lib.c | 24 +++++++++++++++++++++--- drivers/scsi/scsi_scan.c | 1 + include/linux/blkdev.h | 6 ++++++ include/scsi/scsi.h | 2 ++ include/scsi/scsi_cmnd.h | 20 +++++++++++++++++++- include/scsi/scsi_host.h | 8 +++----- 9 files changed, 67 insertions(+), 13 deletions(-)
block/ll_rw_blk.c +2 -0
@@ -256,6 +256,8 @@ static void rq_init(request_queue_t *q, rq->q = q; rq->special =NULL ; rq->data =NULL ; + rq->varlen_cdb_len =0 ; + rq->varlen_cdb =NULL ; rq->sense =NULL ; rq->end_io =NULL ; rq->end_io_data =NULL ;
drivers/scsi/scsi.c +8 -3
@@ -485,6 +485,7 @@ int scsi_dispatch_cmd(struct scsi_cmnd *unsigned long flags =0 ;unsigned long timeout;int rtn =0 ; +int cdb_size;/* check if the device is still usable */ if (unlikely (cmd->device->sdev_state ==SDEV_DEL )) {
@@ -566,9 +567,13 @@ int scsi_dispatch_cmd(struct scsi_cmnd ** 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) { -SCSI_LOG_MLQUEUE (3 , -printk ("queuecommand : command too long.\n" )); + cdb_size = cmd->request->varlen_cdb ? + cmd->request->varlen_cdb_len :COMMAND_SIZE (cmd->cmnd[0 ]); +if (cdb_size > cmd->device->host->max_cmd_len) { +SCSI_LOG_MLQUEUE (0 , +printk ("queuecommand : command too long. " +"cdb_size(%d) host->max_cmd_len(%d)\n" , + cdb_size, cmd->device->host->max_cmd_len)); cmd->result = (DID_ABORT <<16 );scsi_done (cmd);
drivers/scsi/scsi_debug.c +5 -1
@@ -1993,8 +1993,12 @@ static int scsi_debug_slave_configure(stif (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)printk (KERN_INFO "scsi_debug: slave_configure <%u %u %u %u>\n" , sdp->host->host_no, sdp->channel, sdp->id, sdp->lun); -if (sdp->host->max_cmd_len !=SCSI_DEBUG_MAX_CMD_LEN ) +if (sdp->host->max_cmd_len <SCSI_DEBUG_MAX_CMD_LEN ) { +printk (KERN_INFO +"scsi_debug: max_cmd_len(%d) < SCSI_DEBUG_MAX_CMD_LEN\n" , + sdp->host->max_cmd_len); sdp->host->max_cmd_len =SCSI_DEBUG_MAX_CMD_LEN ; + } devip =devInfoReg (sdp); sdp->hostdata = devip;if (sdp->host->cmd_per_lun)
drivers/scsi/scsi_lib.c +21 -3
@@ -189,8 +189,17 @@ int scsi_execute(struct scsi_device *sde buffer, bufflen, __GFP_WAIT)) goto out; - req->cmd_len =COMMAND_SIZE (cmd[0 ]); +if (cmd[0 ] ==VARLEN_CDB ) { + req->varlen_cdb_len =scsi_varlen_cdb_length (cmd); + req->varlen_cdb = (unsigned char *)cmd;/* varlen cmd is pointed to */ + } + req->cmd_len =min ( + req->varlen_cdb_len ? req->varlen_cdb_len :COMMAND_SIZE (cmd[0 ]), +MAX_COMMAND_SIZE );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;
@@ -452,8 +461,6 @@ int scsi_execute_bidi_async(struct scsi_if (err) goto free_req; - req->cmd_len = cmd_len; -memset (req->cmd,0 ,BLK_MAX_CDB );/* ATAPI hates garbage after CDB */ if (is_bidi) {if (bidi_read_buff->use_sg) err = scsi_req_map_sg(
@@ -469,7 +476,18 @@ int scsi_execute_bidi_async(struct scsi_ } } +BUG_ON ( (cmd[0 ]==VARLEN_CDB ) && (scsi_varlen_cdb_length (cmd) > cmd_len) ); +/* Unlike scsi_excute, scsi_execute_bidi_xxx supports big commands that are not VARLEN_CDB */ +if ((cmd[0 ] ==VARLEN_CDB ) || (cmd_len >MAX_COMMAND_SIZE )) { + req->varlen_cdb_len = cmd_len; + req->varlen_cdb = cmd; + } + req->cmd_len =min ( cmd_len ? cmd_len :COMMAND_SIZE (cmd[0 ]), +MAX_COMMAND_SIZE );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 = sioc->sense; req->sense_len =0 ; req->timeout = timeout;
drivers/scsi/scsi_scan.c +1 -0
@@ -750,6 +750,7 @@ static int scsi_add_lun(struct scsi_devicase TYPE_COMM :case TYPE_RAID :case TYPE_RBC : +case TYPE_OSD : sdev->writeable =1 ;break ;case TYPE_WORM :
include/linux/blkdev.h +6 -0
@@ -294,6 +294,7 @@ struct request {unsigned long start_time;unsigned short ioprio; +unsigned short varlen_cdb_len;/* length of varlen_cdb buffer */ void *special;char *buffer;/* FIXME: should be Deprecated */
@@ -309,6 +310,11 @@ struct request {*/ unsigned int cmd_len;unsigned char cmd[BLK_MAX_CDB ]; +unsigned char *varlen_cdb;/* an optional variable-length cdb. +* first 16 bytes are copied also into cmd[]. +* points to a user buffer that must be valid +* until end of request +*/ unsigned int sense_len;void *sense;
include/scsi/scsi.h +2 -0
@@ -96,6 +96,7 @@ #define RELEASE_10 0x57#define MODE_SENSE_10 0x5a#define PERSISTENT_RESERVE_IN 0x5e#define PERSISTENT_RESERVE_OUT 0x5f +#define VARLEN_CDB 0x7f#define REPORT_LUNS 0xa0#define MAINTENANCE_IN 0xa3#define MOVE_MEDIUM 0xa5
@@ -219,6 +220,7 @@ #define TYPE_COMM 0x09 /* C#define TYPE_RAID 0x0c#define TYPE_ENCLOSURE 0x0d/* Enclosure Services Device */ #define TYPE_RBC 0x0e +#define TYPE_OSD 0x11#define TYPE_NO_LUN 0x7f/* Returns a human-readable name for the device */
include/scsi/scsi_cmnd.h +19 -1
@@ -11,6 +11,24 @@ struct scatterlist;struct Scsi_Host ;struct scsi_device ; +#define SCSI_MAX_VARLEN_CDB_LEN 260 + +/* defined in T10 SCSI Primary Commands-3 */ +struct scsi_varlen_cdb_hdr { +unsigned char opcode;/* opcode always == VARLEN_CDB */ +unsigned char control; +unsigned char misc[5 ]; +unsigned char additional_cdb_length;/* total cdb length - 8 */ +unsigned char service_action[2 ]; +/* service specific data follows */ +}; + +static inline int +scsi_varlen_cdb_length (const void *hdr) +{ +return ((struct scsi_varlen_cdb_hdr *)hdr)->additional_cdb_length +8 ; +} +/* * This structure maps data buffers into a scatter-gather list for DMA purposes. * Embedded in struct scsi_cmnd.
@@ -76,7 +94,7 @@ struct scsi_cmnd {int allowed;int timeout_per_command; -unsigned char cmd_len; +unsigned char cmd_len;/* fixed cdb command length (<= 16) */ enum dma_data_direction sc_data_direction;/* These elements define the operation we are about to perform */
include/scsi/scsi_host.h +3 -5
@@ -559,13 +559,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;