Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause 2 : : * Copyright (C) 2020 Intel Corporation. All rights reserved. 3 : : * Copyright (c) Mellanox Technologies LTD. All rights reserved. 4 : : */ 5 : : 6 : : #include <rdma/rdma_cma.h> 7 : : 8 : : #include "spdk/stdinc.h" 9 : : #include "spdk/string.h" 10 : : #include "spdk/likely.h" 11 : : 12 : : #include "spdk_internal/rdma.h" 13 : : #include "spdk/log.h" 14 : : 15 : : struct spdk_rdma_qp * 16 : 2991 : spdk_rdma_qp_create(struct rdma_cm_id *cm_id, struct spdk_rdma_qp_init_attr *qp_attr) 17 : : { 18 : : struct spdk_rdma_qp *spdk_rdma_qp; 19 : : int rc; 20 : 2991 : struct ibv_qp_init_attr attr = { 21 : 2991 : .qp_context = qp_attr->qp_context, 22 : 2991 : .send_cq = qp_attr->send_cq, 23 : 2991 : .recv_cq = qp_attr->recv_cq, 24 : 2991 : .srq = qp_attr->srq, 25 : : .cap = qp_attr->cap, 26 : : .qp_type = IBV_QPT_RC 27 : : }; 28 : : 29 : 2991 : spdk_rdma_qp = calloc(1, sizeof(*spdk_rdma_qp)); 30 [ - + ]: 2991 : if (!spdk_rdma_qp) { 31 : 0 : SPDK_ERRLOG("qp memory allocation failed\n"); 32 : 0 : return NULL; 33 : : } 34 : : 35 [ + + ]: 2991 : if (qp_attr->stats) { 36 : 2158 : spdk_rdma_qp->stats = qp_attr->stats; 37 : 2158 : spdk_rdma_qp->shared_stats = true; 38 : : } else { 39 : 833 : spdk_rdma_qp->stats = calloc(1, sizeof(*spdk_rdma_qp->stats)); 40 [ - + ]: 833 : if (!spdk_rdma_qp->stats) { 41 : 0 : SPDK_ERRLOG("qp statistics memory allocation failed\n"); 42 : 0 : free(spdk_rdma_qp); 43 : 0 : return NULL; 44 : : } 45 : : } 46 : : 47 : 2991 : rc = rdma_create_qp(cm_id, qp_attr->pd, &attr); 48 [ - + ]: 2991 : if (rc) { 49 : 0 : SPDK_ERRLOG("Failed to create qp, errno %s (%d)\n", spdk_strerror(errno), errno); 50 : 0 : free(spdk_rdma_qp); 51 : 0 : return NULL; 52 : : } 53 : : 54 : 2991 : qp_attr->cap = attr.cap; 55 : 2991 : spdk_rdma_qp->qp = cm_id->qp; 56 : 2991 : spdk_rdma_qp->cm_id = cm_id; 57 : : 58 : 2991 : return spdk_rdma_qp; 59 : : } 60 : : 61 : : int 62 : 2038 : spdk_rdma_qp_accept(struct spdk_rdma_qp *spdk_rdma_qp, struct rdma_conn_param *conn_param) 63 : : { 64 [ - + ]: 2038 : assert(spdk_rdma_qp != NULL); 65 [ - + ]: 2038 : assert(spdk_rdma_qp->cm_id != NULL); 66 : : 67 : 2038 : return rdma_accept(spdk_rdma_qp->cm_id, conn_param); 68 : : } 69 : : 70 : : int 71 : 0 : spdk_rdma_qp_complete_connect(struct spdk_rdma_qp *spdk_rdma_qp) 72 : : { 73 : : /* Nothing to be done for Verbs */ 74 : 0 : return 0; 75 : : } 76 : : 77 : : void 78 : 2991 : spdk_rdma_qp_destroy(struct spdk_rdma_qp *spdk_rdma_qp) 79 : : { 80 [ - + ]: 2991 : assert(spdk_rdma_qp != NULL); 81 : : 82 [ - + ]: 2991 : if (spdk_rdma_qp->send_wrs.first != NULL) { 83 : 0 : SPDK_WARNLOG("Destroying qpair with queued Work Requests\n"); 84 : : } 85 : : 86 [ + - ]: 2991 : if (spdk_rdma_qp->qp) { 87 : 2991 : rdma_destroy_qp(spdk_rdma_qp->cm_id); 88 : : } 89 : : 90 [ - + + + ]: 2991 : if (!spdk_rdma_qp->shared_stats) { 91 : 833 : free(spdk_rdma_qp->stats); 92 : : } 93 : : 94 : 2991 : free(spdk_rdma_qp); 95 : 2991 : } 96 : : 97 : : int 98 : 2991 : spdk_rdma_qp_disconnect(struct spdk_rdma_qp *spdk_rdma_qp) 99 : : { 100 : 2991 : int rc = 0; 101 : : 102 [ - + ]: 2991 : assert(spdk_rdma_qp != NULL); 103 : : 104 [ + - ]: 2991 : if (spdk_rdma_qp->cm_id) { 105 : 2991 : rc = rdma_disconnect(spdk_rdma_qp->cm_id); 106 [ - + ]: 2991 : if (rc) { 107 [ # # # # ]: 0 : if (errno == EINVAL && spdk_rdma_qp->qp->context->device->transport_type == IBV_TRANSPORT_IWARP) { 108 : : /* rdma_disconnect may return an error and set errno to EINVAL in case of iWARP. 109 : : * This behaviour is expected since iWARP handles disconnect event other than IB and 110 : : * qpair is already in error state when we call rdma_disconnect */ 111 : 0 : return 0; 112 : : } 113 : 0 : SPDK_ERRLOG("rdma_disconnect failed, errno %s (%d)\n", spdk_strerror(errno), errno); 114 : : } 115 : : } 116 : : 117 : 2991 : return rc; 118 : : } 119 : : 120 : : bool 121 : 14023892 : spdk_rdma_qp_queue_send_wrs(struct spdk_rdma_qp *spdk_rdma_qp, struct ibv_send_wr *first) 122 : : { 123 : : struct ibv_send_wr *last; 124 : : 125 [ - + ]: 14023892 : assert(spdk_rdma_qp); 126 [ - + ]: 14023892 : assert(first); 127 : : 128 : 14023892 : spdk_rdma_qp->stats->send.num_submitted_wrs++; 129 : 14023892 : last = first; 130 [ + + ]: 17727120 : while (last->next != NULL) { 131 : 3703228 : last = last->next; 132 : 3703228 : spdk_rdma_qp->stats->send.num_submitted_wrs++; 133 : : } 134 : : 135 [ + + ]: 14023892 : if (spdk_rdma_qp->send_wrs.first == NULL) { 136 : 3147187 : spdk_rdma_qp->send_wrs.first = first; 137 : 3147187 : spdk_rdma_qp->send_wrs.last = last; 138 : 3147187 : return true; 139 : : } else { 140 : 10876705 : spdk_rdma_qp->send_wrs.last->next = first; 141 : 10876705 : spdk_rdma_qp->send_wrs.last = last; 142 : 10876705 : return false; 143 : : } 144 : : } 145 : : 146 : : int 147 : 103904685 : spdk_rdma_qp_flush_send_wrs(struct spdk_rdma_qp *spdk_rdma_qp, struct ibv_send_wr **bad_wr) 148 : : { 149 : : int rc; 150 : : 151 [ - + ]: 103904685 : assert(spdk_rdma_qp); 152 [ - + ]: 103904685 : assert(bad_wr); 153 : : 154 [ + + ]: 103904685 : if (spdk_unlikely(!spdk_rdma_qp->send_wrs.first)) { 155 : 100757498 : return 0; 156 : : } 157 : : 158 : 3147187 : rc = ibv_post_send(spdk_rdma_qp->qp, spdk_rdma_qp->send_wrs.first, bad_wr); 159 : : 160 : 3147187 : spdk_rdma_qp->send_wrs.first = NULL; 161 : 3147187 : spdk_rdma_qp->stats->send.doorbell_updates++; 162 : : 163 : 3147187 : return rc; 164 : : }