Skip to content

Commit 882981f

Browse files
bvanasschedledford
authored andcommitted
RDMA/srp: Add support for immediate data
Request permission to send immediate data during login. If the SRP target grants this request, send the payload of write requests <= 8 KB as immediate data. Cc: Sergey Gorenko <[email protected]> Cc: Max Gurtovoy <[email protected]> Cc: Laurence Oberman <[email protected]> Signed-off-by: Bart Van Assche <[email protected]> Signed-off-by: Doug Ledford <[email protected]>
1 parent 513d564 commit 882981f

File tree

2 files changed

+89
-14
lines changed

2 files changed

+89
-14
lines changed

drivers/infiniband/ulp/srp/ib_srp.c

Lines changed: 77 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,15 @@ MODULE_PARM_DESC(dev_loss_tmo,
132132
" if fast_io_fail_tmo has not been set. \"off\" means that"
133133
" this functionality is disabled.");
134134

135+
static bool srp_use_imm_data = true;
136+
module_param_named(use_imm_data, srp_use_imm_data, bool, 0644);
137+
MODULE_PARM_DESC(use_imm_data,
138+
"Whether or not to request permission to use immediate data during SRP login.");
139+
140+
static unsigned int srp_max_imm_data = 8 * 1024;
141+
module_param_named(max_imm_data, srp_max_imm_data, uint, 0644);
142+
MODULE_PARM_DESC(max_imm_data, "Maximum immediate data size.");
143+
135144
static unsigned ch_count;
136145
module_param(ch_count, uint, 0444);
137146
MODULE_PARM_DESC(ch_count,
@@ -573,7 +582,7 @@ static int srp_create_ch_ib(struct srp_rdma_ch *ch)
573582
init_attr->cap.max_send_wr = m * target->queue_size;
574583
init_attr->cap.max_recv_wr = target->queue_size + 1;
575584
init_attr->cap.max_recv_sge = 1;
576-
init_attr->cap.max_send_sge = 1;
585+
init_attr->cap.max_send_sge = SRP_MAX_SGE;
577586
init_attr->sq_sig_type = IB_SIGNAL_REQ_WR;
578587
init_attr->qp_type = IB_QPT_RC;
579588
init_attr->send_cq = send_cq;
@@ -858,6 +867,10 @@ static int srp_send_req(struct srp_rdma_ch *ch, uint32_t max_iu_len,
858867
SRP_BUF_FORMAT_INDIRECT);
859868
req->ib_req.req_flags = (multich ? SRP_MULTICHAN_MULTI :
860869
SRP_MULTICHAN_SINGLE);
870+
if (srp_use_imm_data) {
871+
req->ib_req.req_flags |= SRP_IMMED_REQUESTED;
872+
req->ib_req.imm_data_offset = cpu_to_be16(SRP_IMM_DATA_OFFSET);
873+
}
861874

862875
if (target->using_rdma_cm) {
863876
req->rdma_param.flow_control = req->ib_param.flow_control;
@@ -874,6 +887,7 @@ static int srp_send_req(struct srp_rdma_ch *ch, uint32_t max_iu_len,
874887
req->rdma_req.req_it_iu_len = req->ib_req.req_it_iu_len;
875888
req->rdma_req.req_buf_fmt = req->ib_req.req_buf_fmt;
876889
req->rdma_req.req_flags = req->ib_req.req_flags;
890+
req->rdma_req.imm_data_offset = req->ib_req.imm_data_offset;
877891

878892
ipi = req->rdma_req.initiator_port_id;
879893
tpi = req->rdma_req.target_port_id;
@@ -1347,12 +1361,16 @@ static void srp_terminate_io(struct srp_rport *rport)
13471361
}
13481362

13491363
/* Calculate maximum initiator to target information unit length. */
1350-
static uint32_t srp_max_it_iu_len(int cmd_sg_cnt)
1364+
static uint32_t srp_max_it_iu_len(int cmd_sg_cnt, bool use_imm_data)
13511365
{
13521366
uint32_t max_iu_len = sizeof(struct srp_cmd) + SRP_MAX_ADD_CDB_LEN +
13531367
sizeof(struct srp_indirect_buf) +
13541368
cmd_sg_cnt * sizeof(struct srp_direct_buf);
13551369

1370+
if (use_imm_data)
1371+
max_iu_len = max(max_iu_len, SRP_IMM_DATA_OFFSET +
1372+
srp_max_imm_data);
1373+
13561374
return max_iu_len;
13571375
}
13581376

@@ -1369,7 +1387,8 @@ static int srp_rport_reconnect(struct srp_rport *rport)
13691387
{
13701388
struct srp_target_port *target = rport->lld_data;
13711389
struct srp_rdma_ch *ch;
1372-
uint32_t max_iu_len = srp_max_it_iu_len(target->cmd_sg_cnt);
1390+
uint32_t max_iu_len = srp_max_it_iu_len(target->cmd_sg_cnt,
1391+
srp_use_imm_data);
13731392
int i, j, ret = 0;
13741393
bool multich = false;
13751394

@@ -1777,23 +1796,27 @@ static void srp_check_mapping(struct srp_map_state *state,
17771796
* @req: SRP request
17781797
*
17791798
* Returns the length in bytes of the SRP_CMD IU or a negative value if
1780-
* mapping failed.
1799+
* mapping failed. The size of any immediate data is not included in the
1800+
* return value.
17811801
*/
17821802
static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_rdma_ch *ch,
17831803
struct srp_request *req)
17841804
{
17851805
struct srp_target_port *target = ch->target;
1786-
struct scatterlist *scat;
1806+
struct scatterlist *scat, *sg;
17871807
struct srp_cmd *cmd = req->cmd->buf;
1788-
int len, nents, count, ret;
1808+
int i, len, nents, count, ret;
17891809
struct srp_device *dev;
17901810
struct ib_device *ibdev;
17911811
struct srp_map_state state;
17921812
struct srp_indirect_buf *indirect_hdr;
1813+
u64 data_len;
17931814
u32 idb_len, table_len;
17941815
__be32 idb_rkey;
17951816
u8 fmt;
17961817

1818+
req->cmd->num_sge = 1;
1819+
17971820
if (!scsi_sglist(scmnd) || scmnd->sc_data_direction == DMA_NONE)
17981821
return sizeof(struct srp_cmd) + cmd->add_cdb_len;
17991822

@@ -1807,6 +1830,7 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_rdma_ch *ch,
18071830

18081831
nents = scsi_sg_count(scmnd);
18091832
scat = scsi_sglist(scmnd);
1833+
data_len = scsi_bufflen(scmnd);
18101834

18111835
dev = target->srp_host->srp_dev;
18121836
ibdev = dev->dev;
@@ -1815,6 +1839,28 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_rdma_ch *ch,
18151839
if (unlikely(count == 0))
18161840
return -EIO;
18171841

1842+
if (ch->use_imm_data &&
1843+
count <= SRP_MAX_IMM_SGE &&
1844+
SRP_IMM_DATA_OFFSET + data_len <= ch->max_it_iu_len &&
1845+
scmnd->sc_data_direction == DMA_TO_DEVICE) {
1846+
struct srp_imm_buf *buf;
1847+
struct ib_sge *sge = &req->cmd->sge[1];
1848+
1849+
fmt = SRP_DATA_DESC_IMM;
1850+
len = SRP_IMM_DATA_OFFSET;
1851+
req->nmdesc = 0;
1852+
buf = (void *)cmd->add_data + cmd->add_cdb_len;
1853+
buf->len = cpu_to_be32(data_len);
1854+
WARN_ON_ONCE((void *)(buf + 1) > (void *)cmd + len);
1855+
for_each_sg(scat, sg, count, i) {
1856+
sge[i].addr = ib_sg_dma_address(ibdev, sg);
1857+
sge[i].length = ib_sg_dma_len(ibdev, sg);
1858+
sge[i].lkey = target->lkey;
1859+
}
1860+
req->cmd->num_sge += count;
1861+
goto map_complete;
1862+
}
1863+
18181864
fmt = SRP_DATA_DESC_DIRECT;
18191865
len = sizeof(struct srp_cmd) + cmd->add_cdb_len +
18201866
sizeof(struct srp_direct_buf);
@@ -2018,22 +2064,30 @@ static void srp_send_done(struct ib_cq *cq, struct ib_wc *wc)
20182064
list_add(&iu->list, &ch->free_tx);
20192065
}
20202066

2067+
/**
2068+
* srp_post_send() - send an SRP information unit
2069+
* @ch: RDMA channel over which to send the information unit.
2070+
* @iu: Information unit to send.
2071+
* @len: Length of the information unit excluding immediate data.
2072+
*/
20212073
static int srp_post_send(struct srp_rdma_ch *ch, struct srp_iu *iu, int len)
20222074
{
20232075
struct srp_target_port *target = ch->target;
2024-
struct ib_sge list;
20252076
struct ib_send_wr wr;
20262077

2027-
list.addr = iu->dma;
2028-
list.length = len;
2029-
list.lkey = target->lkey;
2078+
if (WARN_ON_ONCE(iu->num_sge > SRP_MAX_SGE))
2079+
return -EINVAL;
2080+
2081+
iu->sge[0].addr = iu->dma;
2082+
iu->sge[0].length = len;
2083+
iu->sge[0].lkey = target->lkey;
20302084

20312085
iu->cqe.done = srp_send_done;
20322086

20332087
wr.next = NULL;
20342088
wr.wr_cqe = &iu->cqe;
2035-
wr.sg_list = &list;
2036-
wr.num_sge = 1;
2089+
wr.sg_list = &iu->sge[0];
2090+
wr.num_sge = iu->num_sge;
20372091
wr.opcode = IB_WR_SEND;
20382092
wr.send_flags = IB_SEND_SIGNALED;
20392093

@@ -2146,6 +2200,7 @@ static int srp_response_common(struct srp_rdma_ch *ch, s32 req_delta,
21462200
return 1;
21472201
}
21482202

2203+
iu->num_sge = 1;
21492204
ib_dma_sync_single_for_cpu(dev, iu->dma, len, DMA_TO_DEVICE);
21502205
memcpy(iu->buf, rsp, len);
21512206
ib_dma_sync_single_for_device(dev, iu->dma, len, DMA_TO_DEVICE);
@@ -2500,10 +2555,16 @@ static void srp_cm_rep_handler(struct ib_cm_id *cm_id,
25002555
if (lrsp->opcode == SRP_LOGIN_RSP) {
25012556
ch->max_ti_iu_len = be32_to_cpu(lrsp->max_ti_iu_len);
25022557
ch->req_lim = be32_to_cpu(lrsp->req_lim_delta);
2503-
ch->max_it_iu_len = srp_max_it_iu_len(target->cmd_sg_cnt);
2558+
ch->use_imm_data = lrsp->rsp_flags & SRP_LOGIN_RSP_IMMED_SUPP;
2559+
ch->max_it_iu_len = srp_max_it_iu_len(target->cmd_sg_cnt,
2560+
ch->use_imm_data);
25042561
WARN_ON_ONCE(ch->max_it_iu_len >
25052562
be32_to_cpu(lrsp->max_it_iu_len));
25062563

2564+
if (ch->use_imm_data)
2565+
shost_printk(KERN_DEBUG, target->scsi_host,
2566+
PFX "using immediate data\n");
2567+
25072568
/*
25082569
* Reserve credits for task management so we don't
25092570
* bounce requests back to the SCSI mid-layer.
@@ -2891,6 +2952,8 @@ static int srp_send_tsk_mgmt(struct srp_rdma_ch *ch, u64 req_tag, u64 lun,
28912952
return -1;
28922953
}
28932954

2955+
iu->num_sge = 1;
2956+
28942957
ib_dma_sync_single_for_cpu(dev, iu->dma, sizeof *tsk_mgmt,
28952958
DMA_TO_DEVICE);
28962959
tsk_mgmt = iu->buf;
@@ -3856,7 +3919,7 @@ static ssize_t srp_create_target(struct device *dev,
38563919
target->mr_per_cmd = mr_per_cmd;
38573920
target->indirect_size = target->sg_tablesize *
38583921
sizeof (struct srp_direct_buf);
3859-
max_iu_len = srp_max_it_iu_len(target->cmd_sg_cnt);
3922+
max_iu_len = srp_max_it_iu_len(target->cmd_sg_cnt, srp_use_imm_data);
38603923

38613924
INIT_WORK(&target->tl_err_work, srp_tl_err_work);
38623925
INIT_WORK(&target->remove_work, srp_remove_work);

drivers/infiniband/ulp/srp/ib_srp.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,15 @@ enum {
6969
SRP_MAX_PAGES_PER_MR = 512,
7070

7171
SRP_MAX_ADD_CDB_LEN = 16,
72+
73+
SRP_MAX_IMM_SGE = 2,
74+
SRP_MAX_SGE = SRP_MAX_IMM_SGE + 1,
75+
/*
76+
* Choose the immediate data offset such that a 32 byte CDB still fits.
77+
*/
78+
SRP_IMM_DATA_OFFSET = sizeof(struct srp_cmd) +
79+
SRP_MAX_ADD_CDB_LEN +
80+
sizeof(struct srp_imm_buf),
7281
};
7382

7483
enum srp_target_state {
@@ -152,6 +161,7 @@ struct srp_rdma_ch {
152161
};
153162
uint32_t max_it_iu_len;
154163
uint32_t max_ti_iu_len;
164+
bool use_imm_data;
155165

156166
/* Everything above this point is used in the hot path of
157167
* command processing. Try to keep them packed into cachelines.
@@ -263,6 +273,8 @@ struct srp_iu {
263273
void *buf;
264274
size_t size;
265275
enum dma_data_direction direction;
276+
u32 num_sge;
277+
struct ib_sge sge[SRP_MAX_SGE];
266278
struct ib_cqe cqe;
267279
};
268280

0 commit comments

Comments
 (0)