Subversion Repositories Kolibri OS

Rev

Rev 5270 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5056 serge 1
/*
2
 * Copyright (C) 2007 Jens Axboe 
3
 *
4
 * Scatterlist handling helpers.
5
 *
6
 * This source code is licensed under the GNU General Public License,
7
 * Version 2. See the file COPYING for more details.
8
 */
9
#include 
10
#include 
11
 
12
/**
13
 * sg_next - return the next scatterlist entry in a list
14
 * @sg:		The current sg entry
15
 *
16
 * Description:
17
 *   Usually the next entry will be @sg@ + 1, but if this sg element is part
18
 *   of a chained scatterlist, it could jump to the start of a new
19
 *   scatterlist array.
20
 *
21
 **/
22
struct scatterlist *sg_next(struct scatterlist *sg)
23
{
24
#ifdef CONFIG_DEBUG_SG
25
	BUG_ON(sg->sg_magic != SG_MAGIC);
26
#endif
27
    if (sg_is_last(sg))
28
        return NULL;
29
 
30
    sg++;
31
    if (unlikely(sg_is_chain(sg)))
32
            sg = sg_chain_ptr(sg);
33
 
34
    return sg;
35
}
36
EXPORT_SYMBOL(sg_next);
37
 
38
/**
39
 * sg_nents - return total count of entries in scatterlist
40
 * @sg:		The scatterlist
41
 *
42
 * Description:
43
 * Allows to know how many entries are in sg, taking into acount
44
 * chaining as well
45
 *
46
 **/
47
int sg_nents(struct scatterlist *sg)
48
{
49
	int nents;
50
	for (nents = 0; sg; sg = sg_next(sg))
51
		nents++;
52
	return nents;
53
}
54
EXPORT_SYMBOL(sg_nents);
55
 
56
 
57
/**
58
 * sg_last - return the last scatterlist entry in a list
59
 * @sgl:	First entry in the scatterlist
60
 * @nents:	Number of entries in the scatterlist
61
 *
62
 * Description:
63
 *   Should only be used casually, it (currently) scans the entire list
64
 *   to get the last entry.
65
 *
66
 *   Note that the @sgl@ pointer passed in need not be the first one,
67
 *   the important bit is that @nents@ denotes the number of entries that
68
 *   exist from @sgl@.
69
 *
70
 **/
71
struct scatterlist *sg_last(struct scatterlist *sgl, unsigned int nents)
72
{
73
#ifndef ARCH_HAS_SG_CHAIN
74
	struct scatterlist *ret = &sgl[nents - 1];
75
#else
76
	struct scatterlist *sg, *ret = NULL;
77
	unsigned int i;
78
 
79
	for_each_sg(sgl, sg, nents, i)
80
		ret = sg;
81
 
82
#endif
83
#ifdef CONFIG_DEBUG_SG
84
	BUG_ON(sgl[0].sg_magic != SG_MAGIC);
85
	BUG_ON(!sg_is_last(ret));
86
#endif
87
	return ret;
88
}
89
EXPORT_SYMBOL(sg_last);
90
 
91
/**
92
 * sg_init_table - Initialize SG table
93
 * @sgl:	   The SG table
94
 * @nents:	   Number of entries in table
95
 *
96
 * Notes:
97
 *   If this is part of a chained sg table, sg_mark_end() should be
98
 *   used only on the last table part.
99
 *
100
 **/
101
void sg_init_table(struct scatterlist *sgl, unsigned int nents)
102
{
103
    memset(sgl, 0, sizeof(*sgl) * nents);
104
#ifdef CONFIG_DEBUG_SG
105
    {
106
            unsigned int i;
107
            for (i = 0; i < nents; i++)
108
                    sgl[i].sg_magic = SG_MAGIC;
109
    }
110
#endif
111
    sg_mark_end(&sgl[nents - 1]);
112
}
113
EXPORT_SYMBOL(sg_init_table);
114
 
115
/**
116
 * sg_init_one - Initialize a single entry sg list
117
 * @sg:		 SG entry
118
 * @buf:	 Virtual address for IO
119
 * @buflen:	 IO length
120
 *
121
 **/
