| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | #include <linux/module.h> |
|---|
| 2 | 3 | #include <linux/scatterlist.h> |
|---|
| 3 | 4 | #include <linux/mempool.h> |
|---|
| .. | .. |
|---|
| 69 | 70 | /** |
|---|
| 70 | 71 | * sg_free_table_chained - Free a previously mapped sg table |
|---|
| 71 | 72 | * @table: The sg table header to use |
|---|
| 72 | | - * @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 |
|---|
| 73 | 75 | * |
|---|
| 74 | 76 | * Description: |
|---|
| 75 | 77 | * Free an sg table previously allocated and setup with |
|---|
| 76 | 78 | * sg_alloc_table_chained(). |
|---|
| 77 | 79 | * |
|---|
| 80 | + * @nents_first_chunk has to be same with that same parameter passed |
|---|
| 81 | + * to sg_alloc_table_chained(). |
|---|
| 82 | + * |
|---|
| 78 | 83 | **/ |
|---|
| 79 | | -void sg_free_table_chained(struct sg_table *table, bool first_chunk) |
|---|
| 84 | +void sg_free_table_chained(struct sg_table *table, |
|---|
| 85 | + unsigned nents_first_chunk) |
|---|
| 80 | 86 | { |
|---|
| 81 | | - if (first_chunk && table->orig_nents <= SG_CHUNK_SIZE) |
|---|
| 87 | + if (table->orig_nents <= nents_first_chunk) |
|---|
| 82 | 88 | return; |
|---|
| 83 | | - __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); |
|---|
| 84 | 94 | } |
|---|
| 85 | 95 | EXPORT_SYMBOL_GPL(sg_free_table_chained); |
|---|
| 86 | 96 | |
|---|
| .. | .. |
|---|
| 89 | 99 | * @table: The sg table header to use |
|---|
| 90 | 100 | * @nents: Number of entries in sg list |
|---|
| 91 | 101 | * @first_chunk: first SGL |
|---|
| 102 | + * @nents_first_chunk: number of the SGL of @first_chunk |
|---|
| 92 | 103 | * |
|---|
| 93 | 104 | * Description: |
|---|
| 94 | 105 | * Allocate and chain SGLs in an sg table. If @nents@ is larger than |
|---|
| 95 | | - * 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. |
|---|
| 96 | 109 | * |
|---|
| 97 | 110 | **/ |
|---|
| 98 | 111 | int sg_alloc_table_chained(struct sg_table *table, int nents, |
|---|
| 99 | | - struct scatterlist *first_chunk) |
|---|
| 112 | + struct scatterlist *first_chunk, unsigned nents_first_chunk) |
|---|
| 100 | 113 | { |
|---|
| 101 | 114 | int ret; |
|---|
| 102 | 115 | |
|---|
| 103 | 116 | BUG_ON(!nents); |
|---|
| 104 | 117 | |
|---|
| 105 | | - if (first_chunk) { |
|---|
| 106 | | - if (nents <= SG_CHUNK_SIZE) { |
|---|
| 118 | + if (first_chunk && nents_first_chunk) { |
|---|
| 119 | + if (nents <= nents_first_chunk) { |
|---|
| 107 | 120 | table->nents = table->orig_nents = nents; |
|---|
| 108 | 121 | sg_init_table(table->sgl, nents); |
|---|
| 109 | 122 | return 0; |
|---|
| 110 | 123 | } |
|---|
| 111 | 124 | } |
|---|
| 112 | 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 | + |
|---|
| 113 | 132 | ret = __sg_alloc_table(table, nents, SG_CHUNK_SIZE, |
|---|
| 114 | | - first_chunk, GFP_ATOMIC, sg_pool_alloc); |
|---|
| 133 | + first_chunk, nents_first_chunk, |
|---|
| 134 | + GFP_ATOMIC, sg_pool_alloc); |
|---|
| 115 | 135 | if (unlikely(ret)) |
|---|
| 116 | | - sg_free_table_chained(table, (bool)first_chunk); |
|---|
| 136 | + sg_free_table_chained(table, nents_first_chunk); |
|---|
| 117 | 137 | return ret; |
|---|
| 118 | 138 | } |
|---|
| 119 | 139 | EXPORT_SYMBOL_GPL(sg_alloc_table_chained); |
|---|
| .. | .. |
|---|
| 148 | 168 | cleanup_sdb: |
|---|
| 149 | 169 | for (i = 0; i < SG_MEMPOOL_NR; i++) { |
|---|
| 150 | 170 | struct sg_pool *sgp = sg_pools + i; |
|---|
| 151 | | - if (sgp->pool) |
|---|
| 152 | | - mempool_destroy(sgp->pool); |
|---|
| 153 | | - if (sgp->slab) |
|---|
| 154 | | - kmem_cache_destroy(sgp->slab); |
|---|
| 171 | + |
|---|
| 172 | + mempool_destroy(sgp->pool); |
|---|
| 173 | + kmem_cache_destroy(sgp->slab); |
|---|
| 155 | 174 | } |
|---|
| 156 | 175 | |
|---|
| 157 | 176 | return -ENOMEM; |
|---|