Ejemplo n.º 1
0
static void init_sa_mad(struct mca_btl_openib_sa_qp_cache *cache,
                       ib_sa_mad_t *sa_mad,
                       struct ibv_send_wr *swr,
                       struct ibv_sge *ssge,
                       uint16_t lid,
                       uint16_t rem_lid)
{
    ib_path_rec_t *path_record = (ib_path_rec_t*)sa_mad->data;

    memset(swr, 0, sizeof(*swr));
    memset(ssge, 0, sizeof(*ssge));

    /* Initialize the standard MAD header. */
    memset(sa_mad, 0, MAD_BLOCK_SIZE);
    ib_mad_init_new((ib_mad_t *)sa_mad,          /* mad header pointer */
                    IB_MCLASS_SUBN_ADM,          /* management class */
                    (uint8_t) 2,                 /* version */
                    IB_MAD_METHOD_GET,           /* method */
                    hton64((uint64_t)lid << 48 | /* transaction ID */
                           (uint64_t)rem_lid << 32 |
                           (uint64_t)cache->qp->qp_num << 8),
                    IB_MAD_ATTR_PATH_RECORD,     /* attribute ID */
                    0);                          /* attribute modifier */

    sa_mad->comp_mask = IB_PR_COMPMASK_DLID | IB_PR_COMPMASK_SLID;
    path_record->dlid = htons(rem_lid);
    path_record->slid = htons(lid);

    swr->sg_list = ssge;
    swr->num_sge = 1;
    swr->opcode = IBV_WR_SEND;
    swr->wr.ud.ah = cache->ah;
    swr->wr.ud.remote_qpn = ntohl(IB_QP1);
    swr->wr.ud.remote_qkey = ntohl(IB_QP1_WELL_KNOWN_Q_KEY);
    swr->send_flags = IBV_SEND_SIGNALED | IBV_SEND_SOLICITED;

    ssge->addr = (uint64_t)(void *)sa_mad;
    ssge->length = MAD_BLOCK_SIZE;
    ssge->lkey = cache->mr->lkey;
}
Ejemplo n.º 2
0
/* Send a MAD out on the GSI interface */
static ib_api_status_t
__osmv_send_sa_req(IN osmv_sa_bind_info_t * p_bind,
		   IN const osmv_sa_mad_data_t * const p_sa_mad_data,
		   IN const osmv_query_req_t * const p_query_req)
{
	ib_api_status_t status;
	ib_mad_t *p_mad_hdr;
	ib_sa_mad_t *p_sa_mad;
	osm_madw_t *p_madw;
	osm_log_t *p_log = p_bind->p_log;
	static atomic32_t trans_id;
	boolean_t sync;
	osmv_query_req_t *p_query_req_copy;

	OSM_LOG_ENTER(p_log);

	/*
	   since the sm_lid might change we obtain it every send
	   (actually it is cached in the bind object and refreshed
	   every 30sec by this proc)
	 */
	if (time(NULL) > p_bind->last_lids_update_sec + 30) {
		status = update_umad_port(p_bind->p_vendor);
		if (status != IB_SUCCESS) {
			OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 5509: "
				"Failed to obtain the SM lid\n");
			goto Exit;
		}
		p_bind->last_lids_update_sec = time(NULL);
	}

	/* Get a MAD wrapper for the send */
	p_madw = osm_mad_pool_get(p_bind->p_mad_pool,
				  p_bind->h_bind, MAD_BLOCK_SIZE, NULL);

	if (p_madw == NULL) {
		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 5510: "
			"Unable to acquire MAD\n");
		status = IB_INSUFFICIENT_RESOURCES;
		goto Exit;
	}

	/* Initialize the Sent MAD: */

	/* Initialize the MAD buffer for the send operation. */
	p_mad_hdr = osm_madw_get_mad_ptr(p_madw);
	p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);

	/* Get a new transaction Id */
	cl_atomic_inc(&trans_id);

	/* Cleanup the MAD from any residue */
	memset(p_sa_mad, 0, MAD_BLOCK_SIZE);

	/* Initialize the standard MAD header. */
	ib_mad_init_new(p_mad_hdr,	/* mad pointer */
			IB_MCLASS_SUBN_ADM,	/* class */
			(uint8_t) 2,	/* version */
			p_sa_mad_data->method,	/* method */
			cl_hton64((uint64_t) trans_id),	/* tid */
			p_sa_mad_data->attr_id,	/* attr id */
			p_sa_mad_data->attr_mod	/* attr mod */);

	/* Set the query information. */
	p_sa_mad->sm_key = p_query_req->sm_key;
	p_sa_mad->attr_offset = 0;
	p_sa_mad->comp_mask = p_sa_mad_data->comp_mask;
