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