|
@@ -1453,18 +1453,58 @@ out:
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * Register the indirect data buffer descriptor with the HCA.
|
|
|
+ *
|
|
|
+ * Note: since the indirect data buffer descriptor has been allocated with
|
|
|
+ * kmalloc() it is guaranteed that this buffer is a physically contiguous
|
|
|
+ * memory buffer.
|
|
|
+ */
|
|
|
+static int srp_map_idb(struct srp_rdma_ch *ch, struct srp_request *req,
|
|
|
+ void **next_mr, void **end_mr, u32 idb_len,
|
|
|
+ __be32 *idb_rkey)
|
|
|
+{
|
|
|
+ struct srp_target_port *target = ch->target;
|
|
|
+ struct srp_device *dev = target->srp_host->srp_dev;
|
|
|
+ struct srp_map_state state;
|
|
|
+ struct srp_direct_buf idb_desc;
|
|
|
+ u64 idb_pages[1];
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ memset(&state, 0, sizeof(state));
|
|
|
+ memset(&idb_desc, 0, sizeof(idb_desc));
|
|
|
+ state.gen.next = next_mr;
|
|
|
+ state.gen.end = end_mr;
|
|
|
+ state.desc = &idb_desc;
|
|
|
+ state.pages = idb_pages;
|
|
|
+ state.pages[0] = (req->indirect_dma_addr &
|
|
|
+ dev->mr_page_mask);
|
|
|
+ state.npages = 1;
|
|
|
+ state.base_dma_addr = req->indirect_dma_addr;
|
|
|
+ state.dma_len = idb_len;
|
|
|
+ ret = srp_finish_mapping(&state, ch);
|
|
|
+ if (ret < 0)
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ *idb_rkey = idb_desc.key;
|
|
|
+
|
|
|
+out:
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_rdma_ch *ch,
|
|
|
struct srp_request *req)
|
|
|
{
|
|
|
struct srp_target_port *target = ch->target;
|
|
|
struct scatterlist *scat;
|
|
|
struct srp_cmd *cmd = req->cmd->buf;
|
|
|
- int len, nents, count;
|
|
|
+ int len, nents, count, ret;
|
|
|
struct srp_device *dev;
|
|
|
struct ib_device *ibdev;
|
|
|
struct srp_map_state state;
|
|
|
struct srp_indirect_buf *indirect_hdr;
|
|
|
- u32 table_len;
|
|
|
+ u32 idb_len, table_len;
|
|
|
+ __be32 idb_rkey;
|
|
|
u8 fmt;
|
|
|
|
|
|
if (!scsi_sglist(scmnd) || scmnd->sc_data_direction == DMA_NONE)
|
|
@@ -1546,6 +1586,7 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_rdma_ch *ch,
|
|
|
|
|
|
count = min(state.ndesc, target->cmd_sg_cnt);
|
|
|
table_len = state.ndesc * sizeof (struct srp_direct_buf);
|
|
|
+ idb_len = sizeof(struct srp_indirect_buf) + table_len;
|
|
|
|
|
|
fmt = SRP_DATA_DESC_INDIRECT;
|
|
|
len = sizeof(struct srp_cmd) + sizeof (struct srp_indirect_buf);
|
|
@@ -1554,8 +1595,18 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_rdma_ch *ch,
|
|
|
memcpy(indirect_hdr->desc_list, req->indirect_desc,
|
|
|
count * sizeof (struct srp_direct_buf));
|
|
|
|
|
|
+ if (register_always && (dev->use_fast_reg || dev->use_fmr)) {
|
|
|
+ ret = srp_map_idb(ch, req, state.gen.next, state.gen.end,
|
|
|
+ idb_len, &idb_rkey);
|
|
|
+ if (ret < 0)
|
|
|
+ return ret;
|
|
|
+ req->nmdesc++;
|
|
|
+ } else {
|
|
|
+ idb_rkey = target->rkey;
|
|
|
+ }
|
|
|
+
|
|
|
indirect_hdr->table_desc.va = cpu_to_be64(req->indirect_dma_addr);
|
|
|
- indirect_hdr->table_desc.key = cpu_to_be32(target->rkey);
|
|
|
+ indirect_hdr->table_desc.key = idb_rkey;
|
|
|
indirect_hdr->table_desc.len = cpu_to_be32(table_len);
|
|
|
indirect_hdr->len = cpu_to_be32(state.total_len);
|
|
|
|