// SPDX-License-Identifier: GPL-2.0-only /* * RDMA transport layer based on the trans_fd.c implementation. * * Copyright (C) 2008 by Tom Tucker <[email protected]> * Copyright (C) 2006 by Russ Cox <[email protected]> * Copyright (C) 2004-2005 by Latchesar Ionkov <[email protected]> * Copyright (C) 2004-2008 by Eric Van Hensbergen <[email protected]> * Copyright (C) 1997-2002 by Ron Minnich <[email protected]> */ #define pr_fmt(fmt) … #include <linux/in.h> #include <linux/module.h> #include <linux/net.h> #include <linux/ipv6.h> #include <linux/kthread.h> #include <linux/errno.h> #include <linux/kernel.h> #include <linux/un.h> #include <linux/uaccess.h> #include <linux/inet.h> #include <linux/file.h> #include <linux/parser.h> #include <linux/semaphore.h> #include <linux/slab.h> #include <linux/seq_file.h> #include <net/9p/9p.h> #include <net/9p/client.h> #include <net/9p/transport.h> #include <rdma/ib_verbs.h> #include <rdma/rdma_cm.h> #define P9_PORT … #define P9_RDMA_SQ_DEPTH … #define P9_RDMA_RQ_DEPTH … #define P9_RDMA_SEND_SGE … #define P9_RDMA_RECV_SGE … #define P9_RDMA_IRD … #define P9_RDMA_ORD … #define P9_RDMA_TIMEOUT … #define P9_RDMA_MAXSIZE … /** * struct p9_trans_rdma - RDMA transport instance * * @state: tracks the transport state machine for connection setup and tear down * @cm_id: The RDMA CM ID * @pd: Protection Domain pointer * @qp: Queue Pair pointer * @cq: Completion Queue pointer * @timeout: Number of uSecs to wait for connection management events * @privport: Whether a privileged port may be used * @port: The port to use * @sq_depth: The depth of the Send Queue * @sq_sem: Semaphore for the SQ * @rq_depth: The depth of the Receive Queue. * @rq_sem: Semaphore for the RQ * @excess_rc : Amount of posted Receive Contexts without a pending request. * See rdma_request() * @addr: The remote peer's address * @req_lock: Protects the active request list * @cm_done: Completion event for connection management tracking */ struct p9_trans_rdma { … }; struct p9_rdma_req; /** * struct p9_rdma_context - Keeps track of in-process WR * * @cqe: completion queue entry * @busa: Bus address to unmap when the WR completes * @req: Keeps track of requests (send) * @rc: Keepts track of replies (receive) */ struct p9_rdma_context { … }; /** * struct p9_rdma_opts - Collection of mount options * @port: port of connection * @privport: Whether a privileged port may be used * @sq_depth: The requested depth of the SQ. This really doesn't need * to be any deeper than the number of threads used in the client * @rq_depth: The depth of the RQ. Should be greater than or equal to SQ depth * @timeout: Time to wait in msecs for CM events */ struct p9_rdma_opts { … }; /* * Option Parsing (code inspired by NFS code) */ enum { … }; static match_table_t tokens = …; static int p9_rdma_show_options(struct seq_file *m, struct p9_client *clnt) { … } /** * parse_opts - parse mount options into rdma options structure * @params: options string passed from mount * @opts: rdma transport-specific structure to parse options into * * Returns 0 upon success, -ERRNO upon failure */ static int parse_opts(char *params, struct p9_rdma_opts *opts) { … } static int p9_cm_event_handler(struct rdma_cm_id *id, struct rdma_cm_event *event) { … } static void recv_done(struct ib_cq *cq, struct ib_wc *wc) { … } static void send_done(struct ib_cq *cq, struct ib_wc *wc) { … } static void qp_event_handler(struct ib_event *event, void *context) { … } static void rdma_destroy_trans(struct p9_trans_rdma *rdma) { … } static int post_recv(struct p9_client *client, struct p9_rdma_context *c) { … } static int rdma_request(struct p9_client *client, struct p9_req_t *req) { … } static void rdma_close(struct p9_client *client) { … } /** * alloc_rdma - Allocate and initialize the rdma transport structure * @opts: Mount options structure */ static struct p9_trans_rdma *alloc_rdma(struct p9_rdma_opts *opts) { … } static int rdma_cancel(struct p9_client *client, struct p9_req_t *req) { … } /* A request has been fully flushed without a reply. * That means we have posted one buffer in excess. */ static int rdma_cancelled(struct p9_client *client, struct p9_req_t *req) { … } static int p9_rdma_bind_privport(struct p9_trans_rdma *rdma) { … } /** * rdma_create_trans - Transport method for creating a transport instance * @client: client instance * @addr: IP address string * @args: Mount options string */ static int rdma_create_trans(struct p9_client *client, const char *addr, char *args) { … } static struct p9_trans_module p9_rdma_trans = …; /** * p9_trans_rdma_init - Register the 9P RDMA transport driver */ static int __init p9_trans_rdma_init(void) { … } static void __exit p9_trans_rdma_exit(void) { … } module_init(…) …; module_exit(p9_trans_rdma_exit); MODULE_ALIAS_9P(…) …; MODULE_AUTHOR(…) …; MODULE_DESCRIPTION(…) …; MODULE_LICENSE(…) …;