1 #include <stdio.h>
2 #include <assert.h>
3 
4 #include <linux/scatterlist.h>
5 
6 #define MAX_PAGES (64)
7 
set_pages(struct page ** pages,const unsigned * array,unsigned num)8 static void set_pages(struct page **pages, const unsigned *array, unsigned num)
9 {
10 	unsigned int i;
11 
12 	assert(num < MAX_PAGES);
13 	for (i = 0; i < num; i++)
14 		pages[i] = (struct page *)(unsigned long)
15 			   ((1 + array[i]) * PAGE_SIZE);
16 }
17 
18 #define pfn(...) (unsigned []){ __VA_ARGS__ }
19 
main(void)20 int main(void)
21 {
22 	const unsigned int sgmax = SCATTERLIST_MAX_SEGMENT;
23 	struct test {
24 		int alloc_ret;
25 		unsigned num_pages;
26 		unsigned *pfn;
27 		unsigned size;
28 		unsigned int max_seg;
29 		unsigned int expected_segments;
30 	} *test, tests[] = {
31 		{ -EINVAL, 1, pfn(0), PAGE_SIZE, PAGE_SIZE + 1, 1 },
32 		{ -EINVAL, 1, pfn(0), PAGE_SIZE, 0, 1 },
33 		{ -EINVAL, 1, pfn(0), PAGE_SIZE, sgmax + 1, 1 },
34 		{ 0, 1, pfn(0), PAGE_SIZE, sgmax, 1 },
35 		{ 0, 1, pfn(0), 1, sgmax, 1 },
36 		{ 0, 2, pfn(0, 1), 2 * PAGE_SIZE, sgmax, 1 },
37 		{ 0, 2, pfn(1, 0), 2 * PAGE_SIZE, sgmax, 2 },
38 		{ 0, 3, pfn(0, 1, 2), 3 * PAGE_SIZE, sgmax, 1 },
39 		{ 0, 3, pfn(0, 2, 1), 3 * PAGE_SIZE, sgmax, 3 },
40 		{ 0, 3, pfn(0, 1, 3), 3 * PAGE_SIZE, sgmax, 2 },
41 		{ 0, 3, pfn(1, 2, 4), 3 * PAGE_SIZE, sgmax, 2 },
42 		{ 0, 3, pfn(1, 3, 4), 3 * PAGE_SIZE, sgmax, 2 },
43 		{ 0, 4, pfn(0, 1, 3, 4), 4 * PAGE_SIZE, sgmax, 2 },
44 		{ 0, 5, pfn(0, 1, 3, 4, 5), 5 * PAGE_SIZE, sgmax, 2 },
45 		{ 0, 5, pfn(0, 1, 3, 4, 6), 5 * PAGE_SIZE, sgmax, 3 },
46 		{ 0, 5, pfn(0, 1, 2, 3, 4), 5 * PAGE_SIZE, sgmax, 1 },
47 		{ 0, 5, pfn(0, 1, 2, 3, 4), 5 * PAGE_SIZE, 2 * PAGE_SIZE, 3 },
48 		{ 0, 6, pfn(0, 1, 2, 3, 4, 5), 6 * PAGE_SIZE, 2 * PAGE_SIZE, 3 },
49 		{ 0, 6, pfn(0, 2, 3, 4, 5, 6), 6 * PAGE_SIZE, 2 * PAGE_SIZE, 4 },
50 		{ 0, 6, pfn(0, 1, 3, 4, 5, 6), 6 * PAGE_SIZE, 2 * PAGE_SIZE, 3 },
51 		{ 0, 0, NULL, 0, 0, 0 },
52 	};
53 	unsigned int i;
54 
55 	for (i = 0, test = tests; test->expected_segments; test++, i++) {
56 		struct page *pages[MAX_PAGES];
57 		struct sg_table st;
58 		int ret;
59 
60 		set_pages(pages, test->pfn, test->num_pages);
61 
62 		ret = __sg_alloc_table_from_pages(&st, pages, test->num_pages,
63 						  0, test->size, test->max_seg,
64 						  GFP_KERNEL);
65 		assert(ret == test->alloc_ret);
66 
67 		if (test->alloc_ret)
68 			continue;
69 
70 		assert(st.nents == test->expected_segments);
71 		assert(st.orig_nents == test->expected_segments);
72 
73 		sg_free_table(&st);
74 	}
75 
76 	assert(i == (sizeof(tests) / sizeof(tests[0])) - 1);
77 
78 	return 0;
79 }
80