/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2015 Intel Corporation. All rights reserved.
* Copyright(c) 2017 T-Platforms. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* BSD LICENSE
*
* Copyright(c) 2015 Intel Corporation. All rights reserved.
* Copyright(c) 2017 T-Platforms. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copy
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
* OWNER 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.
*
* PCIe NTB Perf Linux driver
*/
/*
* How to use this tool, by example.
*
* Assuming $DBG_DIR is something like:
* '/sys/kernel/debug/ntb_perf/0000:00:03.0'
* Suppose aside from local device there is at least one remote device
* connected to NTB with index 0.
*-----------------------------------------------------------------------------
* Eg: install driver with specified chunk/total orders and dma-enabled flag
*
* root@self# insmod ntb_perf.ko chunk_order=19 total_order=28 use_dma
*-----------------------------------------------------------------------------
* Eg: check NTB ports (index) and MW mapping information
*
* root@self# cat $DBG_DIR/info
*-----------------------------------------------------------------------------
* Eg: start performance test with peer (index 0) and get the test metrics
*
* root@self# echo 0 > $DBG_DIR/run
* root@self# cat $DBG_DIR/run
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
#include <linux/pci.h>
#include <linux/ktime.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/sizes.h>
#include <linux/workqueue.h>
#include <linux/debugfs.h>
#include <linux/random.h>
#include <linux/ntb.h>
#define DRIVER_NAME "ntb_perf"
#define DRIVER_VERSION "2.0"
MODULE_LICENSE("Dual BSD/GPL");
MODULE_VERSION(DRIVER_VERSION);
MODULE_AUTHOR("Dave Jiang <dave.jiang@intel.com>");
MODULE_DESCRIPTION("PCIe NTB Performance Measurement Tool");
#define MAX_THREADS_CNT 32
#define DEF_THREADS_CNT 1
#define MAX_CHUNK_SIZE SZ_1M
#define MAX_CHUNK_ORDER 20 /* no larger than 1M */
#define DMA_TRIES 100
#define DMA_MDELAY 10
#define MSG_TRIES 1000
#define MSG_UDELAY_LOW 1000000
#define MSG_UDELAY_HIGH 2000000
#define PERF_BUF_LEN 1024
static unsigned long max_mw_size;
module_param(max_mw_size, ulong, 0644);
MODULE_PARM_DESC(max_mw_size, "Upper limit of memory window size");
static unsigned char chunk_order = 19; /* 512K */
module_param(chunk_order, byte, 0644);
MODULE_PARM_DESC(chunk_order, "Data chunk order [2^n] to transfer");
static unsigned char total_order = 30; /* 1G */
module_param(total_order, byte, 0644);
MODULE_PARM_DESC(total_order, "Total data order [2^n] to transfer");
static bool use_dma; /* default to 0 */
module_param(use_dma, bool, 0644);
MODULE_PARM_DESC(use_dma, "Use DMA engine to measure performance");
/*==============================================================================
* Perf driver data definition
*==============================================================================
*/
enum perf_cmd {
PERF_CMD_INVAL = -1,/* invalid spad command */
PERF_CMD_SSIZE = 0, /* send out buffer size */
PERF_CMD_RSIZE = 1, /* recv in buffer size */
PERF_CMD_SXLAT = 2, /* send in buffer xlat */
PERF_CMD_RXLAT = 3, /* recv out buffer xlat */
PERF_CMD_CLEAR = 4, /* clear allocated memory */
PERF_STS_DONE = 5, /* init is done */
PERF_STS_LNKUP = 6, /* link up state flag */
};
struct perf_ctx;
struct perf_peer {
struct perf_ctx *perf;
int pidx;
int gidx;
/* Outbound MW params */
u64 outbuf_xlat;
resource_size_t outbuf_size;
void __iomem *outbuf;
phys_addr_t out_phys_addr;
dma_addr_t dma_dst_addr;
/* Inbound MW params */
dma_addr_t inbuf_xlat;
resource_size_t inbuf_size;
void *inbuf;
/* NTB connection setup service */
struct work_struct service;
unsigned long sts;
struct completion init_comp;
};
#define to_peer_service(__work) \
container_of(__work, struct perf_peer, service)
struct perf_thread {
struct perf_ctx *perf;
int tidx;
/* DMA-based test sync parameters */
atomic_t dma_sync;
wait_queue_head_t dma_wait;
struct dma_chan *dma_chan;
/* Data source and measured statistics */
void *src;
u64 copied;
ktime_t duration;
int status;
struct work_struct work;
};
#define to_thread_work(__work) \
container_of(__work, struct perf_thread, work)
struct perf_ctx {
struct ntb_dev *ntb;
/* Global device
|