summaryrefslogtreecommitdiffstats
path: root/lib/sg_pool.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sg_pool.c')
-rw-r--r--lib/sg_pool.c39
1 files changed, 29 insertions, 10 deletions
diff --git a/lib/sg_pool.c b/lib/sg_pool.c
index cff20df2695e..db29e5c1f790 100644
--- a/lib/sg_pool.c
+++ b/lib/sg_pool.c
@@ -70,18 +70,27 @@ static struct scatterlist *sg_pool_alloc(unsigned int nents, gfp_t gfp_mask)
70/** 70/**
71 * sg_free_table_chained - Free a previously mapped sg table 71 * sg_free_table_chained - Free a previously mapped sg table
72 * @table: The sg table header to use 72 * @table: The sg table header to use
73 * @first_chunk: was first_chunk not NULL in sg_alloc_table_chained? 73 * @nents_first_chunk: size of the first_chunk SGL passed to
74 * sg_alloc_table_chained
74 * 75 *
75 * Description: 76 * Description:
76 * Free an sg table previously allocated and setup with 77 * Free an sg table previously allocated and setup with
77 * sg_alloc_table_chained(). 78 * sg_alloc_table_chained().
78 * 79 *
80 * @nents_first_chunk has to be same with that same parameter passed
81 * to sg_alloc_table_chained().
82 *
79 **/ 83 **/
80void sg_free_table_chained(struct sg_table *table, bool first_chunk) 84void sg_free_table_chained(struct sg_table *table,
85 unsigned nents_first_chunk)
81{ 86{
82 if (first_chunk && table->orig_nents <= SG_CHUNK_SIZE) 87 if (table->orig_nents <= nents_first_chunk)
83 return; 88 return;
84 __sg_free_table(table, SG_CHUNK_SIZE, first_chunk, sg_pool_free); 89
90 if (nents_first_chunk == 1)
91 nents_first_chunk = 0;
92
93 __sg_free_table(table, SG_CHUNK_SIZE, nents_first_chunk, sg_pool_free);
85} 94}
86EXPORT_SYMBOL_GPL(sg_free_table_chained); 95EXPORT_SYMBOL_GPL(sg_free_table_chained);
87 96
@@ -90,31 +99,41 @@ EXPORT_SYMBOL_GPL(sg_free_table_chained);
90 * @table: The sg table header to use 99 * @table: The sg table header to use
91 * @nents: Number of entries in sg list 100 * @nents: Number of entries in sg list
92 * @first_chunk: first SGL 101 * @first_chunk: first SGL
102 * @nents_first_chunk: number of the SGL of @first_chunk
93 * 103 *
94 * Description: 104 * Description:
95 * Allocate and chain SGLs in an sg table. If @nents@ is larger than 105 * Allocate and chain SGLs in an sg table. If @nents@ is larger than
96 * SG_CHUNK_SIZE a chained sg table will be setup. 106 * @nents_first_chunk a chained sg table will be setup. @first_chunk is
107 * ignored if nents_first_chunk <= 1 because user expects the SGL points
108 * non-chain SGL.
97 * 109 *
98 **/ 110 **/
99int sg_alloc_table_chained(struct sg_table *table, int nents, 111int sg_alloc_table_chained(struct sg_table *table, int nents,
100 struct scatterlist *first_chunk) 112 struct scatterlist *first_chunk, unsigned nents_first_chunk)
101{ 113{
102 int ret; 114 int ret;
103 115
104 BUG_ON(!nents); 116 BUG_ON(!nents);
105 117
106 if (first_chunk) { 118 if (first_chunk && nents_first_chunk) {
107 if (nents <= SG_CHUNK_SIZE) { 119 if (nents <= nents_first_chunk) {
108 table->nents = table->orig_nents = nents; 120 table->nents = table->orig_nents = nents;
109 sg_init_table(table->sgl, nents); 121 sg_init_table(table->sgl, nents);
110 return 0; 122 return 0;
111 } 123 }
112 } 124 }
113 125
126 /* User supposes that the 1st SGL includes real entry */
127 if (nents_first_chunk <= 1) {
128 first_chunk = NULL;
129 nents_first_chunk = 0;
130 }
131
114 ret = __sg_alloc_table(table, nents, SG_CHUNK_SIZE, 132 ret = __sg_alloc_table(table, nents, SG_CHUNK_SIZE,
115 first_chunk, GFP_ATOMIC, sg_pool_alloc); 133 first_chunk, nents_first_chunk,
134 GFP_ATOMIC, sg_pool_alloc);
116 if (unlikely(ret)) 135 if (unlikely(ret))
117 sg_free_table_chained(table, (bool)first_chunk); 136 sg_free_table_chained(table, nents_first_chunk);
118 return ret; 137 return ret;
119} 138}
120EXPORT_SYMBOL_GPL(sg_alloc_table_chained); 139EXPORT_SYMBOL_GPL(sg_alloc_table_chained);