diff options
author | mav <mav@FreeBSD.org> | 2016-05-25 07:09:54 +0000 |
---|---|---|
committer | mav <mav@FreeBSD.org> | 2016-05-25 07:09:54 +0000 |
commit | d748f0adede2aeb8cb93f4f727575df0987fec63 (patch) | |
tree | c3ddc45d3097fc4ebffb152e65e728afd2d6e73f /tools | |
parent | 9067c52647a790e0945bbadd59190a5e1be02e48 (diff) | |
download | FreeBSD-src-d748f0adede2aeb8cb93f4f727575df0987fec63.zip FreeBSD-src-d748f0adede2aeb8cb93f4f727575df0987fec63.tar.gz |
MFC ioat(4) driver in its present state.
Diffstat (limited to 'tools')
-rw-r--r-- | tools/tools/ioat/Makefile | 9 | ||||
-rw-r--r-- | tools/tools/ioat/ioatcontrol.8 | 182 | ||||
-rw-r--r-- | tools/tools/ioat/ioatcontrol.c | 258 |
3 files changed, 449 insertions, 0 deletions
diff --git a/tools/tools/ioat/Makefile b/tools/tools/ioat/Makefile new file mode 100644 index 0000000..7ea3e6e --- /dev/null +++ b/tools/tools/ioat/Makefile @@ -0,0 +1,9 @@ +# $FreeBSD$ + +PROG= ioatcontrol +MAN= ioatcontrol.8 +CFLAGS+= -I${.CURDIR:H:H:H}/sys/dev/ioat +WARNS?= 6 +LIBADD= util + +.include <bsd.prog.mk> diff --git a/tools/tools/ioat/ioatcontrol.8 b/tools/tools/ioat/ioatcontrol.8 new file mode 100644 index 0000000..9e156fd --- /dev/null +++ b/tools/tools/ioat/ioatcontrol.8 @@ -0,0 +1,182 @@ +.\" Copyright (c) 2015 EMC / Isilon Storage Division +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd December 14, 2015 +.Dt IOATCONTROL 8 +.Os +.Sh NAME +.Nm ioatcontrol +.Nd Userspace tool to test +.Xr ioat 4 +.Sh SYNOPSIS +.Nm +.Op Fl c Ar period +.Op Fl E +.Op Fl f +.Op Fl m +.Op Fl V +.Op Fl z +.Ar channel_number +.Ar num_txns +.Ar [ bufsize +.Ar [ chain-len +.Ar [ duration ] ] ] +.Nm +.Fl r +.Op Fl c Ar period +.Op Fl v +.Op Fl V +.Op Fl w +.Op Fl z +.Ar channel_number +.Ar address +.Ar [ bufsize ] +.Sh DESCRIPTION +.Nm +allows one to issue some number of test operations to the +.Xr ioat 4 +driver on a specific hardware channel. +The arguments are as follows: +.Bl -tag -width Ds +.It Fl c Ar period +Configure the channel's interrupt coalescing period, in microseconds. +.It Fl E +Test non-contiguous 8k copy. +.It Fl f +Test block fill (by default, +.Nm +tests copy) +.It Fl m +Test memcpy instead of DMA. +.It Fl V +Verify copies/fills for accuracy +.It Fl z +Zero device statistics before running test. +.El +.Pp +Alternatively one can use +.Nm +.Fl r +to issue DMA to or from a specific +.Ar address . +The arguments in "raw" mode are: +.Bl -tag -width Ds +.It Fl c Ar period +As above. +.It Fl v +.Ar address +is a kernel virtual address (by default, +.Ar address +is assumed to be a physical address) +.It Fl V +Dump the resulting hex to syslog +.It Fl w +Write to the specified +.Ar address +(by default, +.Nm +.Fl r +reads) +.It Fl z +As above. +.El +.Pp +.Nm +operates in one of two modes; if the +.Ar duration +argument is passed, +.Nm +tries to estimate the copy rate in bytes per second by running +.Ar num_txns +repeatedly in loop. +If +.Ar duration +is not passed, +.Nm +only runs through +.Ar num_txns +once and prints the total bytes copied, as well as error information. +.Pp +The +.Ar bufsize +argument determines the size of buffers to use for each +.Fn ioat_copy +invocation. +The default is 256 KB. +In raw mode, the default is 4 KB. +.Pp +The +.Ar chain-len +argument determines the number of copies to chain together in a single DMA +transaction. +The default is 1, and the maximum is currently 4. +.Pp +The +.Ar duration +argument specifies an approximate time limit for the test, in milliseconds. +.Pp +The test will allocate two chunks of memory for each component of each +transaction's chain. +It will initialize them with specific data patterns. +During the test, it submits DMA requests to copy between pairs of buffers. +If the +.Fl V +flag was specified, it will compare the contents in the callback for a copy +error. +.Sh FILES +.Pa /dev/ioat_test +.Pp +The interface between +.Nm +and +.Xr ioat 4 . +.Xr ioat 4 +exposes it with +.Cd hw.ioat.enable_ioat_test=1 . +.Sh DIAGNOSTICS +The wait channel +.Va test_submit +indicates that the test code has enqueued all requested transactions and is +waiting on the IOAT hardware to complete one before issuing another operation. +.Sh SEE ALSO +.Xr ioat 4 +.Sh HISTORY +The +.Xr ioat 4 +driver first appeared in +.Fx 11.0 . +.Sh AUTHORS +The +.Xr ioat 4 +driver and +.Nm +tool were developed by +.An \&Jim Harris Aq Mt jimharris@FreeBSD.org , +.An \&Carl Delsey Aq Mt carl.r.delsey@intel.com , +and +.An \&Conrad Meyer Aq Mt cem@FreeBSD.org . +This manual page was written by +.An \&Conrad Meyer Aq Mt cem@FreeBSD.org . diff --git a/tools/tools/ioat/ioatcontrol.c b/tools/tools/ioat/ioatcontrol.c new file mode 100644 index 0000000..32decc7 --- /dev/null +++ b/tools/tools/ioat/ioatcontrol.c @@ -0,0 +1,258 @@ +/*- + * Copyright (C) 2012 Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/ioctl.h> +#include <sys/queue.h> + +#include <fcntl.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <sysexits.h> +#include <unistd.h> + +#include <libutil.h> + +#include "ioat_test.h" + +static int prettyprint(struct ioat_test *); + +static void +usage(void) +{ + + printf("Usage: %s [-E|-f|-m] OPTIONS <channel #> <txns> [<bufsize> " + "[<chain-len> [duration]]]\n", getprogname()); + printf(" %s -r [-v] OPTIONS <channel #> <addr> [<bufsize>]\n\n", + getprogname()); + printf(" OPTIONS:\n"); + printf(" -c <period> - Enable interrupt coalescing (us)\n"); + printf(" -V - Enable verification\n"); + printf(" -z - Zero device stats before test\n"); + exit(EX_USAGE); +} + +static void +main_raw(struct ioat_test *t, int argc, char **argv) +{ + int fd; + + /* Raw DMA defaults */ + t->testkind = IOAT_TEST_RAW_DMA; + t->transactions = 1; + t->chain_depth = 1; + t->buffer_size = 4 * 1024; + + t->raw_target = strtoull(argv[1], NULL, 0); + if (t->raw_target == 0) { + printf("Target shoudln't be NULL\n"); + exit(EX_USAGE); + } + + if (argc >= 3) { + t->buffer_size = atoi(argv[2]); + if (t->buffer_size == 0) { + printf("Buffer size must be greater than zero\n"); + exit(EX_USAGE); + } + } + + fd = open("/dev/ioat_test", O_RDWR); + if (fd < 0) { + printf("Cannot open /dev/ioat_test\n"); + exit(EX_UNAVAILABLE); + } + + (void)ioctl(fd, IOAT_DMATEST, t); + close(fd); + + exit(prettyprint(t)); +} + +int +main(int argc, char **argv) +{ + struct ioat_test t; + int fd, ch; + bool fflag, rflag, Eflag, mflag; + unsigned modeflags; + + fflag = rflag = Eflag = mflag = false; + modeflags = 0; + + while ((ch = getopt(argc, argv, "c:EfmrvVwz")) != -1) { + switch (ch) { + case 'c': + t.coalesce_period = atoi(optarg); + break; + case 'E': + Eflag = true; + modeflags++; + break; + case 'f': + fflag = true; + modeflags++; + break; + case 'm': + mflag = true; + modeflags++; + break; + case 'r': + rflag = true; + modeflags++; + break; + case 'v': + t.raw_is_virtual = true; + break; + case 'V': + t.verify = true; + break; + case 'w': + t.raw_write = true; + break; + case 'z': + t.zero_stats = true; + break; + default: + usage(); + } + } + argc -= optind; + argv += optind; + + if (argc < 2) + usage(); + + if (modeflags > 1) { + printf("Invalid: Cannot use >1 mode flag (-E, -f, -m, or -r)\n"); + usage(); + } + + /* Defaults for optional args */ + t.buffer_size = 256 * 1024; + t.chain_depth = 2; + t.duration = 0; + t.testkind = IOAT_TEST_DMA; + + if (fflag) + t.testkind = IOAT_TEST_FILL; + else if (Eflag) { + t.testkind = IOAT_TEST_DMA_8K; + t.buffer_size = 8 * 1024; + } else if (mflag) + t.testkind = IOAT_TEST_MEMCPY; + + t.channel_index = atoi(argv[0]); + if (t.channel_index > 8) { + printf("Channel number must be between 0 and 7.\n"); + return (EX_USAGE); + } + + if (rflag) { + main_raw(&t, argc, argv); + return (EX_OK); + } + + t.transactions = atoi(argv[1]); + + if (argc >= 3) { + t.buffer_size = atoi(argv[2]); + if (t.buffer_size == 0) { + printf("Buffer size must be greater than zero\n"); + return (EX_USAGE); + } + } + + if (argc >= 4) { + t.chain_depth = atoi(argv[3]); + if (t.chain_depth < 1) { + printf("Chain length must be greater than zero\n"); + return (EX_USAGE); + } + } + + if (argc >= 5) { + t.duration = atoi(argv[4]); + if (t.duration < 1) { + printf("Duration must be greater than zero\n"); + return (EX_USAGE); + } + } + + fd = open("/dev/ioat_test", O_RDWR); + if (fd < 0) { + printf("Cannot open /dev/ioat_test\n"); + return (EX_UNAVAILABLE); + } + + (void)ioctl(fd, IOAT_DMATEST, &t); + close(fd); + + return (prettyprint(&t)); +} + +static int +prettyprint(struct ioat_test *t) +{ + char bps[10], bytesh[10]; + uintmax_t bytes; + + if (t->status[IOAT_TEST_NO_DMA_ENGINE] != 0 || + t->status[IOAT_TEST_NO_MEMORY] != 0 || + t->status[IOAT_TEST_MISCOMPARE] != 0) { + printf("Errors:\n"); + if (t->status[IOAT_TEST_NO_DMA_ENGINE] != 0) + printf("\tNo DMA engine present: %u\n", + (unsigned)t->status[IOAT_TEST_NO_DMA_ENGINE]); + if (t->status[IOAT_TEST_NO_MEMORY] != 0) + printf("\tOut of memory: %u\n", + (unsigned)t->status[IOAT_TEST_NO_MEMORY]); + if (t->status[IOAT_TEST_MISCOMPARE] != 0) + printf("\tMiscompares: %u\n", + (unsigned)t->status[IOAT_TEST_MISCOMPARE]); + } + + printf("Processed %u txns\n", (unsigned)t->status[IOAT_TEST_OK] / + t->chain_depth); + bytes = (uintmax_t)t->buffer_size * t->status[IOAT_TEST_OK]; + + humanize_number(bytesh, sizeof(bytesh), (int64_t)bytes, "B", + HN_AUTOSCALE, HN_DECIMAL); + if (t->duration) { + humanize_number(bps, sizeof(bps), + (int64_t)1000 * bytes / t->duration, "B/s", HN_AUTOSCALE, + HN_DECIMAL); + printf("%ju (%s) copied in %u ms (%s)\n", bytes, bytesh, + (unsigned)t->duration, bps); + } else + printf("%ju (%s) copied\n", bytes, bytesh); + + return (EX_OK); +} |