osm_bind_handle_t osm_vendor_bind(IN osm_vendor_t * const p_vend, IN osm_bind_info_t * const p_bind_info, IN osm_mad_pool_t * const p_mad_pool, IN osm_vend_mad_recv_callback_t mad_recv_callback, IN osm_vend_mad_send_err_callback_t send_err_callback, IN void *context) { osmv_bind_obj_t *p_bo; ib_api_status_t status; char hca_id[32]; cl_status_t cl_st; cl_list_obj_t *p_obj; uint8_t hca_index; if (NULL == p_vend || NULL == p_bind_info || NULL == p_mad_pool || NULL == mad_recv_callback || NULL == send_err_callback) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "osm_vendor_bind: ERR 7302: " "NULL parameter passed in: p_vend=%p p_bind_info=%p p_mad_pool=%p recv_cb=%p send_err_cb=%p\n", p_vend, p_bind_info, p_mad_pool, mad_recv_callback, send_err_callback); return OSM_BIND_INVALID_HANDLE; } p_bo = malloc(sizeof(osmv_bind_obj_t)); if (NULL == p_bo) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "osm_vendor_bind: ERR 7303: could not allocate the bind object\n"); return OSM_BIND_INVALID_HANDLE; } memset(p_bo, 0, sizeof(osmv_bind_obj_t)); p_bo->p_vendor = p_vend; p_bo->recv_cb = mad_recv_callback; p_bo->send_err_cb = send_err_callback; p_bo->cb_context = context; p_bo->p_osm_pool = p_mad_pool; /* obtain the hca name and port num from the guid */ osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "osm_vendor_bind: " "Finding CA and Port that owns port guid 0x%" PRIx64 ".\n", cl_ntoh64(p_bind_info->port_guid)); status = osm_vendor_get_guid_ca_and_port(p_bo->p_vendor, p_bind_info->port_guid, &(p_bo->hca_hndl), hca_id, &hca_index, &(p_bo->port_num)); if (status != IB_SUCCESS) { osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR, "osm_vendor_bind: ERR 7304: " "Fail to find port number of port guid:0x%016" PRIx64 "\n", p_bind_info->port_guid); free(p_bo); return OSM_BIND_INVALID_HANDLE; } /* Initialize the magic_ptr to the pointer of the p_bo info. This will be used to signal when the object is being destroyed, so no real action will be done then. */ p_bo->magic_ptr = p_bo; p_bo->is_closing = FALSE; cl_spinlock_construct(&(p_bo->lock)); cl_st = cl_spinlock_init(&(p_bo->lock)); if (cl_st != CL_SUCCESS) { osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR, "osm_vendor_bind: ERR 7305: " "could not initialize the spinlock ...\n"); free(p_bo); return OSM_BIND_INVALID_HANDLE; } osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "osm_vendor_bind: osmv_txnmgr_init ... \n"); if (osmv_txnmgr_init(&p_bo->txn_mgr, p_vend->p_log, &(p_bo->lock)) != IB_SUCCESS) { osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR, "osm_vendor_bind: ERR 7306: " "osmv_txnmgr_init failed \n"); cl_spinlock_destroy(&p_bo->lock); free(p_bo); return OSM_BIND_INVALID_HANDLE; } /* Do the real job! (Transport-dependent) */ if (IB_SUCCESS != osmv_transport_init(p_bind_info, hca_id, hca_index, p_bo)) { osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR, "osm_vendor_bind: ERR 7307: " "osmv_transport_init failed \n"); osmv_txnmgr_done((osm_bind_handle_t) p_bo); cl_spinlock_destroy(&p_bo->lock); free(p_bo); return OSM_BIND_INVALID_HANDLE; } /* insert bind handle into db */ p_obj = malloc(sizeof(cl_list_obj_t)); if (NULL == p_obj) { osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR, "osm_vendor_bind: ERR 7308: " "osm_vendor_bind: could not allocate the list object\n"); osmv_transport_done(p_bo->p_transp_mgr); osmv_txnmgr_done((osm_bind_handle_t) p_bo); cl_spinlock_destroy(&p_bo->lock); free(p_bo); return OSM_BIND_INVALID_HANDLE; } memset(p_obj, 0, sizeof(cl_list_obj_t)); cl_qlist_set_obj(p_obj, p_bo); cl_qlist_insert_head(&p_vend->bind_handles, &p_obj->list_item); return (osm_bind_handle_t) p_bo; }
/********************************************************************** * BINDs a callback (rcv and send error) for a given class and method * defined by the given: osm_bind_info_t **********************************************************************/ osm_bind_handle_t osm_vendor_bind(IN osm_vendor_t * const p_vend, IN osm_bind_info_t * const p_user_bind, IN osm_mad_pool_t * const p_mad_pool, IN osm_vend_mad_recv_callback_t mad_recv_callback, IN osm_vend_mad_send_err_callback_t send_err_callback, IN void *context) { ib_net64_t port_guid; osm_ts_bind_info_t *p_bind = NULL; VAPI_hca_hndl_t hca_hndl; VAPI_hca_id_t hca_id; uint32_t port_num; ib_api_status_t status; int device_fd; char device_file[16]; osm_ts_user_mad_filter filter; int ts_ioctl_ret; int qpn; OSM_LOG_ENTER(p_vend->p_log); CL_ASSERT(p_mad_pool); port_guid = p_user_bind->port_guid; osm_log(p_vend->p_log, OSM_LOG_INFO, "osm_vendor_bind: " "Binding to port 0x%" PRIx64 ".\n", cl_ntoh64(port_guid)); switch (p_user_bind->mad_class) { case IB_MCLASS_SUBN_LID: case IB_MCLASS_SUBN_DIR: p_bind = &(p_vend->smi_bind); qpn = 0; break; case IB_MCLASS_SUBN_ADM: default: p_bind = &(p_vend->gsi_bind); qpn = 1; break; } /* Make sure we did not previously opened the file */ if (p_bind->ul_dev_fd >= 0) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "osm_vendor_bind: ERR 5004: " "Already binded to port %u\n", p_bind->port_num); goto Exit; } /* We need to figure out what is the TS file name to attach to. I guess it is following the index of the port in the table of ports. */ /* obtain the hca name and port num from the guid */ osm_log(p_vend->p_log, OSM_LOG_DEBUG, "osm_vendor_bind: " "Finding CA and Port that owns port guid 0x%" PRIx64 ".\n", cl_ntoh64(port_guid)); status = osm_vendor_get_guid_ca_and_port(p_vend, port_guid, &hca_hndl, &hca_id, &port_num); if (status != IB_SUCCESS) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "osm_vendor_bind: ERR 5005: " "Fail to find port number of port guid:0x%016" PRIx64 "\n", port_guid); goto Exit; } /* the file name is just /dev/ts_ua0: */ strcpy(device_file, "/dev/ts_ua0"); osm_log(p_vend->p_log, OSM_LOG_ERROR, "osm_vendor_bind: " "Opening TS UL dev file:%s\n", device_file); /* Open the file ... */ device_fd = open(device_file, O_RDWR); if (device_fd < 0) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "osm_vendor_bind: ERR 5006: " "Fail to open TS UL dev file:%s\n", device_file); goto Exit; } /* track this bind request info */ p_bind->ul_dev_fd = device_fd; p_bind->port_num = port_num; p_bind->p_vend = p_vend; p_bind->client_context = context; p_bind->rcv_callback = mad_recv_callback; p_bind->send_err_callback = send_err_callback; p_bind->p_osm_pool = p_mad_pool; p_bind->hca_hndl = hca_hndl; /* * Create the MAD filter on this file handle. */ filter.port = port_num; filter.qpn = qpn; filter.mgmt_class = p_user_bind->mad_class; filter.direction = TS_IB_MAD_DIRECTION_IN; filter.mask = TS_IB_MAD_FILTER_DIRECTION | TS_IB_MAD_FILTER_PORT | TS_IB_MAD_FILTER_QPN | TS_IB_MAD_FILTER_MGMT_CLASS; ts_ioctl_ret = ioctl(device_fd, TS_IB_IOCSMADFILTADD, &filter); if (ts_ioctl_ret < 0) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "osm_vendor_bind: ERR 5014: " "Fail to register MAD filter with err:%u\n", ts_ioctl_ret); goto Exit; } /* Initialize the listener thread for this port */ status = cl_thread_init(&p_bind->poller, __osm_vendor_ts_poller, p_bind, "osm ts poller"); if (status != IB_SUCCESS) goto Exit; Exit: OSM_LOG_EXIT(p_vend->p_log); return ((osm_bind_handle_t) p_bind); }
/* * Prepare an asynchronous QP (rcv) for sending inform info and * handling the incoming reports. * */ ib_api_status_t osmt_bind_inform_qp(IN osmtest_t * const p_osmt, OUT osmt_qp_ctx_t * p_qp_ctx) { ib_net64_t port_guid; VAPI_hca_hndl_t hca_hndl; VAPI_hca_id_t hca_id; uint32_t port_num; VAPI_ret_t vapi_ret; IB_MGT_ret_t mgt_ret; uint8_t hca_index; osm_log_t *p_log = &p_osmt->log; ib_api_status_t status = IB_SUCCESS; OSM_LOG_ENTER(p_log); port_guid = p_osmt->local_port.port_guid; OSM_LOG(p_log, OSM_LOG_DEBUG, "Binding to port 0x%" PRIx64 "\n", cl_ntoh64(port_guid)); /* obtain the hca name and port num from the guid */ OSM_LOG(p_log, OSM_LOG_DEBUG, "Finding CA and Port that owns port guid 0x%" PRIx64 "\n", port_guid); mgt_ret = osm_vendor_get_guid_ca_and_port(p_osmt->p_vendor, port_guid, &hca_hndl, &hca_id[0], &hca_index, &port_num); if (mgt_ret != IB_MGT_OK) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0109: " "Unable to obtain CA and port (%d).\n"); status = IB_ERROR; goto Exit; } #define OSMT_MTL_REVERSE_QP1_WELL_KNOWN_Q_KEY 0x80010000 strncpy(p_qp_ctx->qp_bind_hndl.hca_id, hca_id, sizeof(hca_id)); p_qp_ctx->qp_bind_hndl.hca_hndl = hca_hndl; p_qp_ctx->qp_bind_hndl.port_num = port_num; p_qp_ctx->qp_bind_hndl.max_outs_sq = 10; p_qp_ctx->qp_bind_hndl.max_outs_rq = 10; p_qp_ctx->qp_bind_hndl.qkey = OSMT_MTL_REVERSE_QP1_WELL_KNOWN_Q_KEY; vapi_ret = osmt_mtl_init_opened_hca(&p_qp_ctx->qp_bind_hndl); if (vapi_ret != VAPI_OK) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0114: " "Error initializing QP.\n"); status = IB_ERROR; goto Exit; } /* we use the pre-allocated buffers for send and receive : send from buf[0] receive from buf[2] */ p_qp_ctx->p_send_buf = (uint8_t *) p_qp_ctx->qp_bind_hndl.buf_ptr + GRH_LEN; p_qp_ctx->p_recv_buf = (uint8_t *) p_qp_ctx->qp_bind_hndl.buf_ptr + 2 * (GRH_LEN + MAD_BLOCK_SIZE); /* Need to clear assigned memory of p_send_buf - before using it to send any data */ memset(p_qp_ctx->p_send_buf, 0, MAD_BLOCK_SIZE); status = IB_SUCCESS; OSM_LOG(p_log, OSM_LOG_DEBUG, "Initialized QP:0x%X in VAPI Mode\n", p_qp_ctx->qp_bind_hndl.qp_id); OSM_LOG(p_log, OSM_LOG_DEBUG, "Binding to IB_MGT SMI\n"); /* we also need a QP0 handle for sending packets */ mgt_ret = IB_MGT_get_handle(hca_id, port_num, IB_MGT_SMI, &(p_qp_ctx->ib_mgt_qp0_handle)); if (IB_MGT_OK != mgt_ret) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0115: " "Error obtaining IB_MGT handle to SMI\n"); status = IB_ERROR; goto Exit; } Exit: OSM_LOG_EXIT(p_log); return status; }