예제 #1
0
void __mad_recv_processor(IN void *context)
{
	mad_bind_info_t *p_mad_bind_info = (mad_bind_info_t *) context;
	umadt_obj_t *p_umadt_obj;
	osm_madw_t *p_osm_madw = NULL;
	osm_vend_wrap_t *p_vend_wrap = NULL;
	osm_mad_addr_t osm_mad_addr = { 0 };
	cl_list_item_t *p_list_item;
	void *transaction_context;

	FSTATUS Status;
	MadtStruct *pRecvMad = NULL;
	MadWorkCompletion *pRecvCmp = NULL;

	CL_ASSERT(context);

	p_mad_bind_info = (mad_bind_info_t *) context;
	p_umadt_obj = p_mad_bind_info->p_umadt_obj;
	/*  PollFor a completion */
	/*  if FNOTFOND, then wait for a completion then again poll and return the MAD */
	while (1) {
		Status =
		    p_umadt_obj->uMadtInterface.
		    uMadtPollForRecvCompletion(p_mad_bind_info->umadt_handle,
					       &pRecvMad, &pRecvCmp);
		if (Status != FSUCCESS) {
			if (Status == FNOT_FOUND) {
				/* Wait for a completion */
				Status = p_umadt_obj->uMadtInterface.uMadtWaitForAnyCompletion(p_mad_bind_info->umadt_handle, RECV_COMPLETION, 0x5000);	/* 5 sec timeout */

				if (Status == FTIMEOUT) {
					continue;
				}
				CL_ASSERT(Status == FSUCCESS);

				Status =
				    p_umadt_obj->uMadtInterface.
				    uMadtPollForRecvCompletion(p_mad_bind_info->
							       umadt_handle,
							       &pRecvMad,
							       &pRecvCmp);
				if (Status != FSUCCESS) {
					printf
					    (" mad_recv_worker: Error in PollForRecv returning <%x>\n",
					     Status);
					CL_ASSERT(0);
				}
			} else {
				printf
				    ("uMadtPollForRecvCompletion Status=<%x>\n",
				     Status);
				CL_ASSERT(0);
			}
		}
		CL_ASSERT(pRecvMad);
		CL_ASSERT(pRecvCmp);

		if (((ib_sa_mad_t_vM3 *) (&pRecvMad->IBMad))->frag_flag & 0x20) {
			/*  Ignore the ACK packet */
			Status =
			    p_umadt_obj->uMadtInterface.
			    uMadtReleaseRecvMad(p_mad_bind_info->umadt_handle,
						pRecvMad);
			continue;
		}
		/*  */
		/*  Extract the return address to pass it on to the client */
		/*  */
		osm_mad_addr.dest_lid = pRecvCmp->AddressInfo.DestLid;
		osm_mad_addr.path_bits = pRecvCmp->AddressInfo.PathBits;
		osm_mad_addr.static_rate = pRecvCmp->AddressInfo.StaticRate;

		if (p_mad_bind_info->umadt_reg_class.ClassId ==
		    IB_MCLASS_SUBN_LID
		    || p_mad_bind_info->umadt_reg_class.ClassId ==
		    IB_MCLASS_SUBN_DIR) {
			osm_mad_addr.addr_type.smi.source_lid =
			    pRecvCmp->AddressInfo.AddrType.Smi.SourceLid;
			/* osm_mad_addr.addr_type.smi.port_num = pRecvCmp->AddressInfo.AddrType.Smi.PortNumber; */
		} else {
			osm_mad_addr.addr_type.gsi.remote_qp =
			    pRecvCmp->AddressInfo.AddrType.Gsi.RemoteQpNumber;
			osm_mad_addr.addr_type.gsi.remote_qkey =
			    pRecvCmp->AddressInfo.AddrType.Gsi.RemoteQkey;
			osm_mad_addr.addr_type.gsi.pkey_ix = 0;
			osm_mad_addr.addr_type.gsi.service_level =
			    pRecvCmp->AddressInfo.AddrType.Gsi.ServiceLevel;
			osm_mad_addr.addr_type.gsi.global_route =
			    pRecvCmp->AddressInfo.AddrType.Gsi.GlobalRoute;
			/* osm_mad_addr.addr_type.gsi.grh_info = pRecvCmp->AddressInfo.AddrType.Gsi.GRHInfo; */
		}
		p_osm_madw =
		    osm_mad_pool_get_wrapper(p_mad_bind_info->p_mad_pool,
					     p_mad_bind_info, MAD_BLOCK_SIZE,
					     (ib_mad_t *) & pRecvMad->IBMad,
					     &osm_mad_addr);
		CL_ASSERT(p_osm_madw);
		p_vend_wrap = osm_madw_get_vend_ptr(p_osm_madw);
		CL_ASSERT(p_vend_wrap);
		p_vend_wrap->p_madt_struct = pRecvMad;
		p_vend_wrap->direction = RECEIVE;

		osm_log(p_mad_bind_info->p_umadt_obj->p_log, OSM_LOG_DEBUG,
			"__mad_recv_processor: "
			"Received data p_osm_madw[0x%p].\n", p_osm_madw);

		/*  */
		/*  Do TID Processing. */
		/*  */
		/*  If R bit is set swap the TID */

		cl_spinlock_acquire(&p_mad_bind_info->trans_ctxt_lock);
		p_list_item =
		    cl_qlist_find_from_head(&p_mad_bind_info->trans_ctxt_list,
					    __match_tid_context,
					    &p_osm_madw->p_mad->trans_id);

		if (p_list_item ==
		    cl_qlist_end(&p_mad_bind_info->trans_ctxt_list)) {
			transaction_context = NULL;
		} else {
			transaction_context =
			    ((trans_context_t *) p_list_item)->context;
			cl_qlist_remove_item(&p_mad_bind_info->trans_ctxt_list,
					     p_list_item);
			free(p_list_item);
		}
		cl_spinlock_release(&p_mad_bind_info->trans_ctxt_lock);
		((ib_mad_t *) p_osm_madw->p_mad)->trans_id =
		    cl_ntoh64(p_osm_madw->p_mad->trans_id >> 24);
		osm_log(p_mad_bind_info->p_umadt_obj->p_log, OSM_LOG_DEBUG,
			"__mad_recv_processor: "
			"Received data p_osm_madw [0x%p]" "\n\t\t\t\tTID[0x%"
			PRIx64 ", context[%p]. \n", p_osm_madw,
			((ib_mad_t *) p_osm_madw->p_mad)->trans_id,
			transaction_context);

		(*(p_mad_bind_info->mad_recv_callback)) (p_osm_madw,
							 p_mad_bind_info->
							 client_context,
							 transaction_context);

	}
}
예제 #2
0
static void
__osm_al_rcv_callback(IN void *mad_svc_context, IN ib_mad_element_t * p_elem)
{
	osm_al_bind_info_t *const p_bind =
	    (osm_al_bind_info_t *) mad_svc_context;
	osm_vendor_t *const p_vend = p_bind->p_vend;
	osm_madw_t *p_old_madw;
	osm_madw_t *p_new_madw;
	osm_vend_wrap_t *p_old_vw;
	osm_vend_wrap_t *p_new_vw;
	ib_mad_t *p_new_mad;
	osm_mad_addr_t mad_addr;

	OSM_LOG_ENTER(p_vend->p_log);

	CL_ASSERT(p_elem->context1 == NULL);
	CL_ASSERT(p_elem->context2 == NULL);

	p_new_mad = ib_get_mad_buf(p_elem);

	/*
	   In preperation for initializing the new mad wrapper,
	   Initialize the mad_addr structure for the received wire MAD.
	 */
	mad_addr.dest_lid = p_elem->remote_lid;
	mad_addr.path_bits = p_elem->path_bits;

	/* TO DO - figure out which #define to use for the 2.5 Gb rate... */
	mad_addr.static_rate = 0;

	if (p_new_mad->mgmt_class == IB_MCLASS_SUBN_LID ||
	    p_new_mad->mgmt_class == IB_MCLASS_SUBN_DIR) {
		mad_addr.addr_type.smi.source_lid = p_elem->remote_lid;
	} else {
		mad_addr.addr_type.gsi.remote_qp = p_elem->remote_qp;
		mad_addr.addr_type.gsi.remote_qkey = p_elem->remote_qkey;
		mad_addr.addr_type.gsi.pkey_ix = p_elem->pkey_index;
		mad_addr.addr_type.gsi.service_level = p_elem->remote_sl;
		mad_addr.addr_type.gsi.global_route = FALSE;
	}

	/*
	   If this MAD is a response to a previous request,
	   then grab our pre-allocated MAD wrapper.
	   Otherwise, allocate a new MAD wrapper.
	 */
	if (ib_mad_is_response(p_new_mad)) {
		CL_ASSERT(p_elem->send_context1 != NULL);
		CL_ASSERT(p_elem->send_context2 == NULL);

		p_old_madw = (osm_madw_t *) p_elem->send_context1;
		p_old_vw = osm_madw_get_vend_ptr(p_old_madw);
		p_new_madw = p_old_vw->p_resp_madw;

		CL_ASSERT(p_new_madw);

		osm_madw_init(p_new_madw, p_bind, p_elem->size, &mad_addr);
		osm_madw_set_mad(p_new_madw, p_new_mad);
	} else {
		CL_ASSERT(p_elem->send_context1 == NULL);
		CL_ASSERT(p_elem->send_context2 == NULL);

		p_new_madw = osm_mad_pool_get_wrapper(p_bind->p_osm_pool,
						      p_bind, p_elem->size,
						      p_new_mad, &mad_addr);
	}

	CL_ASSERT(p_new_madw);
	p_new_vw = osm_madw_get_vend_ptr(p_new_madw);

	p_new_vw->h_bind = p_bind;
	p_new_vw->size = p_elem->size;
	p_new_vw->p_elem = p_elem;
	p_new_vw->h_av = 0;
	p_new_vw->p_resp_madw = NULL;

	osm_log(p_vend->p_log, OSM_LOG_DEBUG,
		"__osm_al_rcv_callback: "
		"Calling receive callback function %p.\n",
		p_bind->rcv_callback);

	p_bind->rcv_callback(p_new_madw, p_bind->client_context,
			     p_elem->send_context1);

	OSM_LOG_EXIT(p_vend->p_log);
}