]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tools/tools/ioat/ioatcontrol.c
Merge llvm-project release/18.x llvmorg-18.1.1-0-gdba2a75e9c7e
[FreeBSD/FreeBSD.git] / tools / tools / ioat / ioatcontrol.c
1 /*-
2  * Copyright (C) 2012 Intel Corporation
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26
27 #include <sys/cdefs.h>
28 #include <sys/ioctl.h>
29 #include <sys/queue.h>
30
31 #include <fcntl.h>
32 #include <stdbool.h>
33 #include <stdio.h>
34 #include <stdint.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <sysexits.h>
38 #include <unistd.h>
39
40 #include <libutil.h>
41
42 #include "ioat_test.h"
43
44 static int prettyprint(struct ioat_test *);
45
46 static void
47 usage(void)
48 {
49
50         printf("Usage: %s [-c period] [-EefmVxXz] channel-number num-txns [<bufsize> "
51             "[<chain-len> [duration]]]\n", getprogname());
52         printf("       %s -r [-c period] [-vVwz] channel-number address [<bufsize>]\n\n",
53             getprogname());
54         printf("           -c period - Enable interrupt coalescing (us) (default: 0)\n");
55         printf("           -E        - Test contiguous 8k copy.\n");
56         printf("           -e        - Test non-contiguous 8k copy.\n");
57         printf("           -f        - Test block fill.\n");
58         printf("           -m        - Test memcpy instead of DMA.\n");
59         printf("           -r        - Issue DMA to or from a specific address.\n");
60         printf("           -V        - Enable verification\n");
61         printf("           -v        - <address> is a kernel virtual address\n");
62         printf("           -w        - Write to the specified address\n");
63         printf("           -x        - Test DMA CRC.\n");
64         printf("           -X        - Test DMA CRC copy.\n");
65         printf("           -z        - Zero device stats before test\n");
66         exit(EX_USAGE);
67 }
68
69 static void
70 main_raw(struct ioat_test *t, int argc, char **argv)
71 {
72         int fd;
73
74         /* Raw DMA defaults */
75         t->testkind = IOAT_TEST_RAW_DMA;
76         t->transactions = 1;
77         t->chain_depth = 1;
78         t->buffer_size = 4 * 1024;
79
80         t->raw_target = strtoull(argv[1], NULL, 0);
81         if (t->raw_target == 0) {
82                 printf("Target shoudln't be NULL\n");
83                 exit(EX_USAGE);
84         }
85
86         if (argc >= 3) {
87                 t->buffer_size = atoi(argv[2]);
88                 if (t->buffer_size == 0) {
89                         printf("Buffer size must be greater than zero\n");
90                         exit(EX_USAGE);
91                 }
92         }
93
94         fd = open("/dev/ioat_test", O_RDWR);
95         if (fd < 0) {
96                 printf("Cannot open /dev/ioat_test\n");
97                 exit(EX_UNAVAILABLE);
98         }
99
100         (void)ioctl(fd, IOAT_DMATEST, t);
101         close(fd);
102
103         exit(prettyprint(t));
104 }
105
106 int
107 main(int argc, char **argv)
108 {
109         struct ioat_test t;
110         int fd, ch;
111         bool fflag, rflag, Eflag, eflag, mflag, xflag, Xflag;
112         unsigned modeflags;
113
114         memset(&t, 0, sizeof(t));
115
116         fflag = rflag = Eflag = eflag = mflag = xflag = Xflag = false;
117         modeflags = 0;
118
119         while ((ch = getopt(argc, argv, "c:EefmrvVwxXz")) != -1) {
120                 switch (ch) {
121                 case 'c':
122                         t.coalesce_period = atoi(optarg);
123                         break;
124                 case 'E':
125                         Eflag = true;
126                         modeflags++;
127                         break;
128                 case 'e':
129                         eflag = true;
130                         modeflags++;
131                         break;
132                 case 'f':
133                         fflag = true;
134                         modeflags++;
135                         break;
136                 case 'm':
137                         mflag = true;
138                         modeflags++;
139                         break;
140                 case 'r':
141                         rflag = true;
142                         modeflags++;
143                         break;
144                 case 'v':
145                         t.raw_is_virtual = true;
146                         break;
147                 case 'V':
148                         t.verify = true;
149                         break;
150                 case 'w':
151                         t.raw_write = true;
152                         break;
153                 case 'x':
154                         xflag = true;
155                         modeflags++;
156                         break;
157                 case 'X':
158                         Xflag = true;
159                         modeflags++;
160                         break;
161                 case 'z':
162                         t.zero_stats = true;
163                         break;
164                 default:
165                         usage();
166                 }
167         }
168         argc -= optind;
169         argv += optind;
170
171         if (argc < 2)
172                 usage();
173
174         if (modeflags > 1) {
175                 printf("Invalid: Cannot use >1 mode flag (-E, -e, -f, -m, -r, -x or -X)\n");
176                 usage();
177         }
178
179         /* Defaults for optional args */
180         t.buffer_size = 256 * 1024;
181         t.chain_depth = 2;
182         t.duration = 0;
183         t.testkind = IOAT_TEST_DMA;
184
185         if (fflag)
186                 t.testkind = IOAT_TEST_FILL;
187         else if (Eflag || eflag) {
188                 t.testkind = IOAT_TEST_DMA_8K;
189                 t.buffer_size = 8 * 1024;
190         } else if (mflag)
191                 t.testkind = IOAT_TEST_MEMCPY;
192         else if (xflag)
193                 t.testkind = IOAT_TEST_DMA_CRC;
194         else if (Xflag)
195                 t.testkind = IOAT_TEST_DMA_CRC_COPY;
196
197         t.channel_index = atoi(argv[0]);
198         if (t.channel_index > 8) {
199                 printf("Channel number must be between 0 and 7.\n");
200                 return (EX_USAGE);
201         }
202
203         if (rflag) {
204                 main_raw(&t, argc, argv);
205                 return (EX_OK);
206         }
207
208         t.transactions = atoi(argv[1]);
209
210         if (argc >= 3) {
211                 t.buffer_size = atoi(argv[2]);
212                 if (t.buffer_size == 0) {
213                         printf("Buffer size must be greater than zero\n");
214                         return (EX_USAGE);
215                 }
216         }
217
218         if (argc >= 4) {
219                 t.chain_depth = atoi(argv[3]);
220                 if (t.chain_depth < 1) {
221                         printf("Chain length must be greater than zero\n");
222                         return (EX_USAGE);
223                 }
224         }
225
226         if (argc >= 5) {
227                 t.duration = atoi(argv[4]);
228                 if (t.duration < 1) {
229                         printf("Duration must be greater than zero\n");
230                         return (EX_USAGE);
231                 }
232         }
233
234         fd = open("/dev/ioat_test", O_RDWR);
235         if (fd < 0) {
236                 printf("Cannot open /dev/ioat_test\n");
237                 return (EX_UNAVAILABLE);
238         }
239
240         (void)ioctl(fd, IOAT_DMATEST, &t);
241         close(fd);
242
243         return (prettyprint(&t));
244 }
245
246 static int
247 prettyprint(struct ioat_test *t)
248 {
249         char bps[10], bytesh[10];
250         uintmax_t bytes;
251
252         if (t->status[IOAT_TEST_NO_DMA_ENGINE] != 0 ||
253             t->status[IOAT_TEST_NO_MEMORY] != 0 ||
254             t->status[IOAT_TEST_MISCOMPARE] != 0) {
255                 printf("Errors:\n");
256                 if (t->status[IOAT_TEST_NO_DMA_ENGINE] != 0)
257                         printf("\tNo DMA engine present: %u\n",
258                             (unsigned)t->status[IOAT_TEST_NO_DMA_ENGINE]);
259                 if (t->status[IOAT_TEST_NO_MEMORY] != 0)
260                         printf("\tOut of memory: %u\n",
261                             (unsigned)t->status[IOAT_TEST_NO_MEMORY]);
262                 if (t->status[IOAT_TEST_MISCOMPARE] != 0)
263                         printf("\tMiscompares: %u\n",
264                             (unsigned)t->status[IOAT_TEST_MISCOMPARE]);
265         }
266
267         printf("Processed %u txns\n", (unsigned)t->status[IOAT_TEST_OK] /
268             t->chain_depth);
269         bytes = (uintmax_t)t->buffer_size * t->status[IOAT_TEST_OK];
270
271         humanize_number(bytesh, sizeof(bytesh), (int64_t)bytes, "B",
272             HN_AUTOSCALE, HN_DECIMAL);
273         if (t->duration) {
274                 humanize_number(bps, sizeof(bps),
275                     (int64_t)1000 * bytes / t->duration, "B/s", HN_AUTOSCALE,
276                     HN_DECIMAL);
277                 printf("%ju (%s) copied in %u ms (%s)\n", bytes, bytesh,
278                     (unsigned)t->duration, bps);
279         } else
280                 printf("%ju (%s) copied\n", bytes, bytesh);
281
282         return (EX_OK);
283 }