#ifdef DUAL_SIDED_RMPP
	if (p_sa_mad->method == IB_MAD_METHOD_GETMULTI)
		p_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
#endif
	if (p_sa_mad->comp_mask) {
		memcpy(p_sa_mad->data, p_sa_mad_data->p_attr,
		       ib_get_attr_size(p_sa_mad_data->attr_offset));
	}

	/*
	   Provide the address to send to
	 */
	p_madw->mad_addr.dest_lid =
	    cl_hton16(p_bind->p_vendor->umad_port.sm_lid);
	p_madw->mad_addr.addr_type.smi.source_lid =
	    cl_hton16(p_bind->p_vendor->umad_port.base_lid);
	p_madw->mad_addr.addr_type.gsi.remote_qp = CL_HTON32(1);
	p_madw->resp_expected = TRUE;
	p_madw->fail_msg = CL_DISP_MSGID_NONE;

	/*
	   Provide MAD context such that the call back will know what to do.
	   We have to keep the entire request structure so we know the CB.
	   Since we can not rely on the client to keep it around until
	   the response - we duplicate it and will later dispose it (in CB).
	   To store on the MADW we cast it into what opensm has:
	   p_madw->context.ni_context.node_guid
	 */
	p_query_req_copy = malloc(sizeof(*p_query_req_copy));
	*p_query_req_copy = *p_query_req;
	p_madw->context.ni_context.node_guid =
	    (ib_net64_t) (long)p_query_req_copy;

	/* we can support async as well as sync calls */
	sync = ((p_query_req->flags & OSM_SA_FLAGS_SYNC) == OSM_SA_FLAGS_SYNC);

	/* send the mad asynchronously */
	status = osm_vendor_send(osm_madw_get_bind_handle(p_madw),
				 p_madw, p_madw->resp_expected);

	/* if synchronous - wait on the event */
	if (sync) {
		OSM_LOG(p_log, OSM_LOG_DEBUG, "Waiting for async event\n");
		cl_event_wait_on(&p_bind->sync_event, EVENT_NO_TIMEOUT, FALSE);
		cl_event_reset(&p_bind->sync_event);
		status = p_madw->status;
	}

Exit:
	OSM_LOG_EXIT(p_log);
	return status;
}
Ejemplo n.º 3
0
/* Send a MAD out on the GSI interface */
ib_api_status_t
__osmv_send_sa_req(IN osmv_sa_bind_info_t * p_bind,
		   IN const osmv_sa_mad_data_t * const p_sa_mad_data,
		   IN const osmv_query_req_t * const p_query_req)
{
	ib_api_status_t status;
	ib_mad_t *p_mad_hdr;
	ib_sa_mad_t *p_sa_mad;
	osm_madw_t *p_madw;
	osm_log_t *p_log = p_bind->p_log;
	static atomic32_t trans_id;
	boolean_t sync;
	osmv_query_req_t *p_query_req_copy;

	OSM_LOG_ENTER(p_log);

	/*
	   since the sm_lid might change we obtain it every send
	   (actually it is cached in the bind object and refreshed
	   every 30sec by this proc )
	 */
	status =
	    __osmv_get_lid_and_sm_lid_by_port_guid(p_bind->p_vendor,
						   p_bind->port_guid,
						   &p_bind->
						   last_lids_update_sec,
						   &p_bind->lid,
						   &p_bind->sm_lid);
	if (status != IB_SUCCESS) {
		osm_log(p_log, OSM_LOG_ERROR,
			"__osmv_send_sa_req: ERR 0509: "
			"Fail to obtain the sm lid.\n");
		goto Exit;
	}

	/* Get a MAD wrapper for the send */
	p_madw = osm_mad_pool_get(p_bind->p_mad_pool,
				  p_bind->h_bind, MAD_BLOCK_SIZE, NULL);

	if (p_madw == NULL) {
		osm_log(p_log, OSM_LOG_ERROR,
			"__osmv_send_sa_req: ERR 0510: "
			"Unable to acquire MAD.\n");
		status = IB_INSUFFICIENT_RESOURCES;
		goto Exit;
	}

	/* Initialize the Sent MAD: */

	/* Initialize the MAD buffer for the send operation. */
	p_mad_hdr = osm_madw_get_mad_ptr(p_madw);
	p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);

	/* Get a new transaction Id */
	cl_atomic_inc(&trans_id);

	/* Cleanup the MAD from any residue */
	memset(p_sa_mad, 0, MAD_BLOCK_SIZE);

	/* Initialize the standard MAD header. */
	ib_mad_init_new(p_mad_hdr,	/* mad pointer */
			IB_MCLASS_SUBN_ADM,	/* class */
			(uint8_t) 2,	/* version */
			p_sa_mad_data->method,	/* method */
			cl_hton64((uint64_t) trans_id),	/* tid */
			p_sa_mad_data->attr_id,	/* attr id */
			p_sa_mad_data->attr_mod	/* attr mod */
	    );

	/* Set the query information. */
	p_sa_mad->sm_key = p_query_req->sm_key;
	p_sa_mad->attr_offset = 0;
	p_sa_mad->comp_mask = p_sa_mad_data->comp_mask;
	if (p_sa_mad->comp_mask) {
		memcpy(p_sa_mad->data, p_sa_mad_data->p_attr,
		       ib_get_attr_size(p_sa_mad_data->attr_offset));
	}

	/*
	   Provide the address to send to
	 */
	/* Patch to handle IBAL - host order , where it should take destination lid in network order */
