RDMA/srp: Handle large SCSI CDBs correctly
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>
This commit is contained in:
parent
e37df2d5b5
commit
482fffc43c
@ -1782,7 +1782,7 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_rdma_ch *ch,
|
|||||||
u8 fmt;
|
u8 fmt;
|
||||||
|
|
||||||
if (!scsi_sglist(scmnd) || scmnd->sc_data_direction == DMA_NONE)
|
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 &&
|
if (scmnd->sc_data_direction != DMA_FROM_DEVICE &&
|
||||||
scmnd->sc_data_direction != DMA_TO_DEVICE) {
|
scmnd->sc_data_direction != DMA_TO_DEVICE) {
|
||||||
@ -1803,7 +1803,8 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_rdma_ch *ch,
|
|||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
fmt = SRP_DATA_DESC_DIRECT;
|
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) {
|
if (count == 1 && target->global_rkey) {
|
||||||
/*
|
/*
|
||||||
@ -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
|
* single entry. So a direct descriptor along with
|
||||||
* the DMA MR suffices.
|
* 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->va = cpu_to_be64(ib_sg_dma_address(ibdev, scat));
|
||||||
buf->key = cpu_to_be32(target->global_rkey);
|
buf->key = cpu_to_be32(target->global_rkey);
|
||||||
buf->len = cpu_to_be32(ib_sg_dma_len(ibdev, scat));
|
buf->len = cpu_to_be32(ib_sg_dma_len(ibdev, scat));
|
||||||
@ -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
|
* We have more than one scatter/gather entry, so build our indirect
|
||||||
* descriptor table, trying to merge as many entries as we can.
|
* 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,
|
ib_dma_sync_single_for_cpu(ibdev, req->indirect_dma_addr,
|
||||||
target->indirect_size, DMA_TO_DEVICE);
|
target->indirect_size, DMA_TO_DEVICE);
|
||||||
@ -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,
|
* Memory registration collapsed the sg-list into one entry,
|
||||||
* so use a direct descriptor.
|
* 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];
|
*buf = req->indirect_desc[0];
|
||||||
goto map_complete;
|
goto map_complete;
|
||||||
}
|
}
|
||||||
@ -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;
|
idb_len = sizeof(struct srp_indirect_buf) + table_len;
|
||||||
|
|
||||||
fmt = SRP_DATA_DESC_INDIRECT;
|
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);
|
len += count * sizeof (struct srp_direct_buf);
|
||||||
|
|
||||||
memcpy(indirect_hdr->desc_list, req->indirect_desc,
|
memcpy(indirect_hdr->desc_list, req->indirect_desc,
|
||||||
@ -2324,6 +2328,12 @@ static int srp_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmnd)
|
|||||||
int_to_scsilun(scmnd->device->lun, &cmd->lun);
|
int_to_scsilun(scmnd->device->lun, &cmd->lun);
|
||||||
cmd->tag = tag;
|
cmd->tag = tag;
|
||||||
memcpy(cmd->cdb, scmnd->cmnd, scmnd->cmd_len);
|
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->scmnd = scmnd;
|
||||||
req->cmd = iu;
|
req->cmd = iu;
|
||||||
@ -3829,6 +3839,7 @@ static ssize_t srp_create_target(struct device *dev,
|
|||||||
target->indirect_size = target->sg_tablesize *
|
target->indirect_size = target->sg_tablesize *
|
||||||
sizeof (struct srp_direct_buf);
|
sizeof (struct srp_direct_buf);
|
||||||
target->max_iu_len = sizeof (struct srp_cmd) +
|
target->max_iu_len = sizeof (struct srp_cmd) +
|
||||||
|
SRP_MAX_ADD_CDB_LEN +
|
||||||
sizeof (struct srp_indirect_buf) +
|
sizeof (struct srp_indirect_buf) +
|
||||||
target->cmd_sg_cnt * sizeof (struct srp_direct_buf);
|
target->cmd_sg_cnt * sizeof (struct srp_direct_buf);
|
||||||
|
|
||||||
|
@ -67,6 +67,8 @@ enum {
|
|||||||
SRP_TAG_TSK_MGMT = 1U << 31,
|
SRP_TAG_TSK_MGMT = 1U << 31,
|
||||||
|
|
||||||
SRP_MAX_PAGES_PER_MR = 512,
|
SRP_MAX_PAGES_PER_MR = 512,
|
||||||
|
|
||||||
|
SRP_MAX_ADD_CDB_LEN = 16,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum srp_target_state {
|
enum srp_target_state {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user