1fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker/* 2fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * linux/fs/9p/trans_rdma.c 3fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * 4fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * RDMA transport layer based on the trans_fd.c implementation. 5fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * 6fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * Copyright (C) 2008 by Tom Tucker <tom@opengridcomputing.com> 7fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * Copyright (C) 2006 by Russ Cox <rsc@swtch.com> 8fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * Copyright (C) 2004-2005 by Latchesar Ionkov <lucho@ionkov.net> 9fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * Copyright (C) 2004-2008 by Eric Van Hensbergen <ericvh@gmail.com> 10fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * Copyright (C) 1997-2002 by Ron Minnich <rminnich@sarnoff.com> 11fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * 12fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * This program is free software; you can redistribute it and/or modify 13fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * it under the terms of the GNU General Public License version 2 14fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * as published by the Free Software Foundation. 15fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * 16fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * This program is distributed in the hope that it will be useful, 17fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * but WITHOUT ANY WARRANTY; without even the implied warranty of 18fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * GNU General Public License for more details. 20fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * 21fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * You should have received a copy of the GNU General Public License 22fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * along with this program; if not, write to: 23fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * Free Software Foundation 24fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * 51 Franklin Street, Fifth Floor 25fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * Boston, MA 02111-1301 USA 26fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * 27fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker */ 28fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 295d3851530d6d68564e4e0ce04d0547d4d106fc72Joe Perches#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 305d3851530d6d68564e4e0ce04d0547d4d106fc72Joe Perches 31fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker#include <linux/in.h> 32fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker#include <linux/module.h> 33fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker#include <linux/net.h> 34fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker#include <linux/ipv6.h> 35fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker#include <linux/kthread.h> 36fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker#include <linux/errno.h> 37fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker#include <linux/kernel.h> 38fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker#include <linux/un.h> 39fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker#include <linux/uaccess.h> 40fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker#include <linux/inet.h> 41fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker#include <linux/idr.h> 42fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker#include <linux/file.h> 43fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker#include <linux/parser.h> 44fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker#include <linux/semaphore.h> 455a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 46fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker#include <net/9p/9p.h> 47fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker#include <net/9p/client.h> 48fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker#include <net/9p/transport.h> 49fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker#include <rdma/ib_verbs.h> 50fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker#include <rdma/rdma_cm.h> 51fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 52fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker#define P9_PORT 5640 53fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker#define P9_RDMA_SQ_DEPTH 32 54fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker#define P9_RDMA_RQ_DEPTH 32 55fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker#define P9_RDMA_SEND_SGE 4 56fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker#define P9_RDMA_RECV_SGE 4 57fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker#define P9_RDMA_IRD 0 58fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker#define P9_RDMA_ORD 0 59fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker#define P9_RDMA_TIMEOUT 30000 /* 30 seconds */ 60fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker#define P9_RDMA_MAXSIZE (4*4096) /* Min SGE is 4, so we can 61fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * safely advertise a maxsize 62fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * of 64k */ 63fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 64fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker/** 65fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * struct p9_trans_rdma - RDMA transport instance 66fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * 67fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * @state: tracks the transport state machine for connection setup and tear down 68fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * @cm_id: The RDMA CM ID 69fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * @pd: Protection Domain pointer 70fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * @qp: Queue Pair pointer 71fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * @cq: Completion Queue pointer 720e15597ebfe00e28857185f46aba00f400480ffeAbhishek Kulkarni * @dm_mr: DMA Memory Region pointer 73fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * @lkey: The local access only memory region key 74fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * @timeout: Number of uSecs to wait for connection management events 75fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * @sq_depth: The depth of the Send Queue 76fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * @sq_sem: Semaphore for the SQ 77fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * @rq_depth: The depth of the Receive Queue. 780e15597ebfe00e28857185f46aba00f400480ffeAbhishek Kulkarni * @rq_count: Count of requests in the Receive Queue. 79fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * @addr: The remote peer's address 80fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * @req_lock: Protects the active request list 81fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * @cm_done: Completion event for connection management tracking 82fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker */ 83fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tuckerstruct p9_trans_rdma { 84fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker enum { 85fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker P9_RDMA_INIT, 86fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker P9_RDMA_ADDR_RESOLVED, 87fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker P9_RDMA_ROUTE_RESOLVED, 88fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker P9_RDMA_CONNECTED, 89fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker P9_RDMA_FLUSHING, 90fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker P9_RDMA_CLOSING, 91fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker P9_RDMA_CLOSED, 92fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker } state; 93fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker struct rdma_cm_id *cm_id; 94fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker struct ib_pd *pd; 95fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker struct ib_qp *qp; 96fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker struct ib_cq *cq; 97fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker struct ib_mr *dma_mr; 98fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker u32 lkey; 99fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker long timeout; 100fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker int sq_depth; 101fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker struct semaphore sq_sem; 102fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker int rq_depth; 103fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker atomic_t rq_count; 104fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker struct sockaddr_in addr; 105fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker spinlock_t req_lock; 106fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 107fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker struct completion cm_done; 108fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker}; 109fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 110fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker/** 111fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * p9_rdma_context - Keeps track of in-process WR 112fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * 113fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * @wc_op: The original WR op for when the CQE completes in error. 114fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * @busa: Bus address to unmap when the WR completes 115fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * @req: Keeps track of requests (send) 116fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * @rc: Keepts track of replies (receive) 117fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker */ 118fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tuckerstruct p9_rdma_req; 119fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tuckerstruct p9_rdma_context { 120fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker enum ib_wc_opcode wc_op; 121fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker dma_addr_t busa; 122fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker union { 123fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker struct p9_req_t *req; 124fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker struct p9_fcall *rc; 125fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker }; 126fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker}; 127fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 128fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker/** 129fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * p9_rdma_opts - Collection of mount options 130fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * @port: port of connection 131fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * @sq_depth: The requested depth of the SQ. This really doesn't need 132fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * to be any deeper than the number of threads used in the client 133fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * @rq_depth: The depth of the RQ. Should be greater than or equal to SQ depth 134fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * @timeout: Time to wait in msecs for CM events 135fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker */ 136fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tuckerstruct p9_rdma_opts { 137fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker short port; 138fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker int sq_depth; 139fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker int rq_depth; 140fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker long timeout; 141fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker}; 142fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 143fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker/* 144fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * Option Parsing (code inspired by NFS code) 145fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker */ 146fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tuckerenum { 147fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker /* Options that take integer arguments */ 148fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker Opt_port, Opt_rq_depth, Opt_sq_depth, Opt_timeout, Opt_err, 149fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker}; 150fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 151fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tuckerstatic match_table_t tokens = { 152fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker {Opt_port, "port=%u"}, 153fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker {Opt_sq_depth, "sq=%u"}, 154fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker {Opt_rq_depth, "rq=%u"}, 155fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker {Opt_timeout, "timeout=%u"}, 156fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker {Opt_err, NULL}, 157fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker}; 158fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 159fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker/** 1600e15597ebfe00e28857185f46aba00f400480ffeAbhishek Kulkarni * parse_opts - parse mount options into rdma options structure 1610e15597ebfe00e28857185f46aba00f400480ffeAbhishek Kulkarni * @params: options string passed from mount 1620e15597ebfe00e28857185f46aba00f400480ffeAbhishek Kulkarni * @opts: rdma transport-specific structure to parse options into 163fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * 164fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * Returns 0 upon success, -ERRNO upon failure 165fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker */ 166fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tuckerstatic int parse_opts(char *params, struct p9_rdma_opts *opts) 167fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker{ 168fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker char *p; 169fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker substring_t args[MAX_OPT_ARGS]; 170fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker int option; 171d8c8a9e36560e9ff4c99279d64ce5dd0e1a33fa6Eric Van Hensbergen char *options, *tmp_options; 172fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 173fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker opts->port = P9_PORT; 174fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker opts->sq_depth = P9_RDMA_SQ_DEPTH; 175fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker opts->rq_depth = P9_RDMA_RQ_DEPTH; 176fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker opts->timeout = P9_RDMA_TIMEOUT; 177fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 178fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker if (!params) 179fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker return 0; 180fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 181d8c8a9e36560e9ff4c99279d64ce5dd0e1a33fa6Eric Van Hensbergen tmp_options = kstrdup(params, GFP_KERNEL); 182d8c8a9e36560e9ff4c99279d64ce5dd0e1a33fa6Eric Van Hensbergen if (!tmp_options) { 1835d3851530d6d68564e4e0ce04d0547d4d106fc72Joe Perches p9_debug(P9_DEBUG_ERROR, 1845d3851530d6d68564e4e0ce04d0547d4d106fc72Joe Perches "failed to allocate copy of option string\n"); 185fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker return -ENOMEM; 186fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker } 187d8c8a9e36560e9ff4c99279d64ce5dd0e1a33fa6Eric Van Hensbergen options = tmp_options; 188fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 189fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker while ((p = strsep(&options, ",")) != NULL) { 190fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker int token; 191fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker int r; 192fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker if (!*p) 193fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker continue; 194fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker token = match_token(p, tokens, args); 195fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker r = match_int(&args[0], &option); 196fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker if (r < 0) { 1975d3851530d6d68564e4e0ce04d0547d4d106fc72Joe Perches p9_debug(P9_DEBUG_ERROR, 1985d3851530d6d68564e4e0ce04d0547d4d106fc72Joe Perches "integer field, but no integer?\n"); 199fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker continue; 200fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker } 201fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker switch (token) { 202fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker case Opt_port: 203fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker opts->port = option; 204fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker break; 205fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker case Opt_sq_depth: 206fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker opts->sq_depth = option; 207fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker break; 208fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker case Opt_rq_depth: 209fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker opts->rq_depth = option; 210fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker break; 211fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker case Opt_timeout: 212fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker opts->timeout = option; 213fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker break; 214fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker default: 215fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker continue; 216fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker } 217fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker } 218fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker /* RQ must be at least as large as the SQ */ 219fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker opts->rq_depth = max(opts->rq_depth, opts->sq_depth); 220d8c8a9e36560e9ff4c99279d64ce5dd0e1a33fa6Eric Van Hensbergen kfree(tmp_options); 221fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker return 0; 222fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker} 223fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 224fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tuckerstatic int 225fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tuckerp9_cm_event_handler(struct rdma_cm_id *id, struct rdma_cm_event *event) 226fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker{ 227fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker struct p9_client *c = id->context; 228fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker struct p9_trans_rdma *rdma = c->trans; 229fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker switch (event->event) { 230fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker case RDMA_CM_EVENT_ADDR_RESOLVED: 231fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker BUG_ON(rdma->state != P9_RDMA_INIT); 232fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker rdma->state = P9_RDMA_ADDR_RESOLVED; 233fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker break; 234fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 235fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker case RDMA_CM_EVENT_ROUTE_RESOLVED: 236fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker BUG_ON(rdma->state != P9_RDMA_ADDR_RESOLVED); 237fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker rdma->state = P9_RDMA_ROUTE_RESOLVED; 238fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker break; 239fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 240fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker case RDMA_CM_EVENT_ESTABLISHED: 241fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker BUG_ON(rdma->state != P9_RDMA_ROUTE_RESOLVED); 242fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker rdma->state = P9_RDMA_CONNECTED; 243fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker break; 244fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 245fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker case RDMA_CM_EVENT_DISCONNECTED: 246fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker if (rdma) 247fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker rdma->state = P9_RDMA_CLOSED; 248fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker if (c) 249fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker c->status = Disconnected; 250fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker break; 251fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 252fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker case RDMA_CM_EVENT_TIMEWAIT_EXIT: 253fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker break; 254fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 255fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker case RDMA_CM_EVENT_ADDR_CHANGE: 256fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker case RDMA_CM_EVENT_ROUTE_ERROR: 257fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker case RDMA_CM_EVENT_DEVICE_REMOVAL: 258fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker case RDMA_CM_EVENT_MULTICAST_JOIN: 259fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker case RDMA_CM_EVENT_MULTICAST_ERROR: 260fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker case RDMA_CM_EVENT_REJECTED: 261fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker case RDMA_CM_EVENT_CONNECT_REQUEST: 262fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker case RDMA_CM_EVENT_CONNECT_RESPONSE: 263fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker case RDMA_CM_EVENT_CONNECT_ERROR: 264fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker case RDMA_CM_EVENT_ADDR_ERROR: 265fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker case RDMA_CM_EVENT_UNREACHABLE: 266fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker c->status = Disconnected; 267fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker rdma_disconnect(rdma->cm_id); 268fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker break; 269fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker default: 270fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker BUG(); 271fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker } 272fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker complete(&rdma->cm_done); 273fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker return 0; 274fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker} 275fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 276fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tuckerstatic void 277fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tuckerhandle_recv(struct p9_client *client, struct p9_trans_rdma *rdma, 278fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker struct p9_rdma_context *c, enum ib_wc_status status, u32 byte_len) 279fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker{ 280fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker struct p9_req_t *req; 281fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker int err = 0; 282fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker int16_t tag; 283fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 284fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker req = NULL; 285fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker ib_dma_unmap_single(rdma->cm_id->device, c->busa, client->msize, 286fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker DMA_FROM_DEVICE); 287fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 288fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker if (status != IB_WC_SUCCESS) 289fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker goto err_out; 290fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 291fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker err = p9_parse_header(c->rc, NULL, NULL, &tag, 1); 292fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker if (err) 293fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker goto err_out; 294fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 295fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker req = p9_tag_lookup(client, tag); 296fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker if (!req) 297fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker goto err_out; 298fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 299fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker req->rc = c->rc; 3001bab88b2310998de18b32529a27ea835d164254aLatchesar Ionkov req->status = REQ_STATUS_RCVD; 301fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker p9_client_cb(client, req); 302fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 303fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker return; 304fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 305fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker err_out: 3065d3851530d6d68564e4e0ce04d0547d4d106fc72Joe Perches p9_debug(P9_DEBUG_ERROR, "req %p err %d status %d\n", req, err, status); 307fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker rdma->state = P9_RDMA_FLUSHING; 308fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker client->status = Disconnected; 309fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker} 310fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 311fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tuckerstatic void 312fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tuckerhandle_send(struct p9_client *client, struct p9_trans_rdma *rdma, 313fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker struct p9_rdma_context *c, enum ib_wc_status status, u32 byte_len) 314fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker{ 315fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker ib_dma_unmap_single(rdma->cm_id->device, 316fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker c->busa, c->req->tc->size, 317fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker DMA_TO_DEVICE); 318fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker} 319fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 320fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tuckerstatic void qp_event_handler(struct ib_event *event, void *context) 321fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker{ 3225d3851530d6d68564e4e0ce04d0547d4d106fc72Joe Perches p9_debug(P9_DEBUG_ERROR, "QP event %d context %p\n", 3235d3851530d6d68564e4e0ce04d0547d4d106fc72Joe Perches event->event, context); 324fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker} 325fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 326fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tuckerstatic void cq_comp_handler(struct ib_cq *cq, void *cq_context) 327fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker{ 328fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker struct p9_client *client = cq_context; 329fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker struct p9_trans_rdma *rdma = client->trans; 330fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker int ret; 331fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker struct ib_wc wc; 332fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 333fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker ib_req_notify_cq(rdma->cq, IB_CQ_NEXT_COMP); 334fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker while ((ret = ib_poll_cq(cq, 1, &wc)) > 0) { 335fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker struct p9_rdma_context *c = (void *) (unsigned long) wc.wr_id; 336fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 337fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker switch (c->wc_op) { 338fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker case IB_WC_RECV: 339fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker atomic_dec(&rdma->rq_count); 340fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker handle_recv(client, rdma, c, wc.status, wc.byte_len); 341fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker break; 342fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 343fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker case IB_WC_SEND: 344fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker handle_send(client, rdma, c, wc.status, wc.byte_len); 345fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker up(&rdma->sq_sem); 346fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker break; 347fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 348fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker default: 3495d3851530d6d68564e4e0ce04d0547d4d106fc72Joe Perches pr_err("unexpected completion type, c->wc_op=%d, wc.opcode=%d, status=%d\n", 350fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker c->wc_op, wc.opcode, wc.status); 351fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker break; 352fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker } 353fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker kfree(c); 354fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker } 355fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker} 356fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 357fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tuckerstatic void cq_event_handler(struct ib_event *e, void *v) 358fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker{ 3595d3851530d6d68564e4e0ce04d0547d4d106fc72Joe Perches p9_debug(P9_DEBUG_ERROR, "CQ event %d context %p\n", e->event, v); 360fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker} 361fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 362fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tuckerstatic void rdma_destroy_trans(struct p9_trans_rdma *rdma) 363fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker{ 364fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker if (!rdma) 365fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker return; 366fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 367fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker if (rdma->dma_mr && !IS_ERR(rdma->dma_mr)) 368fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker ib_dereg_mr(rdma->dma_mr); 369fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 370fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker if (rdma->qp && !IS_ERR(rdma->qp)) 371fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker ib_destroy_qp(rdma->qp); 372fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 373fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker if (rdma->pd && !IS_ERR(rdma->pd)) 374fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker ib_dealloc_pd(rdma->pd); 375fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 376fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker if (rdma->cq && !IS_ERR(rdma->cq)) 377fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker ib_destroy_cq(rdma->cq); 378fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 379fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker if (rdma->cm_id && !IS_ERR(rdma->cm_id)) 380fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker rdma_destroy_id(rdma->cm_id); 381fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 382fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker kfree(rdma); 383fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker} 384fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 385fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tuckerstatic int 386fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tuckerpost_recv(struct p9_client *client, struct p9_rdma_context *c) 387fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker{ 388fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker struct p9_trans_rdma *rdma = client->trans; 389fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker struct ib_recv_wr wr, *bad_wr; 390fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker struct ib_sge sge; 391fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 392fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker c->busa = ib_dma_map_single(rdma->cm_id->device, 393fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker c->rc->sdata, client->msize, 394fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker DMA_FROM_DEVICE); 395fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker if (ib_dma_mapping_error(rdma->cm_id->device, c->busa)) 396fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker goto error; 397fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 398fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker sge.addr = c->busa; 399fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker sge.length = client->msize; 400fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker sge.lkey = rdma->lkey; 401fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 402fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker wr.next = NULL; 403fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker c->wc_op = IB_WC_RECV; 404fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker wr.wr_id = (unsigned long) c; 405fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker wr.sg_list = &sge; 406fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker wr.num_sge = 1; 407fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker return ib_post_recv(rdma->qp, &wr, &bad_wr); 408fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 409fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker error: 4105d3851530d6d68564e4e0ce04d0547d4d106fc72Joe Perches p9_debug(P9_DEBUG_ERROR, "EIO\n"); 411fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker return -EIO; 412fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker} 413fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 414fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tuckerstatic int rdma_request(struct p9_client *client, struct p9_req_t *req) 415fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker{ 416fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker struct p9_trans_rdma *rdma = client->trans; 417fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker struct ib_send_wr wr, *bad_wr; 418fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker struct ib_sge sge; 419fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker int err = 0; 420fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker unsigned long flags; 421fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker struct p9_rdma_context *c = NULL; 422fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker struct p9_rdma_context *rpl_context = NULL; 423fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 424fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker /* Allocate an fcall for the reply */ 425eeff66ef6e33925f615d49e6c846263e342ab60eAneesh Kumar K.V rpl_context = kmalloc(sizeof *rpl_context, GFP_NOFS); 4261d6400c7c9cfd38976b25d55b357200ad3ff1be9Davidlohr Bueso if (!rpl_context) { 4271d6400c7c9cfd38976b25d55b357200ad3ff1be9Davidlohr Bueso err = -ENOMEM; 428fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker goto err_close; 4291d6400c7c9cfd38976b25d55b357200ad3ff1be9Davidlohr Bueso } 430fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 431fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker /* 432fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * If the request has a buffer, steal it, otherwise 433fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * allocate a new one. Typically, requests should already 434fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * have receive buffers allocated and just swap them around 435fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker */ 436fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker if (!req->rc) { 437fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker req->rc = kmalloc(sizeof(struct p9_fcall)+client->msize, 438eeff66ef6e33925f615d49e6c846263e342ab60eAneesh Kumar K.V GFP_NOFS); 439fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker if (req->rc) { 440fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker req->rc->sdata = (char *) req->rc + 441fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker sizeof(struct p9_fcall); 442fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker req->rc->capacity = client->msize; 443fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker } 444fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker } 445fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker rpl_context->rc = req->rc; 446fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker if (!rpl_context->rc) { 4471d6400c7c9cfd38976b25d55b357200ad3ff1be9Davidlohr Bueso err = -ENOMEM; 4481d6400c7c9cfd38976b25d55b357200ad3ff1be9Davidlohr Bueso goto err_free2; 449fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker } 450fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 451fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker /* 452fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * Post a receive buffer for this request. We need to ensure 453fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * there is a reply buffer available for every outstanding 454fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * request. A flushed request can result in no reply for an 455fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * outstanding request, so we must keep a count to avoid 456fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * overflowing the RQ. 457fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker */ 458fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker if (atomic_inc_return(&rdma->rq_count) <= rdma->rq_depth) { 459fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker err = post_recv(client, rpl_context); 4601d6400c7c9cfd38976b25d55b357200ad3ff1be9Davidlohr Bueso if (err) 4611d6400c7c9cfd38976b25d55b357200ad3ff1be9Davidlohr Bueso goto err_free1; 462fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker } else 463fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker atomic_dec(&rdma->rq_count); 464fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 465fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker /* remove posted receive buffer from request structure */ 466fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker req->rc = NULL; 467fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 468fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker /* Post the request */ 469eeff66ef6e33925f615d49e6c846263e342ab60eAneesh Kumar K.V c = kmalloc(sizeof *c, GFP_NOFS); 4701d6400c7c9cfd38976b25d55b357200ad3ff1be9Davidlohr Bueso if (!c) { 4711d6400c7c9cfd38976b25d55b357200ad3ff1be9Davidlohr Bueso err = -ENOMEM; 4721d6400c7c9cfd38976b25d55b357200ad3ff1be9Davidlohr Bueso goto err_free1; 4731d6400c7c9cfd38976b25d55b357200ad3ff1be9Davidlohr Bueso } 474fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker c->req = req; 475fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 476fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker c->busa = ib_dma_map_single(rdma->cm_id->device, 477fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker c->req->tc->sdata, c->req->tc->size, 478fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker DMA_TO_DEVICE); 479fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker if (ib_dma_mapping_error(rdma->cm_id->device, c->busa)) 480fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker goto error; 481fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 482fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker sge.addr = c->busa; 483fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker sge.length = c->req->tc->size; 484fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker sge.lkey = rdma->lkey; 485fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 486fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker wr.next = NULL; 487fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker c->wc_op = IB_WC_SEND; 488fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker wr.wr_id = (unsigned long) c; 489fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker wr.opcode = IB_WR_SEND; 490fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker wr.send_flags = IB_SEND_SIGNALED; 491fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker wr.sg_list = &sge; 492fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker wr.num_sge = 1; 493fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 494fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker if (down_interruptible(&rdma->sq_sem)) 495fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker goto error; 496fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 497fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker return ib_post_send(rdma->qp, &wr, &bad_wr); 498fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 499fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker error: 5001d6400c7c9cfd38976b25d55b357200ad3ff1be9Davidlohr Bueso kfree(c); 5011d6400c7c9cfd38976b25d55b357200ad3ff1be9Davidlohr Bueso kfree(rpl_context->rc); 5021d6400c7c9cfd38976b25d55b357200ad3ff1be9Davidlohr Bueso kfree(rpl_context); 5035d3851530d6d68564e4e0ce04d0547d4d106fc72Joe Perches p9_debug(P9_DEBUG_ERROR, "EIO\n"); 504fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker return -EIO; 5051d6400c7c9cfd38976b25d55b357200ad3ff1be9Davidlohr Bueso err_free1: 5061d6400c7c9cfd38976b25d55b357200ad3ff1be9Davidlohr Bueso kfree(rpl_context->rc); 5071d6400c7c9cfd38976b25d55b357200ad3ff1be9Davidlohr Bueso err_free2: 5081d6400c7c9cfd38976b25d55b357200ad3ff1be9Davidlohr Bueso kfree(rpl_context); 509fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker err_close: 510fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker spin_lock_irqsave(&rdma->req_lock, flags); 511fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker if (rdma->state < P9_RDMA_CLOSING) { 512fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker rdma->state = P9_RDMA_CLOSING; 513fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker spin_unlock_irqrestore(&rdma->req_lock, flags); 514fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker rdma_disconnect(rdma->cm_id); 515fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker } else 516fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker spin_unlock_irqrestore(&rdma->req_lock, flags); 517fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker return err; 518fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker} 519fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 520fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tuckerstatic void rdma_close(struct p9_client *client) 521fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker{ 522fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker struct p9_trans_rdma *rdma; 523fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 524fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker if (!client) 525fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker return; 526fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 527fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker rdma = client->trans; 528fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker if (!rdma) 529fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker return; 530fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 531fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker client->status = Disconnected; 532fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker rdma_disconnect(rdma->cm_id); 533fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker rdma_destroy_trans(rdma); 534fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker} 535fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 536fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker/** 537fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * alloc_rdma - Allocate and initialize the rdma transport structure 538fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * @opts: Mount options structure 539fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker */ 540fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tuckerstatic struct p9_trans_rdma *alloc_rdma(struct p9_rdma_opts *opts) 541fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker{ 542fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker struct p9_trans_rdma *rdma; 543fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 544fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker rdma = kzalloc(sizeof(struct p9_trans_rdma), GFP_KERNEL); 545fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker if (!rdma) 546fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker return NULL; 547fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 548fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker rdma->sq_depth = opts->sq_depth; 549fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker rdma->rq_depth = opts->rq_depth; 550fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker rdma->timeout = opts->timeout; 551fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker spin_lock_init(&rdma->req_lock); 552fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker init_completion(&rdma->cm_done); 553fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker sema_init(&rdma->sq_sem, rdma->sq_depth); 554fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker atomic_set(&rdma->rq_count, 0); 555fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 556fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker return rdma; 557fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker} 558fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 559fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker/* its not clear to me we can do anything after send has been posted */ 560fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tuckerstatic int rdma_cancel(struct p9_client *client, struct p9_req_t *req) 561fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker{ 562fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker return 1; 563fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker} 564fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 565fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker/** 566fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * trans_create_rdma - Transport method for creating atransport instance 567fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * @client: client instance 568fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * @addr: IP address string 569fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * @args: Mount options string 570fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker */ 571fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tuckerstatic int 572fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tuckerrdma_create_trans(struct p9_client *client, const char *addr, char *args) 573fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker{ 574fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker int err; 575fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker struct p9_rdma_opts opts; 576fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker struct p9_trans_rdma *rdma; 577fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker struct rdma_conn_param conn_param; 578fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker struct ib_qp_init_attr qp_attr; 579fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker struct ib_device_attr devattr; 580fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 581fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker /* Parse the transport specific mount options */ 582fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker err = parse_opts(args, &opts); 583fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker if (err < 0) 584fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker return err; 585fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 586fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker /* Create and initialize the RDMA transport structure */ 587fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker rdma = alloc_rdma(&opts); 588fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker if (!rdma) 589fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker return -ENOMEM; 590fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 591fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker /* Create the RDMA CM ID */ 592b26f9b9949013fec31b23c426fc463164ae08891Sean Hefty rdma->cm_id = rdma_create_id(p9_cm_event_handler, client, RDMA_PS_TCP, 593b26f9b9949013fec31b23c426fc463164ae08891Sean Hefty IB_QPT_RC); 594fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker if (IS_ERR(rdma->cm_id)) 595fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker goto error; 596fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 597517ac45af4b55913587279d89001171c222f22e7Tom Tucker /* Associate the client with the transport */ 598517ac45af4b55913587279d89001171c222f22e7Tom Tucker client->trans = rdma; 599517ac45af4b55913587279d89001171c222f22e7Tom Tucker 600fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker /* Resolve the server's address */ 601fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker rdma->addr.sin_family = AF_INET; 602fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker rdma->addr.sin_addr.s_addr = in_aton(addr); 603fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker rdma->addr.sin_port = htons(opts.port); 604fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker err = rdma_resolve_addr(rdma->cm_id, NULL, 605fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker (struct sockaddr *)&rdma->addr, 606fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker rdma->timeout); 607fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker if (err) 608fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker goto error; 609fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker err = wait_for_completion_interruptible(&rdma->cm_done); 610fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker if (err || (rdma->state != P9_RDMA_ADDR_RESOLVED)) 611fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker goto error; 612fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 613fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker /* Resolve the route to the server */ 614fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker err = rdma_resolve_route(rdma->cm_id, rdma->timeout); 615fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker if (err) 616fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker goto error; 617fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker err = wait_for_completion_interruptible(&rdma->cm_done); 618fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker if (err || (rdma->state != P9_RDMA_ROUTE_RESOLVED)) 619fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker goto error; 620fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 621fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker /* Query the device attributes */ 622fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker err = ib_query_device(rdma->cm_id->device, &devattr); 623fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker if (err) 624fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker goto error; 625fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 626fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker /* Create the Completion Queue */ 627fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker rdma->cq = ib_create_cq(rdma->cm_id->device, cq_comp_handler, 628fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker cq_event_handler, client, 629fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker opts.sq_depth + opts.rq_depth + 1, 0); 630fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker if (IS_ERR(rdma->cq)) 631fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker goto error; 632fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker ib_req_notify_cq(rdma->cq, IB_CQ_NEXT_COMP); 633fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 634fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker /* Create the Protection Domain */ 635fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker rdma->pd = ib_alloc_pd(rdma->cm_id->device); 636fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker if (IS_ERR(rdma->pd)) 637fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker goto error; 638fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 639fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker /* Cache the DMA lkey in the transport */ 640fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker rdma->dma_mr = NULL; 641fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker if (devattr.device_cap_flags & IB_DEVICE_LOCAL_DMA_LKEY) 642fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker rdma->lkey = rdma->cm_id->device->local_dma_lkey; 643fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker else { 644fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker rdma->dma_mr = ib_get_dma_mr(rdma->pd, IB_ACCESS_LOCAL_WRITE); 645fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker if (IS_ERR(rdma->dma_mr)) 646fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker goto error; 647fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker rdma->lkey = rdma->dma_mr->lkey; 648fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker } 649fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 650fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker /* Create the Queue Pair */ 651fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker memset(&qp_attr, 0, sizeof qp_attr); 652fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker qp_attr.event_handler = qp_event_handler; 653fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker qp_attr.qp_context = client; 654fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker qp_attr.cap.max_send_wr = opts.sq_depth; 655fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker qp_attr.cap.max_recv_wr = opts.rq_depth; 656fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker qp_attr.cap.max_send_sge = P9_RDMA_SEND_SGE; 657fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker qp_attr.cap.max_recv_sge = P9_RDMA_RECV_SGE; 658fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker qp_attr.sq_sig_type = IB_SIGNAL_REQ_WR; 659fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker qp_attr.qp_type = IB_QPT_RC; 660fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker qp_attr.send_cq = rdma->cq; 661fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker qp_attr.recv_cq = rdma->cq; 662fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker err = rdma_create_qp(rdma->cm_id, rdma->pd, &qp_attr); 663fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker if (err) 664fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker goto error; 665fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker rdma->qp = rdma->cm_id->qp; 666fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 667fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker /* Request a connection */ 668fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker memset(&conn_param, 0, sizeof(conn_param)); 669fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker conn_param.private_data = NULL; 670fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker conn_param.private_data_len = 0; 671fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker conn_param.responder_resources = P9_RDMA_IRD; 672fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker conn_param.initiator_depth = P9_RDMA_ORD; 673fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker err = rdma_connect(rdma->cm_id, &conn_param); 674fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker if (err) 675fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker goto error; 676fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker err = wait_for_completion_interruptible(&rdma->cm_done); 677fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker if (err || (rdma->state != P9_RDMA_CONNECTED)) 678fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker goto error; 679fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 680fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker client->status = Connected; 681fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 682fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker return 0; 683fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 684fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tuckererror: 685fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker rdma_destroy_trans(rdma); 686fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker return -ENOTCONN; 687fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker} 688fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 689fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tuckerstatic struct p9_trans_module p9_rdma_trans = { 690fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker .name = "rdma", 691fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker .maxsize = P9_RDMA_MAXSIZE, 692fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker .def = 0, 693fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker .owner = THIS_MODULE, 694fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker .create = rdma_create_trans, 695fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker .close = rdma_close, 696fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker .request = rdma_request, 697fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker .cancel = rdma_cancel, 698fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker}; 699fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 700fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker/** 701fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker * p9_trans_rdma_init - Register the 9P RDMA transport driver 702fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker */ 703fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tuckerstatic int __init p9_trans_rdma_init(void) 704fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker{ 705fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker v9fs_register_trans(&p9_rdma_trans); 706fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker return 0; 707fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker} 708fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 709fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tuckerstatic void __exit p9_trans_rdma_exit(void) 710fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker{ 711fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker v9fs_unregister_trans(&p9_rdma_trans); 712fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker} 713fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 714fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tuckermodule_init(p9_trans_rdma_init); 715fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tuckermodule_exit(p9_trans_rdma_exit); 716fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom Tucker 717fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom TuckerMODULE_AUTHOR("Tom Tucker <tom@opengridcomputing.com>"); 718fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom TuckerMODULE_DESCRIPTION("RDMA Transport for 9P"); 719fc79d4b104f0eb8c2a7242150eaf8756ced4c344Tom TuckerMODULE_LICENSE("Dual BSD/GPL"); 720