Merge tag 'scsi-sg' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull SCSI scatter-gather list updates from James Bottomley: "This topic branch covers a fundamental change in how our sg lists are allocated to make mq more efficient by reducing the size of the preallocated sg list. This necessitates a large number of driver changes because the previous guarantee that if a driver specified SG_ALL as the size of its scatter list, it would get a non-chained list and didn't need to bother with scatterlist iterators is now broken and every driver *must* use scatterlist iterators. This was broken out as a separate topic because we need to convert all the drivers before pulling the trigger and unconverted drivers kept being found, necessitating a rebase" * tag 'scsi-sg' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (21 commits) scsi: core: don't preallocate small SGL in case of NO_SG_CHAIN scsi: lib/sg_pool.c: clear 'first_chunk' in case of no preallocation scsi: core: avoid preallocating big SGL for data scsi: core: avoid preallocating big SGL for protection information scsi: lib/sg_pool.c: improve APIs for allocating sg pool scsi: esp: use sg helper to iterate over scatterlist scsi: NCR5380: use sg helper to iterate over scatterlist scsi: wd33c93: use sg helper to iterate over scatterlist scsi: ppa: use sg helper to iterate over scatterlist scsi: pcmcia: nsp_cs: use sg helper to iterate over scatterlist scsi: imm: use sg helper to iterate over scatterlist scsi: aha152x: use sg helper to iterate over scatterlist scsi: s390: zfcp_fc: use sg helper to iterate over scatterlist scsi: staging: unisys: visorhba: use sg helper to iterate over scatterlist scsi: usb: image: microtek: use sg helper to iterate over scatterlist scsi: pmcraid: use sg helper to iterate over scatterlist scsi: ipr: use sg helper to iterate over scatterlist scsi: mvumi: use sg helper to iterate over scatterlist scsi: lpfc: use sg helper to iterate over scatterlist scsi: advansys: use sg helper to iterate over scatterlist ...
This commit is contained in:
@@ -179,7 +179,8 @@ static void sg_kfree(struct scatterlist *sg, unsigned int nents)
|
||||
* __sg_free_table - Free a previously mapped sg table
|
||||
* @table: The sg table header to use
|
||||
* @max_ents: The maximum number of entries per single scatterlist
|
||||
* @skip_first_chunk: don't free the (preallocated) first scatterlist chunk
|
||||
* @nents_first_chunk: Number of entries int the (preallocated) first
|
||||
* scatterlist chunk, 0 means no such preallocated first chunk
|
||||
* @free_fn: Free function
|
||||
*
|
||||
* Description:
|
||||
@@ -189,9 +190,10 @@ static void sg_kfree(struct scatterlist *sg, unsigned int nents)
|
||||
*
|
||||
**/
|
||||
void __sg_free_table(struct sg_table *table, unsigned int max_ents,
|
||||
bool skip_first_chunk, sg_free_fn *free_fn)
|
||||
unsigned int nents_first_chunk, sg_free_fn *free_fn)
|
||||
{
|
||||
struct scatterlist *sgl, *next;
|
||||
unsigned curr_max_ents = nents_first_chunk ?: max_ents;
|
||||
|
||||
if (unlikely(!table->sgl))
|
||||
return;
|
||||
@@ -207,9 +209,9 @@ void __sg_free_table(struct sg_table *table, unsigned int max_ents,
|
||||
* sg_size is then one less than alloc size, since the last
|
||||
* element is the chain pointer.
|
||||
*/
|
||||
if (alloc_size > max_ents) {
|
||||
next = sg_chain_ptr(&sgl[max_ents - 1]);
|
||||
alloc_size = max_ents;
|
||||
if (alloc_size > curr_max_ents) {
|
||||
next = sg_chain_ptr(&sgl[curr_max_ents - 1]);
|
||||
alloc_size = curr_max_ents;
|
||||
sg_size = alloc_size - 1;
|
||||
} else {
|
||||
sg_size = alloc_size;
|
||||
@@ -217,11 +219,12 @@ void __sg_free_table(struct sg_table *table, unsigned int max_ents,
|
||||
}
|
||||
|
||||
table->orig_nents -= sg_size;
|
||||
if (skip_first_chunk)
|
||||
skip_first_chunk = false;
|
||||
if (nents_first_chunk)
|
||||
nents_first_chunk = 0;
|
||||
else
|
||||
free_fn(sgl, alloc_size);
|
||||
sgl = next;
|
||||
curr_max_ents = max_ents;
|
||||
}
|
||||
|
||||
table->sgl = NULL;
|
||||
@@ -244,6 +247,8 @@ EXPORT_SYMBOL(sg_free_table);
|
||||
* @table: The sg table header to use
|
||||
* @nents: Number of entries in sg list
|
||||
* @max_ents: The maximum number of entries the allocator returns per call
|
||||
* @nents_first_chunk: Number of entries int the (preallocated) first
|
||||
* scatterlist chunk, 0 means no such preallocated chunk provided by user
|
||||
* @gfp_mask: GFP allocation mask
|
||||
* @alloc_fn: Allocator to use
|
||||
*
|
||||
@@ -260,10 +265,13 @@ EXPORT_SYMBOL(sg_free_table);
|
||||
**/
|
||||
int __sg_alloc_table(struct sg_table *table, unsigned int nents,
|
||||
unsigned int max_ents, struct scatterlist *first_chunk,
|
||||
gfp_t gfp_mask, sg_alloc_fn *alloc_fn)
|
||||
unsigned int nents_first_chunk, gfp_t gfp_mask,
|
||||
sg_alloc_fn *alloc_fn)
|
||||
{
|
||||
struct scatterlist *sg, *prv;
|
||||
unsigned int left;
|
||||
unsigned curr_max_ents = nents_first_chunk ?: max_ents;
|
||||
unsigned prv_max_ents;
|
||||
|
||||
memset(table, 0, sizeof(*table));
|
||||
|
||||
@@ -279,8 +287,8 @@ int __sg_alloc_table(struct sg_table *table, unsigned int nents,
|
||||
do {
|
||||
unsigned int sg_size, alloc_size = left;
|
||||
|
||||
if (alloc_size > max_ents) {
|
||||
alloc_size = max_ents;
|
||||
if (alloc_size > curr_max_ents) {
|
||||
alloc_size = curr_max_ents;
|
||||
sg_size = alloc_size - 1;
|
||||
} else
|
||||
sg_size = alloc_size;
|
||||
@@ -314,7 +322,7 @@ int __sg_alloc_table(struct sg_table *table, unsigned int nents,
|
||||
* If this is not the first mapping, chain previous part.
|
||||
*/
|
||||
if (prv)
|
||||
sg_chain(prv, max_ents, sg);
|
||||
sg_chain(prv, prv_max_ents, sg);
|
||||
else
|
||||
table->sgl = sg;
|
||||
|
||||
@@ -325,6 +333,8 @@ int __sg_alloc_table(struct sg_table *table, unsigned int nents,
|
||||
sg_mark_end(&sg[sg_size - 1]);
|
||||
|
||||
prv = sg;
|
||||
prv_max_ents = curr_max_ents;
|
||||
curr_max_ents = max_ents;
|
||||
} while (left);
|
||||
|
||||
return 0;
|
||||
@@ -347,9 +357,9 @@ int sg_alloc_table(struct sg_table *table, unsigned int nents, gfp_t gfp_mask)
|
||||
int ret;
|
||||
|
||||
ret = __sg_alloc_table(table, nents, SG_MAX_SINGLE_ALLOC,
|
||||
NULL, gfp_mask, sg_kmalloc);
|
||||
NULL, 0, gfp_mask, sg_kmalloc);
|
||||
if (unlikely(ret))
|
||||
__sg_free_table(table, SG_MAX_SINGLE_ALLOC, false, sg_kfree);
|
||||
__sg_free_table(table, SG_MAX_SINGLE_ALLOC, 0, sg_kfree);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
Reference in New Issue
Block a user