--- /dev/null
+Bottom: ff25a98f5caa5889dfa52d7e2a6a9aa3e69b3ee5
+Top: 261f148eb3217529a654c1d876ec3902e40bcc3d
+Author: Sean Hefty <sean.hefty@intel.com>
+Date: 2012-09-28 10:36:41 -0700
+
+Refresh of xrcd
+
+---
+
+diff --git a/include/infiniband/driver.h b/include/infiniband/driver.h
+index f22f287..ce88442 100644
+--- a/include/infiniband/driver.h
++++ b/include/infiniband/driver.h
+@@ -53,6 +53,17 @@
+ */
+ #define IBV_DEVICE_LIBRARY_EXTENSION rdmav2
+
++enum verbs_xrcd_mask {
++ VERBS_XRCD_HANDLE = 1 << 0,
++ VERBS_XRCD_RESERVED = 1 << 1
++};
++
++struct verbs_xrcd {
++ struct ibv_xrcd xrcd;
++ uint64_t comp_mask;
++ uint32_t handle;
++};
++
+ typedef struct ibv_device *(*ibv_driver_init_func)(const char *uverbs_sys_path,
+ int abi_version);
+ typedef struct verbs_device *(*verbs_driver_init_func)(const char *uverbs_sys_path,
+@@ -78,6 +89,11 @@ int ibv_cmd_alloc_pd(struct ibv_context *context, struct ibv_pd *pd,
+ struct ibv_alloc_pd *cmd, size_t cmd_size,
+ struct ibv_alloc_pd_resp *resp, size_t resp_size);
+ int ibv_cmd_dealloc_pd(struct ibv_pd *pd);
++int ibv_cmd_open_xrcd(struct ibv_context *context, struct verbs_xrcd *xrcd,
++ struct ibv_xrcd_init_attr *attr,
++ struct ibv_open_xrcd *cmd, size_t cmd_size,
++ struct ibv_open_xrcd_resp *resp, size_t resp_size);
++int ibv_cmd_close_xrcd(struct verbs_xrcd *xrcd);
+ #define IBV_CMD_REG_MR_HAS_RESP_PARAMS
+ int ibv_cmd_reg_mr(struct ibv_pd *pd, void *addr, size_t length,
+ uint64_t hca_va, int access,
+diff --git a/include/infiniband/kern-abi.h b/include/infiniband/kern-abi.h
+index 619ea7e..d7c673f 100644
+--- a/include/infiniband/kern-abi.h
++++ b/include/infiniband/kern-abi.h
+@@ -85,7 +85,9 @@ enum {
+ IB_USER_VERBS_CMD_MODIFY_SRQ,
+ IB_USER_VERBS_CMD_QUERY_SRQ,
+ IB_USER_VERBS_CMD_DESTROY_SRQ,
+- IB_USER_VERBS_CMD_POST_SRQ_RECV
++ IB_USER_VERBS_CMD_POST_SRQ_RECV,
++ IB_USER_VERBS_CMD_OPEN_XRCD,
++ IB_USER_VERBS_CMD_CLOSE_XRCD,
+ };
+
+ /*
+@@ -246,6 +248,27 @@ struct ibv_dealloc_pd {
+ __u32 pd_handle;
+ };
+
++struct ibv_open_xrcd {
++ __u32 command;
++ __u16 in_words;
++ __u16 out_words;
++ __u64 response;
++ __u32 fd;
++ __u32 oflags;
++ __u64 driver_data[0];
++};
++
++struct ibv_open_xrcd_resp {
++ __u32 xrcd_handle;
++};
++
++struct ibv_close_xrcd {
++ __u32 command;
++ __u16 in_words;
++ __u16 out_words;
++ __u32 xrcd_handle;
++};
++
+ struct ibv_reg_mr {
+ __u32 command;
+ __u16 in_words;
+@@ -804,6 +827,8 @@ enum {
+ * trick opcodes in IBV_INIT_CMD() doesn't break.
+ */
+ IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL_V2 = -1,
++ IB_USER_VERBS_CMD_OPEN_XRCD_V2 = -1,
++ IB_USER_VERBS_CMD_CLOSE_XRCD_V2 = -1,
+ };
+
+ struct ibv_destroy_cq_v1 {
+diff --git a/include/infiniband/verbs.h b/include/infiniband/verbs.h
+index d944680..7e32e64 100644
+--- a/include/infiniband/verbs.h
++++ b/include/infiniband/verbs.h
+@@ -1,6 +1,6 @@
+ /*
+ * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
+- * Copyright (c) 2004 Intel Corporation. All rights reserved.
++ * Copyright (c) 2004, 2011-2012 Intel Corporation. All rights reserved.
+ * Copyright (c) 2005, 2006, 2007 Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2005 PathScale, Inc. All rights reserved.
+ *
+@@ -39,6 +39,7 @@
+ #include <stdint.h>
+ #include <pthread.h>
+ #include <stddef.h>
++#include <errno.h>
+
+ #ifdef __cplusplus
+ # define BEGIN_C_DECLS extern "C" {
+@@ -57,20 +58,20 @@
+ BEGIN_C_DECLS
+
+ union ibv_gid {
+- uint8_t raw[16];
++ uint8_t raw[16];
+ struct {
+- uint64_t subnet_prefix;
+- uint64_t interface_id;
++ uint64_t subnet_prefix;
++ uint64_t interface_id;
+ } global;
+ };
+
+ #ifndef container_of
+ /**
+- * container_of - cast a member of a structure out to the containing structure
+- * @ptr: the pointer to the member.
+- * @type: the type of the container struct this is embedded in.
+- * @member: the name of the member within the struct.
+- *
++ * container_of - cast a member of a structure out to the containing structure
++ * @ptr: the pointer to the member.
++ * @type: the type of the container struct this is embedded in.
++ * @member: the name of the member within the struct.
++ *
+ */
+ #define container_of(ptr, type, member) ({\
+ const typeof(((type *)0)->member) * __mptr = (ptr);\
+@@ -78,101 +79,97 @@ union ibv_gid {
+ #endif
+
+ enum ibv_node_type {
+- IBV_NODE_UNKNOWN = -1,
+- IBV_NODE_CA = 1,
++ IBV_NODE_UNKNOWN = -1,
++ IBV_NODE_CA = 1,
+ IBV_NODE_SWITCH,
+ IBV_NODE_ROUTER,
+ IBV_NODE_RNIC
+ };
+
+ enum ibv_transport_type {
+- IBV_TRANSPORT_UNKNOWN = -1,
+- IBV_TRANSPORT_IB = 0,
+- IBV_TRANSPORT_IWARP
++ IBV_TRANSPORT_UNKNOWN = -1, IBV_TRANSPORT_IB = 0, IBV_TRANSPORT_IWARP
+ };
+
+ enum ibv_device_cap_flags {
+- IBV_DEVICE_RESIZE_MAX_WR = 1,
+- IBV_DEVICE_BAD_PKEY_CNTR = 1 << 1,
+- IBV_DEVICE_BAD_QKEY_CNTR = 1 << 2,
+- IBV_DEVICE_RAW_MULTI = 1 << 3,
+- IBV_DEVICE_AUTO_PATH_MIG = 1 << 4,
+- IBV_DEVICE_CHANGE_PHY_PORT = 1 << 5,
+- IBV_DEVICE_UD_AV_PORT_ENFORCE = 1 << 6,
+- IBV_DEVICE_CURR_QP_STATE_MOD = 1 << 7,
+- IBV_DEVICE_SHUTDOWN_PORT = 1 << 8,
+- IBV_DEVICE_INIT_TYPE = 1 << 9,
+- IBV_DEVICE_PORT_ACTIVE_EVENT = 1 << 10,
+- IBV_DEVICE_SYS_IMAGE_GUID = 1 << 11,
+- IBV_DEVICE_RC_RNR_NAK_GEN = 1 << 12,
+- IBV_DEVICE_SRQ_RESIZE = 1 << 13,
+- IBV_DEVICE_N_NOTIFY_CQ = 1 << 14
++ IBV_DEVICE_RESIZE_MAX_WR = 1,
++ IBV_DEVICE_BAD_PKEY_CNTR = 1 << 1,
++ IBV_DEVICE_BAD_QKEY_CNTR = 1 << 2,
++ IBV_DEVICE_RAW_MULTI = 1 << 3,
++ IBV_DEVICE_AUTO_PATH_MIG = 1 << 4,
++ IBV_DEVICE_CHANGE_PHY_PORT = 1 << 5,
++ IBV_DEVICE_UD_AV_PORT_ENFORCE = 1 << 6,
++ IBV_DEVICE_CURR_QP_STATE_MOD = 1 << 7,
++ IBV_DEVICE_SHUTDOWN_PORT = 1 << 8,
++ IBV_DEVICE_INIT_TYPE = 1 << 9,
++ IBV_DEVICE_PORT_ACTIVE_EVENT = 1 << 10,
++ IBV_DEVICE_SYS_IMAGE_GUID = 1 << 11,
++ IBV_DEVICE_RC_RNR_NAK_GEN = 1 << 12,
++ IBV_DEVICE_SRQ_RESIZE = 1 << 13,
++ IBV_DEVICE_N_NOTIFY_CQ = 1 << 14
+ };
+
+ enum ibv_atomic_cap {
+- IBV_ATOMIC_NONE,
+- IBV_ATOMIC_HCA,
+- IBV_ATOMIC_GLOB
++ IBV_ATOMIC_NONE, IBV_ATOMIC_HCA, IBV_ATOMIC_GLOB
+ };
+
+ struct ibv_device_attr {
+- char fw_ver[64];
+- uint64_t node_guid;
+- uint64_t sys_image_guid;
+- uint64_t max_mr_size;
+- uint64_t page_size_cap;
+- uint32_t vendor_id;
+- uint32_t vendor_part_id;
+- uint32_t hw_ver;
+- int max_qp;
+- int max_qp_wr;
+- int device_cap_flags;
+- int max_sge;
+- int max_sge_rd;
+- int max_cq;
+- int max_cqe;
+- int max_mr;
+- int max_pd;
+- int max_qp_rd_atom;
+- int max_ee_rd_atom;
+- int max_res_rd_atom;
+- int max_qp_init_rd_atom;
+- int max_ee_init_rd_atom;
+- enum ibv_atomic_cap atomic_cap;
+- int max_ee;
+- int max_rdd;
+- int max_mw;
+- int max_raw_ipv6_qp;
+- int max_raw_ethy_qp;
+- int max_mcast_grp;
+- int max_mcast_qp_attach;
+- int max_total_mcast_qp_attach;
+- int max_ah;
+- int max_fmr;
+- int max_map_per_fmr;
+- int max_srq;
+- int max_srq_wr;
+- int max_srq_sge;
+- uint16_t max_pkeys;
+- uint8_t local_ca_ack_delay;
+- uint8_t phys_port_cnt;
++ char fw_ver[64];
++ uint64_t node_guid;
++ uint64_t sys_image_guid;
++ uint64_t max_mr_size;
++ uint64_t page_size_cap;
++ uint32_t vendor_id;
++ uint32_t vendor_part_id;
++ uint32_t hw_ver;
++ int max_qp;
++ int max_qp_wr;
++ int device_cap_flags;
++ int max_sge;
++ int max_sge_rd;
++ int max_cq;
++ int max_cqe;
++ int max_mr;
++ int max_pd;
++ int max_qp_rd_atom;
++ int max_ee_rd_atom;
++ int max_res_rd_atom;
++ int max_qp_init_rd_atom;
++ int max_ee_init_rd_atom;
++ enum ibv_atomic_cap atomic_cap;
++ int max_ee;
++ int max_rdd;
++ int max_mw;
++ int max_raw_ipv6_qp;
++ int max_raw_ethy_qp;
++ int max_mcast_grp;
++ int max_mcast_qp_attach;
++ int max_total_mcast_qp_attach;
++ int max_ah;
++ int max_fmr;
++ int max_map_per_fmr;
++ int max_srq;
++ int max_srq_wr;
++ int max_srq_sge;
++ uint16_t max_pkeys;
++ uint8_t local_ca_ack_delay;
++ uint8_t phys_port_cnt;
+ };
+
+ enum ibv_mtu {
+- IBV_MTU_256 = 1,
+- IBV_MTU_512 = 2,
++ IBV_MTU_256 = 1,
++ IBV_MTU_512 = 2,
+ IBV_MTU_1024 = 3,
+ IBV_MTU_2048 = 4,
+ IBV_MTU_4096 = 5
+ };
+
+ enum ibv_port_state {
+- IBV_PORT_NOP = 0,
+- IBV_PORT_DOWN = 1,
+- IBV_PORT_INIT = 2,
+- IBV_PORT_ARMED = 3,
+- IBV_PORT_ACTIVE = 4,
+- IBV_PORT_ACTIVE_DEFER = 5
++ IBV_PORT_NOP = 0,
++ IBV_PORT_DOWN = 1,
++ IBV_PORT_INIT = 2,
++ IBV_PORT_ARMED = 3,
++ IBV_PORT_ACTIVE = 4,
++ IBV_PORT_ACTIVE_DEFER = 5
+ };
+
+ enum {
+@@ -182,27 +179,27 @@ enum {
+ };
+
+ struct ibv_port_attr {
+- enum ibv_port_state state;
+- enum ibv_mtu max_mtu;
+- enum ibv_mtu active_mtu;
+- int gid_tbl_len;
+- uint32_t port_cap_flags;
+- uint32_t max_msg_sz;
+- uint32_t bad_pkey_cntr;
+- uint32_t qkey_viol_cntr;
+- uint16_t pkey_tbl_len;
+- uint16_t lid;
+- uint16_t sm_lid;
+- uint8_t lmc;
+- uint8_t max_vl_num;
+- uint8_t sm_sl;
+- uint8_t subnet_timeout;
+- uint8_t init_type_reply;
+- uint8_t active_width;
+- uint8_t active_speed;
+- uint8_t phys_state;
+- uint8_t link_layer;
+- uint8_t reserved;
++ enum ibv_port_state state;
++ enum ibv_mtu max_mtu;
++ enum ibv_mtu active_mtu;
++ int gid_tbl_len;
++ uint32_t port_cap_flags;
++ uint32_t max_msg_sz;
++ uint32_t bad_pkey_cntr;
++ uint32_t qkey_viol_cntr;
++ uint16_t pkey_tbl_len;
++ uint16_t lid;
++ uint16_t sm_lid;
++ uint8_t lmc;
++ uint8_t max_vl_num;
++ uint8_t sm_sl;
++ uint8_t subnet_timeout;
++ uint8_t init_type_reply;
++ uint8_t active_width;
++ uint8_t active_speed;
++ uint8_t phys_state;
++ uint8_t link_layer;
++ uint8_t reserved;
+ };
+
+ enum ibv_event_type {
+@@ -229,12 +226,12 @@ enum ibv_event_type {
+
+ struct ibv_async_event {
+ union {
+- struct ibv_cq *cq;
+- struct ibv_qp *qp;
++ struct ibv_cq *cq;
++ struct ibv_qp *qp;
+ struct ibv_srq *srq;
+- int port_num;
++ int port_num;
+ } element;
+- enum ibv_event_type event_type;
++ enum ibv_event_type event_type;
+ };
+
+ enum ibv_wc_status {
+@@ -270,103 +267,117 @@ enum ibv_wc_opcode {
+ IBV_WC_COMP_SWAP,
+ IBV_WC_FETCH_ADD,
+ IBV_WC_BIND_MW,
+-/*
+- * Set value of IBV_WC_RECV so consumers can test if a completion is a
+- * receive by testing (opcode & IBV_WC_RECV).
+- */
+- IBV_WC_RECV = 1 << 7,
++ /*
++ * Set value of IBV_WC_RECV so consumers can test if a completion is a
++ * receive by testing (opcode & IBV_WC_RECV).
++ */
++ IBV_WC_RECV = 1 << 7,
+ IBV_WC_RECV_RDMA_WITH_IMM
+ };
+
+ enum ibv_wc_flags {
+- IBV_WC_GRH = 1 << 0,
+- IBV_WC_WITH_IMM = 1 << 1
++ IBV_WC_GRH = 1 << 0, IBV_WC_WITH_IMM = 1 << 1
+ };
+
+ struct ibv_wc {
+- uint64_t wr_id;
+- enum ibv_wc_status status;
+- enum ibv_wc_opcode opcode;
+- uint32_t vendor_err;
+- uint32_t byte_len;
+- uint32_t imm_data; /* in network byte order */
+- uint32_t qp_num;
+- uint32_t src_qp;
+- int wc_flags;
+- uint16_t pkey_index;
+- uint16_t slid;
+- uint8_t sl;
+- uint8_t dlid_path_bits;
++ uint64_t wr_id;
++ enum ibv_wc_status status;
++ enum ibv_wc_opcode opcode;
++ uint32_t vendor_err;
++ uint32_t byte_len;
++ uint32_t imm_data; /* in network byte order */
++ uint32_t qp_num;
++ uint32_t src_qp;
++ int wc_flags;
++ uint16_t pkey_index;
++ uint16_t slid;
++ uint8_t sl;
++ uint8_t dlid_path_bits;
+ };
+
+ enum ibv_access_flags {
+- IBV_ACCESS_LOCAL_WRITE = 1,
+- IBV_ACCESS_REMOTE_WRITE = (1<<1),
+- IBV_ACCESS_REMOTE_READ = (1<<2),
+- IBV_ACCESS_REMOTE_ATOMIC = (1<<3),
+- IBV_ACCESS_MW_BIND = (1<<4)
++ IBV_ACCESS_LOCAL_WRITE = 1,
++ IBV_ACCESS_REMOTE_WRITE = (1 << 1),
++ IBV_ACCESS_REMOTE_READ = (1 << 2),
++ IBV_ACCESS_REMOTE_ATOMIC = (1 << 3),
++ IBV_ACCESS_MW_BIND = (1 << 4)
+ };
+
+ struct ibv_pd {
+- struct ibv_context *context;
+- uint32_t handle;
++ struct ibv_context *context;
++ uint32_t handle;
++};
++
++enum ibv_xrcd_init_attr_mask {
++ IBV_XRCD_INIT_ATTR_FD = 1 << 0,
++ IBV_XRCD_INIT_ATTR_OFLAGS = 1 << 1,
++ IBV_XRCD_INIT_ATTR_RESERVED = 1 << 2
++};
++
++struct ibv_xrcd_init_attr {
++ uint32_t comp_mask;
++ int fd;
++ int oflags;
++};
++
++struct ibv_xrcd {
++ struct ibv_context *context;
+ };
+
+ enum ibv_rereg_mr_flags {
+- IBV_REREG_MR_CHANGE_TRANSLATION = (1 << 0),
+- IBV_REREG_MR_CHANGE_PD = (1 << 1),
+- IBV_REREG_MR_CHANGE_ACCESS = (1 << 2),
+- IBV_REREG_MR_KEEP_VALID = (1 << 3)
++ IBV_REREG_MR_CHANGE_TRANSLATION = (1 << 0),
++ IBV_REREG_MR_CHANGE_PD = (1 << 1),
++ IBV_REREG_MR_CHANGE_ACCESS = (1 << 2),
++ IBV_REREG_MR_KEEP_VALID = (1 << 3)
+ };
+
+ struct ibv_mr {
+- struct ibv_context *context;
+- struct ibv_pd *pd;
+- void *addr;
+- size_t length;
+- uint32_t handle;
+- uint32_t lkey;
+- uint32_t rkey;
++ struct ibv_context *context;
++ struct ibv_pd *pd;
++ void *addr;
++ size_t length;
++ uint32_t handle;
++ uint32_t lkey;
++ uint32_t rkey;
+ };
+
+ enum ibv_mw_type {
+- IBV_MW_TYPE_1 = 1,
+- IBV_MW_TYPE_2 = 2
++ IBV_MW_TYPE_1 = 1, IBV_MW_TYPE_2 = 2
+ };
+
+ struct ibv_mw {
+- struct ibv_context *context;
+- struct ibv_pd *pd;
+- uint32_t rkey;
++ struct ibv_context *context;
++ struct ibv_pd *pd;
++ uint32_t rkey;
+ };
+
+ struct ibv_global_route {
+- union ibv_gid dgid;
+- uint32_t flow_label;
+- uint8_t sgid_index;
+- uint8_t hop_limit;
+- uint8_t traffic_class;
++ union ibv_gid dgid;
++ uint32_t flow_label;
++ uint8_t sgid_index;
++ uint8_t hop_limit;
++ uint8_t traffic_class;
+ };
+
+ struct ibv_grh {
+- uint32_t version_tclass_flow;
+- uint16_t paylen;
+- uint8_t next_hdr;
+- uint8_t hop_limit;
+- union ibv_gid sgid;
+- union ibv_gid dgid;
++ uint32_t version_tclass_flow;
++ uint16_t paylen;
++ uint8_t next_hdr;
++ uint8_t hop_limit;
++ union ibv_gid sgid;
++ union ibv_gid dgid;
+ };
+
+ enum ibv_rate {
+- IBV_RATE_MAX = 0,
++ IBV_RATE_MAX = 0,
+ IBV_RATE_2_5_GBPS = 2,
+- IBV_RATE_5_GBPS = 5,
+- IBV_RATE_10_GBPS = 3,
+- IBV_RATE_20_GBPS = 6,
+- IBV_RATE_30_GBPS = 4,
+- IBV_RATE_40_GBPS = 7,
+- IBV_RATE_60_GBPS = 8,
+- IBV_RATE_80_GBPS = 9,
++ IBV_RATE_5_GBPS = 5,
++ IBV_RATE_10_GBPS = 3,
++ IBV_RATE_20_GBPS = 6,
++ IBV_RATE_30_GBPS = 4,
++ IBV_RATE_40_GBPS = 7,
++ IBV_RATE_60_GBPS = 8,
++ IBV_RATE_80_GBPS = 9,
+ IBV_RATE_120_GBPS = 10
+ };
+
+@@ -385,77 +396,74 @@ int ibv_rate_to_mult(enum ibv_rate rate) __attribute_const;
+ enum ibv_rate mult_to_ibv_rate(int mult) __attribute_const;
+
+ struct ibv_ah_attr {
+- struct ibv_global_route grh;
+- uint16_t dlid;
+- uint8_t sl;
+- uint8_t src_path_bits;
+- uint8_t static_rate;
+- uint8_t is_global;
+- uint8_t port_num;
++ struct ibv_global_route grh;
++ uint16_t dlid;
++ uint8_t sl;
++ uint8_t src_path_bits;
++ uint8_t static_rate;
++ uint8_t is_global;
++ uint8_t port_num;
+ };
+
+ enum ibv_srq_attr_mask {
+- IBV_SRQ_MAX_WR = 1 << 0,
+- IBV_SRQ_LIMIT = 1 << 1
++ IBV_SRQ_MAX_WR = 1 << 0, IBV_SRQ_LIMIT = 1 << 1
+ };
+
+ struct ibv_srq_attr {
+- uint32_t max_wr;
+- uint32_t max_sge;
+- uint32_t srq_limit;
++ uint32_t max_wr;
++ uint32_t max_sge;
++ uint32_t srq_limit;
+ };
+
+ struct ibv_srq_init_attr {
+- void *srq_context;
+- struct ibv_srq_attr attr;
++ void *srq_context;
++ struct ibv_srq_attr attr;
+ };
+
+ enum ibv_qp_type {
+- IBV_QPT_RC = 2,
+- IBV_QPT_UC,
+- IBV_QPT_UD
++ IBV_QPT_RC = 2, IBV_QPT_UC, IBV_QPT_UD
+ };
+
+ struct ibv_qp_cap {
+- uint32_t max_send_wr;
+- uint32_t max_recv_wr;
+- uint32_t max_send_sge;
+- uint32_t max_recv_sge;
+- uint32_t max_inline_data;
++ uint32_t max_send_wr;
++ uint32_t max_recv_wr;
++ uint32_t max_send_sge;
++ uint32_t max_recv_sge;
++ uint32_t max_inline_data;
+ };
+
+ struct ibv_qp_init_attr {
+- void *qp_context;
+- struct ibv_cq *send_cq;
+- struct ibv_cq *recv_cq;
+- struct ibv_srq *srq;
+- struct ibv_qp_cap cap;
+- enum ibv_qp_type qp_type;
+- int sq_sig_all;
++ void *qp_context;
++ struct ibv_cq *send_cq;
++ struct ibv_cq *recv_cq;
++ struct ibv_srq *srq;
++ struct ibv_qp_cap cap;
++ enum ibv_qp_type qp_type;
++ int sq_sig_all;
+ };
+
+ enum ibv_qp_attr_mask {
+- IBV_QP_STATE = 1 << 0,
+- IBV_QP_CUR_STATE = 1 << 1,
+- IBV_QP_EN_SQD_ASYNC_NOTIFY = 1 << 2,
+- IBV_QP_ACCESS_FLAGS = 1 << 3,
+- IBV_QP_PKEY_INDEX = 1 << 4,
+- IBV_QP_PORT = 1 << 5,
+- IBV_QP_QKEY = 1 << 6,
+- IBV_QP_AV = 1 << 7,
+- IBV_QP_PATH_MTU = 1 << 8,
+- IBV_QP_TIMEOUT = 1 << 9,
+- IBV_QP_RETRY_CNT = 1 << 10,
+- IBV_QP_RNR_RETRY = 1 << 11,
+- IBV_QP_RQ_PSN = 1 << 12,
+- IBV_QP_MAX_QP_RD_ATOMIC = 1 << 13,
+- IBV_QP_ALT_PATH = 1 << 14,
+- IBV_QP_MIN_RNR_TIMER = 1 << 15,
+- IBV_QP_SQ_PSN = 1 << 16,
+- IBV_QP_MAX_DEST_RD_ATOMIC = 1 << 17,
+- IBV_QP_PATH_MIG_STATE = 1 << 18,
+- IBV_QP_CAP = 1 << 19,
+- IBV_QP_DEST_QPN = 1 << 20
++ IBV_QP_STATE = 1 << 0,
++ IBV_QP_CUR_STATE = 1 << 1,
++ IBV_QP_EN_SQD_ASYNC_NOTIFY = 1 << 2,
++ IBV_QP_ACCESS_FLAGS = 1 << 3,
++ IBV_QP_PKEY_INDEX = 1 << 4,
++ IBV_QP_PORT = 1 << 5,
++ IBV_QP_QKEY = 1 << 6,
++ IBV_QP_AV = 1 << 7,
++ IBV_QP_PATH_MTU = 1 << 8,
++ IBV_QP_TIMEOUT = 1 << 9,
++ IBV_QP_RETRY_CNT = 1 << 10,
++ IBV_QP_RNR_RETRY = 1 << 11,
++ IBV_QP_RQ_PSN = 1 << 12,
++ IBV_QP_MAX_QP_RD_ATOMIC = 1 << 13,
++ IBV_QP_ALT_PATH = 1 << 14,
++ IBV_QP_MIN_RNR_TIMER = 1 << 15,
++ IBV_QP_SQ_PSN = 1 << 16,
++ IBV_QP_MAX_DEST_RD_ATOMIC = 1 << 17,
++ IBV_QP_PATH_MIG_STATE = 1 << 18,
++ IBV_QP_CAP = 1 << 19,
++ IBV_QP_DEST_QPN = 1 << 20
+ };
+
+ enum ibv_qp_state {
+@@ -469,37 +477,35 @@ enum ibv_qp_state {
+ };
+
+ enum ibv_mig_state {
+- IBV_MIG_MIGRATED,
+- IBV_MIG_REARM,
+- IBV_MIG_ARMED
++ IBV_MIG_MIGRATED, IBV_MIG_REARM, IBV_MIG_ARMED
+ };
+
+ struct ibv_qp_attr {
+- enum ibv_qp_state qp_state;
+- enum ibv_qp_state cur_qp_state;
+- enum ibv_mtu path_mtu;
+- enum ibv_mig_state path_mig_state;
+- uint32_t qkey;
+- uint32_t rq_psn;
+- uint32_t sq_psn;
+- uint32_t dest_qp_num;
+- int qp_access_flags;
+- struct ibv_qp_cap cap;
+- struct ibv_ah_attr ah_attr;
+- struct ibv_ah_attr alt_ah_attr;
+- uint16_t pkey_index;
+- uint16_t alt_pkey_index;
+- uint8_t en_sqd_async_notify;
+- uint8_t sq_draining;
+- uint8_t max_rd_atomic;
+- uint8_t max_dest_rd_atomic;
+- uint8_t min_rnr_timer;
+- uint8_t port_num;
+- uint8_t timeout;
+- uint8_t retry_cnt;
+- uint8_t rnr_retry;
+- uint8_t alt_port_num;
+- uint8_t alt_timeout;
++ enum ibv_qp_state qp_state;
++ enum ibv_qp_state cur_qp_state;
++ enum ibv_mtu path_mtu;
++ enum ibv_mig_state path_mig_state;
++ uint32_t qkey;
++ uint32_t rq_psn;
++ uint32_t sq_psn;
++ uint32_t dest_qp_num;
++ int qp_access_flags;
++ struct ibv_qp_cap cap;
++ struct ibv_ah_attr ah_attr;
++ struct ibv_ah_attr alt_ah_attr;
++ uint16_t pkey_index;
++ uint16_t alt_pkey_index;
++ uint8_t en_sqd_async_notify;
++ uint8_t sq_draining;
++ uint8_t max_rd_atomic;
++ uint8_t max_dest_rd_atomic;
++ uint8_t min_rnr_timer;
++ uint8_t port_num;
++ uint8_t timeout;
++ uint8_t retry_cnt;
++ uint8_t rnr_retry;
++ uint8_t alt_port_num;
++ uint8_t alt_timeout;
+ };
+
+ enum ibv_wr_opcode {
+@@ -513,249 +519,249 @@ enum ibv_wr_opcode {
+ };
+
+ enum ibv_send_flags {
+- IBV_SEND_FENCE = 1 << 0,
+- IBV_SEND_SIGNALED = 1 << 1,
+- IBV_SEND_SOLICITED = 1 << 2,
+- IBV_SEND_INLINE = 1 << 3
++ IBV_SEND_FENCE = 1 << 0,
++ IBV_SEND_SIGNALED = 1 << 1,
++ IBV_SEND_SOLICITED = 1 << 2,
++ IBV_SEND_INLINE = 1 << 3
+ };
+
+ struct ibv_sge {
+- uint64_t addr;
+- uint32_t length;
+- uint32_t lkey;
++ uint64_t addr;
++ uint32_t length;
++ uint32_t lkey;
+ };
+
+ struct ibv_send_wr {
+- uint64_t wr_id;
+- struct ibv_send_wr *next;
+- struct ibv_sge *sg_list;
+- int num_sge;
+- enum ibv_wr_opcode opcode;
+- int send_flags;
+- uint32_t imm_data; /* in network byte order */
++ uint64_t wr_id;
++ struct ibv_send_wr *next;
++ struct ibv_sge *sg_list;
++ int num_sge;
++ enum ibv_wr_opcode opcode;
++ int send_flags;
++ uint32_t imm_data; /* in network byte order */
+ union {
+ struct {
+- uint64_t remote_addr;
+- uint32_t rkey;
++ uint64_t remote_addr;
++ uint32_t rkey;
+ } rdma;
+ struct {
+- uint64_t remote_addr;
+- uint64_t compare_add;
+- uint64_t swap;
+- uint32_t rkey;
++ uint64_t remote_addr;
++ uint64_t compare_add;
++ uint64_t swap;
++ uint32_t rkey;
+ } atomic;
+ struct {
+- struct ibv_ah *ah;
+- uint32_t remote_qpn;
+- uint32_t remote_qkey;
++ struct ibv_ah *ah;
++ uint32_t remote_qpn;
++ uint32_t remote_qkey;
+ } ud;
+ } wr;
+ };
+
+ struct ibv_recv_wr {
+- uint64_t wr_id;
+- struct ibv_recv_wr *next;
+- struct ibv_sge *sg_list;
+- int num_sge;
++ uint64_t wr_id;
++ struct ibv_recv_wr *next;
++ struct ibv_sge *sg_list;
++ int num_sge;
+ };
+
+ struct ibv_mw_bind {
+- uint64_t wr_id;
+- struct ibv_mr *mr;
+- void *addr;
+- size_t length;
+- int send_flags;
+- int mw_access_flags;
++ uint64_t wr_id;
++ struct ibv_mr *mr;
++ void *addr;
++ size_t length;
++ int send_flags;
++ int mw_access_flags;
+ };
+
+ struct ibv_srq {
+- struct ibv_context *context;
+- void *srq_context;
+- struct ibv_pd *pd;
+- uint32_t handle;
+-
+- pthread_mutex_t mutex;
+- pthread_cond_t cond;
+- uint32_t events_completed;
++ struct ibv_context *context;
++ void *srq_context;
++ struct ibv_pd *pd;
++ uint32_t handle;
++
++ pthread_mutex_t mutex;
++ pthread_cond_t cond;
++ uint32_t events_completed;
+ };
+
+ struct ibv_qp {
+- struct ibv_context *context;
+- void *qp_context;
+- struct ibv_pd *pd;
+- struct ibv_cq *send_cq;
+- struct ibv_cq *recv_cq;
+- struct ibv_srq *srq;
+- uint32_t handle;
+- uint32_t qp_num;
+- enum ibv_qp_state state;
+- enum ibv_qp_type qp_type;
+-
+- pthread_mutex_t mutex;
+- pthread_cond_t cond;
+- uint32_t events_completed;
++ struct ibv_context *context;
++ void *qp_context;
++ struct ibv_pd *pd;
++ struct ibv_cq *send_cq;
++ struct ibv_cq *recv_cq;
++ struct ibv_srq *srq;
++ uint32_t handle;
++ uint32_t qp_num;
++ enum ibv_qp_state state;
++ enum ibv_qp_type qp_type;
++
++ pthread_mutex_t mutex;
++ pthread_cond_t cond;
++ uint32_t events_completed;
+ };
+
+ struct ibv_comp_channel {
+- struct ibv_context *context;
+- int fd;
+- int refcnt;
++ struct ibv_context *context;
++ int fd;
++ int refcnt;
+ };
+
+ struct ibv_cq {
+- struct ibv_context *context;
++ struct ibv_context *context;
+ struct ibv_comp_channel *channel;
+- void *cq_context;
+- uint32_t handle;
+- int cqe;
+-
+- pthread_mutex_t mutex;
+- pthread_cond_t cond;
+- uint32_t comp_events_completed;
+- uint32_t async_events_completed;
++ void *cq_context;
++ uint32_t handle;
++ int cqe;
++
++ pthread_mutex_t mutex;
++ pthread_cond_t cond;
++ uint32_t comp_events_completed;
++ uint32_t async_events_completed;
+ };
+
+ struct ibv_ah {
+- struct ibv_context *context;
+- struct ibv_pd *pd;
+- uint32_t handle;
++ struct ibv_context *context;
++ struct ibv_pd *pd;
++ uint32_t handle;
+ };
+
+ struct ibv_device;
+ struct ibv_context;
+
+ struct ibv_device_ops {
+- struct ibv_context * (*alloc_context)(struct ibv_device *device, int cmd_fd);
+- void (*free_context)(struct ibv_context *context);
++ struct ibv_context * (*alloc_context)(struct ibv_device *device,
++ int cmd_fd);
++ void (*free_context)(struct ibv_context *context);
+ };
+
+ enum {
+- IBV_SYSFS_NAME_MAX = 64,
+- IBV_SYSFS_PATH_MAX = 256
++ IBV_SYSFS_NAME_MAX = 64, IBV_SYSFS_PATH_MAX = 256
+ };
+
+ struct ibv_device {
+- struct ibv_device_ops ops;
+- enum ibv_node_type node_type;
+- enum ibv_transport_type transport_type;
++ struct ibv_device_ops ops;
++ enum ibv_node_type node_type;
++ enum ibv_transport_type transport_type;
+ /* Name of underlying kernel IB device, eg "mthca0" */
+- char name[IBV_SYSFS_NAME_MAX];
++ char name[IBV_SYSFS_NAME_MAX];
+ /* Name of uverbs device, eg "uverbs0" */
+- char dev_name[IBV_SYSFS_NAME_MAX];
++ char dev_name[IBV_SYSFS_NAME_MAX];
+ /* Path to infiniband_verbs class device in sysfs */
+- char dev_path[IBV_SYSFS_PATH_MAX];
++ char dev_path[IBV_SYSFS_PATH_MAX];
+ /* Path to infiniband class device in sysfs */
+- char ibdev_path[IBV_SYSFS_PATH_MAX];
++ char ibdev_path[IBV_SYSFS_PATH_MAX];
+ };
+
+ struct verbs_device {
+ struct ibv_device device; /* Must be first */
+- size_t sz;
+- size_t size_of_context;
+- int (*init_context)(struct verbs_device *device,
+- struct ibv_context *ctx, int cmd_fd);
+- void (*uninit_context)(struct verbs_device *device,
+- struct ibv_context *ctx);
+- /* future fields added here */
++ size_t sz;
++ size_t size_of_context;
++ int (*init_context)(struct verbs_device *device,
++ struct ibv_context *ctx, int cmd_fd);
++ void (*uninit_context)(struct verbs_device *device,
++ struct ibv_context *ctx);
++/* future fields added here */
+ };
+
+ struct ibv_context_ops {
+- int (*query_device)(struct ibv_context *context,
+- struct ibv_device_attr *device_attr);
+- int (*query_port)(struct ibv_context *context, uint8_t port_num,
+- struct ibv_port_attr *port_attr);
+- struct ibv_pd * (*alloc_pd)(struct ibv_context *context);
+- int (*dealloc_pd)(struct ibv_pd *pd);
+- struct ibv_mr * (*reg_mr)(struct ibv_pd *pd, void *addr, size_t length,
+- int access);
+- struct ibv_mr * (*rereg_mr)(struct ibv_mr *mr,
+- int flags,
+- struct ibv_pd *pd, void *addr,
+- size_t length,
+- int access);
+- int (*dereg_mr)(struct ibv_mr *mr);
+- struct ibv_mw * (*alloc_mw)(struct ibv_pd *pd, enum ibv_mw_type type);
+- int (*bind_mw)(struct ibv_qp *qp, struct ibv_mw *mw,
+- struct ibv_mw_bind *mw_bind);
+- int (*dealloc_mw)(struct ibv_mw *mw);
+- struct ibv_cq * (*create_cq)(struct ibv_context *context, int cqe,
+- struct ibv_comp_channel *channel,
+- int comp_vector);
+- int (*poll_cq)(struct ibv_cq *cq, int num_entries, struct ibv_wc *wc);
+- int (*req_notify_cq)(struct ibv_cq *cq, int solicited_only);
+- void (*cq_event)(struct ibv_cq *cq);
+- int (*resize_cq)(struct ibv_cq *cq, int cqe);
+- int (*destroy_cq)(struct ibv_cq *cq);
+- struct ibv_srq * (*create_srq)(struct ibv_pd *pd,
+- struct ibv_srq_init_attr *srq_init_attr);
+- int (*modify_srq)(struct ibv_srq *srq,
+- struct ibv_srq_attr *srq_attr,
+- int srq_attr_mask);
+- int (*query_srq)(struct ibv_srq *srq,
+- struct ibv_srq_attr *srq_attr);
+- int (*destroy_srq)(struct ibv_srq *srq);
+- int (*post_srq_recv)(struct ibv_srq *srq,
+- struct ibv_recv_wr *recv_wr,
+- struct ibv_recv_wr **bad_recv_wr);
+- struct ibv_qp * (*create_qp)(struct ibv_pd *pd, struct ibv_qp_init_attr *attr);
+- int (*query_qp)(struct ibv_qp *qp, struct ibv_qp_attr *attr,
+- int attr_mask,
+- struct ibv_qp_init_attr *init_attr);
+- int (*modify_qp)(struct ibv_qp *qp, struct ibv_qp_attr *attr,
+- int attr_mask);
+- int (*destroy_qp)(struct ibv_qp *qp);
+- int (*post_send)(struct ibv_qp *qp, struct ibv_send_wr *wr,
+- struct ibv_send_wr **bad_wr);
+- int (*post_recv)(struct ibv_qp *qp, struct ibv_recv_wr *wr,
+- struct ibv_recv_wr **bad_wr);
+- struct ibv_ah * (*create_ah)(struct ibv_pd *pd, struct ibv_ah_attr *attr);
+- int (*destroy_ah)(struct ibv_ah *ah);
+- int (*attach_mcast)(struct ibv_qp *qp, const union ibv_gid *gid,
+- uint16_t lid);
+- int (*detach_mcast)(struct ibv_qp *qp, const union ibv_gid *gid,
+- uint16_t lid);
+- void (*async_event)(struct ibv_async_event *event);
++ int (*query_device)(struct ibv_context *context,
++ struct ibv_device_attr *device_attr);
++ int (*query_port)(struct ibv_context *context, uint8_t port_num,
++ struct ibv_port_attr *port_attr);
++ struct ibv_pd * (*alloc_pd)(struct ibv_context *context);
++ int (*dealloc_pd)(struct ibv_pd *pd);
++ struct ibv_mr * (*reg_mr)(struct ibv_pd *pd, void *addr, size_t length,
++ int access);
++ struct ibv_mr * (*rereg_mr)(struct ibv_mr *mr, int flags,
++ struct ibv_pd *pd, void *addr, size_t length,
++ int access);
++ int (*dereg_mr)(struct ibv_mr *mr);
++ struct ibv_mw * (*alloc_mw)(struct ibv_pd *pd, enum ibv_mw_type type);
++ int (*bind_mw)(struct ibv_qp *qp, struct ibv_mw *mw,
++ struct ibv_mw_bind *mw_bind);
++ int (*dealloc_mw)(struct ibv_mw *mw);
++ struct ibv_cq * (*create_cq)(struct ibv_context *context, int cqe,
++ struct ibv_comp_channel *channel, int comp_vector);
++ int (*poll_cq)(struct ibv_cq *cq, int num_entries, struct ibv_wc *wc);
++ int (*req_notify_cq)(struct ibv_cq *cq, int solicited_only);
++ void (*cq_event)(struct ibv_cq *cq);
++ int (*resize_cq)(struct ibv_cq *cq, int cqe);
++ int (*destroy_cq)(struct ibv_cq *cq);
++ struct ibv_srq * (*create_srq)(struct ibv_pd *pd,
++ struct ibv_srq_init_attr *srq_init_attr);
++ int (*modify_srq)(struct ibv_srq *srq, struct ibv_srq_attr *srq_attr,
++ int srq_attr_mask);
++ int (*query_srq)(struct ibv_srq *srq, struct ibv_srq_attr *srq_attr);
++ int (*destroy_srq)(struct ibv_srq *srq);
++ int (*post_srq_recv)(struct ibv_srq *srq, struct ibv_recv_wr *recv_wr,
++ struct ibv_recv_wr **bad_recv_wr);
++ struct ibv_qp * (*create_qp)(struct ibv_pd *pd,
++ struct ibv_qp_init_attr *attr);
++ int (*query_qp)(struct ibv_qp *qp, struct ibv_qp_attr *attr,
++ int attr_mask, struct ibv_qp_init_attr *init_attr);
++ int (*modify_qp)(struct ibv_qp *qp, struct ibv_qp_attr *attr,
++ int attr_mask);
++ int (*destroy_qp)(struct ibv_qp *qp);
++ int (*post_send)(struct ibv_qp *qp, struct ibv_send_wr *wr,
++ struct ibv_send_wr **bad_wr);
++ int (*post_recv)(struct ibv_qp *qp, struct ibv_recv_wr *wr,
++ struct ibv_recv_wr **bad_wr);
++ struct ibv_ah * (*create_ah)(struct ibv_pd *pd,
++ struct ibv_ah_attr *attr);
++ int (*destroy_ah)(struct ibv_ah *ah);
++ int (*attach_mcast)(struct ibv_qp *qp, const union ibv_gid *gid,
++ uint16_t lid);
++ int (*detach_mcast)(struct ibv_qp *qp, const union ibv_gid *gid,
++ uint16_t lid);
++ void (*async_event)(struct ibv_async_event *event);
+ };
+
+ struct ibv_context {
+- struct ibv_device *device;
+- struct ibv_context_ops ops;
+- int cmd_fd;
+- int async_fd;
+- int num_comp_vectors;
+- pthread_mutex_t mutex;
+- void *abi_compat;
++ struct ibv_device *device;
++ struct ibv_context_ops ops;
++ int cmd_fd;
++ int async_fd;
++ int num_comp_vectors;
++ pthread_mutex_t mutex;
++ void *abi_compat;
+ };
+
+ enum verbs_context_mask {
+- VERBS_CONTEXT_RESERVED = 1 << 0
++ VERBS_CONTEXT_XRCD = 1 << 0,
++ VERBS_CONTEXT_RESERVED = 1 << 1
+ };
+
+ struct verbs_context {
+-
+ /* "grows up" - new fields go here
+- int (*drv_new_func1) (); new corresponding provider call of func1
+- int (*lib_new_func1) (); New library call func1
+- */
++ int (*drv_new_func1) (); new corresponding provider call of func1
++ int (*lib_new_func1) (); New library call func1
++ */
++ struct ibv_xrcd * (*open_xrcd)(struct ibv_context *context,
++ struct ibv_xrcd_init_attr *xrcd_init_attr);
++ int (*close_xrcd)(struct ibv_xrcd *xrcd);
+ uint64_t has_comp_mask;
+- size_t sz; /* Set by library on struct allocation,must be
+- * located right before struct ibv_context
+- */
++ size_t sz; /* Set by library on struct allocation,must be
++ * located right before struct ibv_context
++ */
+ struct ibv_context context;/* Must be last field in the struct */
+ };
+
+-static inline struct verbs_context *verbs_get_ctx(
+- const struct ibv_context *ctx)
+-{
++static inline struct verbs_context *verbs_get_ctx(const struct ibv_context *ctx) {
+ return (ctx->abi_compat != ((uint8_t *) NULL) - 1) ?
+- NULL : container_of(ctx, struct verbs_context, context);
++ NULL : container_of(ctx, struct verbs_context, context);
+ }
+
++#define verbs_get_ctx_op(ctx, op) ({ \
++ struct verbs_context *vctx = verbs_get_ctx(ctx); \
++ (!vctx || (vctx->sz < sizeof(*vctx) - offsetof(struct verbs_context, op)) || \
++ !vctx->op) ? NULL : vctx; })
++
+ static inline struct verbs_device *verbs_get_device(
+- const struct ibv_device *dev)
+-{
++ const struct ibv_device *dev) {
+ return (dev->ops.alloc_context) ?
+- NULL : container_of(dev, struct verbs_device, device);
++ NULL : container_of(dev, struct verbs_device, device);
+ }
+
+ /**
+@@ -806,7 +812,7 @@ int ibv_close_device(struct ibv_context *context);
+ * be acknowledged with ibv_ack_async_event().
+ */
+ int ibv_get_async_event(struct ibv_context *context,
+- struct ibv_async_event *event);
++ struct ibv_async_event *event);
+
+ /**
+ * ibv_ack_async_event - Acknowledge an async event
+@@ -824,21 +830,19 @@ void ibv_ack_async_event(struct ibv_async_event *event);
+ * ibv_query_device - Get device properties
+ */
+ int ibv_query_device(struct ibv_context *context,
+- struct ibv_device_attr *device_attr);
++ struct ibv_device_attr *device_attr);
+
+ /**
+ * ibv_query_port - Get port properties
+ */
+ int ibv_query_port(struct ibv_context *context, uint8_t port_num,
+- struct ibv_port_attr *port_attr);
++ struct ibv_port_attr *port_attr);
+
+ static inline int ___ibv_query_port(struct ibv_context *context,
+- uint8_t port_num,
+- struct ibv_port_attr *port_attr)
+-{
+- /* For compatability when running with old libibverbs */
++ uint8_t port_num, struct ibv_port_attr *port_attr) {
++ /* For compatibility when running with old libibverbs */
+ port_attr->link_layer = IBV_LINK_LAYER_UNSPECIFIED;
+- port_attr->reserved = 0;
++ port_attr->reserved = 0;
+
+ return ibv_query_port(context, port_num, port_attr);
+ }
+@@ -849,14 +853,14 @@ static inline int ___ibv_query_port(struct ibv_context *context,
+ /**
+ * ibv_query_gid - Get a GID table entry
+ */
+-int ibv_query_gid(struct ibv_context *context, uint8_t port_num,
+- int index, union ibv_gid *gid);
++int ibv_query_gid(struct ibv_context *context, uint8_t port_num, int index,
++ union ibv_gid *gid);
+
+ /**
+ * ibv_query_pkey - Get a P_Key table entry
+ */
+-int ibv_query_pkey(struct ibv_context *context, uint8_t port_num,
+- int index, uint16_t *pkey);
++int ibv_query_pkey(struct ibv_context *context, uint8_t port_num, int index,
++ uint16_t *pkey);
+
+ /**
+ * ibv_alloc_pd - Allocate a protection domain
+@@ -869,10 +873,31 @@ struct ibv_pd *ibv_alloc_pd(struct ibv_context *context);
+ int ibv_dealloc_pd(struct ibv_pd *pd);
+
+ /**
++ * ibv_open_xrcd - Open an extended connection domain
++ */
++static inline struct ibv_xrcd *
++ibv_open_xrcd(struct ibv_context *context, struct ibv_xrcd_init_attr *xrcd_init_attr) {
++ struct verbs_context *vctx = verbs_get_ctx_op(context, open_xrcd);
++ if (!vctx) {
++ errno = ENOSYS;
++ return NULL;
++ }
++ return vctx->open_xrcd(context, xrcd_init_attr);
++}
++
++/**
++ * ibv_close_xrcd - Close an extended connection domain
++ */
++static inline int ibv_close_xrcd(struct ibv_xrcd *xrcd) {
++ struct verbs_context *vctx = verbs_get_ctx(xrcd->context);
++ return vctx->close_xrcd(xrcd);
++}
++
++/**
+ * ibv_reg_mr - Register a memory region
+ */
+-struct ibv_mr *ibv_reg_mr(struct ibv_pd *pd, void *addr,
+- size_t length, int access);
++struct ibv_mr *ibv_reg_mr(struct ibv_pd *pd, void *addr, size_t length,
++ int access);
+
+ /**
+ * ibv_dereg_mr - Deregister a memory region
+@@ -900,9 +925,8 @@ int ibv_destroy_comp_channel(struct ibv_comp_channel *channel);
+ * Must be >= 0 and < context->num_comp_vectors.
+ */
+ struct ibv_cq *ibv_create_cq(struct ibv_context *context, int cqe,
+- void *cq_context,
+- struct ibv_comp_channel *channel,
+- int comp_vector);
++ void *cq_context, struct ibv_comp_channel *channel,
++ int comp_vector);
+
+ /**
+ * ibv_resize_cq - Modifies the capacity of the CQ.
+@@ -927,8 +951,8 @@ int ibv_destroy_cq(struct ibv_cq *cq);
+ * All completion events returned by ibv_get_cq_event() must
+ * eventually be acknowledged with ibv_ack_cq_events().
+ */
+-int ibv_get_cq_event(struct ibv_comp_channel *channel,
+- struct ibv_cq **cq, void **cq_context);
++int ibv_get_cq_event(struct ibv_comp_channel *channel, struct ibv_cq **cq,
++ void **cq_context);
+
+ /**
+ * ibv_ack_cq_events - Acknowledge CQ completion events
+@@ -958,8 +982,8 @@ void ibv_ack_cq_events(struct ibv_cq *cq, unsigned int nevents);
+ * non-negative and strictly less than num_entries, then the CQ was
+ * emptied.
+ */
+-static inline int ibv_poll_cq(struct ibv_cq *cq, int num_entries, struct ibv_wc *wc)
+-{
++static inline int ibv_poll_cq(struct ibv_cq *cq, int num_entries,
++ struct ibv_wc *wc) {
+ return cq->context->ops.poll_cq(cq, num_entries, wc);
+ }
+
+@@ -972,8 +996,7 @@ static inline int ibv_poll_cq(struct ibv_cq *cq, int num_entries, struct ibv_wc
+ * the next solicited CQ entry. If zero, any CQ entry, solicited or
+ * not, will generate an event.
+ */
+-static inline int ibv_req_notify_cq(struct ibv_cq *cq, int solicited_only)
+-{
++static inline int ibv_req_notify_cq(struct ibv_cq *cq, int solicited_only) {
+ return cq->context->ops.req_notify_cq(cq, solicited_only);
+ }
+
+@@ -989,7 +1012,7 @@ static inline int ibv_req_notify_cq(struct ibv_cq *cq, int solicited_only)
+ * will always be at least as large as the requested values.
+ */
+ struct ibv_srq *ibv_create_srq(struct ibv_pd *pd,
+- struct ibv_srq_init_attr *srq_init_attr);
++ struct ibv_srq_init_attr *srq_init_attr);
+
+ /**
+ * ibv_modify_srq - Modifies the attributes for the specified SRQ.
+@@ -1003,9 +1026,8 @@ struct ibv_srq *ibv_create_srq(struct ibv_pd *pd,
+ * IBV_SRQ_LIMIT to set the SRQ's limit and request notification when
+ * the number of receives queued drops below the limit.
+ */
+-int ibv_modify_srq(struct ibv_srq *srq,
+- struct ibv_srq_attr *srq_attr,
+- int srq_attr_mask);
++int ibv_modify_srq(struct ibv_srq *srq, struct ibv_srq_attr *srq_attr,
++ int srq_attr_mask);
+
+ /**
+ * ibv_query_srq - Returns the attribute list and current values for the
+@@ -1029,9 +1051,7 @@ int ibv_destroy_srq(struct ibv_srq *srq);
+ * the work request that failed to be posted on the QP.
+ */
+ static inline int ibv_post_srq_recv(struct ibv_srq *srq,
+- struct ibv_recv_wr *recv_wr,
+- struct ibv_recv_wr **bad_recv_wr)
+-{
++ struct ibv_recv_wr *recv_wr, struct ibv_recv_wr **bad_recv_wr) {
+ return srq->context->ops.post_srq_recv(srq, recv_wr, bad_recv_wr);
+ }
+
+@@ -1039,13 +1059,12 @@ static inline int ibv_post_srq_recv(struct ibv_srq *srq,
+ * ibv_create_qp - Create a queue pair.
+ */
+ struct ibv_qp *ibv_create_qp(struct ibv_pd *pd,
+- struct ibv_qp_init_attr *qp_init_attr);
++ struct ibv_qp_init_attr *qp_init_attr);
+
+ /**
+ * ibv_modify_qp - Modify a queue pair.
+ */
+-int ibv_modify_qp(struct ibv_qp *qp, struct ibv_qp_attr *attr,
+- int attr_mask);
++int ibv_modify_qp(struct ibv_qp *qp, struct ibv_qp_attr *attr, int attr_mask);
+
+ /**
+ * ibv_query_qp - Returns the attribute list and current values for the
+@@ -1058,9 +1077,8 @@ int ibv_modify_qp(struct ibv_qp *qp, struct ibv_qp_attr *attr,
+ * The qp_attr_mask may be used to limit the query to gathering only the
+ * selected attributes.
+ */
+-int ibv_query_qp(struct ibv_qp *qp, struct ibv_qp_attr *attr,
+- int attr_mask,
+- struct ibv_qp_init_attr *init_attr);
++int ibv_query_qp(struct ibv_qp *qp, struct ibv_qp_attr *attr, int attr_mask,
++ struct ibv_qp_init_attr *init_attr);
+
+ /**
+ * ibv_destroy_qp - Destroy a queue pair.
+@@ -1074,8 +1092,7 @@ int ibv_destroy_qp(struct ibv_qp *qp);
+ * immediately after the call returns.
+ */
+ static inline int ibv_post_send(struct ibv_qp *qp, struct ibv_send_wr *wr,
+- struct ibv_send_wr **bad_wr)
+-{
++ struct ibv_send_wr **bad_wr) {
+ return qp->context->ops.post_send(qp, wr, bad_wr);
+ }
+
+@@ -1083,8 +1100,7 @@ static inline int ibv_post_send(struct ibv_qp *qp, struct ibv_send_wr *wr,
+ * ibv_post_recv - Post a list of work requests to a receive queue.
+ */
+ static inline int ibv_post_recv(struct ibv_qp *qp, struct ibv_recv_wr *wr,
+- struct ibv_recv_wr **bad_wr)
+-{
++ struct ibv_recv_wr **bad_wr) {
+ return qp->context->ops.post_recv(qp, wr, bad_wr);
+ }
+
+@@ -1105,8 +1121,8 @@ struct ibv_ah *ibv_create_ah(struct ibv_pd *pd, struct ibv_ah_attr *attr);
+ * handle for replying to the message.
+ */
+ int ibv_init_ah_from_wc(struct ibv_context *context, uint8_t port_num,
+- struct ibv_wc *wc, struct ibv_grh *grh,
+- struct ibv_ah_attr *ah_attr);
++ struct ibv_wc *wc, struct ibv_grh *grh,
++ struct ibv_ah_attr *ah_attr);
+
+ /**
+ * ibv_create_ah_from_wc - Creates an address handle associated with the
+@@ -1121,7 +1137,7 @@ int ibv_init_ah_from_wc(struct ibv_context *context, uint8_t port_num,
+ * in all UD QP post sends.
+ */
+ struct ibv_ah *ibv_create_ah_from_wc(struct ibv_pd *pd, struct ibv_wc *wc,
+- struct ibv_grh *grh, uint8_t port_num);
++ struct ibv_grh *grh, uint8_t port_num);
+
+ /**
+ * ibv_destroy_ah - Destroy an address handle.
+@@ -1176,5 +1192,4 @@ END_C_DECLS
+
+ # undef __attribute_const
+
+-
+ #endif /* INFINIBAND_VERBS_H */
+diff --git a/src/cmd.c b/src/cmd.c
+index dab8930..f0fb1dc 100644
+--- a/src/cmd.c
++++ b/src/cmd.c
+@@ -194,6 +194,47 @@ int ibv_cmd_dealloc_pd(struct ibv_pd *pd)
+ return 0;
+ }
+
++int ibv_cmd_open_xrcd(struct ibv_context *context, struct verbs_xrcd *xrcd,
++ struct ibv_xrcd_init_attr *attr,
++ struct ibv_open_xrcd *cmd, size_t cmd_size,
++ struct ibv_open_xrcd_resp *resp, size_t resp_size)
++{
++ IBV_INIT_CMD_RESP(cmd, cmd_size, OPEN_XRCD, resp, resp_size);
++
++ if (attr->comp_mask >= IBV_XRCD_INIT_ATTR_RESERVED)
++ return ENOSYS;
++
++ if (!(attr->comp_mask & IBV_XRCD_INIT_ATTR_FD) ||
++ !(attr->comp_mask & IBV_XRCD_INIT_ATTR_OFLAGS))
++ return EINVAL;
++
++ cmd->fd = attr->fd;
++ cmd->oflags = attr->oflags;
++ if (write(context->cmd_fd, cmd, cmd_size) != cmd_size)
++ return errno;
++
++ VALGRIND_MAKE_MEM_DEFINED(resp, resp_size);
++
++ xrcd->xrcd.context = context;
++ xrcd->comp_mask = VERBS_XRCD_HANDLE;
++ xrcd->handle = resp->xrcd_handle;
++
++ return 0;
++}
++
++int ibv_cmd_close_xrcd(struct verbs_xrcd *xrcd)
++{
++ struct ibv_close_xrcd cmd;
++
++ IBV_INIT_CMD(&cmd, sizeof cmd, CLOSE_XRCD);
++ cmd.xrcd_handle = xrcd->handle;
++
++ if (write(xrcd->xrcd.context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
++ return errno;
++
++ return 0;
++}
++
+ int ibv_cmd_reg_mr(struct ibv_pd *pd, void *addr, size_t length,
+ uint64_t hca_va, int access,
+ struct ibv_mr *mr, struct ibv_reg_mr *cmd,
+diff --git a/src/libibverbs.map b/src/libibverbs.map
+index ee9adea..9a15f3f 100644
+--- a/src/libibverbs.map
++++ b/src/libibverbs.map
+@@ -97,4 +97,8 @@ IBVERBS_1.1 {
+ ibv_port_state_str;
+ ibv_event_type_str;
+ ibv_wc_status_str;
++
++ ibv_cmd_open_xrcd;
++ ibv_cmd_close_xrcd;
++
+ } IBVERBS_1.0;