#ifdef OSM_VENDOR_INTF_AL
	p_madw->mad_addr.dest_lid = p_bind->sm_lid;
#else
	p_madw->mad_addr.dest_lid = cl_hton16(p_bind->sm_lid);
#endif
	p_madw->mad_addr.addr_type.smi.source_lid = cl_hton16(p_bind->lid);
	p_madw->mad_addr.addr_type.gsi.remote_qp = CL_HTON32(1);
	p_madw->mad_addr.addr_type.gsi.remote_qkey = IB_QP1_WELL_KNOWN_Q_KEY;
	p_madw->mad_addr.addr_type.gsi.pkey_ix = 0;
	p_madw->resp_expected = TRUE;
	p_madw->fail_msg = CL_DISP_MSGID_NONE;

	/*
	   Provide MAD context such that the call back will know what to do.
	   We have to keep the entire request structure so we know the CB.
	   Since we can not rely on the client to keep it arroud until
	   the response - we duplicate it and will later dispose it (in CB).
	   To store on the MADW we cast it into what opensm has:
	   p_madw->context.arb_context.context1
	 */
	p_query_req_copy = malloc(sizeof(*p_query_req_copy));
	*p_query_req_copy = *p_query_req;
	p_madw->context.arb_context.context1 = p_query_req_copy;

	/* we can support async as well as sync calls */
	sync = ((p_query_req->flags & OSM_SA_FLAGS_SYNC) == OSM_SA_FLAGS_SYNC);

	/* send the mad asynchronously */
	status = osm_vendor_send(osm_madw_get_bind_handle(p_madw),
				 p_madw, p_madw->resp_expected);

	/* if synchronous - wait on the event */
	if (sync) {
		osm_log(p_log, OSM_LOG_DEBUG,
			"__osmv_send_sa_req: " "Waiting for async event.\n");
		cl_event_wait_on(&p_bind->sync_event, EVENT_NO_TIMEOUT, FALSE);
		cl_event_reset(&p_bind->sync_event);
		status = p_madw->status;
	}

Exit:
	OSM_LOG_EXIT(p_log);
	return status;
}
Ejemplo n.º 4
0
/*
 * Send a trap (Subn LID Route) Trap(Notice) through the regular
 * connection QP connection (targeted at QP0)
 *
 * Wait for the trap repress
 */
