Re: [PATCH rdma-next 1/6] RDMA/umem: Combine contiguous PAGE_SIZE regions in SGEs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, Dec 24, 2018 at 04:32:22PM -0600, Shiraz Saleem wrote:
> Combine contiguous regions of PAGE_SIZE pages
> into single scatter list entries while adding
> to the scatter table. This minimizes the number
> of the entries in the scatter list and reduces
> the DMA mapping overhead, particularly with the
> IOMMU.
> 
> Additionally, update driver call sites to use the
> for_each_sg_page variant to iterate through the
> pages in the SGE. In certain call sites, there is
> the assumption of single SGE to page mapping and
> hence the iterator variant is required. In others,
> it is simpler to use the iterator variant.
> 
> Suggested-by: Jason Gunthorpe <jgg@xxxxxxxx>
> Reviewed-by: Michael J. Ruhl <michael.j.ruhl@xxxxxxxxx>
> Signed-off-by: Shiraz Saleem <shiraz.saleem@xxxxxxxxx>
>  drivers/infiniband/core/umem.c                 |  87 ++++++++---
>  drivers/infiniband/hw/bnxt_re/ib_verbs.c       |  21 +--
>  drivers/infiniband/hw/bnxt_re/qplib_res.c      |   9 +-
>  drivers/infiniband/hw/cxgb3/iwch_provider.c    |  27 ++--
>  drivers/infiniband/hw/cxgb4/mem.c              |  31 ++--
>  drivers/infiniband/hw/hns/hns_roce_hw_v1.c     |   7 +-
>  drivers/infiniband/hw/hns/hns_roce_hw_v2.c     |  25 ++-
>  drivers/infiniband/hw/hns/hns_roce_mr.c        |  88 +++++------
>  drivers/infiniband/hw/i40iw/i40iw_verbs.c      |  35 ++---
>  drivers/infiniband/hw/mthca/mthca_provider.c   |  33 ++--
>  drivers/infiniband/hw/nes/nes_verbs.c          | 203 +++++++++++--------------
>  drivers/infiniband/hw/ocrdma/ocrdma_verbs.c    |  54 +++----
>  drivers/infiniband/hw/qedr/verbs.c             |  56 +++----
>  drivers/infiniband/hw/vmw_pvrdma/pvrdma_misc.c |  21 +--
>  drivers/infiniband/sw/rdmavt/mr.c              |   8 +-
>  drivers/infiniband/sw/rxe/rxe_mr.c             |   7 +-
>  16 files changed, 342 insertions(+), 370 deletions(-)
> 
> diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c
> index c6144df..64bacc5 100644
> +++ b/drivers/infiniband/core/umem.c
> @@ -39,25 +39,23 @@
>  #include <linux/export.h>
>  #include <linux/hugetlb.h>
>  #include <linux/slab.h>
> +#include <linux/pagemap.h>
>  #include <rdma/ib_umem_odp.h>
>  
>  #include "uverbs.h"
>  
> -
>  static void __ib_umem_release(struct ib_device *dev, struct ib_umem *umem, int dirty)
>  {
> -	struct scatterlist *sg;
> +	struct sg_page_iter sg_iter;
>  	struct page *page;
> -	int i;
> +	int nents = sg_nents(umem->sg_head.sgl);

I wonder if we should cache sg_nents in the umem? We compute it twice
and since this now directly adds each sgl we know the nents
naturally..

> +/* ib_umem_add_sg_table - Add N contiguous pages to scatter table
> + *
> + * cur: current scatterlist entry
> + * nxt: next scatterlist entry
> + * page_list: array of npage struct page pointers
> + * npages: number of pages in page_list
> + */
> +static void ib_umem_add_sg_table(struct scatterlist **cur,
> +				 struct scatterlist **nxt,
> +				 struct page **page_list,
> +				 unsigned long npages)

I think this is more understandable as:

struct scatterlist *ib_umem_add_sg_table(struct scatterlist *sgl,
                                 struct page **page_list,
				 unsigned long npages,
                                 bool first)

Where first is set if sgl does not already point to a valid entry, and
the return result is new end of the list.


> +	/* Check if new page_list is contiguous with end of previous page_list*/
> +	if (*cur != *nxt) {
> +		cur_sglen = (*cur)->length >> PAGE_SHIFT;
> +		first_pfn = page_to_pfn(sg_page(*cur));
> +		if (first_pfn + cur_sglen == page_to_pfn(page_list[0]))
> +			update_cur_sg = true;
> +	}
> +
> +	while (i != npages) {
> +		unsigned long len;
> +		struct page *first_page = page_list[i];
> +
> +		first_pfn = page_to_pfn(first_page);
> +
> +		/* Compute the number of contiguous pages we have starting
> +		 * at i
> +		 */
> +		for (len = 0; i != npages &&
> +			      first_pfn + len == page_to_pfn(page_list[i]);
> +		     i++, len++);

The semicolon should be on a blank line alone for this construction

> +
> +		/* Squash first N contiguous pages from page_list into current
> +		 * SGE
> +		 */
> +		if (update_cur_sg) {
> +			sg_set_page(*cur, sg_page(*cur),
> +				    (len + cur_sglen) * PAGE_SIZE, 0);

This would be nicer as (*cur)->length instead of cur_sglen

And if we are touching cur->length, it begs the question why not just
write cur->length += len << PAGE_SHIFT ?

> +	sg_mark_end(sg_cur);

This seems like a good approach for now. We can look at trimming the
unused memory later..

Jason



[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Photo]     [Yosemite News]     [Yosemite Photos]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux