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