2 * Copyright (c) 2010 Isilon Systems, Inc.
3 * Copyright (c) 2010 iX Systems, Inc.
4 * Copyright (c) 2010 Panasas, Inc.
5 * Copyright (c) 2013, 2014 Mellanox Technologies, Ltd.
6 * Copyright (c) 2015 Matthew Dillon <dillon@backplane.com>
7 * Copyright (c) 2016 Matt Macy <mmacy@nextbsd.org>
8 * Copyright (c) 2017-2018 François Tigeot <ftigeot@wolfpond.org>
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice unmodified, this list of conditions, and the following
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #include <linux/slab.h>
34 #include <linux/scatterlist.h>
35 #include <linux/highmem.h>
38 * __sg_alloc_table - Allocate and initialize an sg table with given allocator
39 * @table: The sg table header to use
40 * @nents: Number of entries in sg list
41 * @max_ents: The maximum number of entries the allocator returns per call
42 * @gfp_mask: GFP allocation mask
45 * This function returns a @table @nents long. The allocator is
46 * defined to return scatterlist chunks of maximum size @max_ents.
47 * Thus if @nents is bigger than @max_ents, the scatterlists will be
48 * chained in units of @max_ents.
51 * If this function returns non-0 (eg failure), the caller must call
52 * __sg_free_table() to cleanup any leftover allocations.
56 __sg_alloc_table(struct sg_table
*table
, unsigned int nents
,
57 unsigned int max_ents
, gfp_t gfp_mask
)
59 struct scatterlist
*sg
, *prv
;
62 memset(table
, 0, sizeof(*table
));
69 unsigned int sg_size
, alloc_size
= left
;
71 if (alloc_size
> max_ents
) {
72 alloc_size
= max_ents
;
73 sg_size
= alloc_size
- 1;
79 sg
= kmalloc(alloc_size
* sizeof(struct scatterlist
), M_DRM
, gfp_mask
);
82 * Adjust entry count to reflect that the last
83 * entry of the previous table won't be used for
84 * linkage. Without this, sg_kfree() may get
88 table
->nents
= ++table
->orig_nents
;
93 sg_init_table(sg
, alloc_size
);
94 table
->nents
= table
->orig_nents
+= sg_size
;
97 * If this is the first mapping, assign the sg table header.
98 * If this is not the first mapping, chain previous part.
101 sg_chain(prv
, max_ents
, sg
);
106 * If no more entries after this one, mark the end
109 sg_mark_end(&sg
[sg_size
- 1]);
118 __sg_free_table(struct sg_table
*table
, unsigned int max_ents
)
120 struct scatterlist
*sgl
, *next
;
122 if (unlikely(!table
->sgl
))
126 while (table
->orig_nents
) {
127 unsigned int alloc_size
= table
->orig_nents
;
128 unsigned int sg_size
;
131 * If we have more than max_ents segments left,
132 * then assign 'next' to the sg table after the current one.
133 * sg_size is then one less than alloc size, since the last
134 * element is the chain pointer.
136 if (alloc_size
> max_ents
) {
137 next
= sgl
[max_ents
- 1].sl_un
.sg
;
138 alloc_size
= max_ents
;
139 sg_size
= alloc_size
- 1;
141 sg_size
= alloc_size
;
145 table
->orig_nents
-= sg_size
;
154 sg_pcopy_from_buffer(struct scatterlist
*sgl
, unsigned int nents
,
155 const void *buf
, size_t buflen
, off_t skip
)
158 int len
, curlen
, curoff
;
159 struct sg_page_iter iter
;
160 struct scatterlist
*sg
;
165 for_each_sg_page(sgl
, &iter
, nents
, 0) {
169 if (skip
&& curlen
>= skip
) {
178 len
= min(curlen
, buflen
- off
);
179 page
= sg_page_iter_page(&iter
);
180 vaddr
= (char *)kmap(page
) + sg
->offset
;
181 memcpy(vaddr
, (const char *)buf
+ off
, len
);
190 sg_pcopy_to_buffer(struct scatterlist
*sgl
, unsigned int nents
,
191 void *buf
, size_t buflen
, off_t skip
)
194 int len
, curlen
, curoff
;
195 struct sg_page_iter iter
;
196 struct scatterlist
*sg
;
201 for_each_sg_page(sgl
, &iter
, nents
, 0) {
205 if (skip
&& curlen
>= skip
) {
214 len
= min(curlen
, buflen
- off
);
215 page
= sg_page_iter_page(&iter
);
216 vaddr
= (char *)kmap(page
) + sg
->offset
;
217 memcpy((char *)buf
+ off
, vaddr
, len
);