From: Leon Romanovsky <leon@kernel.org>
To: Christoph Hellwig <hch@lst.de>,
Doug Ledford <dledford@redhat.com>,
Jason Gunthorpe <jgg@nvidia.com>
Cc: Maor Gottlieb <maorg@nvidia.com>,
linux-kernel@vger.kernel.org, linux-rdma@vger.kernel.org
Subject: [PATCH rdma-next 2/4] lib/scatterlist: Add support in dynamically allocation of SG entries
Date: Thu, 3 Sep 2020 15:18:51 +0300 [thread overview]
Message-ID: <20200903121853.1145976-3-leon@kernel.org> (raw)
In-Reply-To: <20200903121853.1145976-1-leon@kernel.org>
From: Maor Gottlieb <maorg@nvidia.com>
In order to support dynamic allocation of SG table, this patch
introduces sg_alloc_next. This function should be called to add more
entries to the table. In order to share the code, we will do the
following:
* Extract the allocation code from __sg_alloc_table to sg_alloc.
* Add a function to chain SGE to the next page.
Signed-off-by: Maor Gottlieb <maorg@nvidia.com>
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
---
include/linux/scatterlist.h | 29 ++++++----
lib/scatterlist.c | 110 ++++++++++++++++++++++++------------
2 files changed, 91 insertions(+), 48 deletions(-)
diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h
index 45cf7b69d852..877d6e160b06 100644
--- a/include/linux/scatterlist.h
+++ b/include/linux/scatterlist.h
@@ -165,6 +165,22 @@ static inline void sg_set_buf(struct scatterlist *sg, const void *buf,
#define for_each_sgtable_dma_sg(sgt, sg, i) \
for_each_sg((sgt)->sgl, sg, (sgt)->nents, i)
+static inline void _sg_chain(struct scatterlist *chain_sg,
+ struct scatterlist *sgl)
+{
+ /*
+ * offset and length are unused for chain entry. Clear them.
+ */
+ chain_sg->offset = 0;
+ chain_sg->length = 0;
+
+ /*
+ * Set lowest bit to indicate a link pointer, and make sure to clear
+ * the termination bit if it happens to be set.
+ */
+ chain_sg->page_link = ((unsigned long) sgl | SG_CHAIN) & ~SG_END;
+}
+
/**
* sg_chain - Chain two sglists together
* @prv: First scatterlist
@@ -178,18 +194,7 @@ static inline void sg_set_buf(struct scatterlist *sg, const void *buf,
static inline void sg_chain(struct scatterlist *prv, unsigned int prv_nents,
struct scatterlist *sgl)
{
- /*
- * offset and length are unused for chain entry. Clear them.
- */
- prv[prv_nents - 1].offset = 0;
- prv[prv_nents - 1].length = 0;
-
- /*
- * Set lowest bit to indicate a link pointer, and make sure to clear
- * the termination bit if it happens to be set.
- */
- prv[prv_nents - 1].page_link = ((unsigned long) sgl | SG_CHAIN)
- & ~SG_END;
+ _sg_chain(&prv[prv_nents - 1], sgl);
}
/**
diff --git a/lib/scatterlist.c b/lib/scatterlist.c
index 292e785d21ee..669bd6e6d16a 100644
--- a/lib/scatterlist.c
+++ b/lib/scatterlist.c
@@ -242,38 +242,15 @@ void sg_free_table(struct sg_table *table)
}
EXPORT_SYMBOL(sg_free_table);
-/**
- * __sg_alloc_table - Allocate and initialize an sg table with given allocator
- * @table: The sg table header to use
- * @nents: Number of entries in sg list
- * @max_ents: The maximum number of entries the allocator returns per call
- * @nents_first_chunk: Number of entries int the (preallocated) first
- * scatterlist chunk, 0 means no such preallocated chunk provided by user
- * @gfp_mask: GFP allocation mask
- * @alloc_fn: Allocator to use
- *
- * Description:
- * This function returns a @table @nents long. The allocator is
- * defined to return scatterlist chunks of maximum size @max_ents.
- * Thus if @nents is bigger than @max_ents, the scatterlists will be
- * chained in units of @max_ents.
- *
- * Notes:
- * If this function returns non-0 (eg failure), the caller must call
- * __sg_free_table() to cleanup any leftover allocations.
- *
- **/
-int __sg_alloc_table(struct sg_table *table, unsigned int nents,
- unsigned int max_ents, struct scatterlist *first_chunk,
- unsigned int nents_first_chunk, gfp_t gfp_mask,
- sg_alloc_fn *alloc_fn)
+static int sg_alloc(struct sg_table *table, struct scatterlist *prv,
+ unsigned int nents, unsigned int max_ents,
+ struct scatterlist *first_chunk,
+ unsigned int nents_first_chunk,
+ gfp_t gfp_mask, sg_alloc_fn *alloc_fn)
{
- struct scatterlist *sg, *prv;
- unsigned int left;
- unsigned curr_max_ents = nents_first_chunk ?: max_ents;
- unsigned prv_max_ents;
-
- memset(table, 0, sizeof(*table));
+ unsigned int curr_max_ents = nents_first_chunk ?: max_ents;
+ unsigned int left, prv_max_ents = 0;
+ struct scatterlist *sg;
if (nents == 0)
return -EINVAL;
@@ -283,7 +260,6 @@ int __sg_alloc_table(struct sg_table *table, unsigned int nents,
#endif
left = nents;
- prv = NULL;
do {
unsigned int sg_size, alloc_size = left;
@@ -308,7 +284,7 @@ int __sg_alloc_table(struct sg_table *table, unsigned int nents,
* linkage. Without this, sg_kfree() may get
* confused.
*/
- if (prv)
+ if (prv_max_ents)
table->nents = ++table->orig_nents;
return -ENOMEM;
@@ -321,10 +297,17 @@ int __sg_alloc_table(struct sg_table *table, unsigned int nents,
* If this is the first mapping, assign the sg table header.
* If this is not the first mapping, chain previous part.
*/
- if (prv)
- sg_chain(prv, prv_max_ents, sg);
- else
+ if (!prv)
table->sgl = sg;
+ else if (prv_max_ents)
+ sg_chain(prv, prv_max_ents, sg);
+ else {
+ _sg_chain(prv, sg);
+ /* We decrease one since the prvious last sge in used to
+ * chainning.
+ */
+ table->nents = table->orig_nents -= 1;
+ }
/*
* If no more entries after this one, mark the end
@@ -339,6 +322,61 @@ int __sg_alloc_table(struct sg_table *table, unsigned int nents,
return 0;
}
+
+/**
+ * sg_alloc_next - Allocate and initialize new entries in the sg table
+ * @table: The sg table header to use
+ * @last: The last scatter list entry in the table
+ * @nents: Number of entries in sg list
+ * @max_ents: The maximum number of entries the allocator returns per call
+ * @gfp_mask: GFP allocation mask
+ * @alloc_fn: Allocator to use
+ *
+ * Description:
+ * This function extend @table with @nents long. The allocator is
+ * defined to return scatterlist chunks of maximum size @max_ents.
+ * Thus if @nents is bigger than @max_ents, the scatterlists will be
+ * chained in units of @max_ents.
+ *
+ **/
+static int sg_alloc_next(struct sg_table *table, struct scatterlist *last,
+ unsigned int nents, unsigned int max_ents,
+ gfp_t gfp_mask)
+{
+ return sg_alloc(table, last, nents, max_ents, NULL, 0, gfp_mask,
+ sg_kmalloc);
+}
+
+/**
+ * __sg_alloc_table - Allocate and initialize an sg table with given allocator
+ * @table: The sg table header to use
+ * @nents: Number of entries in sg list
+ * @max_ents: The maximum number of entries the allocator returns per call
+ * @nents_first_chunk: Number of entries int the (preallocated) first
+ * scatterlist chunk, 0 means no such preallocated chunk provided by user
+ * @gfp_mask: GFP allocation mask
+ * @alloc_fn: Allocator to use
+ *
+ * Description:
+ * This function returns a @table @nents long. The allocator is
+ * defined to return scatterlist chunks of maximum size @max_ents.
+ * Thus if @nents is bigger than @max_ents, the scatterlists will be
+ * chained in units of @max_ents.
+ *
+ * Notes:
+ * If this function returns non-0 (eg failure), the caller must call
+ * __sg_free_table() to cleanup any leftover allocations.
+ *
+ **/
+int __sg_alloc_table(struct sg_table *table, unsigned int nents,
+ unsigned int max_ents, struct scatterlist *first_chunk,
+ unsigned int nents_first_chunk, gfp_t gfp_mask,
+ sg_alloc_fn *alloc_fn)
+{
+ memset(table, 0, sizeof(*table));
+ return sg_alloc(table, NULL, nents, max_ents, first_chunk,
+ nents_first_chunk, gfp_mask, alloc_fn);
+}
EXPORT_SYMBOL(__sg_alloc_table);
/**
--
2.26.2
next prev parent reply other threads:[~2020-09-03 15:12 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-09-03 12:18 [PATCH rdma-next 0/4] scatterlist: add sg_alloc_table_append function Leon Romanovsky
2020-09-03 12:18 ` Leon Romanovsky [this message]
2020-09-07 7:29 ` [PATCH rdma-next 2/4] lib/scatterlist: Add support in dynamically allocation of SG entries Christoph Hellwig
2020-09-07 12:34 ` Maor Gottlieb
2020-09-03 12:18 ` [PATCH rdma-next 3/4] lib/scatterlist: Add support in dynamic allocation of SG table from pages Leon Romanovsky
2020-09-07 7:29 ` Christoph Hellwig
2020-09-07 12:44 ` Maor Gottlieb
2020-09-08 15:54 ` Christoph Hellwig
2020-09-08 16:13 ` Jason Gunthorpe
2020-09-03 12:18 ` [PATCH rdma-next 4/4] RDMA/umem: Move to allocate " Leon Romanovsky
2020-09-07 7:29 ` Christoph Hellwig
2020-09-08 14:10 ` Jason Gunthorpe
2020-09-03 15:32 ` [PATCH rdma-next 0/4] scatterlist: add sg_alloc_table_append function Christoph Hellwig
2020-09-03 15:55 ` Leon Romanovsky
2020-09-03 15:54 ` [PATCH rdma-next 1/4] lib/scatterlist: Refactor sg_alloc_table_from_pages Leon Romanovsky
2020-09-07 7:29 ` Christoph Hellwig
2020-09-07 12:32 ` Maor Gottlieb
2020-09-08 15:52 ` Christoph Hellwig
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200903121853.1145976-3-leon@kernel.org \
--to=leon@kernel.org \
--cc=dledford@redhat.com \
--cc=hch@lst.de \
--cc=jgg@nvidia.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-rdma@vger.kernel.org \
--cc=maorg@nvidia.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.