aboutsummaryrefslogblamecommitdiff
path: root/tools/tools/ioat/ioatcontrol.c
blob: 32decc77a2f74eb3c050e24fe3e105ea3df1bc67 (plain) (tree)

























                                                                             
                      


                      
                      

                  
                    





                     

                    

                      





                                           
                                                                            
                                                          
                                                                              
                           



                                                                              


                       




































                                                                          



                           
                   

                                        
 


                                              
                                                               
                             


                                                         



                                     

                                     




                                     
                              

                                     
                                    



                                                


                                        


                                           


                                            


                                
         





                        

                                                                                 


                        



                                        



                                            




                                              
 
                                        




                                                                    




                                         
























                                                                           









                                                       







































                                                                             
 
/*-
 * 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);
}