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