Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/testing/selftests/dma/dma_map_benchmark.c
26302 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/*
3
* Copyright (C) 2020 HiSilicon Limited.
4
*/
5
6
#include <fcntl.h>
7
#include <stdio.h>
8
#include <stdlib.h>
9
#include <string.h>
10
#include <unistd.h>
11
#include <sys/ioctl.h>
12
#include <sys/mman.h>
13
#include <linux/types.h>
14
#include <linux/map_benchmark.h>
15
16
#define NSEC_PER_MSEC 1000000L
17
18
static char *directions[] = {
19
"BIDIRECTIONAL",
20
"TO_DEVICE",
21
"FROM_DEVICE",
22
};
23
24
int main(int argc, char **argv)
25
{
26
struct map_benchmark map;
27
int fd, opt;
28
/* default single thread, run 20 seconds on NUMA_NO_NODE */
29
int threads = 1, seconds = 20, node = -1;
30
/* default dma mask 32bit, bidirectional DMA */
31
int bits = 32, xdelay = 0, dir = DMA_MAP_BIDIRECTIONAL;
32
/* default granule 1 PAGESIZE */
33
int granule = 1;
34
35
int cmd = DMA_MAP_BENCHMARK;
36
37
while ((opt = getopt(argc, argv, "t:s:n:b:d:x:g:")) != -1) {
38
switch (opt) {
39
case 't':
40
threads = atoi(optarg);
41
break;
42
case 's':
43
seconds = atoi(optarg);
44
break;
45
case 'n':
46
node = atoi(optarg);
47
break;
48
case 'b':
49
bits = atoi(optarg);
50
break;
51
case 'd':
52
dir = atoi(optarg);
53
break;
54
case 'x':
55
xdelay = atoi(optarg);
56
break;
57
case 'g':
58
granule = atoi(optarg);
59
break;
60
default:
61
return -1;
62
}
63
}
64
65
if (threads <= 0 || threads > DMA_MAP_MAX_THREADS) {
66
fprintf(stderr, "invalid number of threads, must be in 1-%d\n",
67
DMA_MAP_MAX_THREADS);
68
exit(1);
69
}
70
71
if (seconds <= 0 || seconds > DMA_MAP_MAX_SECONDS) {
72
fprintf(stderr, "invalid number of seconds, must be in 1-%d\n",
73
DMA_MAP_MAX_SECONDS);
74
exit(1);
75
}
76
77
if (xdelay < 0 || xdelay > DMA_MAP_MAX_TRANS_DELAY) {
78
fprintf(stderr, "invalid transmit delay, must be in 0-%ld\n",
79
DMA_MAP_MAX_TRANS_DELAY);
80
exit(1);
81
}
82
83
/* suppose the mininum DMA zone is 1MB in the world */
84
if (bits < 20 || bits > 64) {
85
fprintf(stderr, "invalid dma mask bit, must be in 20-64\n");
86
exit(1);
87
}
88
89
if (dir != DMA_MAP_BIDIRECTIONAL && dir != DMA_MAP_TO_DEVICE &&
90
dir != DMA_MAP_FROM_DEVICE) {
91
fprintf(stderr, "invalid dma direction\n");
92
exit(1);
93
}
94
95
if (granule < 1 || granule > 1024) {
96
fprintf(stderr, "invalid granule size\n");
97
exit(1);
98
}
99
100
fd = open("/sys/kernel/debug/dma_map_benchmark", O_RDWR);
101
if (fd == -1) {
102
perror("open");
103
exit(1);
104
}
105
106
memset(&map, 0, sizeof(map));
107
map.seconds = seconds;
108
map.threads = threads;
109
map.node = node;
110
map.dma_bits = bits;
111
map.dma_dir = dir;
112
map.dma_trans_ns = xdelay;
113
map.granule = granule;
114
115
if (ioctl(fd, cmd, &map)) {
116
perror("ioctl");
117
exit(1);
118
}
119
120
printf("dma mapping benchmark: threads:%d seconds:%d node:%d dir:%s granule: %d\n",
121
threads, seconds, node, dir[directions], granule);
122
printf("average map latency(us):%.1f standard deviation:%.1f\n",
123
map.avg_map_100ns/10.0, map.map_stddev/10.0);
124
printf("average unmap latency(us):%.1f standard deviation:%.1f\n",
125
map.avg_unmap_100ns/10.0, map.unmap_stddev/10.0);
126
127
return 0;
128
}
129
130