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