[openib-general] [RFC] [PATCH 4/7] ibrdmaverbs src files
Krishna Kumar
krkumar2 at in.ibm.com
Mon Jul 10 03:39:45 PDT 2006
Resending this with correct subject. Also set "Preformat".
Thanks,
- KK
This library provides equivalent functionality to
libibverbs, but changes the data types and verb
API's to be transport neutral. This patch contains
the source files.
Signed-of-by: Krishna Kumar <krkumar2 at in.ibm.com>
diff -ruNp ORG/librdmaverbs/src/cmd.c NEW/librdmaverbs/src/cmd.c
--- ORG/librdmaverbs/src/cmd.c 1969-12-31 16:00:00.000000000 -0800
+++ NEW/librdmaverbs/src/cmd.c 2006-07-10 18:07:47.000000000 -0700
@@ -0,0 +1,1060 @@
+/*
+ * Copyright (c) 2005 Topspin Communications. All rights reserved.
+ * Copyright (c) 2005 PathScale, Inc. All rights reserved.
+ * Copyright (c) 2006 Cisco Systems, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: cmd.c 7631 2006-06-02 19:53:25Z swise $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <alloca.h>
+#include <string.h>
+
+#include "rdmaverbs.h"
+
+static int rdma_cmd_get_context_v2(struct rdma_context *context,
+ struct rdma_get_context *new_cmd,
+ size_t new_cmd_size,
+ struct rdma_get_context_resp *resp,
+ size_t resp_size)
+{
+ struct rdma_abi_compat_v2 *t;
+ struct rdma_get_context_v2 *cmd;
+ size_t cmd_size;
+ uint32_t cq_fd;
+
+ t = malloc(sizeof *t);
+ if (!t)
+ return ENOMEM;
+ pthread_mutex_init(&t->in_use, NULL);
+
+ cmd_size = sizeof *cmd + new_cmd_size - sizeof *new_cmd;
+ cmd = alloca(cmd_size);
+ memcpy(cmd->driver_data, new_cmd->driver_data, new_cmd_size - sizeof *new_cmd);
+
+ RDMA_INIT_CMD_RESP(cmd, cmd_size, GET_CONTEXT, resp, resp_size);
+ cmd->cq_fd_tab = (uintptr_t) &cq_fd;
+
+ if (write(context->cmd_fd, cmd, cmd_size) != cmd_size)
+ return errno;
+
+ context->async_fd = resp->async_fd;
+ context->num_comp_vectors = 1;
+ t->channel.fd = cq_fd;
+ context->abi_compat = t;
+
+ return 0;
+}
+
+int rdma_cmd_get_context(struct rdma_context *context, struct rdma_get_context *cmd,
+ size_t cmd_size, struct rdma_get_context_resp *resp,
+ size_t resp_size)
+{
+ if (abi_ver <= 2)
+ return rdma_cmd_get_context_v2(context, cmd, cmd_size, resp, resp_size);
+
+ RDMA_INIT_CMD_RESP(cmd, cmd_size, GET_CONTEXT, resp, resp_size);
+
+ if (write(context->cmd_fd, cmd, cmd_size) != cmd_size)
+ return errno;
+
+ context->async_fd = resp->async_fd;
+ context->num_comp_vectors = resp->num_comp_vectors;
+
+ return 0;
+}
+
+int rdma_cmd_query_device(struct rdma_context *context,
+ struct rdma_device_attr *device_attr,
+ uint64_t *raw_fw_ver,
+ struct rdma_query_device *cmd, size_t cmd_size)
+{
+ struct rdma_query_device_resp resp;
+
+ RDMA_INIT_CMD_RESP(cmd, cmd_size, QUERY_DEVICE, &resp, sizeof resp);
+
+ if (write(context->cmd_fd, cmd, cmd_size) != cmd_size)
+ return errno;
+
+ memset(device_attr->fw_ver, 0, sizeof device_attr->fw_ver);
+ *raw_fw_ver = resp.fw_ver;
+ device_attr->node_guid = resp.node_guid;
+ device_attr->sys_image_guid = resp.sys_image_guid;
+ device_attr->max_mr_size = resp.max_mr_size;
+ device_attr->page_size_cap = resp.page_size_cap;
+ device_attr->vendor_id = resp.vendor_id;
+ device_attr->vendor_part_id = resp.vendor_part_id;
+ device_attr->hw_ver = resp.hw_ver;
+ device_attr->max_qp = resp.max_qp;
+ device_attr->max_qp_wr = resp.max_qp_wr;
+ device_attr->device_cap_flags = resp.device_cap_flags;
+ device_attr->max_sge = resp.max_sge;
+ device_attr->max_sge_rd = resp.max_sge_rd;
+ device_attr->max_cq = resp.max_cq;
+ device_attr->max_cqe = resp.max_cqe;
+ device_attr->max_mr = resp.max_mr;
+ device_attr->max_pd = resp.max_pd;
+ device_attr->max_qp_rd_atom = resp.max_qp_rd_atom;
+ device_attr->max_ee_rd_atom = resp.max_ee_rd_atom;
+ device_attr->max_res_rd_atom = resp.max_res_rd_atom;
+ device_attr->max_qp_init_rd_atom = resp.max_qp_init_rd_atom;
+ device_attr->max_ee_init_rd_atom = resp.max_ee_init_rd_atom;
+ device_attr->atomic_cap = resp.atomic_cap;
+ device_attr->max_ee = resp.max_ee;
+ device_attr->max_rdd = resp.max_rdd;
+ device_attr->max_mw = resp.max_mw;
+ device_attr->max_raw_ipv6_qp = resp.max_raw_ipv6_qp;
+ device_attr->max_raw_ethy_qp = resp.max_raw_ethy_qp;
+ device_attr->max_mcast_grp = resp.max_mcast_grp;
+ device_attr->max_mcast_qp_attach = resp.max_mcast_qp_attach;
+ device_attr->max_total_mcast_qp_attach = resp.max_total_mcast_qp_attach;
+ device_attr->max_ah = resp.max_ah;
+ device_attr->max_fmr = resp.max_fmr;
+ device_attr->max_map_per_fmr = resp.max_map_per_fmr;
+ device_attr->max_srq = resp.max_srq;
+ device_attr->max_srq_wr = resp.max_srq_wr;
+ device_attr->max_srq_sge = resp.max_srq_sge;
+ device_attr->max_pkeys = resp.max_pkeys;
+ device_attr->local_ca_ack_delay = resp.local_ca_ack_delay;
+ device_attr->phys_port_cnt = resp.phys_port_cnt;
+
+ return 0;
+}
+
+int rdma_cmd_query_port(struct rdma_context *context, uint8_t port_num,
+ struct rdma_port_attr *port_attr,
+ struct rdma_query_port *cmd, size_t cmd_size)
+{
+ struct rdma_query_port_resp resp;
+
+ RDMA_INIT_CMD_RESP(cmd, cmd_size, QUERY_PORT, &resp, sizeof resp);
+ cmd->port_num = port_num;
+
+ if (write(context->cmd_fd, cmd, cmd_size) != cmd_size)
+ return errno;
+
+ port_attr->state = resp.state;
+ port_attr->max_mtu = resp.max_mtu;
+ port_attr->active_mtu = resp.active_mtu;
+ port_attr->gid_tbl_len = resp.gid_tbl_len;
+ port_attr->port_cap_flags = resp.port_cap_flags;
+ port_attr->max_msg_sz = resp.max_msg_sz;
+ port_attr->bad_pkey_cntr = resp.bad_pkey_cntr;
+ port_attr->qkey_viol_cntr = resp.qkey_viol_cntr;
+ port_attr->pkey_tbl_len = resp.pkey_tbl_len;
+ port_attr->lid = resp.lid;
+ port_attr->sm_lid = resp.sm_lid;
+ port_attr->lmc = resp.lmc;
+ port_attr->max_vl_num = resp.max_vl_num;
+ port_attr->sm_sl = resp.sm_sl;
+ port_attr->subnet_timeout = resp.subnet_timeout;
+ port_attr->init_type_reply = resp.init_type_reply;
+ port_attr->active_width = resp.active_width;
+ port_attr->active_speed = resp.active_speed;
+ port_attr->phys_state = resp.phys_state;
+
+ return 0;
+}
+
+int rdma_cmd_alloc_pd(struct rdma_context *context, struct rdma_pd *pd,
+ struct rdma_alloc_pd *cmd, size_t cmd_size,
+ struct rdma_alloc_pd_resp *resp, size_t resp_size)
+{
+ RDMA_INIT_CMD_RESP(cmd, cmd_size, ALLOC_PD, resp, resp_size);
+
+ if (write(context->cmd_fd, cmd, cmd_size) != cmd_size)
+ return errno;
+
+ pd->handle = resp->pd_handle;
+
+ return 0;
+}
+
+int rdma_cmd_dealloc_pd(struct rdma_pd *pd)
+{
+ struct rdma_dealloc_pd cmd;
+
+ RDMA_INIT_CMD(&cmd, sizeof cmd, DEALLOC_PD);
+ cmd.pd_handle = pd->handle;
+
+ if (write(pd->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
+ return errno;
+
+ return 0;
+}
+
+int rdma_cmd_reg_mr(struct rdma_pd *pd, void *addr, size_t length,
+ uint64_t hca_va, enum rdma_access_flags access,
+ struct rdma_mr *mr, struct rdma_reg_mr *cmd,
+ size_t cmd_size)
+{
+ struct rdma_reg_mr_resp resp;
+
+ RDMA_INIT_CMD_RESP(cmd, cmd_size, REG_MR, &resp, sizeof resp);
+
+ cmd->start = (uintptr_t) addr;
+ cmd->length = length;
+ cmd->hca_va = hca_va;
+ cmd->pd_handle = pd->handle;
+ cmd->access_flags = access;
+
+ if (write(pd->context->cmd_fd, cmd, cmd_size) != cmd_size)
+ return errno;
+
+ mr->handle = resp.mr_handle;
+ mr->lkey = resp.lkey;
+ mr->rkey = resp.rkey;
+
+ return 0;
+}
+
+int rdma_cmd_dereg_mr(struct rdma_mr *mr)
+{
+ struct rdma_dereg_mr cmd;
+
+ RDMA_INIT_CMD(&cmd, sizeof cmd, DEREG_MR);
+ cmd.mr_handle = mr->handle;
+
+ if (write(mr->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
+ return errno;
+
+ return 0;
+}
+
+static int rdma_cmd_create_cq_v2(struct rdma_context *context, int cqe,
+ struct rdma_cq *cq,
+ struct rdma_create_cq *new_cmd, size_t new_cmd_size,
+ struct rdma_create_cq_resp *resp, size_t resp_size)
+{
+ struct rdma_create_cq_v2 *cmd;
+ size_t cmd_size;
+
+ cmd_size = sizeof *cmd + new_cmd_size - sizeof *new_cmd;
+ cmd = alloca(cmd_size);
+ memcpy(cmd->driver_data, new_cmd->driver_data, new_cmd_size - sizeof *new_cmd);
+
+ RDMA_INIT_CMD_RESP(cmd, cmd_size, CREATE_CQ, resp, resp_size);
+ cmd->user_handle = (uintptr_t) cq;
+ cmd->cqe = cqe;
+ cmd->event_handler = 0;
+
+ if (write(context->cmd_fd, cmd, cmd_size) != cmd_size)
+ return errno;
+
+ cq->handle = resp->cq_handle;
+ cq->cqe = resp->cqe;
+
+ return 0;
+}
+
+int rdma_cmd_create_cq(struct rdma_context *context, int cqe,
+ struct rdma_comp_channel *channel,
+ int comp_vector, struct rdma_cq *cq,
+ struct rdma_create_cq *cmd, size_t cmd_size,
+ struct rdma_create_cq_resp *resp, size_t resp_size)
+{
+ if (abi_ver <= 2)
+ return rdma_cmd_create_cq_v2(context, cqe, cq,
+ cmd, cmd_size, resp, resp_size);
+
+ RDMA_INIT_CMD_RESP(cmd, cmd_size, CREATE_CQ, resp, resp_size);
+ cmd->user_handle = (uintptr_t) cq;
+ cmd->cqe = cqe;
+ cmd->comp_vector = comp_vector;
+ cmd->comp_channel = channel ? channel->fd : -1;
+ cmd->reserved = 0;
+
+ if (write(context->cmd_fd, cmd, cmd_size) != cmd_size)
+ return errno;
+
+ cq->handle = resp->cq_handle;
+ cq->cqe = resp->cqe;
+
+ return 0;
+}
+
+int rdma_cmd_poll_cq(struct rdma_cq *ibcq, int ne, struct rdma_wc *wc)
+{
+ struct rdma_poll_cq cmd;
+ struct rdma_poll_cq_resp *resp;
+ int i;
+ int rsize;
+ int ret;
+
+ rsize = sizeof *resp + ne * sizeof(struct rdma_kern_wc);
+ resp = malloc(rsize);
+ if (!resp)
+ return -1;
+
+ RDMA_INIT_CMD_RESP(&cmd, sizeof cmd, POLL_CQ, resp, rsize);
+ cmd.cq_handle = ibcq->handle;
+ cmd.ne = ne;
+
+ if (write(ibcq->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd) {
+ ret = -1;
+ goto out;
+ }
+
+ for (i = 0; i < resp->count; i++) {
+ wc[i].wr_id = resp->wc[i].wr_id;
+ wc[i].status = resp->wc[i].status;
+ wc[i].opcode = resp->wc[i].opcode;
+ wc[i].vendor_err = resp->wc[i].vendor_err;
+ wc[i].byte_len = resp->wc[i].byte_len;
+ wc[i].imm_data = resp->wc[i].imm_data;
+ wc[i].qp_num = resp->wc[i].qp_num;
+ wc[i].src_qp = resp->wc[i].src_qp;
+ wc[i].wc_flags = resp->wc[i].wc_flags;
+ wc[i].pkey_index = resp->wc[i].pkey_index;
+ wc[i].slid = resp->wc[i].slid;
+ wc[i].sl = resp->wc[i].sl;
+ wc[i].dlid_path_bits = resp->wc[i].dlid_path_bits;
+ }
+
+ ret = resp->count;
+
+out:
+ free(resp);
+ return ret;
+}
+
+int rdma_cmd_req_notify_cq(struct rdma_cq *ibcq, int solicited_only)
+{
+ struct rdma_req_notify_cq cmd;
+
+ RDMA_INIT_CMD(&cmd, sizeof cmd, REQ_NOTIFY_CQ);
+ cmd.cq_handle = ibcq->handle;
+ cmd.solicited = !!solicited_only;
+
+ if (write(ibcq->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
+ return errno;
+
+ return 0;
+}
+
+int rdma_cmd_resize_cq(struct rdma_cq *cq, int cqe,
+ struct rdma_resize_cq *cmd, size_t cmd_size)
+{
+ struct rdma_resize_cq_resp resp;
+
+ RDMA_INIT_CMD_RESP(cmd, cmd_size, RESIZE_CQ, &resp, sizeof resp);
+ cmd->cq_handle = cq->handle;
+ cmd->cqe = cqe;
+
+ if (write(cq->context->cmd_fd, cmd, cmd_size) != cmd_size)
+ return errno;
+
+ cq->cqe = resp.cqe;
+
+ return 0;
+}
+
+static int rdma_cmd_destroy_cq_v1(struct rdma_cq *cq)
+{
+ struct rdma_destroy_cq_v1 cmd;
+
+ RDMA_INIT_CMD(&cmd, sizeof cmd, DESTROY_CQ);
+ cmd.cq_handle = cq->handle;
+
+ if (write(cq->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
+ return errno;
+
+ return 0;
+}
+
+int rdma_cmd_destroy_cq(struct rdma_cq *cq)
+{
+ struct rdma_destroy_cq cmd;
+ struct rdma_destroy_cq_resp resp;
+
+ if (abi_ver == 1)
+ return rdma_cmd_destroy_cq_v1(cq);
+
+ RDMA_INIT_CMD_RESP(&cmd, sizeof cmd, DESTROY_CQ, &resp, sizeof resp);
+ cmd.cq_handle = cq->handle;
+
+ if (write(cq->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
+ return errno;
+
+ pthread_mutex_lock(&cq->mutex);
+ while (cq->comp_events_completed != resp.comp_events_reported ||
+ cq->async_events_completed != resp.async_events_reported)
+ pthread_cond_wait(&cq->cond, &cq->mutex);
+ pthread_mutex_unlock(&cq->mutex);
+
+ return 0;
+}
+
+int rdma_cmd_create_srq(struct rdma_pd *pd,
+ struct rdma_srq *srq, struct rdma_srq_init_attr *attr,
+ struct rdma_create_srq *cmd, size_t cmd_size,
+ struct rdma_create_srq_resp *resp, size_t resp_size)
+{
+ RDMA_INIT_CMD_RESP(cmd, cmd_size, CREATE_SRQ, resp, resp_size);
+ cmd->user_handle = (uintptr_t) srq;
+ cmd->pd_handle = pd->handle;
+ cmd->max_wr = attr->attr.max_wr;
+ cmd->max_sge = attr->attr.max_sge;
+ cmd->srq_limit = attr->attr.srq_limit;
+
+ if (write(pd->context->cmd_fd, cmd, cmd_size) != cmd_size)
+ return errno;
+
+ srq->handle = resp->srq_handle;
+
+ if (abi_ver > 5) {
+ attr->attr.max_wr = resp->max_wr;
+ attr->attr.max_sge = resp->max_sge;
+ } else {
+ struct rdma_create_srq_resp_v5 *resp_v5 =
+ (struct rdma_create_srq_resp_v5 *) resp;
+
+ memmove((void *) resp + sizeof *resp,
+ (void *) resp_v5 + sizeof *resp_v5,
+ resp_size - sizeof *resp);
+ }
+
+ return 0;
+}
+
+static int rdma_cmd_modify_srq_v3(struct rdma_srq *srq,
+ struct rdma_srq_attr *srq_attr,
+ enum rdma_srq_attr_mask srq_attr_mask,
+ struct rdma_modify_srq *new_cmd,
+ size_t new_cmd_size)
+{
+ struct rdma_modify_srq_v3 *cmd;
+ size_t cmd_size;
+
+ cmd_size = sizeof *cmd + new_cmd_size - sizeof *new_cmd;
+ cmd = alloca(cmd_size);
+ memcpy(cmd->driver_data, new_cmd->driver_data, new_cmd_size - sizeof *new_cmd);
+
+ RDMA_INIT_CMD(cmd, cmd_size, MODIFY_SRQ);
+
+ cmd->srq_handle = srq->handle;
+ cmd->attr_mask = srq_attr_mask;
+ cmd->max_wr = srq_attr->max_wr;
+ cmd->srq_limit = srq_attr->srq_limit;
+ cmd->max_sge = 0;
+ cmd->reserved = 0;
+
+ if (write(srq->context->cmd_fd, cmd, cmd_size) != cmd_size)
+ return errno;
+
+ return 0;
+}
+
+int rdma_cmd_modify_srq(struct rdma_srq *srq,
+ struct rdma_srq_attr *srq_attr,
+ enum rdma_srq_attr_mask srq_attr_mask,
+ struct rdma_modify_srq *cmd, size_t cmd_size)
+{
+ if (abi_ver == 3)
+ return rdma_cmd_modify_srq_v3(srq, srq_attr, srq_attr_mask,
+ cmd, cmd_size);
+
+ RDMA_INIT_CMD(cmd, cmd_size, MODIFY_SRQ);
+
+ cmd->srq_handle = srq->handle;
+ cmd->attr_mask = srq_attr_mask;
+ cmd->max_wr = srq_attr->max_wr;
+ cmd->srq_limit = srq_attr->srq_limit;
+
+ if (write(srq->context->cmd_fd, cmd, cmd_size) != cmd_size)
+ return errno;
+
+ return 0;
+}
+
+int rdma_cmd_query_srq(struct rdma_srq *srq, struct rdma_srq_attr *srq_attr,
+ struct rdma_query_srq *cmd, size_t cmd_size)
+{
+ struct rdma_query_srq_resp resp;
+
+ RDMA_INIT_CMD_RESP(cmd, cmd_size, QUERY_SRQ, &resp, sizeof resp);
+ cmd->srq_handle = srq->handle;
+
+ if (write(srq->context->cmd_fd, cmd, cmd_size) != cmd_size)
+ return errno;
+
+ srq_attr->max_wr = resp.max_wr;
+ srq_attr->max_sge = resp.max_sge;
+ srq_attr->srq_limit = resp.srq_limit;
+
+ return 0;
+}
+
+static int rdma_cmd_destroy_srq_v1(struct rdma_srq *srq)
+{
+ struct rdma_destroy_srq_v1 cmd;
+
+ RDMA_INIT_CMD(&cmd, sizeof cmd, DESTROY_SRQ);
+ cmd.srq_handle = srq->handle;
+
+ if (write(srq->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
+ return errno;
+
+ return 0;
+}
+
+int rdma_cmd_destroy_srq(struct rdma_srq *srq)
+{
+ struct rdma_destroy_srq cmd;
+ struct rdma_destroy_srq_resp resp;
+
+ if (abi_ver == 1)
+ return rdma_cmd_destroy_srq_v1(srq);
+
+ RDMA_INIT_CMD_RESP(&cmd, sizeof cmd, DESTROY_SRQ, &resp, sizeof resp);
+ cmd.srq_handle = srq->handle;
+
+ if (write(srq->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
+ return errno;
+
+ pthread_mutex_lock(&srq->mutex);
+ while (srq->events_completed != resp.events_reported)
+ pthread_cond_wait(&srq->cond, &srq->mutex);
+ pthread_mutex_unlock(&srq->mutex);
+
+ return 0;
+}
+
+int rdma_cmd_create_qp(struct rdma_pd *pd,
+ struct rdma_qp *qp, struct rdma_qp_init_attr *attr,
+ struct rdma_create_qp *cmd, size_t cmd_size,
+ struct rdma_create_qp_resp *resp, size_t resp_size)
+{
+ RDMA_INIT_CMD_RESP(cmd, cmd_size, CREATE_QP, resp, resp_size);
+
+ cmd->user_handle = (uintptr_t) qp;
+ cmd->pd_handle = pd->handle;
+ cmd->send_cq_handle = attr->send_cq->handle;
+ cmd->recv_cq_handle = attr->recv_cq->handle;
+ cmd->srq_handle = attr->srq ? attr->srq->handle : 0;
+ cmd->max_send_wr = attr->cap.max_send_wr;
+ cmd->max_recv_wr = attr->cap.max_recv_wr;
+ cmd->max_send_sge = attr->cap.max_send_sge;
+ cmd->max_recv_sge = attr->cap.max_recv_sge;
+ cmd->max_inline_data = attr->cap.max_inline_data;
+ cmd->sq_sig_all = attr->sq_sig_all;
+ cmd->qp_type = attr->qp_type;
+ cmd->is_srq = !!attr->srq;
+
+ if (write(pd->context->cmd_fd, cmd, cmd_size) != cmd_size)
+ return errno;
+
+ qp->handle = resp->qp_handle;
+ qp->qp_num = resp->qpn;
+
+ if (abi_ver > 3) {
+ attr->cap.max_recv_sge = resp->max_recv_sge;
+ attr->cap.max_send_sge = resp->max_send_sge;
+ attr->cap.max_recv_wr = resp->max_recv_wr;
+ attr->cap.max_send_wr = resp->max_send_wr;
+ attr->cap.max_inline_data = resp->max_inline_data;
+ }
+
+ if (abi_ver == 4) {
+ struct rdma_create_qp_resp_v4 *resp_v4 =
+ (struct rdma_create_qp_resp_v4 *) resp;
+
+ memmove((void *) resp + sizeof *resp,
+ (void *) resp_v4 + sizeof *resp_v4,
+ resp_size - sizeof *resp);
+ } else if (abi_ver <= 3) {
+ struct rdma_create_qp_resp_v3 *resp_v3 =
+ (struct rdma_create_qp_resp_v3 *) resp;
+
+ memmove((void *) resp + sizeof *resp,
+ (void *) resp_v3 + sizeof *resp_v3,
+ resp_size - sizeof *resp);
+ }
+
+ return 0;
+}
+
+int rdma_cmd_query_qp(struct rdma_qp *qp, struct rdma_qp_attr *attr,
+ enum rdma_qp_attr_mask attr_mask,
+ struct rdma_qp_init_attr *init_attr,
+ struct rdma_query_qp *cmd, size_t cmd_size)
+{
+ struct rdma_query_qp_resp resp;
+
+ RDMA_INIT_CMD_RESP(cmd, cmd_size, QUERY_QP, &resp, sizeof resp);
+ cmd->qp_handle = qp->handle;
+ cmd->attr_mask = attr_mask;
+
+ if (write(qp->context->cmd_fd, cmd, cmd_size) != cmd_size)
+ return errno;
+
+ attr->qkey = resp.qkey;
+ attr->rq_psn = resp.rq_psn;
+ attr->sq_psn = resp.sq_psn;
+ attr->dest_qp_num = resp.dest_qp_num;
+ attr->qp_access_flags = resp.qp_access_flags;
+ attr->pkey_index = resp.pkey_index;
+ attr->alt_pkey_index = resp.alt_pkey_index;
+ attr->qp_state = resp.qp_state;
+ attr->cur_qp_state = resp.cur_qp_state;
+ attr->path_mtu = resp.path_mtu;
+ attr->path_mig_state = resp.path_mig_state;
+ attr->en_sqd_async_notify = resp.en_sqd_async_notify;
+ attr->max_rd_atomic = resp.max_rd_atomic;
+ attr->max_dest_rd_atomic = resp.max_dest_rd_atomic;
+ attr->min_rnr_timer = resp.min_rnr_timer;
+ attr->port_num = resp.port_num;
+ attr->timeout = resp.timeout;
+ attr->retry_cnt = resp.retry_cnt;
+ attr->rnr_retry = resp.rnr_retry;
+ attr->alt_port_num = resp.alt_port_num;
+ attr->alt_timeout = resp.alt_timeout;
+ attr->cap.max_send_wr = resp.max_send_wr;
+ attr->cap.max_recv_wr = resp.max_recv_wr;
+ attr->cap.max_send_sge = resp.max_send_sge;
+ attr->cap.max_recv_sge = resp.max_recv_sge;
+ attr->cap.max_inline_data = resp.max_inline_data;
+
+ memcpy(attr->ah_attr.grh.dgid.raw, resp.dest.dgid, 16);
+ attr->ah_attr.grh.flow_label = resp.dest.flow_label;
+ attr->ah_attr.dlid = resp.dest.dlid;
+ attr->ah_attr.grh.sgid_index = resp.dest.sgid_index;
+ attr->ah_attr.grh.hop_limit = resp.dest.hop_limit;
+ attr->ah_attr.grh.traffic_class = resp.dest.traffic_class;
+ attr->ah_attr.sl = resp.dest.sl;
+ attr->ah_attr.src_path_bits = resp.dest.src_path_bits;
+ attr->ah_attr.static_rate = resp.dest.static_rate;
+ attr->ah_attr.is_global = resp.dest.is_global;
+ attr->ah_attr.port_num = resp.dest.port_num;
+
+ memcpy(attr->alt_ah_attr.grh.dgid.raw, resp.alt_dest.dgid, 16);
+ attr->alt_ah_attr.grh.flow_label = resp.alt_dest.flow_label;
+ attr->alt_ah_attr.dlid = resp.alt_dest.dlid;
+ attr->alt_ah_attr.grh.sgid_index = resp.alt_dest.sgid_index;
+ attr->alt_ah_attr.grh.hop_limit = resp.alt_dest.hop_limit;
+ attr->alt_ah_attr.grh.traffic_class = resp.alt_dest.traffic_class;
+ attr->alt_ah_attr.sl = resp.alt_dest.sl;
+ attr->alt_ah_attr.src_path_bits = resp.alt_dest.src_path_bits;
+ attr->alt_ah_attr.static_rate = resp.alt_dest.static_rate;
+ attr->alt_ah_attr.is_global = resp.alt_dest.is_global;
+ attr->alt_ah_attr.port_num = resp.alt_dest.port_num;
+
+ init_attr->qp_context = qp->qp_context;
+ init_attr->send_cq = qp->send_cq;
+ init_attr->recv_cq = qp->recv_cq;
+ init_attr->srq = qp->srq;
+ init_attr->qp_type = qp->qp_type;
+ init_attr->cap.max_send_wr = resp.max_send_wr;
+ init_attr->cap.max_recv_wr = resp.max_recv_wr;
+ init_attr->cap.max_send_sge = resp.max_send_sge;
+ init_attr->cap.max_recv_sge = resp.max_recv_sge;
+ init_attr->cap.max_inline_data = resp.max_inline_data;
+ init_attr->sq_sig_all = resp.sq_sig_all;
+
+ return 0;
+}
+
+int rdma_cmd_modify_qp(struct rdma_qp *qp, struct rdma_qp_attr *attr,
+ enum rdma_qp_attr_mask attr_mask,
+ struct rdma_modify_qp *cmd, size_t cmd_size)
+{
+ RDMA_INIT_CMD(cmd, cmd_size, MODIFY_QP);
+
+ cmd->qp_handle = qp->handle;
+ cmd->attr_mask = attr_mask;
+ cmd->qkey = attr->qkey;
+ cmd->rq_psn = attr->rq_psn;
+ cmd->sq_psn = attr->sq_psn;
+ cmd->dest_qp_num = attr->dest_qp_num;
+ cmd->qp_access_flags = attr->qp_access_flags;
+ cmd->pkey_index = attr->pkey_index;
+ cmd->alt_pkey_index = attr->alt_pkey_index;
+ cmd->qp_state = attr->qp_state;
+ cmd->cur_qp_state = attr->cur_qp_state;
+ cmd->path_mtu = attr->path_mtu;
+ cmd->path_mig_state = attr->path_mig_state;
+ cmd->en_sqd_async_notify = attr->en_sqd_async_notify;
+ cmd->max_rd_atomic = attr->max_rd_atomic;
+ cmd->max_dest_rd_atomic = attr->max_dest_rd_atomic;
+ cmd->min_rnr_timer = attr->min_rnr_timer;
+ cmd->port_num = attr->port_num;
+ cmd->timeout = attr->timeout;
+ cmd->retry_cnt = attr->retry_cnt;
+ cmd->rnr_retry = attr->rnr_retry;
+ cmd->alt_port_num = attr->alt_port_num;
+ cmd->alt_timeout = attr->alt_timeout;
+
+ memcpy(cmd->dest.dgid, attr->ah_attr.grh.dgid.raw, 16);
+ cmd->dest.flow_label = attr->ah_attr.grh.flow_label;
+ cmd->dest.dlid = attr->ah_attr.dlid;
+ cmd->dest.sgid_index = attr->ah_attr.grh.sgid_index;
+ cmd->dest.hop_limit = attr->ah_attr.grh.hop_limit;
+ cmd->dest.traffic_class = attr->ah_attr.grh.traffic_class;
+ cmd->dest.sl = attr->ah_attr.sl;
+ cmd->dest.src_path_bits = attr->ah_attr.src_path_bits;
+ cmd->dest.static_rate = attr->ah_attr.static_rate;
+ cmd->dest.is_global = attr->ah_attr.is_global;
+ cmd->dest.port_num = attr->ah_attr.port_num;
+
+ memcpy(cmd->alt_dest.dgid, attr->alt_ah_attr.grh.dgid.raw, 16);
+ cmd->alt_dest.flow_label = attr->alt_ah_attr.grh.flow_label;
+ cmd->alt_dest.dlid = attr->alt_ah_attr.dlid;
+ cmd->alt_dest.sgid_index = attr->alt_ah_attr.grh.sgid_index;
+ cmd->alt_dest.hop_limit = attr->alt_ah_attr.grh.hop_limit;
+ cmd->alt_dest.traffic_class = attr->alt_ah_attr.grh.traffic_class;
+ cmd->alt_dest.sl = attr->alt_ah_attr.sl;
+ cmd->alt_dest.src_path_bits = attr->alt_ah_attr.src_path_bits;
+ cmd->alt_dest.static_rate = attr->alt_ah_attr.static_rate;
+ cmd->alt_dest.is_global = attr->alt_ah_attr.is_global;
+ cmd->alt_dest.port_num = attr->alt_ah_attr.port_num;
+
+ if (write(qp->context->cmd_fd, cmd, cmd_size) != cmd_size)
+ return errno;
+
+ return 0;
+}
+
+static int rdma_cmd_destroy_qp_v1(struct rdma_qp *qp)
+{
+ struct rdma_destroy_qp_v1 cmd;
+
+ RDMA_INIT_CMD(&cmd, sizeof cmd, DESTROY_QP);
+ cmd.qp_handle = qp->handle;
+
+ if (write(qp->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
+ return errno;
+
+ return 0;
+}
+
+int rdma_cmd_post_send(struct rdma_qp *ibqp, struct rdma_send_wr *wr,
+ struct rdma_send_wr **bad_wr)
+{
+ struct rdma_post_send *cmd;
+ struct rdma_post_send_resp resp;
+ struct rdma_send_wr *i;
+ struct rdma_kern_send_wr *n, *tmp;
+ struct rdma_sge *s;
+ unsigned wr_count = 0;
+ unsigned sge_count = 0;
+ int cmd_size;
+ int ret = 0;
+
+ for (i = wr; i; i = i->next) {
+ wr_count++;
+ sge_count += i->num_sge;
+ }
+
+ cmd_size = sizeof *cmd + wr_count * sizeof *n + sge_count * sizeof *s;
+ cmd = alloca(cmd_size);
+
+ RDMA_INIT_CMD_RESP(cmd, cmd_size, POST_SEND, &resp, sizeof resp);
+ cmd->qp_handle = ibqp->handle;
+ cmd->wr_count = wr_count;
+ cmd->sge_count = sge_count;
+ cmd->wqe_size = sizeof *n;
+
+ n = (struct rdma_kern_send_wr *) ((void *) cmd + sizeof *cmd);
+ s = (struct rdma_sge *) (n + wr_count);
+
+ tmp = n;
+ for (i = wr; i; i = i->next) {
+ tmp->wr_id = i->wr_id;
+ tmp->num_sge = i->num_sge;
+ tmp->opcode = i->opcode;
+ tmp->send_flags = i->send_flags;
+ tmp->imm_data = i->imm_data;
+ if (ibqp->qp_type == RDMA_QPT_UD) {
+ tmp->wr.ud.ah = i->wr.ud.ah->handle;
+ tmp->wr.ud.remote_qpn = i->wr.ud.remote_qpn;
+ tmp->wr.ud.remote_qkey = i->wr.ud.remote_qkey;
+ } else {
+ switch(i->opcode) {
+ case RDMA_WR_RDMA_WRITE:
+ case RDMA_WR_RDMA_WRITE_WITH_IMM:
+ case RDMA_WR_RDMA_READ:
+ tmp->wr.rdma.remote_addr =
+ i->wr.rdma.remote_addr;
+ tmp->wr.rdma.rkey = i->wr.rdma.rkey;
+ break;
+ case RDMA_WR_ATOMIC_CMP_AND_SWP:
+ case RDMA_WR_ATOMIC_FETCH_AND_ADD:
+ tmp->wr.atomic.remote_addr =
+ i->wr.atomic.remote_addr;
+ tmp->wr.atomic.compare_add =
+ i->wr.atomic.compare_add;
+ tmp->wr.atomic.swap = i->wr.atomic.swap;
+ tmp->wr.atomic.rkey = i->wr.atomic.rkey;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (tmp->num_sge) {
+ memcpy(s, i->sg_list, tmp->num_sge * sizeof *s);
+ s += tmp->num_sge;
+ }
+
+ tmp++;
+ }
+
+ resp.bad_wr = 0;
+ if (write(ibqp->context->cmd_fd, cmd, cmd_size) != cmd_size)
+ ret = errno;
+
+ wr_count = resp.bad_wr;
+ if (wr_count) {
+ i = wr;
+ while (--wr_count)
+ i = i->next;
+ *bad_wr = i;
+ }
+
+ return ret;
+}
+
+int rdma_cmd_post_recv(struct rdma_qp *ibqp, struct rdma_recv_wr *wr,
+ struct rdma_recv_wr **bad_wr)
+{
+ struct rdma_post_recv *cmd;
+ struct rdma_post_recv_resp resp;
+ struct rdma_recv_wr *i;
+ struct rdma_kern_recv_wr *n, *tmp;
+ struct rdma_sge *s;
+ unsigned wr_count = 0;
+ unsigned sge_count = 0;
+ int cmd_size;
+ int ret = 0;
+
+ for (i = wr; i; i = i->next) {
+ wr_count++;
+ sge_count += i->num_sge;
+ }
+
+ cmd_size = sizeof *cmd + wr_count * sizeof *n + sge_count * sizeof *s;
+ cmd = alloca(cmd_size);
+
+ RDMA_INIT_CMD_RESP(cmd, cmd_size, POST_RECV, &resp, sizeof resp);
+ cmd->qp_handle = ibqp->handle;
+ cmd->wr_count = wr_count;
+ cmd->sge_count = sge_count;
+ cmd->wqe_size = sizeof *n;
+
+ n = (struct rdma_kern_recv_wr *) ((void *) cmd + sizeof *cmd);
+ s = (struct rdma_sge *) (n + wr_count);
+
+ tmp = n;
+ for (i = wr; i; i = i->next) {
+ tmp->wr_id = i->wr_id;
+ tmp->num_sge = i->num_sge;
+
+ if (tmp->num_sge) {
+ memcpy(s, i->sg_list, tmp->num_sge * sizeof *s);
+ s += tmp->num_sge;
+ }
+
+ tmp++;
+ }
+
+ resp.bad_wr = 0;
+ if (write(ibqp->context->cmd_fd, cmd, cmd_size) != cmd_size)
+ ret = errno;
+
+ wr_count = resp.bad_wr;
+ if (wr_count) {
+ i = wr;
+ while (--wr_count)
+ i = i->next;
+ *bad_wr = i;
+ }
+
+ return ret;
+}
+
+int rdma_cmd_post_srq_recv(struct rdma_srq *srq, struct rdma_recv_wr *wr,
+ struct rdma_recv_wr **bad_wr)
+{
+ struct rdma_post_srq_recv *cmd;
+ struct rdma_post_srq_recv_resp resp;
+ struct rdma_recv_wr *i;
+ struct rdma_kern_recv_wr *n, *tmp;
+ struct rdma_sge *s;
+ unsigned wr_count = 0;
+ unsigned sge_count = 0;
+ int cmd_size;
+ int ret = 0;
+
+ for (i = wr; i; i = i->next) {
+ wr_count++;
+ sge_count += i->num_sge;
+ }
+
+ cmd_size = sizeof *cmd + wr_count * sizeof *n + sge_count * sizeof *s;
+ cmd = alloca(cmd_size);
+
+ RDMA_INIT_CMD_RESP(cmd, cmd_size, POST_SRQ_RECV, &resp, sizeof resp);
+ cmd->srq_handle = srq->handle;
+ cmd->wr_count = wr_count;
+ cmd->sge_count = sge_count;
+ cmd->wqe_size = sizeof *n;
+
+ n = (struct rdma_kern_recv_wr *) ((void *) cmd + sizeof *cmd);
+ s = (struct rdma_sge *) (n + wr_count);
+
+ tmp = n;
+ for (i = wr; i; i = i->next) {
+ tmp->wr_id = i->wr_id;
+ tmp->num_sge = i->num_sge;
+
+ if (tmp->num_sge) {
+ memcpy(s, i->sg_list, tmp->num_sge * sizeof *s);
+ s += tmp->num_sge;
+ }
+
+ tmp++;
+ }
+
+ resp.bad_wr = 0;
+ if (write(srq->context->cmd_fd, cmd, cmd_size) != cmd_size)
+ ret = errno;
+
+ wr_count = resp.bad_wr;
+ if (wr_count) {
+ i = wr;
+ while (--wr_count)
+ i = i->next;
+ *bad_wr = i;
+ }
+
+ return ret;
+}
+
+int rdma_cmd_create_ah(struct rdma_pd *pd, struct rdma_ah *ah,
+ struct rdma_ah_attr *attr)
+{
+ struct rdma_create_ah cmd;
+ struct rdma_create_ah_resp resp;
+
+ RDMA_INIT_CMD_RESP(&cmd, sizeof cmd, CREATE_AH, &resp, sizeof resp);
+ cmd.user_handle = (uintptr_t) ah;
+ cmd.pd_handle = pd->handle;
+ cmd.attr.dlid = attr->dlid;
+ cmd.attr.sl = attr->sl;
+ cmd.attr.src_path_bits = attr->src_path_bits;
+ cmd.attr.static_rate = attr->static_rate;
+ cmd.attr.is_global = attr->is_global;
+ cmd.attr.port_num = attr->port_num;
+ cmd.attr.grh.flow_label = attr->grh.flow_label;
+ cmd.attr.grh.sgid_index = attr->grh.sgid_index;
+ cmd.attr.grh.hop_limit = attr->grh.hop_limit;
+ cmd.attr.grh.traffic_class = attr->grh.traffic_class;
+ memcpy(cmd.attr.grh.dgid, attr->grh.dgid.raw, 16);
+
+ if (write(pd->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
+ return errno;
+
+ ah->handle = resp.handle;
+
+ return 0;
+}
+
+int rdma_cmd_destroy_ah(struct rdma_ah *ah)
+{
+ struct rdma_destroy_ah cmd;
+
+ RDMA_INIT_CMD(&cmd, sizeof cmd, DESTROY_AH);
+ cmd.ah_handle = ah->handle;
+
+ if (write(ah->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
+ return errno;
+
+ return 0;
+}
+
+int rdma_cmd_destroy_qp(struct rdma_qp *qp)
+{
+ struct rdma_destroy_qp cmd;
+ struct rdma_destroy_qp_resp resp;
+
+ if (abi_ver == 1)
+ return rdma_cmd_destroy_qp_v1(qp);
+
+ RDMA_INIT_CMD_RESP(&cmd, sizeof cmd, DESTROY_QP, &resp, sizeof resp);
+ cmd.qp_handle = qp->handle;
+
+ if (write(qp->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
+ return errno;
+
+ pthread_mutex_lock(&qp->mutex);
+ while (qp->events_completed != resp.events_reported)
+ pthread_cond_wait(&qp->cond, &qp->mutex);
+ pthread_mutex_unlock(&qp->mutex);
+
+ return 0;
+}
+
+int rdma_cmd_attach_mcast(struct rdma_qp *qp, union rdma_gid *gid, uint16_t lid)
+{
+ struct rdma_attach_mcast cmd;
+
+ RDMA_INIT_CMD(&cmd, sizeof cmd, ATTACH_MCAST);
+ memcpy(cmd.gid, gid->raw, sizeof cmd.gid);
+ cmd.qp_handle = qp->handle;
+ cmd.mlid = lid;
+
+ if (write(qp->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
+ return errno;
+
+ return 0;
+}
+
+int rdma_cmd_detach_mcast(struct rdma_qp *qp, union rdma_gid *gid, uint16_t lid)
+{
+ struct rdma_detach_mcast cmd;
+
+ RDMA_INIT_CMD(&cmd, sizeof cmd, DETACH_MCAST);
+ memcpy(cmd.gid, gid->raw, sizeof cmd.gid);
+ cmd.qp_handle = qp->handle;
+ cmd.mlid = lid;
+
+ if (write(qp->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
+ return errno;
+
+ return 0;
+}
diff -ruNp ORG/librdmaverbs/src/device.c NEW/librdmaverbs/src/device.c
--- ORG/librdmaverbs/src/device.c 1969-12-31 16:00:00.000000000 -0800
+++ NEW/librdmaverbs/src/device.c 2006-07-10 18:07:47.000000000 -0700
@@ -0,0 +1,270 @@
+/*
+ * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
+ * Copyright (c) 2006 Cisco Systems, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: device.c 7631 2006-06-02 19:53:25Z swise $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdio.h>
+#include <netinet/in.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <alloca.h>
+
+#include <rdma/arch.h>
+
+#include "rdmaverbs.h"
+
+static pthread_mutex_t device_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static int num_devices;
+static struct rdma_device **device_list;
+
+struct rdma_device **rdma_get_device_list(int *num)
+{
+ struct rdma_device **l;
+ int i;
+
+ pthread_mutex_lock(&device_list_lock);
+
+ if (!num_devices)
+ num_devices = rdmaverbs_init(&device_list);
+
+ l = calloc(num_devices + 1, sizeof (struct rdma_device *));
+ for (i = 0; i < num_devices; ++i)
+ l[i] = device_list[i];
+
+ pthread_mutex_unlock(&device_list_lock);
+
+ if (num)
+ *num = l ? num_devices : 0;
+
+ return l;
+}
+
+void rdma_free_device_list(struct rdma_device **list)
+{
+ free(list);
+}
+
+const char *rdma_get_device_name(struct rdma_device *device)
+{
+ return device->name;
+}
+
+uint64_t rdma_get_device_guid(struct rdma_device *device)
+{
+ char attr[24];
+ uint64_t guid = 0;
+ uint16_t parts[4];
+ int i;
+
+ if (rdma_read_sysfs_file(device->ibdev_path, "node_guid",
+ attr, sizeof attr) < 0)
+ return 0;
+
+ if (sscanf(attr, "%hx:%hx:%hx:%hx",
+ parts, parts + 1, parts + 2, parts + 3) != 4)
+ return 0;
+
+ for (i = 0; i < 4; ++i)
+ guid = (guid << 16) | parts[i];
+
+ return htonll(guid);
+}
+
+static enum rdma_node_type query_node_type(struct rdma_device *device)
+{
+ char node_desc[24];
+ char node_str[24];
+ int node_type;
+
+ if (rdma_read_sysfs_file(device->ibdev_path, "node_type",
+ node_desc, sizeof(node_desc)) < 0)
+ return RDMA_NODE_UNKNOWN;
+
+ sscanf(node_desc, "%d: %s\n", (int*)&node_type, node_str);
+ return (enum rdma_node_type) node_type;
+}
+
+struct rdma_context *rdma_open_device(struct rdma_device *device)
+{
+ char *devpath;
+ int cmd_fd;
+ struct rdma_context *context;
+
+ asprintf(&devpath, "/dev/infiniband/%s", device->dev_name);
+
+ /*
+ * We'll only be doing writes, but we need O_RDWR in case the
+ * provider needs to mmap() the file.
+ */
+ cmd_fd = open(devpath, O_RDWR);
+ free(devpath);
+
+ if (cmd_fd < 0)
+ return NULL;
+
+ device->node_type = query_node_type(device);
+
+ context = device->ops.alloc_context(device, cmd_fd);
+ if (!context)
+ goto err;
+
+ context->device = device;
+ context->cmd_fd = cmd_fd;
+
+ return context;
+
+err:
+ close(cmd_fd);
+
+ return NULL;
+}
+
+int rdma_close_device(struct rdma_context *context)
+{
+ int async_fd = context->async_fd;
+ int cmd_fd = context->cmd_fd;
+ int cq_fd = -1;
+
+ if (abi_ver <= 2) {
+ struct rdma_abi_compat_v2 *t = context->abi_compat;
+ cq_fd = t->channel.fd;
+ free(context->abi_compat);
+ }
+
+ context->device->ops.free_context(context);
+
+ close(async_fd);
+ close(cmd_fd);
+ if (abi_ver <= 2)
+ close(cq_fd);
+
+ return 0;
+}
+
+int rdma_get_async_event(struct rdma_context *context,
+ struct rdma_async_event *event)
+{
+ struct rdma_kern_async_event ev;
+
+ if (read(context->async_fd, &ev, sizeof ev) != sizeof ev)
+ return -1;
+
+ event->event_type = ev.event_type;
+
+ switch (event->event_type) {
+ case RDMA_EVENT_CQ_ERR:
+ event->element.cq = (void *) (uintptr_t) ev.element;
+ break;
+
+ case RDMA_EVENT_QP_FATAL:
+ case RDMA_EVENT_QP_REQ_ERR:
+ case RDMA_EVENT_QP_ACCESS_ERR:
+ case RDMA_EVENT_COMM_EST:
+ case RDMA_EVENT_SQ_DRAINED:
+ case RDMA_EVENT_PATH_MIG:
+ case RDMA_EVENT_PATH_MIG_ERR:
+ case RDMA_EVENT_QP_LAST_WQE_REACHED:
+ event->element.qp = (void *) (uintptr_t) ev.element;
+ break;
+
+ case RDMA_EVENT_SRQ_ERR:
+ case RDMA_EVENT_SRQ_LIMIT_REACHED:
+ event->element.srq = (void *) (uintptr_t) ev.element;
+ break;
+
+ default:
+ event->element.port_num = ev.element;
+ break;
+ }
+
+ return 0;
+}
+
+void rdma_ack_async_event(struct rdma_async_event *event)
+{
+ switch (event->event_type) {
+ case RDMA_EVENT_CQ_ERR:
+ {
+ struct rdma_cq *cq = event->element.cq;
+
+ pthread_mutex_lock(&cq->mutex);
+ ++cq->async_events_completed;
+ pthread_cond_signal(&cq->cond);
+ pthread_mutex_unlock(&cq->mutex);
+
+ return;
+ }
+
+ case RDMA_EVENT_QP_FATAL:
+ case RDMA_EVENT_QP_REQ_ERR:
+ case RDMA_EVENT_QP_ACCESS_ERR:
+ case RDMA_EVENT_COMM_EST:
+ case RDMA_EVENT_SQ_DRAINED:
+ case RDMA_EVENT_PATH_MIG:
+ case RDMA_EVENT_PATH_MIG_ERR:
+ case RDMA_EVENT_QP_LAST_WQE_REACHED:
+ {
+ struct rdma_qp *qp = event->element.qp;
+
+ pthread_mutex_lock(&qp->mutex);
+ ++qp->events_completed;
+ pthread_cond_signal(&qp->cond);
+ pthread_mutex_unlock(&qp->mutex);
+
+ return;
+ }
+
+ case RDMA_EVENT_SRQ_ERR:
+ case RDMA_EVENT_SRQ_LIMIT_REACHED:
+ {
+ struct rdma_srq *srq = event->element.srq;
+
+ pthread_mutex_lock(&srq->mutex);
+ ++srq->events_completed;
+ pthread_cond_signal(&srq->cond);
+ pthread_mutex_unlock(&srq->mutex);
+
+ return;
+ }
+
+ default:
+ return;
+ }
+}
diff -ruNp ORG/librdmaverbs/src/init.c NEW/librdmaverbs/src/init.c
--- ORG/librdmaverbs/src/init.c 1969-12-31 16:00:00.000000000 -0800
+++ NEW/librdmaverbs/src/init.c 2006-07-10 18:07:47.000000000 -0700
@@ -0,0 +1,274 @@
+/*
+ * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
+ * Copyright (c) 2006 Cisco Systems, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: init.c 7631 2006-06-02 19:53:25Z swise $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <glob.h>
+#include <stdio.h>
+#include <dlfcn.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <dirent.h>
+
+#include "rdmaverbs.h"
+
+#ifndef OPENRDMA_DRIVER_PATH_ENV
+# define OPENRDMA_DRIVER_PATH_ENV "OPENRDMA_DRIVER_PATH"
+#endif
+
+HIDDEN int abi_ver;
+
+static char default_path[] = DRIVER_PATH;
+static const char *user_path;
+
+static struct rdma_driver *driver_list;
+
+static void load_driver(char *so_path)
+{
+ void *dlhandle;
+ rdma_driver_init_func init_func;
+ struct rdma_driver *driver;
+
+ dlhandle = dlopen(so_path, RTLD_NOW);
+ if (!dlhandle) {
+ fprintf(stderr, PFX "Warning: couldn't load driver %s: %s\n",
+ so_path, dlerror());
+ return;
+ }
+
+ dlerror();
+ init_func = dlsym(dlhandle, "rdma_driver_init");
+ if (dlerror() != NULL || !init_func) {
+ dlclose(dlhandle);
+ return;
+ }
+
+ driver = malloc(sizeof *driver);
+ if (!driver) {
+ fprintf(stderr, PFX "Fatal: couldn't allocate driver for %s\n", so_path);
+ dlclose(dlhandle);
+ return;
+ }
+
+ driver->init_func = init_func;
+ driver->next = driver_list;
+ driver_list = driver;
+}
+
+static void find_drivers(char *dir)
+{
+ size_t len = strlen(dir);
+ glob_t so_glob;
+ char *pat;
+ int ret;
+ int i;
+
+ if (!len)
+ return;
+
+ while (len && dir[len - 1] == '/')
+ dir[--len] = '\0';
+
+ asprintf(&pat, "%s/*.so", dir);
+
+ ret = glob(pat, 0, NULL, &so_glob);
+ free(pat);
+
+ if (ret) {
+ if (ret != GLOB_NOMATCH)
+ fprintf(stderr, PFX "Warning: couldn't search %s\n", pat);
+ return;
+ }
+
+ for (i = 0; i < so_glob.gl_pathc; ++i)
+ load_driver(so_glob.gl_pathv[i]);
+
+ globfree(&so_glob);
+}
+
+static struct rdma_device *init_drivers(const char *class_path,
+ const char *dev_name)
+{
+ struct rdma_driver *driver;
+ struct rdma_device *dev;
+ int abi_ver = 0;
+ char sys_path[RDMA_SYSFS_PATH_MAX];
+ char ibdev_name[RDMA_SYSFS_NAME_MAX];
+ char value[8];
+
+ snprintf(sys_path, sizeof sys_path, "%s/%s",
+ class_path, dev_name);
+
+ if (rdma_read_sysfs_file(sys_path, "abi_version", value, sizeof value) > 0)
+ abi_ver = strtol(value, NULL, 10);
+
+ if (rdma_read_sysfs_file(sys_path, "ibdev", ibdev_name, sizeof ibdev_name) < 0) {
+ fprintf(stderr, PFX "Warning: no ibdev class attr for %s\n",
+ sys_path);
+ return NULL;
+ }
+
+ for (driver = driver_list; driver; driver = driver->next) {
+ dev = driver->init_func(sys_path, abi_ver);
+ if (!dev)
+ continue;
+
+ dev->driver = driver;
+ strcpy(dev->dev_path, sys_path);
+ snprintf(dev->ibdev_path, RDMA_SYSFS_PATH_MAX, "%s/class/infiniband/%s",
+ rdma_get_sysfs_path(), ibdev_name);
+ strcpy(dev->dev_name, dev_name);
+ strcpy(dev->name, ibdev_name);
+
+ return dev;
+ }
+
+ fprintf(stderr, PFX "Warning: no userspace device-specific driver found for %s\n"
+ " driver search path: ", dev_name);
+ if (user_path)
+ fprintf(stderr, "%s:", user_path);
+ fprintf(stderr, "%s\n", default_path);
+
+ return NULL;
+}
+
+static int check_abi_version(const char *path)
+{
+ char value[8];
+
+ if (rdma_read_sysfs_file(path, "class/infiniband_verbs/abi_version",
+ value, sizeof value) < 0) {
+ fprintf(stderr, PFX "Fatal: couldn't read uverbs ABI version.\n");
+ return -1;
+ }
+
+ abi_ver = strtol(value, NULL, 10);
+
+ if (abi_ver < RDMA_USER_VERBS_MIN_ABI_VERSION ||
+ abi_ver > RDMA_USER_VERBS_MAX_ABI_VERSION) {
+ fprintf(stderr, PFX "Fatal: kernel ABI version %d "
+ "doesn't match library version %d.\n",
+ abi_ver, RDMA_USER_VERBS_MAX_ABI_VERSION);
+ return -1;
+ }
+
+ return 0;
+}
+
+HIDDEN int rdmaverbs_init(struct rdma_device ***list)
+{
+ const char *sysfs_path;
+ char *wr_path, *dir;
+ char class_path[RDMA_SYSFS_PATH_MAX];
+ DIR *class_dir;
+ struct dirent *dent;
+ struct rdma_device *device;
+ struct rdma_device **new_list;
+ int num_devices = 0;
+ int list_size = 0;
+
+ *list = NULL;
+
+ if (rdma_init_mem_map())
+ return 0;
+
+ find_drivers(default_path);
+
+ /*
+ * Only follow use path passed in through the calling user's
+ * environment if we're not running SUID.
+ */
+ if (getuid() == geteuid()) {
+ user_path = getenv(OPENRDMA_DRIVER_PATH_ENV);
+ if (user_path) {
+ wr_path = strdupa(user_path);
+ while ((dir = strsep(&wr_path, ";:")))
+ find_drivers(dir);
+ }
+ }
+
+ /*
+ * Now check if a driver is statically linked. Since we push
+ * drivers onto our driver list, the last driver we find will
+ * be the first one we try.
+ */
+ load_driver(NULL);
+
+ sysfs_path = rdma_get_sysfs_path();
+ if (!sysfs_path) {
+ fprintf(stderr, PFX "Fatal: couldn't find sysfs mount.\n");
+ return 0;
+ }
+
+ if (check_abi_version(sysfs_path))
+ return 0;
+
+ snprintf(class_path, sizeof class_path, "%s/class/infiniband_verbs",
+ sysfs_path);
+ class_dir = opendir(class_path);
+ if (!class_dir) {
+ fprintf(stderr, PFX "Fatal: couldn't open sysfs class "
+ "directory '%s'.\n", class_path);
+ return 0;
+ }
+
+ while ((dent = readdir(class_dir))) {
+ if (dent->d_name[0] == '.' || dent->d_type == DT_REG)
+ continue;
+
+ device = init_drivers(class_path, dent->d_name);
+ if (!device)
+ continue;
+
+ if (list_size <= num_devices) {
+ list_size = list_size ? list_size * 2 : 1;
+ new_list = realloc(*list, list_size * sizeof (struct rdma_device *));
+ if (!new_list)
+ goto out;
+ *list = new_list;
+ }
+
+ (*list)[num_devices++] = device;
+ }
+
+ closedir(class_dir);
+
+out:
+ return num_devices;
+}
diff -ruNp ORG/librdmaverbs/src/librdmaverbs.map NEW/librdmaverbs/src/librdmaverbs.map
--- ORG/librdmaverbs/src/librdmaverbs.map 1969-12-31 16:00:00.000000000 -0800
+++ NEW/librdmaverbs/src/librdmaverbs.map 2006-07-10 18:07:47.000000000 -0700
@@ -0,0 +1,76 @@
+IBVERBS_1.0 {
+ global:
+ rdma_get_device_list;
+ rdma_free_device_list;
+ rdma_get_device_name;
+ rdma_get_device_guid;
+ rdma_open_device;
+ rdma_close_device;
+ rdma_get_async_event;
+ rdma_ack_async_event;
+ rdma_query_device;
+ rdma_query_port;
+ rdma_query_gid;
+ rdma_query_pkey;
+ rdma_alloc_pd;
+ rdma_dealloc_pd;
+ rdma_reg_mr;
+ rdma_dereg_mr;
+ rdma_create_comp_channel;
+ rdma_destroy_comp_channel;
+ rdma_create_cq;
+ rdma_resize_cq;
+ rdma_destroy_cq;
+ rdma_get_cq_event;
+ rdma_ack_cq_events;
+ rdma_create_srq;
+ rdma_modify_srq;
+ rdma_query_srq;
+ rdma_destroy_srq;
+ rdmav_create_qp;
+ rdma_query_qp;
+ rdma_modify_qp;
+ rdmav_destroy_qp;
+ rdma_create_ah;
+ rdma_destroy_ah;
+ rdma_attach_mcast;
+ rdma_detach_mcast;
+ rdma_cmd_get_context;
+ rdma_cmd_query_device;
+ rdma_cmd_query_port;
+ rdma_cmd_query_gid;
+ rdma_cmd_query_pkey;
+ rdma_cmd_alloc_pd;
+ rdma_cmd_dealloc_pd;
+ rdma_cmd_reg_mr;
+ rdma_cmd_dereg_mr;
+ rdma_cmd_create_cq;
+ rdma_cmd_poll_cq;
+ rdma_cmd_req_notify_cq;
+ rdma_cmd_resize_cq;
+ rdma_cmd_destroy_cq;
+ rdma_cmd_create_srq;
+ rdma_cmd_modify_srq;
+ rdma_cmd_query_srq;
+ rdma_cmd_destroy_srq;
+ rdma_cmd_create_qp;
+ rdma_cmd_query_qp;
+ rdma_cmd_modify_qp;
+ rdma_cmd_destroy_qp;
+ rdma_cmd_post_send;
+ rdma_cmd_post_recv;
+ rdma_cmd_post_srq_recv;
+ rdma_cmd_create_ah;
+ rdma_cmd_destroy_ah;
+ rdma_cmd_attach_mcast;
+ rdma_cmd_detach_mcast;
+ rdma_copy_qp_attr_from_kern;
+ rdma_copy_path_rec_from_kern;
+ rdma_copy_path_rec_to_kern;
+ rdma_rate_to_mult;
+ mult_to_rdma_rate;
+ rdma_get_sysfs_path;
+ rdma_read_sysfs_file;
+
+ local: *;
+};
diff -ruNp ORG/librdmaverbs/src/marshall.c NEW/librdmaverbs/src/marshall.c
--- ORG/librdmaverbs/src/marshall.c 1969-12-31 16:00:00.000000000 -0800
+++ NEW/librdmaverbs/src/marshall.c 2006-07-10 18:07:47.000000000 -0700
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2005 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+
+#include <rdma/marshall.h>
+
+static void rdma_copy_ah_attr_from_kern(struct rdma_ah_attr *dst,
+ struct rdma_kern_ah_attr *src)
+{
+ memcpy(dst->grh.dgid.raw, src->grh.dgid, sizeof dst->grh.dgid);
+ dst->grh.flow_label = src->grh.flow_label;
+ dst->grh.sgid_index = src->grh.sgid_index;
+ dst->grh.hop_limit = src->grh.hop_limit;
+ dst->grh.traffic_class = src->grh.traffic_class;
+
+ dst->dlid = src->dlid;
+ dst->sl = src->sl;
+ dst->src_path_bits = src->src_path_bits;
+ dst->static_rate = src->static_rate;
+ dst->is_global = src->is_global;
+ dst->port_num = src->port_num;
+}
+
+void rdma_copy_qp_attr_from_kern(struct rdma_qp_attr *dst,
+ struct rdma_kern_qp_attr *src)
+{
+ dst->cur_qp_state = src->cur_qp_state;
+ dst->path_mtu = src->path_mtu;
+ dst->path_mig_state = src->path_mig_state;
+ dst->qkey = src->qkey;
+ dst->rq_psn = src->rq_psn;
+ dst->sq_psn = src->sq_psn;
+ dst->dest_qp_num = src->dest_qp_num;
+ dst->qp_access_flags = src->qp_access_flags;
+
+ dst->cap.max_send_wr = src->max_send_wr;
+ dst->cap.max_recv_wr = src->max_recv_wr;
+ dst->cap.max_send_sge = src->max_send_sge;
+ dst->cap.max_recv_sge = src->max_recv_sge;
+ dst->cap.max_inline_data = src->max_inline_data;
+
+ rdma_copy_ah_attr_from_kern(&dst->ah_attr, &src->ah_attr);
+ rdma_copy_ah_attr_from_kern(&dst->alt_ah_attr, &src->alt_ah_attr);
+
+ dst->pkey_index = src->pkey_index;
+ dst->alt_pkey_index = src->alt_pkey_index;
+ dst->en_sqd_async_notify = src->en_sqd_async_notify;
+ dst->sq_draining = src->sq_draining;
+ dst->max_rd_atomic = src->max_rd_atomic;
+ dst->max_dest_rd_atomic = src->max_dest_rd_atomic;
+ dst->min_rnr_timer = src->min_rnr_timer;
+ dst->port_num = src->port_num;
+ dst->timeout = src->timeout;
+ dst->retry_cnt = src->retry_cnt;
+ dst->rnr_retry = src->rnr_retry;
+ dst->alt_port_num = src->alt_port_num;
+ dst->alt_timeout = src->alt_timeout;
+}
+
+void rdma_copy_path_rec_from_kern(struct rdma_sa_path_rec *dst,
+ struct rdma_kern_path_rec *src)
+{
+ memcpy(dst->dgid.raw, src->dgid, sizeof dst->dgid);
+ memcpy(dst->sgid.raw, src->sgid, sizeof dst->sgid);
+
+ dst->dlid = src->dlid;
+ dst->slid = src->slid;
+ dst->raw_traffic = src->raw_traffic;
+ dst->flow_label = src->flow_label;
+ dst->hop_limit = src->hop_limit;
+ dst->traffic_class = src->traffic_class;
+ dst->reversible = src->reversible;
+ dst->numb_path = src->numb_path;
+ dst->pkey = src->pkey;
+ dst->sl = src->sl;
+ dst->mtu_selector = src->mtu_selector;
+ dst->mtu = src->mtu;
+ dst->rate_selector = src->rate_selector;
+ dst->rate = src->rate;
+ dst->packet_life_time = src->packet_life_time;
+ dst->preference = src->preference;
+ dst->packet_life_time_selector = src->packet_life_time_selector;
+}
+
+void rdma_copy_path_rec_to_kern(struct rdma_kern_path_rec *dst,
+ struct rdma_sa_path_rec *src)
+{
+ memcpy(dst->dgid, src->dgid.raw, sizeof src->dgid);
+ memcpy(dst->sgid, src->sgid.raw, sizeof src->sgid);
+
+ dst->dlid = src->dlid;
+ dst->slid = src->slid;
+ dst->raw_traffic = src->raw_traffic;
+ dst->flow_label = src->flow_label;
+ dst->hop_limit = src->hop_limit;
+ dst->traffic_class = src->traffic_class;
+ dst->reversible = src->reversible;
+ dst->numb_path = src->numb_path;
+ dst->pkey = src->pkey;
+ dst->sl = src->sl;
+ dst->mtu_selector = src->mtu_selector;
+ dst->mtu = src->mtu;
+ dst->rate_selector = src->rate_selector;
+ dst->rate = src->rate;
+ dst->packet_life_time = src->packet_life_time;
+ dst->preference = src->preference;
+ dst->packet_life_time_selector = src->packet_life_time_selector;
+}
diff -ruNp ORG/librdmaverbs/src/memory.c NEW/librdmaverbs/src/memory.c
--- ORG/librdmaverbs/src/memory.c 1969-12-31 16:00:00.000000000 -0800
+++ NEW/librdmaverbs/src/memory.c 2006-07-10 18:07:47.000000000 -0700
@@ -0,0 +1,258 @@
+/*
+ * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: memory.c 6987 2006-05-08 15:18:51Z tom $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <sys/mman.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#include "rdmaverbs.h"
+
+/*
+ * We keep a linked list of page ranges that have been locked along with a
+ * reference count to manage overlapping registrations, etc.
+ *
+ * Eventually we should turn this into an RB-tree or something similar
+ * to avoid the O(n) cost of registering/unregistering memory.
+ */
+
+struct rdma_mem_node {
+ struct rdma_mem_node *prev, *next;
+ uintptr_t start, end;
+ int refcnt;
+};
+
+static struct {
+ struct rdma_mem_node *first;
+ pthread_mutex_t mutex;
+ uintptr_t page_size;
+} mem_map;
+
+int rdma_init_mem_map(void)
+{
+ struct rdma_mem_node *node = NULL;
+
+ node = malloc(sizeof *node);
+ if (!node)
+ goto fail;
+
+ node->prev = node->next = NULL;
+ node->start = 0;
+ node->end = UINTPTR_MAX;
+ node->refcnt = 0;
+
+ mem_map.first = node;
+
+ mem_map.page_size = sysconf(_SC_PAGESIZE);
+ if (mem_map.page_size < 0)
+ goto fail;
+
+ if (pthread_mutex_init(&mem_map.mutex, NULL))
+ goto fail;
+
+ return 0;
+
+fail:
+ if (node)
+ free(node);
+
+ return -1;
+}
+
+static struct rdma_mem_node *__mm_find_first(uintptr_t start, uintptr_t end)
+{
+ struct rdma_mem_node *node = mem_map.first;
+
+ while (node) {
+ if ((node->start <= start && node->end >= start) ||
+ (node->start <= end && node->end >= end))
+ break;
+ node = node->next;
+ }
+
+ return node;
+}
+
+static struct rdma_mem_node *__mm_prev(struct rdma_mem_node *node)
+{
+ return node->prev;
+}
+
+static struct rdma_mem_node *__mm_next(struct rdma_mem_node *node)
+{
+ return node->next;
+}
+
+static void __mm_add(struct rdma_mem_node *node,
+ struct rdma_mem_node *new)
+{
+ new->prev = node;
+ new->next = node->next;
+ node->next = new;
+ if (new->next)
+ new->next->prev = new;
+}
+
+static void __mm_remove(struct rdma_mem_node *node)
+{
+ /* Never have to remove the first node, so we can use prev */
+ node->prev->next = node->next;
+ if (node->next)
+ node->next->prev = node->prev;
+}
+
+int rdma_lock_range(void *base, size_t size)
+{
+ uintptr_t start, end;
+ struct rdma_mem_node *node, *tmp;
+ int ret = 0;
+
+ if (!size)
+ return 0;
+
+ start = (uintptr_t) base & ~(mem_map.page_size - 1);
+ end = ((uintptr_t) (base + size + mem_map.page_size - 1) &
+ ~(mem_map.page_size - 1)) - 1;
+
+ pthread_mutex_lock(&mem_map.mutex);
+
+ node = __mm_find_first(start, end);
+
+ if (node->start < start) {
+ tmp = malloc(sizeof *tmp);
+ if (!tmp) {
+ ret = -1;
+ goto out;
+ }
+
+ tmp->start = start;
+ tmp->end = node->end;
+ tmp->refcnt = node->refcnt;
+ node->end = start - 1;
+
+ __mm_add(node, tmp);
+ node = tmp;
+ }
+
+ while (node->start <= end) {
+ if (node->end > end) {
+ tmp = malloc(sizeof *tmp);
+ if (!tmp) {
+ ret = -1;
+ goto out;
+ }
+
+ tmp->start = end + 1;
+ tmp->end = node->end;
+ tmp->refcnt = node->refcnt;
+ node->end = end;
+
+ __mm_add(node, tmp);
+ }
+
+
+ if (node->refcnt++ == 0) {
+ ret = mlock((void *) node->start,
+ node->end - node->start + 1);
+ if (ret)
+ goto out;
+ }
+
+ node = __mm_next(node);
+ }
+
+out:
+ pthread_mutex_unlock(&mem_map.mutex);
+
+ return ret;
+}
+
+int rdma_unlock_range(void *base, size_t size)
+{
+ uintptr_t start, end;
+ struct rdma_mem_node *node, *tmp;
+ int ret = 0;
+
+ if (!size)
+ return 0;
+
+ start = (uintptr_t) base & ~(mem_map.page_size - 1);
+ end = ((uintptr_t) (base + size + mem_map.page_size - 1) &
+ ~(mem_map.page_size - 1)) - 1;
+
+ pthread_mutex_lock(&mem_map.mutex);
+
+ node = __mm_find_first(start, end);
+
+ if (node->start != start) {
+ ret = -1;
+ goto out;
+ }
+
+ while (node && node->end <= end) {
+ if (--node->refcnt == 0) {
+ ret = munlock((void *) node->start,
+ node->end - node->start + 1);
+ }
+
+ if (__mm_prev(node) && node->refcnt == __mm_prev(node)->refcnt) {
+ __mm_prev(node)->end = node->end;
+ tmp = __mm_prev(node);
+ __mm_remove(node);
+ node = tmp;
+ }
+
+ node = __mm_next(node);
+ }
+
+ if (node && node->refcnt == __mm_prev(node)->refcnt) {
+ __mm_prev(node)->end = node->end;
+ tmp = __mm_prev(node);
+ __mm_remove(node);
+ }
+
+ if (node->end != end) {
+ ret = -1;
+ goto out;
+ }
+
+out:
+ pthread_mutex_unlock(&mem_map.mutex);
+
+ return ret;
+}
diff -ruNp ORG/librdmaverbs/src/rdmaverbs.h NEW/librdmaverbs/src/rdmaverbs.h
--- ORG/librdmaverbs/src/rdmaverbs.h 1969-12-31 16:00:00.000000000 -0800
+++ NEW/librdmaverbs/src/rdmaverbs.h 2006-07-10 18:07:47.000000000 -0700
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef RDMA_VERBS_H
+#define RDMA_VERBS_H
+
+#include <pthread.h>
+
+#include <rdma/driver.h>
+
+#define HIDDEN __attribute__((visibility ("hidden")))
+
+#define INIT __attribute__((constructor))
+#define FINI __attribute__((destructor))
+
+#define PFX "librdmaverbs: "
+
+struct rdma_driver {
+ rdma_driver_init_func init_func;
+ struct rdma_driver *next;
+};
+
+struct rdma_abi_compat_v2 {
+ struct rdma_comp_channel channel;
+ pthread_mutex_t in_use;
+};
+
+extern HIDDEN int abi_ver;
+
+extern HIDDEN int rdmaverbs_init(struct rdma_device ***list);
+
+extern HIDDEN int rdma_init_mem_map(void);
+extern HIDDEN int rdma_lock_range(void *base, size_t size);
+extern HIDDEN int rdma_unlock_range(void *base, size_t size);
+
+#define RDMA_INIT_CMD(cmd, size, opcode) \
+ do { \
+ if (abi_ver > 2) \
+ (cmd)->command = RDMA_USER_VERBS_CMD_##opcode; \
+ else \
+ (cmd)->command = RDMA_USER_VERBS_CMD_##opcode##_V2; \
+ (cmd)->in_words = (size) / 4; \
+ (cmd)->out_words = 0; \
+ } while (0)
+
+#define RDMA_INIT_CMD_RESP(cmd, size, opcode, out, outsize) \
+ do { \
+ if (abi_ver > 2) \
+ (cmd)->command = RDMA_USER_VERBS_CMD_##opcode; \
+ else \
+ (cmd)->command = RDMA_USER_VERBS_CMD_##opcode##_V2; \
+ (cmd)->in_words = (size) / 4; \
+ (cmd)->out_words = (outsize) / 4; \
+ (cmd)->response = (uintptr_t) (out); \
+ } while (0)
+
+#endif /* RDMA_VERBS_H */
diff -ruNp ORG/librdmaverbs/src/sysfs.c NEW/librdmaverbs/src/sysfs.c
--- ORG/librdmaverbs/src/sysfs.c 1969-12-31 16:00:00.000000000 -0800
+++ NEW/librdmaverbs/src/sysfs.c 2006-07-10 18:07:47.000000000 -0700
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2006 Cisco Systems, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include "rdmaverbs.h"
+
+static char *sysfs_path;
+
+const char *rdma_get_sysfs_path(void)
+{
+ char *env = NULL;
+
+ if (sysfs_path)
+ return sysfs_path;
+
+ /*
+ * Only follow use path passed in through the calling user's
+ * environment if we're not running SUID.
+ */
+ if (getuid() == geteuid())
+ env = getenv("SYSFS_PATH");
+
+ if (env) {
+ int len;
+
+ sysfs_path = strndup(env, RDMA_SYSFS_PATH_MAX);
+ len = strlen(sysfs_path);
+ while (len > 0 && sysfs_path[len - 1] == '/') {
+ --len;
+ sysfs_path[len] = '\0';
+ }
+ } else
+ sysfs_path = "/sys";
+
+ return sysfs_path;
+}
+
+int rdma_read_sysfs_file(const char *dir, const char *file,
+ char *buf, size_t size)
+{
+ char *path;
+ int fd;
+ int len;
+
+ asprintf(&path, "%s/%s", dir, file);
+
+ fd = open(path, O_RDONLY);
+ if (fd < 0) {
+ free(path);
+ return -1;
+ }
+
+ len = read(fd, buf, size);
+
+ close(fd);
+ free(path);
+
+ if (len > 0 && buf[len - 1] == '\n')
+ buf[--len] = '\0';
+
+ return len;
+}
diff -ruNp ORG/librdmaverbs/src/verbs.c NEW/librdmaverbs/src/verbs.c
--- ORG/librdmaverbs/src/verbs.c 1969-12-31 16:00:00.000000000 -0800
+++ NEW/librdmaverbs/src/verbs.c 2006-07-10 18:07:47.000000000 -0700
@@ -0,0 +1,408 @@
+/*
+ * Copyright (c) 2005 Topspin Communications. All rights reserved.
+ * Copyright (c) 2006 Cisco Systems, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: verbs.c 7631 2006-06-02 19:53:25Z swise $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdio.h>
+#include <netinet/in.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include "rdmaverbs.h"
+
+int rdma_rate_to_mult(enum rdma_rate rate)
+{
+ switch (rate) {
+ case RDMA_RATE_2_5_GBPS: return 1;
+ case RDMA_RATE_5_GBPS: return 2;
+ case RDMA_RATE_10_GBPS: return 4;
+ case RDMA_RATE_20_GBPS: return 8;
+ case RDMA_RATE_30_GBPS: return 12;
+ case RDMA_RATE_40_GBPS: return 16;
+ case RDMA_RATE_60_GBPS: return 24;
+ case RDMA_RATE_80_GBPS: return 32;
+ case RDMA_RATE_120_GBPS: return 48;
+ default: return -1;
+ }
+}
+
+enum rdma_rate mult_to_rdma_rate(int mult)
+{
+ switch (mult) {
+ case 1: return RDMA_RATE_2_5_GBPS;
+ case 2: return RDMA_RATE_5_GBPS;
+ case 4: return RDMA_RATE_10_GBPS;
+ case 8: return RDMA_RATE_20_GBPS;
+ case 12: return RDMA_RATE_30_GBPS;
+ case 16: return RDMA_RATE_40_GBPS;
+ case 24: return RDMA_RATE_60_GBPS;
+ case 32: return RDMA_RATE_80_GBPS;
+ case 48: return RDMA_RATE_120_GBPS;
+ default: return RDMA_RATE_MAX;
+ }
+}
+
+int rdma_query_device(struct rdma_context *context,
+ struct rdma_device_attr *device_attr)
+{
+ return context->ops.query_device(context, device_attr);
+}
+
+int rdma_query_port(struct rdma_context *context, uint8_t port_num,
+ struct rdma_port_attr *port_attr)
+{
+ return context->ops.query_port(context, port_num, port_attr);
+}
+
+int rdma_query_gid(struct rdma_context *context, uint8_t port_num,
+ int index, union rdma_gid *gid)
+{
+ char name[24];
+ char attr[41];
+ uint16_t val;
+ int i;
+
+ snprintf(name, sizeof name, "ports/%d/gids/%d", port_num, index);
+
+ if (rdma_read_sysfs_file(context->device->ibdev_path, name,
+ attr, sizeof attr) < 0)
+ return -1;
+
+ for (i = 0; i < 8; ++i) {
+ if (sscanf(attr + i * 5, "%hx", &val) != 1)
+ return -1;
+ gid->raw[i * 2 ] = val >> 8;
+ gid->raw[i * 2 + 1] = val & 0xff;
+ }
+
+ return 0;
+}
+
+int rdma_query_pkey(struct rdma_context *context, uint8_t port_num,
+ int index, uint16_t *pkey)
+{
+ char name[24];
+ char attr[8];
+ uint16_t val;
+
+ snprintf(name, sizeof name, "ports/%d/pkeys/%d", port_num, index);
+
+ if (rdma_read_sysfs_file(context->device->ibdev_path, name,
+ attr, sizeof attr) < 0)
+ return -1;
+
+ if (sscanf(attr, "%hx", &val) != 1)
+ return -1;
+
+ *pkey = htons(val);
+ return 0;
+}
+
+struct rdma_pd *rdma_alloc_pd(struct rdma_context *context)
+{
+ struct rdma_pd *pd;
+
+ pd = context->ops.alloc_pd(context);
+ if (pd)
+ pd->context = context;
+
+ return pd;
+}
+
+int rdma_dealloc_pd(struct rdma_pd *pd)
+{
+ return pd->context->ops.dealloc_pd(pd);
+}
+
+struct rdma_mr *rdma_reg_mr(struct rdma_pd *pd, void *addr,
+ size_t length, enum rdma_access_flags access)
+{
+ struct rdma_mr *mr;
+
+ mr = pd->context->ops.reg_mr(pd, addr, length, access);
+ if (mr) {
+ mr->context = pd->context;
+ mr->pd = pd;
+ }
+
+ return mr;
+}
+
+int rdma_dereg_mr(struct rdma_mr *mr)
+{
+ return mr->context->ops.dereg_mr(mr);
+}
+
+static struct rdma_comp_channel *rdma_create_comp_channel_v2(struct rdma_context *context)
+{
+ struct rdma_abi_compat_v2 *t = context->abi_compat;
+ static int warned;
+
+ if (!pthread_mutex_trylock(&t->in_use))
+ return &t->channel;
+
+ if (!warned) {
+ fprintf(stderr, PFX "Warning: kernel's ABI version %d limits capacity.\n"
+ " Only one completion channel can be created per context.\n",
+ abi_ver);
+ ++warned;
+ }
+
+ return NULL;
+}
+
+struct rdma_comp_channel *rdma_create_comp_channel(struct rdma_context *context)
+{
+ struct rdma_comp_channel *channel;
+ struct rdma_create_comp_channel cmd;
+ struct rdma_create_comp_channel_resp resp;
+
+ if (abi_ver <= 2)
+ return rdma_create_comp_channel_v2(context);
+
+ channel = malloc(sizeof *channel);
+ if (!channel)
+ return NULL;
+
+ RDMA_INIT_CMD_RESP(&cmd, sizeof cmd, CREATE_COMP_CHANNEL, &resp, sizeof resp);
+ if (write(context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd) {
+ free(channel);
+ return NULL;
+ }
+
+ channel->fd = resp.fd;
+
+ return channel;
+}
+
+static int rdma_destroy_comp_channel_v2(struct rdma_comp_channel *channel)
+{
+ struct rdma_abi_compat_v2 *t = (struct rdma_abi_compat_v2 *) channel;
+ pthread_mutex_unlock(&t->in_use);
+ return 0;
+}
+
+int rdma_destroy_comp_channel(struct rdma_comp_channel *channel)
+{
+ if (abi_ver <= 2)
+ return rdma_destroy_comp_channel_v2(channel);
+
+ close(channel->fd);
+ free(channel);
+
+ return 0;
+}
+
+struct rdma_cq *rdma_create_cq(struct rdma_context *context, int cqe, void *cq_context,
+ struct rdma_comp_channel *channel, int comp_vector)
+{
+ struct rdma_cq *cq = context->ops.create_cq(context, cqe, channel,
+ comp_vector);
+
+ if (cq) {
+ cq->context = context;
+ cq->cq_context = cq_context;
+ cq->comp_events_completed = 0;
+ cq->async_events_completed = 0;
+ pthread_mutex_init(&cq->mutex, NULL);
+ pthread_cond_init(&cq->cond, NULL);
+ }
+
+ return cq;
+}
+
+int rdma_resize_cq(struct rdma_cq *cq, int cqe)
+{
+ if (!cq->context->ops.resize_cq)
+ return ENOSYS;
+
+ return cq->context->ops.resize_cq(cq, cqe);
+}
+
+int rdma_destroy_cq(struct rdma_cq *cq)
+{
+ return cq->context->ops.destroy_cq(cq);
+}
+
+
+int rdma_get_cq_event(struct rdma_comp_channel *channel,
+ struct rdma_cq **cq, void **cq_context)
+{
+ struct rdma_comp_event ev;
+
+ if (read(channel->fd, &ev, sizeof ev) != sizeof ev)
+ return -1;
+
+ *cq = (struct rdma_cq *) (uintptr_t) ev.cq_handle;
+ *cq_context = (*cq)->cq_context;
+
+ if ((*cq)->context->ops.cq_event)
+ (*cq)->context->ops.cq_event(*cq);
+
+ return 0;
+}
+
+void rdma_ack_cq_events(struct rdma_cq *cq, unsigned int nevents)
+{
+ pthread_mutex_lock(&cq->mutex);
+ cq->comp_events_completed += nevents;
+ pthread_cond_signal(&cq->cond);
+ pthread_mutex_unlock(&cq->mutex);
+}
+
+struct rdma_srq *rdma_create_srq(struct rdma_pd *pd,
+ struct rdma_srq_init_attr *srq_init_attr)
+{
+ struct rdma_srq *srq;
+
+ if (!pd->context->ops.create_srq)
+ return NULL;
+
+ srq = pd->context->ops.create_srq(pd, srq_init_attr);
+ if (srq) {
+ srq->context = pd->context;
+ srq->srq_context = srq_init_attr->srq_context;
+ srq->pd = pd;
+ srq->events_completed = 0;
+ pthread_mutex_init(&srq->mutex, NULL);
+ pthread_cond_init(&srq->cond, NULL);
+ }
+
+ return srq;
+}
+
+int rdma_modify_srq(struct rdma_srq *srq,
+ struct rdma_srq_attr *srq_attr,
+ enum rdma_srq_attr_mask srq_attr_mask)
+{
+ return srq->context->ops.modify_srq(srq, srq_attr, srq_attr_mask);
+}
+
+int rdma_query_srq(struct rdma_srq *srq, struct rdma_srq_attr *srq_attr)
+{
+ return srq->context->ops.query_srq(srq, srq_attr);
+}
+
+int rdma_destroy_srq(struct rdma_srq *srq)
+{
+ return srq->context->ops.destroy_srq(srq);
+}
+
+struct rdma_qp *rdmav_create_qp(struct rdma_pd *pd,
+ struct rdma_qp_init_attr *qp_init_attr)
+{
+ struct rdma_qp *qp = pd->context->ops.create_qp(pd, qp_init_attr);
+
+ if (qp) {
+ qp->context = pd->context;
+ qp->qp_context = qp_init_attr->qp_context;
+ qp->pd = pd;
+ qp->send_cq = qp_init_attr->send_cq;
+ qp->recv_cq = qp_init_attr->recv_cq;
+ qp->srq = qp_init_attr->srq;
+ qp->qp_type = qp_init_attr->qp_type;
+ qp->events_completed = 0;
+ pthread_mutex_init(&qp->mutex, NULL);
+ pthread_cond_init(&qp->cond, NULL);
+ }
+
+ return qp;
+}
+
+int rdma_query_qp(struct rdma_qp *qp, struct rdma_qp_attr *attr,
+ enum rdma_qp_attr_mask attr_mask,
+ struct rdma_qp_init_attr *init_attr)
+{
+ int ret;
+
+ ret = qp->context->ops.query_qp(qp, attr, attr_mask, init_attr);
+ if (ret)
+ return ret;
+
+ if (attr_mask & RDMA_QP_STATE)
+ qp->state = attr->qp_state;
+
+ return 0;
+}
+
+int rdma_modify_qp(struct rdma_qp *qp, struct rdma_qp_attr *attr,
+ enum rdma_qp_attr_mask attr_mask)
+{
+ int ret;
+
+ ret = qp->context->ops.modify_qp(qp, attr, attr_mask);
+ if (ret)
+ return ret;
+
+ if (attr_mask & RDMA_QP_STATE)
+ qp->state = attr->qp_state;
+
+ return 0;
+}
+
+int rdmav_destroy_qp(struct rdma_qp *qp)
+{
+ return qp->context->ops.destroy_qp(qp);
+}
+
+struct rdma_ah *rdma_create_ah(struct rdma_pd *pd, struct rdma_ah_attr *attr)
+{
+ struct rdma_ah *ah = pd->context->ops.create_ah(pd, attr);
+
+ if (ah) {
+ ah->context = pd->context;
+ ah->pd = pd;
+ }
+
+ return ah;
+}
+
+int rdma_destroy_ah(struct rdma_ah *ah)
+{
+ return ah->context->ops.destroy_ah(ah);
+}
+
+int rdma_attach_mcast(struct rdma_qp *qp, union rdma_gid *gid, uint16_t lid)
+{
+ return qp->context->ops.attach_mcast(qp, gid, lid);
+}
+
+int rdma_detach_mcast(struct rdma_qp *qp, union rdma_gid *gid, uint16_t lid)
+{
+ return qp->context->ops.detach_mcast(qp, gid, lid);
+}
More information about the general
mailing list