ib_api_status_t
osmt_send_trap_wait_for_forward(IN osmtest_t * const p_osmt,
				IN osmt_qp_ctx_t * p_qp_ctx)
{
	ib_smp_t *p_smp = (ib_smp_t *) (p_qp_ctx->p_send_buf);
	ib_mad_notice_attr_t *p_ntc = ib_smp_get_payload_ptr(p_smp);
	ib_sa_mad_t *p_sa_mad;
	IB_MGT_ret_t mgt_res;
	VAPI_ret_t vapi_ret;
	VAPI_wc_desc_t wc_desc;
	VAPI_ud_av_hndl_t avh;
	IB_ud_av_t av;
	static VAPI_wr_id_t wrid = 2222;
	osm_log_t *p_log = &p_osmt->log;
	ib_api_status_t status = IB_SUCCESS;

	OSM_LOG_ENTER(p_log);

	OSM_LOG(p_log, OSM_LOG_INFO,
		"Sending Traps to QP0 of SA LID:0x%X\n",
		p_osmt->local_port.sm_lid);

	/* init the MAD */
	memset(p_smp, 0, sizeof(ib_smp_t));
	ib_mad_init_new((ib_mad_t *) p_smp,
			IB_MCLASS_SUBN_LID,
			(uint8_t) 2,
			IB_MAD_METHOD_TRAP, cl_hton64(wrid), (ib_net16_t) 0, 0);

	wrid++;
	p_smp->attr_id = IB_MAD_ATTR_NOTICE;

	/* prepare the notice */
	p_ntc->generic_type = 0x82;	/*  generic, type = 2 */
	ib_notice_set_prod_type_ho(p_ntc, 1);
	p_ntc->g_or_v.generic.trap_num = cl_hton16(0x26);
	p_ntc->issuer_lid = cl_hton16(2);

	/* --------------------- PREP ------------------------- */
	if (osmt_mtl_mad_post_recv_bufs(&p_qp_ctx->qp_bind_hndl, p_qp_ctx->p_recv_buf, 1,	/*  we need to receive both trap repress and report */
					GRH_LEN + MAD_BLOCK_SIZE, wrid) != 1) {
		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0127: "
			"Error posting recv bufs\n");
		status = IB_ERROR;
		goto Exit;
	}
	OSM_LOG(p_log, OSM_LOG_DEBUG, "Posted recv bufs\n");

	av.dlid = p_osmt->local_port.sm_lid;
	av.grh_flag = FALSE;

	/*  EZ: returned in HACK: use constants */
	av.static_rate = 0;	/*  p_mad_addr->static_rate; */
	av.src_path_bits = 1;	/*  p_mad_addr->path_bits; */
	av.sl = 0;		/*  p_mad_addr->addr_type.gsi.service_level; */

	OSM_LOG(p_log, OSM_LOG_DEBUG,
		"av.dlid 0x%X, av.static_rate %d, av.path_bits %d\n",
		cl_ntoh16(av.dlid), av.static_rate, av.src_path_bits);

	/* send it */
	mgt_res = IB_MGT_send_mad(p_qp_ctx->ib_mgt_qp0_handle, p_smp,	/*  actual payload */
				  &av,	/*  address vector */
				  wrid,	/*  casting the mad wrapper pointer for err cb */
				  p_osmt->opt.transaction_timeout);
	if (mgt_res != IB_MGT_OK) {
		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0128: "
			"Error sending mad (%d)\n", mgt_res);
		status = IB_ERROR;
		goto Exit;
	}

	vapi_ret =
	    osmt_mtl_create_av(&p_qp_ctx->qp_bind_hndl,
			       p_osmt->local_port.sm_lid, &avh);
	if (vapi_ret != VAPI_OK) {
		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0129: "
			"Error Preparing AVH (%s)\n",
			VAPI_strerror_sym(vapi_ret));
		status = IB_ERROR;
		goto Exit;
	}
	OSM_LOG(p_log, OSM_LOG_DEBUG, "Prepared AVH\n");

	OSM_LOG(p_log, OSM_LOG_DEBUG, "Trap MAD Sent\n");

	/* --------------------- RECV ------------------------- */
	vapi_ret = osmt_mtl_mad_poll4cqe(p_qp_ctx->qp_bind_hndl.hca_hndl,
					 p_qp_ctx->qp_bind_hndl.rq_cq_hndl,
					 &wc_desc, 200, 10000, &avh);
	if (vapi_ret != VAPI_SUCCESS) {
		if (vapi_ret == VAPI_CQ_EMPTY) {
			OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0130: "
				"Timeout receiving mad (%s)\n",
				VAPI_strerror_sym(vapi_ret));
			status = IB_TIMEOUT;
		} else {
			OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0131: "
				"Error receiving mad (%s)\n",
				VAPI_strerror_sym(vapi_ret));
			status = IB_ERROR;
		}
		goto Exit;
	}

	/* check to see if successful - by examination of the subscribe bit */
	p_sa_mad = (ib_sa_mad_t *) (p_qp_ctx->p_recv_buf + GRH_LEN);

	if (p_sa_mad->method == IB_MAD_METHOD_REPORT) {
		if (p_sa_mad->attr_id == IB_MAD_ATTR_NOTICE) {
			OSM_LOG(p_log, OSM_LOG_INFO, "Received the Report!\n");
			status = IB_SUCCESS;
		} else {
			OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 1020"
				"Did not receive a Report(Notice) but attr:%d\n",
				cl_ntoh16(p_sa_mad->attr_id));
			status = IB_ERROR;
		}
	} else {
		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 1020"
			"Received an Unexpected Method:%d\n", p_smp->method);
		status = IB_ERROR;
	}

