]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - tools/tools/ioat/ioatcontrol.c
MFC ioat(4) driver in its present state.
[FreeBSD/stable/10.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 __FBSDID("$FreeBSD$");
29
30 #include <sys/ioctl.h>
31 #include <sys/queue.h>
32
33 #include <fcntl.h>
34 #include <stdbool.h>
35 #include <stdio.h>
36 #include <stdint.h>
37 #include <stdlib.h>
38 #include <sysexits.h>
39 #include <unistd.h>
40
41 #include <libutil.h>
42
43 #include "ioat_test.h"
44
45 static int prettyprint(struct ioat_test *);
46
47 static void
48 usage(void)
49 {
50
51         printf("Usage: %s [-E|-f|-m] OPTIONS <channel #> <txns> [<bufsize> "
52             "[<chain-len> [duration]]]\n", getprogname());
53         printf("       %s -r [-v] OPTIONS <channel #> <addr> [<bufsize>]\n\n",
54             getprogname());
55         printf("       OPTIONS:\n");
56         printf("           -c <period> - Enable interrupt coalescing (us)\n");
57         printf("           -V          - Enable verification\n");
58         printf("           -z          - Zero device stats before test\n");
59         exit(EX_USAGE);
60 }
61
62 static void
63 main_raw(struct ioat_test *t, int argc, char **argv)
64 {
65         int fd;
66
67         /* Raw DMA defaults */
68         t->testkind = IOAT_TEST_RAW_DMA;
69         t->transactions = 1;
70         t->chain_depth = 1;
71         t->buffer_size = 4 * 1024;
72
73         t->raw_target = strtoull(argv[1], NULL, 0);
74         if (t->raw_target == 0) {
75                 printf("Target shoudln't be NULL\n");
76                 exit(EX_USAGE);
77         }
78
79         if (argc >= 3) {
80                 t->buffer_size = atoi(argv[2]);
81                 if (t->buffer_size == 0) {
82                         printf("Buffer size must be greater than zero\n");
83                         exit(EX_USAGE);
84                 }
85         }
86
87         fd = open("/dev/ioat_test", O_RDWR);
88         if (fd < 0) {
89                 printf("Cannot open /dev/ioat_test\n");
90                 exit(EX_UNAVAILABLE);
91         }
92
93         (void)ioctl(fd, IOAT_DMATEST, t);
94         close(fd);
95
96         exit(prettyprint(t));
97 }
98
99 int
100 main(int argc, char **argv)
101 {
102         struct ioat_test t;
103         int fd, ch;
104         bool fflag, rflag, Eflag, mflag;
105         unsigned modeflags;
106
107         fflag = rflag = Eflag = mflag = false;
108         modeflags = 0;
109
110         while ((ch = getopt(argc, argv, "c:EfmrvVwz")) != -1) {
111                 switch (ch) {
112                 case 'c':
113                         t.coalesce_period = atoi(optarg);
114                         break;
115                 case 'E':
116                         Eflag = true;
117                         modeflags++;
118                         break;
119                 case 'f':
120                         fflag = true;
121                         modeflags++;
122                         break;
123                 case 'm':
124                         mflag = true;
125                         modeflags++;
126                         break;
127                 case 'r':
128                         rflag = true;
129                         modeflags++;
130                         break;
131                 case 'v':
132                         t.raw_is_virtual = true;
133                         break;
134                 case 'V':
135                         t.verify = true;
136                         break;
137                 case 'w':
138                         t.raw_write = true;
139                         break;
140                 case 'z':
141                         t.zero_stats = true;
142                         break;
143                 default:
144                         usage();
145                 }
146         }
147         argc -= optind;
148         argv += optind;
149
150         if (argc < 2)
151                 usage();
152
153         if (modeflags > 1) {
154                 printf("Invalid: Cannot use >1 mode flag (-E, -f, -m, or -r)\n");
155                 usage();
156         }
157
158         /* Defaults for optional args */
159         t.buffer_size = 256 * 1024;
160         t.chain_depth = 2;
161         t.duration = 0;
162         t.testkind = IOAT_TEST_DMA;
163
164         if (fflag)
165                 t.testkind = IOAT_TEST_FILL;
166         else if (Eflag) {
167                 t.testkind = IOAT_TEST_DMA_8K;
168                 t.buffer_size = 8 * 1024;
169         } else if (mflag)
170                 t.testkind = IOAT_TEST_MEMCPY;
171
172         t.channel_index = atoi(argv[0]);
173         if (t.channel_index > 8) {
174                 printf("Channel number must be between 0 and 7.\n");
175                 return (EX_USAGE);
176         }
177
178         if (rflag) {
179                 main_raw(&t, argc, argv);
180                 return (EX_OK);
181         }
182
183         t.transactions = atoi(argv[1]);
184
185         if (argc >= 3) {
186                 t.buffer_size = atoi(argv[2]);
187                 if (t.buffer_size == 0) {
188                         printf("Buffer size must be greater than zero\n");
189                         return (EX_USAGE);
190                 }
191         }
192
193         if (argc >= 4) {
194                 t.chain_depth = atoi(argv[3]);
195                 if (t.chain_depth < 1) {
196                         printf("Chain length must be greater than zero\n");
197                         return (EX_USAGE);
198                 }
199         }
200
201         if (argc >= 5) {
202                 t.duration = atoi(argv[4]);
203                 if (t.duration < 1) {
204                         printf("Duration must be greater than zero\n");
205                         return (EX_USAGE);
206                 }
207         }
208
209         fd = open("/dev/ioat_test", O_RDWR);
210         if (fd < 0) {
211                 printf("Cannot open /dev/ioat_test\n");
212                 return (EX_UNAVAILABLE);
213         }
214
215         (void)ioctl(fd, IOAT_DMATEST, &t);
216         close(fd);
217
218         return (prettyprint(&t));
219 }
220
221 static int
222 prettyprint(struct ioat_test *t)
223 {
224         char bps[10], bytesh[10];
225         uintmax_t bytes;
226
227         if (t->status[IOAT_TEST_NO_DMA_ENGINE] != 0 ||
228             t->status[IOAT_TEST_NO_MEMORY] != 0 ||
229             t->status[IOAT_TEST_MISCOMPARE] != 0) {
230                 printf("Errors:\n");
231                 if (t->status[IOAT_TEST_NO_DMA_ENGINE] != 0)
232                         printf("\tNo DMA engine present: %u\n",
233                             (unsigned)t->status[IOAT_TEST_NO_DMA_ENGINE]);
234                 if (t->status[IOAT_TEST_NO_MEMORY] != 0)
235                         printf("\tOut of memory: %u\n",
236                             (unsigned)t->status[IOAT_TEST_NO_MEMORY]);
237                 if (t->status[IOAT_TEST_MISCOMPARE] != 0)
238                         printf("\tMiscompares: %u\n",
239                             (unsigned)t->status[IOAT_TEST_MISCOMPARE]);
240         }
241
242         printf("Processed %u txns\n", (unsigned)t->status[IOAT_TEST_OK] /
243             t->chain_depth);
244         bytes = (uintmax_t)t->buffer_size * t->status[IOAT_TEST_OK];
245
246         humanize_number(bytesh, sizeof(bytesh), (int64_t)bytes, "B",
247             HN_AUTOSCALE, HN_DECIMAL);
248         if (t->duration) {
249                 humanize_number(bps, sizeof(bps),
250                     (int64_t)1000 * bytes / t->duration, "B/s", HN_AUTOSCALE,
251                     HN_DECIMAL);
252                 printf("%ju (%s) copied in %u ms (%s)\n", bytes, bytesh,
253                     (unsigned)t->duration, bps);
254         } else
255                 printf("%ju (%s) copied\n", bytes, bytesh);
256
257         return (EX_OK);
258 }