122
//void sg_init_one(struct scatterlist *sg, const void *buf, unsigned int buflen)
123
//{
124
//   sg_init_table(sg, 1);
125
//   sg_set_buf(sg, buf, buflen);
126
//}
127
EXPORT_SYMBOL(sg_init_one);
128
 
129
/*
130
 * The default behaviour of sg_alloc_table() is to use these kmalloc/kfree
131
 * helpers.
132
 */
133
static struct scatterlist *sg_kmalloc(unsigned int nents, gfp_t gfp_mask)
134
{
135
	return kmalloc(nents * sizeof(struct scatterlist), gfp_mask);
136
}
137
 
138
static void sg_kfree(struct scatterlist *sg, unsigned int nents)
139
{
140
	kfree(sg);
141
}
142
 
143
/**
144
 * __sg_free_table - Free a previously mapped sg table
145
 * @table:	The sg table header to use
146
 * @max_ents:	The maximum number of entries per single scatterlist
147
 * @skip_first_chunk: don't free the (preallocated) first scatterlist chunk
148
 * @free_fn:	Free function
149
 *
150
 *  Description:
151
 *    Free an sg table previously allocated and setup with
152
 *    __sg_alloc_table().  The @max_ents value must be identical to
153
 *    that previously used with __sg_alloc_table().
154
 *
155
 **/
156
void __sg_free_table(struct sg_table *table, unsigned int max_ents,
157
		     bool skip_first_chunk, sg_free_fn *free_fn)
158
{
159
    struct scatterlist *sgl, *next;
160
 
161
    if (unlikely(!table->sgl))
162
            return;
163
 
164
    sgl = table->sgl;
165
    while (table->orig_nents) {
166
        unsigned int alloc_size = table->orig_nents;
167
        unsigned int sg_size;
168
 
169
        /*
170
         * If we have more than max_ents segments left,
171
         * then assign 'next' to the sg table after the current one.
172
         * sg_size is then one less than alloc size, since the last
173
         * element is the chain pointer.
174
         */
175
        if (alloc_size > max_ents) {
176
                next = sg_chain_ptr(&sgl[max_ents - 1]);
177
                alloc_size = max_ents;
178
                sg_size = alloc_size - 1;
179
        } else {
180
                sg_size = alloc_size;
181
                next = NULL;
182
        }
183
 
184
        table->orig_nents -= sg_size;
185
		if (!skip_first_chunk) {
186
			free_fn(sgl, alloc_size);
187
			skip_first_chunk = false;
188
		}
189
        sgl = next;
190
    }
191
 
192
    table->sgl = NULL;
193
}
194
EXPORT_SYMBOL(__sg_free_table);
195
 
196
/**
197
 * sg_free_table - Free a previously allocated sg table
198
 * @table:	The mapped sg table header
199
 *
200
 **/
201
void sg_free_table(struct sg_table *table)
202
{
203
	__sg_free_table(table, SG_MAX_SINGLE_ALLOC, false, sg_kfree);
204
}
205
EXPORT_SYMBOL(sg_free_table);
206
 
207
/**
208
 * __sg_alloc_table - Allocate and initialize an sg table with given allocator
209
 * @table:	The sg table header to use
210
 * @nents:	Number of entries in sg list
211
 * @max_ents:	The maximum number of entries the allocator returns per call
212
 * @gfp_mask:	GFP allocation mask
213
 * @alloc_fn:	Allocator to use
214
 *
215
 * Description:
216
 *   This function returns a @table @nents long. The allocator is
217
 *   defined to return scatterlist chunks of maximum size @max_ents.
218
 *   Thus if @nents is bigger than @max_ents, the scatterlists will be
219
 *   chained in units of @max_ents.
220
 *
221
 * Notes:
222
 *   If this function returns non-0 (eg failure), the caller must call
223
 *   __sg_free_table() to cleanup any leftover allocations.
224
 *
225
 **/
226
int __sg_alloc_table(struct sg_table *table, unsigned int nents,
227
		     unsigned int max_ents, struct scatterlist *first_chunk,
228
		     gfp_t gfp_mask, sg_alloc_fn *alloc_fn)