Exit:
	OSM_LOG_EXIT(p_log);
	return status;
}
Ejemplo n.º 5
0
/*
 * Register/Unregister to receive the given InformInfo
 *
 * Uses the qp context to send the inform info mad.
 * Wait for GetResp(InformInfoResp)
 *
 */
ib_api_status_t
osmt_reg_unreg_inform_info(IN osmtest_t * p_osmt,
			   IN osmt_qp_ctx_t * p_qp_ctx,
			   IN ib_inform_info_t * p_inform_info,
			   IN uint8_t reg_flag)
{
	ib_sa_mad_t *p_sa_mad = (ib_sa_mad_t *) (p_qp_ctx->p_send_buf);
	ib_inform_info_t *p_ii = ib_sa_mad_get_payload_ptr(p_sa_mad);	/*  SA Payload */
	VAPI_ret_t vapi_ret;
	VAPI_wc_desc_t wc_desc;
	VAPI_ud_av_hndl_t avh;
	static VAPI_wr_id_t wrid = 16198;
	osm_log_t *p_log = &p_osmt->log;
	ib_api_status_t status = IB_SUCCESS;

	OSM_LOG_ENTER(&p_osmt->log);

	/* init the MAD */
	ib_mad_init_new((ib_mad_t *) p_sa_mad,
			IB_MCLASS_SUBN_ADM,
			(uint8_t) 2,
			IB_MAD_METHOD_SET, cl_hton64(wrid), (ib_net16_t) 0, 0);
	wrid++;
	p_sa_mad->attr_id = IB_MAD_ATTR_INFORM_INFO;

	/* copy the reference inform info */
	memcpy(p_ii, p_inform_info, sizeof(ib_inform_info_t));

	if (reg_flag) {
		OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
			"Subscribing InformInfo: Traps from lid:0x%X to 0x%X, trap num :0x%X\n",
			p_ii->lid_range_begin, p_ii->lid_range_end,
			p_ii->g_or_v.generic.trap_num);
	} else {
		OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
			"UnSubscribing InformInfo: Traps from lid:0x%X to 0x%X\n",
			p_ii->lid_range_begin, p_ii->lid_range_end);
	}

	/* set the subscribe bit */
	if (reg_flag) {
		p_ii->subscribe = 1;
	} else {
		p_ii->subscribe = 0;
		/*
		 * we need to set the QPN on the mad if we unsubscribe:
		 * o13-2.1.1 - QPN Field need to be set when unsubscribing.
		 */
		ib_inform_info_set_qpn(p_ii,
				       cl_hton32(p_qp_ctx->qp_bind_hndl.qp_id.
						 qp_num));
	}

	osm_dump_inform_info(&p_osmt->log, p_ii, OSM_LOG_DEBUG);

	/* --------------------- PREP ------------------------- */
	if (osmt_mtl_mad_post_recv_bufs(&p_qp_ctx->qp_bind_hndl, p_qp_ctx->p_recv_buf, 1,	/*  but we need only one mad at a time */
					GRH_LEN + MAD_BLOCK_SIZE, wrid) != 1) {
		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0120: "
			"Error posting recv bufs\n");
		status = IB_ERROR;
		goto Exit;
	}
	OSM_LOG(p_log, OSM_LOG_DEBUG, "Posted recv bufs\n");

	vapi_ret =
	    osmt_mtl_create_av(&p_qp_ctx->qp_bind_hndl,
			       p_osmt->local_port.sm_lid, &avh);
	if (vapi_ret != VAPI_OK) {
		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0121: "
			"Error Preparing AVH (%s)\n",
			VAPI_strerror_sym(vapi_ret));
		status = IB_ERROR;
		goto Exit;
	}
	OSM_LOG(p_log, OSM_LOG_DEBUG, "Prepared AVH\n");

	if (osm_log_is_active(p_log, OSM_LOG_DEBUG)) {
		osm_dump_sa_mad(p_log, (ib_sa_mad_t *) (p_qp_ctx->p_send_buf),
				OSM_LOG_DEBUG);
#if 0
		for (i = 56; i < 253; i++) {
			if (i % 8 == 0) {
				printf("\n %d : ", i);
			}
			printf("0x%02X ", p_qp_ctx->p_send_buf[i]);
		}
#endif
		printf("\n");
	}

	/* --------------------- SEND ------------------------- */
	vapi_ret = osmt_mtl_mad_send(&p_qp_ctx->qp_bind_hndl, wrid, p_qp_ctx->p_send_buf, 1,	/*  SA is QP1 */
				     0,	/*  SL is 0 */
				     OSMT_MTL_REVERSE_QP1_WELL_KNOWN_Q_KEY,
				     avh);
	if (vapi_ret != VAPI_OK) {
		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0122: "
			"Error sending mad (%s)\n",
			VAPI_strerror_sym(vapi_ret));
		status = IB_ERROR;
		goto Exit;
	}

	vapi_ret = osmt_mtl_mad_poll4cqe(p_qp_ctx->qp_bind_hndl.hca_hndl,
					 p_qp_ctx->qp_bind_hndl.sq_cq_hndl,
					 &wc_desc, 20, 10000, NULL);
	if (vapi_ret != VAPI_OK) {
		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0123: "
			"Error getting send completion (%s)\n",
			VAPI_strerror_sym(vapi_ret));
		status = IB_ERROR;
		goto Exit;
	}

	if (wc_desc.status != VAPI_SUCCESS) {
		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0124: "
			"Error on send completion (%s) (%d)\n",
			VAPI_strerror_sym(wc_desc.status), wc_desc.status);
		status = IB_ERROR;
		goto Exit;
	}
	OSM_LOG(p_log, OSM_LOG_DEBUG, "Sent MAD\n");

	/* --------------------- RECV ------------------------- */
	vapi_ret = osmt_mtl_mad_poll4cqe(p_qp_ctx->qp_bind_hndl.hca_hndl,
					 p_qp_ctx->qp_bind_hndl.rq_cq_hndl,
					 &wc_desc, 20, 10000, &avh);
	if (vapi_ret != VAPI_SUCCESS) {
		if (vapi_ret == VAPI_CQ_EMPTY) {
			status = IB_TIMEOUT;
		} else {
			OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0125: "
				"Error receiving mad (%s)\n",
				VAPI_strerror_sym(vapi_ret));
			status = IB_ERROR;
		}
		goto Exit;
	}

	/* check to see if successful - by examination of the subscribe bit */
	p_sa_mad = (ib_sa_mad_t *) (p_qp_ctx->p_recv_buf + GRH_LEN);

	if (p_sa_mad->status != IB_SUCCESS) {
		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Remote error = %s\n",
			ib_get_mad_status_str((ib_mad_t *) p_sa_mad));
		status = IB_REMOTE_ERROR;
		goto Exit;
	}

	if (p_sa_mad->method != IB_MAD_METHOD_GET_RESP) {
		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
			"Expected IB_MAD_METHOD_GET_RESP but got:(%X)\n",
			p_sa_mad->method);
		status = IB_REMOTE_ERROR;
		goto Exit;
	}

	if (p_sa_mad->attr_id != IB_MAD_ATTR_INFORM_INFO) {
		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
			"Expected IB_MAD_ATTR_INFORM_INFO but got:(%X)\n",
			cl_ntoh16(p_sa_mad->attr_id));
		status = IB_REMOTE_ERROR;
		goto Exit;
	}

	p_ii = ib_sa_mad_get_payload_ptr(p_sa_mad);
	if (!p_ii->subscribe) {
		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0126: "
			"Subscribe/Unsubscribe Failed\n");
		status = IB_REMOTE_ERROR;
	}

Exit:
	OSM_LOG_EXIT(&p_osmt->log);
	return status;
}