xref: /linux/mm/dmapool_test.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
1*def85743SKeith Busch #include <linux/device.h>
2*def85743SKeith Busch #include <linux/dma-map-ops.h>
3*def85743SKeith Busch #include <linux/dma-mapping.h>
4*def85743SKeith Busch #include <linux/dmapool.h>
5*def85743SKeith Busch #include <linux/kernel.h>
6*def85743SKeith Busch #include <linux/ktime.h>
7*def85743SKeith Busch #include <linux/module.h>
8*def85743SKeith Busch 
9*def85743SKeith Busch #define NR_TESTS (100)
10*def85743SKeith Busch 
11*def85743SKeith Busch struct dma_pool_pair {
12*def85743SKeith Busch 	dma_addr_t dma;
13*def85743SKeith Busch 	void *v;
14*def85743SKeith Busch };
15*def85743SKeith Busch 
16*def85743SKeith Busch struct dmapool_parms {
17*def85743SKeith Busch 	size_t size;
18*def85743SKeith Busch 	size_t align;
19*def85743SKeith Busch 	size_t boundary;
20*def85743SKeith Busch };
21*def85743SKeith Busch 
22*def85743SKeith Busch static const struct dmapool_parms pool_parms[] = {
23*def85743SKeith Busch 	{ .size = 16, .align = 16, .boundary = 0 },
24*def85743SKeith Busch 	{ .size = 64, .align = 64, .boundary = 0 },
25*def85743SKeith Busch 	{ .size = 256, .align = 256, .boundary = 0 },
26*def85743SKeith Busch 	{ .size = 1024, .align = 1024, .boundary = 0 },
27*def85743SKeith Busch 	{ .size = 4096, .align = 4096, .boundary = 0 },
28*def85743SKeith Busch 	{ .size = 68, .align = 32, .boundary = 4096 },
29*def85743SKeith Busch };
30*def85743SKeith Busch 
31*def85743SKeith Busch static struct dma_pool *pool;
32*def85743SKeith Busch static struct device test_dev;
33*def85743SKeith Busch static u64 dma_mask;
34*def85743SKeith Busch 
nr_blocks(int size)35*def85743SKeith Busch static inline int nr_blocks(int size)
36*def85743SKeith Busch {
37*def85743SKeith Busch 	return clamp_t(int, (PAGE_SIZE / size) * 512, 1024, 8192);
38*def85743SKeith Busch }
39*def85743SKeith Busch 
dmapool_test_alloc(struct dma_pool_pair * p,int blocks)40*def85743SKeith Busch static int dmapool_test_alloc(struct dma_pool_pair *p, int blocks)
41*def85743SKeith Busch {
42*def85743SKeith Busch 	int i;
43*def85743SKeith Busch 
44*def85743SKeith Busch 	for (i = 0; i < blocks; i++) {
45*def85743SKeith Busch 		p[i].v = dma_pool_alloc(pool, GFP_KERNEL,
46*def85743SKeith Busch 					&p[i].dma);
47*def85743SKeith Busch 		if (!p[i].v)
48*def85743SKeith Busch 			goto pool_fail;
49*def85743SKeith Busch 	}
50*def85743SKeith Busch 
51*def85743SKeith Busch 	for (i = 0; i < blocks; i++)
52*def85743SKeith Busch 		dma_pool_free(pool, p[i].v, p[i].dma);
53*def85743SKeith Busch 
54*def85743SKeith Busch 	return 0;
55*def85743SKeith Busch 
56*def85743SKeith Busch pool_fail:
57*def85743SKeith Busch 	for (--i; i >= 0; i--)
58*def85743SKeith Busch 		dma_pool_free(pool, p[i].v, p[i].dma);
59*def85743SKeith Busch 	return -ENOMEM;
60*def85743SKeith Busch }
61*def85743SKeith Busch 
dmapool_test_block(const struct dmapool_parms * parms)62*def85743SKeith Busch static int dmapool_test_block(const struct dmapool_parms *parms)
63*def85743SKeith Busch {
64*def85743SKeith Busch 	int blocks = nr_blocks(parms->size);
65*def85743SKeith Busch 	ktime_t start_time, end_time;
66*def85743SKeith Busch 	struct dma_pool_pair *p;
67*def85743SKeith Busch 	int i, ret;
68*def85743SKeith Busch 
69*def85743SKeith Busch 	p = kcalloc(blocks, sizeof(*p), GFP_KERNEL);
70*def85743SKeith Busch 	if (!p)
71*def85743SKeith Busch 		return -ENOMEM;
72*def85743SKeith Busch 
73*def85743SKeith Busch 	pool = dma_pool_create("test pool", &test_dev, parms->size,
74*def85743SKeith Busch 			       parms->align, parms->boundary);
75*def85743SKeith Busch 	if (!pool) {
76*def85743SKeith Busch 		ret = -ENOMEM;
77*def85743SKeith Busch 		goto free_pairs;
78*def85743SKeith Busch 	}
79*def85743SKeith Busch 
80*def85743SKeith Busch 	start_time = ktime_get();
81*def85743SKeith Busch 	for (i = 0; i < NR_TESTS; i++) {
82*def85743SKeith Busch 		ret = dmapool_test_alloc(p, blocks);
83*def85743SKeith Busch 		if (ret)
84*def85743SKeith Busch 			goto free_pool;
85*def85743SKeith Busch 		if (need_resched())
86*def85743SKeith Busch 			cond_resched();
87*def85743SKeith Busch 	}
88*def85743SKeith Busch 	end_time = ktime_get();
89*def85743SKeith Busch 
90*def85743SKeith Busch 	printk("dmapool test: size:%-4zu align:%-4zu blocks:%-4d time:%llu\n",
91*def85743SKeith Busch 		parms->size, parms->align, blocks,
92*def85743SKeith Busch 		ktime_us_delta(end_time, start_time));
93*def85743SKeith Busch 
94*def85743SKeith Busch free_pool:
95*def85743SKeith Busch 	dma_pool_destroy(pool);
96*def85743SKeith Busch free_pairs:
97*def85743SKeith Busch 	kfree(p);
98*def85743SKeith Busch 	return ret;
99*def85743SKeith Busch }
100*def85743SKeith Busch 
dmapool_test_release(struct device * dev)101*def85743SKeith Busch static void dmapool_test_release(struct device *dev)
102*def85743SKeith Busch {
103*def85743SKeith Busch }
104*def85743SKeith Busch 
dmapool_checks(void)105*def85743SKeith Busch static int dmapool_checks(void)
106*def85743SKeith Busch {
107*def85743SKeith Busch 	int i, ret;
108*def85743SKeith Busch 
109*def85743SKeith Busch 	ret = dev_set_name(&test_dev, "dmapool-test");
110*def85743SKeith Busch 	if (ret)
111*def85743SKeith Busch 		return ret;
112*def85743SKeith Busch 
113*def85743SKeith Busch 	ret = device_register(&test_dev);
114*def85743SKeith Busch 	if (ret) {
115*def85743SKeith Busch 		printk("%s: register failed:%d\n", __func__, ret);
116*def85743SKeith Busch 		goto put_device;
117*def85743SKeith Busch 	}
118*def85743SKeith Busch 
119*def85743SKeith Busch 	test_dev.release = dmapool_test_release;
120*def85743SKeith Busch 	set_dma_ops(&test_dev, NULL);
121*def85743SKeith Busch 	test_dev.dma_mask = &dma_mask;
122*def85743SKeith Busch 	ret = dma_set_mask_and_coherent(&test_dev, DMA_BIT_MASK(64));
123*def85743SKeith Busch 	if (ret) {
124*def85743SKeith Busch 		printk("%s: mask failed:%d\n", __func__, ret);
125*def85743SKeith Busch 		goto del_device;
126*def85743SKeith Busch 	}
127*def85743SKeith Busch 
128*def85743SKeith Busch 	for (i = 0; i < ARRAY_SIZE(pool_parms); i++) {
129*def85743SKeith Busch 		ret = dmapool_test_block(&pool_parms[i]);
130*def85743SKeith Busch 		if (ret)
131*def85743SKeith Busch 			break;
132*def85743SKeith Busch 	}
133*def85743SKeith Busch 
134*def85743SKeith Busch del_device:
135*def85743SKeith Busch 	device_del(&test_dev);
136*def85743SKeith Busch put_device:
137*def85743SKeith Busch 	put_device(&test_dev);
138*def85743SKeith Busch 	return ret;
139*def85743SKeith Busch }
140*def85743SKeith Busch 
dmapool_exit(void)141*def85743SKeith Busch static void dmapool_exit(void)
142*def85743SKeith Busch {
143*def85743SKeith Busch }
144*def85743SKeith Busch 
145*def85743SKeith Busch module_init(dmapool_checks);
146*def85743SKeith Busch module_exit(dmapool_exit);
147*def85743SKeith Busch MODULE_LICENSE("GPL");
148