xref: /freebsd/tools/tools/ioat/ioatcontrol.c (revision 1d386b48)
1e974f91cSConrad Meyer /*-
2e974f91cSConrad Meyer  * Copyright (C) 2012 Intel Corporation
3e974f91cSConrad Meyer  * All rights reserved.
4e974f91cSConrad Meyer  *
5e974f91cSConrad Meyer  * Redistribution and use in source and binary forms, with or without
6e974f91cSConrad Meyer  * modification, are permitted provided that the following conditions
7e974f91cSConrad Meyer  * are met:
8e974f91cSConrad Meyer  * 1. Redistributions of source code must retain the above copyright
9e974f91cSConrad Meyer  *    notice, this list of conditions and the following disclaimer.
10e974f91cSConrad Meyer  * 2. Redistributions in binary form must reproduce the above copyright
11e974f91cSConrad Meyer  *    notice, this list of conditions and the following disclaimer in the
12e974f91cSConrad Meyer  *    documentation and/or other materials provided with the distribution.
13e974f91cSConrad Meyer  *
14e974f91cSConrad Meyer  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15e974f91cSConrad Meyer  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16e974f91cSConrad Meyer  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17e974f91cSConrad Meyer  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18e974f91cSConrad Meyer  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19e974f91cSConrad Meyer  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20e974f91cSConrad Meyer  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21e974f91cSConrad Meyer  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22e974f91cSConrad Meyer  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23e974f91cSConrad Meyer  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24e974f91cSConrad Meyer  * SUCH DAMAGE.
25e974f91cSConrad Meyer  */
26e974f91cSConrad Meyer 
27e25d0a6dSConrad Meyer #include <sys/cdefs.h>
28e974f91cSConrad Meyer #include <sys/ioctl.h>
297c69db50SConrad Meyer #include <sys/queue.h>
30e974f91cSConrad Meyer 
31e974f91cSConrad Meyer #include <fcntl.h>
327c69db50SConrad Meyer #include <stdbool.h>
33e974f91cSConrad Meyer #include <stdio.h>
34e974f91cSConrad Meyer #include <stdint.h>
35e974f91cSConrad Meyer #include <stdlib.h>
36613fbf2cSEnji Cooper #include <string.h>
37e974f91cSConrad Meyer #include <sysexits.h>
38e974f91cSConrad Meyer #include <unistd.h>
39e974f91cSConrad Meyer 
407c69db50SConrad Meyer #include <libutil.h>
417c69db50SConrad Meyer 
42e974f91cSConrad Meyer #include "ioat_test.h"
43e974f91cSConrad Meyer 
447c69db50SConrad Meyer static int prettyprint(struct ioat_test *);
457c69db50SConrad Meyer 
467c69db50SConrad Meyer static void
usage(void)477c69db50SConrad Meyer usage(void)
487c69db50SConrad Meyer {
497c69db50SConrad Meyer 
50e92a9a8cSTycho Nightingale 	printf("Usage: %s [-c period] [-EefmVxXz] channel-number num-txns [<bufsize> "
517c69db50SConrad Meyer 	    "[<chain-len> [duration]]]\n", getprogname());
521874b317SEnji Cooper 	printf("       %s -r [-c period] [-vVwz] channel-number address [<bufsize>]\n\n",
53e9497f9bSConrad Meyer 	    getprogname());
541874b317SEnji Cooper 	printf("           -c period - Enable interrupt coalescing (us) (default: 0)\n");
55a8d9ee9cSTycho Nightingale 	printf("           -E        - Test contiguous 8k copy.\n");
56a8d9ee9cSTycho Nightingale 	printf("           -e        - Test non-contiguous 8k copy.\n");
57a8d9ee9cSTycho Nightingale 	printf("           -f        - Test block fill.\n");
581874b317SEnji Cooper 	printf("           -m        - Test memcpy instead of DMA.\n");
591874b317SEnji Cooper 	printf("           -r        - Issue DMA to or from a specific address.\n");
60d37872daSConrad Meyer 	printf("           -V        - Enable verification\n");
611874b317SEnji Cooper 	printf("           -v        - <address> is a kernel virtual address\n");
621874b317SEnji Cooper 	printf("           -w        - Write to the specified address\n");
63a8d9ee9cSTycho Nightingale 	printf("           -x        - Test DMA CRC.\n");
64a8d9ee9cSTycho Nightingale 	printf("           -X        - Test DMA CRC copy.\n");
65d37872daSConrad Meyer 	printf("           -z        - Zero device stats before test\n");
667c69db50SConrad Meyer 	exit(EX_USAGE);
677c69db50SConrad Meyer }
687c69db50SConrad Meyer 
69e9497f9bSConrad Meyer static void
main_raw(struct ioat_test * t,int argc,char ** argv)70e9497f9bSConrad Meyer main_raw(struct ioat_test *t, int argc, char **argv)
71e9497f9bSConrad Meyer {
72e9497f9bSConrad Meyer 	int fd;
73e9497f9bSConrad Meyer 
74e9497f9bSConrad Meyer 	/* Raw DMA defaults */
75e9497f9bSConrad Meyer 	t->testkind = IOAT_TEST_RAW_DMA;
76e9497f9bSConrad Meyer 	t->transactions = 1;
77e9497f9bSConrad Meyer 	t->chain_depth = 1;
78e9497f9bSConrad Meyer 	t->buffer_size = 4 * 1024;
79e9497f9bSConrad Meyer 
80e9497f9bSConrad Meyer 	t->raw_target = strtoull(argv[1], NULL, 0);
81e9497f9bSConrad Meyer 	if (t->raw_target == 0) {
82e9497f9bSConrad Meyer 		printf("Target shoudln't be NULL\n");
83e9497f9bSConrad Meyer 		exit(EX_USAGE);
84e9497f9bSConrad Meyer 	}
85e9497f9bSConrad Meyer 
86e9497f9bSConrad Meyer 	if (argc >= 3) {
87e9497f9bSConrad Meyer 		t->buffer_size = atoi(argv[2]);
88e9497f9bSConrad Meyer 		if (t->buffer_size == 0) {
89e9497f9bSConrad Meyer 			printf("Buffer size must be greater than zero\n");
90e9497f9bSConrad Meyer 			exit(EX_USAGE);
91e9497f9bSConrad Meyer 		}
92e9497f9bSConrad Meyer 	}
93e9497f9bSConrad Meyer 
94e9497f9bSConrad Meyer 	fd = open("/dev/ioat_test", O_RDWR);
95e9497f9bSConrad Meyer 	if (fd < 0) {
96e9497f9bSConrad Meyer 		printf("Cannot open /dev/ioat_test\n");
97e9497f9bSConrad Meyer 		exit(EX_UNAVAILABLE);
98e9497f9bSConrad Meyer 	}
99e9497f9bSConrad Meyer 
100e9497f9bSConrad Meyer 	(void)ioctl(fd, IOAT_DMATEST, t);
101e9497f9bSConrad Meyer 	close(fd);
102e9497f9bSConrad Meyer 
103e9497f9bSConrad Meyer 	exit(prettyprint(t));
104e9497f9bSConrad Meyer }
105e9497f9bSConrad Meyer 
106e974f91cSConrad Meyer int
main(int argc,char ** argv)107e974f91cSConrad Meyer main(int argc, char **argv)
108e974f91cSConrad Meyer {
109e974f91cSConrad Meyer 	struct ioat_test t;
1107c69db50SConrad Meyer 	int fd, ch;
111a8d9ee9cSTycho Nightingale 	bool fflag, rflag, Eflag, eflag, mflag, xflag, Xflag;
1126a301ac8SConrad Meyer 	unsigned modeflags;
113e974f91cSConrad Meyer 
114613fbf2cSEnji Cooper 	memset(&t, 0, sizeof(t));
115613fbf2cSEnji Cooper 
116a8d9ee9cSTycho Nightingale 	fflag = rflag = Eflag = eflag = mflag = xflag = Xflag = false;
1176a301ac8SConrad Meyer 	modeflags = 0;
1186a301ac8SConrad Meyer 
119a8d9ee9cSTycho Nightingale 	while ((ch = getopt(argc, argv, "c:EefmrvVwxXz")) != -1) {
1207c69db50SConrad Meyer 		switch (ch) {
121d37872daSConrad Meyer 		case 'c':
122d37872daSConrad Meyer 			t.coalesce_period = atoi(optarg);
123d37872daSConrad Meyer 			break;
1246a301ac8SConrad Meyer 		case 'E':
1256a301ac8SConrad Meyer 			Eflag = true;
1266a301ac8SConrad Meyer 			modeflags++;
1276a301ac8SConrad Meyer 			break;
128a8d9ee9cSTycho Nightingale 		case 'e':
129a8d9ee9cSTycho Nightingale 			eflag = true;
130a8d9ee9cSTycho Nightingale 			modeflags++;
131a8d9ee9cSTycho Nightingale 			break;
1322a4fd6b1SConrad Meyer 		case 'f':
1332a4fd6b1SConrad Meyer 			fflag = true;
1346a301ac8SConrad Meyer 			modeflags++;
1356a301ac8SConrad Meyer 			break;
1366a301ac8SConrad Meyer 		case 'm':
1376a301ac8SConrad Meyer 			mflag = true;
1386a301ac8SConrad Meyer 			modeflags++;
1392a4fd6b1SConrad Meyer 			break;
140e9497f9bSConrad Meyer 		case 'r':
141e9497f9bSConrad Meyer 			rflag = true;
1426a301ac8SConrad Meyer 			modeflags++;
143e9497f9bSConrad Meyer 			break;
144e9497f9bSConrad Meyer 		case 'v':
145e9497f9bSConrad Meyer 			t.raw_is_virtual = true;
146e9497f9bSConrad Meyer 			break;
1477c69db50SConrad Meyer 		case 'V':
1487c69db50SConrad Meyer 			t.verify = true;
1497c69db50SConrad Meyer 			break;
150e9497f9bSConrad Meyer 		case 'w':
151e9497f9bSConrad Meyer 			t.raw_write = true;
152e9497f9bSConrad Meyer 			break;
153a8d9ee9cSTycho Nightingale 		case 'x':
154a8d9ee9cSTycho Nightingale 			xflag = true;
155e92a9a8cSTycho Nightingale 			modeflags++;
156a8d9ee9cSTycho Nightingale 			break;
157a8d9ee9cSTycho Nightingale 		case 'X':
158a8d9ee9cSTycho Nightingale 			Xflag = true;
159e92a9a8cSTycho Nightingale 			modeflags++;
160a8d9ee9cSTycho Nightingale 			break;
161d37872daSConrad Meyer 		case 'z':
162d37872daSConrad Meyer 			t.zero_stats = true;
163d37872daSConrad Meyer 			break;
1647c69db50SConrad Meyer 		default:
1657c69db50SConrad Meyer 			usage();
166e974f91cSConrad Meyer 		}
1677c69db50SConrad Meyer 	}
1687c69db50SConrad Meyer 	argc -= optind;
1697c69db50SConrad Meyer 	argv += optind;
170e974f91cSConrad Meyer 
1717c69db50SConrad Meyer 	if (argc < 2)
1727c69db50SConrad Meyer 		usage();
1737c69db50SConrad Meyer 
1746a301ac8SConrad Meyer 	if (modeflags > 1) {
175e92a9a8cSTycho Nightingale 		printf("Invalid: Cannot use >1 mode flag (-E, -e, -f, -m, -r, -x or -X)\n");
176e9497f9bSConrad Meyer 		usage();
177e9497f9bSConrad Meyer 	}
178e9497f9bSConrad Meyer 
1797c69db50SConrad Meyer 	/* Defaults for optional args */
1807c69db50SConrad Meyer 	t.buffer_size = 256 * 1024;
1817c69db50SConrad Meyer 	t.chain_depth = 2;
1827c69db50SConrad Meyer 	t.duration = 0;
1832a4fd6b1SConrad Meyer 	t.testkind = IOAT_TEST_DMA;
1842a4fd6b1SConrad Meyer 
1852a4fd6b1SConrad Meyer 	if (fflag)
1862a4fd6b1SConrad Meyer 		t.testkind = IOAT_TEST_FILL;
187a8d9ee9cSTycho Nightingale 	else if (Eflag || eflag) {
1886a301ac8SConrad Meyer 		t.testkind = IOAT_TEST_DMA_8K;
1896a301ac8SConrad Meyer 		t.buffer_size = 8 * 1024;
1906a301ac8SConrad Meyer 	} else if (mflag)
1916a301ac8SConrad Meyer 		t.testkind = IOAT_TEST_MEMCPY;
192a8d9ee9cSTycho Nightingale 	else if (xflag)
193a8d9ee9cSTycho Nightingale 		t.testkind = IOAT_TEST_DMA_CRC;
194e92a9a8cSTycho Nightingale 	else if (Xflag)
195a8d9ee9cSTycho Nightingale 		t.testkind = IOAT_TEST_DMA_CRC_COPY;
1967c69db50SConrad Meyer 
1977c69db50SConrad Meyer 	t.channel_index = atoi(argv[0]);
198e974f91cSConrad Meyer 	if (t.channel_index > 8) {
199e974f91cSConrad Meyer 		printf("Channel number must be between 0 and 7.\n");
200e974f91cSConrad Meyer 		return (EX_USAGE);
201e974f91cSConrad Meyer 	}
202e974f91cSConrad Meyer 
203e9497f9bSConrad Meyer 	if (rflag) {
204e9497f9bSConrad Meyer 		main_raw(&t, argc, argv);
205e9497f9bSConrad Meyer 		return (EX_OK);
206e9497f9bSConrad Meyer 	}
207e9497f9bSConrad Meyer 
2087c69db50SConrad Meyer 	t.transactions = atoi(argv[1]);
2097c69db50SConrad Meyer 
2107c69db50SConrad Meyer 	if (argc >= 3) {
2117c69db50SConrad Meyer 		t.buffer_size = atoi(argv[2]);
2127c69db50SConrad Meyer 		if (t.buffer_size == 0) {
2137c69db50SConrad Meyer 			printf("Buffer size must be greater than zero\n");
2147c69db50SConrad Meyer 			return (EX_USAGE);
2157c69db50SConrad Meyer 		}
2167c69db50SConrad Meyer 	}
2177c69db50SConrad Meyer 
2187c69db50SConrad Meyer 	if (argc >= 4) {
2197c69db50SConrad Meyer 		t.chain_depth = atoi(argv[3]);
2207c69db50SConrad Meyer 		if (t.chain_depth < 1) {
2217c69db50SConrad Meyer 			printf("Chain length must be greater than zero\n");
2227c69db50SConrad Meyer 			return (EX_USAGE);
2237c69db50SConrad Meyer 		}
2247c69db50SConrad Meyer 	}
2257c69db50SConrad Meyer 
2267c69db50SConrad Meyer 	if (argc >= 5) {
2277c69db50SConrad Meyer 		t.duration = atoi(argv[4]);
2287c69db50SConrad Meyer 		if (t.duration < 1) {
2297c69db50SConrad Meyer 			printf("Duration must be greater than zero\n");
2307c69db50SConrad Meyer 			return (EX_USAGE);
2317c69db50SConrad Meyer 		}
2327c69db50SConrad Meyer 	}
233e974f91cSConrad Meyer 
234e974f91cSConrad Meyer 	fd = open("/dev/ioat_test", O_RDWR);
235e974f91cSConrad Meyer 	if (fd < 0) {
236e974f91cSConrad Meyer 		printf("Cannot open /dev/ioat_test\n");
237e974f91cSConrad Meyer 		return (EX_UNAVAILABLE);
238e974f91cSConrad Meyer 	}
239e974f91cSConrad Meyer 
240e974f91cSConrad Meyer 	(void)ioctl(fd, IOAT_DMATEST, &t);
241e974f91cSConrad Meyer 	close(fd);
242e974f91cSConrad Meyer 
2437c69db50SConrad Meyer 	return (prettyprint(&t));
2447c69db50SConrad Meyer }
2457c69db50SConrad Meyer 
2467c69db50SConrad Meyer static int
prettyprint(struct ioat_test * t)2477c69db50SConrad Meyer prettyprint(struct ioat_test *t)
2487c69db50SConrad Meyer {
2497c69db50SConrad Meyer 	char bps[10], bytesh[10];
2507c69db50SConrad Meyer 	uintmax_t bytes;
2517c69db50SConrad Meyer 
2527c69db50SConrad Meyer 	if (t->status[IOAT_TEST_NO_DMA_ENGINE] != 0 ||
2537c69db50SConrad Meyer 	    t->status[IOAT_TEST_NO_MEMORY] != 0 ||
2547c69db50SConrad Meyer 	    t->status[IOAT_TEST_MISCOMPARE] != 0) {
2557c69db50SConrad Meyer 		printf("Errors:\n");
2567c69db50SConrad Meyer 		if (t->status[IOAT_TEST_NO_DMA_ENGINE] != 0)
2577c69db50SConrad Meyer 			printf("\tNo DMA engine present: %u\n",
2587c69db50SConrad Meyer 			    (unsigned)t->status[IOAT_TEST_NO_DMA_ENGINE]);
2597c69db50SConrad Meyer 		if (t->status[IOAT_TEST_NO_MEMORY] != 0)
2607c69db50SConrad Meyer 			printf("\tOut of memory: %u\n",
2617c69db50SConrad Meyer 			    (unsigned)t->status[IOAT_TEST_NO_MEMORY]);
2627c69db50SConrad Meyer 		if (t->status[IOAT_TEST_MISCOMPARE] != 0)
2637c69db50SConrad Meyer 			printf("\tMiscompares: %u\n",
2647c69db50SConrad Meyer 			    (unsigned)t->status[IOAT_TEST_MISCOMPARE]);
2657c69db50SConrad Meyer 	}
2667c69db50SConrad Meyer 
2677c69db50SConrad Meyer 	printf("Processed %u txns\n", (unsigned)t->status[IOAT_TEST_OK] /
2687c69db50SConrad Meyer 	    t->chain_depth);
2697c69db50SConrad Meyer 	bytes = (uintmax_t)t->buffer_size * t->status[IOAT_TEST_OK];
2707c69db50SConrad Meyer 
2717c69db50SConrad Meyer 	humanize_number(bytesh, sizeof(bytesh), (int64_t)bytes, "B",
2727c69db50SConrad Meyer 	    HN_AUTOSCALE, HN_DECIMAL);
2737c69db50SConrad Meyer 	if (t->duration) {
2747c69db50SConrad Meyer 		humanize_number(bps, sizeof(bps),
2757c69db50SConrad Meyer 		    (int64_t)1000 * bytes / t->duration, "B/s", HN_AUTOSCALE,
2767c69db50SConrad Meyer 		    HN_DECIMAL);
2777c69db50SConrad Meyer 		printf("%ju (%s) copied in %u ms (%s)\n", bytes, bytesh,
2787c69db50SConrad Meyer 		    (unsigned)t->duration, bps);
2797c69db50SConrad Meyer 	} else
2807c69db50SConrad Meyer 		printf("%ju (%s) copied\n", bytes, bytesh);
2817c69db50SConrad Meyer 
2827c69db50SConrad Meyer 	return (EX_OK);
283e974f91cSConrad Meyer }
284