Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 38d1c069 authored by Boaz Harrosh's avatar Boaz Harrosh Committed by James Bottomley
Browse files

[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: default avatarBoaz Harrosh <bharrosh@panasas.com>
Reviewed-by: default avatarPete Wyckoff <pw@osc.edu>
Signed-off-by: default avatarMike Christie <michaelc@cs.wisc.edu>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@HansenPartnership.com>
parent 57b7658a
Loading
Loading
Loading
Loading
+50 −5
Original line number Diff line number Diff line
@@ -137,6 +137,45 @@ static int iscsi_add_hdr(struct iscsi_cmd_task *ctask, unsigned len)
	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
 * @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_cmd *hdr = ctask->hdr;
	struct scsi_cmnd *sc = ctask->sc;
	unsigned hdrlength;
	unsigned hdrlength, cmd_len;
	int rc;

	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);
	session->cmdsn++;
	hdr->exp_statsn = cpu_to_be32(conn->exp_statsn);
	memcpy(hdr->cdb, sc->cmnd, sc->cmd_len);
	if (sc->cmd_len < MAX_COMMAND_SIZE)
		memset(&hdr->cdb[sc->cmd_len], 0,
			MAX_COMMAND_SIZE - sc->cmd_len);
	cmd_len = sc->cmd_len;
	if (cmd_len < ISCSI_CDB_SIZE)
		memset(&hdr->cdb[cmd_len], 0, ISCSI_CDB_SIZE - 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;
	if (sc->sc_data_direction == DMA_TO_DEVICE) {
+4 −2
Original line number Diff line number Diff line
@@ -112,6 +112,7 @@ struct iscsi_ahs_hdr {

#define ISCSI_AHSTYPE_CDB		1
#define ISCSI_AHSTYPE_RLENGTH		2
#define ISCSI_CDB_SIZE			16

/* iSCSI PDU Header */
struct iscsi_cmd {
@@ -125,7 +126,7 @@ struct iscsi_cmd {
	__be32 data_length;
	__be32 cmdsn;
	__be32 exp_statsn;
	uint8_t cdb[16];	/* SCSI Command Block */
	uint8_t cdb[ISCSI_CDB_SIZE];	/* SCSI Command Block */
	/* Additional Data (Command Dependent) */
};

@@ -154,7 +155,8 @@ struct iscsi_ecdb_ahdr {
	__be16 ahslength;	/* CDB length - 15, including reserved byte */
	uint8_t ahstype;
	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 */