@@ -274,6 +274,115 @@ static int rdma_rw_init_single_wr(struct rdma_rw_ctx *ctx, struct ib_qp *qp,
274274 return 1 ;
275275}
276276
277+ static int rdma_rw_init_single_wr_bvec (struct rdma_rw_ctx * ctx ,
278+ struct ib_qp * qp , const struct bio_vec * bvecs ,
279+ struct bvec_iter * iter , u64 remote_addr , u32 rkey ,
280+ enum dma_data_direction dir )
281+ {
282+ struct ib_device * dev = qp -> pd -> device ;
283+ struct ib_rdma_wr * rdma_wr = & ctx -> single .wr ;
284+ struct bio_vec bv = mp_bvec_iter_bvec (bvecs , * iter );
285+ u64 dma_addr ;
286+
287+ ctx -> nr_ops = 1 ;
288+
289+ dma_addr = ib_dma_map_bvec (dev , & bv , dir );
290+ if (ib_dma_mapping_error (dev , dma_addr ))
291+ return - ENOMEM ;
292+
293+ ctx -> single .sge .lkey = qp -> pd -> local_dma_lkey ;
294+ ctx -> single .sge .addr = dma_addr ;
295+ ctx -> single .sge .length = bv .bv_len ;
296+
297+ memset (rdma_wr , 0 , sizeof (* rdma_wr ));
298+ if (dir == DMA_TO_DEVICE )
299+ rdma_wr -> wr .opcode = IB_WR_RDMA_WRITE ;
300+ else
301+ rdma_wr -> wr .opcode = IB_WR_RDMA_READ ;
302+ rdma_wr -> wr .sg_list = & ctx -> single .sge ;
303+ rdma_wr -> wr .num_sge = 1 ;
304+ rdma_wr -> remote_addr = remote_addr ;
305+ rdma_wr -> rkey = rkey ;
306+
307+ ctx -> type = RDMA_RW_SINGLE_WR ;
308+ return 1 ;
309+ }
310+
311+ static int rdma_rw_init_map_wrs_bvec (struct rdma_rw_ctx * ctx , struct ib_qp * qp ,
312+ const struct bio_vec * bvecs , u32 nr_bvec , struct bvec_iter * iter ,
313+ u64 remote_addr , u32 rkey , enum dma_data_direction dir )
314+ {
315+ struct ib_device * dev = qp -> pd -> device ;
316+ u32 max_sge = dir == DMA_TO_DEVICE ? qp -> max_write_sge :
317+ qp -> max_read_sge ;
318+ struct ib_sge * sge ;
319+ u32 total_len = 0 , i , j ;
320+ u32 mapped_bvecs = 0 ;
321+ u32 nr_ops = DIV_ROUND_UP (nr_bvec , max_sge );
322+ size_t sges_size = array_size (nr_bvec , sizeof (* ctx -> map .sges ));
323+ size_t wrs_offset = ALIGN (sges_size , __alignof__(* ctx -> map .wrs ));
324+ size_t wrs_size = array_size (nr_ops , sizeof (* ctx -> map .wrs ));
325+ void * mem ;
326+
327+ if (sges_size == SIZE_MAX || wrs_size == SIZE_MAX ||
328+ check_add_overflow (wrs_offset , wrs_size , & wrs_size ))
329+ return - ENOMEM ;
330+
331+ mem = kzalloc (wrs_size , GFP_KERNEL );
332+ if (!mem )
333+ return - ENOMEM ;
334+
335+ ctx -> map .sges = sge = mem ;
336+ ctx -> map .wrs = mem + wrs_offset ;
337+
338+ for (i = 0 ; i < nr_ops ; i ++ ) {
339+ struct ib_rdma_wr * rdma_wr = & ctx -> map .wrs [i ];
340+ u32 nr_sge = min (nr_bvec - mapped_bvecs , max_sge );
341+
342+ if (dir == DMA_TO_DEVICE )
343+ rdma_wr -> wr .opcode = IB_WR_RDMA_WRITE ;
344+ else
345+ rdma_wr -> wr .opcode = IB_WR_RDMA_READ ;
346+ rdma_wr -> remote_addr = remote_addr + total_len ;
347+ rdma_wr -> rkey = rkey ;
348+ rdma_wr -> wr .num_sge = nr_sge ;
349+ rdma_wr -> wr .sg_list = sge ;
350+
351+ for (j = 0 ; j < nr_sge ; j ++ ) {
352+ struct bio_vec bv = mp_bvec_iter_bvec (bvecs , * iter );
353+ u64 dma_addr ;
354+
355+ dma_addr = ib_dma_map_bvec (dev , & bv , dir );
356+ if (ib_dma_mapping_error (dev , dma_addr ))
357+ goto out_unmap ;
358+
359+ mapped_bvecs ++ ;
360+ sge -> addr = dma_addr ;
361+ sge -> length = bv .bv_len ;
362+ sge -> lkey = qp -> pd -> local_dma_lkey ;
363+
364+ total_len += bv .bv_len ;
365+ sge ++ ;
366+
367+ bvec_iter_advance_single (bvecs , iter , bv .bv_len );
368+ }
369+
370+ rdma_wr -> wr .next = i + 1 < nr_ops ?
371+ & ctx -> map .wrs [i + 1 ].wr : NULL ;
372+ }
373+
374+ ctx -> nr_ops = nr_ops ;
375+ ctx -> type = RDMA_RW_MULTI_WR ;
376+ return nr_ops ;
377+
378+ out_unmap :
379+ for (i = 0 ; i < mapped_bvecs ; i ++ )
380+ ib_dma_unmap_bvec (dev , ctx -> map .sges [i ].addr ,
381+ ctx -> map .sges [i ].length , dir );
382+ kfree (ctx -> map .sges );
383+ return - ENOMEM ;
384+ }
385+
277386/**
278387 * rdma_rw_ctx_init - initialize a RDMA READ/WRITE context
279388 * @ctx: context to initialize
@@ -344,6 +453,53 @@ int rdma_rw_ctx_init(struct rdma_rw_ctx *ctx, struct ib_qp *qp, u32 port_num,
344453}
345454EXPORT_SYMBOL (rdma_rw_ctx_init );
346455
456+ /**
457+ * rdma_rw_ctx_init_bvec - initialize a RDMA READ/WRITE context from bio_vec
458+ * @ctx: context to initialize
459+ * @qp: queue pair to operate on
460+ * @port_num: port num to which the connection is bound
461+ * @bvecs: bio_vec array to READ/WRITE from/to
462+ * @nr_bvec: number of entries in @bvecs
463+ * @iter: bvec iterator describing offset and length
464+ * @remote_addr: remote address to read/write (relative to @rkey)
465+ * @rkey: remote key to operate on
466+ * @dir: %DMA_TO_DEVICE for RDMA WRITE, %DMA_FROM_DEVICE for RDMA READ
467+ *
468+ * Accepts bio_vec arrays directly, avoiding scatterlist conversion for
469+ * callers that already have data in bio_vec form. Prefer this over
470+ * rdma_rw_ctx_init() when the source data is a bio_vec array.
471+ *
472+ * This function does not support devices requiring memory registration.
473+ * iWARP devices and configurations with force_mr=1 should use
474+ * rdma_rw_ctx_init() with a scatterlist instead.
475+ *
476+ * Returns the number of WQEs that will be needed on the workqueue if
477+ * successful, or a negative error code:
478+ *
479+ * * -EINVAL - @nr_bvec is zero or @iter.bi_size is zero
480+ * * -EOPNOTSUPP - device requires MR path (iWARP or force_mr=1)
481+ * * -ENOMEM - DMA mapping or memory allocation failed
482+ */
483+ int rdma_rw_ctx_init_bvec (struct rdma_rw_ctx * ctx , struct ib_qp * qp ,
484+ u32 port_num , const struct bio_vec * bvecs , u32 nr_bvec ,
485+ struct bvec_iter iter , u64 remote_addr , u32 rkey ,
486+ enum dma_data_direction dir )
487+ {
488+ if (nr_bvec == 0 || iter .bi_size == 0 )
489+ return - EINVAL ;
490+
491+ /* MR path not supported for bvec - reject iWARP and force_mr */
492+ if (rdma_rw_io_needs_mr (qp -> device , port_num , dir , nr_bvec ))
493+ return - EOPNOTSUPP ;
494+
495+ if (nr_bvec == 1 )
496+ return rdma_rw_init_single_wr_bvec (ctx , qp , bvecs , & iter ,
497+ remote_addr , rkey , dir );
498+ return rdma_rw_init_map_wrs_bvec (ctx , qp , bvecs , nr_bvec , & iter ,
499+ remote_addr , rkey , dir );
500+ }
501+ EXPORT_SYMBOL (rdma_rw_ctx_init_bvec );
502+
347503/**
348504 * rdma_rw_ctx_signature_init - initialize a RW context with signature offload
349505 * @ctx: context to initialize
@@ -598,6 +754,47 @@ void rdma_rw_ctx_destroy(struct rdma_rw_ctx *ctx, struct ib_qp *qp,
598754}
599755EXPORT_SYMBOL (rdma_rw_ctx_destroy );
600756
757+ /**
758+ * rdma_rw_ctx_destroy_bvec - release resources from rdma_rw_ctx_init_bvec
759+ * @ctx: context to release
760+ * @qp: queue pair to operate on
761+ * @port_num: port num to which the connection is bound (unused)
762+ * @bvecs: bio_vec array that was used for the READ/WRITE (unused)
763+ * @nr_bvec: number of entries in @bvecs
764+ * @dir: %DMA_TO_DEVICE for RDMA WRITE, %DMA_FROM_DEVICE for RDMA READ
765+ *
766+ * Releases all resources allocated by a successful rdma_rw_ctx_init_bvec()
767+ * call. Must not be called if rdma_rw_ctx_init_bvec() returned an error.
768+ *
769+ * The @port_num and @bvecs parameters are unused but present for API
770+ * symmetry with rdma_rw_ctx_destroy().
771+ */
772+ void rdma_rw_ctx_destroy_bvec (struct rdma_rw_ctx * ctx , struct ib_qp * qp ,
773+ u32 __maybe_unused port_num ,
774+ const struct bio_vec __maybe_unused * bvecs ,
775+ u32 nr_bvec , enum dma_data_direction dir )
776+ {
777+ struct ib_device * dev = qp -> pd -> device ;
778+ u32 i ;
779+
780+ switch (ctx -> type ) {
781+ case RDMA_RW_MULTI_WR :
782+ for (i = 0 ; i < nr_bvec ; i ++ )
783+ ib_dma_unmap_bvec (dev , ctx -> map .sges [i ].addr ,
784+ ctx -> map .sges [i ].length , dir );
785+ kfree (ctx -> map .sges );
786+ break ;
787+ case RDMA_RW_SINGLE_WR :
788+ ib_dma_unmap_bvec (dev , ctx -> single .sge .addr ,
789+ ctx -> single .sge .length , dir );
790+ break ;
791+ default :
792+ WARN_ON_ONCE (1 );
793+ return ;
794+ }
795+ }
796+ EXPORT_SYMBOL (rdma_rw_ctx_destroy_bvec );
797+
601798/**
602799 * rdma_rw_ctx_destroy_signature - release all resources allocated by
603800 * rdma_rw_ctx_signature_init
0 commit comments