Changeset View
Changeset View
Standalone View
Standalone View
sys/contrib/rdma/krping/krping.c
Show First 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | |||||
#include <asm/atomic.h> | #include <asm/atomic.h> | ||||
#include <rdma/ib_verbs.h> | #include <rdma/ib_verbs.h> | ||||
#include <rdma/rdma_cm.h> | #include <rdma/rdma_cm.h> | ||||
#include "krping.h" | #include "krping.h" | ||||
#include "getopt.h" | #include "getopt.h" | ||||
#define PFX "krping: " | |||||
extern int krping_debug; | extern int krping_debug; | ||||
#define DEBUG_LOG(cb, x...) if (krping_debug) log(LOG_INFO, x) | #define DEBUG_LOG(...) do { if (krping_debug) log(LOG_INFO, __VA_ARGS__); } while (0) | ||||
#define PRINTF(cb, x...) log(LOG_INFO, x) | |||||
#define BIND_INFO 1 | #define BIND_INFO 1 | ||||
MODULE_AUTHOR("Steve Wise"); | MODULE_AUTHOR("Steve Wise"); | ||||
MODULE_DESCRIPTION("RDMA ping client/server"); | MODULE_DESCRIPTION("RDMA ping server"); | ||||
MODULE_LICENSE("Dual BSD/GPL"); | MODULE_LICENSE("Dual BSD/GPL"); | ||||
MODULE_VERSION(krping, 1); | MODULE_VERSION(krping, 1); | ||||
MODULE_DEPEND(krping, linuxkpi, 1, 1, 1); | MODULE_DEPEND(krping, linuxkpi, 1, 1, 1); | ||||
static __inline uint64_t | static __inline uint64_t | ||||
get_cycles(void) | get_cycles(void) | ||||
{ | { | ||||
uint32_t low, high; | uint32_t low, high; | ||||
__asm __volatile("rdtsc" : "=a" (low), "=d" (high)); | __asm __volatile("rdtsc" : "=a" (low), "=d" (high)); | ||||
return (low | ((u_int64_t)high << 32)); | return (low | ((u_int64_t)high << 32)); | ||||
} | } | ||||
typedef uint64_t cycles_t; | typedef uint64_t cycles_t; | ||||
enum mem_type { | enum mem_type { | ||||
DMA = 1, | DMA = 1, | ||||
FASTREG = 2, | REG = 2, | ||||
MW = 3, | |||||
MR = 4 | |||||
}; | }; | ||||
static const struct krping_option krping_opts[] = { | static const struct krping_option krping_opts[] = { | ||||
{"count", OPT_INT, 'C'}, | {"count", OPT_INT, 'C'}, | ||||
{"size", OPT_INT, 'S'}, | {"size", OPT_INT, 'S'}, | ||||
{"addr", OPT_STRING, 'a'}, | {"addr", OPT_STRING, 'a'}, | ||||
{"addr6", OPT_STRING, 'A'}, | |||||
{"port", OPT_INT, 'p'}, | {"port", OPT_INT, 'p'}, | ||||
{"verbose", OPT_NOPARAM, 'v'}, | {"verbose", OPT_NOPARAM, 'v'}, | ||||
{"validate", OPT_NOPARAM, 'V'}, | {"validate", OPT_NOPARAM, 'V'}, | ||||
{"server", OPT_NOPARAM, 's'}, | {"server", OPT_NOPARAM, 's'}, | ||||
{"client", OPT_NOPARAM, 'c'}, | {"client", OPT_NOPARAM, 'c'}, | ||||
{"mem_mode", OPT_STRING, 'm'}, | |||||
{"server_inv", OPT_NOPARAM, 'I'}, | {"server_inv", OPT_NOPARAM, 'I'}, | ||||
{"wlat", OPT_NOPARAM, 'l'}, | {"wlat", OPT_NOPARAM, 'l'}, | ||||
{"rlat", OPT_NOPARAM, 'L'}, | {"rlat", OPT_NOPARAM, 'L'}, | ||||
{"bw", OPT_NOPARAM, 'B'}, | {"bw", OPT_NOPARAM, 'B'}, | ||||
{"duplex", OPT_NOPARAM, 'd'}, | {"duplex", OPT_NOPARAM, 'd'}, | ||||
{"txdepth", OPT_INT, 'T'}, | {"txdepth", OPT_INT, 'T'}, | ||||
{"poll", OPT_NOPARAM, 'P'}, | {"poll", OPT_NOPARAM, 'P'}, | ||||
{"local_dma_lkey", OPT_NOPARAM, 'Z'}, | {"local_dma_lkey", OPT_NOPARAM, 'Z'}, | ||||
{"read_inv", OPT_NOPARAM, 'R'}, | {"read_inv", OPT_NOPARAM, 'R'}, | ||||
{"fr", OPT_INT, 'f'}, | {"fr", OPT_NOPARAM, 'f'}, | ||||
{NULL, 0, 0} | {NULL, 0, 0} | ||||
}; | }; | ||||
#define htonll(x) cpu_to_be64((x)) | #define htonll(x) cpu_to_be64((x)) | ||||
#define ntohll(x) cpu_to_be64((x)) | #define ntohll(x) cpu_to_be64((x)) | ||||
static struct mutex krping_mutex; | static DEFINE_MUTEX(krping_mutex); | ||||
/* | /* | ||||
* List of running krping threads. | * List of running krping threads. | ||||
*/ | */ | ||||
static LIST_HEAD(krping_cbs); | static LIST_HEAD(krping_cbs); | ||||
/* | /* | ||||
* Invoke like this, one on each side, using the server's address on | |||||
* the RDMA device (iw%d): | |||||
* | |||||
* /bin/echo server,port=9999,addr=192.168.69.142,validate > /proc/krping | |||||
* /bin/echo client,port=9999,addr=192.168.69.142,validate > /proc/krping | |||||
* /bin/echo client,port=9999,addr6=2001:db8:0:f101::1,validate > /proc/krping | |||||
* | |||||
* krping "ping/pong" loop: | * krping "ping/pong" loop: | ||||
* client sends source rkey/addr/len | * client sends source rkey/addr/len | ||||
* server receives source rkey/add/len | * server receives source rkey/add/len | ||||
* server rdma reads "ping" data from source | * server rdma reads "ping" data from source | ||||
* server sends "go ahead" on rdma read completion | * server sends "go ahead" on rdma read completion | ||||
* client sends sink rkey/addr/len | * client sends sink rkey/addr/len | ||||
* server receives sink rkey/addr/len | * server receives sink rkey/addr/len | ||||
* server rdma writes "pong" data to sink | * server rdma writes "pong" data to sink | ||||
Show All 32 Lines | |||||
*/ | */ | ||||
#define RPING_BUFSIZE 128*1024 | #define RPING_BUFSIZE 128*1024 | ||||
#define RPING_SQ_DEPTH 64 | #define RPING_SQ_DEPTH 64 | ||||
/* | /* | ||||
* Control block struct. | * Control block struct. | ||||
*/ | */ | ||||
struct krping_cb { | struct krping_cb { | ||||
void *cookie; | |||||
int server; /* 0 iff client */ | int server; /* 0 iff client */ | ||||
struct ib_cq *cq; | struct ib_cq *cq; | ||||
struct ib_pd *pd; | struct ib_pd *pd; | ||||
struct ib_qp *qp; | struct ib_qp *qp; | ||||
enum mem_type mem; | |||||
struct ib_mr *dma_mr; | struct ib_mr *dma_mr; | ||||
struct ib_fast_reg_page_list *page_list; | struct ib_fast_reg_page_list *page_list; | ||||
int page_list_len; | int page_list_len; | ||||
struct ib_send_wr fastreg_wr; | struct ib_reg_wr reg_mr_wr; | ||||
struct ib_send_wr invalidate_wr; | struct ib_send_wr invalidate_wr; | ||||
struct ib_mr *fastreg_mr; | struct ib_mr *reg_mr; | ||||
int server_invalidate; | int server_invalidate; | ||||
int read_inv; | int read_inv; | ||||
u8 key; | u8 key; | ||||
struct ib_mw *mw; | |||||
struct ib_mw_bind bind_attr; | |||||
struct ib_recv_wr rq_wr; /* recv work request record */ | struct ib_recv_wr rq_wr; /* recv work request record */ | ||||
struct ib_sge recv_sgl; /* recv single SGE */ | struct ib_sge recv_sgl; /* recv single SGE */ | ||||
struct krping_rdma_info recv_buf;/* malloc'd buffer */ | struct krping_rdma_info recv_buf __aligned(16); /* malloc'd buffer */ | ||||
u64 recv_dma_addr; | u64 recv_dma_addr; | ||||
DECLARE_PCI_UNMAP_ADDR(recv_mapping) | DECLARE_PCI_UNMAP_ADDR(recv_mapping) | ||||
struct ib_mr *recv_mr; | |||||
struct ib_send_wr sq_wr; /* send work requrest record */ | struct ib_send_wr sq_wr; /* send work requrest record */ | ||||
struct ib_sge send_sgl; | struct ib_sge send_sgl; | ||||
struct krping_rdma_info send_buf;/* single send buf */ | struct krping_rdma_info send_buf __aligned(16); /* single send buf */ | ||||
u64 send_dma_addr; | u64 send_dma_addr; | ||||
DECLARE_PCI_UNMAP_ADDR(send_mapping) | DECLARE_PCI_UNMAP_ADDR(send_mapping) | ||||
struct ib_mr *send_mr; | |||||
struct ib_send_wr rdma_sq_wr; /* rdma work request record */ | struct ib_rdma_wr rdma_sq_wr; /* rdma work request record */ | ||||
struct ib_sge rdma_sgl; /* rdma single SGE */ | struct ib_sge rdma_sgl; /* rdma single SGE */ | ||||
char *rdma_buf; /* used as rdma sink */ | char *rdma_buf; /* used as rdma sink */ | ||||
u64 rdma_dma_addr; | u64 rdma_dma_addr; | ||||
DECLARE_PCI_UNMAP_ADDR(rdma_mapping) | DECLARE_PCI_UNMAP_ADDR(rdma_mapping) | ||||
struct ib_mr *rdma_mr; | struct ib_mr *rdma_mr; | ||||
uint32_t remote_rkey; /* remote guys RKEY */ | uint32_t remote_rkey; /* remote guys RKEY */ | ||||
uint64_t remote_addr; /* remote guys TO */ | uint64_t remote_addr; /* remote guys TO */ | ||||
uint32_t remote_len; /* remote guys LEN */ | uint32_t remote_len; /* remote guys LEN */ | ||||
char *start_buf; /* rdma read src */ | char *start_buf; /* rdma read src */ | ||||
u64 start_dma_addr; | u64 start_dma_addr; | ||||
DECLARE_PCI_UNMAP_ADDR(start_mapping) | DECLARE_PCI_UNMAP_ADDR(start_mapping) | ||||
struct ib_mr *start_mr; | struct ib_mr *start_mr; | ||||
enum test_state state; /* used for cond/signalling */ | enum test_state state; /* used for cond/signalling */ | ||||
wait_queue_head_t sem; | wait_queue_head_t sem; | ||||
struct krping_stats stats; | struct krping_stats stats; | ||||
uint16_t port; /* dst port in NBO */ | uint16_t port; /* dst port in NBO */ | ||||
struct in_addr addr; /* dst addr in NBO */ | u8 addr[16]; /* dst addr in NBO */ | ||||
char *addr_str; /* dst addr string */ | char *addr_str; /* dst addr string */ | ||||
uint8_t addr_type; /* ADDR_FAMILY - IPv4/V6 */ | |||||
int verbose; /* verbose logging */ | int verbose; /* verbose logging */ | ||||
int count; /* ping count */ | int count; /* ping count */ | ||||
int size; /* ping data size */ | int size; /* ping data size */ | ||||
int validate; /* validate ping data */ | int validate; /* validate ping data */ | ||||
int wlat; /* run wlat test */ | int wlat; /* run wlat test */ | ||||
int rlat; /* run rlat test */ | int rlat; /* run rlat test */ | ||||
int bw; /* run bw test */ | int bw; /* run bw test */ | ||||
int duplex; /* run bw full duplex test */ | int duplex; /* run bw full duplex test */ | ||||
int poll; /* poll or block for rlat test */ | int poll; /* poll or block for rlat test */ | ||||
int txdepth; /* SQ depth */ | int txdepth; /* SQ depth */ | ||||
int local_dma_lkey; /* use 0 for lkey */ | int local_dma_lkey; /* use 0 for lkey */ | ||||
int frtest; /* fastreg test */ | int frtest; /* reg test */ | ||||
int testnum; | |||||
/* CM stuff */ | /* CM stuff */ | ||||
struct rdma_cm_id *cm_id; /* connection on client side,*/ | struct rdma_cm_id *cm_id; /* connection on client side,*/ | ||||
/* listener on server side. */ | /* listener on server side. */ | ||||
struct rdma_cm_id *child_cm_id; /* connection on server side */ | struct rdma_cm_id *child_cm_id; /* connection on server side */ | ||||
struct list_head list; | struct list_head list; | ||||
}; | }; | ||||
static int krping_cma_event_handler(struct rdma_cm_id *cma_id, | static int krping_cma_event_handler(struct rdma_cm_id *cma_id, | ||||
struct rdma_cm_event *event) | struct rdma_cm_event *event) | ||||
{ | { | ||||
int ret; | int ret; | ||||
struct krping_cb *cb = cma_id->context; | struct krping_cb *cb = cma_id->context; | ||||
DEBUG_LOG(cb, "cma_event type %d cma_id %p (%s)\n", event->event, | DEBUG_LOG("cma_event type %d cma_id %p (%s)\n", event->event, cma_id, | ||||
cma_id, (cma_id == cb->cm_id) ? "parent" : "child"); | (cma_id == cb->cm_id) ? "parent" : "child"); | ||||
switch (event->event) { | switch (event->event) { | ||||
case RDMA_CM_EVENT_ADDR_RESOLVED: | case RDMA_CM_EVENT_ADDR_RESOLVED: | ||||
cb->state = ADDR_RESOLVED; | cb->state = ADDR_RESOLVED; | ||||
ret = rdma_resolve_route(cma_id, 2000); | ret = rdma_resolve_route(cma_id, 2000); | ||||
if (ret) { | if (ret) { | ||||
PRINTF(cb, "rdma_resolve_route error %d\n", ret); | printk(KERN_ERR PFX "rdma_resolve_route error %d\n", | ||||
ret); | |||||
wake_up_interruptible(&cb->sem); | wake_up_interruptible(&cb->sem); | ||||
} | } | ||||
break; | break; | ||||
case RDMA_CM_EVENT_ROUTE_RESOLVED: | case RDMA_CM_EVENT_ROUTE_RESOLVED: | ||||
cb->state = ROUTE_RESOLVED; | cb->state = ROUTE_RESOLVED; | ||||
cb->child_cm_id = cma_id; | |||||
wake_up_interruptible(&cb->sem); | wake_up_interruptible(&cb->sem); | ||||
break; | break; | ||||
case RDMA_CM_EVENT_CONNECT_REQUEST: | case RDMA_CM_EVENT_CONNECT_REQUEST: | ||||
if (cb->state == IDLE) { | |||||
cb->state = CONNECT_REQUEST; | cb->state = CONNECT_REQUEST; | ||||
cb->child_cm_id = cma_id; | cb->child_cm_id = cma_id; | ||||
} else { | DEBUG_LOG("child cma %p\n", cb->child_cm_id); | ||||
PRINTF(cb, "Received connection request in wrong state" | |||||
" (%d)\n", cb->state); | |||||
} | |||||
DEBUG_LOG(cb, "child cma %p\n", cb->child_cm_id); | |||||
wake_up_interruptible(&cb->sem); | wake_up_interruptible(&cb->sem); | ||||
break; | break; | ||||
case RDMA_CM_EVENT_ESTABLISHED: | case RDMA_CM_EVENT_ESTABLISHED: | ||||
DEBUG_LOG(cb, "ESTABLISHED\n"); | DEBUG_LOG("ESTABLISHED\n"); | ||||
if (!cb->server) { | if (!cb->server) { | ||||
cb->state = CONNECTED; | cb->state = CONNECTED; | ||||
} | } | ||||
wake_up_interruptible(&cb->sem); | wake_up_interruptible(&cb->sem); | ||||
break; | break; | ||||
case RDMA_CM_EVENT_ADDR_ERROR: | case RDMA_CM_EVENT_ADDR_ERROR: | ||||
case RDMA_CM_EVENT_ROUTE_ERROR: | case RDMA_CM_EVENT_ROUTE_ERROR: | ||||
case RDMA_CM_EVENT_CONNECT_ERROR: | case RDMA_CM_EVENT_CONNECT_ERROR: | ||||
case RDMA_CM_EVENT_UNREACHABLE: | case RDMA_CM_EVENT_UNREACHABLE: | ||||
case RDMA_CM_EVENT_REJECTED: | case RDMA_CM_EVENT_REJECTED: | ||||
PRINTF(cb, "cma event %d, error %d\n", event->event, | printk(KERN_ERR PFX "cma event %d, error %d\n", event->event, | ||||
event->status); | event->status); | ||||
cb->state = ERROR; | cb->state = ERROR; | ||||
wake_up_interruptible(&cb->sem); | wake_up_interruptible(&cb->sem); | ||||
break; | break; | ||||
case RDMA_CM_EVENT_DISCONNECTED: | case RDMA_CM_EVENT_DISCONNECTED: | ||||
PRINTF(cb, "DISCONNECT EVENT...\n"); | printk(KERN_ERR PFX "DISCONNECT EVENT...\n"); | ||||
cb->state = ERROR; | cb->state = ERROR; | ||||
wake_up_interruptible(&cb->sem); | wake_up_interruptible(&cb->sem); | ||||
break; | break; | ||||
case RDMA_CM_EVENT_DEVICE_REMOVAL: | case RDMA_CM_EVENT_DEVICE_REMOVAL: | ||||
PRINTF(cb, "cma detected device removal!!!!\n"); | printk(KERN_ERR PFX "cma detected device removal!!!!\n"); | ||||
break; | break; | ||||
default: | default: | ||||
PRINTF(cb, "oof bad type!\n"); | printk(KERN_ERR PFX "oof bad type!\n"); | ||||
wake_up_interruptible(&cb->sem); | wake_up_interruptible(&cb->sem); | ||||
break; | break; | ||||
} | } | ||||
return 0; | return 0; | ||||
} | } | ||||
static int server_recv(struct krping_cb *cb, struct ib_wc *wc) | static int server_recv(struct krping_cb *cb, struct ib_wc *wc) | ||||
{ | { | ||||
if (wc->byte_len != sizeof(cb->recv_buf)) { | if (wc->byte_len != sizeof(cb->recv_buf)) { | ||||
PRINTF(cb, "Received bogus data, size %d\n", | printk(KERN_ERR PFX "Received bogus data, size %d\n", | ||||
wc->byte_len); | wc->byte_len); | ||||
return -1; | return -1; | ||||
} | } | ||||
cb->remote_rkey = ntohl(cb->recv_buf.rkey); | cb->remote_rkey = ntohl(cb->recv_buf.rkey); | ||||
cb->remote_addr = ntohll(cb->recv_buf.buf); | cb->remote_addr = ntohll(cb->recv_buf.buf); | ||||
cb->remote_len = ntohl(cb->recv_buf.size); | cb->remote_len = ntohl(cb->recv_buf.size); | ||||
DEBUG_LOG(cb, "Received rkey %x addr %llx len %d from peer\n", | DEBUG_LOG("Received rkey %x addr %llx len %d from peer\n", | ||||
cb->remote_rkey, (unsigned long long)cb->remote_addr, | cb->remote_rkey, (unsigned long long)cb->remote_addr, | ||||
cb->remote_len); | cb->remote_len); | ||||
if (cb->state <= CONNECTED || cb->state == RDMA_WRITE_COMPLETE) | if (cb->state <= CONNECTED || cb->state == RDMA_WRITE_COMPLETE) | ||||
cb->state = RDMA_READ_ADV; | cb->state = RDMA_READ_ADV; | ||||
else | else | ||||
cb->state = RDMA_WRITE_ADV; | cb->state = RDMA_WRITE_ADV; | ||||
return 0; | return 0; | ||||
} | } | ||||
static int client_recv(struct krping_cb *cb, struct ib_wc *wc) | static int client_recv(struct krping_cb *cb, struct ib_wc *wc) | ||||
{ | { | ||||
if (wc->byte_len != sizeof(cb->recv_buf)) { | if (wc->byte_len != sizeof(cb->recv_buf)) { | ||||
PRINTF(cb, "Received bogus data, size %d\n", | printk(KERN_ERR PFX "Received bogus data, size %d\n", | ||||
wc->byte_len); | wc->byte_len); | ||||
return -1; | return -1; | ||||
} | } | ||||
if (cb->state == RDMA_READ_ADV) | if (cb->state == RDMA_READ_ADV) | ||||
cb->state = RDMA_WRITE_ADV; | cb->state = RDMA_WRITE_ADV; | ||||
else | else | ||||
cb->state = RDMA_WRITE_COMPLETE; | cb->state = RDMA_WRITE_COMPLETE; | ||||
return 0; | return 0; | ||||
} | } | ||||
static void krping_cq_event_handler(struct ib_cq *cq, void *ctx) | static void krping_cq_event_handler(struct ib_cq *cq, void *ctx) | ||||
{ | { | ||||
struct krping_cb *cb = ctx; | struct krping_cb *cb = ctx; | ||||
struct ib_wc wc; | struct ib_wc wc; | ||||
struct ib_recv_wr *bad_wr; | struct ib_recv_wr *bad_wr; | ||||
int ret; | int ret; | ||||
BUG_ON(cb->cq != cq); | BUG_ON(cb->cq != cq); | ||||
if (cb->state == ERROR) { | if (cb->state == ERROR) { | ||||
PRINTF(cb, "cq completion in ERROR state\n"); | printk(KERN_ERR PFX "cq completion in ERROR state\n"); | ||||
return; | return; | ||||
} | } | ||||
if (!cb->wlat && !cb->rlat && !cb->bw && !cb->frtest) | if (cb->frtest) { | ||||
printk(KERN_ERR PFX "cq completion event in frtest!\n"); | |||||
return; | |||||
} | |||||
if (!cb->wlat && !cb->rlat && !cb->bw) | |||||
ib_req_notify_cq(cb->cq, IB_CQ_NEXT_COMP); | ib_req_notify_cq(cb->cq, IB_CQ_NEXT_COMP); | ||||
while ((ret = ib_poll_cq(cb->cq, 1, &wc)) == 1) { | while ((ret = ib_poll_cq(cb->cq, 1, &wc)) == 1) { | ||||
if (wc.status) { | if (wc.status) { | ||||
if (wc.status == IB_WC_WR_FLUSH_ERR) { | if (wc.status == IB_WC_WR_FLUSH_ERR) { | ||||
DEBUG_LOG(cb, "cq flushed\n"); | DEBUG_LOG("cq flushed\n"); | ||||
continue; | continue; | ||||
} else { | } else { | ||||
PRINTF(cb, "cq completion failed with " | printk(KERN_ERR PFX "cq completion failed with " | ||||
"wr_id %jx status %d opcode %d vender_err %x\n", | "wr_id %jx status %d opcode %d vender_err %x\n", | ||||
(uintmax_t)wc.wr_id, wc.status, wc.opcode, wc.vendor_err); | (uintmax_t)wc.wr_id, wc.status, wc.opcode, wc.vendor_err); | ||||
goto error; | goto error; | ||||
} | } | ||||
} | } | ||||
switch (wc.opcode) { | switch (wc.opcode) { | ||||
case IB_WC_SEND: | case IB_WC_SEND: | ||||
DEBUG_LOG(cb, "send completion\n"); | DEBUG_LOG("send completion\n"); | ||||
cb->stats.send_bytes += cb->send_sgl.length; | cb->stats.send_bytes += cb->send_sgl.length; | ||||
cb->stats.send_msgs++; | cb->stats.send_msgs++; | ||||
break; | break; | ||||
case IB_WC_RDMA_WRITE: | case IB_WC_RDMA_WRITE: | ||||
DEBUG_LOG(cb, "rdma write completion\n"); | DEBUG_LOG("rdma write completion\n"); | ||||
cb->stats.write_bytes += cb->rdma_sq_wr.sg_list->length; | cb->stats.write_bytes += cb->rdma_sq_wr.wr.sg_list->length; | ||||
cb->stats.write_msgs++; | cb->stats.write_msgs++; | ||||
cb->state = RDMA_WRITE_COMPLETE; | cb->state = RDMA_WRITE_COMPLETE; | ||||
wake_up_interruptible(&cb->sem); | wake_up_interruptible(&cb->sem); | ||||
break; | break; | ||||
case IB_WC_RDMA_READ: | case IB_WC_RDMA_READ: | ||||
DEBUG_LOG(cb, "rdma read completion\n"); | DEBUG_LOG("rdma read completion\n"); | ||||
cb->stats.read_bytes += cb->rdma_sq_wr.sg_list->length; | cb->stats.read_bytes += cb->rdma_sq_wr.wr.sg_list->length; | ||||
cb->stats.read_msgs++; | cb->stats.read_msgs++; | ||||
cb->state = RDMA_READ_COMPLETE; | cb->state = RDMA_READ_COMPLETE; | ||||
wake_up_interruptible(&cb->sem); | wake_up_interruptible(&cb->sem); | ||||
break; | break; | ||||
case IB_WC_RECV: | case IB_WC_RECV: | ||||
DEBUG_LOG(cb, "recv completion\n"); | DEBUG_LOG("recv completion\n"); | ||||
cb->stats.recv_bytes += sizeof(cb->recv_buf); | cb->stats.recv_bytes += sizeof(cb->recv_buf); | ||||
cb->stats.recv_msgs++; | cb->stats.recv_msgs++; | ||||
if (cb->wlat || cb->rlat || cb->bw || cb->frtest) | if (cb->wlat || cb->rlat || cb->bw) | ||||
ret = server_recv(cb, &wc); | ret = server_recv(cb, &wc); | ||||
else | else | ||||
ret = cb->server ? server_recv(cb, &wc) : | ret = cb->server ? server_recv(cb, &wc) : | ||||
client_recv(cb, &wc); | client_recv(cb, &wc); | ||||
if (ret) { | if (ret) { | ||||
PRINTF(cb, "recv wc error: %d\n", ret); | printk(KERN_ERR PFX "recv wc error: %d\n", ret); | ||||
goto error; | goto error; | ||||
} | } | ||||
ret = ib_post_recv(cb->qp, &cb->rq_wr, &bad_wr); | ret = ib_post_recv(cb->qp, &cb->rq_wr, &bad_wr); | ||||
if (ret) { | if (ret) { | ||||
PRINTF(cb, "post recv error: %d\n", | printk(KERN_ERR PFX "post recv error: %d\n", | ||||
ret); | ret); | ||||
goto error; | goto error; | ||||
} | } | ||||
wake_up_interruptible(&cb->sem); | wake_up_interruptible(&cb->sem); | ||||
break; | break; | ||||
default: | default: | ||||
PRINTF(cb, | printk(KERN_ERR PFX | ||||
"%s:%d Unexpected opcode %d, Shutting down\n", | "%s:%d Unexpected opcode %d, Shutting down\n", | ||||
__func__, __LINE__, wc.opcode); | __func__, __LINE__, wc.opcode); | ||||
goto error; | goto error; | ||||
} | } | ||||
} | } | ||||
if (ret) { | if (ret) { | ||||
PRINTF(cb, "poll error %d\n", ret); | printk(KERN_ERR PFX "poll error %d\n", ret); | ||||
goto error; | goto error; | ||||
} | } | ||||
return; | return; | ||||
error: | error: | ||||
cb->state = ERROR; | cb->state = ERROR; | ||||
wake_up_interruptible(&cb->sem); | wake_up_interruptible(&cb->sem); | ||||
} | } | ||||
static int krping_accept(struct krping_cb *cb) | static int krping_accept(struct krping_cb *cb) | ||||
{ | { | ||||
struct rdma_conn_param conn_param; | struct rdma_conn_param conn_param; | ||||
int ret; | int ret; | ||||
DEBUG_LOG(cb, "accepting client connection request\n"); | DEBUG_LOG("accepting client connection request\n"); | ||||
memset(&conn_param, 0, sizeof conn_param); | memset(&conn_param, 0, sizeof conn_param); | ||||
conn_param.responder_resources = 1; | conn_param.responder_resources = 1; | ||||
conn_param.initiator_depth = 1; | conn_param.initiator_depth = 1; | ||||
ret = rdma_accept(cb->child_cm_id, &conn_param); | ret = rdma_accept(cb->child_cm_id, &conn_param); | ||||
if (ret) { | if (ret) { | ||||
PRINTF(cb, "rdma_accept error: %d\n", ret); | printk(KERN_ERR PFX "rdma_accept error: %d\n", ret); | ||||
return ret; | return ret; | ||||
} | } | ||||
if (!cb->wlat && !cb->rlat && !cb->bw && !cb->frtest) { | if (!cb->wlat && !cb->rlat && !cb->bw) { | ||||
wait_event_interruptible(cb->sem, cb->state >= CONNECTED); | wait_event_interruptible(cb->sem, cb->state >= CONNECTED); | ||||
if (cb->state == ERROR) { | if (cb->state == ERROR) { | ||||
PRINTF(cb, "wait for CONNECTED state %d\n", | printk(KERN_ERR PFX "wait for CONNECTED state %d\n", | ||||
cb->state); | cb->state); | ||||
return -1; | return -1; | ||||
} | } | ||||
} | } | ||||
return 0; | return 0; | ||||
} | } | ||||
static void krping_setup_wr(struct krping_cb *cb) | static void krping_setup_wr(struct krping_cb *cb) | ||||
{ | { | ||||
cb->recv_sgl.addr = cb->recv_dma_addr; | cb->recv_sgl.addr = cb->recv_dma_addr; | ||||
cb->recv_sgl.length = sizeof cb->recv_buf; | cb->recv_sgl.length = sizeof cb->recv_buf; | ||||
if (cb->local_dma_lkey) | cb->recv_sgl.lkey = cb->pd->local_dma_lkey; | ||||
cb->recv_sgl.lkey = cb->qp->device->local_dma_lkey; | |||||
else if (cb->mem == DMA) | |||||
cb->recv_sgl.lkey = cb->dma_mr->lkey; | |||||
else | |||||
cb->recv_sgl.lkey = cb->recv_mr->lkey; | |||||
cb->rq_wr.sg_list = &cb->recv_sgl; | cb->rq_wr.sg_list = &cb->recv_sgl; | ||||
cb->rq_wr.num_sge = 1; | cb->rq_wr.num_sge = 1; | ||||
cb->send_sgl.addr = cb->send_dma_addr; | cb->send_sgl.addr = cb->send_dma_addr; | ||||
cb->send_sgl.length = sizeof cb->send_buf; | cb->send_sgl.length = sizeof cb->send_buf; | ||||
if (cb->local_dma_lkey) | cb->send_sgl.lkey = cb->pd->local_dma_lkey; | ||||
cb->send_sgl.lkey = cb->qp->device->local_dma_lkey; | |||||
else if (cb->mem == DMA) | |||||
cb->send_sgl.lkey = cb->dma_mr->lkey; | |||||
else | |||||
cb->send_sgl.lkey = cb->send_mr->lkey; | |||||
cb->sq_wr.opcode = IB_WR_SEND; | cb->sq_wr.opcode = IB_WR_SEND; | ||||
cb->sq_wr.send_flags = IB_SEND_SIGNALED; | cb->sq_wr.send_flags = IB_SEND_SIGNALED; | ||||
cb->sq_wr.sg_list = &cb->send_sgl; | cb->sq_wr.sg_list = &cb->send_sgl; | ||||
cb->sq_wr.num_sge = 1; | cb->sq_wr.num_sge = 1; | ||||
if (cb->server || cb->wlat || cb->rlat || cb->bw || cb->frtest) { | if (cb->server || cb->wlat || cb->rlat || cb->bw) { | ||||
cb->rdma_sgl.addr = cb->rdma_dma_addr; | cb->rdma_sgl.addr = cb->rdma_dma_addr; | ||||
if (cb->mem == MR) | cb->rdma_sq_wr.wr.send_flags = IB_SEND_SIGNALED; | ||||
cb->rdma_sgl.lkey = cb->rdma_mr->lkey; | cb->rdma_sq_wr.wr.sg_list = &cb->rdma_sgl; | ||||
cb->rdma_sq_wr.send_flags = IB_SEND_SIGNALED; | cb->rdma_sq_wr.wr.num_sge = 1; | ||||
cb->rdma_sq_wr.sg_list = &cb->rdma_sgl; | |||||
cb->rdma_sq_wr.num_sge = 1; | |||||
} | } | ||||
switch(cb->mem) { | |||||
case FASTREG: | |||||
/* | /* | ||||
* A chain of 2 WRs, INVALDATE_MR + FAST_REG_MR. | * A chain of 2 WRs, INVALDATE_MR + REG_MR. | ||||
* both unsignaled. The client uses them to reregister | * both unsignaled. The client uses them to reregister | ||||
* the rdma buffers with a new key each iteration. | * the rdma buffers with a new key each iteration. | ||||
*/ | */ | ||||
cb->fastreg_wr.opcode = IB_WR_FAST_REG_MR; | cb->reg_mr_wr.wr.opcode = IB_WR_REG_MR; | ||||
cb->fastreg_wr.wr.fast_reg.page_shift = PAGE_SHIFT; | cb->reg_mr_wr.mr = cb->reg_mr; | ||||
cb->fastreg_wr.wr.fast_reg.length = cb->size; | |||||
cb->fastreg_wr.wr.fast_reg.page_list = cb->page_list; | |||||
cb->fastreg_wr.wr.fast_reg.page_list_len = cb->page_list_len; | |||||
cb->invalidate_wr.next = &cb->fastreg_wr; | cb->invalidate_wr.next = &cb->reg_mr_wr.wr; | ||||
cb->invalidate_wr.opcode = IB_WR_LOCAL_INV; | cb->invalidate_wr.opcode = IB_WR_LOCAL_INV; | ||||
break; | |||||
case MW: | |||||
cb->bind_attr.wr_id = 0xabbaabba; | |||||
cb->bind_attr.send_flags = 0; /* unsignaled */ | |||||
#ifdef BIND_INFO | |||||
cb->bind_attr.bind_info.length = cb->size; | |||||
#else | |||||
cb->bind_attr.length = cb->size; | |||||
#endif | |||||
break; | |||||
default: | |||||
break; | |||||
} | } | ||||
} | |||||
static int krping_setup_buffers(struct krping_cb *cb) | static int krping_setup_buffers(struct krping_cb *cb) | ||||
{ | { | ||||
int ret; | int ret; | ||||
struct ib_phys_buf buf; | |||||
u64 iovbase; | |||||
DEBUG_LOG(cb, "krping_setup_buffers called on cb %p\n", cb); | DEBUG_LOG(PFX "krping_setup_buffers called on cb %p\n", cb); | ||||
cb->recv_dma_addr = ib_dma_map_single(cb->pd->device, | cb->recv_dma_addr = ib_dma_map_single(cb->pd->device, | ||||
&cb->recv_buf, | &cb->recv_buf, | ||||
sizeof(cb->recv_buf), DMA_BIDIRECTIONAL); | sizeof(cb->recv_buf), DMA_BIDIRECTIONAL); | ||||
pci_unmap_addr_set(cb, recv_mapping, cb->recv_dma_addr); | pci_unmap_addr_set(cb, recv_mapping, cb->recv_dma_addr); | ||||
cb->send_dma_addr = ib_dma_map_single(cb->pd->device, | cb->send_dma_addr = ib_dma_map_single(cb->pd->device, | ||||
&cb->send_buf, sizeof(cb->send_buf), | &cb->send_buf, sizeof(cb->send_buf), | ||||
DMA_BIDIRECTIONAL); | DMA_BIDIRECTIONAL); | ||||
pci_unmap_addr_set(cb, send_mapping, cb->send_dma_addr); | pci_unmap_addr_set(cb, send_mapping, cb->send_dma_addr); | ||||
if (cb->mem == DMA) { | cb->rdma_buf = ib_dma_alloc_coherent(cb->pd->device, cb->size, | ||||
cb->dma_mr = ib_get_dma_mr(cb->pd, IB_ACCESS_LOCAL_WRITE| | &cb->rdma_dma_addr, | ||||
IB_ACCESS_REMOTE_READ| | GFP_KERNEL); | ||||
IB_ACCESS_REMOTE_WRITE); | |||||
if (IS_ERR(cb->dma_mr)) { | |||||
DEBUG_LOG(cb, "reg_dmamr failed\n"); | |||||
ret = PTR_ERR(cb->dma_mr); | |||||
goto bail; | |||||
} | |||||
} else { | |||||
if (!cb->local_dma_lkey) { | |||||
buf.addr = cb->recv_dma_addr; | |||||
buf.size = sizeof cb->recv_buf; | |||||
DEBUG_LOG(cb, "recv buf dma_addr %jx size %d\n", | |||||
(uintmax_t)buf.addr, (int)buf.size); | |||||
iovbase = cb->recv_dma_addr; | |||||
cb->recv_mr = ib_reg_phys_mr(cb->pd, &buf, 1, | |||||
IB_ACCESS_LOCAL_WRITE, | |||||
&iovbase); | |||||
if (IS_ERR(cb->recv_mr)) { | |||||
DEBUG_LOG(cb, "recv_buf reg_mr failed\n"); | |||||
ret = PTR_ERR(cb->recv_mr); | |||||
goto bail; | |||||
} | |||||
buf.addr = cb->send_dma_addr; | |||||
buf.size = sizeof cb->send_buf; | |||||
DEBUG_LOG(cb, "send buf dma_addr %jx size %d\n", | |||||
(uintmax_t)buf.addr, (int)buf.size); | |||||
iovbase = cb->send_dma_addr; | |||||
cb->send_mr = ib_reg_phys_mr(cb->pd, &buf, 1, | |||||
0, &iovbase); | |||||
if (IS_ERR(cb->send_mr)) { | |||||
DEBUG_LOG(cb, "send_buf reg_mr failed\n"); | |||||
ret = PTR_ERR(cb->send_mr); | |||||
goto bail; | |||||
} | |||||
} | |||||
} | |||||
cb->rdma_buf = kmalloc(cb->size, GFP_KERNEL); | |||||
if (!cb->rdma_buf) { | if (!cb->rdma_buf) { | ||||
DEBUG_LOG(cb, "rdma_buf malloc failed\n"); | DEBUG_LOG(PFX "rdma_buf allocation failed\n"); | ||||
ret = -ENOMEM; | ret = -ENOMEM; | ||||
goto bail; | goto bail; | ||||
} | } | ||||
cb->rdma_dma_addr = ib_dma_map_single(cb->pd->device, | |||||
cb->rdma_buf, cb->size, | |||||
DMA_BIDIRECTIONAL); | |||||
pci_unmap_addr_set(cb, rdma_mapping, cb->rdma_dma_addr); | pci_unmap_addr_set(cb, rdma_mapping, cb->rdma_dma_addr); | ||||
if (cb->mem != DMA) { | cb->page_list_len = (((cb->size - 1) & PAGE_MASK) + PAGE_SIZE) | ||||
switch (cb->mem) { | >> PAGE_SHIFT; | ||||
case FASTREG: | cb->reg_mr = ib_alloc_mr(cb->pd, IB_MR_TYPE_MEM_REG, | ||||
cb->page_list_len = (((cb->size - 1) & PAGE_MASK) + | |||||
PAGE_SIZE) >> PAGE_SHIFT; | |||||
cb->page_list = ib_alloc_fast_reg_page_list( | |||||
cb->pd->device, | |||||
cb->page_list_len); | cb->page_list_len); | ||||
if (IS_ERR(cb->page_list)) { | if (IS_ERR(cb->reg_mr)) { | ||||
DEBUG_LOG(cb, "recv_buf reg_mr failed\n"); | ret = PTR_ERR(cb->reg_mr); | ||||
ret = PTR_ERR(cb->page_list); | DEBUG_LOG(PFX "recv_buf reg_mr failed %d\n", ret); | ||||
goto bail; | goto bail; | ||||
} | } | ||||
cb->fastreg_mr = ib_alloc_fast_reg_mr(cb->pd, | DEBUG_LOG(PFX "reg rkey 0x%x page_list_len %u\n", | ||||
cb->page_list->max_page_list_len); | cb->reg_mr->rkey, cb->page_list_len); | ||||
if (IS_ERR(cb->fastreg_mr)) { | |||||
DEBUG_LOG(cb, "recv_buf reg_mr failed\n"); | |||||
ret = PTR_ERR(cb->fastreg_mr); | |||||
goto bail; | |||||
} | |||||
DEBUG_LOG(cb, "fastreg rkey 0x%x page_list %p" | |||||
" page_list_len %u\n", cb->fastreg_mr->rkey, | |||||
cb->page_list, cb->page_list_len); | |||||
break; | |||||
case MW: | |||||
cb->mw = ib_alloc_mw(cb->pd,IB_MW_TYPE_1); | |||||
if (IS_ERR(cb->mw)) { | |||||
DEBUG_LOG(cb, "recv_buf alloc_mw failed\n"); | |||||
ret = PTR_ERR(cb->mw); | |||||
goto bail; | |||||
} | |||||
DEBUG_LOG(cb, "mw rkey 0x%x\n", cb->mw->rkey); | |||||
/*FALLTHROUGH*/ | |||||
case MR: | |||||
buf.addr = cb->rdma_dma_addr; | |||||
buf.size = cb->size; | |||||
iovbase = cb->rdma_dma_addr; | |||||
cb->rdma_mr = ib_reg_phys_mr(cb->pd, &buf, 1, | |||||
IB_ACCESS_LOCAL_WRITE| | |||||
IB_ACCESS_REMOTE_READ| | |||||
IB_ACCESS_REMOTE_WRITE, | |||||
&iovbase); | |||||
if (IS_ERR(cb->rdma_mr)) { | |||||
DEBUG_LOG(cb, "rdma_buf reg_mr failed\n"); | |||||
ret = PTR_ERR(cb->rdma_mr); | |||||
goto bail; | |||||
} | |||||
DEBUG_LOG(cb, "rdma buf dma_addr %jx size %d mr rkey 0x%x\n", | |||||
(uintmax_t)buf.addr, (int)buf.size, cb->rdma_mr->rkey); | |||||
break; | |||||
default: | |||||
ret = -EINVAL; | |||||
goto bail; | |||||
break; | |||||
} | |||||
} | |||||
if (!cb->server || cb->wlat || cb->rlat || cb->bw || cb->frtest) { | if (!cb->server || cb->wlat || cb->rlat || cb->bw) { | ||||
cb->start_buf = kmalloc(cb->size, GFP_KERNEL); | cb->start_buf = ib_dma_alloc_coherent(cb->pd->device, cb->size, | ||||
&cb->start_dma_addr, | |||||
GFP_KERNEL); | |||||
if (!cb->start_buf) { | if (!cb->start_buf) { | ||||
DEBUG_LOG(cb, "start_buf malloc failed\n"); | DEBUG_LOG(PFX "start_buf malloc failed\n"); | ||||
ret = -ENOMEM; | ret = -ENOMEM; | ||||
goto bail; | goto bail; | ||||
} | } | ||||
cb->start_dma_addr = ib_dma_map_single(cb->pd->device, | |||||
cb->start_buf, cb->size, | |||||
DMA_BIDIRECTIONAL); | |||||
pci_unmap_addr_set(cb, start_mapping, cb->start_dma_addr); | pci_unmap_addr_set(cb, start_mapping, cb->start_dma_addr); | ||||
if (cb->mem == MR || cb->mem == MW) { | |||||
unsigned flags = IB_ACCESS_REMOTE_READ; | |||||
if (cb->wlat || cb->rlat || cb->bw || cb->frtest) { | |||||
flags |= IB_ACCESS_LOCAL_WRITE | | |||||
IB_ACCESS_REMOTE_WRITE; | |||||
} | } | ||||
buf.addr = cb->start_dma_addr; | |||||
buf.size = cb->size; | |||||
DEBUG_LOG(cb, "start buf dma_addr %jx size %d\n", | |||||
(uintmax_t)buf.addr, (int)buf.size); | |||||
iovbase = cb->start_dma_addr; | |||||
cb->start_mr = ib_reg_phys_mr(cb->pd, &buf, 1, | |||||
flags, | |||||
&iovbase); | |||||
if (IS_ERR(cb->start_mr)) { | |||||
DEBUG_LOG(cb, "start_buf reg_mr failed\n"); | |||||
ret = PTR_ERR(cb->start_mr); | |||||
goto bail; | |||||
} | |||||
} | |||||
} | |||||
krping_setup_wr(cb); | krping_setup_wr(cb); | ||||
DEBUG_LOG(cb, "allocated & registered buffers...\n"); | DEBUG_LOG(PFX "allocated & registered buffers...\n"); | ||||
return 0; | return 0; | ||||
bail: | bail: | ||||
if (cb->fastreg_mr && !IS_ERR(cb->fastreg_mr)) | if (cb->reg_mr && !IS_ERR(cb->reg_mr)) | ||||
ib_dereg_mr(cb->fastreg_mr); | ib_dereg_mr(cb->reg_mr); | ||||
if (cb->mw && !IS_ERR(cb->mw)) | |||||
ib_dealloc_mw(cb->mw); | |||||
if (cb->rdma_mr && !IS_ERR(cb->rdma_mr)) | if (cb->rdma_mr && !IS_ERR(cb->rdma_mr)) | ||||
ib_dereg_mr(cb->rdma_mr); | ib_dereg_mr(cb->rdma_mr); | ||||
if (cb->page_list && !IS_ERR(cb->page_list)) | |||||
ib_free_fast_reg_page_list(cb->page_list); | |||||
if (cb->dma_mr && !IS_ERR(cb->dma_mr)) | if (cb->dma_mr && !IS_ERR(cb->dma_mr)) | ||||
ib_dereg_mr(cb->dma_mr); | ib_dereg_mr(cb->dma_mr); | ||||
if (cb->recv_mr && !IS_ERR(cb->recv_mr)) | if (cb->rdma_buf) { | ||||
ib_dereg_mr(cb->recv_mr); | ib_dma_free_coherent(cb->pd->device, cb->size, cb->rdma_buf, | ||||
if (cb->send_mr && !IS_ERR(cb->send_mr)) | cb->rdma_dma_addr); | ||||
ib_dereg_mr(cb->send_mr); | } | ||||
if (cb->rdma_buf) | if (cb->start_buf) { | ||||
kfree(cb->rdma_buf); | ib_dma_free_coherent(cb->pd->device, cb->size, cb->start_buf, | ||||
if (cb->start_buf) | cb->start_dma_addr); | ||||
kfree(cb->start_buf); | } | ||||
return ret; | return ret; | ||||
} | } | ||||
static void krping_free_buffers(struct krping_cb *cb) | static void krping_free_buffers(struct krping_cb *cb) | ||||
{ | { | ||||
DEBUG_LOG(cb, "krping_free_buffers called on cb %p\n", cb); | DEBUG_LOG("krping_free_buffers called on cb %p\n", cb); | ||||
if (cb->dma_mr) | if (cb->dma_mr) | ||||
ib_dereg_mr(cb->dma_mr); | ib_dereg_mr(cb->dma_mr); | ||||
if (cb->send_mr) | |||||
ib_dereg_mr(cb->send_mr); | |||||
if (cb->recv_mr) | |||||
ib_dereg_mr(cb->recv_mr); | |||||
if (cb->rdma_mr) | if (cb->rdma_mr) | ||||
ib_dereg_mr(cb->rdma_mr); | ib_dereg_mr(cb->rdma_mr); | ||||
if (cb->start_mr) | if (cb->start_mr) | ||||
ib_dereg_mr(cb->start_mr); | ib_dereg_mr(cb->start_mr); | ||||
if (cb->fastreg_mr) | if (cb->reg_mr) | ||||
ib_dereg_mr(cb->fastreg_mr); | ib_dereg_mr(cb->reg_mr); | ||||
if (cb->mw) | |||||
ib_dealloc_mw(cb->mw); | |||||
dma_unmap_single(cb->pd->device->dma_device, | dma_unmap_single(cb->pd->device->dma_device, | ||||
pci_unmap_addr(cb, recv_mapping), | pci_unmap_addr(cb, recv_mapping), | ||||
sizeof(cb->recv_buf), DMA_BIDIRECTIONAL); | sizeof(cb->recv_buf), DMA_BIDIRECTIONAL); | ||||
dma_unmap_single(cb->pd->device->dma_device, | dma_unmap_single(cb->pd->device->dma_device, | ||||
pci_unmap_addr(cb, send_mapping), | pci_unmap_addr(cb, send_mapping), | ||||
sizeof(cb->send_buf), DMA_BIDIRECTIONAL); | sizeof(cb->send_buf), DMA_BIDIRECTIONAL); | ||||
dma_unmap_single(cb->pd->device->dma_device, | |||||
pci_unmap_addr(cb, rdma_mapping), | ib_dma_free_coherent(cb->pd->device, cb->size, cb->rdma_buf, | ||||
cb->size, DMA_BIDIRECTIONAL); | cb->rdma_dma_addr); | ||||
kfree(cb->rdma_buf); | |||||
if (cb->start_buf) { | if (cb->start_buf) { | ||||
dma_unmap_single(cb->pd->device->dma_device, | ib_dma_free_coherent(cb->pd->device, cb->size, cb->start_buf, | ||||
pci_unmap_addr(cb, start_mapping), | cb->start_dma_addr); | ||||
cb->size, DMA_BIDIRECTIONAL); | |||||
kfree(cb->start_buf); | |||||
} | } | ||||
} | } | ||||
static int krping_create_qp(struct krping_cb *cb) | static int krping_create_qp(struct krping_cb *cb) | ||||
{ | { | ||||
struct ib_qp_init_attr init_attr; | struct ib_qp_init_attr init_attr; | ||||
int ret; | int ret; | ||||
memset(&init_attr, 0, sizeof(init_attr)); | memset(&init_attr, 0, sizeof(init_attr)); | ||||
init_attr.cap.max_send_wr = cb->txdepth; | init_attr.cap.max_send_wr = cb->txdepth; | ||||
init_attr.cap.max_recv_wr = 2; | init_attr.cap.max_recv_wr = 2; | ||||
/* For flush_qp() */ | |||||
init_attr.cap.max_send_wr++; | |||||
init_attr.cap.max_recv_wr++; | |||||
init_attr.cap.max_recv_sge = 1; | init_attr.cap.max_recv_sge = 1; | ||||
init_attr.cap.max_send_sge = 1; | init_attr.cap.max_send_sge = 1; | ||||
init_attr.qp_type = IB_QPT_RC; | init_attr.qp_type = IB_QPT_RC; | ||||
init_attr.send_cq = cb->cq; | init_attr.send_cq = cb->cq; | ||||
init_attr.recv_cq = cb->cq; | init_attr.recv_cq = cb->cq; | ||||
init_attr.sq_sig_type = IB_SIGNAL_REQ_WR; | init_attr.sq_sig_type = IB_SIGNAL_REQ_WR; | ||||
if (cb->server) { | if (cb->server) { | ||||
Show All 14 Lines | static void krping_free_qp(struct krping_cb *cb) | ||||
ib_destroy_qp(cb->qp); | ib_destroy_qp(cb->qp); | ||||
ib_destroy_cq(cb->cq); | ib_destroy_cq(cb->cq); | ||||
ib_dealloc_pd(cb->pd); | ib_dealloc_pd(cb->pd); | ||||
} | } | ||||
static int krping_setup_qp(struct krping_cb *cb, struct rdma_cm_id *cm_id) | static int krping_setup_qp(struct krping_cb *cb, struct rdma_cm_id *cm_id) | ||||
{ | { | ||||
int ret; | int ret; | ||||
cb->pd = ib_alloc_pd(cm_id->device); | struct ib_cq_init_attr attr = {0}; | ||||
cb->pd = ib_alloc_pd(cm_id->device, 0); | |||||
if (IS_ERR(cb->pd)) { | if (IS_ERR(cb->pd)) { | ||||
PRINTF(cb, "ib_alloc_pd failed\n"); | printk(KERN_ERR PFX "ib_alloc_pd failed\n"); | ||||
return PTR_ERR(cb->pd); | return PTR_ERR(cb->pd); | ||||
} | } | ||||
DEBUG_LOG(cb, "created pd %p\n", cb->pd); | DEBUG_LOG("created pd %p\n", cb->pd); | ||||
strlcpy(cb->stats.name, cb->pd->device->name, sizeof(cb->stats.name)); | strlcpy(cb->stats.name, cb->pd->device->name, sizeof(cb->stats.name)); | ||||
attr.cqe = cb->txdepth * 2; | |||||
attr.comp_vector = 0; | |||||
cb->cq = ib_create_cq(cm_id->device, krping_cq_event_handler, NULL, | cb->cq = ib_create_cq(cm_id->device, krping_cq_event_handler, NULL, | ||||
cb, cb->txdepth * 2, 0); | cb, &attr); | ||||
if (IS_ERR(cb->cq)) { | if (IS_ERR(cb->cq)) { | ||||
PRINTF(cb, "ib_create_cq failed\n"); | printk(KERN_ERR PFX "ib_create_cq failed\n"); | ||||
ret = PTR_ERR(cb->cq); | ret = PTR_ERR(cb->cq); | ||||
goto err1; | goto err1; | ||||
} | } | ||||
DEBUG_LOG(cb, "created cq %p\n", cb->cq); | DEBUG_LOG("created cq %p\n", cb->cq); | ||||
if (!cb->wlat && !cb->rlat && !cb->bw && !cb->frtest) { | if (!cb->wlat && !cb->rlat && !cb->bw && !cb->frtest) { | ||||
ret = ib_req_notify_cq(cb->cq, IB_CQ_NEXT_COMP); | ret = ib_req_notify_cq(cb->cq, IB_CQ_NEXT_COMP); | ||||
if (ret) { | if (ret) { | ||||
PRINTF(cb, "ib_create_cq failed\n"); | printk(KERN_ERR PFX "ib_create_cq failed\n"); | ||||
goto err2; | goto err2; | ||||
} | } | ||||
} | } | ||||
ret = krping_create_qp(cb); | ret = krping_create_qp(cb); | ||||
if (ret) { | if (ret) { | ||||
PRINTF(cb, "krping_create_qp failed: %d\n", ret); | printk(KERN_ERR PFX "krping_create_qp failed: %d\n", ret); | ||||
goto err2; | goto err2; | ||||
} | } | ||||
DEBUG_LOG(cb, "created qp %p\n", cb->qp); | DEBUG_LOG("created qp %p\n", cb->qp); | ||||
return 0; | return 0; | ||||
err2: | err2: | ||||
ib_destroy_cq(cb->cq); | ib_destroy_cq(cb->cq); | ||||
err1: | err1: | ||||
ib_dealloc_pd(cb->pd); | ib_dealloc_pd(cb->pd); | ||||
return ret; | return ret; | ||||
} | } | ||||
/* | /* | ||||
* return the (possibly rebound) rkey for the rdma buffer. | * return the (possibly rebound) rkey for the rdma buffer. | ||||
* FASTREG mode: invalidate and rebind via fastreg wr. | * REG mode: invalidate and rebind via reg wr. | ||||
* MW mode: rebind the MW. | |||||
* other modes: just return the mr rkey. | * other modes: just return the mr rkey. | ||||
*/ | */ | ||||
static u32 krping_rdma_rkey(struct krping_cb *cb, u64 buf, int post_inv) | static u32 krping_rdma_rkey(struct krping_cb *cb, u64 buf, int post_inv) | ||||
{ | { | ||||
u32 rkey = 0xffffffff; | u32 rkey; | ||||
u64 p; | |||||
struct ib_send_wr *bad_wr; | struct ib_send_wr *bad_wr; | ||||
int i; | |||||
int ret; | int ret; | ||||
struct scatterlist sg = {0}; | |||||
switch (cb->mem) { | cb->invalidate_wr.ex.invalidate_rkey = cb->reg_mr->rkey; | ||||
case FASTREG: | |||||
cb->invalidate_wr.ex.invalidate_rkey = cb->fastreg_mr->rkey; | |||||
/* | /* | ||||
* Update the fastreg key. | * Update the reg key. | ||||
*/ | */ | ||||
ib_update_fast_reg_key(cb->fastreg_mr, ++cb->key); | ib_update_fast_reg_key(cb->reg_mr, ++cb->key); | ||||
cb->fastreg_wr.wr.fast_reg.rkey = cb->fastreg_mr->rkey; | cb->reg_mr_wr.key = cb->reg_mr->rkey; | ||||
/* | /* | ||||
* Update the fastreg WR with new buf info. | * Update the reg WR with new buf info. | ||||
*/ | */ | ||||
if (buf == (u64)cb->start_dma_addr) | if (buf == (u64)cb->start_dma_addr) | ||||
cb->fastreg_wr.wr.fast_reg.access_flags = IB_ACCESS_REMOTE_READ; | cb->reg_mr_wr.access = IB_ACCESS_REMOTE_READ; | ||||
else | else | ||||
cb->fastreg_wr.wr.fast_reg.access_flags = IB_ACCESS_REMOTE_WRITE | IB_ACCESS_LOCAL_WRITE; | cb->reg_mr_wr.access = IB_ACCESS_REMOTE_WRITE | IB_ACCESS_LOCAL_WRITE; | ||||
cb->fastreg_wr.wr.fast_reg.iova_start = buf; | sg_dma_address(&sg) = buf; | ||||
p = (u64)(buf & PAGE_MASK); | sg_dma_len(&sg) = cb->size; | ||||
for (i=0; i < cb->fastreg_wr.wr.fast_reg.page_list_len; | |||||
i++, p += PAGE_SIZE) { | |||||
cb->page_list->page_list[i] = p; | |||||
DEBUG_LOG(cb, "page_list[%d] 0x%jx\n", i, (uintmax_t)p); | |||||
} | |||||
DEBUG_LOG(cb, "post_inv = %d, fastreg new rkey 0x%x shift %u len %u" | ret = ib_map_mr_sg(cb->reg_mr, &sg, 1, NULL, PAGE_SIZE); | ||||
" iova_start %jx page_list_len %u\n", | BUG_ON(ret <= 0 || ret > cb->page_list_len); | ||||
DEBUG_LOG(PFX "post_inv = %d, reg_mr new rkey 0x%x pgsz %u len %u" | |||||
" iova_start %llx\n", | |||||
post_inv, | post_inv, | ||||
cb->fastreg_wr.wr.fast_reg.rkey, | cb->reg_mr_wr.key, | ||||
cb->fastreg_wr.wr.fast_reg.page_shift, | cb->reg_mr->page_size, | ||||
(unsigned)cb->fastreg_wr.wr.fast_reg.length, | cb->reg_mr->length, | ||||
(uintmax_t)cb->fastreg_wr.wr.fast_reg.iova_start, | (unsigned long long)cb->reg_mr->iova); | ||||
cb->fastreg_wr.wr.fast_reg.page_list_len); | |||||
if (post_inv) | if (post_inv) | ||||
ret = ib_post_send(cb->qp, &cb->invalidate_wr, &bad_wr); | ret = ib_post_send(cb->qp, &cb->invalidate_wr, &bad_wr); | ||||
else | else | ||||
ret = ib_post_send(cb->qp, &cb->fastreg_wr, &bad_wr); | ret = ib_post_send(cb->qp, &cb->reg_mr_wr.wr, &bad_wr); | ||||
if (ret) { | if (ret) { | ||||
PRINTF(cb, "post send error %d\n", ret); | printk(KERN_ERR PFX "post send error %d\n", ret); | ||||
cb->state = ERROR; | cb->state = ERROR; | ||||
} | } | ||||
rkey = cb->fastreg_mr->rkey; | rkey = cb->reg_mr->rkey; | ||||
break; | |||||
case MW: | |||||
/* | |||||
* Update the MW with new buf info. | |||||
*/ | |||||
if (buf == (u64)cb->start_dma_addr) { | |||||
#ifdef BIND_INFO | |||||
cb->bind_attr.bind_info.mw_access_flags = IB_ACCESS_REMOTE_READ; | |||||
cb->bind_attr.bind_info.mr = cb->start_mr; | |||||
#else | |||||
cb->bind_attr.mw_access_flags = IB_ACCESS_REMOTE_READ; | |||||
cb->bind_attr.mr = cb->start_mr; | |||||
#endif | |||||
} else { | |||||
#ifdef BIND_INFO | |||||
cb->bind_attr.bind_info.mw_access_flags = IB_ACCESS_REMOTE_WRITE; | |||||
cb->bind_attr.bind_info.mr = cb->rdma_mr; | |||||
#else | |||||
cb->bind_attr.mw_access_flags = IB_ACCESS_REMOTE_WRITE; | |||||
cb->bind_attr.mr = cb->rdma_mr; | |||||
#endif | |||||
} | |||||
#ifdef BIND_INFO | |||||
cb->bind_attr.bind_info.addr = buf; | |||||
#else | |||||
cb->bind_attr.addr = buf; | |||||
#endif | |||||
DEBUG_LOG(cb, "binding mw rkey 0x%x to buf %jx mr rkey 0x%x\n", | |||||
#ifdef BIND_INFO | |||||
cb->mw->rkey, (uintmax_t)buf, cb->bind_attr.bind_info.mr->rkey); | |||||
#else | |||||
cb->mw->rkey, buf, cb->bind_attr.mr->rkey); | |||||
#endif | |||||
ret = ib_bind_mw(cb->qp, cb->mw, &cb->bind_attr); | |||||
if (ret) { | |||||
PRINTF(cb, "bind mw error %d\n", ret); | |||||
cb->state = ERROR; | |||||
} else | |||||
rkey = cb->mw->rkey; | |||||
break; | |||||
case MR: | |||||
if (buf == (u64)cb->start_dma_addr) | |||||
rkey = cb->start_mr->rkey; | |||||
else | |||||
rkey = cb->rdma_mr->rkey; | |||||
break; | |||||
case DMA: | |||||
rkey = cb->dma_mr->rkey; | |||||
break; | |||||
default: | |||||
PRINTF(cb, "%s:%d case ERROR\n", __func__, __LINE__); | |||||
cb->state = ERROR; | |||||
break; | |||||
} | |||||
return rkey; | return rkey; | ||||
} | } | ||||
static void krping_format_send(struct krping_cb *cb, u64 buf) | static void krping_format_send(struct krping_cb *cb, u64 buf) | ||||
{ | { | ||||
struct krping_rdma_info *info = &cb->send_buf; | struct krping_rdma_info *info = &cb->send_buf; | ||||
u32 rkey; | u32 rkey; | ||||
/* | /* | ||||
* Client side will do fastreg or mw bind before | * Client side will do reg or mw bind before | ||||
* advertising the rdma buffer. Server side | * advertising the rdma buffer. Server side | ||||
* sends have no data. | * sends have no data. | ||||
*/ | */ | ||||
if (!cb->server || cb->wlat || cb->rlat || cb->bw || cb->frtest) { | if (!cb->server || cb->wlat || cb->rlat || cb->bw) { | ||||
rkey = krping_rdma_rkey(cb, buf, !cb->server_invalidate); | rkey = krping_rdma_rkey(cb, buf, !cb->server_invalidate); | ||||
info->buf = htonll(buf); | info->buf = htonll(buf); | ||||
info->rkey = htonl(rkey); | info->rkey = htonl(rkey); | ||||
info->size = htonl(cb->size); | info->size = htonl(cb->size); | ||||
DEBUG_LOG(cb, "RDMA addr %llx rkey %x len %d\n", | DEBUG_LOG("RDMA addr %llx rkey %x len %d\n", | ||||
(unsigned long long)buf, rkey, cb->size); | (unsigned long long)buf, rkey, cb->size); | ||||
} | } | ||||
} | } | ||||
static void krping_test_server(struct krping_cb *cb) | static void krping_test_server(struct krping_cb *cb) | ||||
{ | { | ||||
struct ib_send_wr *bad_wr, inv; | struct ib_send_wr *bad_wr, inv; | ||||
int ret; | int ret; | ||||
while (1) { | while (1) { | ||||
/* Wait for client's Start STAG/TO/Len */ | /* Wait for client's Start STAG/TO/Len */ | ||||
wait_event_interruptible(cb->sem, cb->state >= RDMA_READ_ADV); | wait_event_interruptible(cb->sem, cb->state >= RDMA_READ_ADV); | ||||
if (cb->state != RDMA_READ_ADV) { | if (cb->state != RDMA_READ_ADV) { | ||||
PRINTF(cb, "wait for RDMA_READ_ADV state %d\n", | printk(KERN_ERR PFX "wait for RDMA_READ_ADV state %d\n", | ||||
cb->state); | cb->state); | ||||
break; | break; | ||||
} | } | ||||
DEBUG_LOG(cb, "server received sink adv\n"); | DEBUG_LOG("server received sink adv\n"); | ||||
cb->rdma_sq_wr.wr.rdma.rkey = cb->remote_rkey; | cb->rdma_sq_wr.rkey = cb->remote_rkey; | ||||
cb->rdma_sq_wr.wr.rdma.remote_addr = cb->remote_addr; | cb->rdma_sq_wr.remote_addr = cb->remote_addr; | ||||
cb->rdma_sq_wr.sg_list->length = cb->remote_len; | cb->rdma_sq_wr.wr.sg_list->length = cb->remote_len; | ||||
cb->rdma_sgl.lkey = krping_rdma_rkey(cb, cb->rdma_dma_addr, 1); | cb->rdma_sgl.lkey = krping_rdma_rkey(cb, cb->rdma_dma_addr, !cb->read_inv); | ||||
cb->rdma_sq_wr.wr.next = NULL; | |||||
/* Issue RDMA Read. */ | /* Issue RDMA Read. */ | ||||
if (cb->read_inv) | if (cb->read_inv) | ||||
cb->rdma_sq_wr.opcode = IB_WR_RDMA_READ_WITH_INV; | cb->rdma_sq_wr.wr.opcode = IB_WR_RDMA_READ_WITH_INV; | ||||
else { | else { | ||||
cb->rdma_sq_wr.opcode = IB_WR_RDMA_READ; | cb->rdma_sq_wr.wr.opcode = IB_WR_RDMA_READ; | ||||
if (cb->mem == FASTREG) { | |||||
/* | /* | ||||
* Immediately follow the read with a | * Immediately follow the read with a | ||||
* fenced LOCAL_INV. | * fenced LOCAL_INV. | ||||
*/ | */ | ||||
cb->rdma_sq_wr.next = &inv; | cb->rdma_sq_wr.wr.next = &inv; | ||||
memset(&inv, 0, sizeof inv); | memset(&inv, 0, sizeof inv); | ||||
inv.opcode = IB_WR_LOCAL_INV; | inv.opcode = IB_WR_LOCAL_INV; | ||||
inv.ex.invalidate_rkey = cb->fastreg_mr->rkey; | inv.ex.invalidate_rkey = cb->reg_mr->rkey; | ||||
inv.send_flags = IB_SEND_FENCE; | inv.send_flags = IB_SEND_FENCE; | ||||
} | } | ||||
} | |||||
ret = ib_post_send(cb->qp, &cb->rdma_sq_wr, &bad_wr); | ret = ib_post_send(cb->qp, &cb->rdma_sq_wr.wr, &bad_wr); | ||||
if (ret) { | if (ret) { | ||||
PRINTF(cb, "post send error %d\n", ret); | printk(KERN_ERR PFX "post send error %d\n", ret); | ||||
break; | break; | ||||
} | } | ||||
cb->rdma_sq_wr.next = NULL; | cb->rdma_sq_wr.wr.next = NULL; | ||||
DEBUG_LOG(cb, "server posted rdma read req \n"); | DEBUG_LOG("server posted rdma read req \n"); | ||||
/* Wait for read completion */ | /* Wait for read completion */ | ||||
wait_event_interruptible(cb->sem, | wait_event_interruptible(cb->sem, | ||||
cb->state >= RDMA_READ_COMPLETE); | cb->state >= RDMA_READ_COMPLETE); | ||||
if (cb->state != RDMA_READ_COMPLETE) { | if (cb->state != RDMA_READ_COMPLETE) { | ||||
PRINTF(cb, | printk(KERN_ERR PFX | ||||
"wait for RDMA_READ_COMPLETE state %d\n", | "wait for RDMA_READ_COMPLETE state %d\n", | ||||
cb->state); | cb->state); | ||||
break; | break; | ||||
} | } | ||||
DEBUG_LOG(cb, "server received read complete\n"); | DEBUG_LOG("server received read complete\n"); | ||||
/* Display data in recv buf */ | /* Display data in recv buf */ | ||||
if (cb->verbose) { | if (cb->verbose) | ||||
if (strlen(cb->rdma_buf) > 128) { | printk(KERN_INFO PFX "server ping data: %s\n", | ||||
char msgbuf[128]; | |||||
strlcpy(msgbuf, cb->rdma_buf, sizeof(msgbuf)); | |||||
PRINTF(cb, "server ping data stripped: %s\n", | |||||
msgbuf); | |||||
} else | |||||
PRINTF(cb, "server ping data: %s\n", | |||||
cb->rdma_buf); | cb->rdma_buf); | ||||
} | |||||
/* Tell client to continue */ | /* Tell client to continue */ | ||||
if (cb->server && cb->server_invalidate) { | if (cb->server && cb->server_invalidate) { | ||||
cb->sq_wr.ex.invalidate_rkey = cb->remote_rkey; | cb->sq_wr.ex.invalidate_rkey = cb->remote_rkey; | ||||
cb->sq_wr.opcode = IB_WR_SEND_WITH_INV; | cb->sq_wr.opcode = IB_WR_SEND_WITH_INV; | ||||
DEBUG_LOG(cb, "send-w-inv rkey 0x%x\n", cb->remote_rkey); | DEBUG_LOG("send-w-inv rkey 0x%x\n", cb->remote_rkey); | ||||
} | } | ||||
ret = ib_post_send(cb->qp, &cb->sq_wr, &bad_wr); | ret = ib_post_send(cb->qp, &cb->sq_wr, &bad_wr); | ||||
if (ret) { | if (ret) { | ||||
PRINTF(cb, "post send error %d\n", ret); | printk(KERN_ERR PFX "post send error %d\n", ret); | ||||
break; | break; | ||||
} | } | ||||
DEBUG_LOG(cb, "server posted go ahead\n"); | DEBUG_LOG("server posted go ahead\n"); | ||||
/* Wait for client's RDMA STAG/TO/Len */ | /* Wait for client's RDMA STAG/TO/Len */ | ||||
wait_event_interruptible(cb->sem, cb->state >= RDMA_WRITE_ADV); | wait_event_interruptible(cb->sem, cb->state >= RDMA_WRITE_ADV); | ||||
if (cb->state != RDMA_WRITE_ADV) { | if (cb->state != RDMA_WRITE_ADV) { | ||||
PRINTF(cb, | printk(KERN_ERR PFX | ||||
"wait for RDMA_WRITE_ADV state %d\n", | "wait for RDMA_WRITE_ADV state %d\n", | ||||
cb->state); | cb->state); | ||||
break; | break; | ||||
} | } | ||||
DEBUG_LOG(cb, "server received sink adv\n"); | DEBUG_LOG("server received sink adv\n"); | ||||
/* RDMA Write echo data */ | /* RDMA Write echo data */ | ||||
cb->rdma_sq_wr.opcode = IB_WR_RDMA_WRITE; | cb->rdma_sq_wr.wr.opcode = IB_WR_RDMA_WRITE; | ||||
cb->rdma_sq_wr.wr.rdma.rkey = cb->remote_rkey; | cb->rdma_sq_wr.rkey = cb->remote_rkey; | ||||
cb->rdma_sq_wr.wr.rdma.remote_addr = cb->remote_addr; | cb->rdma_sq_wr.remote_addr = cb->remote_addr; | ||||
cb->rdma_sq_wr.sg_list->length = strlen(cb->rdma_buf) + 1; | cb->rdma_sq_wr.wr.sg_list->length = strlen(cb->rdma_buf) + 1; | ||||
if (cb->local_dma_lkey) | if (cb->local_dma_lkey) | ||||
cb->rdma_sgl.lkey = cb->qp->device->local_dma_lkey; | cb->rdma_sgl.lkey = cb->pd->local_dma_lkey; | ||||
else | else | ||||
cb->rdma_sgl.lkey = krping_rdma_rkey(cb, cb->rdma_dma_addr, 0); | cb->rdma_sgl.lkey = krping_rdma_rkey(cb, cb->rdma_dma_addr, 0); | ||||
DEBUG_LOG(cb, "rdma write from lkey %x laddr %llx len %d\n", | DEBUG_LOG("rdma write from lkey %x laddr %llx len %d\n", | ||||
cb->rdma_sq_wr.sg_list->lkey, | cb->rdma_sq_wr.wr.sg_list->lkey, | ||||
(unsigned long long)cb->rdma_sq_wr.sg_list->addr, | (unsigned long long)cb->rdma_sq_wr.wr.sg_list->addr, | ||||
cb->rdma_sq_wr.sg_list->length); | cb->rdma_sq_wr.wr.sg_list->length); | ||||
ret = ib_post_send(cb->qp, &cb->rdma_sq_wr, &bad_wr); | ret = ib_post_send(cb->qp, &cb->rdma_sq_wr.wr, &bad_wr); | ||||
if (ret) { | if (ret) { | ||||
PRINTF(cb, "post send error %d\n", ret); | printk(KERN_ERR PFX "post send error %d\n", ret); | ||||
break; | break; | ||||
} | } | ||||
/* Wait for completion */ | /* Wait for completion */ | ||||
ret = wait_event_interruptible(cb->sem, cb->state >= | ret = wait_event_interruptible(cb->sem, cb->state >= | ||||
RDMA_WRITE_COMPLETE); | RDMA_WRITE_COMPLETE); | ||||
if (cb->state != RDMA_WRITE_COMPLETE) { | if (cb->state != RDMA_WRITE_COMPLETE) { | ||||
PRINTF(cb, | printk(KERN_ERR PFX | ||||
"wait for RDMA_WRITE_COMPLETE state %d\n", | "wait for RDMA_WRITE_COMPLETE state %d\n", | ||||
cb->state); | cb->state); | ||||
break; | break; | ||||
} | } | ||||
DEBUG_LOG(cb, "server rdma write complete \n"); | DEBUG_LOG("server rdma write complete \n"); | ||||
cb->state = CONNECTED; | cb->state = CONNECTED; | ||||
/* Tell client to begin again */ | /* Tell client to begin again */ | ||||
if (cb->server && cb->server_invalidate) { | if (cb->server && cb->server_invalidate) { | ||||
cb->sq_wr.ex.invalidate_rkey = cb->remote_rkey; | cb->sq_wr.ex.invalidate_rkey = cb->remote_rkey; | ||||
cb->sq_wr.opcode = IB_WR_SEND_WITH_INV; | cb->sq_wr.opcode = IB_WR_SEND_WITH_INV; | ||||
DEBUG_LOG(cb, "send-w-inv rkey 0x%x\n", cb->remote_rkey); | DEBUG_LOG("send-w-inv rkey 0x%x\n", cb->remote_rkey); | ||||
} | } | ||||
ret = ib_post_send(cb->qp, &cb->sq_wr, &bad_wr); | ret = ib_post_send(cb->qp, &cb->sq_wr, &bad_wr); | ||||
if (ret) { | if (ret) { | ||||
PRINTF(cb, "post send error %d\n", ret); | printk(KERN_ERR PFX "post send error %d\n", ret); | ||||
break; | break; | ||||
} | } | ||||
DEBUG_LOG(cb, "server posted go ahead\n"); | DEBUG_LOG("server posted go ahead\n"); | ||||
} | } | ||||
} | } | ||||
static void rlat_test(struct krping_cb *cb) | static void rlat_test(struct krping_cb *cb) | ||||
{ | { | ||||
int scnt; | int scnt; | ||||
int iters = cb->count; | int iters = cb->count; | ||||
struct timeval start_tv, stop_tv; | struct timeval start_tv, stop_tv; | ||||
int ret; | int ret; | ||||
struct ib_wc wc; | struct ib_wc wc; | ||||
struct ib_send_wr *bad_wr; | struct ib_send_wr *bad_wr; | ||||
int ne; | int ne; | ||||
scnt = 0; | scnt = 0; | ||||
cb->rdma_sq_wr.opcode = IB_WR_RDMA_READ; | cb->rdma_sq_wr.wr.opcode = IB_WR_RDMA_READ; | ||||
cb->rdma_sq_wr.wr.rdma.rkey = cb->remote_rkey; | cb->rdma_sq_wr.rkey = cb->remote_rkey; | ||||
cb->rdma_sq_wr.wr.rdma.remote_addr = cb->remote_addr; | cb->rdma_sq_wr.remote_addr = cb->remote_addr; | ||||
cb->rdma_sq_wr.sg_list->length = cb->size; | cb->rdma_sq_wr.wr.sg_list->length = cb->size; | ||||
microtime(&start_tv); | microtime(&start_tv); | ||||
if (!cb->poll) { | if (!cb->poll) { | ||||
cb->state = RDMA_READ_ADV; | cb->state = RDMA_READ_ADV; | ||||
ib_req_notify_cq(cb->cq, IB_CQ_NEXT_COMP); | ib_req_notify_cq(cb->cq, IB_CQ_NEXT_COMP); | ||||
} | } | ||||
while (scnt < iters) { | while (scnt < iters) { | ||||
cb->state = RDMA_READ_ADV; | cb->state = RDMA_READ_ADV; | ||||
ret = ib_post_send(cb->qp, &cb->rdma_sq_wr, &bad_wr); | ret = ib_post_send(cb->qp, &cb->rdma_sq_wr.wr, &bad_wr); | ||||
if (ret) { | if (ret) { | ||||
PRINTF(cb, | printk(KERN_ERR PFX | ||||
"Couldn't post send: ret=%d scnt %d\n", | "Couldn't post send: ret=%d scnt %d\n", | ||||
ret, scnt); | ret, scnt); | ||||
return; | return; | ||||
} | } | ||||
do { | do { | ||||
if (!cb->poll) { | if (!cb->poll) { | ||||
wait_event_interruptible(cb->sem, | wait_event_interruptible(cb->sem, | ||||
cb->state != RDMA_READ_ADV); | cb->state != RDMA_READ_ADV); | ||||
if (cb->state == RDMA_READ_COMPLETE) { | if (cb->state == RDMA_READ_COMPLETE) { | ||||
ne = 1; | ne = 1; | ||||
ib_req_notify_cq(cb->cq, | ib_req_notify_cq(cb->cq, | ||||
IB_CQ_NEXT_COMP); | IB_CQ_NEXT_COMP); | ||||
} else { | } else { | ||||
ne = -1; | ne = -1; | ||||
} | } | ||||
} else | } else | ||||
ne = ib_poll_cq(cb->cq, 1, &wc); | ne = ib_poll_cq(cb->cq, 1, &wc); | ||||
if (cb->state == ERROR) { | if (cb->state == ERROR) { | ||||
PRINTF(cb, | printk(KERN_ERR PFX | ||||
"state == ERROR...bailing scnt %d\n", | "state == ERROR...bailing scnt %d\n", | ||||
scnt); | scnt); | ||||
return; | return; | ||||
} | } | ||||
} while (ne == 0); | } while (ne == 0); | ||||
if (ne < 0) { | if (ne < 0) { | ||||
PRINTF(cb, "poll CQ failed %d\n", ne); | printk(KERN_ERR PFX "poll CQ failed %d\n", ne); | ||||
return; | return; | ||||
} | } | ||||
if (cb->poll && wc.status != IB_WC_SUCCESS) { | if (cb->poll && wc.status != IB_WC_SUCCESS) { | ||||
PRINTF(cb, "Completion wth error at %s:\n", | printk(KERN_ERR PFX "Completion wth error at %s:\n", | ||||
cb->server ? "server" : "client"); | cb->server ? "server" : "client"); | ||||
PRINTF(cb, "Failed status %d: wr_id %d\n", | printk(KERN_ERR PFX "Failed status %d: wr_id %d\n", | ||||
wc.status, (int) wc.wr_id); | wc.status, (int) wc.wr_id); | ||||
return; | return; | ||||
} | } | ||||
++scnt; | ++scnt; | ||||
} | } | ||||
microtime(&stop_tv); | microtime(&stop_tv); | ||||
if (stop_tv.tv_usec < start_tv.tv_usec) { | if (stop_tv.tv_usec < start_tv.tv_usec) { | ||||
stop_tv.tv_usec += 1000000; | stop_tv.tv_usec += 1000000; | ||||
stop_tv.tv_sec -= 1; | stop_tv.tv_sec -= 1; | ||||
} | } | ||||
PRINTF(cb, "delta sec %lu delta usec %lu iter %d size %d\n", | printk(KERN_ERR PFX "delta sec %lu delta usec %lu iter %d size %d\n", | ||||
(unsigned long)(stop_tv.tv_sec - start_tv.tv_sec), | (unsigned long)(stop_tv.tv_sec - start_tv.tv_sec), | ||||
(unsigned long)(stop_tv.tv_usec - start_tv.tv_usec), | (unsigned long)(stop_tv.tv_usec - start_tv.tv_usec), | ||||
scnt, cb->size); | scnt, cb->size); | ||||
} | } | ||||
static void wlat_test(struct krping_cb *cb) | static void wlat_test(struct krping_cb *cb) | ||||
{ | { | ||||
int ccnt, scnt, rcnt; | int ccnt, scnt, rcnt; | ||||
Show All 9 Lines | static void wlat_test(struct krping_cb *cb) | ||||
int cycle_iters = 1000; | int cycle_iters = 1000; | ||||
ccnt = 0; | ccnt = 0; | ||||
scnt = 0; | scnt = 0; | ||||
rcnt = 0; | rcnt = 0; | ||||
post_cycles_start = kmalloc(cycle_iters * sizeof(cycles_t), GFP_KERNEL); | post_cycles_start = kmalloc(cycle_iters * sizeof(cycles_t), GFP_KERNEL); | ||||
if (!post_cycles_start) { | if (!post_cycles_start) { | ||||
PRINTF(cb, "%s kmalloc failed\n", __FUNCTION__); | printk(KERN_ERR PFX "%s kmalloc failed\n", __FUNCTION__); | ||||
return; | return; | ||||
} | } | ||||
post_cycles_stop = kmalloc(cycle_iters * sizeof(cycles_t), GFP_KERNEL); | post_cycles_stop = kmalloc(cycle_iters * sizeof(cycles_t), GFP_KERNEL); | ||||
if (!post_cycles_stop) { | if (!post_cycles_stop) { | ||||
PRINTF(cb, "%s kmalloc failed\n", __FUNCTION__); | printk(KERN_ERR PFX "%s kmalloc failed\n", __FUNCTION__); | ||||
return; | return; | ||||
} | } | ||||
poll_cycles_start = kmalloc(cycle_iters * sizeof(cycles_t), GFP_KERNEL); | poll_cycles_start = kmalloc(cycle_iters * sizeof(cycles_t), GFP_KERNEL); | ||||
if (!poll_cycles_start) { | if (!poll_cycles_start) { | ||||
PRINTF(cb, "%s kmalloc failed\n", __FUNCTION__); | printk(KERN_ERR PFX "%s kmalloc failed\n", __FUNCTION__); | ||||
return; | return; | ||||
} | } | ||||
poll_cycles_stop = kmalloc(cycle_iters * sizeof(cycles_t), GFP_KERNEL); | poll_cycles_stop = kmalloc(cycle_iters * sizeof(cycles_t), GFP_KERNEL); | ||||
if (!poll_cycles_stop) { | if (!poll_cycles_stop) { | ||||
PRINTF(cb, "%s kmalloc failed\n", __FUNCTION__); | printk(KERN_ERR PFX "%s kmalloc failed\n", __FUNCTION__); | ||||
return; | return; | ||||
} | } | ||||
last_poll_cycles_start = kmalloc(cycle_iters * sizeof(cycles_t), | last_poll_cycles_start = kmalloc(cycle_iters * sizeof(cycles_t), | ||||
GFP_KERNEL); | GFP_KERNEL); | ||||
if (!last_poll_cycles_start) { | if (!last_poll_cycles_start) { | ||||
PRINTF(cb, "%s kmalloc failed\n", __FUNCTION__); | printk(KERN_ERR PFX "%s kmalloc failed\n", __FUNCTION__); | ||||
return; | return; | ||||
} | } | ||||
cb->rdma_sq_wr.opcode = IB_WR_RDMA_WRITE; | cb->rdma_sq_wr.wr.opcode = IB_WR_RDMA_WRITE; | ||||
cb->rdma_sq_wr.wr.rdma.rkey = cb->remote_rkey; | cb->rdma_sq_wr.rkey = cb->remote_rkey; | ||||
cb->rdma_sq_wr.wr.rdma.remote_addr = cb->remote_addr; | cb->rdma_sq_wr.remote_addr = cb->remote_addr; | ||||
cb->rdma_sq_wr.sg_list->length = cb->size; | cb->rdma_sq_wr.wr.sg_list->length = cb->size; | ||||
if (cycle_iters > iters) | if (cycle_iters > iters) | ||||
cycle_iters = iters; | cycle_iters = iters; | ||||
microtime(&start_tv); | microtime(&start_tv); | ||||
while (scnt < iters || ccnt < iters || rcnt < iters) { | while (scnt < iters || ccnt < iters || rcnt < iters) { | ||||
/* Wait till buffer changes. */ | /* Wait till buffer changes. */ | ||||
if (rcnt < iters && !(scnt < 1 && !cb->server)) { | if (rcnt < iters && !(scnt < 1 && !cb->server)) { | ||||
++rcnt; | ++rcnt; | ||||
while (*poll_buf != (char)rcnt) { | while (*poll_buf != (char)rcnt) { | ||||
if (cb->state == ERROR) { | if (cb->state == ERROR) { | ||||
PRINTF(cb, | printk(KERN_ERR PFX | ||||
"state = ERROR, bailing\n"); | "state = ERROR, bailing\n"); | ||||
return; | return; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
if (scnt < iters) { | if (scnt < iters) { | ||||
struct ib_send_wr *bad_wr; | struct ib_send_wr *bad_wr; | ||||
*buf = (char)scnt+1; | *buf = (char)scnt+1; | ||||
if (scnt < cycle_iters) | if (scnt < cycle_iters) | ||||
post_cycles_start[scnt] = get_cycles(); | post_cycles_start[scnt] = get_cycles(); | ||||
if (ib_post_send(cb->qp, &cb->rdma_sq_wr, &bad_wr)) { | if (ib_post_send(cb->qp, &cb->rdma_sq_wr.wr, &bad_wr)) { | ||||
PRINTF(cb, | printk(KERN_ERR PFX | ||||
"Couldn't post send: scnt=%d\n", | "Couldn't post send: scnt=%d\n", | ||||
scnt); | scnt); | ||||
return; | return; | ||||
} | } | ||||
if (scnt < cycle_iters) | if (scnt < cycle_iters) | ||||
post_cycles_stop[scnt] = get_cycles(); | post_cycles_stop[scnt] = get_cycles(); | ||||
scnt++; | scnt++; | ||||
} | } | ||||
Show All 10 Lines | if (ccnt < iters) { | ||||
get_cycles(); | get_cycles(); | ||||
ne = ib_poll_cq(cb->cq, 1, &wc); | ne = ib_poll_cq(cb->cq, 1, &wc); | ||||
} while (ne == 0); | } while (ne == 0); | ||||
if (ccnt < cycle_iters) | if (ccnt < cycle_iters) | ||||
poll_cycles_stop[ccnt] = get_cycles(); | poll_cycles_stop[ccnt] = get_cycles(); | ||||
++ccnt; | ++ccnt; | ||||
if (ne < 0) { | if (ne < 0) { | ||||
PRINTF(cb, "poll CQ failed %d\n", ne); | printk(KERN_ERR PFX "poll CQ failed %d\n", ne); | ||||
return; | return; | ||||
} | } | ||||
if (wc.status != IB_WC_SUCCESS) { | if (wc.status != IB_WC_SUCCESS) { | ||||
PRINTF(cb, | printk(KERN_ERR PFX | ||||
"Completion wth error at %s:\n", | "Completion wth error at %s:\n", | ||||
cb->server ? "server" : "client"); | cb->server ? "server" : "client"); | ||||
PRINTF(cb, | printk(KERN_ERR PFX | ||||
"Failed status %d: wr_id %d\n", | "Failed status %d: wr_id %d\n", | ||||
wc.status, (int) wc.wr_id); | wc.status, (int) wc.wr_id); | ||||
PRINTF(cb, | printk(KERN_ERR PFX | ||||
"scnt=%d, rcnt=%d, ccnt=%d\n", | "scnt=%d, rcnt=%d, ccnt=%d\n", | ||||
scnt, rcnt, ccnt); | scnt, rcnt, ccnt); | ||||
return; | return; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
microtime(&stop_tv); | microtime(&stop_tv); | ||||
if (stop_tv.tv_usec < start_tv.tv_usec) { | if (stop_tv.tv_usec < start_tv.tv_usec) { | ||||
stop_tv.tv_usec += 1000000; | stop_tv.tv_usec += 1000000; | ||||
stop_tv.tv_sec -= 1; | stop_tv.tv_sec -= 1; | ||||
} | } | ||||
for (i=0; i < cycle_iters; i++) { | for (i=0; i < cycle_iters; i++) { | ||||
sum_post += post_cycles_stop[i] - post_cycles_start[i]; | sum_post += post_cycles_stop[i] - post_cycles_start[i]; | ||||
sum_poll += poll_cycles_stop[i] - poll_cycles_start[i]; | sum_poll += poll_cycles_stop[i] - poll_cycles_start[i]; | ||||
sum_last_poll += poll_cycles_stop[i]-last_poll_cycles_start[i]; | sum_last_poll += poll_cycles_stop[i]-last_poll_cycles_start[i]; | ||||
} | } | ||||
PRINTF(cb, | printk(KERN_ERR PFX | ||||
"delta sec %lu delta usec %lu iter %d size %d cycle_iters %d" | "delta sec %lu delta usec %lu iter %d size %d cycle_iters %d" | ||||
" sum_post %llu sum_poll %llu sum_last_poll %llu\n", | " sum_post %llu sum_poll %llu sum_last_poll %llu\n", | ||||
(unsigned long)(stop_tv.tv_sec - start_tv.tv_sec), | (unsigned long)(stop_tv.tv_sec - start_tv.tv_sec), | ||||
(unsigned long)(stop_tv.tv_usec - start_tv.tv_usec), | (unsigned long)(stop_tv.tv_usec - start_tv.tv_usec), | ||||
scnt, cb->size, cycle_iters, | scnt, cb->size, cycle_iters, | ||||
(unsigned long long)sum_post, (unsigned long long)sum_poll, | (unsigned long long)sum_post, (unsigned long long)sum_poll, | ||||
(unsigned long long)sum_last_poll); | (unsigned long long)sum_last_poll); | ||||
kfree(post_cycles_start); | kfree(post_cycles_start); | ||||
Show All 16 Lines | static void bw_test(struct krping_cb *cb) | ||||
int cycle_iters = 1000; | int cycle_iters = 1000; | ||||
ccnt = 0; | ccnt = 0; | ||||
scnt = 0; | scnt = 0; | ||||
rcnt = 0; | rcnt = 0; | ||||
post_cycles_start = kmalloc(cycle_iters * sizeof(cycles_t), GFP_KERNEL); | post_cycles_start = kmalloc(cycle_iters * sizeof(cycles_t), GFP_KERNEL); | ||||
if (!post_cycles_start) { | if (!post_cycles_start) { | ||||
PRINTF(cb, "%s kmalloc failed\n", __FUNCTION__); | printk(KERN_ERR PFX "%s kmalloc failed\n", __FUNCTION__); | ||||
return; | return; | ||||
} | } | ||||
post_cycles_stop = kmalloc(cycle_iters * sizeof(cycles_t), GFP_KERNEL); | post_cycles_stop = kmalloc(cycle_iters * sizeof(cycles_t), GFP_KERNEL); | ||||
if (!post_cycles_stop) { | if (!post_cycles_stop) { | ||||
PRINTF(cb, "%s kmalloc failed\n", __FUNCTION__); | printk(KERN_ERR PFX "%s kmalloc failed\n", __FUNCTION__); | ||||
return; | return; | ||||
} | } | ||||
poll_cycles_start = kmalloc(cycle_iters * sizeof(cycles_t), GFP_KERNEL); | poll_cycles_start = kmalloc(cycle_iters * sizeof(cycles_t), GFP_KERNEL); | ||||
if (!poll_cycles_start) { | if (!poll_cycles_start) { | ||||
PRINTF(cb, "%s kmalloc failed\n", __FUNCTION__); | printk(KERN_ERR PFX "%s kmalloc failed\n", __FUNCTION__); | ||||
return; | return; | ||||
} | } | ||||
poll_cycles_stop = kmalloc(cycle_iters * sizeof(cycles_t), GFP_KERNEL); | poll_cycles_stop = kmalloc(cycle_iters * sizeof(cycles_t), GFP_KERNEL); | ||||
if (!poll_cycles_stop) { | if (!poll_cycles_stop) { | ||||
PRINTF(cb, "%s kmalloc failed\n", __FUNCTION__); | printk(KERN_ERR PFX "%s kmalloc failed\n", __FUNCTION__); | ||||
return; | return; | ||||
} | } | ||||
last_poll_cycles_start = kmalloc(cycle_iters * sizeof(cycles_t), | last_poll_cycles_start = kmalloc(cycle_iters * sizeof(cycles_t), | ||||
GFP_KERNEL); | GFP_KERNEL); | ||||
if (!last_poll_cycles_start) { | if (!last_poll_cycles_start) { | ||||
PRINTF(cb, "%s kmalloc failed\n", __FUNCTION__); | printk(KERN_ERR PFX "%s kmalloc failed\n", __FUNCTION__); | ||||
return; | return; | ||||
} | } | ||||
cb->rdma_sq_wr.opcode = IB_WR_RDMA_WRITE; | cb->rdma_sq_wr.wr.opcode = IB_WR_RDMA_WRITE; | ||||
cb->rdma_sq_wr.wr.rdma.rkey = cb->remote_rkey; | cb->rdma_sq_wr.rkey = cb->remote_rkey; | ||||
cb->rdma_sq_wr.wr.rdma.remote_addr = cb->remote_addr; | cb->rdma_sq_wr.remote_addr = cb->remote_addr; | ||||
cb->rdma_sq_wr.sg_list->length = cb->size; | cb->rdma_sq_wr.wr.sg_list->length = cb->size; | ||||
if (cycle_iters > iters) | if (cycle_iters > iters) | ||||
cycle_iters = iters; | cycle_iters = iters; | ||||
microtime(&start_tv); | microtime(&start_tv); | ||||
while (scnt < iters || ccnt < iters) { | while (scnt < iters || ccnt < iters) { | ||||
while (scnt < iters && scnt - ccnt < cb->txdepth) { | while (scnt < iters && scnt - ccnt < cb->txdepth) { | ||||
struct ib_send_wr *bad_wr; | struct ib_send_wr *bad_wr; | ||||
if (scnt < cycle_iters) | if (scnt < cycle_iters) | ||||
post_cycles_start[scnt] = get_cycles(); | post_cycles_start[scnt] = get_cycles(); | ||||
if (ib_post_send(cb->qp, &cb->rdma_sq_wr, &bad_wr)) { | if (ib_post_send(cb->qp, &cb->rdma_sq_wr.wr, &bad_wr)) { | ||||
PRINTF(cb, | printk(KERN_ERR PFX | ||||
"Couldn't post send: scnt=%d\n", | "Couldn't post send: scnt=%d\n", | ||||
scnt); | scnt); | ||||
return; | return; | ||||
} | } | ||||
if (scnt < cycle_iters) | if (scnt < cycle_iters) | ||||
post_cycles_stop[scnt] = get_cycles(); | post_cycles_stop[scnt] = get_cycles(); | ||||
++scnt; | ++scnt; | ||||
} | } | ||||
Show All 10 Lines | if (ccnt < iters) { | ||||
get_cycles(); | get_cycles(); | ||||
ne = ib_poll_cq(cb->cq, 1, &wc); | ne = ib_poll_cq(cb->cq, 1, &wc); | ||||
} while (ne == 0); | } while (ne == 0); | ||||
if (ccnt < cycle_iters) | if (ccnt < cycle_iters) | ||||
poll_cycles_stop[ccnt] = get_cycles(); | poll_cycles_stop[ccnt] = get_cycles(); | ||||
ccnt += 1; | ccnt += 1; | ||||
if (ne < 0) { | if (ne < 0) { | ||||
PRINTF(cb, "poll CQ failed %d\n", ne); | printk(KERN_ERR PFX "poll CQ failed %d\n", ne); | ||||
return; | return; | ||||
} | } | ||||
if (wc.status != IB_WC_SUCCESS) { | if (wc.status != IB_WC_SUCCESS) { | ||||
PRINTF(cb, | printk(KERN_ERR PFX | ||||
"Completion wth error at %s:\n", | "Completion wth error at %s:\n", | ||||
cb->server ? "server" : "client"); | cb->server ? "server" : "client"); | ||||
PRINTF(cb, | printk(KERN_ERR PFX | ||||
"Failed status %d: wr_id %d\n", | "Failed status %d: wr_id %d\n", | ||||
wc.status, (int) wc.wr_id); | wc.status, (int) wc.wr_id); | ||||
return; | return; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
microtime(&stop_tv); | microtime(&stop_tv); | ||||
if (stop_tv.tv_usec < start_tv.tv_usec) { | if (stop_tv.tv_usec < start_tv.tv_usec) { | ||||
stop_tv.tv_usec += 1000000; | stop_tv.tv_usec += 1000000; | ||||
stop_tv.tv_sec -= 1; | stop_tv.tv_sec -= 1; | ||||
} | } | ||||
for (i=0; i < cycle_iters; i++) { | for (i=0; i < cycle_iters; i++) { | ||||
sum_post += post_cycles_stop[i] - post_cycles_start[i]; | sum_post += post_cycles_stop[i] - post_cycles_start[i]; | ||||
sum_poll += poll_cycles_stop[i] - poll_cycles_start[i]; | sum_poll += poll_cycles_stop[i] - poll_cycles_start[i]; | ||||
sum_last_poll += poll_cycles_stop[i]-last_poll_cycles_start[i]; | sum_last_poll += poll_cycles_stop[i]-last_poll_cycles_start[i]; | ||||
} | } | ||||
PRINTF(cb, | printk(KERN_ERR PFX | ||||
"delta sec %lu delta usec %lu iter %d size %d cycle_iters %d" | "delta sec %lu delta usec %lu iter %d size %d cycle_iters %d" | ||||
" sum_post %llu sum_poll %llu sum_last_poll %llu\n", | " sum_post %llu sum_poll %llu sum_last_poll %llu\n", | ||||
(unsigned long)(stop_tv.tv_sec - start_tv.tv_sec), | (unsigned long)(stop_tv.tv_sec - start_tv.tv_sec), | ||||
(unsigned long)(stop_tv.tv_usec - start_tv.tv_usec), | (unsigned long)(stop_tv.tv_usec - start_tv.tv_usec), | ||||
scnt, cb->size, cycle_iters, | scnt, cb->size, cycle_iters, | ||||
(unsigned long long)sum_post, (unsigned long long)sum_poll, | (unsigned long long)sum_post, (unsigned long long)sum_poll, | ||||
(unsigned long long)sum_last_poll); | (unsigned long long)sum_last_poll); | ||||
kfree(post_cycles_start); | kfree(post_cycles_start); | ||||
Show All 13 Lines | static void krping_rlat_test_server(struct krping_cb *cb) | ||||
while (cb->state < RDMA_READ_ADV) { | while (cb->state < RDMA_READ_ADV) { | ||||
krping_cq_event_handler(cb->cq, cb); | krping_cq_event_handler(cb->cq, cb); | ||||
} | } | ||||
/* Send STAG/TO/Len to client */ | /* Send STAG/TO/Len to client */ | ||||
krping_format_send(cb, cb->start_dma_addr); | krping_format_send(cb, cb->start_dma_addr); | ||||
ret = ib_post_send(cb->qp, &cb->sq_wr, &bad_wr); | ret = ib_post_send(cb->qp, &cb->sq_wr, &bad_wr); | ||||
if (ret) { | if (ret) { | ||||
PRINTF(cb, "post send error %d\n", ret); | printk(KERN_ERR PFX "post send error %d\n", ret); | ||||
return; | return; | ||||
} | } | ||||
/* Spin waiting for send completion */ | /* Spin waiting for send completion */ | ||||
while ((ret = ib_poll_cq(cb->cq, 1, &wc) == 0)); | while ((ret = ib_poll_cq(cb->cq, 1, &wc) == 0)); | ||||
if (ret < 0) { | if (ret < 0) { | ||||
PRINTF(cb, "poll error %d\n", ret); | printk(KERN_ERR PFX "poll error %d\n", ret); | ||||
return; | return; | ||||
} | } | ||||
if (wc.status) { | if (wc.status) { | ||||
PRINTF(cb, "send completiong error %d\n", wc.status); | printk(KERN_ERR PFX "send completiong error %d\n", wc.status); | ||||
return; | return; | ||||
} | } | ||||
wait_event_interruptible(cb->sem, cb->state == ERROR); | wait_event_interruptible(cb->sem, cb->state == ERROR); | ||||
} | } | ||||
static void krping_wlat_test_server(struct krping_cb *cb) | static void krping_wlat_test_server(struct krping_cb *cb) | ||||
{ | { | ||||
struct ib_send_wr *bad_wr; | struct ib_send_wr *bad_wr; | ||||
struct ib_wc wc; | struct ib_wc wc; | ||||
int ret; | int ret; | ||||
/* Spin waiting for client's Start STAG/TO/Len */ | /* Spin waiting for client's Start STAG/TO/Len */ | ||||
while (cb->state < RDMA_READ_ADV) { | while (cb->state < RDMA_READ_ADV) { | ||||
krping_cq_event_handler(cb->cq, cb); | krping_cq_event_handler(cb->cq, cb); | ||||
} | } | ||||
/* Send STAG/TO/Len to client */ | /* Send STAG/TO/Len to client */ | ||||
krping_format_send(cb, cb->start_dma_addr); | krping_format_send(cb, cb->start_dma_addr); | ||||
ret = ib_post_send(cb->qp, &cb->sq_wr, &bad_wr); | ret = ib_post_send(cb->qp, &cb->sq_wr, &bad_wr); | ||||
if (ret) { | if (ret) { | ||||
PRINTF(cb, "post send error %d\n", ret); | printk(KERN_ERR PFX "post send error %d\n", ret); | ||||
return; | return; | ||||
} | } | ||||
/* Spin waiting for send completion */ | /* Spin waiting for send completion */ | ||||
while ((ret = ib_poll_cq(cb->cq, 1, &wc) == 0)); | while ((ret = ib_poll_cq(cb->cq, 1, &wc) == 0)); | ||||
if (ret < 0) { | if (ret < 0) { | ||||
PRINTF(cb, "poll error %d\n", ret); | printk(KERN_ERR PFX "poll error %d\n", ret); | ||||
return; | return; | ||||
} | } | ||||
if (wc.status) { | if (wc.status) { | ||||
PRINTF(cb, "send completiong error %d\n", wc.status); | printk(KERN_ERR PFX "send completiong error %d\n", wc.status); | ||||
return; | return; | ||||
} | } | ||||
wlat_test(cb); | wlat_test(cb); | ||||
wait_event_interruptible(cb->sem, cb->state == ERROR); | wait_event_interruptible(cb->sem, cb->state == ERROR); | ||||
} | } | ||||
static void krping_bw_test_server(struct krping_cb *cb) | static void krping_bw_test_server(struct krping_cb *cb) | ||||
{ | { | ||||
struct ib_send_wr *bad_wr; | struct ib_send_wr *bad_wr; | ||||
struct ib_wc wc; | struct ib_wc wc; | ||||
int ret; | int ret; | ||||
/* Spin waiting for client's Start STAG/TO/Len */ | /* Spin waiting for client's Start STAG/TO/Len */ | ||||
while (cb->state < RDMA_READ_ADV) { | while (cb->state < RDMA_READ_ADV) { | ||||
krping_cq_event_handler(cb->cq, cb); | krping_cq_event_handler(cb->cq, cb); | ||||
} | } | ||||
/* Send STAG/TO/Len to client */ | /* Send STAG/TO/Len to client */ | ||||
krping_format_send(cb, cb->start_dma_addr); | krping_format_send(cb, cb->start_dma_addr); | ||||
ret = ib_post_send(cb->qp, &cb->sq_wr, &bad_wr); | ret = ib_post_send(cb->qp, &cb->sq_wr, &bad_wr); | ||||
if (ret) { | if (ret) { | ||||
PRINTF(cb, "post send error %d\n", ret); | printk(KERN_ERR PFX "post send error %d\n", ret); | ||||
return; | return; | ||||
} | } | ||||
/* Spin waiting for send completion */ | /* Spin waiting for send completion */ | ||||
while ((ret = ib_poll_cq(cb->cq, 1, &wc) == 0)); | while ((ret = ib_poll_cq(cb->cq, 1, &wc) == 0)); | ||||
if (ret < 0) { | if (ret < 0) { | ||||
PRINTF(cb, "poll error %d\n", ret); | printk(KERN_ERR PFX "poll error %d\n", ret); | ||||
return; | return; | ||||
} | } | ||||
if (wc.status) { | if (wc.status) { | ||||
PRINTF(cb, "send completiong error %d\n", wc.status); | printk(KERN_ERR PFX "send completiong error %d\n", wc.status); | ||||
return; | return; | ||||
} | } | ||||
if (cb->duplex) | if (cb->duplex) | ||||
bw_test(cb); | bw_test(cb); | ||||
wait_event_interruptible(cb->sem, cb->state == ERROR); | wait_event_interruptible(cb->sem, cb->state == ERROR); | ||||
} | } | ||||
static int fastreg_supported(struct krping_cb *cb, int server) | static int reg_supported(struct ib_device *dev) | ||||
{ | { | ||||
struct ib_device *dev = server?cb->child_cm_id->device: | u64 needed_flags = IB_DEVICE_MEM_MGT_EXTENSIONS; | ||||
cb->cm_id->device; | |||||
struct ib_device_attr attr; | |||||
int ret; | |||||
ret = ib_query_device(dev, &attr); | if ((dev->attrs.device_cap_flags & needed_flags) != needed_flags) { | ||||
if (ret) { | printk(KERN_ERR PFX | ||||
PRINTF(cb, "ib_query_device failed ret %d\n", ret); | "Fastreg not supported - device_cap_flags 0x%llx\n", | ||||
(unsigned long long)dev->attrs.device_cap_flags); | |||||
return 0; | return 0; | ||||
} | } | ||||
if (!(attr.device_cap_flags & IB_DEVICE_MEM_MGT_EXTENSIONS)) { | DEBUG_LOG("Fastreg supported - device_cap_flags 0x%llx\n", | ||||
PRINTF(cb, "Fastreg not supported - device_cap_flags 0x%llx\n", | (unsigned long long)dev->attrs.device_cap_flags); | ||||
(unsigned long long)attr.device_cap_flags); | |||||
return 0; | |||||
} | |||||
DEBUG_LOG(cb, "Fastreg supported - device_cap_flags 0x%jx\n", | |||||
(uintmax_t)attr.device_cap_flags); | |||||
return 1; | return 1; | ||||
} | } | ||||
static void fill_sockaddr(struct sockaddr_storage *sin, struct krping_cb *cb) | |||||
{ | |||||
memset(sin, 0, sizeof(*sin)); | |||||
if (cb->addr_type == AF_INET) { | |||||
struct sockaddr_in *sin4 = (struct sockaddr_in *)sin; | |||||
sin4->sin_family = AF_INET; | |||||
memcpy((void *)&sin4->sin_addr.s_addr, cb->addr, 4); | |||||
sin4->sin_port = cb->port; | |||||
} else if (cb->addr_type == AF_INET6) { | |||||
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sin; | |||||
sin6->sin6_family = AF_INET6; | |||||
memcpy((void *)&sin6->sin6_addr, cb->addr, 16); | |||||
sin6->sin6_port = cb->port; | |||||
} | |||||
} | |||||
static int krping_bind_server(struct krping_cb *cb) | static int krping_bind_server(struct krping_cb *cb) | ||||
{ | { | ||||
struct sockaddr_in sin; | struct sockaddr_storage sin; | ||||
int ret; | int ret; | ||||
memset(&sin, 0, sizeof(sin)); | |||||
sin.sin_len = sizeof sin; | |||||
sin.sin_family = AF_INET; | |||||
sin.sin_addr.s_addr = cb->addr.s_addr; | |||||
sin.sin_port = cb->port; | |||||
fill_sockaddr(&sin, cb); | |||||
ret = rdma_bind_addr(cb->cm_id, (struct sockaddr *) &sin); | ret = rdma_bind_addr(cb->cm_id, (struct sockaddr *)&sin); | ||||
if (ret) { | if (ret) { | ||||
PRINTF(cb, "rdma_bind_addr error %d\n", ret); | printk(KERN_ERR PFX "rdma_bind_addr error %d\n", ret); | ||||
return ret; | return ret; | ||||
} | } | ||||
DEBUG_LOG(cb, "rdma_bind_addr successful\n"); | DEBUG_LOG("rdma_bind_addr successful\n"); | ||||
DEBUG_LOG(cb, "rdma_listen\n"); | DEBUG_LOG("rdma_listen\n"); | ||||
ret = rdma_listen(cb->cm_id, 3); | ret = rdma_listen(cb->cm_id, 3); | ||||
if (ret) { | if (ret) { | ||||
PRINTF(cb, "rdma_listen failed: %d\n", ret); | printk(KERN_ERR PFX "rdma_listen failed: %d\n", ret); | ||||
return ret; | return ret; | ||||
} | } | ||||
wait_event_interruptible(cb->sem, cb->state >= CONNECT_REQUEST); | wait_event_interruptible(cb->sem, cb->state >= CONNECT_REQUEST); | ||||
if (cb->state != CONNECT_REQUEST) { | if (cb->state != CONNECT_REQUEST) { | ||||
PRINTF(cb, "wait for CONNECT_REQUEST state %d\n", | printk(KERN_ERR PFX "wait for CONNECT_REQUEST state %d\n", | ||||
cb->state); | cb->state); | ||||
return -1; | return -1; | ||||
} | } | ||||
if (cb->mem == FASTREG && !fastreg_supported(cb, 1)) | if (!reg_supported(cb->child_cm_id->device)) | ||||
return -EINVAL; | return -EINVAL; | ||||
return 0; | return 0; | ||||
} | } | ||||
/* | |||||
* sq-depth worth of fastreg + 0B read-inv pairs, reposting them as the reads | |||||
* complete. | |||||
* NOTE: every 9 seconds we sleep for 1 second to keep the kernel happy. | |||||
*/ | |||||
static void krping_fr_test5(struct krping_cb *cb) | |||||
{ | |||||
struct ib_fast_reg_page_list **pl; | |||||
struct ib_send_wr *fr, *read, *bad; | |||||
struct ib_wc wc; | |||||
struct ib_sge *sgl; | |||||
u8 key = 0; | |||||
struct ib_mr **mr; | |||||
u8 **buf; | |||||
dma_addr_t *dma_addr; | |||||
int i; | |||||
int ret; | |||||
int plen = (((cb->size - 1) & PAGE_MASK) + PAGE_SIZE) >> PAGE_SHIFT; | |||||
time_t start; | |||||
int count = 0; | |||||
int scnt; | |||||
int depth = cb->txdepth >> 1; | |||||
if (!depth) { | |||||
PRINTF(cb, "txdepth must be > 1 for this test!\n"); | |||||
return; | |||||
} | |||||
pl = kzalloc(sizeof *pl * depth, GFP_KERNEL); | |||||
DEBUG_LOG(cb, "%s pl %p size %zu\n", __func__, pl, sizeof *pl * depth); | |||||
mr = kzalloc(sizeof *mr * depth, GFP_KERNEL); | |||||
DEBUG_LOG(cb, "%s mr %p size %zu\n", __func__, mr, sizeof *mr * depth); | |||||
fr = kzalloc(sizeof *fr * depth, GFP_KERNEL); | |||||
DEBUG_LOG(cb, "%s fr %p size %zu\n", __func__, fr, sizeof *fr * depth); | |||||
sgl = kzalloc(sizeof *sgl * depth, GFP_KERNEL); | |||||
DEBUG_LOG(cb, "%s sgl %p size %zu\n", __func__, sgl, sizeof *sgl * depth); | |||||
read = kzalloc(sizeof *read * depth, GFP_KERNEL); | |||||
DEBUG_LOG(cb, "%s read %p size %zu\n", __func__, read, sizeof *read * depth); | |||||
buf = kzalloc(sizeof *buf * depth, GFP_KERNEL); | |||||
DEBUG_LOG(cb, "%s buf %p size %zu\n", __func__, buf, sizeof *buf * depth); | |||||
dma_addr = kzalloc(sizeof *dma_addr * depth, GFP_KERNEL); | |||||
DEBUG_LOG(cb, "%s dma_addr %p size %zu\n", __func__, dma_addr, sizeof *dma_addr * depth); | |||||
if (!pl || !mr || !fr || !read || !sgl || !buf || !dma_addr) { | |||||
PRINTF(cb, "kzalloc failed\n"); | |||||
goto err1; | |||||
} | |||||
for (scnt = 0; scnt < depth; scnt++) { | |||||
pl[scnt] = ib_alloc_fast_reg_page_list(cb->qp->device, plen); | |||||
if (IS_ERR(pl[scnt])) { | |||||
PRINTF(cb, "alloc_fr_page_list failed %ld\n", | |||||
PTR_ERR(pl[scnt])); | |||||
goto err2; | |||||
} | |||||
DEBUG_LOG(cb, "%s pl[%u] %p\n", __func__, scnt, pl[scnt]); | |||||
mr[scnt] = ib_alloc_fast_reg_mr(cb->pd, plen); | |||||
if (IS_ERR(mr[scnt])) { | |||||
PRINTF(cb, "alloc_fr failed %ld\n", | |||||
PTR_ERR(mr[scnt])); | |||||
goto err2; | |||||
} | |||||
DEBUG_LOG(cb, "%s mr[%u] %p\n", __func__, scnt, mr[scnt]); | |||||
ib_update_fast_reg_key(mr[scnt], ++key); | |||||
buf[scnt] = kmalloc(cb->size, GFP_KERNEL); | |||||
if (!buf[scnt]) { | |||||
PRINTF(cb, "kmalloc failed\n"); | |||||
ret = -ENOMEM; | |||||
goto err2; | |||||
} | |||||
DEBUG_LOG(cb, "%s buf[%u] %p\n", __func__, scnt, buf[scnt]); | |||||
dma_addr[scnt] = ib_dma_map_single(cb->pd->device, | |||||
buf[scnt], cb->size, | |||||
DMA_BIDIRECTIONAL); | |||||
if (dma_mapping_error(cb->pd->device->dma_device, | |||||
dma_addr[scnt])) { | |||||
PRINTF(cb, "dma_map failed\n"); | |||||
ret = -ENOMEM; | |||||
goto err2; | |||||
} | |||||
DEBUG_LOG(cb, "%s dma_addr[%u] %p\n", __func__, scnt, (void *)dma_addr[scnt]); | |||||
for (i=0; i<plen; i++) { | |||||
pl[scnt]->page_list[i] = ((unsigned long)dma_addr[scnt] & PAGE_MASK) + (i * PAGE_SIZE); | |||||
DEBUG_LOG(cb, "%s pl[%u]->page_list[%u] 0x%jx\n", | |||||
__func__, scnt, i, (uintmax_t)pl[scnt]->page_list[i]); | |||||
} | |||||
sgl[scnt].lkey = mr[scnt]->rkey; | |||||
sgl[scnt].length = cb->size; | |||||
sgl[scnt].addr = (u64)buf[scnt]; | |||||
DEBUG_LOG(cb, "%s sgl[%u].lkey 0x%x length %u addr 0x%jx\n", | |||||
__func__, scnt, sgl[scnt].lkey, sgl[scnt].length, | |||||
(uintmax_t)sgl[scnt].addr); | |||||
fr[scnt].opcode = IB_WR_FAST_REG_MR; | |||||
fr[scnt].wr_id = scnt; | |||||
fr[scnt].send_flags = 0; | |||||
fr[scnt].wr.fast_reg.page_shift = PAGE_SHIFT; | |||||
fr[scnt].wr.fast_reg.length = cb->size; | |||||
fr[scnt].wr.fast_reg.page_list = pl[scnt]; | |||||
fr[scnt].wr.fast_reg.page_list_len = plen; | |||||
fr[scnt].wr.fast_reg.iova_start = (u64)buf[scnt]; | |||||
fr[scnt].wr.fast_reg.access_flags = IB_ACCESS_REMOTE_WRITE | IB_ACCESS_LOCAL_WRITE; | |||||
fr[scnt].wr.fast_reg.rkey = mr[scnt]->rkey; | |||||
fr[scnt].next = &read[scnt]; | |||||
read[scnt].opcode = IB_WR_RDMA_READ_WITH_INV; | |||||
read[scnt].wr_id = scnt; | |||||
read[scnt].send_flags = IB_SEND_SIGNALED; | |||||
read[scnt].wr.rdma.rkey = cb->remote_rkey; | |||||
read[scnt].wr.rdma.remote_addr = cb->remote_addr; | |||||
read[scnt].num_sge = 1; | |||||
read[scnt].sg_list = &sgl[scnt]; | |||||
ret = ib_post_send(cb->qp, &fr[scnt], &bad); | |||||
if (ret) { | |||||
PRINTF(cb, "ib_post_send failed %d\n", ret); | |||||
goto err2; | |||||
} | |||||
} | |||||
start = time_uptime; | |||||
DEBUG_LOG(cb, "%s starting IO.\n", __func__); | |||||
while (!cb->count || cb->server || count < cb->count) { | |||||
if ((time_uptime - start) >= 9) { | |||||
DEBUG_LOG(cb, "%s pausing 1 tick! count %u\n", __func__, | |||||
count); | |||||
wait_event_interruptible_timeout(cb->sem, | |||||
cb->state == ERROR, | |||||
1); | |||||
if (cb->state == ERROR) | |||||
break; | |||||
start = time_uptime; | |||||
} | |||||
do { | |||||
ret = ib_poll_cq(cb->cq, 1, &wc); | |||||
if (ret < 0) { | |||||
PRINTF(cb, "ib_poll_cq failed %d\n", | |||||
ret); | |||||
goto err2; | |||||
} | |||||
if (ret == 1) { | |||||
if (wc.status) { | |||||
PRINTF(cb, | |||||
"completion error %u wr_id %ju " | |||||
"opcode %d\n", wc.status, | |||||
(uintmax_t)wc.wr_id, wc.opcode); | |||||
goto err2; | |||||
} | |||||
count++; | |||||
if (count == cb->count) | |||||
break; | |||||
ib_update_fast_reg_key(mr[wc.wr_id], ++key); | |||||
fr[wc.wr_id].wr.fast_reg.rkey = | |||||
mr[wc.wr_id]->rkey; | |||||
sgl[wc.wr_id].lkey = mr[wc.wr_id]->rkey; | |||||
ret = ib_post_send(cb->qp, &fr[wc.wr_id], &bad); | |||||
if (ret) { | |||||
PRINTF(cb, | |||||
"ib_post_send failed %d\n", ret); | |||||
goto err2; | |||||
} | |||||
} else if (krping_sigpending()) { | |||||
PRINTF(cb, "signal!\n"); | |||||
goto err2; | |||||
} | |||||
} while (ret == 1); | |||||
} | |||||
DEBUG_LOG(cb, "%s done!\n", __func__); | |||||
err2: | |||||
DEBUG_LOG(cb, "sleeping 1 second\n"); | |||||
wait_event_interruptible_timeout(cb->sem, cb->state == ERROR, HZ); | |||||
DEBUG_LOG(cb, "draining the cq...\n"); | |||||
do { | |||||
ret = ib_poll_cq(cb->cq, 1, &wc); | |||||
if (ret < 0) { | |||||
PRINTF(cb, "ib_poll_cq failed %d\n", ret); | |||||
break; | |||||
} | |||||
if (ret == 1) { | |||||
if (wc.status) { | |||||
PRINTF(cb, "completion error %u " | |||||
"opcode %u\n", wc.status, wc.opcode); | |||||
} | |||||
} | |||||
} while (ret == 1); | |||||
DEBUG_LOG(cb, "destroying fr mrs!\n"); | |||||
for (scnt = 0; scnt < depth; scnt++) { | |||||
if (mr[scnt]) { | |||||
ib_dereg_mr(mr[scnt]); | |||||
DEBUG_LOG(cb, "%s dereg mr %p\n", __func__, mr[scnt]); | |||||
} | |||||
} | |||||
DEBUG_LOG(cb, "unmapping/freeing bufs!\n"); | |||||
for (scnt = 0; scnt < depth; scnt++) { | |||||
if (buf[scnt]) { | |||||
dma_unmap_single(cb->pd->device->dma_device, | |||||
dma_addr[scnt], cb->size, | |||||
DMA_BIDIRECTIONAL); | |||||
kfree(buf[scnt]); | |||||
DEBUG_LOG(cb, "%s unmap/free buf %p dma_addr %p\n", __func__, buf[scnt], (void *)dma_addr[scnt]); | |||||
} | |||||
} | |||||
DEBUG_LOG(cb, "destroying fr page lists!\n"); | |||||
for (scnt = 0; scnt < depth; scnt++) { | |||||
if (pl[scnt]) { | |||||
DEBUG_LOG(cb, "%s free pl %p\n", __func__, pl[scnt]); | |||||
ib_free_fast_reg_page_list(pl[scnt]); | |||||
} | |||||
} | |||||
err1: | |||||
if (pl) | |||||
kfree(pl); | |||||
if (mr) | |||||
kfree(mr); | |||||
if (fr) | |||||
kfree(fr); | |||||
if (read) | |||||
kfree(read); | |||||
if (sgl) | |||||
kfree(sgl); | |||||
if (buf) | |||||
kfree(buf); | |||||
if (dma_addr) | |||||
kfree(dma_addr); | |||||
} | |||||
static void krping_fr_test_server(struct krping_cb *cb) | |||||
{ | |||||
DEBUG_LOG(cb, "%s waiting for disconnect...\n", __func__); | |||||
wait_event_interruptible(cb->sem, cb->state == ERROR); | |||||
} | |||||
static void krping_fr_test5_server(struct krping_cb *cb) | |||||
{ | |||||
struct ib_send_wr *bad_wr; | |||||
struct ib_wc wc; | |||||
int ret; | |||||
/* Spin waiting for client's Start STAG/TO/Len */ | |||||
while (cb->state < RDMA_READ_ADV) { | |||||
krping_cq_event_handler(cb->cq, cb); | |||||
} | |||||
DEBUG_LOG(cb, "%s client STAG %x TO 0x%jx\n", __func__, | |||||
cb->remote_rkey, (uintmax_t)cb->remote_addr); | |||||
/* Send STAG/TO/Len to client */ | |||||
krping_format_send(cb, cb->start_dma_addr); | |||||
ret = ib_post_send(cb->qp, &cb->sq_wr, &bad_wr); | |||||
if (ret) { | |||||
PRINTF(cb, "post send error %d\n", ret); | |||||
return; | |||||
} | |||||
/* Spin waiting for send completion */ | |||||
while ((ret = ib_poll_cq(cb->cq, 1, &wc) == 0)); | |||||
if (ret < 0) { | |||||
PRINTF(cb, "poll error %d\n", ret); | |||||
return; | |||||
} | |||||
if (wc.status) { | |||||
PRINTF(cb, "send completiong error %d\n", wc.status); | |||||
return; | |||||
} | |||||
if (cb->duplex) | |||||
krping_fr_test5(cb); | |||||
DEBUG_LOG(cb, "%s waiting for disconnect...\n", __func__); | |||||
wait_event_interruptible(cb->sem, cb->state == ERROR); | |||||
} | |||||
static void krping_fr_test5_client(struct krping_cb *cb) | |||||
{ | |||||
struct ib_send_wr *bad; | |||||
struct ib_wc wc; | |||||
int ret; | |||||
cb->state = RDMA_READ_ADV; | |||||
/* Send STAG/TO/Len to server */ | |||||
krping_format_send(cb, cb->start_dma_addr); | |||||
if (cb->state == ERROR) { | |||||
PRINTF(cb, "krping_format_send failed\n"); | |||||
return; | |||||
} | |||||
ret = ib_post_send(cb->qp, &cb->sq_wr, &bad); | |||||
if (ret) { | |||||
PRINTF(cb, "post send error %d\n", ret); | |||||
return; | |||||
} | |||||
/* Spin waiting for send completion */ | |||||
while ((ret = ib_poll_cq(cb->cq, 1, &wc) == 0)); | |||||
if (ret < 0) { | |||||
PRINTF(cb, "poll error %d\n", ret); | |||||
return; | |||||
} | |||||
if (wc.status) { | |||||
PRINTF(cb, "send completion error %d\n", wc.status); | |||||
return; | |||||
} | |||||
/* Spin waiting for server's Start STAG/TO/Len */ | |||||
while (cb->state < RDMA_WRITE_ADV) { | |||||
krping_cq_event_handler(cb->cq, cb); | |||||
} | |||||
DEBUG_LOG(cb, "%s server STAG %x TO 0x%jx\n", __func__, cb->remote_rkey, | |||||
(uintmax_t)cb->remote_addr); | |||||
return krping_fr_test5(cb); | |||||
} | |||||
/* | |||||
* sq-depth worth of write + fastreg + inv, reposting them as the invs | |||||
* complete. | |||||
* NOTE: every 9 seconds we sleep for 1 second to keep the kernel happy. | |||||
* If a count is given, then the last IO will have a bogus lkey in the | |||||
* write work request. This reproduces a fw bug where the connection | |||||
* will get stuck if a fastreg is processed while the ulptx is failing | |||||
* the bad write. | |||||
*/ | |||||
static void krping_fr_test6(struct krping_cb *cb) | |||||
{ | |||||
struct ib_fast_reg_page_list **pl; | |||||
struct ib_send_wr *fr, *write, *inv, *bad; | |||||
struct ib_wc wc; | |||||
struct ib_sge *sgl; | |||||
u8 key = 0; | |||||
struct ib_mr **mr; | |||||
u8 **buf; | |||||
dma_addr_t *dma_addr; | |||||
int i; | |||||
int ret; | |||||
int plen = (((cb->size - 1) & PAGE_MASK) + PAGE_SIZE) >> PAGE_SHIFT; | |||||
unsigned long start; | |||||
int count = 0; | |||||
int scnt; | |||||
int depth = cb->txdepth / 3; | |||||
if (!depth) { | |||||
PRINTF(cb, "txdepth must be > 3 for this test!\n"); | |||||
return; | |||||
} | |||||
pl = kzalloc(sizeof *pl * depth, GFP_KERNEL); | |||||
DEBUG_LOG(cb, "%s pl %p size %zu\n", __func__, pl, sizeof *pl * depth); | |||||
mr = kzalloc(sizeof *mr * depth, GFP_KERNEL); | |||||
DEBUG_LOG(cb, "%s mr %p size %zu\n", __func__, mr, sizeof *mr * depth); | |||||
fr = kzalloc(sizeof *fr * depth, GFP_KERNEL); | |||||
DEBUG_LOG(cb, "%s fr %p size %zu\n", __func__, fr, sizeof *fr * depth); | |||||
sgl = kzalloc(sizeof *sgl * depth, GFP_KERNEL); | |||||
DEBUG_LOG(cb, "%s sgl %p size %zu\n", __func__, sgl, sizeof *sgl * depth); | |||||
write = kzalloc(sizeof *write * depth, GFP_KERNEL); | |||||
DEBUG_LOG(cb, "%s read %p size %zu\n", __func__, write, sizeof *write * depth); | |||||
inv = kzalloc(sizeof *inv * depth, GFP_KERNEL); | |||||
DEBUG_LOG(cb, "%s inv %p size %zu\n", __func__, inv, sizeof *inv * depth); | |||||
buf = kzalloc(sizeof *buf * depth, GFP_KERNEL); | |||||
DEBUG_LOG(cb, "%s buf %p size %zu\n", __func__, buf, sizeof *buf * depth); | |||||
dma_addr = kzalloc(sizeof *dma_addr * depth, GFP_KERNEL); | |||||
DEBUG_LOG(cb, "%s dma_addr %p size %zu\n", __func__, dma_addr, sizeof *dma_addr * depth); | |||||
if (!pl || !mr || !fr || !write || !sgl || !buf || !dma_addr) { | |||||
PRINTF(cb, "kzalloc failed\n"); | |||||
goto err1; | |||||
} | |||||
for (scnt = 0; scnt < depth; scnt++) { | |||||
pl[scnt] = ib_alloc_fast_reg_page_list(cb->qp->device, plen); | |||||
if (IS_ERR(pl[scnt])) { | |||||
PRINTF(cb, "alloc_fr_page_list failed %ld\n", | |||||
PTR_ERR(pl[scnt])); | |||||
goto err2; | |||||
} | |||||
DEBUG_LOG(cb, "%s pl[%u] %p\n", __func__, scnt, pl[scnt]); | |||||
mr[scnt] = ib_alloc_fast_reg_mr(cb->pd, plen); | |||||
if (IS_ERR(mr[scnt])) { | |||||
PRINTF(cb, "alloc_fr failed %ld\n", | |||||
PTR_ERR(mr[scnt])); | |||||
goto err2; | |||||
} | |||||
DEBUG_LOG(cb, "%s mr[%u] %p\n", __func__, scnt, mr[scnt]); | |||||
ib_update_fast_reg_key(mr[scnt], ++key); | |||||
buf[scnt] = kmalloc(cb->size, GFP_KERNEL); | |||||
if (!buf[scnt]) { | |||||
PRINTF(cb, "kmalloc failed\n"); | |||||
ret = -ENOMEM; | |||||
goto err2; | |||||
} | |||||
DEBUG_LOG(cb, "%s buf[%u] %p\n", __func__, scnt, buf[scnt]); | |||||
dma_addr[scnt] = ib_dma_map_single(cb->pd->device, | |||||
buf[scnt], cb->size, | |||||
DMA_BIDIRECTIONAL); | |||||
if (dma_mapping_error(cb->pd->device->dma_device, | |||||
dma_addr[scnt])) { | |||||
PRINTF(cb, "dma_map failed\n"); | |||||
ret = -ENOMEM; | |||||
goto err2; | |||||
} | |||||
DEBUG_LOG(cb, "%s dma_addr[%u] %p\n", __func__, scnt, (void *)dma_addr[scnt]); | |||||
for (i=0; i<plen; i++) { | |||||
pl[scnt]->page_list[i] = ((unsigned long)dma_addr[scnt] & PAGE_MASK) + (i * PAGE_SIZE); | |||||
DEBUG_LOG(cb, "%s pl[%u]->page_list[%u] 0x%jx\n", | |||||
__func__, scnt, i, (uintmax_t)pl[scnt]->page_list[i]); | |||||
} | |||||
write[scnt].opcode = IB_WR_RDMA_WRITE; | |||||
write[scnt].wr_id = scnt; | |||||
write[scnt].wr.rdma.rkey = cb->remote_rkey; | |||||
write[scnt].wr.rdma.remote_addr = cb->remote_addr; | |||||
write[scnt].num_sge = 1; | |||||
write[scnt].sg_list = &cb->rdma_sgl; | |||||
write[scnt].sg_list->length = cb->size; | |||||
write[scnt].next = &fr[scnt]; | |||||
fr[scnt].opcode = IB_WR_FAST_REG_MR; | |||||
fr[scnt].wr_id = scnt; | |||||
fr[scnt].wr.fast_reg.page_shift = PAGE_SHIFT; | |||||
fr[scnt].wr.fast_reg.length = cb->size; | |||||
fr[scnt].wr.fast_reg.page_list = pl[scnt]; | |||||
fr[scnt].wr.fast_reg.page_list_len = plen; | |||||
fr[scnt].wr.fast_reg.iova_start = (u64)buf[scnt]; | |||||
fr[scnt].wr.fast_reg.access_flags = IB_ACCESS_REMOTE_WRITE | IB_ACCESS_LOCAL_WRITE; | |||||
fr[scnt].wr.fast_reg.rkey = mr[scnt]->rkey; | |||||
fr[scnt].next = &inv[scnt]; | |||||
inv[scnt].opcode = IB_WR_LOCAL_INV; | |||||
inv[scnt].send_flags = IB_SEND_SIGNALED; | |||||
inv[scnt].ex.invalidate_rkey = mr[scnt]->rkey; | |||||
ret = ib_post_send(cb->qp, &write[scnt], &bad); | |||||
if (ret) { | |||||
PRINTF(cb, "ib_post_send failed %d\n", ret); | |||||
goto err2; | |||||
} | |||||
} | |||||
start = time_uptime; | |||||
DEBUG_LOG(cb, "%s starting IO.\n", __func__); | |||||
while (!cb->count || cb->server || count < cb->count) { | |||||
if ((time_uptime - start) >= 9) { | |||||
DEBUG_LOG(cb, "%s pausing 1 tick! count %u\n", __func__, | |||||
count); | |||||
wait_event_interruptible_timeout(cb->sem, | |||||
cb->state == ERROR, | |||||
1); | |||||
if (cb->state == ERROR) | |||||
break; | |||||
start = time_uptime; | |||||
} | |||||
do { | |||||
ret = ib_poll_cq(cb->cq, 1, &wc); | |||||
if (ret < 0) { | |||||
PRINTF(cb, "ib_poll_cq failed %d\n", | |||||
ret); | |||||
goto err2; | |||||
} | |||||
if (ret == 1) { | |||||
if (wc.status) { | |||||
PRINTF(cb, | |||||
"completion error %u wr_id %ju " | |||||
"opcode %d\n", wc.status, | |||||
(uintmax_t)wc.wr_id, wc.opcode); | |||||
goto err2; | |||||
} | |||||
count++; | |||||
if (count == (cb->count -1)) | |||||
cb->rdma_sgl.lkey = 0x00dead; | |||||
if (count == cb->count) | |||||
break; | |||||
ib_update_fast_reg_key(mr[wc.wr_id], ++key); | |||||
fr[wc.wr_id].wr.fast_reg.rkey = | |||||
mr[wc.wr_id]->rkey; | |||||
inv[wc.wr_id].ex.invalidate_rkey = | |||||
mr[wc.wr_id]->rkey; | |||||
ret = ib_post_send(cb->qp, &write[wc.wr_id], &bad); | |||||
if (ret) { | |||||
PRINTF(cb, | |||||
"ib_post_send failed %d\n", ret); | |||||
goto err2; | |||||
} | |||||
} else if (krping_sigpending()){ | |||||
PRINTF(cb, "signal!\n"); | |||||
goto err2; | |||||
} | |||||
} while (ret == 1); | |||||
} | |||||
DEBUG_LOG(cb, "%s done!\n", __func__); | |||||
err2: | |||||
DEBUG_LOG(cb, "sleeping 1 second\n"); | |||||
wait_event_interruptible_timeout(cb->sem, cb->state == ERROR, HZ); | |||||
DEBUG_LOG(cb, "draining the cq...\n"); | |||||
do { | |||||
ret = ib_poll_cq(cb->cq, 1, &wc); | |||||
if (ret < 0) { | |||||
PRINTF(cb, "ib_poll_cq failed %d\n", ret); | |||||
break; | |||||
} | |||||
if (ret == 1) { | |||||
if (wc.status) { | |||||
PRINTF(cb, "completion error %u " | |||||
"opcode %u\n", wc.status, wc.opcode); | |||||
} | |||||
} | |||||
} while (ret == 1); | |||||
DEBUG_LOG(cb, "destroying fr mrs!\n"); | |||||
for (scnt = 0; scnt < depth; scnt++) { | |||||
if (mr[scnt]) { | |||||
ib_dereg_mr(mr[scnt]); | |||||
DEBUG_LOG(cb, "%s dereg mr %p\n", __func__, mr[scnt]); | |||||
} | |||||
} | |||||
DEBUG_LOG(cb, "unmapping/freeing bufs!\n"); | |||||
for (scnt = 0; scnt < depth; scnt++) { | |||||
if (buf[scnt]) { | |||||
dma_unmap_single(cb->pd->device->dma_device, | |||||
dma_addr[scnt], cb->size, | |||||
DMA_BIDIRECTIONAL); | |||||
kfree(buf[scnt]); | |||||
DEBUG_LOG(cb, "%s unmap/free buf %p dma_addr %p\n", __func__, buf[scnt], (void *)dma_addr[scnt]); | |||||
} | |||||
} | |||||
DEBUG_LOG(cb, "destroying fr page lists!\n"); | |||||
for (scnt = 0; scnt < depth; scnt++) { | |||||
if (pl[scnt]) { | |||||
DEBUG_LOG(cb, "%s free pl %p\n", __func__, pl[scnt]); | |||||
ib_free_fast_reg_page_list(pl[scnt]); | |||||
} | |||||
} | |||||
err1: | |||||
if (pl) | |||||
kfree(pl); | |||||
if (mr) | |||||
kfree(mr); | |||||
if (fr) | |||||
kfree(fr); | |||||
if (write) | |||||
kfree(write); | |||||
if (inv) | |||||
kfree(inv); | |||||
if (sgl) | |||||
kfree(sgl); | |||||
if (buf) | |||||
kfree(buf); | |||||
if (dma_addr) | |||||
kfree(dma_addr); | |||||
} | |||||
static void krping_fr_test6_server(struct krping_cb *cb) | |||||
{ | |||||
struct ib_send_wr *bad_wr; | |||||
struct ib_wc wc; | |||||
int ret; | |||||
/* Spin waiting for client's Start STAG/TO/Len */ | |||||
while (cb->state < RDMA_READ_ADV) { | |||||
krping_cq_event_handler(cb->cq, cb); | |||||
} | |||||
DEBUG_LOG(cb, "%s client STAG %x TO 0x%jx\n", __func__, | |||||
cb->remote_rkey, (uintmax_t)cb->remote_addr); | |||||
/* Send STAG/TO/Len to client */ | |||||
krping_format_send(cb, cb->start_dma_addr); | |||||
ret = ib_post_send(cb->qp, &cb->sq_wr, &bad_wr); | |||||
if (ret) { | |||||
PRINTF(cb, "post send error %d\n", ret); | |||||
return; | |||||
} | |||||
/* Spin waiting for send completion */ | |||||
while ((ret = ib_poll_cq(cb->cq, 1, &wc) == 0)); | |||||
if (ret < 0) { | |||||
PRINTF(cb, "poll error %d\n", ret); | |||||
return; | |||||
} | |||||
if (wc.status) { | |||||
PRINTF(cb, "send completiong error %d\n", wc.status); | |||||
return; | |||||
} | |||||
if (cb->duplex) | |||||
krping_fr_test6(cb); | |||||
DEBUG_LOG(cb, "%s waiting for disconnect...\n", __func__); | |||||
wait_event_interruptible(cb->sem, cb->state == ERROR); | |||||
} | |||||
static void krping_fr_test6_client(struct krping_cb *cb) | |||||
{ | |||||
struct ib_send_wr *bad; | |||||
struct ib_wc wc; | |||||
int ret; | |||||
cb->state = RDMA_READ_ADV; | |||||
/* Send STAG/TO/Len to server */ | |||||
krping_format_send(cb, cb->start_dma_addr); | |||||
if (cb->state == ERROR) { | |||||
PRINTF(cb, "krping_format_send failed\n"); | |||||
return; | |||||
} | |||||
ret = ib_post_send(cb->qp, &cb->sq_wr, &bad); | |||||
if (ret) { | |||||
PRINTF(cb, "post send error %d\n", ret); | |||||
return; | |||||
} | |||||
/* Spin waiting for send completion */ | |||||
while ((ret = ib_poll_cq(cb->cq, 1, &wc) == 0)); | |||||
if (ret < 0) { | |||||
PRINTF(cb, "poll error %d\n", ret); | |||||
return; | |||||
} | |||||
if (wc.status) { | |||||
PRINTF(cb, "send completion error %d\n", wc.status); | |||||
return; | |||||
} | |||||
/* Spin waiting for server's Start STAG/TO/Len */ | |||||
while (cb->state < RDMA_WRITE_ADV) { | |||||
krping_cq_event_handler(cb->cq, cb); | |||||
} | |||||
DEBUG_LOG(cb, "%s server STAG %x TO 0x%jx\n", __func__, cb->remote_rkey, | |||||
(uintmax_t)cb->remote_addr); | |||||
return krping_fr_test6(cb); | |||||
} | |||||
static void krping_run_server(struct krping_cb *cb) | static void krping_run_server(struct krping_cb *cb) | ||||
{ | { | ||||
struct ib_recv_wr *bad_wr; | struct ib_recv_wr *bad_wr; | ||||
int ret; | int ret; | ||||
ret = krping_bind_server(cb); | ret = krping_bind_server(cb); | ||||
if (ret) | if (ret) | ||||
return; | return; | ||||
ret = krping_setup_qp(cb, cb->child_cm_id); | ret = krping_setup_qp(cb, cb->child_cm_id); | ||||
if (ret) { | if (ret) { | ||||
PRINTF(cb, "setup_qp failed: %d\n", ret); | printk(KERN_ERR PFX "setup_qp failed: %d\n", ret); | ||||
goto err0; | goto err0; | ||||
} | } | ||||
ret = krping_setup_buffers(cb); | ret = krping_setup_buffers(cb); | ||||
if (ret) { | if (ret) { | ||||
PRINTF(cb, "krping_setup_buffers failed: %d\n", ret); | printk(KERN_ERR PFX "krping_setup_buffers failed: %d\n", ret); | ||||
goto err1; | goto err1; | ||||
} | } | ||||
ret = ib_post_recv(cb->qp, &cb->rq_wr, &bad_wr); | ret = ib_post_recv(cb->qp, &cb->rq_wr, &bad_wr); | ||||
if (ret) { | if (ret) { | ||||
PRINTF(cb, "ib_post_recv failed: %d\n", ret); | printk(KERN_ERR PFX "ib_post_recv failed: %d\n", ret); | ||||
goto err2; | goto err2; | ||||
} | } | ||||
ret = krping_accept(cb); | ret = krping_accept(cb); | ||||
if (ret) { | if (ret) { | ||||
PRINTF(cb, "connect error %d\n", ret); | printk(KERN_ERR PFX "connect error %d\n", ret); | ||||
goto err2; | goto err2; | ||||
} | } | ||||
if (cb->wlat) | if (cb->wlat) | ||||
krping_wlat_test_server(cb); | krping_wlat_test_server(cb); | ||||
else if (cb->rlat) | else if (cb->rlat) | ||||
krping_rlat_test_server(cb); | krping_rlat_test_server(cb); | ||||
else if (cb->bw) | else if (cb->bw) | ||||
krping_bw_test_server(cb); | krping_bw_test_server(cb); | ||||
else if (cb->frtest) { | else | ||||
switch (cb->testnum) { | |||||
case 1: | |||||
case 2: | |||||
case 3: | |||||
case 4: | |||||
krping_fr_test_server(cb); | |||||
break; | |||||
case 5: | |||||
krping_fr_test5_server(cb); | |||||
break; | |||||
case 6: | |||||
krping_fr_test6_server(cb); | |||||
break; | |||||
default: | |||||
PRINTF(cb, "unknown fr test %d\n", cb->testnum); | |||||
goto err2; | |||||
break; | |||||
} | |||||
} else | |||||
krping_test_server(cb); | krping_test_server(cb); | ||||
rdma_disconnect(cb->child_cm_id); | rdma_disconnect(cb->child_cm_id); | ||||
err2: | err2: | ||||
krping_free_buffers(cb); | krping_free_buffers(cb); | ||||
err1: | err1: | ||||
krping_free_qp(cb); | krping_free_qp(cb); | ||||
err0: | err0: | ||||
rdma_destroy_id(cb->child_cm_id); | rdma_destroy_id(cb->child_cm_id); | ||||
Show All 19 Lines | for (ping = 0; !cb->count || ping < cb->count; ping++) { | ||||
} | } | ||||
start++; | start++; | ||||
if (start > 122) | if (start > 122) | ||||
start = 65; | start = 65; | ||||
cb->start_buf[cb->size - 1] = 0; | cb->start_buf[cb->size - 1] = 0; | ||||
krping_format_send(cb, cb->start_dma_addr); | krping_format_send(cb, cb->start_dma_addr); | ||||
if (cb->state == ERROR) { | if (cb->state == ERROR) { | ||||
PRINTF(cb, "krping_format_send failed\n"); | printk(KERN_ERR PFX "krping_format_send failed\n"); | ||||
break; | break; | ||||
} | } | ||||
ret = ib_post_send(cb->qp, &cb->sq_wr, &bad_wr); | ret = ib_post_send(cb->qp, &cb->sq_wr, &bad_wr); | ||||
if (ret) { | if (ret) { | ||||
PRINTF(cb, "post send error %d\n", ret); | printk(KERN_ERR PFX "post send error %d\n", ret); | ||||
break; | break; | ||||
} | } | ||||
/* Wait for server to ACK */ | /* Wait for server to ACK */ | ||||
wait_event_interruptible(cb->sem, cb->state >= RDMA_WRITE_ADV); | wait_event_interruptible(cb->sem, cb->state >= RDMA_WRITE_ADV); | ||||
if (cb->state != RDMA_WRITE_ADV) { | if (cb->state != RDMA_WRITE_ADV) { | ||||
PRINTF(cb, | printk(KERN_ERR PFX | ||||
"wait for RDMA_WRITE_ADV state %d\n", | "wait for RDMA_WRITE_ADV state %d\n", | ||||
cb->state); | cb->state); | ||||
break; | break; | ||||
} | } | ||||
krping_format_send(cb, cb->rdma_dma_addr); | krping_format_send(cb, cb->rdma_dma_addr); | ||||
ret = ib_post_send(cb->qp, &cb->sq_wr, &bad_wr); | ret = ib_post_send(cb->qp, &cb->sq_wr, &bad_wr); | ||||
if (ret) { | if (ret) { | ||||
PRINTF(cb, "post send error %d\n", ret); | printk(KERN_ERR PFX "post send error %d\n", ret); | ||||
break; | break; | ||||
} | } | ||||
/* Wait for the server to say the RDMA Write is complete. */ | /* Wait for the server to say the RDMA Write is complete. */ | ||||
wait_event_interruptible(cb->sem, | wait_event_interruptible(cb->sem, | ||||
cb->state >= RDMA_WRITE_COMPLETE); | cb->state >= RDMA_WRITE_COMPLETE); | ||||
if (cb->state != RDMA_WRITE_COMPLETE) { | if (cb->state != RDMA_WRITE_COMPLETE) { | ||||
PRINTF(cb, | printk(KERN_ERR PFX | ||||
"wait for RDMA_WRITE_COMPLETE state %d\n", | "wait for RDMA_WRITE_COMPLETE state %d\n", | ||||
cb->state); | cb->state); | ||||
break; | break; | ||||
} | } | ||||
if (cb->validate) | if (cb->validate) | ||||
if (memcmp(cb->start_buf, cb->rdma_buf, cb->size)) { | if (memcmp(cb->start_buf, cb->rdma_buf, cb->size)) { | ||||
PRINTF(cb, "data mismatch!\n"); | printk(KERN_ERR PFX "data mismatch!\n"); | ||||
break; | break; | ||||
} | } | ||||
if (cb->verbose) { | if (cb->verbose) | ||||
if (strlen(cb->rdma_buf) > 128) { | printk(KERN_INFO PFX "ping data: %s\n", cb->rdma_buf); | ||||
char msgbuf[128]; | |||||
strlcpy(msgbuf, cb->rdma_buf, sizeof(msgbuf)); | |||||
PRINTF(cb, "ping data stripped: %s\n", | |||||
msgbuf); | |||||
} else | |||||
PRINTF(cb, "ping data: %s\n", cb->rdma_buf); | |||||
} | |||||
#ifdef SLOW_KRPING | #ifdef SLOW_KRPING | ||||
wait_event_interruptible_timeout(cb->sem, cb->state == ERROR, HZ); | wait_event_interruptible_timeout(cb->sem, cb->state == ERROR, HZ); | ||||
#endif | #endif | ||||
} | } | ||||
} | } | ||||
static void krping_rlat_test_client(struct krping_cb *cb) | static void krping_rlat_test_client(struct krping_cb *cb) | ||||
{ | { | ||||
struct ib_send_wr *bad_wr; | struct ib_send_wr *bad_wr; | ||||
struct ib_wc wc; | struct ib_wc wc; | ||||
int ret; | int ret; | ||||
cb->state = RDMA_READ_ADV; | cb->state = RDMA_READ_ADV; | ||||
/* Send STAG/TO/Len to client */ | /* Send STAG/TO/Len to client */ | ||||
krping_format_send(cb, cb->start_dma_addr); | krping_format_send(cb, cb->start_dma_addr); | ||||
if (cb->state == ERROR) { | if (cb->state == ERROR) { | ||||
PRINTF(cb, "krping_format_send failed\n"); | printk(KERN_ERR PFX "krping_format_send failed\n"); | ||||
return; | return; | ||||
} | } | ||||
ret = ib_post_send(cb->qp, &cb->sq_wr, &bad_wr); | ret = ib_post_send(cb->qp, &cb->sq_wr, &bad_wr); | ||||
if (ret) { | if (ret) { | ||||
PRINTF(cb, "post send error %d\n", ret); | printk(KERN_ERR PFX "post send error %d\n", ret); | ||||
return; | return; | ||||
} | } | ||||
/* Spin waiting for send completion */ | /* Spin waiting for send completion */ | ||||
while ((ret = ib_poll_cq(cb->cq, 1, &wc) == 0)); | while ((ret = ib_poll_cq(cb->cq, 1, &wc) == 0)); | ||||
if (ret < 0) { | if (ret < 0) { | ||||
PRINTF(cb, "poll error %d\n", ret); | printk(KERN_ERR PFX "poll error %d\n", ret); | ||||
return; | return; | ||||
} | } | ||||
if (wc.status) { | if (wc.status) { | ||||
PRINTF(cb, "send completion error %d\n", wc.status); | printk(KERN_ERR PFX "send completion error %d\n", wc.status); | ||||
return; | return; | ||||
} | } | ||||
/* Spin waiting for server's Start STAG/TO/Len */ | /* Spin waiting for server's Start STAG/TO/Len */ | ||||
while (cb->state < RDMA_WRITE_ADV) { | while (cb->state < RDMA_WRITE_ADV) { | ||||
krping_cq_event_handler(cb->cq, cb); | krping_cq_event_handler(cb->cq, cb); | ||||
} | } | ||||
#if 0 | #if 0 | ||||
{ | { | ||||
int i; | int i; | ||||
struct timeval start, stop; | struct timeval start, stop; | ||||
time_t sec; | time_t sec; | ||||
suseconds_t usec; | suseconds_t usec; | ||||
unsigned long long elapsed; | unsigned long long elapsed; | ||||
struct ib_wc wc; | struct ib_wc wc; | ||||
struct ib_send_wr *bad_wr; | struct ib_send_wr *bad_wr; | ||||
int ne; | int ne; | ||||
cb->rdma_sq_wr.opcode = IB_WR_RDMA_WRITE; | cb->rdma_sq_wr.wr.opcode = IB_WR_RDMA_WRITE; | ||||
cb->rdma_sq_wr.wr.rdma.rkey = cb->remote_rkey; | cb->rdma_sq_wr.rkey = cb->remote_rkey; | ||||
cb->rdma_sq_wr.wr.rdma.remote_addr = cb->remote_addr; | cb->rdma_sq_wr.remote_addr = cb->remote_addr; | ||||
cb->rdma_sq_wr.sg_list->length = 0; | cb->rdma_sq_wr.wr.sg_list->length = 0; | ||||
cb->rdma_sq_wr.num_sge = 0; | cb->rdma_sq_wr.wr.num_sge = 0; | ||||
microtime(&start); | microtime(&start); | ||||
for (i=0; i < 100000; i++) { | for (i=0; i < 100000; i++) { | ||||
if (ib_post_send(cb->qp, &cb->rdma_sq_wr, &bad_wr)) { | if (ib_post_send(cb->qp, &cb->rdma_sq_wr.wr, &bad_wr)) { | ||||
PRINTF(cb, "Couldn't post send\n"); | printk(KERN_ERR PFX "Couldn't post send\n"); | ||||
return; | return; | ||||
} | } | ||||
do { | do { | ||||
ne = ib_poll_cq(cb->cq, 1, &wc); | ne = ib_poll_cq(cb->cq, 1, &wc); | ||||
} while (ne == 0); | } while (ne == 0); | ||||
if (ne < 0) { | if (ne < 0) { | ||||
PRINTF(cb, "poll CQ failed %d\n", ne); | printk(KERN_ERR PFX "poll CQ failed %d\n", ne); | ||||
return; | return; | ||||
} | } | ||||
if (wc.status != IB_WC_SUCCESS) { | if (wc.status != IB_WC_SUCCESS) { | ||||
PRINTF(cb, "Completion wth error at %s:\n", | printk(KERN_ERR PFX "Completion wth error at %s:\n", | ||||
cb->server ? "server" : "client"); | cb->server ? "server" : "client"); | ||||
PRINTF(cb, "Failed status %d: wr_id %d\n", | printk(KERN_ERR PFX "Failed status %d: wr_id %d\n", | ||||
wc.status, (int) wc.wr_id); | wc.status, (int) wc.wr_id); | ||||
return; | return; | ||||
} | } | ||||
} | } | ||||
microtime(&stop); | microtime(&stop); | ||||
if (stop.tv_usec < start.tv_usec) { | if (stop.tv_usec < start.tv_usec) { | ||||
stop.tv_usec += 1000000; | stop.tv_usec += 1000000; | ||||
stop.tv_sec -= 1; | stop.tv_sec -= 1; | ||||
} | } | ||||
sec = stop.tv_sec - start.tv_sec; | sec = stop.tv_sec - start.tv_sec; | ||||
usec = stop.tv_usec - start.tv_usec; | usec = stop.tv_usec - start.tv_usec; | ||||
elapsed = sec * 1000000 + usec; | elapsed = sec * 1000000 + usec; | ||||
PRINTF(cb, "0B-write-lat iters 100000 usec %llu\n", elapsed); | printk(KERN_ERR PFX "0B-write-lat iters 100000 usec %llu\n", elapsed); | ||||
} | } | ||||
#endif | #endif | ||||
rlat_test(cb); | rlat_test(cb); | ||||
} | } | ||||
static void krping_wlat_test_client(struct krping_cb *cb) | static void krping_wlat_test_client(struct krping_cb *cb) | ||||
{ | { | ||||
struct ib_send_wr *bad_wr; | struct ib_send_wr *bad_wr; | ||||
struct ib_wc wc; | struct ib_wc wc; | ||||
int ret; | int ret; | ||||
cb->state = RDMA_READ_ADV; | cb->state = RDMA_READ_ADV; | ||||
/* Send STAG/TO/Len to client */ | /* Send STAG/TO/Len to client */ | ||||
krping_format_send(cb, cb->start_dma_addr); | krping_format_send(cb, cb->start_dma_addr); | ||||
if (cb->state == ERROR) { | if (cb->state == ERROR) { | ||||
PRINTF(cb, "krping_format_send failed\n"); | printk(KERN_ERR PFX "krping_format_send failed\n"); | ||||
return; | return; | ||||
} | } | ||||
ret = ib_post_send(cb->qp, &cb->sq_wr, &bad_wr); | ret = ib_post_send(cb->qp, &cb->sq_wr, &bad_wr); | ||||
if (ret) { | if (ret) { | ||||
PRINTF(cb, "post send error %d\n", ret); | printk(KERN_ERR PFX "post send error %d\n", ret); | ||||
return; | return; | ||||
} | } | ||||
/* Spin waiting for send completion */ | /* Spin waiting for send completion */ | ||||
while ((ret = ib_poll_cq(cb->cq, 1, &wc) == 0)); | while ((ret = ib_poll_cq(cb->cq, 1, &wc) == 0)); | ||||
if (ret < 0) { | if (ret < 0) { | ||||
PRINTF(cb, "poll error %d\n", ret); | printk(KERN_ERR PFX "poll error %d\n", ret); | ||||
return; | return; | ||||
} | } | ||||
if (wc.status) { | if (wc.status) { | ||||
PRINTF(cb, "send completion error %d\n", wc.status); | printk(KERN_ERR PFX "send completion error %d\n", wc.status); | ||||
return; | return; | ||||
} | } | ||||
/* Spin waiting for server's Start STAG/TO/Len */ | /* Spin waiting for server's Start STAG/TO/Len */ | ||||
while (cb->state < RDMA_WRITE_ADV) { | while (cb->state < RDMA_WRITE_ADV) { | ||||
krping_cq_event_handler(cb->cq, cb); | krping_cq_event_handler(cb->cq, cb); | ||||
} | } | ||||
wlat_test(cb); | wlat_test(cb); | ||||
} | } | ||||
static void krping_bw_test_client(struct krping_cb *cb) | static void krping_bw_test_client(struct krping_cb *cb) | ||||
{ | { | ||||
struct ib_send_wr *bad_wr; | struct ib_send_wr *bad_wr; | ||||
struct ib_wc wc; | struct ib_wc wc; | ||||
int ret; | int ret; | ||||
cb->state = RDMA_READ_ADV; | cb->state = RDMA_READ_ADV; | ||||
/* Send STAG/TO/Len to client */ | /* Send STAG/TO/Len to client */ | ||||
krping_format_send(cb, cb->start_dma_addr); | krping_format_send(cb, cb->start_dma_addr); | ||||
if (cb->state == ERROR) { | if (cb->state == ERROR) { | ||||
PRINTF(cb, "krping_format_send failed\n"); | printk(KERN_ERR PFX "krping_format_send failed\n"); | ||||
return; | return; | ||||
} | } | ||||
ret = ib_post_send(cb->qp, &cb->sq_wr, &bad_wr); | ret = ib_post_send(cb->qp, &cb->sq_wr, &bad_wr); | ||||
if (ret) { | if (ret) { | ||||
PRINTF(cb, "post send error %d\n", ret); | printk(KERN_ERR PFX "post send error %d\n", ret); | ||||
return; | return; | ||||
} | } | ||||
/* Spin waiting for send completion */ | /* Spin waiting for send completion */ | ||||
while ((ret = ib_poll_cq(cb->cq, 1, &wc) == 0)); | while ((ret = ib_poll_cq(cb->cq, 1, &wc) == 0)); | ||||
if (ret < 0) { | if (ret < 0) { | ||||
PRINTF(cb, "poll error %d\n", ret); | printk(KERN_ERR PFX "poll error %d\n", ret); | ||||
return; | return; | ||||
} | } | ||||
if (wc.status) { | if (wc.status) { | ||||
PRINTF(cb, "send completion error %d\n", wc.status); | printk(KERN_ERR PFX "send completion error %d\n", wc.status); | ||||
return; | return; | ||||
} | } | ||||
/* Spin waiting for server's Start STAG/TO/Len */ | /* Spin waiting for server's Start STAG/TO/Len */ | ||||
while (cb->state < RDMA_WRITE_ADV) { | while (cb->state < RDMA_WRITE_ADV) { | ||||
krping_cq_event_handler(cb->cq, cb); | krping_cq_event_handler(cb->cq, cb); | ||||
} | } | ||||
bw_test(cb); | bw_test(cb); | ||||
} | } | ||||
/* | /* | ||||
* fastreg 2 valid different mrs and verify the completions. | * Manual qp flush test | ||||
*/ | */ | ||||
static void krping_fr_test1(struct krping_cb *cb) | static void flush_qp(struct krping_cb *cb) | ||||
{ | { | ||||
struct ib_fast_reg_page_list *pl; | struct ib_send_wr wr = { 0 }, *bad; | ||||
struct ib_send_wr fr, *bad; | struct ib_recv_wr recv_wr = { 0 }, *recv_bad; | ||||
struct ib_wc wc; | struct ib_wc wc; | ||||
struct ib_mr *mr1, *mr2; | |||||
int i; | |||||
int ret; | int ret; | ||||
int size = cb->size; | int flushed = 0; | ||||
int plen = (((size - 1) & PAGE_MASK) + PAGE_SIZE) >> PAGE_SHIFT; | int ccnt = 0; | ||||
int count = 0; | |||||
pl = ib_alloc_fast_reg_page_list(cb->qp->device, plen); | rdma_disconnect(cb->cm_id); | ||||
if (IS_ERR(pl)) { | DEBUG_LOG("disconnected!\n"); | ||||
PRINTF(cb, "ib_alloc_fast_reg_page_list failed %ld\n", PTR_ERR(pl)); | |||||
return; | |||||
} | |||||
mr1 = ib_alloc_fast_reg_mr(cb->pd, plen); | wr.opcode = IB_WR_SEND; | ||||
if (IS_ERR(mr1)) { | wr.wr_id = 0xdeadbeefcafebabe; | ||||
PRINTF(cb, "ib_alloc_fast_reg_mr failed %ld\n", PTR_ERR(pl)); | ret = ib_post_send(cb->qp, &wr, &bad); | ||||
goto err1; | |||||
} | |||||
mr2 = ib_alloc_fast_reg_mr(cb->pd, plen); | |||||
if (IS_ERR(mr2)) { | |||||
PRINTF(cb, "ib_alloc_fast_reg_mr failed %ld\n", PTR_ERR(pl)); | |||||
goto err2; | |||||
} | |||||
for (i=0; i<plen; i++) | |||||
pl->page_list[i] = i * PAGE_SIZE; | |||||
memset(&fr, 0, sizeof fr); | |||||
fr.opcode = IB_WR_FAST_REG_MR; | |||||
fr.wr_id = 1; | |||||
fr.wr.fast_reg.page_shift = PAGE_SHIFT; | |||||
fr.wr.fast_reg.length = size; | |||||
fr.wr.fast_reg.page_list = pl; | |||||
fr.wr.fast_reg.page_list_len = plen; | |||||
fr.wr.fast_reg.iova_start = 0; | |||||
fr.wr.fast_reg.access_flags = IB_ACCESS_REMOTE_WRITE | IB_ACCESS_LOCAL_WRITE; | |||||
fr.send_flags = IB_SEND_SIGNALED; | |||||
fr.wr.fast_reg.rkey = mr1->rkey; | |||||
DEBUG_LOG(cb, "%s fr1: stag 0x%x plen %u size %u depth %u\n", __func__, fr.wr.fast_reg.rkey, plen, cb->size, cb->txdepth); | |||||
ret = ib_post_send(cb->qp, &fr, &bad); | |||||
if (ret) { | if (ret) { | ||||
PRINTF(cb, "ib_post_send failed %d\n", ret); | printk(KERN_ERR PFX "%s post_send failed ret %d\n", __func__, ret); | ||||
goto err3; | |||||
} | |||||
fr.wr.fast_reg.rkey = mr2->rkey; | |||||
DEBUG_LOG(cb, "%s fr2: stag 0x%x plen %u size %u depth %u\n", __func__, fr.wr.fast_reg.rkey, plen, cb->size, cb->txdepth); | |||||
ret = ib_post_send(cb->qp, &fr, &bad); | |||||
if (ret) { | |||||
PRINTF(cb, "ib_post_send failed %d\n", ret); | |||||
goto err3; | |||||
} | |||||
DEBUG_LOG(cb, "sleeping 1 second\n"); | |||||
wait_event_interruptible_timeout(cb->sem, cb->state == ERROR, HZ); | |||||
do { | |||||
ret = ib_poll_cq(cb->cq, 1, &wc); | |||||
if (ret < 0) { | |||||
PRINTF(cb, "ib_poll_cq failed %d\n", ret); | |||||
goto err3; | |||||
} | |||||
if (ret == 1) { | |||||
DEBUG_LOG(cb, "completion status %u wr %s\n", | |||||
wc.status, wc.wr_id == 1 ? "fr" : "inv"); | |||||
count++; | |||||
} else if (krping_sigpending()) { | |||||
PRINTF(cb, "signal!\n"); | |||||
goto err3; | |||||
} | |||||
wait_event_interruptible_timeout(cb->sem, cb->state == ERROR, HZ); | |||||
} while (count != 2); | |||||
err3: | |||||
DEBUG_LOG(cb, "sleeping 1 second\n"); | |||||
wait_event_interruptible_timeout(cb->sem, cb->state == ERROR, HZ); | |||||
DEBUG_LOG(cb, "draining the cq...\n"); | |||||
do { | |||||
ret = ib_poll_cq(cb->cq, 1, &wc); | |||||
if (ret < 0) { | |||||
PRINTF(cb, "ib_poll_cq failed %d\n", ret); | |||||
break; | |||||
} | |||||
if (ret == 1) { | |||||
PRINTF(cb, "completion %u opcode %u\n", wc.status, wc.opcode); | |||||
} | |||||
} while (ret == 1); | |||||
DEBUG_LOG(cb, "destroying fr mr2!\n"); | |||||
ib_dereg_mr(mr2); | |||||
err2: | |||||
DEBUG_LOG(cb, "destroying fr mr1!\n"); | |||||
ib_dereg_mr(mr1); | |||||
err1: | |||||
DEBUG_LOG(cb, "destroying fr page list!\n"); | |||||
ib_free_fast_reg_page_list(pl); | |||||
DEBUG_LOG(cb, "%s done!\n", __func__); | |||||
} | |||||
/* | |||||
* fastreg the same mr twice, 2nd one should produce error cqe. | |||||
*/ | |||||
static void krping_fr_test2(struct krping_cb *cb) | |||||
{ | |||||
struct ib_fast_reg_page_list *pl; | |||||
struct ib_send_wr fr, *bad; | |||||
struct ib_wc wc; | |||||
struct ib_mr *mr1; | |||||
int i; | |||||
int ret; | |||||
int size = cb->size; | |||||
int plen = (((size - 1) & PAGE_MASK) + PAGE_SIZE) >> PAGE_SHIFT; | |||||
int count = 0; | |||||
pl = ib_alloc_fast_reg_page_list(cb->qp->device, plen); | |||||
if (IS_ERR(pl)) { | |||||
PRINTF(cb, "ib_alloc_fast_reg_page_list failed %ld\n", PTR_ERR(pl)); | |||||
return; | return; | ||||
} | } | ||||
mr1 = ib_alloc_fast_reg_mr(cb->pd, plen); | recv_wr.wr_id = 0xcafebabedeadbeef; | ||||
if (IS_ERR(mr1)) { | ret = ib_post_recv(cb->qp, &recv_wr, &recv_bad); | ||||
PRINTF(cb, "ib_alloc_fast_reg_mr failed %ld\n", PTR_ERR(pl)); | |||||
goto err1; | |||||
} | |||||
for (i=0; i<plen; i++) | |||||
pl->page_list[i] = i * PAGE_SIZE; | |||||
memset(&fr, 0, sizeof fr); | |||||
fr.opcode = IB_WR_FAST_REG_MR; | |||||
fr.wr_id = 1; | |||||
fr.wr.fast_reg.page_shift = PAGE_SHIFT; | |||||
fr.wr.fast_reg.length = size; | |||||
fr.wr.fast_reg.page_list = pl; | |||||
fr.wr.fast_reg.page_list_len = plen; | |||||
fr.wr.fast_reg.iova_start = 0; | |||||
fr.wr.fast_reg.access_flags = IB_ACCESS_REMOTE_WRITE | IB_ACCESS_LOCAL_WRITE; | |||||
fr.send_flags = IB_SEND_SIGNALED; | |||||
fr.wr.fast_reg.rkey = mr1->rkey; | |||||
DEBUG_LOG(cb, "%s fr1: stag 0x%x plen %u size %u depth %u\n", __func__, fr.wr.fast_reg.rkey, plen, cb->size, cb->txdepth); | |||||
ret = ib_post_send(cb->qp, &fr, &bad); | |||||
if (ret) { | if (ret) { | ||||
PRINTF(cb, "ib_post_send failed %d\n", ret); | printk(KERN_ERR PFX "%s post_recv failed ret %d\n", __func__, ret); | ||||
goto err3; | return; | ||||
} | } | ||||
DEBUG_LOG(cb, "%s fr2: stag 0x%x plen %u size %u depth %u\n", __func__, fr.wr.fast_reg.rkey, plen, cb->size, cb->txdepth); | |||||
ret = ib_post_send(cb->qp, &fr, &bad); | |||||
if (ret) { | |||||
PRINTF(cb, "ib_post_send failed %d\n", ret); | |||||
goto err3; | |||||
} | |||||
DEBUG_LOG(cb, "sleeping 1 second\n"); | /* poll until the flush WRs complete */ | ||||
wait_event_interruptible_timeout(cb->sem, cb->state == ERROR, HZ); | |||||
do { | do { | ||||
ret = ib_poll_cq(cb->cq, 1, &wc); | ret = ib_poll_cq(cb->cq, 1, &wc); | ||||
if (ret < 0) { | if (ret < 0) { | ||||
PRINTF(cb, "ib_poll_cq failed %d\n", ret); | printk(KERN_ERR PFX "ib_poll_cq failed %d\n", ret); | ||||
goto err3; | return; | ||||
} | } | ||||
if (ret == 1) { | if (ret == 0) | ||||
DEBUG_LOG(cb, "completion status %u wr %s\n", | continue; | ||||
wc.status, wc.wr_id == 1 ? "fr" : "inv"); | ccnt++; | ||||
count++; | if (wc.wr_id == 0xdeadbeefcafebabe || | ||||
} else if (krping_sigpending()) { | wc.wr_id == 0xcafebabedeadbeef) | ||||
PRINTF(cb, "signal!\n"); | flushed++; | ||||
goto err3; | } while (flushed != 2); | ||||
DEBUG_LOG("qp_flushed! ccnt %u\n", ccnt); | |||||
} | } | ||||
wait_event_interruptible_timeout(cb->sem, cb->state == ERROR, HZ); | |||||
} while (count != 2); | |||||
err3: | |||||
DEBUG_LOG(cb, "sleeping 1 second\n"); | |||||
wait_event_interruptible_timeout(cb->sem, cb->state == ERROR, HZ); | |||||
DEBUG_LOG(cb, "draining the cq...\n"); | |||||
do { | |||||
ret = ib_poll_cq(cb->cq, 1, &wc); | |||||
if (ret < 0) { | |||||
PRINTF(cb, "ib_poll_cq failed %d\n", ret); | |||||
break; | |||||
} | |||||
if (ret == 1) { | |||||
PRINTF(cb, "completion %u opcode %u\n", wc.status, wc.opcode); | |||||
} | |||||
} while (ret == 1); | |||||
DEBUG_LOG(cb, "destroying fr mr1!\n"); | |||||
ib_dereg_mr(mr1); | |||||
err1: | |||||
DEBUG_LOG(cb, "destroying fr page list!\n"); | |||||
ib_free_fast_reg_page_list(pl); | |||||
DEBUG_LOG(cb, "%s done!\n", __func__); | |||||
} | |||||
/* | static void krping_fr_test(struct krping_cb *cb) | ||||
* fastreg pipelined in a loop as fast as we can until the user interrupts. | |||||
* NOTE: every 9 seconds we sleep for 1 second to keep the kernel happy. | |||||
*/ | |||||
static void krping_fr_test3(struct krping_cb *cb) | |||||
{ | { | ||||
struct ib_fast_reg_page_list *pl; | struct ib_send_wr inv, *bad; | ||||
struct ib_send_wr fr, inv, *bad; | struct ib_reg_wr fr; | ||||
struct ib_wc wc; | struct ib_wc wc; | ||||
u8 key = 0; | u8 key = 0; | ||||
struct ib_mr *mr; | struct ib_mr *mr; | ||||
int i; | |||||
int ret; | int ret; | ||||
int size = cb->size; | int size = cb->size; | ||||
int plen = (((size - 1) & PAGE_MASK) + PAGE_SIZE) >> PAGE_SHIFT; | int plen = (((size - 1) & PAGE_MASK) + PAGE_SIZE) >> PAGE_SHIFT; | ||||
unsigned long start; | unsigned long start; | ||||
int count = 0; | int count = 0; | ||||
int scnt = 0; | int scnt = 0; | ||||
struct scatterlist sg = {0}; | |||||
mr = ib_alloc_mr(cb->pd, IB_MR_TYPE_MEM_REG, plen); | |||||
pl = ib_alloc_fast_reg_page_list(cb->qp->device, plen); | if (IS_ERR(mr)) { | ||||
if (IS_ERR(pl)) { | printk(KERN_ERR PFX "ib_alloc_mr failed %ld\n", PTR_ERR(mr)); | ||||
PRINTF(cb, "ib_alloc_fast_reg_page_list failed %ld\n", PTR_ERR(pl)); | |||||
return; | return; | ||||
} | } | ||||
mr = ib_alloc_fast_reg_mr(cb->pd, plen); | sg_dma_address(&sg) = 0xcafebabe0000UL; | ||||
if (IS_ERR(mr)) { | sg_dma_len(&sg) = size; | ||||
PRINTF(cb, "ib_alloc_fast_reg_mr failed %ld\n", PTR_ERR(pl)); | ret = ib_map_mr_sg(mr, &sg, 1, NULL, PAGE_SIZE); | ||||
goto err1; | if (ret <= 0) { | ||||
printk(KERN_ERR PFX "ib_map_mr_sge err %d\n", ret); | |||||
goto err2; | |||||
} | } | ||||
for (i=0; i<plen; i++) | |||||
pl->page_list[i] = i * PAGE_SIZE; | |||||
memset(&fr, 0, sizeof fr); | memset(&fr, 0, sizeof fr); | ||||
fr.opcode = IB_WR_FAST_REG_MR; | fr.wr.opcode = IB_WR_REG_MR; | ||||
fr.wr.fast_reg.page_shift = PAGE_SHIFT; | fr.access = IB_ACCESS_REMOTE_WRITE | IB_ACCESS_LOCAL_WRITE; | ||||
fr.wr.fast_reg.length = size; | fr.mr = mr; | ||||
fr.wr.fast_reg.page_list = pl; | fr.wr.next = &inv; | ||||
fr.wr.fast_reg.page_list_len = plen; | |||||
fr.wr.fast_reg.iova_start = 0; | |||||
fr.send_flags = IB_SEND_SIGNALED; | |||||
fr.wr.fast_reg.access_flags = IB_ACCESS_REMOTE_WRITE | IB_ACCESS_LOCAL_WRITE; | |||||
fr.next = &inv; | |||||
memset(&inv, 0, sizeof inv); | memset(&inv, 0, sizeof inv); | ||||
inv.opcode = IB_WR_LOCAL_INV; | inv.opcode = IB_WR_LOCAL_INV; | ||||
inv.send_flags = IB_SEND_SIGNALED; | inv.send_flags = IB_SEND_SIGNALED; | ||||
DEBUG_LOG(cb, "fr_test: stag index 0x%x plen %u size %u depth %u\n", mr->rkey >> 8, plen, cb->size, cb->txdepth); | DEBUG_LOG("fr_test: stag index 0x%x plen %u size %u depth %u\n", mr->rkey >> 8, plen, cb->size, cb->txdepth); | ||||
start = time_uptime; | start = time_uptime; | ||||
while (1) { | while (!cb->count || count <= cb->count) { | ||||
if (SIGPENDING(curthread)) { | |||||
printk(KERN_ERR PFX "signal!\n"); | |||||
break; | |||||
} | |||||
if ((time_uptime - start) >= 9) { | if ((time_uptime - start) >= 9) { | ||||
DEBUG_LOG(cb, "fr_test: pausing 1 second! count %u latest size %u plen %u\n", count, size, plen); | DEBUG_LOG("fr_test: pausing 1 second! count %u latest size %u plen %u\n", count, size, plen); | ||||
wait_event_interruptible_timeout(cb->sem, cb->state == ERROR, HZ); | wait_event_interruptible_timeout(cb->sem, cb->state == ERROR, HZ); | ||||
if (cb->state == ERROR) | if (cb->state == ERROR) | ||||
break; | break; | ||||
start = time_uptime; | start = time_uptime; | ||||
} | } | ||||
while (scnt < (cb->txdepth>>1)) { | while (scnt < (cb->txdepth>>1)) { | ||||
ib_update_fast_reg_key(mr, ++key); | ib_update_fast_reg_key(mr, ++key); | ||||
fr.wr.fast_reg.rkey = mr->rkey; | fr.key = mr->rkey; | ||||
inv.ex.invalidate_rkey = mr->rkey; | inv.ex.invalidate_rkey = mr->rkey; | ||||
size = arc4random() % cb->size; | size = arc4random() % cb->size; | ||||
if (size == 0) | if (size == 0) | ||||
size = cb->size; | size = cb->size; | ||||
plen = (((size - 1) & PAGE_MASK) + PAGE_SIZE) >> PAGE_SHIFT; | sg_dma_len(&sg) = size; | ||||
fr.wr.fast_reg.length = size; | ret = ib_map_mr_sg(mr, &sg, 1, NULL, PAGE_SIZE); | ||||
fr.wr.fast_reg.page_list_len = plen; | if (ret <= 0) { | ||||
ret = ib_post_send(cb->qp, &fr, &bad); | printk(KERN_ERR PFX "ib_map_mr_sge err %d\n", ret); | ||||
goto err2; | |||||
} | |||||
ret = ib_post_send(cb->qp, &fr.wr, &bad); | |||||
if (ret) { | if (ret) { | ||||
PRINTF(cb, "ib_post_send failed %d\n", ret); | printk(KERN_ERR PFX "ib_post_send failed %d\n", ret); | ||||
goto err2; | goto err2; | ||||
} | } | ||||
scnt+=2; | scnt++; | ||||
} | } | ||||
do { | |||||
ret = ib_poll_cq(cb->cq, 1, &wc); | ret = ib_poll_cq(cb->cq, 1, &wc); | ||||
if (ret < 0) { | if (ret < 0) { | ||||
PRINTF(cb, "ib_poll_cq failed %d\n", ret); | printk(KERN_ERR PFX "ib_poll_cq failed %d\n", ret); | ||||
goto err2; | goto err2; | ||||
} | } | ||||
if (ret == 1) { | if (ret == 1) { | ||||
if (wc.status) { | if (wc.status) { | ||||
PRINTF(cb, "completion error %u\n", wc.status); | printk(KERN_ERR PFX "completion error %u\n", wc.status); | ||||
goto err2; | goto err2; | ||||
} | } | ||||
count++; | count++; | ||||
scnt--; | scnt--; | ||||
} | } | ||||
else if (krping_sigpending()) { | |||||
PRINTF(cb, "signal!\n"); | |||||
goto err2; | |||||
} | } | ||||
} while (ret == 1); | |||||
} | |||||
err2: | err2: | ||||
DEBUG_LOG(cb, "sleeping 1 second\n"); | flush_qp(cb); | ||||
wait_event_interruptible_timeout(cb->sem, cb->state == ERROR, HZ); | DEBUG_LOG("fr_test: done!\n"); | ||||
DEBUG_LOG(cb, "draining the cq...\n"); | |||||
do { | |||||
ret = ib_poll_cq(cb->cq, 1, &wc); | |||||
if (ret < 0) { | |||||
PRINTF(cb, "ib_poll_cq failed %d\n", ret); | |||||
break; | |||||
} | |||||
if (ret == 1) { | |||||
if (wc.status) { | |||||
PRINTF(cb, "completion error %u opcode %u\n", wc.status, wc.opcode); | |||||
} | |||||
} | |||||
} while (ret == 1); | |||||
DEBUG_LOG(cb, "fr_test: done!\n"); | |||||
ib_dereg_mr(mr); | ib_dereg_mr(mr); | ||||
err1: | |||||
DEBUG_LOG(cb, "destroying fr page list!\n"); | |||||
ib_free_fast_reg_page_list(pl); | |||||
DEBUG_LOG(cb, "%s done!\n", __func__); | |||||
} | } | ||||
/* | |||||
* fastreg 1 and invalidate 1 mr and verify completion. | |||||
*/ | |||||
static void krping_fr_test4(struct krping_cb *cb) | |||||
{ | |||||
struct ib_fast_reg_page_list *pl; | |||||
struct ib_send_wr fr, inv, *bad; | |||||
struct ib_wc wc; | |||||
struct ib_mr *mr1; | |||||
int i; | |||||
int ret; | |||||
int size = cb->size; | |||||
int plen = (((size - 1) & PAGE_MASK) + PAGE_SIZE) >> PAGE_SHIFT; | |||||
int count = 0; | |||||
pl = ib_alloc_fast_reg_page_list(cb->qp->device, plen); | |||||
if (IS_ERR(pl)) { | |||||
PRINTF(cb, "ib_alloc_fast_reg_page_list failed %ld\n", PTR_ERR(pl)); | |||||
return; | |||||
} | |||||
mr1 = ib_alloc_fast_reg_mr(cb->pd, plen); | |||||
if (IS_ERR(mr1)) { | |||||
PRINTF(cb, "ib_alloc_fast_reg_mr failed %ld\n", PTR_ERR(pl)); | |||||
goto err1; | |||||
} | |||||
for (i=0; i<plen; i++) | |||||
pl->page_list[i] = i * PAGE_SIZE; | |||||
memset(&fr, 0, sizeof fr); | |||||
fr.opcode = IB_WR_FAST_REG_MR; | |||||
fr.wr_id = 1; | |||||
fr.wr.fast_reg.page_shift = PAGE_SHIFT; | |||||
fr.wr.fast_reg.length = size; | |||||
fr.wr.fast_reg.page_list = pl; | |||||
fr.wr.fast_reg.page_list_len = plen; | |||||
fr.wr.fast_reg.iova_start = 0; | |||||
fr.wr.fast_reg.access_flags = IB_ACCESS_REMOTE_WRITE | IB_ACCESS_LOCAL_WRITE; | |||||
fr.send_flags = IB_SEND_SIGNALED; | |||||
fr.wr.fast_reg.rkey = mr1->rkey; | |||||
fr.next = &inv; | |||||
memset(&inv, 0, sizeof inv); | |||||
inv.opcode = IB_WR_LOCAL_INV; | |||||
inv.ex.invalidate_rkey = mr1->rkey; | |||||
DEBUG_LOG(cb, "%s fr1: stag 0x%x plen %u size %u depth %u\n", __func__, fr.wr.fast_reg.rkey, plen, cb->size, cb->txdepth); | |||||
ret = ib_post_send(cb->qp, &fr, &bad); | |||||
if (ret) { | |||||
PRINTF(cb, "ib_post_send failed %d\n", ret); | |||||
goto err3; | |||||
} | |||||
DEBUG_LOG(cb, "sleeping 1 second\n"); | |||||
wait_event_interruptible_timeout(cb->sem, cb->state == ERROR, HZ); | |||||
do { | |||||
ret = ib_poll_cq(cb->cq, 1, &wc); | |||||
if (ret < 0) { | |||||
PRINTF(cb, "ib_poll_cq failed %d\n", ret); | |||||
goto err3; | |||||
} | |||||
if (ret == 1) { | |||||
DEBUG_LOG(cb, "completion status %u wr %s\n", | |||||
wc.status, wc.wr_id == 1 ? "fr" : "inv"); | |||||
count++; | |||||
} else if (krping_sigpending()) { | |||||
PRINTF(cb, "signal!\n"); | |||||
goto err3; | |||||
} | |||||
wait_event_interruptible_timeout(cb->sem, cb->state == ERROR, HZ); | |||||
} while (count != 1); | |||||
err3: | |||||
DEBUG_LOG(cb, "sleeping 1 second\n"); | |||||
wait_event_interruptible_timeout(cb->sem, cb->state == ERROR, HZ); | |||||
DEBUG_LOG(cb, "draining the cq...\n"); | |||||
do { | |||||
ret = ib_poll_cq(cb->cq, 1, &wc); | |||||
if (ret < 0) { | |||||
PRINTF(cb, "ib_poll_cq failed %d\n", ret); | |||||
break; | |||||
} | |||||
if (ret == 1) { | |||||
PRINTF(cb, "completion %u opcode %u\n", wc.status, wc.opcode); | |||||
} | |||||
} while (ret == 1); | |||||
DEBUG_LOG(cb, "destroying fr mr1!\n"); | |||||
ib_dereg_mr(mr1); | |||||
err1: | |||||
DEBUG_LOG(cb, "destroying fr page list!\n"); | |||||
ib_free_fast_reg_page_list(pl); | |||||
DEBUG_LOG(cb, "%s done!\n", __func__); | |||||
} | |||||
static void krping_fr_test(struct krping_cb *cb) | |||||
{ | |||||
switch (cb->testnum) { | |||||
case 1: | |||||
krping_fr_test1(cb); | |||||
break; | |||||
case 2: | |||||
krping_fr_test2(cb); | |||||
break; | |||||
case 3: | |||||
krping_fr_test3(cb); | |||||
break; | |||||
case 4: | |||||
krping_fr_test4(cb); | |||||
break; | |||||
case 5: | |||||
krping_fr_test5_client(cb); | |||||
break; | |||||
case 6: | |||||
krping_fr_test6_client(cb); | |||||
break; | |||||
default: | |||||
PRINTF(cb, "Unkown frtest num %u\n", cb->testnum); | |||||
break; | |||||
} | |||||
} | |||||
static int krping_connect_client(struct krping_cb *cb) | static int krping_connect_client(struct krping_cb *cb) | ||||
{ | { | ||||
struct rdma_conn_param conn_param; | struct rdma_conn_param conn_param; | ||||
int ret; | int ret; | ||||
memset(&conn_param, 0, sizeof conn_param); | memset(&conn_param, 0, sizeof conn_param); | ||||
conn_param.responder_resources = 1; | conn_param.responder_resources = 1; | ||||
conn_param.initiator_depth = 1; | conn_param.initiator_depth = 1; | ||||
conn_param.retry_count = 10; | conn_param.retry_count = 10; | ||||
ret = rdma_connect(cb->cm_id, &conn_param); | ret = rdma_connect(cb->cm_id, &conn_param); | ||||
if (ret) { | if (ret) { | ||||
PRINTF(cb, "rdma_connect error %d\n", ret); | printk(KERN_ERR PFX "rdma_connect error %d\n", ret); | ||||
return ret; | return ret; | ||||
} | } | ||||
wait_event_interruptible(cb->sem, cb->state >= CONNECTED); | wait_event_interruptible(cb->sem, cb->state >= CONNECTED); | ||||
if (cb->state == ERROR) { | if (cb->state == ERROR) { | ||||
PRINTF(cb, "wait for CONNECTED state %d\n", cb->state); | printk(KERN_ERR PFX "wait for CONNECTED state %d\n", cb->state); | ||||
return -1; | return -1; | ||||
} | } | ||||
DEBUG_LOG(cb, "rdma_connect successful\n"); | DEBUG_LOG("rdma_connect successful\n"); | ||||
return 0; | return 0; | ||||
} | } | ||||
static int krping_bind_client(struct krping_cb *cb) | static int krping_bind_client(struct krping_cb *cb) | ||||
{ | { | ||||
struct sockaddr_in sin; | struct sockaddr_storage sin; | ||||
int ret; | int ret; | ||||
memset(&sin, 0, sizeof(sin)); | fill_sockaddr(&sin, cb); | ||||
sin.sin_len = sizeof sin; | |||||
sin.sin_family = AF_INET; | |||||
sin.sin_addr.s_addr = cb->addr.s_addr; | |||||
sin.sin_port = cb->port; | |||||
ret = rdma_resolve_addr(cb->cm_id, NULL, (struct sockaddr *) &sin, | ret = rdma_resolve_addr(cb->cm_id, NULL, (struct sockaddr *)&sin, 2000); | ||||
2000); | |||||
if (ret) { | if (ret) { | ||||
PRINTF(cb, "rdma_resolve_addr error %d\n", ret); | printk(KERN_ERR PFX "rdma_resolve_addr error %d\n", ret); | ||||
return ret; | return ret; | ||||
} | } | ||||
wait_event_interruptible(cb->sem, cb->state >= ROUTE_RESOLVED); | wait_event_interruptible(cb->sem, cb->state >= ROUTE_RESOLVED); | ||||
if (cb->state != ROUTE_RESOLVED) { | if (cb->state != ROUTE_RESOLVED) { | ||||
PRINTF(cb, | printk(KERN_ERR PFX | ||||
"addr/route resolution did not resolve: state %d\n", | "addr/route resolution did not resolve: state %d\n", | ||||
cb->state); | cb->state); | ||||
return -EINTR; | return -EINTR; | ||||
} | } | ||||
if (cb->mem == FASTREG && !fastreg_supported(cb, 0)) | if (!reg_supported(cb->cm_id->device)) | ||||
return -EINVAL; | return -EINVAL; | ||||
DEBUG_LOG(cb, "rdma_resolve_addr - rdma_resolve_route successful\n"); | DEBUG_LOG("rdma_resolve_addr - rdma_resolve_route successful\n"); | ||||
return 0; | return 0; | ||||
} | } | ||||
static void krping_run_client(struct krping_cb *cb) | static void krping_run_client(struct krping_cb *cb) | ||||
{ | { | ||||
struct ib_recv_wr *bad_wr; | struct ib_recv_wr *bad_wr; | ||||
int ret; | int ret; | ||||
ret = krping_bind_client(cb); | ret = krping_bind_client(cb); | ||||
if (ret) | if (ret) | ||||
return; | return; | ||||
ret = krping_setup_qp(cb, cb->cm_id); | ret = krping_setup_qp(cb, cb->cm_id); | ||||
if (ret) { | if (ret) { | ||||
PRINTF(cb, "setup_qp failed: %d\n", ret); | printk(KERN_ERR PFX "setup_qp failed: %d\n", ret); | ||||
return; | return; | ||||
} | } | ||||
ret = krping_setup_buffers(cb); | ret = krping_setup_buffers(cb); | ||||
if (ret) { | if (ret) { | ||||
PRINTF(cb, "krping_setup_buffers failed: %d\n", ret); | printk(KERN_ERR PFX "krping_setup_buffers failed: %d\n", ret); | ||||
goto err1; | goto err1; | ||||
} | } | ||||
ret = ib_post_recv(cb->qp, &cb->rq_wr, &bad_wr); | ret = ib_post_recv(cb->qp, &cb->rq_wr, &bad_wr); | ||||
if (ret) { | if (ret) { | ||||
PRINTF(cb, "ib_post_recv failed: %d\n", ret); | printk(KERN_ERR PFX "ib_post_recv failed: %d\n", ret); | ||||
goto err2; | goto err2; | ||||
} | } | ||||
ret = krping_connect_client(cb); | ret = krping_connect_client(cb); | ||||
if (ret) { | if (ret) { | ||||
PRINTF(cb, "connect error %d\n", ret); | printk(KERN_ERR PFX "connect error %d\n", ret); | ||||
goto err2; | goto err2; | ||||
} | } | ||||
if (cb->wlat) | if (cb->wlat) | ||||
krping_wlat_test_client(cb); | krping_wlat_test_client(cb); | ||||
else if (cb->rlat) | else if (cb->rlat) | ||||
krping_rlat_test_client(cb); | krping_rlat_test_client(cb); | ||||
else if (cb->bw) | else if (cb->bw) | ||||
krping_bw_test_client(cb); | krping_bw_test_client(cb); | ||||
else if (cb->frtest) | else if (cb->frtest) | ||||
krping_fr_test(cb); | krping_fr_test(cb); | ||||
else | else | ||||
krping_test_client(cb); | krping_test_client(cb); | ||||
rdma_disconnect(cb->cm_id); | rdma_disconnect(cb->cm_id); | ||||
err2: | err2: | ||||
krping_free_buffers(cb); | krping_free_buffers(cb); | ||||
err1: | err1: | ||||
krping_free_qp(cb); | krping_free_qp(cb); | ||||
} | } | ||||
int krping_doit(char *cmd, void *cookie) | int krping_doit(char *cmd) | ||||
{ | { | ||||
struct krping_cb *cb; | struct krping_cb *cb; | ||||
int op; | int op; | ||||
int ret = 0; | int ret = 0; | ||||
char *optarg; | char *optarg; | ||||
unsigned long optint; | unsigned long optint; | ||||
cb = kzalloc(sizeof(*cb), GFP_KERNEL); | cb = kzalloc(sizeof(*cb), GFP_KERNEL); | ||||
if (!cb) | if (!cb) | ||||
return -ENOMEM; | return -ENOMEM; | ||||
mutex_lock(&krping_mutex); | mutex_lock(&krping_mutex); | ||||
list_add_tail(&cb->list, &krping_cbs); | list_add_tail(&cb->list, &krping_cbs); | ||||
mutex_unlock(&krping_mutex); | mutex_unlock(&krping_mutex); | ||||
cb->cookie = cookie; | |||||
cb->server = -1; | cb->server = -1; | ||||
cb->state = IDLE; | cb->state = IDLE; | ||||
cb->size = 64; | cb->size = 64; | ||||
cb->txdepth = RPING_SQ_DEPTH; | cb->txdepth = RPING_SQ_DEPTH; | ||||
cb->mem = DMA; | |||||
init_waitqueue_head(&cb->sem); | init_waitqueue_head(&cb->sem); | ||||
while ((op = krping_getopt("krping", &cmd, krping_opts, NULL, &optarg, | while ((op = krping_getopt("krping", &cmd, krping_opts, NULL, &optarg, | ||||
&optint)) != 0) { | &optint)) != 0) { | ||||
switch (op) { | switch (op) { | ||||
struct in_addr in_addr; | |||||
case 'a': | case 'a': | ||||
cb->addr_str = optarg; | cb->addr_str = optarg; | ||||
DEBUG_LOG(cb, "ipaddr (%s)\n", optarg); | cb->addr_type = AF_INET; | ||||
if (!inet_aton(optarg, &cb->addr)) { | DEBUG_LOG("ipaddr (%s)\n", optarg); | ||||
PRINTF(cb, "bad addr string %s\n", | if (!inet_aton(optarg, &in_addr)) { | ||||
printk(KERN_ERR PFX "bad addr string %s\n", | |||||
optarg); | optarg); | ||||
ret = EINVAL; | ret = EINVAL; | ||||
} | } | ||||
memcpy(cb->addr, &in_addr.s_addr, sizeof(in_addr.s_addr)); | |||||
break; | break; | ||||
case 'A': | |||||
cb->addr_str = optarg; | |||||
cb->addr_type = AF_INET6; | |||||
DEBUG_LOG("ipv6addr (%s)\n", optarg); | |||||
ret = EAFNOSUPPORT; /* XXX not supported */ | |||||
break; | |||||
case 'p': | case 'p': | ||||
cb->port = htons(optint); | cb->port = htons(optint); | ||||
DEBUG_LOG(cb, "port %d\n", (int)optint); | DEBUG_LOG("port %d\n", (int)optint); | ||||
break; | break; | ||||
case 'P': | case 'P': | ||||
cb->poll = 1; | cb->poll = 1; | ||||
DEBUG_LOG(cb, "server\n"); | DEBUG_LOG("server\n"); | ||||
break; | break; | ||||
case 's': | case 's': | ||||
cb->server = 1; | cb->server = 1; | ||||
DEBUG_LOG(cb, "server\n"); | DEBUG_LOG("server\n"); | ||||
break; | break; | ||||
case 'c': | case 'c': | ||||
cb->server = 0; | cb->server = 0; | ||||
DEBUG_LOG(cb, "client\n"); | DEBUG_LOG("client\n"); | ||||
break; | break; | ||||
case 'S': | case 'S': | ||||
cb->size = optint; | cb->size = optint; | ||||
if ((cb->size < 1) || | if ((cb->size < 1) || | ||||
(cb->size > RPING_BUFSIZE)) { | (cb->size > RPING_BUFSIZE)) { | ||||
PRINTF(cb, "Invalid size %d " | printk(KERN_ERR PFX "Invalid size %d " | ||||
"(valid range is 1 to %d)\n", | "(valid range is 1 to %d)\n", | ||||
cb->size, RPING_BUFSIZE); | cb->size, RPING_BUFSIZE); | ||||
ret = EINVAL; | ret = EINVAL; | ||||
} else | } else | ||||
DEBUG_LOG(cb, "size %d\n", (int)optint); | DEBUG_LOG("size %d\n", (int)optint); | ||||
break; | break; | ||||
case 'C': | case 'C': | ||||
cb->count = optint; | cb->count = optint; | ||||
if (cb->count < 0) { | if (cb->count < 0) { | ||||
PRINTF(cb, "Invalid count %d\n", | printk(KERN_ERR PFX "Invalid count %d\n", | ||||
cb->count); | cb->count); | ||||
ret = EINVAL; | ret = EINVAL; | ||||
} else | } else | ||||
DEBUG_LOG(cb, "count %d\n", (int) cb->count); | DEBUG_LOG("count %d\n", (int) cb->count); | ||||
break; | break; | ||||
case 'v': | case 'v': | ||||
cb->verbose++; | cb->verbose++; | ||||
DEBUG_LOG(cb, "verbose\n"); | DEBUG_LOG("verbose\n"); | ||||
break; | break; | ||||
case 'V': | case 'V': | ||||
cb->validate++; | cb->validate++; | ||||
DEBUG_LOG(cb, "validate data\n"); | DEBUG_LOG("validate data\n"); | ||||
break; | break; | ||||
case 'l': | case 'l': | ||||
cb->wlat++; | cb->wlat++; | ||||
break; | break; | ||||
case 'L': | case 'L': | ||||
cb->rlat++; | cb->rlat++; | ||||
break; | break; | ||||
case 'B': | case 'B': | ||||
cb->bw++; | cb->bw++; | ||||
break; | break; | ||||
case 'd': | case 'd': | ||||
cb->duplex++; | cb->duplex++; | ||||
break; | break; | ||||
case 'm': | |||||
if (!strncmp(optarg, "dma", 3)) | |||||
cb->mem = DMA; | |||||
else if (!strncmp(optarg, "fastreg", 7)) | |||||
cb->mem = FASTREG; | |||||
else if (!strncmp(optarg, "mw", 2)) | |||||
cb->mem = MW; | |||||
else if (!strncmp(optarg, "mr", 2)) | |||||
cb->mem = MR; | |||||
else { | |||||
PRINTF(cb, "unknown mem mode %s. " | |||||
"Must be dma, fastreg, mw, or mr\n", | |||||
optarg); | |||||
ret = -EINVAL; | |||||
break; | |||||
} | |||||
break; | |||||
case 'I': | case 'I': | ||||
cb->server_invalidate = 1; | cb->server_invalidate = 1; | ||||
break; | break; | ||||
case 'T': | case 'T': | ||||
cb->txdepth = optint; | cb->txdepth = optint; | ||||
DEBUG_LOG(cb, "txdepth %d\n", (int) cb->txdepth); | DEBUG_LOG("txdepth %d\n", (int) cb->txdepth); | ||||
break; | break; | ||||
case 'Z': | case 'Z': | ||||
cb->local_dma_lkey = 1; | cb->local_dma_lkey = 1; | ||||
DEBUG_LOG(cb, "using local dma lkey\n"); | DEBUG_LOG("using local dma lkey\n"); | ||||
break; | break; | ||||
case 'R': | case 'R': | ||||
cb->read_inv = 1; | cb->read_inv = 1; | ||||
DEBUG_LOG(cb, "using read-with-inv\n"); | DEBUG_LOG("using read-with-inv\n"); | ||||
break; | break; | ||||
case 'f': | case 'f': | ||||
cb->frtest = 1; | cb->frtest = 1; | ||||
cb->testnum = optint; | DEBUG_LOG("fast-reg test!\n"); | ||||
DEBUG_LOG(cb, "fast-reg test!\n"); | |||||
break; | break; | ||||
default: | default: | ||||
PRINTF(cb, "unknown opt %s\n", optarg); | printk(KERN_ERR PFX "unknown opt %s\n", optarg); | ||||
ret = -EINVAL; | ret = -EINVAL; | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
if (ret) | if (ret) | ||||
goto out; | goto out; | ||||
if (cb->server == -1) { | if (cb->server == -1) { | ||||
PRINTF(cb, "must be either client or server\n"); | printk(KERN_ERR PFX "must be either client or server\n"); | ||||
ret = -EINVAL; | ret = -EINVAL; | ||||
goto out; | goto out; | ||||
} | } | ||||
if ((cb->frtest + cb->bw + cb->rlat + cb->wlat) > 1) { | if (cb->server && cb->frtest) { | ||||
PRINTF(cb, "Pick only one test: fr, bw, rlat, wlat\n"); | printk(KERN_ERR PFX "must be client to run frtest\n"); | ||||
ret = -EINVAL; | ret = -EINVAL; | ||||
goto out; | goto out; | ||||
} | } | ||||
if (cb->server_invalidate && cb->mem != FASTREG) { | |||||
PRINTF(cb, "server_invalidate only valid with fastreg mem_mode\n"); | |||||
ret = -EINVAL; | |||||
goto out; | |||||
} | |||||
if (cb->read_inv && cb->mem != FASTREG) { | if ((cb->frtest + cb->bw + cb->rlat + cb->wlat) > 1) { | ||||
PRINTF(cb, "read_inv only valid with fastreg mem_mode\n"); | printk(KERN_ERR PFX "Pick only one test: fr, bw, rlat, wlat\n"); | ||||
ret = -EINVAL; | ret = -EINVAL; | ||||
goto out; | goto out; | ||||
} | } | ||||
if (cb->mem != MR && (cb->wlat || cb->rlat || cb->bw || cb->frtest)) { | if (cb->wlat || cb->rlat || cb->bw) { | ||||
PRINTF(cb, "wlat, rlat, and bw tests only support mem_mode MR\n"); | printk(KERN_ERR PFX "wlat, rlat, and bw tests only support mem_mode MR - which is no longer supported\n"); | ||||
ret = -EINVAL; | ret = -EINVAL; | ||||
goto out; | goto out; | ||||
} | } | ||||
cb->cm_id = rdma_create_id(krping_cma_event_handler, cb, RDMA_PS_TCP, IB_QPT_RC); | cb->cm_id = rdma_create_id(&init_net, krping_cma_event_handler, cb, RDMA_PS_TCP, IB_QPT_RC); | ||||
if (IS_ERR(cb->cm_id)) { | if (IS_ERR(cb->cm_id)) { | ||||
ret = PTR_ERR(cb->cm_id); | ret = PTR_ERR(cb->cm_id); | ||||
PRINTF(cb, "rdma_create_id error %d\n", ret); | printk(KERN_ERR PFX "rdma_create_id error %d\n", ret); | ||||
goto out; | goto out; | ||||
} | } | ||||
DEBUG_LOG(cb, "created cm_id %p\n", cb->cm_id); | DEBUG_LOG("created cm_id %p\n", cb->cm_id); | ||||
if (cb->server) | if (cb->server) | ||||
krping_run_server(cb); | krping_run_server(cb); | ||||
else | else | ||||
krping_run_client(cb); | krping_run_client(cb); | ||||
DEBUG_LOG(cb, "destroy cm_id %p\n", cb->cm_id); | DEBUG_LOG("destroy cm_id %p\n", cb->cm_id); | ||||
rdma_destroy_id(cb->cm_id); | rdma_destroy_id(cb->cm_id); | ||||
out: | out: | ||||
mutex_lock(&krping_mutex); | mutex_lock(&krping_mutex); | ||||
list_del(&cb->list); | list_del(&cb->list); | ||||
mutex_unlock(&krping_mutex); | mutex_unlock(&krping_mutex); | ||||
kfree(cb); | kfree(cb); | ||||
return ret; | return ret; | ||||
} | } | ||||
void | void | ||||
krping_walk_cb_list(void (*f)(struct krping_stats *, void *), void *arg) | krping_walk_cb_list(void (*f)(struct krping_stats *, void *), void *arg) | ||||
{ | { | ||||
struct krping_cb *cb; | struct krping_cb *cb; | ||||
mutex_lock(&krping_mutex); | mutex_lock(&krping_mutex); | ||||
list_for_each_entry(cb, &krping_cbs, list) | list_for_each_entry(cb, &krping_cbs, list) | ||||
(*f)(cb->pd ? &cb->stats : NULL, arg); | (*f)(cb->pd ? &cb->stats : NULL, arg); | ||||
mutex_unlock(&krping_mutex); | mutex_unlock(&krping_mutex); | ||||
} | |||||
void krping_init(void) | |||||
{ | |||||
mutex_init(&krping_mutex); | |||||
} | } |