229
{
230
    struct scatterlist *sg, *prv;
231
    unsigned int left;
232
 
233
	memset(table, 0, sizeof(*table));
234
 
235
	if (nents == 0)
236
		return -EINVAL;
237
#ifndef ARCH_HAS_SG_CHAIN
238
	if (WARN_ON_ONCE(nents > max_ents))
239
		return -EINVAL;
240
#endif
241
 
242
    left = nents;
243
    prv = NULL;
244
    do {
245
        unsigned int sg_size, alloc_size = left;
246
 
247
        if (alloc_size > max_ents) {
248
                alloc_size = max_ents;
249
                sg_size = alloc_size - 1;
250
        } else
251
                sg_size = alloc_size;
252
 
253
        left -= sg_size;
254
 
255
		if (first_chunk) {
256
			sg = first_chunk;
257
			first_chunk = NULL;
258
		} else {
259
			sg = alloc_fn(alloc_size, gfp_mask);
260
		}
261
        if (unlikely(!sg)) {
262
                /*
263
                 * Adjust entry count to reflect that the last
264
                 * entry of the previous table won't be used for
265
                 * linkage.  Without this, sg_kfree() may get
266
                 * confused.
267
                 */
268
                if (prv)
269
                        table->nents = ++table->orig_nents;
270
 
271
 			return -ENOMEM;
272
        }
273
 
274
        sg_init_table(sg, alloc_size);
275
        table->nents = table->orig_nents += sg_size;
276
 
277
        /*
278
         * If this is the first mapping, assign the sg table header.
279
         * If this is not the first mapping, chain previous part.
280
         */
281
        if (prv)
282
                sg_chain(prv, max_ents, sg);
283
        else
284
                table->sgl = sg;
285
 
286
        /*
287
         * If no more entries after this one, mark the end
288
         */
289
        if (!left)
290
                sg_mark_end(&sg[sg_size - 1]);
291
 
292
        prv = sg;
293
    } while (left);
294
 
295
    return 0;
296
}
297
EXPORT_SYMBOL(__sg_alloc_table);
298
 
299
/**
300
 * sg_alloc_table - Allocate and initialize an sg table
301
 * @table:	The sg table header to use
302
 * @nents:	Number of entries in sg list
303
 * @gfp_mask:	GFP allocation mask
304
 *
305
 *  Description:
306
 *    Allocate and initialize an sg table. If @nents@ is larger than
307
 *    SG_MAX_SINGLE_ALLOC a chained sg table will be setup.
308
 *
309
 **/
310
int sg_alloc_table(struct sg_table *table, unsigned int nents, gfp_t gfp_mask)
311
{
312
	int ret;
313
 
314
	ret = __sg_alloc_table(table, nents, SG_MAX_SINGLE_ALLOC,
315
			       NULL, gfp_mask, sg_kmalloc);
316
	if (unlikely(ret))
317
		__sg_free_table(table, SG_MAX_SINGLE_ALLOC, false, sg_kfree);
318
 
319
	return ret;
320
}
321
EXPORT_SYMBOL(sg_alloc_table);
322
 
323
 
324
 
325
 
326
void __sg_page_iter_start(struct sg_page_iter *piter,
327
              struct scatterlist *sglist, unsigned int nents,
328
              unsigned long pgoffset)
329
{
330
    piter->__pg_advance = 0;
331
    piter->__nents = nents;
332
 
333
    piter->sg = sglist;
334
    piter->sg_pgoffset = pgoffset;
335
}
336
EXPORT_SYMBOL(__sg_page_iter_start);
337
 
338
static int sg_page_count(struct scatterlist *sg)
339
{
340
    return PAGE_ALIGN(sg->offset + sg->length) >> PAGE_SHIFT;
341
}
342
 
343
bool __sg_page_iter_next(struct sg_page_iter *piter)
344
{
345
    if (!piter->__nents || !piter->sg)
346
        return false;
347
 
348
    piter->sg_pgoffset += piter->__pg_advance;
349
    piter->__pg_advance = 1;
350
 
351
    while (piter->sg_pgoffset >= sg_page_count(piter->sg)) {
352
        piter->sg_pgoffset -= sg_page_count(piter->sg);
353
        piter->sg = sg_next(piter->sg);
354
        if (!--piter->__nents || !piter->sg)
355
            return false;
356
    }
357
 
358
    return true;
359
}
360
EXPORT_SYMBOL(__sg_page_iter_next);
361