xref: /OK3568_Linux_fs/kernel/tools/testing/scatterlist/main.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun #include <stdio.h>
2*4882a593Smuzhiyun #include <assert.h>
3*4882a593Smuzhiyun 
4*4882a593Smuzhiyun #include <linux/scatterlist.h>
5*4882a593Smuzhiyun 
6*4882a593Smuzhiyun #define MAX_PAGES (64)
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun struct test {
9*4882a593Smuzhiyun 	int alloc_ret;
10*4882a593Smuzhiyun 	unsigned num_pages;
11*4882a593Smuzhiyun 	unsigned *pfn;
12*4882a593Smuzhiyun 	unsigned size;
13*4882a593Smuzhiyun 	unsigned int max_seg;
14*4882a593Smuzhiyun 	unsigned int expected_segments;
15*4882a593Smuzhiyun };
16*4882a593Smuzhiyun 
set_pages(struct page ** pages,const unsigned * array,unsigned num)17*4882a593Smuzhiyun static void set_pages(struct page **pages, const unsigned *array, unsigned num)
18*4882a593Smuzhiyun {
19*4882a593Smuzhiyun 	unsigned int i;
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun 	assert(num < MAX_PAGES);
22*4882a593Smuzhiyun 	for (i = 0; i < num; i++)
23*4882a593Smuzhiyun 		pages[i] = (struct page *)(unsigned long)
24*4882a593Smuzhiyun 			   ((1 + array[i]) * PAGE_SIZE);
25*4882a593Smuzhiyun }
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun #define pfn(...) (unsigned []){ __VA_ARGS__ }
28*4882a593Smuzhiyun 
fail(struct test * test,struct sg_table * st,const char * cond)29*4882a593Smuzhiyun static void fail(struct test *test, struct sg_table *st, const char *cond)
30*4882a593Smuzhiyun {
31*4882a593Smuzhiyun 	unsigned int i;
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun 	fprintf(stderr, "Failed on '%s'!\n\n", cond);
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun 	printf("size = %u, max segment = %u, expected nents = %u\nst->nents = %u, st->orig_nents= %u\n",
36*4882a593Smuzhiyun 	       test->size, test->max_seg, test->expected_segments, st->nents,
37*4882a593Smuzhiyun 	       st->orig_nents);
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun 	printf("%u input PFNs:", test->num_pages);
40*4882a593Smuzhiyun 	for (i = 0; i < test->num_pages; i++)
41*4882a593Smuzhiyun 		printf(" %x", test->pfn[i]);
42*4882a593Smuzhiyun 	printf("\n");
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun 	exit(1);
45*4882a593Smuzhiyun }
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun #define VALIDATE(cond, st, test) \
48*4882a593Smuzhiyun 	if (!(cond)) \
49*4882a593Smuzhiyun 		fail((test), (st), #cond);
50*4882a593Smuzhiyun 
main(void)51*4882a593Smuzhiyun int main(void)
52*4882a593Smuzhiyun {
53*4882a593Smuzhiyun 	const unsigned int sgmax = SCATTERLIST_MAX_SEGMENT;
54*4882a593Smuzhiyun 	struct test *test, tests[] = {
55*4882a593Smuzhiyun 		{ -EINVAL, 1, pfn(0), PAGE_SIZE, 0, 1 },
56*4882a593Smuzhiyun 		{ 0, 1, pfn(0), PAGE_SIZE, PAGE_SIZE + 1, 1 },
57*4882a593Smuzhiyun 		{ 0, 1, pfn(0), PAGE_SIZE, sgmax + 1, 1 },
58*4882a593Smuzhiyun 		{ 0, 1, pfn(0), PAGE_SIZE, sgmax, 1 },
59*4882a593Smuzhiyun 		{ 0, 1, pfn(0), 1, sgmax, 1 },
60*4882a593Smuzhiyun 		{ 0, 2, pfn(0, 1), 2 * PAGE_SIZE, sgmax, 1 },
61*4882a593Smuzhiyun 		{ 0, 2, pfn(1, 0), 2 * PAGE_SIZE, sgmax, 2 },
62*4882a593Smuzhiyun 		{ 0, 3, pfn(0, 1, 2), 3 * PAGE_SIZE, sgmax, 1 },
63*4882a593Smuzhiyun 		{ 0, 3, pfn(0, 2, 1), 3 * PAGE_SIZE, sgmax, 3 },
64*4882a593Smuzhiyun 		{ 0, 3, pfn(0, 1, 3), 3 * PAGE_SIZE, sgmax, 2 },
65*4882a593Smuzhiyun 		{ 0, 3, pfn(1, 2, 4), 3 * PAGE_SIZE, sgmax, 2 },
66*4882a593Smuzhiyun 		{ 0, 3, pfn(1, 3, 4), 3 * PAGE_SIZE, sgmax, 2 },
67*4882a593Smuzhiyun 		{ 0, 4, pfn(0, 1, 3, 4), 4 * PAGE_SIZE, sgmax, 2 },
68*4882a593Smuzhiyun 		{ 0, 5, pfn(0, 1, 3, 4, 5), 5 * PAGE_SIZE, sgmax, 2 },
69*4882a593Smuzhiyun 		{ 0, 5, pfn(0, 1, 3, 4, 6), 5 * PAGE_SIZE, sgmax, 3 },
70*4882a593Smuzhiyun 		{ 0, 5, pfn(0, 1, 2, 3, 4), 5 * PAGE_SIZE, sgmax, 1 },
71*4882a593Smuzhiyun 		{ 0, 5, pfn(0, 1, 2, 3, 4), 5 * PAGE_SIZE, 2 * PAGE_SIZE, 3 },
72*4882a593Smuzhiyun 		{ 0, 6, pfn(0, 1, 2, 3, 4, 5), 6 * PAGE_SIZE, 2 * PAGE_SIZE, 3 },
73*4882a593Smuzhiyun 		{ 0, 6, pfn(0, 2, 3, 4, 5, 6), 6 * PAGE_SIZE, 2 * PAGE_SIZE, 4 },
74*4882a593Smuzhiyun 		{ 0, 6, pfn(0, 1, 3, 4, 5, 6), 6 * PAGE_SIZE, 2 * PAGE_SIZE, 3 },
75*4882a593Smuzhiyun 		{ 0, 0, NULL, 0, 0, 0 },
76*4882a593Smuzhiyun 	};
77*4882a593Smuzhiyun 	unsigned int i;
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun 	for (i = 0, test = tests; test->expected_segments; test++, i++) {
80*4882a593Smuzhiyun 		struct page *pages[MAX_PAGES];
81*4882a593Smuzhiyun 		struct sg_table st;
82*4882a593Smuzhiyun 		struct scatterlist *sg;
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun 		set_pages(pages, test->pfn, test->num_pages);
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun 		sg = __sg_alloc_table_from_pages(&st, pages, test->num_pages, 0,
87*4882a593Smuzhiyun 				test->size, test->max_seg, NULL, 0, GFP_KERNEL);
88*4882a593Smuzhiyun 		assert(PTR_ERR_OR_ZERO(sg) == test->alloc_ret);
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun 		if (test->alloc_ret)
91*4882a593Smuzhiyun 			continue;
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun 		VALIDATE(st.nents == test->expected_segments, &st, test);
94*4882a593Smuzhiyun 		VALIDATE(st.orig_nents == test->expected_segments, &st, test);
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun 		sg_free_table(&st);
97*4882a593Smuzhiyun 	}
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun 	assert(i == (sizeof(tests) / sizeof(tests[0])) - 1);
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun 	return 0;
102*4882a593Smuzhiyun }
103