/********************************************************************** Send a MAD through. What is unclear to me is the need for the setting of all the MAD Wrapper fields. Seems like the OSM uses these values during it's processing... **********************************************************************/ ib_api_status_t osm_vendor_send(IN osm_bind_handle_t h_bind, IN osm_madw_t * const p_madw, IN boolean_t const resp_expected) { osm_ts_bind_info_t *p_bind = (osm_ts_bind_info_t *) h_bind; osm_vendor_t *const p_vend = p_bind->p_vend; osm_vend_wrap_t *const p_vw = osm_madw_get_vend_ptr(p_madw); ib_api_status_t status; OSM_LOG_ENTER(p_vend->p_log); /* * If a response is expected to this MAD, then preallocate * a mad wrapper to contain the wire MAD received in the * response. Allocating a wrapper here allows for easier * failure paths than after we already received the wire mad. */ if (resp_expected == TRUE) { /* we track it in the vendor wrapper */ p_vw->p_resp_madw = osm_mad_pool_get_wrapper_raw(p_bind->p_osm_pool); if (p_vw->p_resp_madw == NULL) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "osm_vendor_send: ERR 5024: " "Unable to allocate MAD wrapper.\n"); status = IB_INSUFFICIENT_RESOURCES; goto Exit; } /* put some minimal info on that wrapper */ ((osm_madw_t *) (p_vw->p_resp_madw))->h_bind = h_bind; /* we also want to track it in the TID based map */ status = osm_transaction_mgr_insert_madw((osm_bind_handle_t *) p_bind, p_madw); if (status != IB_SUCCESS) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "osm_vendor_send: ERR 5025: " "Error inserting request madw by TID (%d).\n", status); } } else p_vw->p_resp_madw = NULL; /* do the actual send */ /* HACK: to be replaced by call to RMPP Segmentation */ status = osm_ts_send_mad(p_bind, p_madw); /* we do not get an asycn callback so call it ourselves */ /* this will handle all cleanup if neccessary */ __osm_ts_send_callback(p_bind, !resp_expected, p_madw, status); Exit: OSM_LOG_EXIT(p_vend->p_log); return (status); }
ib_api_status_t osm_vendor_send(IN osm_bind_handle_t h_bind, IN osm_madw_t * const p_madw, IN boolean_t const resp_expected) { osm_al_bind_info_t *const p_bind = h_bind; osm_vendor_t *const p_vend = p_bind->p_vend; osm_vend_wrap_t *const p_vw = osm_madw_get_vend_ptr(p_madw); osm_mad_addr_t *const p_mad_addr = osm_madw_get_mad_addr_ptr(p_madw); ib_mad_t *const p_mad = osm_madw_get_mad_ptr(p_madw); ib_api_status_t status; ib_mad_element_t *p_elem; ib_av_attr_t av; OSM_LOG_ENTER(p_vend->p_log); CL_ASSERT(p_vw->h_bind == h_bind); CL_ASSERT(p_vw->p_elem); p_elem = p_vw->p_elem; /* If a response is expected to this MAD, then preallocate a mad wrapper to contain the wire MAD received in the response. Allocating a wrapper here allows for easier failure paths than after we already received the wire mad. */ if (resp_expected) { p_vw->p_resp_madw = osm_mad_pool_get_wrapper_raw(p_bind->p_osm_pool); if (p_vw->p_resp_madw == NULL) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "osm_vendor_send: ERR 3B27: " "Unable to allocate MAD wrapper.\n"); status = IB_INSUFFICIENT_RESOURCES; goto Exit; } } else p_vw->p_resp_madw = NULL; /* For all sends other than directed route SM MADs, acquire an address vector for the destination. */ if (p_mad->mgmt_class != IB_MCLASS_SUBN_DIR) { memset(&av, 0, sizeof(av)); av.port_num = p_bind->port_num; av.dlid = p_mad_addr->dest_lid; av.static_rate = p_mad_addr->static_rate; av.path_bits = p_mad_addr->path_bits; if ((p_mad->mgmt_class != IB_MCLASS_SUBN_LID) && (p_mad->mgmt_class != IB_MCLASS_SUBN_DIR)) { av.sl = p_mad_addr->addr_type.gsi.service_level; if (p_mad_addr->addr_type.gsi.global_route) { av.grh_valid = TRUE; /* ANIL */ /* av.grh = p_mad_addr->addr_type.gsi.grh_info; */ } } if (osm_log_is_active(p_vend->p_log, OSM_LOG_DEBUG)) { osm_log(p_vend->p_log, OSM_LOG_DEBUG, "osm_vendor_send: " "av.port_num 0x%X, " "av.dlid 0x%X, " "av.static_rate %d, " "av.path_bits %d.\n", av.port_num, cl_ntoh16(av.dlid), av.static_rate, av.path_bits); } status = ib_create_av(p_vend->h_pd, &av, &p_vw->h_av); if (status != IB_SUCCESS) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "osm_vendor_send: ERR 3B28: " "Unable to create address vector (%s).\n", ib_get_err_str(status)); if (p_vw->p_resp_madw) osm_mad_pool_put(p_bind->p_osm_pool, p_vw->p_resp_madw); goto Exit; } if (osm_log_is_active(p_vend->p_log, OSM_LOG_DEBUG)) { osm_log(p_vend->p_log, OSM_LOG_DEBUG, "osm_vendor_send: " "Allocating av handle %p.\n", p_vw->h_av); } } else { p_vw->h_av = p_bind->h_dr_av; } p_elem->h_av = p_vw->h_av; p_elem->context1 = p_madw; p_elem->context2 = NULL; p_elem->immediate_data = 0; p_elem->p_grh = NULL; p_elem->resp_expected = resp_expected; p_elem->retry_cnt = OSM_DEFAULT_RETRY_COUNT; p_elem->send_opt = IB_SEND_OPT_SIGNALED; p_elem->timeout_ms = p_vend->timeout; /* Completion information. */ p_elem->status = 0; /* Not trusting AL */ if ((p_mad->mgmt_class == IB_MCLASS_SUBN_LID) || (p_mad->mgmt_class == IB_MCLASS_SUBN_DIR)) { p_elem->remote_qp = 0; p_elem->remote_qkey = 0; } else { p_elem->remote_qp = p_mad_addr->addr_type.gsi.remote_qp; p_elem->remote_qkey = p_mad_addr->addr_type.gsi.remote_qkey; osm_log(p_vend->p_log, OSM_LOG_DEBUG, "osm_vendor_send: " "remote qp = 0x%X, remote qkey = 0x%X.\n", cl_ntoh32(p_elem->remote_qp), cl_ntoh32(p_elem->remote_qkey)); } status = ib_send_mad(p_bind->h_svc, p_elem, NULL); if (status != IB_SUCCESS) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "osm_vendor_send: ERR 3B29: " "Send failed (%s).\n", ib_get_err_str(status)); if (p_vw->p_resp_madw) osm_mad_pool_put(p_bind->p_osm_pool, p_vw->p_resp_madw); goto Exit; } Exit: OSM_LOG_EXIT(p_vend->p_log); return (status); }