1/* 2 * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved. 3 * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. 4 * 5 * This software is available to you under a choice of one of two 6 * licenses. You may choose to be licensed under the terms of the GNU 7 * General Public License (GPL) Version 2, available from the file 8 * COPYING in the main directory of this source tree, or the 9 * OpenIB.org BSD license below: 10 * 11 * Redistribution and use in source and binary forms, with or 12 * without modification, are permitted provided that the following 13 * conditions are met: 14 * 15 * - Redistributions of source code must retain the above 16 * copyright notice, this list of conditions and the following 17 * disclaimer. 18 * 19 * - Redistributions in binary form must reproduce the above 20 * copyright notice, this list of conditions and the following 21 * disclaimer in the documentation and/or other materials 22 * provided with the distribution. 23 * 24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31 * SOFTWARE. 32 * 33 */ 34 35#ifdef OSM_VENDOR_INTF_MTL 36 37/* - Mellanox Confidential and Proprietary - 38 * 39 * Copyright (C) Jul. 2001, Mellanox Technologies Ltd. ALL RIGHTS RESERVED. 40 * 41 * Except as specifically permitted herein, no portion of the information, 42 * including but not limited to object code and source code, may be reproduced, 43 * modified, distributed, republished or otherwise exploited in any form or by 44 * any means for any purpose without the prior written permission of Mellanox 45 * Technologies Ltd. Use of software subject to the terms and conditions 46 * detailed in the file "LICENSE.txt". 47 * 48 * End of legal section ...................................................... 49 * 50 * osmt_mtl_regular_qp.c - 51 * Provide Simple Interface for Sending and Receiving MADS through a regular QP 52 * 53 * Creation date: 54 * 55 * Version: $Id$ 56 * 57 * Authors: 58 * Eitan Zahavi 59 * 60 * Changes: 61 */ 62 63#include <stdio.h> 64#include <stdlib.h> 65#include <string.h> 66#include <unistd.h> 67#include <signal.h> 68 69#include <mtl_common.h> 70#include <vapi.h> 71#include <evapi.h> 72#include <vapi_common.h> 73#include <ib_defs.h> 74#include <osmt_mtl_regular_qp.h> 75#include <complib/cl_types.h> 76/* 77 * Initialize the QP etc. 78 * Given in res: port_num, max_outs_sq, max_outs_rq 79 */ 80VAPI_ret_t osmt_mtl_get_qp_resources(IN OUT osmt_mtl_mad_res_t * res) 81{ 82 VAPI_ret_t ret; 83 VAPI_hca_port_t hca_port_info; 84 VAPI_qp_init_attr_t qp_init_attr; 85 VAPI_qp_prop_t qp_prop; 86 VAPI_cqe_num_t act_num; 87 88 /* Get HCA LID */ 89 ret = 90 VAPI_query_hca_port_prop(res->hca_hndl, res->port_num, 91 &hca_port_info); 92 VAPI_CHECK_RET; 93 res->slid = hca_port_info.lid; 94 95 /* Get a PD */ 96 ret = VAPI_alloc_pd(res->hca_hndl, &(res->pd_hndl)); 97 VAPI_CHECK_RET; 98 99 /* Create CQ for RQ and SQ *//* TBD - Check we have enough act nums */ 100 ret = 101 VAPI_create_cq(res->hca_hndl, res->max_outs_sq + 1, 102 &(res->sq_cq_hndl), &act_num); 103 VAPI_CHECK_RET; 104 ret = 105 VAPI_create_cq(res->hca_hndl, res->max_outs_rq + 1, 106 &(res->rq_cq_hndl), &act_num); 107 VAPI_CHECK_RET; 108 109 /* register event handlers for polling(block mode) internal use */ 110 /* ret= EVAPI_set_comp_eventh(res->hca_hndl,res->rq_cq_hndl, */ 111 /* EVAPI_POLL_CQ_UNBLOCK_HANDLER,NULL,&(res->rq_cq_eventh)); */ 112 /* VAPI_CHECK_RET; */ 113 /* ret= EVAPI_set_comp_eventh(res->hca_hndl,res->sq_cq_hndl, */ 114 /* EVAPI_POLL_CQ_UNBLOCK_HANDLER,NULL,&(res->sq_cq_eventh)); */ 115 /* VAPI_CHECK_RET; */ 116 117 /* Create QP */ 118 qp_init_attr.cap.max_oust_wr_sq = res->max_outs_sq + 1; 119 qp_init_attr.cap.max_oust_wr_rq = res->max_outs_rq + 1; 120 qp_init_attr.cap.max_sg_size_sq = 4; 121 qp_init_attr.cap.max_sg_size_rq = 4; 122 123 qp_init_attr.pd_hndl = res->pd_hndl; 124 qp_init_attr.rdd_hndl = 0; 125 qp_init_attr.rq_cq_hndl = res->rq_cq_hndl; 126 qp_init_attr.rq_sig_type = VAPI_SIGNAL_ALL_WR; /* That's default for IB */ 127 qp_init_attr.sq_cq_hndl = res->sq_cq_hndl; 128 qp_init_attr.sq_sig_type = VAPI_SIGNAL_REQ_WR; 129 qp_init_attr.ts_type = VAPI_TS_UD; 130 131 ret = 132 VAPI_create_qp(res->hca_hndl, &qp_init_attr, &(res->qp_hndl), 133 &qp_prop); 134 VAPI_CHECK_RET; 135 res->qp_id.qp_num = qp_prop.qp_num; 136 137 return (VAPI_OK); 138} 139 140VAPI_ret_t osmt_mtl_qp_init(osmt_mtl_mad_res_t * res) 141{ 142 VAPI_ret_t ret; 143 144 VAPI_qp_attr_t qp_attr; 145 VAPI_qp_attr_mask_t qp_attr_mask; 146 VAPI_qp_cap_t qp_cap; 147 148 /* 149 * Change QP to INIT 150 * 151 */ 152 QP_ATTR_MASK_CLR_ALL(qp_attr_mask); 153 qp_attr.qp_state = VAPI_INIT; 154 QP_ATTR_MASK_SET(qp_attr_mask, QP_ATTR_QP_STATE); 155 qp_attr.pkey_ix = 0; 156 QP_ATTR_MASK_SET(qp_attr_mask, QP_ATTR_PKEY_IX); 157 qp_attr.port = res->port_num; 158 QP_ATTR_MASK_SET(qp_attr_mask, QP_ATTR_PORT); 159 qp_attr.qkey = res->qkey; 160 QP_ATTR_MASK_SET(qp_attr_mask, QP_ATTR_QKEY); 161 162 /* If I do not set this mask, I get an error from HH. QPM should catch it */ 163 ret = 164 VAPI_modify_qp(res->hca_hndl, res->qp_hndl, &qp_attr, &qp_attr_mask, 165 &qp_cap); 166 VAPI_CHECK_RET; 167 168 return (ret); 169 170} 171 172VAPI_ret_t osmt_mtl_qp_2_rtr_rts(osmt_mtl_mad_res_t * res) 173{ 174 VAPI_ret_t ret; 175 176 VAPI_qp_attr_t qp_attr; 177 VAPI_qp_attr_mask_t qp_attr_mask; 178 VAPI_qp_cap_t qp_cap; 179 180 /* 181 * Change QP to RTR 182 * 183 */ 184 QP_ATTR_MASK_CLR_ALL(qp_attr_mask); 185 qp_attr.qp_state = VAPI_RTR; 186 QP_ATTR_MASK_SET(qp_attr_mask, QP_ATTR_QP_STATE); 187 /* qp_attr.rq_psn = 0; */ 188 /* QP_ATTR_MASK_SET(qp_attr_mask,QP_ATTR_RQ_PSN); */ 189 190 ret = 191 VAPI_modify_qp(res->hca_hndl, res->qp_hndl, &qp_attr, &qp_attr_mask, 192 &qp_cap); 193 VAPI_CHECK_RET; 194 195 /* 196 * Change QP to RTS 197 * 198 */ 199 QP_ATTR_MASK_CLR_ALL(qp_attr_mask); 200 qp_attr.qp_state = VAPI_RTS; 201 QP_ATTR_MASK_SET(qp_attr_mask, QP_ATTR_QP_STATE); 202 qp_attr.sq_psn = 0; 203 QP_ATTR_MASK_SET(qp_attr_mask, QP_ATTR_SQ_PSN); 204 205 ret = 206 VAPI_modify_qp(res->hca_hndl, res->qp_hndl, &qp_attr, &qp_attr_mask, 207 &qp_cap); 208 VAPI_CHECK_RET; 209 210 return (ret); 211} 212 213VAPI_ret_t osmt_mtl_mad_create_mr(osmt_mtl_mad_res_t * res) 214{ 215 216 VAPI_ret_t ret; 217 218 VAPI_mrw_t mr_in, mr_out; 219 220 res->buf_size = 221 (MAD_SIZE + GRH_LEN) * (res->max_outs_sq + res->max_outs_rq + 1); 222 223 /* Register single memory address region for all buffers */ 224 res->buf_ptr = VMALLOC(res->buf_size); 225 226 if (res->buf_ptr == ((VAPI_virt_addr_t) NULL)) { 227 ret = VAPI_EAGAIN; 228 VAPI_CHECK_RET; 229 } 230 231 /* Enable local and remote access to memory region */ 232 mr_in.acl = VAPI_EN_LOCAL_WRITE | VAPI_EN_REMOTE_WRITE; 233 mr_in.l_key = 0; 234 mr_in.pd_hndl = res->pd_hndl; 235 mr_in.r_key = 0; 236 mr_in.size = res->buf_size; 237 ASSERT_VOIDP2UINTN(res->buf_ptr); 238 mr_in.start = (VAPI_virt_addr_t) (uintn_t) (res->buf_ptr); 239 mr_in.type = VAPI_MR; 240 241 ret = VAPI_register_mr(res->hca_hndl, &mr_in, &(res->mr_hndl), &mr_out); 242 VAPI_CHECK_RET; 243 244 res->l_key = mr_out.l_key; 245 246 return (ret); 247} 248 249VAPI_ret_t osmt_mtl_init_opened_hca(osmt_mtl_mad_res_t * res) 250{ 251 VAPI_ret_t ret; 252 253 res->pd_hndl = VAPI_INVAL_HNDL; 254 res->rq_cq_hndl = VAPI_INVAL_HNDL; 255 res->sq_cq_hndl = VAPI_INVAL_HNDL; 256 res->sq_cq_eventh = VAPI_INVAL_HNDL; 257 res->rq_cq_eventh = VAPI_INVAL_HNDL; 258 res->qp_hndl = VAPI_INVAL_HNDL; 259 res->mr_hndl = VAPI_INVAL_HNDL; 260 261 /* 262 * Create QP 263 * 264 */ 265 ret = osmt_mtl_get_qp_resources(res); 266 if (ret != VAPI_OK) { 267 return ret; 268 } 269 270 /* 271 * Move to init 272 * 273 */ 274 ret = osmt_mtl_qp_init(res); 275 if (ret != VAPI_OK) { 276 return ret; 277 } 278 279 /* 280 * Initialize memory regions 281 * 282 */ 283 ret = osmt_mtl_mad_create_mr(res); 284 if (ret != VAPI_OK) { 285 return ret; 286 } 287 288 /* only now move to RTR and RTS */ 289 ret = osmt_mtl_qp_2_rtr_rts(res); 290 if (ret != VAPI_OK) { 291 return ret; 292 } 293 294 return VAPI_OK; 295} 296 297VAPI_ret_t osmt_mtl_mad_cleanup(osmt_mtl_mad_res_t * res) 298{ 299 if (res->qp_hndl != VAPI_INVAL_HNDL) { 300 VAPI_destroy_qp(res->hca_hndl, res->qp_hndl); 301 } 302 if (res->sq_cq_eventh != VAPI_INVAL_HNDL) { 303 EVAPI_clear_comp_eventh(res->hca_hndl, res->sq_cq_eventh); 304 } 305 if (res->rq_cq_eventh != VAPI_INVAL_HNDL) { 306 EVAPI_clear_comp_eventh(res->hca_hndl, res->rq_cq_eventh); 307 } 308 if (res->rq_cq_hndl != VAPI_INVAL_HNDL) { 309 VAPI_destroy_cq(res->hca_hndl, res->rq_cq_hndl); 310 } 311 if (res->sq_cq_hndl != VAPI_INVAL_HNDL) { 312 VAPI_destroy_cq(res->hca_hndl, res->sq_cq_hndl); 313 } 314 if (res->mr_hndl != VAPI_INVAL_HNDL) { 315 VAPI_deregister_mr(res->hca_hndl, res->mr_hndl); 316 } 317 if (res->pd_hndl != VAPI_INVAL_HNDL) { 318 VAPI_dealloc_pd(res->hca_hndl, res->pd_hndl); 319 } 320#if 0 321 /* open/close of HCA should be done system wide - not per application */ 322 if (res->hca_hndl != VAPI_INVAL_HNDL) { 323 VAPI_close_hca(res->hca_hndl); /* TBD: HCA_open/close should be done on a system wide basis */ 324 } 325#endif 326 return VAPI_OK; 327} 328 329VAPI_ret_t osmt_mtl_create_av(osmt_mtl_mad_res_t * res, int16_t dlid, 330 VAPI_ud_av_hndl_t * avh_p) 331{ 332 VAPI_ud_av_t av; 333 VAPI_ret_t ret; 334 335 av.dlid = dlid; 336 av.port = res->port_num; 337 av.sl = 0; /* dest->sl; */ 338 av.src_path_bits = 0; /* dest->ee_dlid.dst_path_bits; */ 339 av.static_rate = 0; 340 /* GRH ? */ 341 av.grh_flag = 0; 342 343 ret = VAPI_create_addr_hndl(res->hca_hndl, res->pd_hndl, &av, avh_p); 344 if (ret != VAPI_OK) { 345 MTL_ERROR1("%s: failed VAPI_create_addr_hndl (%s)\n", __func__, 346 VAPI_strerror_sym(ret)); 347 return ret; 348 } 349 return VAPI_OK; 350} 351 352VAPI_ret_t osmt_mtl_mad_send(osmt_mtl_mad_res_t * res, VAPI_wr_id_t id, 353 void *mad, VAPI_qp_num_t dest_qp, IB_sl_t sl, 354 u_int32_t dest_qkey, VAPI_ud_av_hndl_t avh) 355{ 356 VAPI_sr_desc_t sr; 357 VAPI_sg_lst_entry_t sg_entry; 358 VAPI_ret_t ret; 359 360 /* building SEND request */ 361 sr.opcode = VAPI_SEND; 362 sr.remote_ah = avh; 363 sr.remote_qp = dest_qp; 364 sr.remote_qkey = dest_qkey; 365 366 sr.id = id; 367 sr.set_se = FALSE; 368 sr.fence = FALSE; 369 sr.comp_type = VAPI_SIGNALED; 370 sr.sg_lst_len = 1; 371 sr.sg_lst_p = &sg_entry; 372 ASSERT_VOIDP2UINTN(mad); 373 sg_entry.addr = (VAPI_virt_addr_t) (uintn_t) (mad); 374 sg_entry.len = MAD_SIZE; 375 sg_entry.lkey = res->l_key; 376 377 ret = VAPI_post_sr(res->hca_hndl, res->qp_hndl, &sr); 378 if (ret != VAPI_OK) { 379 MTL_ERROR1(__FUNCTION__ ": failed VAPI_post_sr (%s)\n", 380 VAPI_strerror_sym(ret)); 381 return ret; 382 } 383 384 return VAPI_OK; 385} 386 387int osmt_mtl_mad_post_recv_bufs(osmt_mtl_mad_res_t * res, void *buf_array, 388 u_int32_t num_o_bufs, u_int32_t size, 389 VAPI_wr_id_t start_id) 390{ 391 uint32_t i; 392 void *cur_buf; 393 VAPI_rr_desc_t rr; 394 VAPI_sg_lst_entry_t sg_entry; 395 VAPI_ret_t ret; 396 397 rr.opcode = VAPI_RECEIVE; 398 rr.comp_type = VAPI_SIGNALED; /* All with CQE (IB compliant) */ 399 rr.sg_lst_len = 1; /* single buffers */ 400 rr.sg_lst_p = &sg_entry; 401 sg_entry.lkey = res->l_key; 402 cur_buf = buf_array; 403 for (i = 0; i < num_o_bufs; i++) { 404 rr.id = start_id + i; /* WQE id used is the index to buffers ptr array */ 405 ASSERT_VOIDP2UINTN(cur_buf); 406 sg_entry.addr = (VAPI_virt_addr_t) (uintn_t) cur_buf; 407 sg_entry.len = size; 408 memset(cur_buf, 0x00, size); /* fill with 0 */ 409 ret = VAPI_post_rr(res->hca_hndl, res->qp_hndl, &rr); 410 if (ret != VAPI_OK) { 411 MTL_ERROR1(__FUNCTION__ 412 ": failed posting RQ WQE (%s)\n", 413 VAPI_strerror_sym(ret)); 414 return i; 415 } 416 MTL_DEBUG4(__FUNCTION__ ": posted buf at %p\n", cur_buf); 417 cur_buf += size; 418 } 419 420 return i; /* num of buffers posted */ 421} 422 423VAPI_ret_t osmt_mtl_mad_poll4cqe(VAPI_hca_hndl_t hca, VAPI_cq_hndl_t cq, 424 VAPI_wc_desc_t * wc_desc_p, 425 u_int32_t max_poll, u_int32_t poll_sleep, 426 VAPI_ud_av_hndl_t * avh_p) 427{ 428 VAPI_ret_t ret = VAPI_CQ_EMPTY; 429 u_int32_t poll_cnt = 0; 430 431 /* wait for something to arrive */ 432 while ((ret == VAPI_CQ_EMPTY) && (poll_cnt < max_poll)) { 433 ret = VAPI_poll_cq(hca, cq, wc_desc_p); 434 /* don't sleep if we already succeeded) */ 435 if (ret != VAPI_CQ_EMPTY) { 436 break; 437 } 438 usleep(poll_sleep); 439 poll_cnt++; 440 } 441 442 /* if passed an AVH to destory - do it */ 443 if (avh_p != NULL) { 444 VAPI_destroy_addr_hndl(hca, *avh_p); 445 } 446 447 if ((poll_cnt == max_poll) && (ret == VAPI_CQ_EMPTY)) { 448 MTL_DEBUG1(__FUNCTION__ 449 ": Failed to get completion on wq after %d polls.\n", 450 max_poll); 451 return VAPI_CQ_EMPTY; 452 } 453 454 if (ret != VAPI_OK) { 455 MTL_DEBUG1(__FUNCTION__ 456 ": VAPI_poll_cq failed with ret=%s on sq_cq\n", 457 mtl_strerror_sym(ret)); 458 return ret; 459 } 460 461 if (wc_desc_p->status != VAPI_SUCCESS) { 462 MTL_DEBUG1(__FUNCTION__ ": completion error (%d) detected\n", 463 wc_desc_p->status); 464 } 465 466 return VAPI_OK; 467} 468 469#endif /* OSM_VENDOR_INTF_MTL */ 470