162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2007 Jens Axboe <jens.axboe@oracle.com>
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Scatterlist handling helpers.
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci#include <linux/export.h>
862306a36Sopenharmony_ci#include <linux/slab.h>
962306a36Sopenharmony_ci#include <linux/scatterlist.h>
1062306a36Sopenharmony_ci#include <linux/highmem.h>
1162306a36Sopenharmony_ci#include <linux/kmemleak.h>
1262306a36Sopenharmony_ci#include <linux/bvec.h>
1362306a36Sopenharmony_ci#include <linux/uio.h>
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci/**
1662306a36Sopenharmony_ci * sg_next - return the next scatterlist entry in a list
1762306a36Sopenharmony_ci * @sg:		The current sg entry
1862306a36Sopenharmony_ci *
1962306a36Sopenharmony_ci * Description:
2062306a36Sopenharmony_ci *   Usually the next entry will be @sg@ + 1, but if this sg element is part
2162306a36Sopenharmony_ci *   of a chained scatterlist, it could jump to the start of a new
2262306a36Sopenharmony_ci *   scatterlist array.
2362306a36Sopenharmony_ci *
2462306a36Sopenharmony_ci **/
2562306a36Sopenharmony_cistruct scatterlist *sg_next(struct scatterlist *sg)
2662306a36Sopenharmony_ci{
2762306a36Sopenharmony_ci	if (sg_is_last(sg))
2862306a36Sopenharmony_ci		return NULL;
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci	sg++;
3162306a36Sopenharmony_ci	if (unlikely(sg_is_chain(sg)))
3262306a36Sopenharmony_ci		sg = sg_chain_ptr(sg);
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci	return sg;
3562306a36Sopenharmony_ci}
3662306a36Sopenharmony_ciEXPORT_SYMBOL(sg_next);
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci/**
3962306a36Sopenharmony_ci * sg_nents - return total count of entries in scatterlist
4062306a36Sopenharmony_ci * @sg:		The scatterlist
4162306a36Sopenharmony_ci *
4262306a36Sopenharmony_ci * Description:
4362306a36Sopenharmony_ci * Allows to know how many entries are in sg, taking into account
4462306a36Sopenharmony_ci * chaining as well
4562306a36Sopenharmony_ci *
4662306a36Sopenharmony_ci **/
4762306a36Sopenharmony_ciint sg_nents(struct scatterlist *sg)
4862306a36Sopenharmony_ci{
4962306a36Sopenharmony_ci	int nents;
5062306a36Sopenharmony_ci	for (nents = 0; sg; sg = sg_next(sg))
5162306a36Sopenharmony_ci		nents++;
5262306a36Sopenharmony_ci	return nents;
5362306a36Sopenharmony_ci}
5462306a36Sopenharmony_ciEXPORT_SYMBOL(sg_nents);
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci/**
5762306a36Sopenharmony_ci * sg_nents_for_len - return total count of entries in scatterlist
5862306a36Sopenharmony_ci *                    needed to satisfy the supplied length
5962306a36Sopenharmony_ci * @sg:		The scatterlist
6062306a36Sopenharmony_ci * @len:	The total required length
6162306a36Sopenharmony_ci *
6262306a36Sopenharmony_ci * Description:
6362306a36Sopenharmony_ci * Determines the number of entries in sg that are required to meet
6462306a36Sopenharmony_ci * the supplied length, taking into account chaining as well
6562306a36Sopenharmony_ci *
6662306a36Sopenharmony_ci * Returns:
6762306a36Sopenharmony_ci *   the number of sg entries needed, negative error on failure
6862306a36Sopenharmony_ci *
6962306a36Sopenharmony_ci **/
7062306a36Sopenharmony_ciint sg_nents_for_len(struct scatterlist *sg, u64 len)
7162306a36Sopenharmony_ci{
7262306a36Sopenharmony_ci	int nents;
7362306a36Sopenharmony_ci	u64 total;
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci	if (!len)
7662306a36Sopenharmony_ci		return 0;
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci	for (nents = 0, total = 0; sg; sg = sg_next(sg)) {
7962306a36Sopenharmony_ci		nents++;
8062306a36Sopenharmony_ci		total += sg->length;
8162306a36Sopenharmony_ci		if (total >= len)
8262306a36Sopenharmony_ci			return nents;
8362306a36Sopenharmony_ci	}
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci	return -EINVAL;
8662306a36Sopenharmony_ci}
8762306a36Sopenharmony_ciEXPORT_SYMBOL(sg_nents_for_len);
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci/**
9062306a36Sopenharmony_ci * sg_last - return the last scatterlist entry in a list
9162306a36Sopenharmony_ci * @sgl:	First entry in the scatterlist
9262306a36Sopenharmony_ci * @nents:	Number of entries in the scatterlist
9362306a36Sopenharmony_ci *
9462306a36Sopenharmony_ci * Description:
9562306a36Sopenharmony_ci *   Should only be used casually, it (currently) scans the entire list
9662306a36Sopenharmony_ci *   to get the last entry.
9762306a36Sopenharmony_ci *
9862306a36Sopenharmony_ci *   Note that the @sgl@ pointer passed in need not be the first one,
9962306a36Sopenharmony_ci *   the important bit is that @nents@ denotes the number of entries that
10062306a36Sopenharmony_ci *   exist from @sgl@.
10162306a36Sopenharmony_ci *
10262306a36Sopenharmony_ci **/
10362306a36Sopenharmony_cistruct scatterlist *sg_last(struct scatterlist *sgl, unsigned int nents)
10462306a36Sopenharmony_ci{
10562306a36Sopenharmony_ci	struct scatterlist *sg, *ret = NULL;
10662306a36Sopenharmony_ci	unsigned int i;
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci	for_each_sg(sgl, sg, nents, i)
10962306a36Sopenharmony_ci		ret = sg;
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci	BUG_ON(!sg_is_last(ret));
11262306a36Sopenharmony_ci	return ret;
11362306a36Sopenharmony_ci}
11462306a36Sopenharmony_ciEXPORT_SYMBOL(sg_last);
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci/**
11762306a36Sopenharmony_ci * sg_init_table - Initialize SG table
11862306a36Sopenharmony_ci * @sgl:	   The SG table
11962306a36Sopenharmony_ci * @nents:	   Number of entries in table
12062306a36Sopenharmony_ci *
12162306a36Sopenharmony_ci * Notes:
12262306a36Sopenharmony_ci *   If this is part of a chained sg table, sg_mark_end() should be
12362306a36Sopenharmony_ci *   used only on the last table part.
12462306a36Sopenharmony_ci *
12562306a36Sopenharmony_ci **/
12662306a36Sopenharmony_civoid sg_init_table(struct scatterlist *sgl, unsigned int nents)
12762306a36Sopenharmony_ci{
12862306a36Sopenharmony_ci	memset(sgl, 0, sizeof(*sgl) * nents);
12962306a36Sopenharmony_ci	sg_init_marker(sgl, nents);
13062306a36Sopenharmony_ci}
13162306a36Sopenharmony_ciEXPORT_SYMBOL(sg_init_table);
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci/**
13462306a36Sopenharmony_ci * sg_init_one - Initialize a single entry sg list
13562306a36Sopenharmony_ci * @sg:		 SG entry
13662306a36Sopenharmony_ci * @buf:	 Virtual address for IO
13762306a36Sopenharmony_ci * @buflen:	 IO length
13862306a36Sopenharmony_ci *
13962306a36Sopenharmony_ci **/
14062306a36Sopenharmony_civoid sg_init_one(struct scatterlist *sg, const void *buf, unsigned int buflen)
14162306a36Sopenharmony_ci{
14262306a36Sopenharmony_ci	sg_init_table(sg, 1);
14362306a36Sopenharmony_ci	sg_set_buf(sg, buf, buflen);
14462306a36Sopenharmony_ci}
14562306a36Sopenharmony_ciEXPORT_SYMBOL(sg_init_one);
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci/*
14862306a36Sopenharmony_ci * The default behaviour of sg_alloc_table() is to use these kmalloc/kfree
14962306a36Sopenharmony_ci * helpers.
15062306a36Sopenharmony_ci */
15162306a36Sopenharmony_cistatic struct scatterlist *sg_kmalloc(unsigned int nents, gfp_t gfp_mask)
15262306a36Sopenharmony_ci{
15362306a36Sopenharmony_ci	if (nents == SG_MAX_SINGLE_ALLOC) {
15462306a36Sopenharmony_ci		/*
15562306a36Sopenharmony_ci		 * Kmemleak doesn't track page allocations as they are not
15662306a36Sopenharmony_ci		 * commonly used (in a raw form) for kernel data structures.
15762306a36Sopenharmony_ci		 * As we chain together a list of pages and then a normal
15862306a36Sopenharmony_ci		 * kmalloc (tracked by kmemleak), in order to for that last
15962306a36Sopenharmony_ci		 * allocation not to become decoupled (and thus a
16062306a36Sopenharmony_ci		 * false-positive) we need to inform kmemleak of all the
16162306a36Sopenharmony_ci		 * intermediate allocations.
16262306a36Sopenharmony_ci		 */
16362306a36Sopenharmony_ci		void *ptr = (void *) __get_free_page(gfp_mask);
16462306a36Sopenharmony_ci		kmemleak_alloc(ptr, PAGE_SIZE, 1, gfp_mask);
16562306a36Sopenharmony_ci		return ptr;
16662306a36Sopenharmony_ci	} else
16762306a36Sopenharmony_ci		return kmalloc_array(nents, sizeof(struct scatterlist),
16862306a36Sopenharmony_ci				     gfp_mask);
16962306a36Sopenharmony_ci}
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_cistatic void sg_kfree(struct scatterlist *sg, unsigned int nents)
17262306a36Sopenharmony_ci{
17362306a36Sopenharmony_ci	if (nents == SG_MAX_SINGLE_ALLOC) {
17462306a36Sopenharmony_ci		kmemleak_free(sg);
17562306a36Sopenharmony_ci		free_page((unsigned long) sg);
17662306a36Sopenharmony_ci	} else
17762306a36Sopenharmony_ci		kfree(sg);
17862306a36Sopenharmony_ci}
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci/**
18162306a36Sopenharmony_ci * __sg_free_table - Free a previously mapped sg table
18262306a36Sopenharmony_ci * @table:	The sg table header to use
18362306a36Sopenharmony_ci * @max_ents:	The maximum number of entries per single scatterlist
18462306a36Sopenharmony_ci * @nents_first_chunk: Number of entries int the (preallocated) first
18562306a36Sopenharmony_ci * 	scatterlist chunk, 0 means no such preallocated first chunk
18662306a36Sopenharmony_ci * @free_fn:	Free function
18762306a36Sopenharmony_ci * @num_ents:	Number of entries in the table
18862306a36Sopenharmony_ci *
18962306a36Sopenharmony_ci *  Description:
19062306a36Sopenharmony_ci *    Free an sg table previously allocated and setup with
19162306a36Sopenharmony_ci *    __sg_alloc_table().  The @max_ents value must be identical to
19262306a36Sopenharmony_ci *    that previously used with __sg_alloc_table().
19362306a36Sopenharmony_ci *
19462306a36Sopenharmony_ci **/
19562306a36Sopenharmony_civoid __sg_free_table(struct sg_table *table, unsigned int max_ents,
19662306a36Sopenharmony_ci		     unsigned int nents_first_chunk, sg_free_fn *free_fn,
19762306a36Sopenharmony_ci		     unsigned int num_ents)
19862306a36Sopenharmony_ci{
19962306a36Sopenharmony_ci	struct scatterlist *sgl, *next;
20062306a36Sopenharmony_ci	unsigned curr_max_ents = nents_first_chunk ?: max_ents;
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci	if (unlikely(!table->sgl))
20362306a36Sopenharmony_ci		return;
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ci	sgl = table->sgl;
20662306a36Sopenharmony_ci	while (num_ents) {
20762306a36Sopenharmony_ci		unsigned int alloc_size = num_ents;
20862306a36Sopenharmony_ci		unsigned int sg_size;
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ci		/*
21162306a36Sopenharmony_ci		 * If we have more than max_ents segments left,
21262306a36Sopenharmony_ci		 * then assign 'next' to the sg table after the current one.
21362306a36Sopenharmony_ci		 * sg_size is then one less than alloc size, since the last
21462306a36Sopenharmony_ci		 * element is the chain pointer.
21562306a36Sopenharmony_ci		 */
21662306a36Sopenharmony_ci		if (alloc_size > curr_max_ents) {
21762306a36Sopenharmony_ci			next = sg_chain_ptr(&sgl[curr_max_ents - 1]);
21862306a36Sopenharmony_ci			alloc_size = curr_max_ents;
21962306a36Sopenharmony_ci			sg_size = alloc_size - 1;
22062306a36Sopenharmony_ci		} else {
22162306a36Sopenharmony_ci			sg_size = alloc_size;
22262306a36Sopenharmony_ci			next = NULL;
22362306a36Sopenharmony_ci		}
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_ci		num_ents -= sg_size;
22662306a36Sopenharmony_ci		if (nents_first_chunk)
22762306a36Sopenharmony_ci			nents_first_chunk = 0;
22862306a36Sopenharmony_ci		else
22962306a36Sopenharmony_ci			free_fn(sgl, alloc_size);
23062306a36Sopenharmony_ci		sgl = next;
23162306a36Sopenharmony_ci		curr_max_ents = max_ents;
23262306a36Sopenharmony_ci	}
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci	table->sgl = NULL;
23562306a36Sopenharmony_ci}
23662306a36Sopenharmony_ciEXPORT_SYMBOL(__sg_free_table);
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_ci/**
23962306a36Sopenharmony_ci * sg_free_append_table - Free a previously allocated append sg table.
24062306a36Sopenharmony_ci * @table:	 The mapped sg append table header
24162306a36Sopenharmony_ci *
24262306a36Sopenharmony_ci **/
24362306a36Sopenharmony_civoid sg_free_append_table(struct sg_append_table *table)
24462306a36Sopenharmony_ci{
24562306a36Sopenharmony_ci	__sg_free_table(&table->sgt, SG_MAX_SINGLE_ALLOC, 0, sg_kfree,
24662306a36Sopenharmony_ci			table->total_nents);
24762306a36Sopenharmony_ci}
24862306a36Sopenharmony_ciEXPORT_SYMBOL(sg_free_append_table);
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_ci/**
25262306a36Sopenharmony_ci * sg_free_table - Free a previously allocated sg table
25362306a36Sopenharmony_ci * @table:	The mapped sg table header
25462306a36Sopenharmony_ci *
25562306a36Sopenharmony_ci **/
25662306a36Sopenharmony_civoid sg_free_table(struct sg_table *table)
25762306a36Sopenharmony_ci{
25862306a36Sopenharmony_ci	__sg_free_table(table, SG_MAX_SINGLE_ALLOC, 0, sg_kfree,
25962306a36Sopenharmony_ci			table->orig_nents);
26062306a36Sopenharmony_ci}
26162306a36Sopenharmony_ciEXPORT_SYMBOL(sg_free_table);
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_ci/**
26462306a36Sopenharmony_ci * __sg_alloc_table - Allocate and initialize an sg table with given allocator
26562306a36Sopenharmony_ci * @table:	The sg table header to use
26662306a36Sopenharmony_ci * @nents:	Number of entries in sg list
26762306a36Sopenharmony_ci * @max_ents:	The maximum number of entries the allocator returns per call
26862306a36Sopenharmony_ci * @first_chunk: first SGL if preallocated (may be %NULL)
26962306a36Sopenharmony_ci * @nents_first_chunk: Number of entries in the (preallocated) first
27062306a36Sopenharmony_ci * 	scatterlist chunk, 0 means no such preallocated chunk provided by user
27162306a36Sopenharmony_ci * @gfp_mask:	GFP allocation mask
27262306a36Sopenharmony_ci * @alloc_fn:	Allocator to use
27362306a36Sopenharmony_ci *
27462306a36Sopenharmony_ci * Description:
27562306a36Sopenharmony_ci *   This function returns a @table @nents long. The allocator is
27662306a36Sopenharmony_ci *   defined to return scatterlist chunks of maximum size @max_ents.
27762306a36Sopenharmony_ci *   Thus if @nents is bigger than @max_ents, the scatterlists will be
27862306a36Sopenharmony_ci *   chained in units of @max_ents.
27962306a36Sopenharmony_ci *
28062306a36Sopenharmony_ci * Notes:
28162306a36Sopenharmony_ci *   If this function returns non-0 (eg failure), the caller must call
28262306a36Sopenharmony_ci *   __sg_free_table() to cleanup any leftover allocations.
28362306a36Sopenharmony_ci *
28462306a36Sopenharmony_ci **/
28562306a36Sopenharmony_ciint __sg_alloc_table(struct sg_table *table, unsigned int nents,
28662306a36Sopenharmony_ci		     unsigned int max_ents, struct scatterlist *first_chunk,
28762306a36Sopenharmony_ci		     unsigned int nents_first_chunk, gfp_t gfp_mask,
28862306a36Sopenharmony_ci		     sg_alloc_fn *alloc_fn)
28962306a36Sopenharmony_ci{
29062306a36Sopenharmony_ci	struct scatterlist *sg, *prv;
29162306a36Sopenharmony_ci	unsigned int left;
29262306a36Sopenharmony_ci	unsigned curr_max_ents = nents_first_chunk ?: max_ents;
29362306a36Sopenharmony_ci	unsigned prv_max_ents;
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_ci	memset(table, 0, sizeof(*table));
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_ci	if (nents == 0)
29862306a36Sopenharmony_ci		return -EINVAL;
29962306a36Sopenharmony_ci#ifdef CONFIG_ARCH_NO_SG_CHAIN
30062306a36Sopenharmony_ci	if (WARN_ON_ONCE(nents > max_ents))
30162306a36Sopenharmony_ci		return -EINVAL;
30262306a36Sopenharmony_ci#endif
30362306a36Sopenharmony_ci
30462306a36Sopenharmony_ci	left = nents;
30562306a36Sopenharmony_ci	prv = NULL;
30662306a36Sopenharmony_ci	do {
30762306a36Sopenharmony_ci		unsigned int sg_size, alloc_size = left;
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_ci		if (alloc_size > curr_max_ents) {
31062306a36Sopenharmony_ci			alloc_size = curr_max_ents;
31162306a36Sopenharmony_ci			sg_size = alloc_size - 1;
31262306a36Sopenharmony_ci		} else
31362306a36Sopenharmony_ci			sg_size = alloc_size;
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ci		left -= sg_size;
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_ci		if (first_chunk) {
31862306a36Sopenharmony_ci			sg = first_chunk;
31962306a36Sopenharmony_ci			first_chunk = NULL;
32062306a36Sopenharmony_ci		} else {
32162306a36Sopenharmony_ci			sg = alloc_fn(alloc_size, gfp_mask);
32262306a36Sopenharmony_ci		}
32362306a36Sopenharmony_ci		if (unlikely(!sg)) {
32462306a36Sopenharmony_ci			/*
32562306a36Sopenharmony_ci			 * Adjust entry count to reflect that the last
32662306a36Sopenharmony_ci			 * entry of the previous table won't be used for
32762306a36Sopenharmony_ci			 * linkage.  Without this, sg_kfree() may get
32862306a36Sopenharmony_ci			 * confused.
32962306a36Sopenharmony_ci			 */
33062306a36Sopenharmony_ci			if (prv)
33162306a36Sopenharmony_ci				table->nents = ++table->orig_nents;
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_ci			return -ENOMEM;
33462306a36Sopenharmony_ci		}
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_ci		sg_init_table(sg, alloc_size);
33762306a36Sopenharmony_ci		table->nents = table->orig_nents += sg_size;
33862306a36Sopenharmony_ci
33962306a36Sopenharmony_ci		/*
34062306a36Sopenharmony_ci		 * If this is the first mapping, assign the sg table header.
34162306a36Sopenharmony_ci		 * If this is not the first mapping, chain previous part.
34262306a36Sopenharmony_ci		 */
34362306a36Sopenharmony_ci		if (prv)
34462306a36Sopenharmony_ci			sg_chain(prv, prv_max_ents, sg);
34562306a36Sopenharmony_ci		else
34662306a36Sopenharmony_ci			table->sgl = sg;
34762306a36Sopenharmony_ci
34862306a36Sopenharmony_ci		/*
34962306a36Sopenharmony_ci		 * If no more entries after this one, mark the end
35062306a36Sopenharmony_ci		 */
35162306a36Sopenharmony_ci		if (!left)
35262306a36Sopenharmony_ci			sg_mark_end(&sg[sg_size - 1]);
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci		prv = sg;
35562306a36Sopenharmony_ci		prv_max_ents = curr_max_ents;
35662306a36Sopenharmony_ci		curr_max_ents = max_ents;
35762306a36Sopenharmony_ci	} while (left);
35862306a36Sopenharmony_ci
35962306a36Sopenharmony_ci	return 0;
36062306a36Sopenharmony_ci}
36162306a36Sopenharmony_ciEXPORT_SYMBOL(__sg_alloc_table);
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_ci/**
36462306a36Sopenharmony_ci * sg_alloc_table - Allocate and initialize an sg table
36562306a36Sopenharmony_ci * @table:	The sg table header to use
36662306a36Sopenharmony_ci * @nents:	Number of entries in sg list
36762306a36Sopenharmony_ci * @gfp_mask:	GFP allocation mask
36862306a36Sopenharmony_ci *
36962306a36Sopenharmony_ci *  Description:
37062306a36Sopenharmony_ci *    Allocate and initialize an sg table. If @nents@ is larger than
37162306a36Sopenharmony_ci *    SG_MAX_SINGLE_ALLOC a chained sg table will be setup.
37262306a36Sopenharmony_ci *
37362306a36Sopenharmony_ci **/
37462306a36Sopenharmony_ciint sg_alloc_table(struct sg_table *table, unsigned int nents, gfp_t gfp_mask)
37562306a36Sopenharmony_ci{
37662306a36Sopenharmony_ci	int ret;
37762306a36Sopenharmony_ci
37862306a36Sopenharmony_ci	ret = __sg_alloc_table(table, nents, SG_MAX_SINGLE_ALLOC,
37962306a36Sopenharmony_ci			       NULL, 0, gfp_mask, sg_kmalloc);
38062306a36Sopenharmony_ci	if (unlikely(ret))
38162306a36Sopenharmony_ci		sg_free_table(table);
38262306a36Sopenharmony_ci	return ret;
38362306a36Sopenharmony_ci}
38462306a36Sopenharmony_ciEXPORT_SYMBOL(sg_alloc_table);
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_cistatic struct scatterlist *get_next_sg(struct sg_append_table *table,
38762306a36Sopenharmony_ci				       struct scatterlist *cur,
38862306a36Sopenharmony_ci				       unsigned long needed_sges,
38962306a36Sopenharmony_ci				       gfp_t gfp_mask)
39062306a36Sopenharmony_ci{
39162306a36Sopenharmony_ci	struct scatterlist *new_sg, *next_sg;
39262306a36Sopenharmony_ci	unsigned int alloc_size;
39362306a36Sopenharmony_ci
39462306a36Sopenharmony_ci	if (cur) {
39562306a36Sopenharmony_ci		next_sg = sg_next(cur);
39662306a36Sopenharmony_ci		/* Check if last entry should be keeped for chainning */
39762306a36Sopenharmony_ci		if (!sg_is_last(next_sg) || needed_sges == 1)
39862306a36Sopenharmony_ci			return next_sg;
39962306a36Sopenharmony_ci	}
40062306a36Sopenharmony_ci
40162306a36Sopenharmony_ci	alloc_size = min_t(unsigned long, needed_sges, SG_MAX_SINGLE_ALLOC);
40262306a36Sopenharmony_ci	new_sg = sg_kmalloc(alloc_size, gfp_mask);
40362306a36Sopenharmony_ci	if (!new_sg)
40462306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
40562306a36Sopenharmony_ci	sg_init_table(new_sg, alloc_size);
40662306a36Sopenharmony_ci	if (cur) {
40762306a36Sopenharmony_ci		table->total_nents += alloc_size - 1;
40862306a36Sopenharmony_ci		__sg_chain(next_sg, new_sg);
40962306a36Sopenharmony_ci	} else {
41062306a36Sopenharmony_ci		table->sgt.sgl = new_sg;
41162306a36Sopenharmony_ci		table->total_nents = alloc_size;
41262306a36Sopenharmony_ci	}
41362306a36Sopenharmony_ci	return new_sg;
41462306a36Sopenharmony_ci}
41562306a36Sopenharmony_ci
41662306a36Sopenharmony_cistatic bool pages_are_mergeable(struct page *a, struct page *b)
41762306a36Sopenharmony_ci{
41862306a36Sopenharmony_ci	if (page_to_pfn(a) != page_to_pfn(b) + 1)
41962306a36Sopenharmony_ci		return false;
42062306a36Sopenharmony_ci	if (!zone_device_pages_have_same_pgmap(a, b))
42162306a36Sopenharmony_ci		return false;
42262306a36Sopenharmony_ci	return true;
42362306a36Sopenharmony_ci}
42462306a36Sopenharmony_ci
42562306a36Sopenharmony_ci/**
42662306a36Sopenharmony_ci * sg_alloc_append_table_from_pages - Allocate and initialize an append sg
42762306a36Sopenharmony_ci *                                    table from an array of pages
42862306a36Sopenharmony_ci * @sgt_append:  The sg append table to use
42962306a36Sopenharmony_ci * @pages:       Pointer to an array of page pointers
43062306a36Sopenharmony_ci * @n_pages:     Number of pages in the pages array
43162306a36Sopenharmony_ci * @offset:      Offset from start of the first page to the start of a buffer
43262306a36Sopenharmony_ci * @size:        Number of valid bytes in the buffer (after offset)
43362306a36Sopenharmony_ci * @max_segment: Maximum size of a scatterlist element in bytes
43462306a36Sopenharmony_ci * @left_pages:  Left pages caller have to set after this call
43562306a36Sopenharmony_ci * @gfp_mask:	 GFP allocation mask
43662306a36Sopenharmony_ci *
43762306a36Sopenharmony_ci * Description:
43862306a36Sopenharmony_ci *    In the first call it allocate and initialize an sg table from a list of
43962306a36Sopenharmony_ci *    pages, else reuse the scatterlist from sgt_append. Contiguous ranges of
44062306a36Sopenharmony_ci *    the pages are squashed into a single scatterlist entry up to the maximum
44162306a36Sopenharmony_ci *    size specified in @max_segment.  A user may provide an offset at a start
44262306a36Sopenharmony_ci *    and a size of valid data in a buffer specified by the page array. The
44362306a36Sopenharmony_ci *    returned sg table is released by sg_free_append_table
44462306a36Sopenharmony_ci *
44562306a36Sopenharmony_ci * Returns:
44662306a36Sopenharmony_ci *   0 on success, negative error on failure
44762306a36Sopenharmony_ci *
44862306a36Sopenharmony_ci * Notes:
44962306a36Sopenharmony_ci *   If this function returns non-0 (eg failure), the caller must call
45062306a36Sopenharmony_ci *   sg_free_append_table() to cleanup any leftover allocations.
45162306a36Sopenharmony_ci *
45262306a36Sopenharmony_ci *   In the fist call, sgt_append must by initialized.
45362306a36Sopenharmony_ci */
45462306a36Sopenharmony_ciint sg_alloc_append_table_from_pages(struct sg_append_table *sgt_append,
45562306a36Sopenharmony_ci		struct page **pages, unsigned int n_pages, unsigned int offset,
45662306a36Sopenharmony_ci		unsigned long size, unsigned int max_segment,
45762306a36Sopenharmony_ci		unsigned int left_pages, gfp_t gfp_mask)
45862306a36Sopenharmony_ci{
45962306a36Sopenharmony_ci	unsigned int chunks, cur_page, seg_len, i, prv_len = 0;
46062306a36Sopenharmony_ci	unsigned int added_nents = 0;
46162306a36Sopenharmony_ci	struct scatterlist *s = sgt_append->prv;
46262306a36Sopenharmony_ci	struct page *last_pg;
46362306a36Sopenharmony_ci
46462306a36Sopenharmony_ci	/*
46562306a36Sopenharmony_ci	 * The algorithm below requires max_segment to be aligned to PAGE_SIZE
46662306a36Sopenharmony_ci	 * otherwise it can overshoot.
46762306a36Sopenharmony_ci	 */
46862306a36Sopenharmony_ci	max_segment = ALIGN_DOWN(max_segment, PAGE_SIZE);
46962306a36Sopenharmony_ci	if (WARN_ON(max_segment < PAGE_SIZE))
47062306a36Sopenharmony_ci		return -EINVAL;
47162306a36Sopenharmony_ci
47262306a36Sopenharmony_ci	if (IS_ENABLED(CONFIG_ARCH_NO_SG_CHAIN) && sgt_append->prv)
47362306a36Sopenharmony_ci		return -EOPNOTSUPP;
47462306a36Sopenharmony_ci
47562306a36Sopenharmony_ci	if (sgt_append->prv) {
47662306a36Sopenharmony_ci		unsigned long next_pfn = (page_to_phys(sg_page(sgt_append->prv)) +
47762306a36Sopenharmony_ci			sgt_append->prv->offset + sgt_append->prv->length) / PAGE_SIZE;
47862306a36Sopenharmony_ci
47962306a36Sopenharmony_ci		if (WARN_ON(offset))
48062306a36Sopenharmony_ci			return -EINVAL;
48162306a36Sopenharmony_ci
48262306a36Sopenharmony_ci		/* Merge contiguous pages into the last SG */
48362306a36Sopenharmony_ci		prv_len = sgt_append->prv->length;
48462306a36Sopenharmony_ci		if (page_to_pfn(pages[0]) == next_pfn) {
48562306a36Sopenharmony_ci			last_pg = pfn_to_page(next_pfn - 1);
48662306a36Sopenharmony_ci			while (n_pages && pages_are_mergeable(pages[0], last_pg)) {
48762306a36Sopenharmony_ci				if (sgt_append->prv->length + PAGE_SIZE > max_segment)
48862306a36Sopenharmony_ci					break;
48962306a36Sopenharmony_ci				sgt_append->prv->length += PAGE_SIZE;
49062306a36Sopenharmony_ci				last_pg = pages[0];
49162306a36Sopenharmony_ci				pages++;
49262306a36Sopenharmony_ci				n_pages--;
49362306a36Sopenharmony_ci			}
49462306a36Sopenharmony_ci			if (!n_pages)
49562306a36Sopenharmony_ci				goto out;
49662306a36Sopenharmony_ci		}
49762306a36Sopenharmony_ci	}
49862306a36Sopenharmony_ci
49962306a36Sopenharmony_ci	/* compute number of contiguous chunks */
50062306a36Sopenharmony_ci	chunks = 1;
50162306a36Sopenharmony_ci	seg_len = 0;
50262306a36Sopenharmony_ci	for (i = 1; i < n_pages; i++) {
50362306a36Sopenharmony_ci		seg_len += PAGE_SIZE;
50462306a36Sopenharmony_ci		if (seg_len >= max_segment ||
50562306a36Sopenharmony_ci		    !pages_are_mergeable(pages[i], pages[i - 1])) {
50662306a36Sopenharmony_ci			chunks++;
50762306a36Sopenharmony_ci			seg_len = 0;
50862306a36Sopenharmony_ci		}
50962306a36Sopenharmony_ci	}
51062306a36Sopenharmony_ci
51162306a36Sopenharmony_ci	/* merging chunks and putting them into the scatterlist */
51262306a36Sopenharmony_ci	cur_page = 0;
51362306a36Sopenharmony_ci	for (i = 0; i < chunks; i++) {
51462306a36Sopenharmony_ci		unsigned int j, chunk_size;
51562306a36Sopenharmony_ci
51662306a36Sopenharmony_ci		/* look for the end of the current chunk */
51762306a36Sopenharmony_ci		seg_len = 0;
51862306a36Sopenharmony_ci		for (j = cur_page + 1; j < n_pages; j++) {
51962306a36Sopenharmony_ci			seg_len += PAGE_SIZE;
52062306a36Sopenharmony_ci			if (seg_len >= max_segment ||
52162306a36Sopenharmony_ci			    !pages_are_mergeable(pages[j], pages[j - 1]))
52262306a36Sopenharmony_ci				break;
52362306a36Sopenharmony_ci		}
52462306a36Sopenharmony_ci
52562306a36Sopenharmony_ci		/* Pass how many chunks might be left */
52662306a36Sopenharmony_ci		s = get_next_sg(sgt_append, s, chunks - i + left_pages,
52762306a36Sopenharmony_ci				gfp_mask);
52862306a36Sopenharmony_ci		if (IS_ERR(s)) {
52962306a36Sopenharmony_ci			/*
53062306a36Sopenharmony_ci			 * Adjust entry length to be as before function was
53162306a36Sopenharmony_ci			 * called.
53262306a36Sopenharmony_ci			 */
53362306a36Sopenharmony_ci			if (sgt_append->prv)
53462306a36Sopenharmony_ci				sgt_append->prv->length = prv_len;
53562306a36Sopenharmony_ci			return PTR_ERR(s);
53662306a36Sopenharmony_ci		}
53762306a36Sopenharmony_ci		chunk_size = ((j - cur_page) << PAGE_SHIFT) - offset;
53862306a36Sopenharmony_ci		sg_set_page(s, pages[cur_page],
53962306a36Sopenharmony_ci			    min_t(unsigned long, size, chunk_size), offset);
54062306a36Sopenharmony_ci		added_nents++;
54162306a36Sopenharmony_ci		size -= chunk_size;
54262306a36Sopenharmony_ci		offset = 0;
54362306a36Sopenharmony_ci		cur_page = j;
54462306a36Sopenharmony_ci	}
54562306a36Sopenharmony_ci	sgt_append->sgt.nents += added_nents;
54662306a36Sopenharmony_ci	sgt_append->sgt.orig_nents = sgt_append->sgt.nents;
54762306a36Sopenharmony_ci	sgt_append->prv = s;
54862306a36Sopenharmony_ciout:
54962306a36Sopenharmony_ci	if (!left_pages)
55062306a36Sopenharmony_ci		sg_mark_end(s);
55162306a36Sopenharmony_ci	return 0;
55262306a36Sopenharmony_ci}
55362306a36Sopenharmony_ciEXPORT_SYMBOL(sg_alloc_append_table_from_pages);
55462306a36Sopenharmony_ci
55562306a36Sopenharmony_ci/**
55662306a36Sopenharmony_ci * sg_alloc_table_from_pages_segment - Allocate and initialize an sg table from
55762306a36Sopenharmony_ci *                                     an array of pages and given maximum
55862306a36Sopenharmony_ci *                                     segment.
55962306a36Sopenharmony_ci * @sgt:	 The sg table header to use
56062306a36Sopenharmony_ci * @pages:	 Pointer to an array of page pointers
56162306a36Sopenharmony_ci * @n_pages:	 Number of pages in the pages array
56262306a36Sopenharmony_ci * @offset:      Offset from start of the first page to the start of a buffer
56362306a36Sopenharmony_ci * @size:        Number of valid bytes in the buffer (after offset)
56462306a36Sopenharmony_ci * @max_segment: Maximum size of a scatterlist element in bytes
56562306a36Sopenharmony_ci * @gfp_mask:	 GFP allocation mask
56662306a36Sopenharmony_ci *
56762306a36Sopenharmony_ci *  Description:
56862306a36Sopenharmony_ci *    Allocate and initialize an sg table from a list of pages. Contiguous
56962306a36Sopenharmony_ci *    ranges of the pages are squashed into a single scatterlist node up to the
57062306a36Sopenharmony_ci *    maximum size specified in @max_segment. A user may provide an offset at a
57162306a36Sopenharmony_ci *    start and a size of valid data in a buffer specified by the page array.
57262306a36Sopenharmony_ci *
57362306a36Sopenharmony_ci *    The returned sg table is released by sg_free_table.
57462306a36Sopenharmony_ci *
57562306a36Sopenharmony_ci *  Returns:
57662306a36Sopenharmony_ci *   0 on success, negative error on failure
57762306a36Sopenharmony_ci */
57862306a36Sopenharmony_ciint sg_alloc_table_from_pages_segment(struct sg_table *sgt, struct page **pages,
57962306a36Sopenharmony_ci				unsigned int n_pages, unsigned int offset,
58062306a36Sopenharmony_ci				unsigned long size, unsigned int max_segment,
58162306a36Sopenharmony_ci				gfp_t gfp_mask)
58262306a36Sopenharmony_ci{
58362306a36Sopenharmony_ci	struct sg_append_table append = {};
58462306a36Sopenharmony_ci	int err;
58562306a36Sopenharmony_ci
58662306a36Sopenharmony_ci	err = sg_alloc_append_table_from_pages(&append, pages, n_pages, offset,
58762306a36Sopenharmony_ci					       size, max_segment, 0, gfp_mask);
58862306a36Sopenharmony_ci	if (err) {
58962306a36Sopenharmony_ci		sg_free_append_table(&append);
59062306a36Sopenharmony_ci		return err;
59162306a36Sopenharmony_ci	}
59262306a36Sopenharmony_ci	memcpy(sgt, &append.sgt, sizeof(*sgt));
59362306a36Sopenharmony_ci	WARN_ON(append.total_nents != sgt->orig_nents);
59462306a36Sopenharmony_ci	return 0;
59562306a36Sopenharmony_ci}
59662306a36Sopenharmony_ciEXPORT_SYMBOL(sg_alloc_table_from_pages_segment);
59762306a36Sopenharmony_ci
59862306a36Sopenharmony_ci#ifdef CONFIG_SGL_ALLOC
59962306a36Sopenharmony_ci
60062306a36Sopenharmony_ci/**
60162306a36Sopenharmony_ci * sgl_alloc_order - allocate a scatterlist and its pages
60262306a36Sopenharmony_ci * @length: Length in bytes of the scatterlist. Must be at least one
60362306a36Sopenharmony_ci * @order: Second argument for alloc_pages()
60462306a36Sopenharmony_ci * @chainable: Whether or not to allocate an extra element in the scatterlist
60562306a36Sopenharmony_ci *	for scatterlist chaining purposes
60662306a36Sopenharmony_ci * @gfp: Memory allocation flags
60762306a36Sopenharmony_ci * @nent_p: [out] Number of entries in the scatterlist that have pages
60862306a36Sopenharmony_ci *
60962306a36Sopenharmony_ci * Returns: A pointer to an initialized scatterlist or %NULL upon failure.
61062306a36Sopenharmony_ci */
61162306a36Sopenharmony_cistruct scatterlist *sgl_alloc_order(unsigned long long length,
61262306a36Sopenharmony_ci				    unsigned int order, bool chainable,
61362306a36Sopenharmony_ci				    gfp_t gfp, unsigned int *nent_p)
61462306a36Sopenharmony_ci{
61562306a36Sopenharmony_ci	struct scatterlist *sgl, *sg;
61662306a36Sopenharmony_ci	struct page *page;
61762306a36Sopenharmony_ci	unsigned int nent, nalloc;
61862306a36Sopenharmony_ci	u32 elem_len;
61962306a36Sopenharmony_ci
62062306a36Sopenharmony_ci	nent = round_up(length, PAGE_SIZE << order) >> (PAGE_SHIFT + order);
62162306a36Sopenharmony_ci	/* Check for integer overflow */
62262306a36Sopenharmony_ci	if (length > (nent << (PAGE_SHIFT + order)))
62362306a36Sopenharmony_ci		return NULL;
62462306a36Sopenharmony_ci	nalloc = nent;
62562306a36Sopenharmony_ci	if (chainable) {
62662306a36Sopenharmony_ci		/* Check for integer overflow */
62762306a36Sopenharmony_ci		if (nalloc + 1 < nalloc)
62862306a36Sopenharmony_ci			return NULL;
62962306a36Sopenharmony_ci		nalloc++;
63062306a36Sopenharmony_ci	}
63162306a36Sopenharmony_ci	sgl = kmalloc_array(nalloc, sizeof(struct scatterlist),
63262306a36Sopenharmony_ci			    gfp & ~GFP_DMA);
63362306a36Sopenharmony_ci	if (!sgl)
63462306a36Sopenharmony_ci		return NULL;
63562306a36Sopenharmony_ci
63662306a36Sopenharmony_ci	sg_init_table(sgl, nalloc);
63762306a36Sopenharmony_ci	sg = sgl;
63862306a36Sopenharmony_ci	while (length) {
63962306a36Sopenharmony_ci		elem_len = min_t(u64, length, PAGE_SIZE << order);
64062306a36Sopenharmony_ci		page = alloc_pages(gfp, order);
64162306a36Sopenharmony_ci		if (!page) {
64262306a36Sopenharmony_ci			sgl_free_order(sgl, order);
64362306a36Sopenharmony_ci			return NULL;
64462306a36Sopenharmony_ci		}
64562306a36Sopenharmony_ci
64662306a36Sopenharmony_ci		sg_set_page(sg, page, elem_len, 0);
64762306a36Sopenharmony_ci		length -= elem_len;
64862306a36Sopenharmony_ci		sg = sg_next(sg);
64962306a36Sopenharmony_ci	}
65062306a36Sopenharmony_ci	WARN_ONCE(length, "length = %lld\n", length);
65162306a36Sopenharmony_ci	if (nent_p)
65262306a36Sopenharmony_ci		*nent_p = nent;
65362306a36Sopenharmony_ci	return sgl;
65462306a36Sopenharmony_ci}
65562306a36Sopenharmony_ciEXPORT_SYMBOL(sgl_alloc_order);
65662306a36Sopenharmony_ci
65762306a36Sopenharmony_ci/**
65862306a36Sopenharmony_ci * sgl_alloc - allocate a scatterlist and its pages
65962306a36Sopenharmony_ci * @length: Length in bytes of the scatterlist
66062306a36Sopenharmony_ci * @gfp: Memory allocation flags
66162306a36Sopenharmony_ci * @nent_p: [out] Number of entries in the scatterlist
66262306a36Sopenharmony_ci *
66362306a36Sopenharmony_ci * Returns: A pointer to an initialized scatterlist or %NULL upon failure.
66462306a36Sopenharmony_ci */
66562306a36Sopenharmony_cistruct scatterlist *sgl_alloc(unsigned long long length, gfp_t gfp,
66662306a36Sopenharmony_ci			      unsigned int *nent_p)
66762306a36Sopenharmony_ci{
66862306a36Sopenharmony_ci	return sgl_alloc_order(length, 0, false, gfp, nent_p);
66962306a36Sopenharmony_ci}
67062306a36Sopenharmony_ciEXPORT_SYMBOL(sgl_alloc);
67162306a36Sopenharmony_ci
67262306a36Sopenharmony_ci/**
67362306a36Sopenharmony_ci * sgl_free_n_order - free a scatterlist and its pages
67462306a36Sopenharmony_ci * @sgl: Scatterlist with one or more elements
67562306a36Sopenharmony_ci * @nents: Maximum number of elements to free
67662306a36Sopenharmony_ci * @order: Second argument for __free_pages()
67762306a36Sopenharmony_ci *
67862306a36Sopenharmony_ci * Notes:
67962306a36Sopenharmony_ci * - If several scatterlists have been chained and each chain element is
68062306a36Sopenharmony_ci *   freed separately then it's essential to set nents correctly to avoid that a
68162306a36Sopenharmony_ci *   page would get freed twice.
68262306a36Sopenharmony_ci * - All pages in a chained scatterlist can be freed at once by setting @nents
68362306a36Sopenharmony_ci *   to a high number.
68462306a36Sopenharmony_ci */
68562306a36Sopenharmony_civoid sgl_free_n_order(struct scatterlist *sgl, int nents, int order)
68662306a36Sopenharmony_ci{
68762306a36Sopenharmony_ci	struct scatterlist *sg;
68862306a36Sopenharmony_ci	struct page *page;
68962306a36Sopenharmony_ci	int i;
69062306a36Sopenharmony_ci
69162306a36Sopenharmony_ci	for_each_sg(sgl, sg, nents, i) {
69262306a36Sopenharmony_ci		if (!sg)
69362306a36Sopenharmony_ci			break;
69462306a36Sopenharmony_ci		page = sg_page(sg);
69562306a36Sopenharmony_ci		if (page)
69662306a36Sopenharmony_ci			__free_pages(page, order);
69762306a36Sopenharmony_ci	}
69862306a36Sopenharmony_ci	kfree(sgl);
69962306a36Sopenharmony_ci}
70062306a36Sopenharmony_ciEXPORT_SYMBOL(sgl_free_n_order);
70162306a36Sopenharmony_ci
70262306a36Sopenharmony_ci/**
70362306a36Sopenharmony_ci * sgl_free_order - free a scatterlist and its pages
70462306a36Sopenharmony_ci * @sgl: Scatterlist with one or more elements
70562306a36Sopenharmony_ci * @order: Second argument for __free_pages()
70662306a36Sopenharmony_ci */
70762306a36Sopenharmony_civoid sgl_free_order(struct scatterlist *sgl, int order)
70862306a36Sopenharmony_ci{
70962306a36Sopenharmony_ci	sgl_free_n_order(sgl, INT_MAX, order);
71062306a36Sopenharmony_ci}
71162306a36Sopenharmony_ciEXPORT_SYMBOL(sgl_free_order);
71262306a36Sopenharmony_ci
71362306a36Sopenharmony_ci/**
71462306a36Sopenharmony_ci * sgl_free - free a scatterlist and its pages
71562306a36Sopenharmony_ci * @sgl: Scatterlist with one or more elements
71662306a36Sopenharmony_ci */
71762306a36Sopenharmony_civoid sgl_free(struct scatterlist *sgl)
71862306a36Sopenharmony_ci{
71962306a36Sopenharmony_ci	sgl_free_order(sgl, 0);
72062306a36Sopenharmony_ci}
72162306a36Sopenharmony_ciEXPORT_SYMBOL(sgl_free);
72262306a36Sopenharmony_ci
72362306a36Sopenharmony_ci#endif /* CONFIG_SGL_ALLOC */
72462306a36Sopenharmony_ci
72562306a36Sopenharmony_civoid __sg_page_iter_start(struct sg_page_iter *piter,
72662306a36Sopenharmony_ci			  struct scatterlist *sglist, unsigned int nents,
72762306a36Sopenharmony_ci			  unsigned long pgoffset)
72862306a36Sopenharmony_ci{
72962306a36Sopenharmony_ci	piter->__pg_advance = 0;
73062306a36Sopenharmony_ci	piter->__nents = nents;
73162306a36Sopenharmony_ci
73262306a36Sopenharmony_ci	piter->sg = sglist;
73362306a36Sopenharmony_ci	piter->sg_pgoffset = pgoffset;
73462306a36Sopenharmony_ci}
73562306a36Sopenharmony_ciEXPORT_SYMBOL(__sg_page_iter_start);
73662306a36Sopenharmony_ci
73762306a36Sopenharmony_cistatic int sg_page_count(struct scatterlist *sg)
73862306a36Sopenharmony_ci{
73962306a36Sopenharmony_ci	return PAGE_ALIGN(sg->offset + sg->length) >> PAGE_SHIFT;
74062306a36Sopenharmony_ci}
74162306a36Sopenharmony_ci
74262306a36Sopenharmony_cibool __sg_page_iter_next(struct sg_page_iter *piter)
74362306a36Sopenharmony_ci{
74462306a36Sopenharmony_ci	if (!piter->__nents || !piter->sg)
74562306a36Sopenharmony_ci		return false;
74662306a36Sopenharmony_ci
74762306a36Sopenharmony_ci	piter->sg_pgoffset += piter->__pg_advance;
74862306a36Sopenharmony_ci	piter->__pg_advance = 1;
74962306a36Sopenharmony_ci
75062306a36Sopenharmony_ci	while (piter->sg_pgoffset >= sg_page_count(piter->sg)) {
75162306a36Sopenharmony_ci		piter->sg_pgoffset -= sg_page_count(piter->sg);
75262306a36Sopenharmony_ci		piter->sg = sg_next(piter->sg);
75362306a36Sopenharmony_ci		if (!--piter->__nents || !piter->sg)
75462306a36Sopenharmony_ci			return false;
75562306a36Sopenharmony_ci	}
75662306a36Sopenharmony_ci
75762306a36Sopenharmony_ci	return true;
75862306a36Sopenharmony_ci}
75962306a36Sopenharmony_ciEXPORT_SYMBOL(__sg_page_iter_next);
76062306a36Sopenharmony_ci
76162306a36Sopenharmony_cistatic int sg_dma_page_count(struct scatterlist *sg)
76262306a36Sopenharmony_ci{
76362306a36Sopenharmony_ci	return PAGE_ALIGN(sg->offset + sg_dma_len(sg)) >> PAGE_SHIFT;
76462306a36Sopenharmony_ci}
76562306a36Sopenharmony_ci
76662306a36Sopenharmony_cibool __sg_page_iter_dma_next(struct sg_dma_page_iter *dma_iter)
76762306a36Sopenharmony_ci{
76862306a36Sopenharmony_ci	struct sg_page_iter *piter = &dma_iter->base;
76962306a36Sopenharmony_ci
77062306a36Sopenharmony_ci	if (!piter->__nents || !piter->sg)
77162306a36Sopenharmony_ci		return false;
77262306a36Sopenharmony_ci
77362306a36Sopenharmony_ci	piter->sg_pgoffset += piter->__pg_advance;
77462306a36Sopenharmony_ci	piter->__pg_advance = 1;
77562306a36Sopenharmony_ci
77662306a36Sopenharmony_ci	while (piter->sg_pgoffset >= sg_dma_page_count(piter->sg)) {
77762306a36Sopenharmony_ci		piter->sg_pgoffset -= sg_dma_page_count(piter->sg);
77862306a36Sopenharmony_ci		piter->sg = sg_next(piter->sg);
77962306a36Sopenharmony_ci		if (!--piter->__nents || !piter->sg)
78062306a36Sopenharmony_ci			return false;
78162306a36Sopenharmony_ci	}
78262306a36Sopenharmony_ci
78362306a36Sopenharmony_ci	return true;
78462306a36Sopenharmony_ci}
78562306a36Sopenharmony_ciEXPORT_SYMBOL(__sg_page_iter_dma_next);
78662306a36Sopenharmony_ci
78762306a36Sopenharmony_ci/**
78862306a36Sopenharmony_ci * sg_miter_start - start mapping iteration over a sg list
78962306a36Sopenharmony_ci * @miter: sg mapping iter to be started
79062306a36Sopenharmony_ci * @sgl: sg list to iterate over
79162306a36Sopenharmony_ci * @nents: number of sg entries
79262306a36Sopenharmony_ci * @flags: sg iterator flags
79362306a36Sopenharmony_ci *
79462306a36Sopenharmony_ci * Description:
79562306a36Sopenharmony_ci *   Starts mapping iterator @miter.
79662306a36Sopenharmony_ci *
79762306a36Sopenharmony_ci * Context:
79862306a36Sopenharmony_ci *   Don't care.
79962306a36Sopenharmony_ci */
80062306a36Sopenharmony_civoid sg_miter_start(struct sg_mapping_iter *miter, struct scatterlist *sgl,
80162306a36Sopenharmony_ci		    unsigned int nents, unsigned int flags)
80262306a36Sopenharmony_ci{
80362306a36Sopenharmony_ci	memset(miter, 0, sizeof(struct sg_mapping_iter));
80462306a36Sopenharmony_ci
80562306a36Sopenharmony_ci	__sg_page_iter_start(&miter->piter, sgl, nents, 0);
80662306a36Sopenharmony_ci	WARN_ON(!(flags & (SG_MITER_TO_SG | SG_MITER_FROM_SG)));
80762306a36Sopenharmony_ci	miter->__flags = flags;
80862306a36Sopenharmony_ci}
80962306a36Sopenharmony_ciEXPORT_SYMBOL(sg_miter_start);
81062306a36Sopenharmony_ci
81162306a36Sopenharmony_cistatic bool sg_miter_get_next_page(struct sg_mapping_iter *miter)
81262306a36Sopenharmony_ci{
81362306a36Sopenharmony_ci	if (!miter->__remaining) {
81462306a36Sopenharmony_ci		struct scatterlist *sg;
81562306a36Sopenharmony_ci
81662306a36Sopenharmony_ci		if (!__sg_page_iter_next(&miter->piter))
81762306a36Sopenharmony_ci			return false;
81862306a36Sopenharmony_ci
81962306a36Sopenharmony_ci		sg = miter->piter.sg;
82062306a36Sopenharmony_ci
82162306a36Sopenharmony_ci		miter->__offset = miter->piter.sg_pgoffset ? 0 : sg->offset;
82262306a36Sopenharmony_ci		miter->piter.sg_pgoffset += miter->__offset >> PAGE_SHIFT;
82362306a36Sopenharmony_ci		miter->__offset &= PAGE_SIZE - 1;
82462306a36Sopenharmony_ci		miter->__remaining = sg->offset + sg->length -
82562306a36Sopenharmony_ci				     (miter->piter.sg_pgoffset << PAGE_SHIFT) -
82662306a36Sopenharmony_ci				     miter->__offset;
82762306a36Sopenharmony_ci		miter->__remaining = min_t(unsigned long, miter->__remaining,
82862306a36Sopenharmony_ci					   PAGE_SIZE - miter->__offset);
82962306a36Sopenharmony_ci	}
83062306a36Sopenharmony_ci
83162306a36Sopenharmony_ci	return true;
83262306a36Sopenharmony_ci}
83362306a36Sopenharmony_ci
83462306a36Sopenharmony_ci/**
83562306a36Sopenharmony_ci * sg_miter_skip - reposition mapping iterator
83662306a36Sopenharmony_ci * @miter: sg mapping iter to be skipped
83762306a36Sopenharmony_ci * @offset: number of bytes to plus the current location
83862306a36Sopenharmony_ci *
83962306a36Sopenharmony_ci * Description:
84062306a36Sopenharmony_ci *   Sets the offset of @miter to its current location plus @offset bytes.
84162306a36Sopenharmony_ci *   If mapping iterator @miter has been proceeded by sg_miter_next(), this
84262306a36Sopenharmony_ci *   stops @miter.
84362306a36Sopenharmony_ci *
84462306a36Sopenharmony_ci * Context:
84562306a36Sopenharmony_ci *   Don't care.
84662306a36Sopenharmony_ci *
84762306a36Sopenharmony_ci * Returns:
84862306a36Sopenharmony_ci *   true if @miter contains the valid mapping.  false if end of sg
84962306a36Sopenharmony_ci *   list is reached.
85062306a36Sopenharmony_ci */
85162306a36Sopenharmony_cibool sg_miter_skip(struct sg_mapping_iter *miter, off_t offset)
85262306a36Sopenharmony_ci{
85362306a36Sopenharmony_ci	sg_miter_stop(miter);
85462306a36Sopenharmony_ci
85562306a36Sopenharmony_ci	while (offset) {
85662306a36Sopenharmony_ci		off_t consumed;
85762306a36Sopenharmony_ci
85862306a36Sopenharmony_ci		if (!sg_miter_get_next_page(miter))
85962306a36Sopenharmony_ci			return false;
86062306a36Sopenharmony_ci
86162306a36Sopenharmony_ci		consumed = min_t(off_t, offset, miter->__remaining);
86262306a36Sopenharmony_ci		miter->__offset += consumed;
86362306a36Sopenharmony_ci		miter->__remaining -= consumed;
86462306a36Sopenharmony_ci		offset -= consumed;
86562306a36Sopenharmony_ci	}
86662306a36Sopenharmony_ci
86762306a36Sopenharmony_ci	return true;
86862306a36Sopenharmony_ci}
86962306a36Sopenharmony_ciEXPORT_SYMBOL(sg_miter_skip);
87062306a36Sopenharmony_ci
87162306a36Sopenharmony_ci/**
87262306a36Sopenharmony_ci * sg_miter_next - proceed mapping iterator to the next mapping
87362306a36Sopenharmony_ci * @miter: sg mapping iter to proceed
87462306a36Sopenharmony_ci *
87562306a36Sopenharmony_ci * Description:
87662306a36Sopenharmony_ci *   Proceeds @miter to the next mapping.  @miter should have been started
87762306a36Sopenharmony_ci *   using sg_miter_start().  On successful return, @miter->page,
87862306a36Sopenharmony_ci *   @miter->addr and @miter->length point to the current mapping.
87962306a36Sopenharmony_ci *
88062306a36Sopenharmony_ci * Context:
88162306a36Sopenharmony_ci *   May sleep if !SG_MITER_ATOMIC.
88262306a36Sopenharmony_ci *
88362306a36Sopenharmony_ci * Returns:
88462306a36Sopenharmony_ci *   true if @miter contains the next mapping.  false if end of sg
88562306a36Sopenharmony_ci *   list is reached.
88662306a36Sopenharmony_ci */
88762306a36Sopenharmony_cibool sg_miter_next(struct sg_mapping_iter *miter)
88862306a36Sopenharmony_ci{
88962306a36Sopenharmony_ci	sg_miter_stop(miter);
89062306a36Sopenharmony_ci
89162306a36Sopenharmony_ci	/*
89262306a36Sopenharmony_ci	 * Get to the next page if necessary.
89362306a36Sopenharmony_ci	 * __remaining, __offset is adjusted by sg_miter_stop
89462306a36Sopenharmony_ci	 */
89562306a36Sopenharmony_ci	if (!sg_miter_get_next_page(miter))
89662306a36Sopenharmony_ci		return false;
89762306a36Sopenharmony_ci
89862306a36Sopenharmony_ci	miter->page = sg_page_iter_page(&miter->piter);
89962306a36Sopenharmony_ci	miter->consumed = miter->length = miter->__remaining;
90062306a36Sopenharmony_ci
90162306a36Sopenharmony_ci	if (miter->__flags & SG_MITER_ATOMIC)
90262306a36Sopenharmony_ci		miter->addr = kmap_atomic(miter->page) + miter->__offset;
90362306a36Sopenharmony_ci	else
90462306a36Sopenharmony_ci		miter->addr = kmap(miter->page) + miter->__offset;
90562306a36Sopenharmony_ci
90662306a36Sopenharmony_ci	return true;
90762306a36Sopenharmony_ci}
90862306a36Sopenharmony_ciEXPORT_SYMBOL(sg_miter_next);
90962306a36Sopenharmony_ci
91062306a36Sopenharmony_ci/**
91162306a36Sopenharmony_ci * sg_miter_stop - stop mapping iteration
91262306a36Sopenharmony_ci * @miter: sg mapping iter to be stopped
91362306a36Sopenharmony_ci *
91462306a36Sopenharmony_ci * Description:
91562306a36Sopenharmony_ci *   Stops mapping iterator @miter.  @miter should have been started
91662306a36Sopenharmony_ci *   using sg_miter_start().  A stopped iteration can be resumed by
91762306a36Sopenharmony_ci *   calling sg_miter_next() on it.  This is useful when resources (kmap)
91862306a36Sopenharmony_ci *   need to be released during iteration.
91962306a36Sopenharmony_ci *
92062306a36Sopenharmony_ci * Context:
92162306a36Sopenharmony_ci *   Don't care otherwise.
92262306a36Sopenharmony_ci */
92362306a36Sopenharmony_civoid sg_miter_stop(struct sg_mapping_iter *miter)
92462306a36Sopenharmony_ci{
92562306a36Sopenharmony_ci	WARN_ON(miter->consumed > miter->length);
92662306a36Sopenharmony_ci
92762306a36Sopenharmony_ci	/* drop resources from the last iteration */
92862306a36Sopenharmony_ci	if (miter->addr) {
92962306a36Sopenharmony_ci		miter->__offset += miter->consumed;
93062306a36Sopenharmony_ci		miter->__remaining -= miter->consumed;
93162306a36Sopenharmony_ci
93262306a36Sopenharmony_ci		if (miter->__flags & SG_MITER_TO_SG)
93362306a36Sopenharmony_ci			flush_dcache_page(miter->page);
93462306a36Sopenharmony_ci
93562306a36Sopenharmony_ci		if (miter->__flags & SG_MITER_ATOMIC) {
93662306a36Sopenharmony_ci			WARN_ON_ONCE(!pagefault_disabled());
93762306a36Sopenharmony_ci			kunmap_atomic(miter->addr);
93862306a36Sopenharmony_ci		} else
93962306a36Sopenharmony_ci			kunmap(miter->page);
94062306a36Sopenharmony_ci
94162306a36Sopenharmony_ci		miter->page = NULL;
94262306a36Sopenharmony_ci		miter->addr = NULL;
94362306a36Sopenharmony_ci		miter->length = 0;
94462306a36Sopenharmony_ci		miter->consumed = 0;
94562306a36Sopenharmony_ci	}
94662306a36Sopenharmony_ci}
94762306a36Sopenharmony_ciEXPORT_SYMBOL(sg_miter_stop);
94862306a36Sopenharmony_ci
94962306a36Sopenharmony_ci/**
95062306a36Sopenharmony_ci * sg_copy_buffer - Copy data between a linear buffer and an SG list
95162306a36Sopenharmony_ci * @sgl:		 The SG list
95262306a36Sopenharmony_ci * @nents:		 Number of SG entries
95362306a36Sopenharmony_ci * @buf:		 Where to copy from
95462306a36Sopenharmony_ci * @buflen:		 The number of bytes to copy
95562306a36Sopenharmony_ci * @skip:		 Number of bytes to skip before copying
95662306a36Sopenharmony_ci * @to_buffer:		 transfer direction (true == from an sg list to a
95762306a36Sopenharmony_ci *			 buffer, false == from a buffer to an sg list)
95862306a36Sopenharmony_ci *
95962306a36Sopenharmony_ci * Returns the number of copied bytes.
96062306a36Sopenharmony_ci *
96162306a36Sopenharmony_ci **/
96262306a36Sopenharmony_cisize_t sg_copy_buffer(struct scatterlist *sgl, unsigned int nents, void *buf,
96362306a36Sopenharmony_ci		      size_t buflen, off_t skip, bool to_buffer)
96462306a36Sopenharmony_ci{
96562306a36Sopenharmony_ci	unsigned int offset = 0;
96662306a36Sopenharmony_ci	struct sg_mapping_iter miter;
96762306a36Sopenharmony_ci	unsigned int sg_flags = SG_MITER_ATOMIC;
96862306a36Sopenharmony_ci
96962306a36Sopenharmony_ci	if (to_buffer)
97062306a36Sopenharmony_ci		sg_flags |= SG_MITER_FROM_SG;
97162306a36Sopenharmony_ci	else
97262306a36Sopenharmony_ci		sg_flags |= SG_MITER_TO_SG;
97362306a36Sopenharmony_ci
97462306a36Sopenharmony_ci	sg_miter_start(&miter, sgl, nents, sg_flags);
97562306a36Sopenharmony_ci
97662306a36Sopenharmony_ci	if (!sg_miter_skip(&miter, skip))
97762306a36Sopenharmony_ci		return 0;
97862306a36Sopenharmony_ci
97962306a36Sopenharmony_ci	while ((offset < buflen) && sg_miter_next(&miter)) {
98062306a36Sopenharmony_ci		unsigned int len;
98162306a36Sopenharmony_ci
98262306a36Sopenharmony_ci		len = min(miter.length, buflen - offset);
98362306a36Sopenharmony_ci
98462306a36Sopenharmony_ci		if (to_buffer)
98562306a36Sopenharmony_ci			memcpy(buf + offset, miter.addr, len);
98662306a36Sopenharmony_ci		else
98762306a36Sopenharmony_ci			memcpy(miter.addr, buf + offset, len);
98862306a36Sopenharmony_ci
98962306a36Sopenharmony_ci		offset += len;
99062306a36Sopenharmony_ci	}
99162306a36Sopenharmony_ci
99262306a36Sopenharmony_ci	sg_miter_stop(&miter);
99362306a36Sopenharmony_ci
99462306a36Sopenharmony_ci	return offset;
99562306a36Sopenharmony_ci}
99662306a36Sopenharmony_ciEXPORT_SYMBOL(sg_copy_buffer);
99762306a36Sopenharmony_ci
99862306a36Sopenharmony_ci/**
99962306a36Sopenharmony_ci * sg_copy_from_buffer - Copy from a linear buffer to an SG list
100062306a36Sopenharmony_ci * @sgl:		 The SG list
100162306a36Sopenharmony_ci * @nents:		 Number of SG entries
100262306a36Sopenharmony_ci * @buf:		 Where to copy from
100362306a36Sopenharmony_ci * @buflen:		 The number of bytes to copy
100462306a36Sopenharmony_ci *
100562306a36Sopenharmony_ci * Returns the number of copied bytes.
100662306a36Sopenharmony_ci *
100762306a36Sopenharmony_ci **/
100862306a36Sopenharmony_cisize_t sg_copy_from_buffer(struct scatterlist *sgl, unsigned int nents,
100962306a36Sopenharmony_ci			   const void *buf, size_t buflen)
101062306a36Sopenharmony_ci{
101162306a36Sopenharmony_ci	return sg_copy_buffer(sgl, nents, (void *)buf, buflen, 0, false);
101262306a36Sopenharmony_ci}
101362306a36Sopenharmony_ciEXPORT_SYMBOL(sg_copy_from_buffer);
101462306a36Sopenharmony_ci
101562306a36Sopenharmony_ci/**
101662306a36Sopenharmony_ci * sg_copy_to_buffer - Copy from an SG list to a linear buffer
101762306a36Sopenharmony_ci * @sgl:		 The SG list
101862306a36Sopenharmony_ci * @nents:		 Number of SG entries
101962306a36Sopenharmony_ci * @buf:		 Where to copy to
102062306a36Sopenharmony_ci * @buflen:		 The number of bytes to copy
102162306a36Sopenharmony_ci *
102262306a36Sopenharmony_ci * Returns the number of copied bytes.
102362306a36Sopenharmony_ci *
102462306a36Sopenharmony_ci **/
102562306a36Sopenharmony_cisize_t sg_copy_to_buffer(struct scatterlist *sgl, unsigned int nents,
102662306a36Sopenharmony_ci			 void *buf, size_t buflen)
102762306a36Sopenharmony_ci{
102862306a36Sopenharmony_ci	return sg_copy_buffer(sgl, nents, buf, buflen, 0, true);
102962306a36Sopenharmony_ci}
103062306a36Sopenharmony_ciEXPORT_SYMBOL(sg_copy_to_buffer);
103162306a36Sopenharmony_ci
103262306a36Sopenharmony_ci/**
103362306a36Sopenharmony_ci * sg_pcopy_from_buffer - Copy from a linear buffer to an SG list
103462306a36Sopenharmony_ci * @sgl:		 The SG list
103562306a36Sopenharmony_ci * @nents:		 Number of SG entries
103662306a36Sopenharmony_ci * @buf:		 Where to copy from
103762306a36Sopenharmony_ci * @buflen:		 The number of bytes to copy
103862306a36Sopenharmony_ci * @skip:		 Number of bytes to skip before copying
103962306a36Sopenharmony_ci *
104062306a36Sopenharmony_ci * Returns the number of copied bytes.
104162306a36Sopenharmony_ci *
104262306a36Sopenharmony_ci **/
104362306a36Sopenharmony_cisize_t sg_pcopy_from_buffer(struct scatterlist *sgl, unsigned int nents,
104462306a36Sopenharmony_ci			    const void *buf, size_t buflen, off_t skip)
104562306a36Sopenharmony_ci{
104662306a36Sopenharmony_ci	return sg_copy_buffer(sgl, nents, (void *)buf, buflen, skip, false);
104762306a36Sopenharmony_ci}
104862306a36Sopenharmony_ciEXPORT_SYMBOL(sg_pcopy_from_buffer);
104962306a36Sopenharmony_ci
105062306a36Sopenharmony_ci/**
105162306a36Sopenharmony_ci * sg_pcopy_to_buffer - Copy from an SG list to a linear buffer
105262306a36Sopenharmony_ci * @sgl:		 The SG list
105362306a36Sopenharmony_ci * @nents:		 Number of SG entries
105462306a36Sopenharmony_ci * @buf:		 Where to copy to
105562306a36Sopenharmony_ci * @buflen:		 The number of bytes to copy
105662306a36Sopenharmony_ci * @skip:		 Number of bytes to skip before copying
105762306a36Sopenharmony_ci *
105862306a36Sopenharmony_ci * Returns the number of copied bytes.
105962306a36Sopenharmony_ci *
106062306a36Sopenharmony_ci **/
106162306a36Sopenharmony_cisize_t sg_pcopy_to_buffer(struct scatterlist *sgl, unsigned int nents,
106262306a36Sopenharmony_ci			  void *buf, size_t buflen, off_t skip)
106362306a36Sopenharmony_ci{
106462306a36Sopenharmony_ci	return sg_copy_buffer(sgl, nents, buf, buflen, skip, true);
106562306a36Sopenharmony_ci}
106662306a36Sopenharmony_ciEXPORT_SYMBOL(sg_pcopy_to_buffer);
106762306a36Sopenharmony_ci
106862306a36Sopenharmony_ci/**
106962306a36Sopenharmony_ci * sg_zero_buffer - Zero-out a part of a SG list
107062306a36Sopenharmony_ci * @sgl:		 The SG list
107162306a36Sopenharmony_ci * @nents:		 Number of SG entries
107262306a36Sopenharmony_ci * @buflen:		 The number of bytes to zero out
107362306a36Sopenharmony_ci * @skip:		 Number of bytes to skip before zeroing
107462306a36Sopenharmony_ci *
107562306a36Sopenharmony_ci * Returns the number of bytes zeroed.
107662306a36Sopenharmony_ci **/
107762306a36Sopenharmony_cisize_t sg_zero_buffer(struct scatterlist *sgl, unsigned int nents,
107862306a36Sopenharmony_ci		       size_t buflen, off_t skip)
107962306a36Sopenharmony_ci{
108062306a36Sopenharmony_ci	unsigned int offset = 0;
108162306a36Sopenharmony_ci	struct sg_mapping_iter miter;
108262306a36Sopenharmony_ci	unsigned int sg_flags = SG_MITER_ATOMIC | SG_MITER_TO_SG;
108362306a36Sopenharmony_ci
108462306a36Sopenharmony_ci	sg_miter_start(&miter, sgl, nents, sg_flags);
108562306a36Sopenharmony_ci
108662306a36Sopenharmony_ci	if (!sg_miter_skip(&miter, skip))
108762306a36Sopenharmony_ci		return false;
108862306a36Sopenharmony_ci
108962306a36Sopenharmony_ci	while (offset < buflen && sg_miter_next(&miter)) {
109062306a36Sopenharmony_ci		unsigned int len;
109162306a36Sopenharmony_ci
109262306a36Sopenharmony_ci		len = min(miter.length, buflen - offset);
109362306a36Sopenharmony_ci		memset(miter.addr, 0, len);
109462306a36Sopenharmony_ci
109562306a36Sopenharmony_ci		offset += len;
109662306a36Sopenharmony_ci	}
109762306a36Sopenharmony_ci
109862306a36Sopenharmony_ci	sg_miter_stop(&miter);
109962306a36Sopenharmony_ci	return offset;
110062306a36Sopenharmony_ci}
110162306a36Sopenharmony_ciEXPORT_SYMBOL(sg_zero_buffer);
110262306a36Sopenharmony_ci
110362306a36Sopenharmony_ci/*
110462306a36Sopenharmony_ci * Extract and pin a list of up to sg_max pages from UBUF- or IOVEC-class
110562306a36Sopenharmony_ci * iterators, and add them to the scatterlist.
110662306a36Sopenharmony_ci */
110762306a36Sopenharmony_cistatic ssize_t extract_user_to_sg(struct iov_iter *iter,
110862306a36Sopenharmony_ci				  ssize_t maxsize,
110962306a36Sopenharmony_ci				  struct sg_table *sgtable,
111062306a36Sopenharmony_ci				  unsigned int sg_max,
111162306a36Sopenharmony_ci				  iov_iter_extraction_t extraction_flags)
111262306a36Sopenharmony_ci{
111362306a36Sopenharmony_ci	struct scatterlist *sg = sgtable->sgl + sgtable->nents;
111462306a36Sopenharmony_ci	struct page **pages;
111562306a36Sopenharmony_ci	unsigned int npages;
111662306a36Sopenharmony_ci	ssize_t ret = 0, res;
111762306a36Sopenharmony_ci	size_t len, off;
111862306a36Sopenharmony_ci
111962306a36Sopenharmony_ci	/* We decant the page list into the tail of the scatterlist */
112062306a36Sopenharmony_ci	pages = (void *)sgtable->sgl +
112162306a36Sopenharmony_ci		array_size(sg_max, sizeof(struct scatterlist));
112262306a36Sopenharmony_ci	pages -= sg_max;
112362306a36Sopenharmony_ci
112462306a36Sopenharmony_ci	do {
112562306a36Sopenharmony_ci		res = iov_iter_extract_pages(iter, &pages, maxsize, sg_max,
112662306a36Sopenharmony_ci					     extraction_flags, &off);
112762306a36Sopenharmony_ci		if (res < 0)
112862306a36Sopenharmony_ci			goto failed;
112962306a36Sopenharmony_ci
113062306a36Sopenharmony_ci		len = res;
113162306a36Sopenharmony_ci		maxsize -= len;
113262306a36Sopenharmony_ci		ret += len;
113362306a36Sopenharmony_ci		npages = DIV_ROUND_UP(off + len, PAGE_SIZE);
113462306a36Sopenharmony_ci		sg_max -= npages;
113562306a36Sopenharmony_ci
113662306a36Sopenharmony_ci		for (; npages > 0; npages--) {
113762306a36Sopenharmony_ci			struct page *page = *pages;
113862306a36Sopenharmony_ci			size_t seg = min_t(size_t, PAGE_SIZE - off, len);
113962306a36Sopenharmony_ci
114062306a36Sopenharmony_ci			*pages++ = NULL;
114162306a36Sopenharmony_ci			sg_set_page(sg, page, seg, off);
114262306a36Sopenharmony_ci			sgtable->nents++;
114362306a36Sopenharmony_ci			sg++;
114462306a36Sopenharmony_ci			len -= seg;
114562306a36Sopenharmony_ci			off = 0;
114662306a36Sopenharmony_ci		}
114762306a36Sopenharmony_ci	} while (maxsize > 0 && sg_max > 0);
114862306a36Sopenharmony_ci
114962306a36Sopenharmony_ci	return ret;
115062306a36Sopenharmony_ci
115162306a36Sopenharmony_cifailed:
115262306a36Sopenharmony_ci	while (sgtable->nents > sgtable->orig_nents)
115362306a36Sopenharmony_ci		unpin_user_page(sg_page(&sgtable->sgl[--sgtable->nents]));
115462306a36Sopenharmony_ci	return res;
115562306a36Sopenharmony_ci}
115662306a36Sopenharmony_ci
115762306a36Sopenharmony_ci/*
115862306a36Sopenharmony_ci * Extract up to sg_max pages from a BVEC-type iterator and add them to the
115962306a36Sopenharmony_ci * scatterlist.  The pages are not pinned.
116062306a36Sopenharmony_ci */
116162306a36Sopenharmony_cistatic ssize_t extract_bvec_to_sg(struct iov_iter *iter,
116262306a36Sopenharmony_ci				  ssize_t maxsize,
116362306a36Sopenharmony_ci				  struct sg_table *sgtable,
116462306a36Sopenharmony_ci				  unsigned int sg_max,
116562306a36Sopenharmony_ci				  iov_iter_extraction_t extraction_flags)
116662306a36Sopenharmony_ci{
116762306a36Sopenharmony_ci	const struct bio_vec *bv = iter->bvec;
116862306a36Sopenharmony_ci	struct scatterlist *sg = sgtable->sgl + sgtable->nents;
116962306a36Sopenharmony_ci	unsigned long start = iter->iov_offset;
117062306a36Sopenharmony_ci	unsigned int i;
117162306a36Sopenharmony_ci	ssize_t ret = 0;
117262306a36Sopenharmony_ci
117362306a36Sopenharmony_ci	for (i = 0; i < iter->nr_segs; i++) {
117462306a36Sopenharmony_ci		size_t off, len;
117562306a36Sopenharmony_ci
117662306a36Sopenharmony_ci		len = bv[i].bv_len;
117762306a36Sopenharmony_ci		if (start >= len) {
117862306a36Sopenharmony_ci			start -= len;
117962306a36Sopenharmony_ci			continue;
118062306a36Sopenharmony_ci		}
118162306a36Sopenharmony_ci
118262306a36Sopenharmony_ci		len = min_t(size_t, maxsize, len - start);
118362306a36Sopenharmony_ci		off = bv[i].bv_offset + start;
118462306a36Sopenharmony_ci
118562306a36Sopenharmony_ci		sg_set_page(sg, bv[i].bv_page, len, off);
118662306a36Sopenharmony_ci		sgtable->nents++;
118762306a36Sopenharmony_ci		sg++;
118862306a36Sopenharmony_ci		sg_max--;
118962306a36Sopenharmony_ci
119062306a36Sopenharmony_ci		ret += len;
119162306a36Sopenharmony_ci		maxsize -= len;
119262306a36Sopenharmony_ci		if (maxsize <= 0 || sg_max == 0)
119362306a36Sopenharmony_ci			break;
119462306a36Sopenharmony_ci		start = 0;
119562306a36Sopenharmony_ci	}
119662306a36Sopenharmony_ci
119762306a36Sopenharmony_ci	if (ret > 0)
119862306a36Sopenharmony_ci		iov_iter_advance(iter, ret);
119962306a36Sopenharmony_ci	return ret;
120062306a36Sopenharmony_ci}
120162306a36Sopenharmony_ci
120262306a36Sopenharmony_ci/*
120362306a36Sopenharmony_ci * Extract up to sg_max pages from a KVEC-type iterator and add them to the
120462306a36Sopenharmony_ci * scatterlist.  This can deal with vmalloc'd buffers as well as kmalloc'd or
120562306a36Sopenharmony_ci * static buffers.  The pages are not pinned.
120662306a36Sopenharmony_ci */
120762306a36Sopenharmony_cistatic ssize_t extract_kvec_to_sg(struct iov_iter *iter,
120862306a36Sopenharmony_ci				  ssize_t maxsize,
120962306a36Sopenharmony_ci				  struct sg_table *sgtable,
121062306a36Sopenharmony_ci				  unsigned int sg_max,
121162306a36Sopenharmony_ci				  iov_iter_extraction_t extraction_flags)
121262306a36Sopenharmony_ci{
121362306a36Sopenharmony_ci	const struct kvec *kv = iter->kvec;
121462306a36Sopenharmony_ci	struct scatterlist *sg = sgtable->sgl + sgtable->nents;
121562306a36Sopenharmony_ci	unsigned long start = iter->iov_offset;
121662306a36Sopenharmony_ci	unsigned int i;
121762306a36Sopenharmony_ci	ssize_t ret = 0;
121862306a36Sopenharmony_ci
121962306a36Sopenharmony_ci	for (i = 0; i < iter->nr_segs; i++) {
122062306a36Sopenharmony_ci		struct page *page;
122162306a36Sopenharmony_ci		unsigned long kaddr;
122262306a36Sopenharmony_ci		size_t off, len, seg;
122362306a36Sopenharmony_ci
122462306a36Sopenharmony_ci		len = kv[i].iov_len;
122562306a36Sopenharmony_ci		if (start >= len) {
122662306a36Sopenharmony_ci			start -= len;
122762306a36Sopenharmony_ci			continue;
122862306a36Sopenharmony_ci		}
122962306a36Sopenharmony_ci
123062306a36Sopenharmony_ci		kaddr = (unsigned long)kv[i].iov_base + start;
123162306a36Sopenharmony_ci		off = kaddr & ~PAGE_MASK;
123262306a36Sopenharmony_ci		len = min_t(size_t, maxsize, len - start);
123362306a36Sopenharmony_ci		kaddr &= PAGE_MASK;
123462306a36Sopenharmony_ci
123562306a36Sopenharmony_ci		maxsize -= len;
123662306a36Sopenharmony_ci		ret += len;
123762306a36Sopenharmony_ci		do {
123862306a36Sopenharmony_ci			seg = min_t(size_t, len, PAGE_SIZE - off);
123962306a36Sopenharmony_ci			if (is_vmalloc_or_module_addr((void *)kaddr))
124062306a36Sopenharmony_ci				page = vmalloc_to_page((void *)kaddr);
124162306a36Sopenharmony_ci			else
124262306a36Sopenharmony_ci				page = virt_to_page((void *)kaddr);
124362306a36Sopenharmony_ci
124462306a36Sopenharmony_ci			sg_set_page(sg, page, len, off);
124562306a36Sopenharmony_ci			sgtable->nents++;
124662306a36Sopenharmony_ci			sg++;
124762306a36Sopenharmony_ci			sg_max--;
124862306a36Sopenharmony_ci
124962306a36Sopenharmony_ci			len -= seg;
125062306a36Sopenharmony_ci			kaddr += PAGE_SIZE;
125162306a36Sopenharmony_ci			off = 0;
125262306a36Sopenharmony_ci		} while (len > 0 && sg_max > 0);
125362306a36Sopenharmony_ci
125462306a36Sopenharmony_ci		if (maxsize <= 0 || sg_max == 0)
125562306a36Sopenharmony_ci			break;
125662306a36Sopenharmony_ci		start = 0;
125762306a36Sopenharmony_ci	}
125862306a36Sopenharmony_ci
125962306a36Sopenharmony_ci	if (ret > 0)
126062306a36Sopenharmony_ci		iov_iter_advance(iter, ret);
126162306a36Sopenharmony_ci	return ret;
126262306a36Sopenharmony_ci}
126362306a36Sopenharmony_ci
126462306a36Sopenharmony_ci/*
126562306a36Sopenharmony_ci * Extract up to sg_max folios from an XARRAY-type iterator and add them to
126662306a36Sopenharmony_ci * the scatterlist.  The pages are not pinned.
126762306a36Sopenharmony_ci */
126862306a36Sopenharmony_cistatic ssize_t extract_xarray_to_sg(struct iov_iter *iter,
126962306a36Sopenharmony_ci				    ssize_t maxsize,
127062306a36Sopenharmony_ci				    struct sg_table *sgtable,
127162306a36Sopenharmony_ci				    unsigned int sg_max,
127262306a36Sopenharmony_ci				    iov_iter_extraction_t extraction_flags)
127362306a36Sopenharmony_ci{
127462306a36Sopenharmony_ci	struct scatterlist *sg = sgtable->sgl + sgtable->nents;
127562306a36Sopenharmony_ci	struct xarray *xa = iter->xarray;
127662306a36Sopenharmony_ci	struct folio *folio;
127762306a36Sopenharmony_ci	loff_t start = iter->xarray_start + iter->iov_offset;
127862306a36Sopenharmony_ci	pgoff_t index = start / PAGE_SIZE;
127962306a36Sopenharmony_ci	ssize_t ret = 0;
128062306a36Sopenharmony_ci	size_t offset, len;
128162306a36Sopenharmony_ci	XA_STATE(xas, xa, index);
128262306a36Sopenharmony_ci
128362306a36Sopenharmony_ci	rcu_read_lock();
128462306a36Sopenharmony_ci
128562306a36Sopenharmony_ci	xas_for_each(&xas, folio, ULONG_MAX) {
128662306a36Sopenharmony_ci		if (xas_retry(&xas, folio))
128762306a36Sopenharmony_ci			continue;
128862306a36Sopenharmony_ci		if (WARN_ON(xa_is_value(folio)))
128962306a36Sopenharmony_ci			break;
129062306a36Sopenharmony_ci		if (WARN_ON(folio_test_hugetlb(folio)))
129162306a36Sopenharmony_ci			break;
129262306a36Sopenharmony_ci
129362306a36Sopenharmony_ci		offset = offset_in_folio(folio, start);
129462306a36Sopenharmony_ci		len = min_t(size_t, maxsize, folio_size(folio) - offset);
129562306a36Sopenharmony_ci
129662306a36Sopenharmony_ci		sg_set_page(sg, folio_page(folio, 0), len, offset);
129762306a36Sopenharmony_ci		sgtable->nents++;
129862306a36Sopenharmony_ci		sg++;
129962306a36Sopenharmony_ci		sg_max--;
130062306a36Sopenharmony_ci
130162306a36Sopenharmony_ci		maxsize -= len;
130262306a36Sopenharmony_ci		ret += len;
130362306a36Sopenharmony_ci		if (maxsize <= 0 || sg_max == 0)
130462306a36Sopenharmony_ci			break;
130562306a36Sopenharmony_ci	}
130662306a36Sopenharmony_ci
130762306a36Sopenharmony_ci	rcu_read_unlock();
130862306a36Sopenharmony_ci	if (ret > 0)
130962306a36Sopenharmony_ci		iov_iter_advance(iter, ret);
131062306a36Sopenharmony_ci	return ret;
131162306a36Sopenharmony_ci}
131262306a36Sopenharmony_ci
131362306a36Sopenharmony_ci/**
131462306a36Sopenharmony_ci * extract_iter_to_sg - Extract pages from an iterator and add to an sglist
131562306a36Sopenharmony_ci * @iter: The iterator to extract from
131662306a36Sopenharmony_ci * @maxsize: The amount of iterator to copy
131762306a36Sopenharmony_ci * @sgtable: The scatterlist table to fill in
131862306a36Sopenharmony_ci * @sg_max: Maximum number of elements in @sgtable that may be filled
131962306a36Sopenharmony_ci * @extraction_flags: Flags to qualify the request
132062306a36Sopenharmony_ci *
132162306a36Sopenharmony_ci * Extract the page fragments from the given amount of the source iterator and
132262306a36Sopenharmony_ci * add them to a scatterlist that refers to all of those bits, to a maximum
132362306a36Sopenharmony_ci * addition of @sg_max elements.
132462306a36Sopenharmony_ci *
132562306a36Sopenharmony_ci * The pages referred to by UBUF- and IOVEC-type iterators are extracted and
132662306a36Sopenharmony_ci * pinned; BVEC-, KVEC- and XARRAY-type are extracted but aren't pinned; PIPE-
132762306a36Sopenharmony_ci * and DISCARD-type are not supported.
132862306a36Sopenharmony_ci *
132962306a36Sopenharmony_ci * No end mark is placed on the scatterlist; that's left to the caller.
133062306a36Sopenharmony_ci *
133162306a36Sopenharmony_ci * @extraction_flags can have ITER_ALLOW_P2PDMA set to request peer-to-peer DMA
133262306a36Sopenharmony_ci * be allowed on the pages extracted.
133362306a36Sopenharmony_ci *
133462306a36Sopenharmony_ci * If successful, @sgtable->nents is updated to include the number of elements
133562306a36Sopenharmony_ci * added and the number of bytes added is returned.  @sgtable->orig_nents is
133662306a36Sopenharmony_ci * left unaltered.
133762306a36Sopenharmony_ci *
133862306a36Sopenharmony_ci * The iov_iter_extract_mode() function should be used to query how cleanup
133962306a36Sopenharmony_ci * should be performed.
134062306a36Sopenharmony_ci */
134162306a36Sopenharmony_cissize_t extract_iter_to_sg(struct iov_iter *iter, size_t maxsize,
134262306a36Sopenharmony_ci			   struct sg_table *sgtable, unsigned int sg_max,
134362306a36Sopenharmony_ci			   iov_iter_extraction_t extraction_flags)
134462306a36Sopenharmony_ci{
134562306a36Sopenharmony_ci	if (maxsize == 0)
134662306a36Sopenharmony_ci		return 0;
134762306a36Sopenharmony_ci
134862306a36Sopenharmony_ci	switch (iov_iter_type(iter)) {
134962306a36Sopenharmony_ci	case ITER_UBUF:
135062306a36Sopenharmony_ci	case ITER_IOVEC:
135162306a36Sopenharmony_ci		return extract_user_to_sg(iter, maxsize, sgtable, sg_max,
135262306a36Sopenharmony_ci					  extraction_flags);
135362306a36Sopenharmony_ci	case ITER_BVEC:
135462306a36Sopenharmony_ci		return extract_bvec_to_sg(iter, maxsize, sgtable, sg_max,
135562306a36Sopenharmony_ci					  extraction_flags);
135662306a36Sopenharmony_ci	case ITER_KVEC:
135762306a36Sopenharmony_ci		return extract_kvec_to_sg(iter, maxsize, sgtable, sg_max,
135862306a36Sopenharmony_ci					  extraction_flags);
135962306a36Sopenharmony_ci	case ITER_XARRAY:
136062306a36Sopenharmony_ci		return extract_xarray_to_sg(iter, maxsize, sgtable, sg_max,
136162306a36Sopenharmony_ci					    extraction_flags);
136262306a36Sopenharmony_ci	default:
136362306a36Sopenharmony_ci		pr_err("%s(%u) unsupported\n", __func__, iov_iter_type(iter));
136462306a36Sopenharmony_ci		WARN_ON_ONCE(1);
136562306a36Sopenharmony_ci		return -EIO;
136662306a36Sopenharmony_ci	}
136762306a36Sopenharmony_ci}
136862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(extract_iter_to_sg);
1369