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