XRC_RCV_QP.patch revision 285830
1Added support for XRC receive-only QPs. 2(OFED 1.3 libibverbs commit 6e99cddf835d4715ea7ca3641944e6285f27f2df) 3 4V2: 51. checkpatch.pl cleanups 62. Fixed u64 alignment problems in kern-abi.h 73. eliminated unneeded default_symvers 84. Added ibv_xrc_rcv_xxx lines to libibverbs.map IBVERBS_1.1 9 10Signed-off-by: Jack Morgenstein <jackm@dev.mellanox.co.il> 11--- 12 include/infiniband/driver.h | 12 ++- 13 include/infiniband/kern-abi.h | 99 +++++++++++++++++++- 14 include/infiniband/verbs.h | 123 +++++++++++++++++++++++ 15 src/cmd.c | 215 +++++++++++++++++++++++++++++++++++++++++ 16 src/device.c | 52 +++++----- 17 src/libibverbs.map | 10 ++ 18 src/verbs.c | 59 +++++++++++ 19 7 files changed, 543 insertions(+), 27 deletions(-) 20 21Index: libibverbs/include/infiniband/driver.h 22=================================================================== 23--- libibverbs.orig/include/infiniband/driver.h 2009-11-01 15:18:20.624171000 +0200 24+++ libibverbs/include/infiniband/driver.h 2009-11-01 15:18:24.572283000 +0200 25@@ -144,7 +144,17 @@ int ibv_cmd_open_xrc_domain(struct ibv_c 26 struct ibv_open_xrc_domain_resp *resp, 27 size_t resp_size); 28 int ibv_cmd_close_xrc_domain(struct ibv_xrc_domain *d); 29- 30+int ibv_cmd_create_xrc_rcv_qp(struct ibv_qp_init_attr *init_attr, 31+ uint32_t *xrc_rcv_qpn); 32+int ibv_cmd_modify_xrc_rcv_qp(struct ibv_xrc_domain *d, uint32_t xrc_rcv_qpn, 33+ struct ibv_qp_attr *attr, int attr_mask); 34+int ibv_cmd_query_xrc_rcv_qp(struct ibv_xrc_domain *d, uint32_t xrc_rcv_qpn, 35+ struct ibv_qp_attr *attr, int attr_mask, 36+ struct ibv_qp_init_attr *init_attr); 37+int ibv_cmd_reg_xrc_rcv_qp(struct ibv_xrc_domain *xrc_domain, 38+ uint32_t xrc_qp_num); 39+int ibv_cmd_unreg_xrc_rcv_qp(struct ibv_xrc_domain *xrc_domain, 40+ uint32_t xrc_qp_num); 41 42 /* 43 * sysfs helper functions 44Index: libibverbs/include/infiniband/kern-abi.h 45=================================================================== 46--- libibverbs.orig/include/infiniband/kern-abi.h 2009-11-01 15:18:20.629168000 +0200 47+++ libibverbs/include/infiniband/kern-abi.h 2009-11-01 15:18:24.577283000 +0200 48@@ -88,7 +88,12 @@ enum { 49 IB_USER_VERBS_CMD_POST_SRQ_RECV, 50 IB_USER_VERBS_CMD_CREATE_XRC_SRQ, 51 IB_USER_VERBS_CMD_OPEN_XRC_DOMAIN, 52- IB_USER_VERBS_CMD_CLOSE_XRC_DOMAIN 53+ IB_USER_VERBS_CMD_CLOSE_XRC_DOMAIN, 54+ IB_USER_VERBS_CMD_CREATE_XRC_RCV_QP, 55+ IB_USER_VERBS_CMD_MODIFY_XRC_RCV_QP, 56+ IB_USER_VERBS_CMD_QUERY_XRC_RCV_QP, 57+ IB_USER_VERBS_CMD_REG_XRC_RCV_QP, 58+ IB_USER_VERBS_CMD_UNREG_XRC_RCV_QP, 59 }; 60 61 /* 62@@ -570,6 +575,93 @@ struct ibv_destroy_qp_resp { 63 __u32 events_reported; 64 }; 65 66+struct ibv_create_xrc_rcv_qp { 67+ __u32 command; 68+ __u16 in_words; 69+ __u16 out_words; 70+ __u64 response; 71+ __u64 user_handle; 72+ __u32 xrc_domain_handle; 73+ __u32 max_send_wr; 74+ __u32 max_recv_wr; 75+ __u32 max_send_sge; 76+ __u32 max_recv_sge; 77+ __u32 max_inline_data; 78+ __u8 sq_sig_all; 79+ __u8 qp_type; 80+ __u8 reserved[6]; 81+ __u64 driver_data[0]; 82+}; 83+ 84+struct ibv_create_xrc_rcv_qp_resp { 85+ __u32 qpn; 86+ __u32 reserved; 87+}; 88+ 89+struct ibv_modify_xrc_rcv_qp { 90+ __u32 command; 91+ __u16 in_words; 92+ __u16 out_words; 93+ __u32 xrc_domain_handle; 94+ __u32 qp_num; 95+ struct ibv_qp_dest dest; 96+ struct ibv_qp_dest alt_dest; 97+ __u32 attr_mask; 98+ __u32 qkey; 99+ __u32 rq_psn; 100+ __u32 sq_psn; 101+ __u32 dest_qp_num; 102+ __u32 qp_access_flags; 103+ __u16 pkey_index; 104+ __u16 alt_pkey_index; 105+ __u8 qp_state; 106+ __u8 cur_qp_state; 107+ __u8 path_mtu; 108+ __u8 path_mig_state; 109+ __u8 en_sqd_async_notify; 110+ __u8 max_rd_atomic; 111+ __u8 max_dest_rd_atomic; 112+ __u8 min_rnr_timer; 113+ __u8 port_num; 114+ __u8 timeout; 115+ __u8 retry_cnt; 116+ __u8 rnr_retry; 117+ __u8 alt_port_num; 118+ __u8 alt_timeout; 119+ __u8 reserved[6]; 120+ __u64 driver_data[0]; 121+}; 122+ 123+struct ibv_query_xrc_rcv_qp { 124+ __u32 command; 125+ __u16 in_words; 126+ __u16 out_words; 127+ __u64 response; 128+ __u32 xrc_domain_handle; 129+ __u32 qp_num; 130+ __u32 attr_mask; 131+ __u32 reserved; 132+ __u64 driver_data[0]; 133+}; 134+ 135+struct ibv_reg_xrc_rcv_qp { 136+ __u32 command; 137+ __u16 in_words; 138+ __u16 out_words; 139+ __u32 xrc_domain_handle; 140+ __u32 qp_num; 141+ __u64 driver_data[0]; 142+}; 143+ 144+struct ibv_unreg_xrc_rcv_qp { 145+ __u32 command; 146+ __u16 in_words; 147+ __u16 out_words; 148+ __u32 xrc_domain_handle; 149+ __u32 qp_num; 150+ __u64 driver_data[0]; 151+}; 152+ 153 struct ibv_kern_send_wr { 154 __u64 wr_id; 155 __u32 num_sge; 156@@ -848,6 +940,11 @@ enum { 157 IB_USER_VERBS_CMD_CREATE_XRC_SRQ_V2 = -1, 158 IB_USER_VERBS_CMD_OPEN_XRC_DOMAIN_V2 = -1, 159 IB_USER_VERBS_CMD_CLOSE_XRC_DOMAIN_V2 = -1, 160+ IB_USER_VERBS_CMD_CREATE_XRC_RCV_QP_V2 = -1, 161+ IB_USER_VERBS_CMD_MODIFY_XRC_RCV_QP_V2 = -1, 162+ IB_USER_VERBS_CMD_QUERY_XRC_RCV_QP_V2 = -1, 163+ IB_USER_VERBS_CMD_REG_XRC_RCV_QP_V2 = -1, 164+ IB_USER_VERBS_CMD_UNREG_XRC_RCV_QP_V2 = -1, 165 }; 166 167 struct ibv_destroy_cq_v1 { 168Index: libibverbs/include/infiniband/verbs.h 169=================================================================== 170--- libibverbs.orig/include/infiniband/verbs.h 2009-11-01 15:18:20.635171000 +0200 171+++ libibverbs/include/infiniband/verbs.h 2009-11-01 15:18:24.585280000 +0200 172@@ -205,12 +205,17 @@ enum ibv_event_type { 173 IBV_EVENT_CLIENT_REREGISTER 174 }; 175 176+enum ibv_event_flags { 177+ IBV_XRC_QP_EVENT_FLAG = 0x80000000, 178+}; 179+ 180 struct ibv_async_event { 181 union { 182 struct ibv_cq *cq; 183 struct ibv_qp *qp; 184 struct ibv_srq *srq; 185 int port_num; 186+ uint32_t xrc_qp_num; 187 } element; 188 enum ibv_event_type event_type; 189 }; 190@@ -648,6 +653,22 @@ struct ibv_more_ops { 191 struct ibv_xrc_domain * (*open_xrc_domain)(struct ibv_context *context, 192 int fd, int oflag); 193 int (*close_xrc_domain)(struct ibv_xrc_domain *d); 194+ int (*create_xrc_rcv_qp)(struct ibv_qp_init_attr *init_attr, 195+ uint32_t *xrc_qp_num); 196+ int (*modify_xrc_rcv_qp)(struct ibv_xrc_domain *xrc_domain, 197+ uint32_t xrc_qp_num, 198+ struct ibv_qp_attr *attr, 199+ int attr_mask); 200+ int (*query_xrc_rcv_qp)(struct ibv_xrc_domain *xrc_domain, 201+ uint32_t xrc_qp_num, 202+ struct ibv_qp_attr *attr, 203+ int attr_mask, 204+ struct ibv_qp_init_attr *init_attr); 205+ int (*reg_xrc_rcv_qp)(struct ibv_xrc_domain *xrc_domain, 206+ uint32_t xrc_qp_num); 207+ int (*unreg_xrc_rcv_qp)(struct ibv_xrc_domain *xrc_domain, 208+ uint32_t xrc_qp_num); 209+ 210 }; 211 212 struct ibv_context_ops { 213@@ -1174,6 +1195,108 @@ struct ibv_xrc_domain *ibv_open_xrc_doma 214 */ 215 int ibv_close_xrc_domain(struct ibv_xrc_domain *d); 216 217+/** 218+ * ibv_create_xrc_rcv_qp - creates an XRC QP for serving as a receive-side-only QP, 219+ * 220+ * This QP is created in kernel space, and persists until the last process 221+ * registered for the QP calls ibv_unreg_xrc_rcv_qp() (at which time the QP 222+ * is destroyed). 223+ * 224+ * @init_attr: init attributes to use for QP. xrc domain MUST be included here. 225+ * All other fields are ignored. 226+ * 227+ * @xrc_rcv_qpn: qp_num of created QP (if success). To be passed to the 228+ * remote node (sender). The remote node will use xrc_rcv_qpn 229+ * in ibv_post_send when sending to XRC SRQ's on this host 230+ * in the same xrc domain. 231+ * 232+ * RETURNS: success (0), or a (negative) error value. 233+ * 234+ * NOTE: this verb also registers the calling user-process with the QP at its 235+ * creation time (implicit call to ibv_reg_xrc_rcv_qp), to avoid race 236+ * conditions. The creating process will need to call ibv_unreg_xrc_qp() 237+ * for the QP to release it from this process. 238+ */ 239+int ibv_create_xrc_rcv_qp(struct ibv_qp_init_attr *init_attr, 240+ uint32_t *xrc_rcv_qpn); 241+ 242+/** 243+ * ibv_modify_xrc_rcv_qp - modifies an xrc_rcv qp. 244+ * 245+ * @xrc_domain: xrc domain the QP belongs to (for verification). 246+ * @xrc_qp_num: The (24 bit) number of the XRC QP. 247+ * @attr: modify-qp attributes. The following fields must be specified: 248+ * for RESET_2_INIT: qp_state, pkey_index , port, qp_access_flags 249+ * for INIT_2_RTR: qp_state, path_mtu, dest_qp_num, rq_psn, 250+ * max_dest_rd_atomic, min_rnr_timer, ah_attr 251+ * The QP need not be brought to RTS for the QP to operate as a 252+ * receive-only QP. 253+ * @attr_mask: bitmap indicating which attributes are provided in the attr 254+ * struct. Used for validity checking. 255+ * The following bits must be set: 256+ * for RESET_2_INIT: IBV_QP_PKEY_INDEX, IBV_QP_PORT, 257+ * IBV_QP_ACCESS_FLAGS, IBV_QP_STATE 258+ * for INIT_2_RTR: IBV_QP_AV, IBV_QP_PATH_MTU, IBV_QP_DEST_QPN, 259+ * IBV_QP_RQ_PSN, IBV_QP_MAX_DEST_RD_ATOMIC, 260+ * IBV_QP_MIN_RNR_TIMER, IBV_QP_STATE 261+ * 262+ * RETURNS: success (0), or a (positive) error value. 263+ * 264+ */ 265+int ibv_modify_xrc_rcv_qp(struct ibv_xrc_domain *xrc_domain, 266+ uint32_t xrc_qp_num, 267+ struct ibv_qp_attr *attr, int attr_mask); 268+ 269+/** 270+ * ibv_query_xrc_rcv_qp - queries an xrc_rcv qp. 271+ * 272+ * @xrc_domain: xrc domain the QP belongs to (for verification). 273+ * @xrc_qp_num: The (24 bit) number of the XRC QP. 274+ * @attr: for returning qp attributes. 275+ * @attr_mask: bitmap indicating which attributes to return. 276+ * @init_attr: for returning the init attributes 277+ * 278+ * RETURNS: success (0), or a (positive) error value. 279+ * 280+ */ 281+int ibv_query_xrc_rcv_qp(struct ibv_xrc_domain *xrc_domain, uint32_t xrc_qp_num, 282+ struct ibv_qp_attr *attr, int attr_mask, 283+ struct ibv_qp_init_attr *init_attr); 284+ 285+/** 286+ * ibv_reg_xrc_rcv_qp: registers a user process with an XRC QP which serves as 287+ * a receive-side only QP. 288+ * 289+ * @xrc_domain: xrc domain the QP belongs to (for verification). 290+ * @xrc_qp_num: The (24 bit) number of the XRC QP. 291+ * 292+ * RETURNS: success (0), 293+ * or error (EINVAL), if: 294+ * 1. There is no such QP_num allocated. 295+ * 2. The QP is allocated, but is not an receive XRC QP 296+ * 3. The XRC QP does not belong to the given domain. 297+ */ 298+int ibv_reg_xrc_rcv_qp(struct ibv_xrc_domain *xrc_domain, uint32_t xrc_qp_num); 299+ 300+/** 301+ * ibv_unreg_xrc_rcv_qp: detaches a user process from an XRC QP serving as 302+ * a receive-side only QP. If as a result, there are no remaining 303+ * userspace processes registered for this XRC QP, it is destroyed. 304+ * 305+ * @xrc_domain: xrc domain the QP belongs to (for verification). 306+ * @xrc_qp_num: The (24 bit) number of the XRC QP. 307+ * 308+ * RETURNS: success (0), 309+ * or error (EINVAL), if: 310+ * 1. There is no such QP_num allocated. 311+ * 2. The QP is allocated, but is not an XRC QP 312+ * 3. The XRC QP does not belong to the given domain. 313+ * NOTE: There is no reason to return a special code if the QP is destroyed. 314+ * The unregister simply succeeds. 315+ */ 316+int ibv_unreg_xrc_rcv_qp(struct ibv_xrc_domain *xrc_domain, 317+ uint32_t xrc_qp_num); 318+ 319 END_C_DECLS 320 321 # undef __attribute_const 322Index: libibverbs/src/cmd.c 323=================================================================== 324--- libibverbs.orig/src/cmd.c 2009-11-01 15:18:20.643167000 +0200 325+++ libibverbs/src/cmd.c 2009-11-01 15:18:24.592284000 +0200 326@@ -828,6 +828,188 @@ int ibv_cmd_modify_qp(struct ibv_qp *qp, 327 return 0; 328 } 329 330+int ibv_cmd_create_xrc_rcv_qp(struct ibv_qp_init_attr *init_attr, 331+ uint32_t *xrc_rcv_qpn) 332+{ 333+ struct ibv_create_xrc_rcv_qp cmd; 334+ struct ibv_create_xrc_rcv_qp_resp resp; 335+ 336+ if (abi_ver < 6) 337+ return ENOSYS; 338+ 339+ IBV_INIT_CMD_RESP(&cmd, sizeof cmd, CREATE_XRC_RCV_QP, &resp, 340+ sizeof resp); 341+ 342+ cmd.xrc_domain_handle = init_attr->xrc_domain->handle; 343+ cmd.max_send_wr = init_attr->cap.max_send_wr; 344+ cmd.max_recv_wr = init_attr->cap.max_recv_wr; 345+ cmd.max_send_sge = init_attr->cap.max_send_sge; 346+ cmd.max_recv_sge = init_attr->cap.max_recv_sge; 347+ cmd.max_inline_data = init_attr->cap.max_inline_data; 348+ cmd.sq_sig_all = init_attr->sq_sig_all; 349+ cmd.qp_type = init_attr->qp_type; 350+ cmd.reserved[0] = cmd.reserved[1] = 0; 351+ 352+ if (write(init_attr->xrc_domain->context->cmd_fd, &cmd, sizeof cmd) != 353+ sizeof cmd) 354+ return errno; 355+ 356+ *xrc_rcv_qpn = resp.qpn; 357+ 358+ return 0; 359+} 360+ 361+int ibv_cmd_modify_xrc_rcv_qp(struct ibv_xrc_domain *d, uint32_t xrc_qp_num, 362+ struct ibv_qp_attr *attr, int attr_mask) 363+{ 364+ struct ibv_modify_xrc_rcv_qp cmd; 365+ 366+ if (abi_ver < 6) 367+ return ENOSYS; 368+ 369+ IBV_INIT_CMD(&cmd, sizeof cmd, MODIFY_XRC_RCV_QP); 370+ 371+ cmd.xrc_domain_handle = d->handle; 372+ cmd.qp_num = xrc_qp_num; 373+ cmd.attr_mask = attr_mask; 374+ cmd.qkey = attr->qkey; 375+ cmd.rq_psn = attr->rq_psn; 376+ cmd.sq_psn = attr->sq_psn; 377+ cmd.dest_qp_num = attr->dest_qp_num; 378+ cmd.qp_access_flags = attr->qp_access_flags; 379+ cmd.pkey_index = attr->pkey_index; 380+ cmd.alt_pkey_index = attr->alt_pkey_index; 381+ cmd.qp_state = attr->qp_state; 382+ cmd.cur_qp_state = attr->cur_qp_state; 383+ cmd.path_mtu = attr->path_mtu; 384+ cmd.path_mig_state = attr->path_mig_state; 385+ cmd.en_sqd_async_notify = attr->en_sqd_async_notify; 386+ cmd.max_rd_atomic = attr->max_rd_atomic; 387+ cmd.max_dest_rd_atomic = attr->max_dest_rd_atomic; 388+ cmd.min_rnr_timer = attr->min_rnr_timer; 389+ cmd.port_num = attr->port_num; 390+ cmd.timeout = attr->timeout; 391+ cmd.retry_cnt = attr->retry_cnt; 392+ cmd.rnr_retry = attr->rnr_retry; 393+ cmd.alt_port_num = attr->alt_port_num; 394+ cmd.alt_timeout = attr->alt_timeout; 395+ 396+ memcpy(cmd.dest.dgid, attr->ah_attr.grh.dgid.raw, 16); 397+ cmd.dest.flow_label = attr->ah_attr.grh.flow_label; 398+ cmd.dest.dlid = attr->ah_attr.dlid; 399+ cmd.dest.reserved = 0; 400+ cmd.dest.sgid_index = attr->ah_attr.grh.sgid_index; 401+ cmd.dest.hop_limit = attr->ah_attr.grh.hop_limit; 402+ cmd.dest.traffic_class = attr->ah_attr.grh.traffic_class; 403+ cmd.dest.sl = attr->ah_attr.sl; 404+ cmd.dest.src_path_bits = attr->ah_attr.src_path_bits; 405+ cmd.dest.static_rate = attr->ah_attr.static_rate; 406+ cmd.dest.is_global = attr->ah_attr.is_global; 407+ cmd.dest.port_num = attr->ah_attr.port_num; 408+ 409+ memcpy(cmd.alt_dest.dgid, attr->alt_ah_attr.grh.dgid.raw, 16); 410+ cmd.alt_dest.flow_label = attr->alt_ah_attr.grh.flow_label; 411+ cmd.alt_dest.dlid = attr->alt_ah_attr.dlid; 412+ cmd.alt_dest.reserved = 0; 413+ cmd.alt_dest.sgid_index = attr->alt_ah_attr.grh.sgid_index; 414+ cmd.alt_dest.hop_limit = attr->alt_ah_attr.grh.hop_limit; 415+ cmd.alt_dest.traffic_class = attr->alt_ah_attr.grh.traffic_class; 416+ cmd.alt_dest.sl = attr->alt_ah_attr.sl; 417+ cmd.alt_dest.src_path_bits = attr->alt_ah_attr.src_path_bits; 418+ cmd.alt_dest.static_rate = attr->alt_ah_attr.static_rate; 419+ cmd.alt_dest.is_global = attr->alt_ah_attr.is_global; 420+ cmd.alt_dest.port_num = attr->alt_ah_attr.port_num; 421+ 422+ cmd.reserved[0] = cmd.reserved[1] = 0; 423+ 424+ if (write(d->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd) 425+ return errno; 426+ 427+ return 0; 428+} 429+ 430+int ibv_cmd_query_xrc_rcv_qp(struct ibv_xrc_domain *d, uint32_t xrc_qp_num, 431+ struct ibv_qp_attr *attr, int attr_mask, 432+ struct ibv_qp_init_attr *init_attr) 433+{ 434+ struct ibv_query_xrc_rcv_qp cmd; 435+ struct ibv_query_qp_resp resp; 436+ 437+ if (abi_ver < 6) 438+ return ENOSYS; 439+ 440+ IBV_INIT_CMD_RESP(&cmd, sizeof cmd, QUERY_XRC_RCV_QP, &resp, 441+ sizeof resp); 442+ cmd.xrc_domain_handle = d->handle; 443+ cmd.qp_num = xrc_qp_num; 444+ cmd.attr_mask = attr_mask; 445+ 446+ if (write(d->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd) 447+ return errno; 448+ 449+ VALGRIND_MAKE_MEM_DEFINED(&resp, sizeof resp); 450+ 451+ attr->qkey = resp.qkey; 452+ attr->rq_psn = resp.rq_psn; 453+ attr->sq_psn = resp.sq_psn; 454+ attr->dest_qp_num = resp.dest_qp_num; 455+ attr->qp_access_flags = resp.qp_access_flags; 456+ attr->pkey_index = resp.pkey_index; 457+ attr->alt_pkey_index = resp.alt_pkey_index; 458+ attr->qp_state = resp.qp_state; 459+ attr->cur_qp_state = resp.cur_qp_state; 460+ attr->path_mtu = resp.path_mtu; 461+ attr->path_mig_state = resp.path_mig_state; 462+ attr->sq_draining = resp.sq_draining; 463+ attr->max_rd_atomic = resp.max_rd_atomic; 464+ attr->max_dest_rd_atomic = resp.max_dest_rd_atomic; 465+ attr->min_rnr_timer = resp.min_rnr_timer; 466+ attr->port_num = resp.port_num; 467+ attr->timeout = resp.timeout; 468+ attr->retry_cnt = resp.retry_cnt; 469+ attr->rnr_retry = resp.rnr_retry; 470+ attr->alt_port_num = resp.alt_port_num; 471+ attr->alt_timeout = resp.alt_timeout; 472+ attr->cap.max_send_wr = resp.max_send_wr; 473+ attr->cap.max_recv_wr = resp.max_recv_wr; 474+ attr->cap.max_send_sge = resp.max_send_sge; 475+ attr->cap.max_recv_sge = resp.max_recv_sge; 476+ attr->cap.max_inline_data = resp.max_inline_data; 477+ 478+ memcpy(attr->ah_attr.grh.dgid.raw, resp.dest.dgid, 16); 479+ attr->ah_attr.grh.flow_label = resp.dest.flow_label; 480+ attr->ah_attr.dlid = resp.dest.dlid; 481+ attr->ah_attr.grh.sgid_index = resp.dest.sgid_index; 482+ attr->ah_attr.grh.hop_limit = resp.dest.hop_limit; 483+ attr->ah_attr.grh.traffic_class = resp.dest.traffic_class; 484+ attr->ah_attr.sl = resp.dest.sl; 485+ attr->ah_attr.src_path_bits = resp.dest.src_path_bits; 486+ attr->ah_attr.static_rate = resp.dest.static_rate; 487+ attr->ah_attr.is_global = resp.dest.is_global; 488+ attr->ah_attr.port_num = resp.dest.port_num; 489+ 490+ memcpy(attr->alt_ah_attr.grh.dgid.raw, resp.alt_dest.dgid, 16); 491+ attr->alt_ah_attr.grh.flow_label = resp.alt_dest.flow_label; 492+ attr->alt_ah_attr.dlid = resp.alt_dest.dlid; 493+ attr->alt_ah_attr.grh.sgid_index = resp.alt_dest.sgid_index; 494+ attr->alt_ah_attr.grh.hop_limit = resp.alt_dest.hop_limit; 495+ attr->alt_ah_attr.grh.traffic_class = resp.alt_dest.traffic_class; 496+ attr->alt_ah_attr.sl = resp.alt_dest.sl; 497+ attr->alt_ah_attr.src_path_bits = resp.alt_dest.src_path_bits; 498+ attr->alt_ah_attr.static_rate = resp.alt_dest.static_rate; 499+ attr->alt_ah_attr.is_global = resp.alt_dest.is_global; 500+ attr->alt_ah_attr.port_num = resp.alt_dest.port_num; 501+ 502+ init_attr->cap.max_send_wr = resp.max_send_wr; 503+ init_attr->cap.max_recv_wr = resp.max_recv_wr; 504+ init_attr->cap.max_send_sge = resp.max_send_sge; 505+ init_attr->cap.max_recv_sge = resp.max_recv_sge; 506+ init_attr->cap.max_inline_data = resp.max_inline_data; 507+ init_attr->sq_sig_all = resp.sq_sig_all; 508+ 509+ return 0; 510+} 511+ 512 static int ibv_cmd_destroy_qp_v1(struct ibv_qp *qp) 513 { 514 struct ibv_destroy_qp_v1 cmd; 515@@ -1192,3 +1374,36 @@ int ibv_cmd_close_xrc_domain(struct ibv_ 516 return 0; 517 } 518 519+int ibv_cmd_reg_xrc_rcv_qp(struct ibv_xrc_domain *d, uint32_t xrc_qp_num) 520+{ 521+ struct ibv_reg_xrc_rcv_qp cmd; 522+ 523+ if (abi_ver < 6) 524+ return ENOSYS; 525+ 526+ IBV_INIT_CMD(&cmd, sizeof cmd, REG_XRC_RCV_QP); 527+ cmd.xrc_domain_handle = d->handle; 528+ cmd.qp_num = xrc_qp_num; 529+ 530+ if (write(d->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd) 531+ return errno; 532+ return 0; 533+} 534+ 535+int ibv_cmd_unreg_xrc_rcv_qp(struct ibv_xrc_domain *d, uint32_t xrc_qp_num) 536+{ 537+ struct ibv_unreg_xrc_rcv_qp cmd; 538+ 539+ if (abi_ver < 6) 540+ return ENOSYS; 541+ 542+ IBV_INIT_CMD(&cmd, sizeof cmd, UNREG_XRC_RCV_QP); 543+ cmd.xrc_domain_handle = d->handle; 544+ cmd.qp_num = xrc_qp_num; 545+ 546+ if (write(d->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd) 547+ return errno; 548+ return 0; 549+} 550+ 551+ 552Index: libibverbs/src/device.c 553=================================================================== 554--- libibverbs.orig/src/device.c 2009-11-01 15:18:17.794116000 +0200 555+++ libibverbs/src/device.c 2009-11-01 15:18:24.597279000 +0200 556@@ -191,31 +191,33 @@ int __ibv_get_async_event(struct ibv_con 557 558 event->event_type = ev.event_type; 559 560- switch (event->event_type) { 561- case IBV_EVENT_CQ_ERR: 562- event->element.cq = (void *) (uintptr_t) ev.element; 563- break; 564- 565- case IBV_EVENT_QP_FATAL: 566- case IBV_EVENT_QP_REQ_ERR: 567- case IBV_EVENT_QP_ACCESS_ERR: 568- case IBV_EVENT_COMM_EST: 569- case IBV_EVENT_SQ_DRAINED: 570- case IBV_EVENT_PATH_MIG: 571- case IBV_EVENT_PATH_MIG_ERR: 572- case IBV_EVENT_QP_LAST_WQE_REACHED: 573- event->element.qp = (void *) (uintptr_t) ev.element; 574- break; 575- 576- case IBV_EVENT_SRQ_ERR: 577- case IBV_EVENT_SRQ_LIMIT_REACHED: 578- event->element.srq = (void *) (uintptr_t) ev.element; 579- break; 580- 581- default: 582- event->element.port_num = ev.element; 583- break; 584- } 585+ if (event->event_type & IBV_XRC_QP_EVENT_FLAG) { 586+ event->element.xrc_qp_num = ev.element; 587+ } else 588+ switch (event->event_type) { 589+ case IBV_EVENT_CQ_ERR: 590+ event->element.cq = (void *) (uintptr_t) ev.element; 591+ break; 592+ 593+ case IBV_EVENT_QP_FATAL: 594+ case IBV_EVENT_QP_REQ_ERR: 595+ case IBV_EVENT_QP_ACCESS_ERR: 596+ case IBV_EVENT_COMM_EST: 597+ case IBV_EVENT_SQ_DRAINED: 598+ case IBV_EVENT_PATH_MIG: 599+ case IBV_EVENT_PATH_MIG_ERR: 600+ case IBV_EVENT_QP_LAST_WQE_REACHED: 601+ event->element.qp = (void *) (uintptr_t) ev.element; 602+ break; 603+ 604+ case IBV_EVENT_SRQ_ERR: 605+ case IBV_EVENT_SRQ_LIMIT_REACHED: 606+ event->element.srq = (void *) (uintptr_t) ev.element; 607+ break; 608+ default: 609+ event->element.port_num = ev.element; 610+ break; 611+ } 612 613 if (context->ops.async_event) 614 context->ops.async_event(event); 615Index: libibverbs/src/libibverbs.map 616=================================================================== 617--- libibverbs.orig/src/libibverbs.map 2009-11-01 15:18:20.646169000 +0200 618+++ libibverbs/src/libibverbs.map 2009-11-01 15:18:24.600279000 +0200 619@@ -97,6 +97,16 @@ IBVERBS_1.1 { 620 ibv_cmd_open_xrc_domain; 621 ibv_close_xrc_domain; 622 ibv_cmd_close_xrc_domain; 623+ ibv_create_xrc_rcv_qp; 624+ ibv_cmd_create_xrc_rcv_qp; 625+ ibv_modify_xrc_rcv_qp; 626+ ibv_cmd_modify_xrc_rcv_qp; 627+ ibv_query_xrc_rcv_qp; 628+ ibv_cmd_query_xrc_rcv_qp; 629+ ibv_reg_xrc_rcv_qp; 630+ ibv_cmd_reg_xrc_rcv_qp; 631+ ibv_unreg_xrc_rcv_qp; 632+ ibv_cmd_unreg_xrc_rcv_qp; 633 634 ibv_node_type_str; 635 ibv_port_state_str; 636Index: libibverbs/src/verbs.c 637=================================================================== 638--- libibverbs.orig/src/verbs.c 2009-11-01 15:18:20.650169000 +0200 639+++ libibverbs/src/verbs.c 2009-11-01 15:18:24.604279000 +0200 640@@ -597,3 +597,62 @@ int ibv_close_xrc_domain(struct ibv_xrc_ 641 642 return d->context->more_ops->close_xrc_domain(d); 643 } 644+ 645+int ibv_create_xrc_rcv_qp(struct ibv_qp_init_attr *init_attr, 646+ uint32_t *xrc_rcv_qpn) 647+{ 648+ struct ibv_context *c; 649+ if (!init_attr || !(init_attr->xrc_domain)) 650+ return EINVAL; 651+ 652+ c = init_attr->xrc_domain->context; 653+ if (!c->more_ops) 654+ return ENOSYS; 655+ 656+ return c->more_ops->create_xrc_rcv_qp(init_attr, 657+ xrc_rcv_qpn); 658+} 659+ 660+int ibv_modify_xrc_rcv_qp(struct ibv_xrc_domain *d, 661+ uint32_t xrc_rcv_qpn, 662+ struct ibv_qp_attr *attr, 663+ int attr_mask) 664+{ 665+ if (!d || !attr) 666+ return EINVAL; 667+ 668+ if (!d->context->more_ops) 669+ return ENOSYS; 670+ 671+ return d->context->more_ops->modify_xrc_rcv_qp(d, xrc_rcv_qpn, attr, 672+ attr_mask); 673+} 674+ 675+int ibv_query_xrc_rcv_qp(struct ibv_xrc_domain *d, 676+ uint32_t xrc_rcv_qpn, 677+ struct ibv_qp_attr *attr, 678+ int attr_mask, 679+ struct ibv_qp_init_attr *init_attr) 680+{ 681+ if (!d) 682+ return EINVAL; 683+ 684+ if (!d->context->more_ops) 685+ return ENOSYS; 686+ 687+ return d->context->more_ops->query_xrc_rcv_qp(d, xrc_rcv_qpn, attr, 688+ attr_mask, init_attr); 689+} 690+ 691+int ibv_reg_xrc_rcv_qp(struct ibv_xrc_domain *d, 692+ uint32_t xrc_rcv_qpn) 693+{ 694+ return d->context->more_ops->reg_xrc_rcv_qp(d, xrc_rcv_qpn); 695+} 696+ 697+int ibv_unreg_xrc_rcv_qp(struct ibv_xrc_domain *d, 698+ uint32_t xrc_rcv_qpn) 699+{ 700+ return d->context->more_ops->unreg_xrc_rcv_qp(d, xrc_rcv_qpn); 701+} 702+ 703