[SCSI] iscsi: extended cdb support
Support for extended CDBs in iscsi. All we need is to check if command spills over 16 bytes then allocate an iscsi-extended-header for the leftovers. Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> Reviewed-by: Pete Wyckoff <pw@osc.edu> Signed-off-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
This commit is contained in:
parent
57b7658aed
commit
38d1c069db
2 changed files with 54 additions and 7 deletions
|
@ -137,6 +137,45 @@ static int iscsi_add_hdr(struct iscsi_cmd_task *ctask, unsigned len)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* make an extended cdb AHS
|
||||||
|
*/
|
||||||
|
static int iscsi_prep_ecdb_ahs(struct iscsi_cmd_task *ctask)
|
||||||
|
{
|
||||||
|
struct scsi_cmnd *cmd = ctask->sc;
|
||||||
|
unsigned rlen, pad_len;
|
||||||
|
unsigned short ahslength;
|
||||||
|
struct iscsi_ecdb_ahdr *ecdb_ahdr;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
ecdb_ahdr = iscsi_next_hdr(ctask);
|
||||||
|
rlen = cmd->cmd_len - ISCSI_CDB_SIZE;
|
||||||
|
|
||||||
|
BUG_ON(rlen > sizeof(ecdb_ahdr->ecdb));
|
||||||
|
ahslength = rlen + sizeof(ecdb_ahdr->reserved);
|
||||||
|
|
||||||
|
pad_len = iscsi_padding(rlen);
|
||||||
|
|
||||||
|
rc = iscsi_add_hdr(ctask, sizeof(ecdb_ahdr->ahslength) +
|
||||||
|
sizeof(ecdb_ahdr->ahstype) + ahslength + pad_len);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
if (pad_len)
|
||||||
|
memset(&ecdb_ahdr->ecdb[rlen], 0, pad_len);
|
||||||
|
|
||||||
|
ecdb_ahdr->ahslength = cpu_to_be16(ahslength);
|
||||||
|
ecdb_ahdr->ahstype = ISCSI_AHSTYPE_CDB;
|
||||||
|
ecdb_ahdr->reserved = 0;
|
||||||
|
memcpy(ecdb_ahdr->ecdb, cmd->cmnd + ISCSI_CDB_SIZE, rlen);
|
||||||
|
|
||||||
|
debug_scsi("iscsi_prep_ecdb_ahs: varlen_cdb_len %d "
|
||||||
|
"rlen %d pad_len %d ahs_length %d iscsi_headers_size %u\n",
|
||||||
|
cmd->cmd_len, rlen, pad_len, ahslength, ctask->hdr_len);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* iscsi_prep_scsi_cmd_pdu - prep iscsi scsi cmd pdu
|
* iscsi_prep_scsi_cmd_pdu - prep iscsi scsi cmd pdu
|
||||||
* @ctask: iscsi cmd task
|
* @ctask: iscsi cmd task
|
||||||
|
@ -150,7 +189,7 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
|
||||||
struct iscsi_session *session = conn->session;
|
struct iscsi_session *session = conn->session;
|
||||||
struct iscsi_cmd *hdr = ctask->hdr;
|
struct iscsi_cmd *hdr = ctask->hdr;
|
||||||
struct scsi_cmnd *sc = ctask->sc;
|
struct scsi_cmnd *sc = ctask->sc;
|
||||||
unsigned hdrlength;
|
unsigned hdrlength, cmd_len;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
ctask->hdr_len = 0;
|
ctask->hdr_len = 0;
|
||||||
|
@ -165,10 +204,16 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
|
||||||
hdr->cmdsn = cpu_to_be32(session->cmdsn);
|
hdr->cmdsn = cpu_to_be32(session->cmdsn);
|
||||||
session->cmdsn++;
|
session->cmdsn++;
|
||||||
hdr->exp_statsn = cpu_to_be32(conn->exp_statsn);
|
hdr->exp_statsn = cpu_to_be32(conn->exp_statsn);
|
||||||
memcpy(hdr->cdb, sc->cmnd, sc->cmd_len);
|
cmd_len = sc->cmd_len;
|
||||||
if (sc->cmd_len < MAX_COMMAND_SIZE)
|
if (cmd_len < ISCSI_CDB_SIZE)
|
||||||
memset(&hdr->cdb[sc->cmd_len], 0,
|
memset(&hdr->cdb[cmd_len], 0, ISCSI_CDB_SIZE - cmd_len);
|
||||||
MAX_COMMAND_SIZE - sc->cmd_len);
|
else if (cmd_len > ISCSI_CDB_SIZE) {
|
||||||
|
rc = iscsi_prep_ecdb_ahs(ctask);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
cmd_len = ISCSI_CDB_SIZE;
|
||||||
|
}
|
||||||
|
memcpy(hdr->cdb, sc->cmnd, cmd_len);
|
||||||
|
|
||||||
ctask->imm_count = 0;
|
ctask->imm_count = 0;
|
||||||
if (sc->sc_data_direction == DMA_TO_DEVICE) {
|
if (sc->sc_data_direction == DMA_TO_DEVICE) {
|
||||||
|
|
|
@ -112,6 +112,7 @@ struct iscsi_ahs_hdr {
|
||||||
|
|
||||||
#define ISCSI_AHSTYPE_CDB 1
|
#define ISCSI_AHSTYPE_CDB 1
|
||||||
#define ISCSI_AHSTYPE_RLENGTH 2
|
#define ISCSI_AHSTYPE_RLENGTH 2
|
||||||
|
#define ISCSI_CDB_SIZE 16
|
||||||
|
|
||||||
/* iSCSI PDU Header */
|
/* iSCSI PDU Header */
|
||||||
struct iscsi_cmd {
|
struct iscsi_cmd {
|
||||||
|
@ -125,7 +126,7 @@ struct iscsi_cmd {
|
||||||
__be32 data_length;
|
__be32 data_length;
|
||||||
__be32 cmdsn;
|
__be32 cmdsn;
|
||||||
__be32 exp_statsn;
|
__be32 exp_statsn;
|
||||||
uint8_t cdb[16]; /* SCSI Command Block */
|
uint8_t cdb[ISCSI_CDB_SIZE]; /* SCSI Command Block */
|
||||||
/* Additional Data (Command Dependent) */
|
/* Additional Data (Command Dependent) */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -154,7 +155,8 @@ struct iscsi_ecdb_ahdr {
|
||||||
__be16 ahslength; /* CDB length - 15, including reserved byte */
|
__be16 ahslength; /* CDB length - 15, including reserved byte */
|
||||||
uint8_t ahstype;
|
uint8_t ahstype;
|
||||||
uint8_t reserved;
|
uint8_t reserved;
|
||||||
uint8_t ecdb[260 - 16]; /* 4-byte aligned extended CDB spillover */
|
/* 4-byte aligned extended CDB spillover */
|
||||||
|
uint8_t ecdb[260 - ISCSI_CDB_SIZE];
|
||||||
};
|
};
|
||||||
|
|
||||||
/* SCSI Response Header */
|
/* SCSI Response Header */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue