Skip to content

Commit 90e7a6d

Browse files
maorgottliebjgunthorpe
authored andcommitted
lib/scatterlist: Provide a dedicated function to support table append
RDMA is the only in-kernel user that uses __sg_alloc_table_from_pages to append pages dynamically. In the next patch. That mode will be extended and that function will get more parameters. So separate it into a unique function to make such change more clear. Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Maor Gottlieb <[email protected]> Signed-off-by: Leon Romanovsky <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]>
1 parent 7c60610 commit 90e7a6d

File tree

7 files changed

+90
-52
lines changed

7 files changed

+90
-52
lines changed

drivers/gpu/drm/drm_prime.c

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -807,8 +807,8 @@ struct sg_table *drm_prime_pages_to_sg(struct drm_device *dev,
807807
struct page **pages, unsigned int nr_pages)
808808
{
809809
struct sg_table *sg;
810-
struct scatterlist *sge;
811810
size_t max_segment = 0;
811+
int err;
812812

813813
sg = kmalloc(sizeof(struct sg_table), GFP_KERNEL);
814814
if (!sg)
@@ -818,13 +818,12 @@ struct sg_table *drm_prime_pages_to_sg(struct drm_device *dev,
818818
max_segment = dma_max_mapping_size(dev->dev);
819819
if (max_segment == 0)
820820
max_segment = UINT_MAX;
821-
sge = __sg_alloc_table_from_pages(sg, pages, nr_pages, 0,
822-
nr_pages << PAGE_SHIFT,
823-
max_segment,
824-
NULL, 0, GFP_KERNEL);
825-
if (IS_ERR(sge)) {
821+
err = sg_alloc_table_from_pages_segment(sg, pages, nr_pages, 0,
822+
nr_pages << PAGE_SHIFT,
823+
max_segment, GFP_KERNEL);
824+
if (err) {
826825
kfree(sg);
827-
sg = ERR_CAST(sge);
826+
sg = ERR_PTR(err);
828827
}
829828
return sg;
830829
}

drivers/gpu/drm/i915/gem/i915_gem_userptr.c

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,6 @@ static int i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj)
133133
unsigned int max_segment = i915_sg_segment_size();
134134
struct sg_table *st;
135135
unsigned int sg_page_sizes;
136-
struct scatterlist *sg;
137136
struct page **pvec;
138137
int ret;
139138

@@ -153,13 +152,11 @@ static int i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj)
153152
spin_unlock(&i915->mm.notifier_lock);
154153

155154
alloc_table:
156-
sg = __sg_alloc_table_from_pages(st, pvec, num_pages, 0,
157-
num_pages << PAGE_SHIFT, max_segment,
158-
NULL, 0, GFP_KERNEL);
159-
if (IS_ERR(sg)) {
160-
ret = PTR_ERR(sg);
155+
ret = sg_alloc_table_from_pages_segment(st, pvec, num_pages, 0,
156+
num_pages << PAGE_SHIFT,
157+
max_segment, GFP_KERNEL);
158+
if (ret)
161159
goto err;
162-
}
163160

