aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/scsi_lib.c16
-rw-r--r--include/linux/scatterlist.h6
-rw-r--r--lib/scatterlist.c25
3 files changed, 27 insertions, 20 deletions
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 8723abeb018e..bbd7a0a08692 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -564,6 +564,11 @@ static struct scatterlist *scsi_sg_alloc(unsigned int nents, gfp_t gfp_mask)
564 return mempool_alloc(sgp->pool, gfp_mask); 564 return mempool_alloc(sgp->pool, gfp_mask);
565} 565}
566 566
567static void scsi_free_sgtable(struct scsi_data_buffer *sdb)
568{
569 __sg_free_table(&sdb->table, SCSI_MAX_SG_SEGMENTS, false, scsi_sg_free);
570}
571
567static int scsi_alloc_sgtable(struct scsi_data_buffer *sdb, int nents, 572static int scsi_alloc_sgtable(struct scsi_data_buffer *sdb, int nents,
568 gfp_t gfp_mask) 573 gfp_t gfp_mask)
569{ 574{
@@ -572,19 +577,12 @@ static int scsi_alloc_sgtable(struct scsi_data_buffer *sdb, int nents,
572 BUG_ON(!nents); 577 BUG_ON(!nents);
573 578
574 ret = __sg_alloc_table(&sdb->table, nents, SCSI_MAX_SG_SEGMENTS, 579 ret = __sg_alloc_table(&sdb->table, nents, SCSI_MAX_SG_SEGMENTS,
575 gfp_mask, scsi_sg_alloc); 580 NULL, gfp_mask, scsi_sg_alloc);
576 if (unlikely(ret)) 581 if (unlikely(ret))
577 __sg_free_table(&sdb->table, SCSI_MAX_SG_SEGMENTS, 582 scsi_free_sgtable(sdb);
578 scsi_sg_free);
579
580 return ret; 583 return ret;
581} 584}
582 585
583static void scsi_free_sgtable(struct scsi_data_buffer *sdb)
584{
585 __sg_free_table(&sdb->table, SCSI_MAX_SG_SEGMENTS, scsi_sg_free);
586}
587
588/* 586/*
589 * Function: scsi_release_buffers() 587 * Function: scsi_release_buffers()
590 * 588 *
diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h
index a964f7285600..f4ec8bbcb372 100644
--- a/include/linux/scatterlist.h
+++ b/include/linux/scatterlist.h
@@ -229,10 +229,10 @@ void sg_init_one(struct scatterlist *, const void *, unsigned int);
229typedef struct scatterlist *(sg_alloc_fn)(unsigned int, gfp_t); 229typedef struct scatterlist *(sg_alloc_fn)(unsigned int, gfp_t);
230typedef void (sg_free_fn)(struct scatterlist *, unsigned int); 230typedef void (sg_free_fn)(struct scatterlist *, unsigned int);
231 231
232void __sg_free_table(struct sg_table *, unsigned int, sg_free_fn *); 232void __sg_free_table(struct sg_table *, unsigned int, bool, sg_free_fn *);
233void sg_free_table(struct sg_table *); 233void sg_free_table(struct sg_table *);
234int __sg_alloc_table(struct sg_table *, unsigned int, unsigned int, gfp_t, 234int __sg_alloc_table(struct sg_table *, unsigned int, unsigned int,
235 sg_alloc_fn *); 235 struct scatterlist *, gfp_t, sg_alloc_fn *);
236int sg_alloc_table(struct sg_table *, unsigned int, gfp_t); 236int sg_alloc_table(struct sg_table *, unsigned int, gfp_t);
237int sg_alloc_table_from_pages(struct sg_table *sgt, 237int sg_alloc_table_from_pages(struct sg_table *sgt,
238 struct page **pages, unsigned int n_pages, 238 struct page **pages, unsigned int n_pages,
diff --git a/lib/scatterlist.c b/lib/scatterlist.c
index 3a8e8e8fb2a5..b4415fceb7e7 100644
--- a/lib/scatterlist.c
+++ b/lib/scatterlist.c
@@ -165,6 +165,7 @@ static void sg_kfree(struct scatterlist *sg, unsigned int nents)
165 * __sg_free_table - Free a previously mapped sg table 165 * __sg_free_table - Free a previously mapped sg table
166 * @table: The sg table header to use 166 * @table: The sg table header to use
167 * @max_ents: The maximum number of entries per single scatterlist 167 * @max_ents: The maximum number of entries per single scatterlist
168 * @skip_first_chunk: don't free the (preallocated) first scatterlist chunk
168 * @free_fn: Free function 169 * @free_fn: Free function
169 * 170 *
170 * Description: 171 * Description:
@@ -174,7 +175,7 @@ static void sg_kfree(struct scatterlist *sg, unsigned int nents)
174 * 175 *
175 **/ 176 **/
176void __sg_free_table(struct sg_table *table, unsigned int max_ents, 177void __sg_free_table(struct sg_table *table, unsigned int max_ents,
177 sg_free_fn *free_fn) 178 bool skip_first_chunk, sg_free_fn *free_fn)
178{ 179{
179 struct scatterlist *sgl, *next; 180 struct scatterlist *sgl, *next;
180 181
@@ -202,7 +203,10 @@ void __sg_free_table(struct sg_table *table, unsigned int max_ents,
202 } 203 }
203 204
204 table->orig_nents -= sg_size; 205 table->orig_nents -= sg_size;
205 free_fn(sgl, alloc_size); 206 if (!skip_first_chunk) {
207 free_fn(sgl, alloc_size);
208 skip_first_chunk = false;
209 }
206 sgl = next; 210 sgl = next;
207 } 211 }
208 212
@@ -217,7 +221,7 @@ EXPORT_SYMBOL(__sg_free_table);
217 **/ 221 **/
218void sg_free_table(struct sg_table *table) 222void sg_free_table(struct sg_table *table)
219{ 223{
220 __sg_free_table(table, SG_MAX_SINGLE_ALLOC, sg_kfree); 224 __sg_free_table(table, SG_MAX_SINGLE_ALLOC, false, sg_kfree);
221} 225}
222EXPORT_SYMBOL(sg_free_table); 226EXPORT_SYMBOL(sg_free_table);
223 227
@@ -241,8 +245,8 @@ EXPORT_SYMBOL(sg_free_table);
241 * 245 *
242 **/ 246 **/
243int __sg_alloc_table(struct sg_table *table, unsigned int nents, 247int __sg_alloc_table(struct sg_table *table, unsigned int nents,
244 unsigned int max_ents, gfp_t gfp_mask, 248 unsigned int max_ents, struct scatterlist *first_chunk,
245 sg_alloc_fn *alloc_fn) 249 gfp_t gfp_mask, sg_alloc_fn *alloc_fn)
246{ 250{
247 struct scatterlist *sg, *prv; 251 struct scatterlist *sg, *prv;
248 unsigned int left; 252 unsigned int left;
@@ -269,7 +273,12 @@ int __sg_alloc_table(struct sg_table *table, unsigned int nents,
269 273
270 left -= sg_size; 274 left -= sg_size;
271 275
272 sg = alloc_fn(alloc_size, gfp_mask); 276 if (first_chunk) {
277 sg = first_chunk;
278 first_chunk = NULL;
279 } else {
280 sg = alloc_fn(alloc_size, gfp_mask);
281 }
273 if (unlikely(!sg)) { 282 if (unlikely(!sg)) {
274 /* 283 /*
275 * Adjust entry count to reflect that the last 284 * Adjust entry count to reflect that the last
@@ -324,9 +333,9 @@ int sg_alloc_table(struct sg_table *table, unsigned int nents, gfp_t gfp_mask)
324 int ret; 333 int ret;
325 334
326 ret = __sg_alloc_table(table, nents, SG_MAX_SINGLE_ALLOC, 335 ret = __sg_alloc_table(table, nents, SG_MAX_SINGLE_ALLOC,
327 gfp_mask, sg_kmalloc); 336 NULL, gfp_mask, sg_kmalloc);
328 if (unlikely(ret)) 337 if (unlikely(ret))
329 __sg_free_table(table, SG_MAX_SINGLE_ALLOC, sg_kfree); 338 __sg_free_table(table, SG_MAX_SINGLE_ALLOC, false, sg_kfree);
330 339
331 return ret; 340 return ret;
332} 341}