mirror of
https://github.com/tbsdtv/linux_media.git
synced 2025-07-23 20:51:03 +02:00
dma-mapping: benchmark: pretend DMA is transmitting
In a real dma mapping user case, after dma_map is done, data will be transmit. Thus, in multi-threaded user scenario, IOMMU contention should not be that severe. For example, if users enable multiple threads to send network packets through 1G/10G/100Gbps NIC, usually the steps will be: map -> transmission -> unmap. Transmission delay reduces the contention of IOMMU. Here a delay is added to simulate the transmission between map and unmap so that the tested result could be more accurate for TX and simple RX. A typical TX transmission for NIC would be like: map -> TX -> unmap since the socket buffers come from OS. Simple RX model eg. disk driver, is also map -> RX -> unmap, but real RX model in a NIC could be more complicated considering packets can come spontaneously and many drivers are using pre-mapped buffers pool. This is in the TBD list. Signed-off-by: Barry Song <song.bao.hua@hisilicon.com> Signed-off-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
committed by
Christoph Hellwig
parent
9f5f8ec501
commit
9dc00b25ea
@@ -21,6 +21,7 @@
|
|||||||
#define DMA_MAP_BENCHMARK _IOWR('d', 1, struct map_benchmark)
|
#define DMA_MAP_BENCHMARK _IOWR('d', 1, struct map_benchmark)
|
||||||
#define DMA_MAP_MAX_THREADS 1024
|
#define DMA_MAP_MAX_THREADS 1024
|
||||||
#define DMA_MAP_MAX_SECONDS 300
|
#define DMA_MAP_MAX_SECONDS 300
|
||||||
|
#define DMA_MAP_MAX_TRANS_DELAY (10 * NSEC_PER_MSEC)
|
||||||
|
|
||||||
#define DMA_MAP_BIDIRECTIONAL 0
|
#define DMA_MAP_BIDIRECTIONAL 0
|
||||||
#define DMA_MAP_TO_DEVICE 1
|
#define DMA_MAP_TO_DEVICE 1
|
||||||
@@ -36,7 +37,8 @@ struct map_benchmark {
|
|||||||
__s32 node; /* which numa node this benchmark will run on */
|
__s32 node; /* which numa node this benchmark will run on */
|
||||||
__u32 dma_bits; /* DMA addressing capability */
|
__u32 dma_bits; /* DMA addressing capability */
|
||||||
__u32 dma_dir; /* DMA data direction */
|
__u32 dma_dir; /* DMA data direction */
|
||||||
__u8 expansion[84]; /* For future use */
|
__u32 dma_trans_ns; /* time for DMA transmission in ns */
|
||||||
|
__u8 expansion[80]; /* For future use */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct map_benchmark_data {
|
struct map_benchmark_data {
|
||||||
@@ -87,6 +89,9 @@ static int map_benchmark_thread(void *data)
|
|||||||
map_etime = ktime_get();
|
map_etime = ktime_get();
|
||||||
map_delta = ktime_sub(map_etime, map_stime);
|
map_delta = ktime_sub(map_etime, map_stime);
|
||||||
|
|
||||||
|
/* Pretend DMA is transmitting */
|
||||||
|
ndelay(map->bparam.dma_trans_ns);
|
||||||
|
|
||||||
unmap_stime = ktime_get();
|
unmap_stime = ktime_get();
|
||||||
dma_unmap_single(map->dev, dma_addr, PAGE_SIZE, map->dir);
|
dma_unmap_single(map->dev, dma_addr, PAGE_SIZE, map->dir);
|
||||||
unmap_etime = ktime_get();
|
unmap_etime = ktime_get();
|
||||||
@@ -218,6 +223,11 @@ static long map_benchmark_ioctl(struct file *file, unsigned int cmd,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (map->bparam.dma_trans_ns > DMA_MAP_MAX_TRANS_DELAY) {
|
||||||
|
pr_err("invalid transmission delay\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
if (map->bparam.node != NUMA_NO_NODE &&
|
if (map->bparam.node != NUMA_NO_NODE &&
|
||||||
!node_possible(map->bparam.node)) {
|
!node_possible(map->bparam.node)) {
|
||||||
pr_err("invalid numa node\n");
|
pr_err("invalid numa node\n");
|
||||||
|
@@ -12,9 +12,12 @@
|
|||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
|
||||||
|
#define NSEC_PER_MSEC 1000000L
|
||||||
|
|
||||||
#define DMA_MAP_BENCHMARK _IOWR('d', 1, struct map_benchmark)
|
#define DMA_MAP_BENCHMARK _IOWR('d', 1, struct map_benchmark)
|
||||||
#define DMA_MAP_MAX_THREADS 1024
|
#define DMA_MAP_MAX_THREADS 1024
|
||||||
#define DMA_MAP_MAX_SECONDS 300
|
#define DMA_MAP_MAX_SECONDS 300
|
||||||
|
#define DMA_MAP_MAX_TRANS_DELAY (10 * NSEC_PER_MSEC)
|
||||||
|
|
||||||
#define DMA_MAP_BIDIRECTIONAL 0
|
#define DMA_MAP_BIDIRECTIONAL 0
|
||||||
#define DMA_MAP_TO_DEVICE 1
|
#define DMA_MAP_TO_DEVICE 1
|
||||||
@@ -36,7 +39,8 @@ struct map_benchmark {
|
|||||||
__s32 node; /* which numa node this benchmark will run on */
|
__s32 node; /* which numa node this benchmark will run on */
|
||||||
__u32 dma_bits; /* DMA addressing capability */
|
__u32 dma_bits; /* DMA addressing capability */
|
||||||
__u32 dma_dir; /* DMA data direction */
|
__u32 dma_dir; /* DMA data direction */
|
||||||
__u8 expansion[84]; /* For future use */
|
__u32 dma_trans_ns; /* time for DMA transmission in ns */
|
||||||
|
__u8 expansion[80]; /* For future use */
|
||||||
};
|
};
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
@@ -46,12 +50,12 @@ int main(int argc, char **argv)
|
|||||||
/* default single thread, run 20 seconds on NUMA_NO_NODE */
|
/* default single thread, run 20 seconds on NUMA_NO_NODE */
|
||||||
int threads = 1, seconds = 20, node = -1;
|
int threads = 1, seconds = 20, node = -1;
|
||||||
/* default dma mask 32bit, bidirectional DMA */
|
/* default dma mask 32bit, bidirectional DMA */
|
||||||
int bits = 32, dir = DMA_MAP_BIDIRECTIONAL;
|
int bits = 32, xdelay = 0, dir = DMA_MAP_BIDIRECTIONAL;
|
||||||
|
|
||||||
int cmd = DMA_MAP_BENCHMARK;
|
int cmd = DMA_MAP_BENCHMARK;
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "t:s:n:b:d:")) != -1) {
|
while ((opt = getopt(argc, argv, "t:s:n:b:d:x:")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 't':
|
case 't':
|
||||||
threads = atoi(optarg);
|
threads = atoi(optarg);
|
||||||
@@ -68,6 +72,9 @@ int main(int argc, char **argv)
|
|||||||
case 'd':
|
case 'd':
|
||||||
dir = atoi(optarg);
|
dir = atoi(optarg);
|
||||||
break;
|
break;
|
||||||
|
case 'x':
|
||||||
|
xdelay = atoi(optarg);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -85,6 +92,12 @@ int main(int argc, char **argv)
|
|||||||
exit(1);
|
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 */
|
/* suppose the mininum DMA zone is 1MB in the world */
|
||||||
if (bits < 20 || bits > 64) {
|
if (bits < 20 || bits > 64) {
|
||||||
fprintf(stderr, "invalid dma mask bit, must be in 20-64\n");
|
fprintf(stderr, "invalid dma mask bit, must be in 20-64\n");
|
||||||
@@ -109,6 +122,8 @@ int main(int argc, char **argv)
|
|||||||
map.node = node;
|
map.node = node;
|
||||||
map.dma_bits = bits;
|
map.dma_bits = bits;
|
||||||
map.dma_dir = dir;
|
map.dma_dir = dir;
|
||||||
|
map.dma_trans_ns = xdelay;
|
||||||
|
|
||||||
if (ioctl(fd, cmd, &map)) {
|
if (ioctl(fd, cmd, &map)) {
|
||||||
perror("ioctl");
|
perror("ioctl");
|
||||||
exit(1);
|
exit(1);
|
||||||
|
Reference in New Issue
Block a user