164161
ret = i915_gem_gtt_prepare_pages(obj, st);
165162
if (ret) {

drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,6 @@ static int vmw_ttm_map_dma(struct vmw_ttm_tt *vmw_tt)
363363
int ret = 0;
364364
static size_t sgl_size;
365365
static size_t sgt_size;
366-
struct scatterlist *sg;
367366

368367
if (vmw_tt->mapped)
369368
return 0;
@@ -386,15 +385,12 @@ static int vmw_ttm_map_dma(struct vmw_ttm_tt *vmw_tt)
386385
if (unlikely(ret != 0))
387386
return ret;
388387

389-
sg = __sg_alloc_table_from_pages(&vmw_tt->sgt, vsgt->pages,
390-
vsgt->num_pages, 0,
391-
(unsigned long) vsgt->num_pages << PAGE_SHIFT,
392-
dma_get_max_seg_size(dev_priv->drm.dev),
393-
NULL, 0, GFP_KERNEL);
394-
if (IS_ERR(sg)) {
395-
ret = PTR_ERR(sg);
388+
ret = sg_alloc_table_from_pages_segment(
389+
&vmw_tt->sgt, vsgt->pages, vsgt->num_pages, 0,
390+
(unsigned long)vsgt->num_pages << PAGE_SHIFT,
391+
dma_get_max_seg_size(dev_priv->drm.dev), GFP_KERNEL);
392+
if (ret)
396393
goto out_sg_alloc_fail;
397-
}
398394

399395
if (vsgt->num_pages > vmw_tt->sgt.orig_nents) {
400396
uint64_t over_alloc =

drivers/infiniband/core/umem.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,8 +226,8 @@ struct ib_umem *ib_umem_get(struct ib_device *device, unsigned long addr,
226226

227227
cur_base += ret * PAGE_SIZE;
228228
npages -= ret;
229-
sg = __sg_alloc_table_from_pages(&umem->sg_head, page_list, ret,
230-
0, ret << PAGE_SHIFT,
229+
sg = sg_alloc_append_table_from_pages(&umem->sg_head, page_list,
230+
ret, 0, ret << PAGE_SHIFT,
231231
ib_dma_max_seg_size(device), sg, npages,
232232
GFP_KERNEL);
233233
umem->sg_nents = umem->sg_head.nents;

include/linux/scatterlist.h

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -285,14 +285,45 @@ void sg_free_table(struct sg_table *);
285285
int __sg_alloc_table(struct sg_table *, unsigned int, unsigned int,
286286
struct scatterlist *, unsigned int, gfp_t, sg_alloc_fn *);
287287
int sg_alloc_table(struct sg_table *, unsigned int, gfp_t);
288-
struct scatterlist *__sg_alloc_table_from_pages(struct sg_table *sgt,
288+
struct scatterlist *sg_alloc_append_table_from_pages(struct sg_table *sgt,
289289
struct page **pages, unsigned int n_pages, unsigned int offset,
290290
unsigned long size, unsigned int max_segment,
291291
struct scatterlist *prv, unsigned int left_pages,
292292
gfp_t gfp_mask);
293-
int sg_alloc_table_from_pages(struct sg_table *sgt, struct page **pages,
294-
unsigned int n_pages, unsigned int offset,
295-
unsigned long size, gfp_t gfp_mask);
293+
int sg_alloc_table_from_pages_segment(struct sg_table *sgt, struct page **pages,
294+
unsigned int n_pages, unsigned int offset,
295+
unsigned long size,
296+
unsigned int max_segment, gfp_t gfp_mask);
297+
298+
/**
299+
* sg_alloc_table_from_pages - Allocate and initialize an sg table from
300+
* an array of pages
301+
* @sgt: The sg table header to use
302+
* @pages: Pointer to an array of page pointers
303+
* @n_pages: Number of pages in the pages array
304+
* @offset: Offset from start of the first page to the start of a buffer
305+
* @size: Number of valid bytes in the buffer (after offset)
306+
* @gfp_mask: GFP allocation mask
307+
*
308+
* Description:
309+
* Allocate and initialize an sg table from a list of pages. Contiguous
310+
* ranges of the pages are squashed into a single scatterlist node. A user
311+
* may provide an offset at a start and a size of valid data in a buffer
312+
* specified by the page array. The returned sg table is released by
313+
* sg_free_table.
314+
*
315+
* Returns:
316+
* 0 on success, negative error on failure
317+
*/
318+
static inline int sg_alloc_table_from_pages(struct sg_table *sgt,
319+
struct page **pages,
320+
unsigned int n_pages,
321+
unsigned int offset,
322+
unsigned long size, gfp_t gfp_mask)
323+
{
324+
return sg_alloc_table_from_pages_segment(sgt, pages, n_pages, offset,
325+
size, UINT_MAX, gfp_mask);
326+
}
296327

297328
#ifdef CONFIG_SGL_ALLOC
298329
struct scatterlist *sgl_alloc_order(unsigned long long length,

lib/scatterlist.c

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,7 @@ static struct scatterlist *get_next_sg(struct sg_table *table,
397397
}
398398

399399
/**
400-
* __sg_alloc_table_from_pages - Allocate and initialize an sg table from
400+
* sg_alloc_append_table_from_pages - Allocate and initialize an sg table from
401401
* an array of pages
402402
* @sgt: The sg table header to use
403403
* @pages: Pointer to an array of page pointers
@@ -425,7 +425,7 @@ static struct scatterlist *get_next_sg(struct sg_table *table,
425425
* If this function returns non-0 (eg failure), the caller must call
426426
* sg_free_table() to cleanup any leftover allocations.
427427
*/
428-
struct scatterlist *__sg_alloc_table_from_pages(struct sg_table *sgt,
428+
struct scatterlist *sg_alloc_append_table_from_pages(struct sg_table *sgt,
429429
struct page **pages, unsigned int n_pages, unsigned int offset,
430430
unsigned long size, unsigned int max_segment,
431431
struct scatterlist *prv, unsigned int left_pages,
@@ -520,36 +520,40 @@ struct scatterlist *__sg_alloc_table_from_pages(struct sg_table *sgt,
520520
sg_mark_end(s);
521521
return s;
522522
}
523-
EXPORT_SYMBOL(__sg_alloc_table_from_pages);
523+
EXPORT_SYMBOL(sg_alloc_append_table_from_pages);
524524

525525
/**
526-
* sg_alloc_table_from_pages - Allocate and initialize an sg table from
527-
* an array of pages
526+
* sg_alloc_table_from_pages_segment - Allocate and initialize an sg table from
527+
* an array of pages and given maximum
528+
* segment.
528529
* @sgt: The sg table header to use
529530
* @pages: Pointer to an array of page pointers
530531
* @n_pages: Number of pages in the pages array
531532
* @offset: Offset from start of the first page to the start of a buffer
532533
* @size: Number of valid bytes in the buffer (after offset)
534+
* @max_segment: Maximum size of a scatterlist element in bytes
533535
* @gfp_mask: GFP allocation mask
534536
*
535537
* Description:
536538
* Allocate and initialize an sg table from a list of pages. Contiguous
537-
* ranges of the pages are squashed into a single scatterlist node. A user
538-
* may provide an offset at a start and a size of valid data in a buffer
539-
* specified by the page array. The returned sg table is released by
540-
* sg_free_table.
539+
* ranges of the pages are squashed into a single scatterlist node up to the
540+
* maximum size specified in @max_segment. A user may provide an offset at a
541+
* start and a size of valid data in a buffer specified by the page array.
541542
*
542-
* Returns:
543+
* The returned sg table is released by sg_free_table.
544+
*
545+
* Returns:
543546
* 0 on success, negative error on failure
544547
*/
545-
int sg_alloc_table_from_pages(struct sg_table *sgt, struct page **pages,
546-
unsigned int n_pages, unsigned int offset,
547-
unsigned long size, gfp_t gfp_mask)
548+
int sg_alloc_table_from_pages_segment(struct sg_table *sgt, struct page **pages,
549+
unsigned int n_pages, unsigned int offset,
550+
unsigned long size, unsigned int max_segment,
551+
gfp_t gfp_mask)
548552
{
549-
return PTR_ERR_OR_ZERO(__sg_alloc_table_from_pages(sgt, pages, n_pages,
550-
offset, size, UINT_MAX, NULL, 0, gfp_mask));
553+
return PTR_ERR_OR_ZERO(sg_alloc_append_table_from_pages(sgt, pages,
554+
n_pages, offset, size, max_segment, NULL, 0, gfp_mask));
551555
}
552-
EXPORT_SYMBOL(sg_alloc_table_from_pages);
556+
EXPORT_SYMBOL(sg_alloc_table_from_pages_segment);
553557

554558
#ifdef CONFIG_SGL_ALLOC
555559

tools/testing/scatterlist/main.c

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -87,28 +87,39 @@ int main(void)
8787
int left_pages = test->pfn_app ? test->num_pages : 0;
8888
struct page *pages[MAX_PAGES];
8989
struct sg_table st;
90-
struct scatterlist *sg;
90+
struct scatterlist *sg = NULL;
91+
int ret;
9192

9293
set_pages(pages, test->pfn, test->num_pages);
9394

94-
sg = __sg_alloc_table_from_pages(&st, pages, test->num_pages, 0,
95-
test->size, test->max_seg, NULL, left_pages, GFP_KERNEL);
96-
assert(PTR_ERR_OR_ZERO(sg) == test->alloc_ret);
95+
if (test->pfn_app) {
96+
sg = sg_alloc_append_table_from_pages(
97+
&st, pages, test->num_pages, 0, test->size,
98+
test->max_seg, NULL, left_pages, GFP_KERNEL);
99+
assert(PTR_ERR_OR_ZERO(sg) == test->alloc_ret);
100+
} else {
101+
ret = sg_alloc_table_from_pages_segment(
102+
&st, pages, test->num_pages, 0, test->size,
103+
test->max_seg, GFP_KERNEL);
104+
assert(ret == test->alloc_ret);
105+
}
97106

98107
if (test->alloc_ret)
99108
continue;
100109

101110
if (test->pfn_app) {
102111
set_pages(pages, test->pfn_app, test->num_pages);
103-
sg = __sg_alloc_table_from_pages(&st, pages, test->num_pages, 0,
104-
test->size, test->max_seg, sg, 0, GFP_KERNEL);
112+
sg = sg_alloc_append_table_from_pages(
113+
&st, pages, test->num_pages, 0, test->size,
114+
test->max_seg, sg, 0, GFP_KERNEL);
105115

106116
assert(PTR_ERR_OR_ZERO(sg) == test->alloc_ret);
107117
}
108118

109119
VALIDATE(st.nents == test->expected_segments, &st, test);
110120
if (!test->pfn_app)
111-
VALIDATE(st.orig_nents == test->expected_segments, &st, test);
121+
VALIDATE(st.orig_nents == test->expected_segments, &st,
122+
test);
112123

113124
sg_free_table(&st);
114125
}

0 commit comments

Comments
 (0)