Skip to content

Commit

Permalink
RDMA/srp: Handle large SCSI CDBs correctly
Browse files Browse the repository at this point in the history
Reserve additional space for CDBs that contain more than sixteen bytes
and set the add_cdb_len field for such CDBs as required. From the SRP
standard: "The ADDITIONAL CDB LENGTH field contains the length in
dwords of the ADDITIONAL CDB field."

Cc: Sergey Gorenko <sergeygo@mellanox.com>
Cc: Max Gurtovoy <maxg@mellanox.com>
Cc: Laurence Oberman <loberman@redhat.com>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Signed-off-by: Doug Ledford <dledford@redhat.com>
  • Loading branch information
Bart Van Assche authored and Doug Ledford committed Dec 19, 2018
1 parent e37df2d commit 482fffc
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 6 deletions.
23 changes: 17 additions & 6 deletions drivers/infiniband/ulp/srp/ib_srp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1782,7 +1782,7 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_rdma_ch *ch,
u8 fmt;

if (!scsi_sglist(scmnd) || scmnd->sc_data_direction == DMA_NONE)
return sizeof (struct srp_cmd);
return sizeof(struct srp_cmd) + cmd->add_cdb_len;

if (scmnd->sc_data_direction != DMA_FROM_DEVICE &&
scmnd->sc_data_direction != DMA_TO_DEVICE) {
Expand All @@ -1803,7 +1803,8 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_rdma_ch *ch,
return -EIO;

fmt = SRP_DATA_DESC_DIRECT;
len = sizeof (struct srp_cmd) + sizeof (struct srp_direct_buf);
len = sizeof(struct srp_cmd) + cmd->add_cdb_len +
sizeof(struct srp_direct_buf);

if (count == 1 && target->global_rkey) {
/*
Expand All @@ -1812,8 +1813,9 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_rdma_ch *ch,
* single entry. So a direct descriptor along with
* the DMA MR suffices.
*/
struct srp_direct_buf *buf = (void *) cmd->add_data;
struct srp_direct_buf *buf;

buf = (void *)cmd->add_data + cmd->add_cdb_len;
buf->va = cpu_to_be64(ib_sg_dma_address(ibdev, scat));
buf->key = cpu_to_be32(target->global_rkey);
buf->len = cpu_to_be32(ib_sg_dma_len(ibdev, scat));
Expand All @@ -1826,7 +1828,7 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_rdma_ch *ch,
* We have more than one scatter/gather entry, so build our indirect
* descriptor table, trying to merge as many entries as we can.
*/
indirect_hdr = (void *) cmd->add_data;
indirect_hdr = (void *)cmd->add_data + cmd->add_cdb_len;

ib_dma_sync_single_for_cpu(ibdev, req->indirect_dma_addr,
target->indirect_size, DMA_TO_DEVICE);
Expand Down Expand Up @@ -1861,8 +1863,9 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_rdma_ch *ch,
* Memory registration collapsed the sg-list into one entry,
* so use a direct descriptor.
*/
struct srp_direct_buf *buf = (void *) cmd->add_data;
struct srp_direct_buf *buf;

buf = (void *)cmd->add_data + cmd->add_cdb_len;
*buf = req->indirect_desc[0];
goto map_complete;
}
Expand All @@ -1880,7 +1883,8 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_rdma_ch *ch,
idb_len = sizeof(struct srp_indirect_buf) + table_len;

fmt = SRP_DATA_DESC_INDIRECT;
len = sizeof(struct srp_cmd) + sizeof (struct srp_indirect_buf);
len = sizeof(struct srp_cmd) + cmd->add_cdb_len +
sizeof(struct srp_indirect_buf);
len += count * sizeof (struct srp_direct_buf);

memcpy(indirect_hdr->desc_list, req->indirect_desc,
Expand Down Expand Up @@ -2324,6 +2328,12 @@ static int srp_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmnd)
int_to_scsilun(scmnd->device->lun, &cmd->lun);
cmd->tag = tag;
memcpy(cmd->cdb, scmnd->cmnd, scmnd->cmd_len);
if (unlikely(scmnd->cmd_len > sizeof(cmd->cdb))) {
cmd->add_cdb_len = round_up(scmnd->cmd_len - sizeof(cmd->cdb),
4);
if (WARN_ON_ONCE(cmd->add_cdb_len > SRP_MAX_ADD_CDB_LEN))
goto err_iu;
}

req->scmnd = scmnd;
req->cmd = iu;
Expand Down Expand Up @@ -3829,6 +3839,7 @@ static ssize_t srp_create_target(struct device *dev,
target->indirect_size = target->sg_tablesize *
sizeof (struct srp_direct_buf);
target->max_iu_len = sizeof (struct srp_cmd) +
SRP_MAX_ADD_CDB_LEN +
sizeof (struct srp_indirect_buf) +
target->cmd_sg_cnt * sizeof (struct srp_direct_buf);

Expand Down
2 changes: 2 additions & 0 deletions drivers/infiniband/ulp/srp/ib_srp.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ enum {
SRP_TAG_TSK_MGMT = 1U << 31,

SRP_MAX_PAGES_PER_MR = 512,

SRP_MAX_ADD_CDB_LEN = 16,
};

enum srp_target_state {
Expand Down

0 comments on commit 482fffc

Please sign in to comment.