Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9aa8b321 authored by Bart Van Assche's avatar Bart Van Assche Committed by Doug Ledford
Browse files

IB/core: Enhance ib_map_mr_sg()



The SRP initiator allows to set max_sectors to a value that exceeds
the largest amount of data that can be mapped at once with an mlx4
HCA using fast registration and a page size of 4 KB. Hence modify
ib_map_mr_sg() such that it can map partial sg-elements. If an
sg-element has been mapped partially, let the caller know
which fraction has been mapped by adjusting *sg_offset.

Signed-off-by: default avatarBart Van Assche <bart.vanassche@sandisk.com>
Tested-by: default avatarLaurence Oberman <loberman@redhat.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Sagi Grimberg <sagi@grimberg.me>
Signed-off-by: default avatarDoug Ledford <dledford@redhat.com>
parent f83b2561
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -92,7 +92,7 @@ static int rdma_rw_init_one_mr(struct ib_qp *qp, u8 port_num,
		reg->inv_wr.next = NULL;
	}

	ret = ib_map_mr_sg(reg->mr, sg, nents, offset, PAGE_SIZE);
	ret = ib_map_mr_sg(reg->mr, sg, nents, &offset, PAGE_SIZE);
	if (ret < nents) {
		ib_mr_pool_put(qp, &qp->rdma_mrs, reg->mr);
		return -EINVAL;
+21 −5
Original line number Diff line number Diff line
@@ -1655,7 +1655,7 @@ EXPORT_SYMBOL(ib_set_vf_guid);
 * is ready for registration.
 */
int ib_map_mr_sg(struct ib_mr *mr, struct scatterlist *sg, int sg_nents,
		unsigned int sg_offset, unsigned int page_size)
		 unsigned int *sg_offset, unsigned int page_size)
{
	if (unlikely(!mr->device->map_mr_sg))
		return -ENOSYS;
@@ -1672,7 +1672,10 @@ EXPORT_SYMBOL(ib_map_mr_sg);
 * @mr:            memory region
 * @sgl:           dma mapped scatterlist
 * @sg_nents:      number of entries in sg
 * @sg_offset:     offset in bytes into sg
 * @sg_offset_p:   IN:  start offset in bytes into sg
 *                 OUT: offset in bytes for element n of the sg of the first
 *                      byte that has not been processed where n is the return
 *                      value of this function.
 * @set_page:      driver page assignment function pointer
 *
 * Core service helper for drivers to convert the largest
@@ -1684,19 +1687,24 @@ EXPORT_SYMBOL(ib_map_mr_sg);
 * a page vector.
 */
int ib_sg_to_pages(struct ib_mr *mr, struct scatterlist *sgl, int sg_nents,
		unsigned int sg_offset, int (*set_page)(struct ib_mr *, u64))
		unsigned int *sg_offset_p, int (*set_page)(struct ib_mr *, u64))
{
	struct scatterlist *sg;
	u64 last_end_dma_addr = 0;
	unsigned int sg_offset = sg_offset_p ? *sg_offset_p : 0;
	unsigned int last_page_off = 0;
	u64 page_mask = ~((u64)mr->page_size - 1);
	int i, ret;

	if (unlikely(sg_nents <= 0 || sg_offset > sg_dma_len(&sgl[0])))
		return -EINVAL;

	mr->iova = sg_dma_address(&sgl[0]) + sg_offset;
	mr->length = 0;

	for_each_sg(sgl, sg, sg_nents, i) {
		u64 dma_addr = sg_dma_address(sg) + sg_offset;
		u64 prev_addr = dma_addr;
		unsigned int dma_len = sg_dma_len(sg) - sg_offset;
		u64 end_dma_addr = dma_addr + dma_len;
		u64 page_addr = dma_addr & page_mask;
@@ -1721,8 +1729,14 @@ int ib_sg_to_pages(struct ib_mr *mr, struct scatterlist *sgl, int sg_nents,

		do {
			ret = set_page(mr, page_addr);
			if (unlikely(ret < 0))
				return i ? : ret;
			if (unlikely(ret < 0)) {
				sg_offset = prev_addr - sg_dma_address(sg);
				mr->length += prev_addr - dma_addr;
				if (sg_offset_p)
					*sg_offset_p = sg_offset;
				return i || sg_offset ? i : ret;
			}
			prev_addr = page_addr;
next_page:
			page_addr += mr->page_size;
		} while (page_addr < end_dma_addr);
@@ -1734,6 +1748,8 @@ int ib_sg_to_pages(struct ib_mr *mr, struct scatterlist *sgl, int sg_nents,
		sg_offset = 0;
	}

	if (sg_offset_p)
		*sg_offset_p = 0;
	return i;
}
EXPORT_SYMBOL(ib_sg_to_pages);
+1 −1
Original line number Diff line number Diff line
@@ -784,7 +784,7 @@ static int iwch_set_page(struct ib_mr *ibmr, u64 addr)
}

static int iwch_map_mr_sg(struct ib_mr *ibmr, struct scatterlist *sg,
		int sg_nents, unsigned sg_offset)
			  int sg_nents, unsigned int *sg_offset)
{
	struct iwch_mr *mhp = to_iwch_mr(ibmr);

+1 −1
Original line number Diff line number Diff line
@@ -918,7 +918,7 @@ struct ib_mr *c4iw_alloc_mr(struct ib_pd *pd,
			    enum ib_mr_type mr_type,
			    u32 max_num_sg);
int c4iw_map_mr_sg(struct ib_mr *ibmr, struct scatterlist *sg, int sg_nents,
		unsigned int sg_offset);
		   unsigned int *sg_offset);
int c4iw_dealloc_mw(struct ib_mw *mw);
struct ib_mw *c4iw_alloc_mw(struct ib_pd *pd, enum ib_mw_type type,
			    struct ib_udata *udata);
+1 −1
Original line number Diff line number Diff line
@@ -691,7 +691,7 @@ static int c4iw_set_page(struct ib_mr *ibmr, u64 addr)
}

int c4iw_map_mr_sg(struct ib_mr *ibmr, struct scatterlist *sg, int sg_nents,
		unsigned int sg_offset)
		   unsigned int *sg_offset)
{
	struct c4iw_mr *mhp = to_c4iw_mr(ibmr);

Loading