From f74ee32963f1b74865fe679e2475450434fea51c Mon Sep 17 00:00:00 2001 From: Qinxin Xia Date: Tue, 28 Oct 2025 20:09:00 +0800 Subject: tools/dma: move dma_map_benchmark from selftests to tools/dma dma_map_benchmark is a standalone developer tool rather than an automated selftest. It has no pass/fail criteria, expects manual invocation, and is built as a normal userspace binary. Move it to tools/dma/ and add a minimal Makefile. Suggested-by: Marek Szyprowski Suggested-by: Barry Song Signed-off-by: Qinxin Xia Acked-by: Barry Song Signed-off-by: Marek Szyprowski Link: https://lore.kernel.org/r/20251028120900.2265511-3-xiaqinxin@huawei.com --- tools/Makefile | 13 +-- tools/dma/.gitignore | 3 + tools/dma/Makefile | 55 ++++++++++ tools/dma/config | 1 + tools/dma/dma_map_benchmark.c | 127 +++++++++++++++++++++++ tools/testing/selftests/dma/Makefile | 7 -- tools/testing/selftests/dma/config | 1 - tools/testing/selftests/dma/dma_map_benchmark.c | 128 ------------------------ 8 files changed, 193 insertions(+), 142 deletions(-) create mode 100644 tools/dma/.gitignore create mode 100644 tools/dma/Makefile create mode 100644 tools/dma/config create mode 100644 tools/dma/dma_map_benchmark.c delete mode 100644 tools/testing/selftests/dma/Makefile delete mode 100644 tools/testing/selftests/dma/config delete mode 100644 tools/testing/selftests/dma/dma_map_benchmark.c (limited to 'tools') diff --git a/tools/Makefile b/tools/Makefile index c31cbbd12c45..cb40961a740f 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -14,6 +14,7 @@ help: @echo ' counter - counter tools' @echo ' cpupower - a tool for all things x86 CPU power' @echo ' debugging - tools for debugging' + @echo ' dma - tools for DMA mapping' @echo ' firewire - the userspace part of nosy, an IEEE-1394 traffic sniffer' @echo ' firmware - Firmware tools' @echo ' freefall - laptop accelerometer program for disk protection' @@ -69,7 +70,7 @@ acpi: FORCE cpupower: FORCE $(call descend,power/$@) -counter firewire hv guest bootconfig spi usb virtio mm bpf iio gpio objtool leds wmi firmware debugging tracing: FORCE +counter dma firewire hv guest bootconfig spi usb virtio mm bpf iio gpio objtool leds wmi firmware debugging tracing: FORCE $(call descend,$@) bpf/%: FORCE @@ -122,7 +123,7 @@ kvm_stat: FORCE ynl: FORCE $(call descend,net/ynl) -all: acpi counter cpupower gpio hv firewire \ +all: acpi counter cpupower dma gpio hv firewire \ perf selftests bootconfig spi turbostat usb \ virtio mm bpf x86_energy_perf_policy \ tmon freefall iio objtool kvm_stat wmi \ @@ -134,7 +135,7 @@ acpi_install: cpupower_install: $(call descend,power/$(@:_install=),install) -counter_install firewire_install gpio_install hv_install iio_install perf_install bootconfig_install spi_install usb_install virtio_install mm_install bpf_install objtool_install wmi_install debugging_install tracing_install: +counter_install dma_install firewire_install gpio_install hv_install iio_install perf_install bootconfig_install spi_install usb_install virtio_install mm_install bpf_install objtool_install wmi_install debugging_install tracing_install: $(call descend,$(@:_install=),install) selftests_install: @@ -164,7 +165,7 @@ kvm_stat_install: ynl_install: $(call descend,net/$(@:_install=),install) -install: acpi_install counter_install cpupower_install gpio_install \ +install: acpi_install counter_install cpupower_install dma_install gpio_install \ hv_install firewire_install iio_install \ perf_install selftests_install turbostat_install usb_install \ virtio_install mm_install bpf_install x86_energy_perf_policy_install \ @@ -178,7 +179,7 @@ acpi_clean: cpupower_clean: $(call descend,power/cpupower,clean) -counter_clean hv_clean firewire_clean bootconfig_clean spi_clean usb_clean virtio_clean mm_clean wmi_clean bpf_clean iio_clean gpio_clean objtool_clean leds_clean firmware_clean debugging_clean tracing_clean: +counter_clean dma_clean hv_clean firewire_clean bootconfig_clean spi_clean usb_clean virtio_clean mm_clean wmi_clean bpf_clean iio_clean gpio_clean objtool_clean leds_clean firmware_clean debugging_clean tracing_clean: $(call descend,$(@:_clean=),clean) libapi_clean: @@ -224,7 +225,7 @@ build_clean: ynl_clean: $(call descend,net/$(@:_clean=),clean) -clean: acpi_clean counter_clean cpupower_clean hv_clean firewire_clean \ +clean: acpi_clean counter_clean cpupower_clean dma_clean hv_clean firewire_clean \ perf_clean selftests_clean turbostat_clean bootconfig_clean spi_clean usb_clean virtio_clean \ mm_clean bpf_clean iio_clean x86_energy_perf_policy_clean tmon_clean \ freefall_clean build_clean libbpf_clean libsubcmd_clean \ diff --git a/tools/dma/.gitignore b/tools/dma/.gitignore new file mode 100644 index 000000000000..94b68cf4147b --- /dev/null +++ b/tools/dma/.gitignore @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0-only +dma_map_benchmark +include/linux/map_benchmark.h diff --git a/tools/dma/Makefile b/tools/dma/Makefile new file mode 100644 index 000000000000..e4abf37bf020 --- /dev/null +++ b/tools/dma/Makefile @@ -0,0 +1,55 @@ +# SPDX-License-Identifier: GPL-2.0 +include ../scripts/Makefile.include + +bindir ?= /usr/bin + +# This will work when dma is built in tools env. where srctree +# isn't set and when invoked from selftests build, where srctree +# is set to ".". building_out_of_srctree is undefined for in srctree +# builds +ifndef building_out_of_srctree +srctree := $(patsubst %/,%,$(dir $(CURDIR))) +srctree := $(patsubst %/,%,$(dir $(srctree))) +endif + +# Do not use make's built-in rules +# (this improves performance and avoids hard-to-debug behaviour); +MAKEFLAGS += -r + +override CFLAGS += -O2 -Wall -g -D_GNU_SOURCE -I$(OUTPUT)include + +ALL_TARGETS := dma_map_benchmark +ALL_PROGRAMS := $(patsubst %,$(OUTPUT)%,$(ALL_TARGETS)) + +all: $(ALL_PROGRAMS) + +export srctree OUTPUT CC LD CFLAGS +include $(srctree)/tools/build/Makefile.include + +# +# We need the following to be outside of kernel tree +# +$(OUTPUT)include/linux/map_benchmark.h: ../../include/uapi/linux/map_benchmark.h + mkdir -p $(OUTPUT)include/linux 2>&1 || true + ln -sf $(CURDIR)/../../include/uapi/linux/map_benchmark.h $@ + +prepare: $(OUTPUT)include/linux/map_benchmark.h + +FORCE: + +DMA_MAP_BENCHMARK = dma_map_benchmark +$(DMA_MAP_BENCHMARK): prepare FORCE + $(CC) $(CFLAGS) $(DMA_MAP_BENCHMARK).c -o $(DMA_MAP_BENCHMARK) + +clean: + rm -f $(ALL_PROGRAMS) + rm -rf $(OUTPUT)include + find $(or $(OUTPUT),.) -name '*.o' -delete -o -name '\.*.d' -delete -o -name '\.*.cmd' -delete + +install: $(ALL_PROGRAMS) + install -d -m 755 $(DESTDIR)$(bindir); \ + for program in $(ALL_PROGRAMS); do \ + install $$program $(DESTDIR)$(bindir); \ + done + +.PHONY: all install clean prepare FORCE diff --git a/tools/dma/config b/tools/dma/config new file mode 100644 index 000000000000..6102ee3c43cd --- /dev/null +++ b/tools/dma/config @@ -0,0 +1 @@ +CONFIG_DMA_MAP_BENCHMARK=y diff --git a/tools/dma/dma_map_benchmark.c b/tools/dma/dma_map_benchmark.c new file mode 100644 index 000000000000..5474a450863c --- /dev/null +++ b/tools/dma/dma_map_benchmark.c @@ -0,0 +1,127 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2020 HiSilicon Limited. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define NSEC_PER_MSEC 1000000L + +static char *directions[] = { + "BIDIRECTIONAL", + "TO_DEVICE", + "FROM_DEVICE", +}; + +int main(int argc, char **argv) +{ + struct map_benchmark map; + int fd, opt; + /* default single thread, run 20 seconds on NUMA_NO_NODE */ + int threads = 1, seconds = 20, node = -1; + /* default dma mask 32bit, bidirectional DMA */ + int bits = 32, xdelay = 0, dir = DMA_MAP_BIDIRECTIONAL; + /* default granule 1 PAGESIZE */ + int granule = 1; + + int cmd = DMA_MAP_BENCHMARK; + + while ((opt = getopt(argc, argv, "t:s:n:b:d:x:g:")) != -1) { + switch (opt) { + case 't': + threads = atoi(optarg); + break; + case 's': + seconds = atoi(optarg); + break; + case 'n': + node = atoi(optarg); + break; + case 'b': + bits = atoi(optarg); + break; + case 'd': + dir = atoi(optarg); + break; + case 'x': + xdelay = atoi(optarg); + break; + case 'g': + granule = atoi(optarg); + break; + default: + return -1; + } + } + + if (threads <= 0 || threads > DMA_MAP_MAX_THREADS) { + fprintf(stderr, "invalid number of threads, must be in 1-%d\n", + DMA_MAP_MAX_THREADS); + exit(1); + } + + if (seconds <= 0 || seconds > DMA_MAP_MAX_SECONDS) { + fprintf(stderr, "invalid number of seconds, must be in 1-%d\n", + DMA_MAP_MAX_SECONDS); + exit(1); + } + + if (xdelay < 0 || xdelay > DMA_MAP_MAX_TRANS_DELAY) { + fprintf(stderr, "invalid transmit delay, must be in 0-%ld\n", + DMA_MAP_MAX_TRANS_DELAY); + exit(1); + } + + /* suppose the mininum DMA zone is 1MB in the world */ + if (bits < 20 || bits > 64) { + fprintf(stderr, "invalid dma mask bit, must be in 20-64\n"); + exit(1); + } + + if (dir != DMA_MAP_BIDIRECTIONAL && dir != DMA_MAP_TO_DEVICE && + dir != DMA_MAP_FROM_DEVICE) { + fprintf(stderr, "invalid dma direction\n"); + exit(1); + } + + if (granule < 1 || granule > 1024) { + fprintf(stderr, "invalid granule size\n"); + exit(1); + } + + fd = open("/sys/kernel/debug/dma_map_benchmark", O_RDWR); + if (fd == -1) { + perror("open"); + exit(1); + } + + memset(&map, 0, sizeof(map)); + map.seconds = seconds; + map.threads = threads; + map.node = node; + map.dma_bits = bits; + map.dma_dir = dir; + map.dma_trans_ns = xdelay; + map.granule = granule; + + if (ioctl(fd, cmd, &map)) { + perror("ioctl"); + exit(1); + } + + printf("dma mapping benchmark: threads:%d seconds:%d node:%d dir:%s granule: %d\n", + threads, seconds, node, dir[directions], granule); + printf("average map latency(us):%.1f standard deviation:%.1f\n", + map.avg_map_100ns/10.0, map.map_stddev/10.0); + printf("average unmap latency(us):%.1f standard deviation:%.1f\n", + map.avg_unmap_100ns/10.0, map.unmap_stddev/10.0); + + return 0; +} diff --git a/tools/testing/selftests/dma/Makefile b/tools/testing/selftests/dma/Makefile deleted file mode 100644 index cd8c5ece1cba..000000000000 --- a/tools/testing/selftests/dma/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -CFLAGS += -I../../../../usr/include/ -CFLAGS += -I../../../../include/ - -TEST_GEN_PROGS := dma_map_benchmark - -include ../lib.mk diff --git a/tools/testing/selftests/dma/config b/tools/testing/selftests/dma/config deleted file mode 100644 index 6102ee3c43cd..000000000000 --- a/tools/testing/selftests/dma/config +++ /dev/null @@ -1 +0,0 @@ -CONFIG_DMA_MAP_BENCHMARK=y diff --git a/tools/testing/selftests/dma/dma_map_benchmark.c b/tools/testing/selftests/dma/dma_map_benchmark.c deleted file mode 100644 index b12f1f9babf8..000000000000 --- a/tools/testing/selftests/dma/dma_map_benchmark.c +++ /dev/null @@ -1,128 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) 2020 HiSilicon Limited. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define NSEC_PER_MSEC 1000000L - -static char *directions[] = { - "BIDIRECTIONAL", - "TO_DEVICE", - "FROM_DEVICE", -}; - -int main(int argc, char **argv) -{ - struct map_benchmark map; - int fd, opt; - /* default single thread, run 20 seconds on NUMA_NO_NODE */ - int threads = 1, seconds = 20, node = -1; - /* default dma mask 32bit, bidirectional DMA */ - int bits = 32, xdelay = 0, dir = DMA_MAP_BIDIRECTIONAL; - /* default granule 1 PAGESIZE */ - int granule = 1; - - int cmd = DMA_MAP_BENCHMARK; - - while ((opt = getopt(argc, argv, "t:s:n:b:d:x:g:")) != -1) { - switch (opt) { - case 't': - threads = atoi(optarg); - break; - case 's': - seconds = atoi(optarg); - break; - case 'n': - node = atoi(optarg); - break; - case 'b': - bits = atoi(optarg); - break; - case 'd': - dir = atoi(optarg); - break; - case 'x': - xdelay = atoi(optarg); - break; - case 'g': - granule = atoi(optarg); - break; - default: - return -1; - } - } - - if (threads <= 0 || threads > DMA_MAP_MAX_THREADS) { - fprintf(stderr, "invalid number of threads, must be in 1-%d\n", - DMA_MAP_MAX_THREADS); - exit(1); - } - - if (seconds <= 0 || seconds > DMA_MAP_MAX_SECONDS) { - fprintf(stderr, "invalid number of seconds, must be in 1-%d\n", - DMA_MAP_MAX_SECONDS); - exit(1); - } - - if (xdelay < 0 || xdelay > DMA_MAP_MAX_TRANS_DELAY) { - fprintf(stderr, "invalid transmit delay, must be in 0-%ld\n", - DMA_MAP_MAX_TRANS_DELAY); - exit(1); - } - - /* suppose the mininum DMA zone is 1MB in the world */ - if (bits < 20 || bits > 64) { - fprintf(stderr, "invalid dma mask bit, must be in 20-64\n"); - exit(1); - } - - if (dir != DMA_MAP_BIDIRECTIONAL && dir != DMA_MAP_TO_DEVICE && - dir != DMA_MAP_FROM_DEVICE) { - fprintf(stderr, "invalid dma direction\n"); - exit(1); - } - - if (granule < 1 || granule > 1024) { - fprintf(stderr, "invalid granule size\n"); - exit(1); - } - - fd = open("/sys/kernel/debug/dma_map_benchmark", O_RDWR); - if (fd == -1) { - perror("open"); - exit(1); - } - - memset(&map, 0, sizeof(map)); - map.seconds = seconds; - map.threads = threads; - map.node = node; - map.dma_bits = bits; - map.dma_dir = dir; - map.dma_trans_ns = xdelay; - map.granule = granule; - - if (ioctl(fd, cmd, &map)) { - perror("ioctl"); - exit(1); - } - - printf("dma mapping benchmark: threads:%d seconds:%d node:%d dir:%s granule: %d\n", - threads, seconds, node, dir[directions], granule); - printf("average map latency(us):%.1f standard deviation:%.1f\n", - map.avg_map_100ns/10.0, map.map_stddev/10.0); - printf("average unmap latency(us):%.1f standard deviation:%.1f\n", - map.avg_unmap_100ns/10.0, map.unmap_stddev/10.0); - - return 0; -} -- cgit v1.2.3