Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.10.11.
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Copyright (C) 2020 HiSilicon Limited.
  4 */
  5
  6#include <fcntl.h>
  7#include <stdio.h>
  8#include <stdlib.h>
  9#include <string.h>
 10#include <unistd.h>
 11#include <sys/ioctl.h>
 12#include <sys/mman.h>
 13#include <linux/types.h>
 14#include <linux/map_benchmark.h>
 15
 16#define NSEC_PER_MSEC	1000000L
 17
 18static char *directions[] = {
 19	"BIDIRECTIONAL",
 20	"TO_DEVICE",
 21	"FROM_DEVICE",
 22};
 23
 24int main(int argc, char **argv)
 25{
 26	struct map_benchmark map;
 27	int fd, opt;
 28	/* default single thread, run 20 seconds on NUMA_NO_NODE */
 29	int threads = 1, seconds = 20, node = -1;
 30	/* default dma mask 32bit, bidirectional DMA */
 31	int bits = 32, xdelay = 0, dir = DMA_MAP_BIDIRECTIONAL;
 32	/* default granule 1 PAGESIZE */
 33	int granule = 1;
 34
 35	int cmd = DMA_MAP_BENCHMARK;
 36	char *p;
 37
 38	while ((opt = getopt(argc, argv, "t:s:n:b:d:x:g:")) != -1) {
 39		switch (opt) {
 40		case 't':
 41			threads = atoi(optarg);
 42			break;
 43		case 's':
 44			seconds = atoi(optarg);
 45			break;
 46		case 'n':
 47			node = atoi(optarg);
 48			break;
 49		case 'b':
 50			bits = atoi(optarg);
 51			break;
 52		case 'd':
 53			dir = atoi(optarg);
 54			break;
 55		case 'x':
 56			xdelay = atoi(optarg);
 57			break;
 58		case 'g':
 59			granule = atoi(optarg);
 60			break;
 61		default:
 62			return -1;
 63		}
 64	}
 65
 66	if (threads <= 0 || threads > DMA_MAP_MAX_THREADS) {
 67		fprintf(stderr, "invalid number of threads, must be in 1-%d\n",
 68			DMA_MAP_MAX_THREADS);
 69		exit(1);
 70	}
 71
 72	if (seconds <= 0 || seconds > DMA_MAP_MAX_SECONDS) {
 73		fprintf(stderr, "invalid number of seconds, must be in 1-%d\n",
 74			DMA_MAP_MAX_SECONDS);
 75		exit(1);
 76	}
 77
 78	if (xdelay < 0 || xdelay > DMA_MAP_MAX_TRANS_DELAY) {
 79		fprintf(stderr, "invalid transmit delay, must be in 0-%ld\n",
 80			DMA_MAP_MAX_TRANS_DELAY);
 81		exit(1);
 82	}
 83
 84	/* suppose the mininum DMA zone is 1MB in the world */
 85	if (bits < 20 || bits > 64) {
 86		fprintf(stderr, "invalid dma mask bit, must be in 20-64\n");
 87		exit(1);
 88	}
 89
 90	if (dir != DMA_MAP_BIDIRECTIONAL && dir != DMA_MAP_TO_DEVICE &&
 91			dir != DMA_MAP_FROM_DEVICE) {
 92		fprintf(stderr, "invalid dma direction\n");
 93		exit(1);
 94	}
 95
 96	if (granule < 1 || granule > 1024) {
 97		fprintf(stderr, "invalid granule size\n");
 98		exit(1);
 99	}
100
101	fd = open("/sys/kernel/debug/dma_map_benchmark", O_RDWR);
102	if (fd == -1) {
103		perror("open");
104		exit(1);
105	}
106
107	memset(&map, 0, sizeof(map));
108	map.seconds = seconds;
109	map.threads = threads;
110	map.node = node;
111	map.dma_bits = bits;
112	map.dma_dir = dir;
113	map.dma_trans_ns = xdelay;
114	map.granule = granule;
115
116	if (ioctl(fd, cmd, &map)) {
117		perror("ioctl");
118		exit(1);
119	}
120
121	printf("dma mapping benchmark: threads:%d seconds:%d node:%d dir:%s granule: %d\n",
122			threads, seconds, node, dir[directions], granule);
123	printf("average map latency(us):%.1f standard deviation:%.1f\n",
124			map.avg_map_100ns/10.0, map.map_stddev/10.0);
125	printf("average unmap latency(us):%.1f standard deviation:%.1f\n",
126			map.avg_unmap_100ns/10.0, map.unmap_stddev/10.0);
127
128	return 0;
129}