10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
58442SLida.Horn@Sun.COM * Common Development and Distribution License (the "License").
68442SLida.Horn@Sun.COM * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
228523SLida.Horn@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate
270Sstevel@tonic-gate /*
280Sstevel@tonic-gate * This file implements the MAD receive logic in IBMF.
290Sstevel@tonic-gate */
300Sstevel@tonic-gate
310Sstevel@tonic-gate #include <sys/ib/mgt/ibmf/ibmf_impl.h>
320Sstevel@tonic-gate #include <sys/ib/mgt/ibmf/ibmf_saa_impl.h>
330Sstevel@tonic-gate
340Sstevel@tonic-gate extern ibmf_state_t *ibmf_statep;
350Sstevel@tonic-gate extern int ibmf_recv_wqes_per_port;
360Sstevel@tonic-gate extern int ibmf_send_wqes_posted_per_qp;
370Sstevel@tonic-gate extern int ibmf_recv_wqes_posted_per_qp;
380Sstevel@tonic-gate
390Sstevel@tonic-gate #define IBMF_RECV_WR_ID_TO_ADDR(id, ptr) \
400Sstevel@tonic-gate (ptr) = (void *)(uintptr_t)((uint64_t)(id) & ~IBMF_RCV_CQE)
410Sstevel@tonic-gate
420Sstevel@tonic-gate #define IBMF_QP0_NUM 0
430Sstevel@tonic-gate #define IBMF_QP1_NUM 1
440Sstevel@tonic-gate #define IBMF_BM_MAD_ATTR_MOD_REQRESP_BIT 0x00000001
450Sstevel@tonic-gate #define IBMF_BM_MAD_ATTR_MOD_RESP 0x1
460Sstevel@tonic-gate
470Sstevel@tonic-gate /*
480Sstevel@tonic-gate * Structure defintion of entries in the module names table
490Sstevel@tonic-gate */
500Sstevel@tonic-gate typedef struct _ibmf_mod_names_t {
510Sstevel@tonic-gate char mod_name[8];
520Sstevel@tonic-gate ibmf_client_type_t mgt_class;
530Sstevel@tonic-gate } ibmf_mod_names_t;
540Sstevel@tonic-gate
550Sstevel@tonic-gate typedef struct _ibmf_mod_load_args_t {
560Sstevel@tonic-gate ibmf_ci_t *cip;
570Sstevel@tonic-gate ibmf_recv_wqe_t *recv_wqep;
580Sstevel@tonic-gate char *modname;
590Sstevel@tonic-gate ibmf_client_type_t ibmf_class;
600Sstevel@tonic-gate } ibmf_mod_load_args_t;
610Sstevel@tonic-gate
620Sstevel@tonic-gate extern int ibmf_trace_level;
630Sstevel@tonic-gate extern int ibmf_send_wqes_posted_per_qp;
640Sstevel@tonic-gate extern int ibmf_recv_wqes_posted_per_qp;
650Sstevel@tonic-gate
660Sstevel@tonic-gate static void ibmf_i_do_recv_cb(void *taskq_arg);
670Sstevel@tonic-gate static int ibmf_i_repost_recv_buffer(ibmf_ci_t *cip,
680Sstevel@tonic-gate ibmf_recv_wqe_t *recv_wqep);
690Sstevel@tonic-gate static int ibmf_i_get_class(ib_mad_hdr_t *madhdrp,
700Sstevel@tonic-gate ibmf_qp_handle_t dest_ibmf_qp_handle, ib_lid_t slid,
710Sstevel@tonic-gate ibmf_client_type_t *dest_classp);
720Sstevel@tonic-gate static void ibmf_i_handle_non_rmpp(ibmf_client_t *clientp,
730Sstevel@tonic-gate ibmf_msg_impl_t *msgimplp, uchar_t *mad);
740Sstevel@tonic-gate static void ibmf_get_mod_name(uint8_t mad_class, ibmf_client_type_t class,
750Sstevel@tonic-gate char *modname);
760Sstevel@tonic-gate static void ibmf_module_load(void *taskq_arg);
770Sstevel@tonic-gate static void ibmf_send_busy(ibmf_mod_load_args_t *modlargsp);
780Sstevel@tonic-gate
790Sstevel@tonic-gate #define AGENT_CLASS(class) \
800Sstevel@tonic-gate (((class & 0x000F0000) == IBMF_AGENT_ID))
810Sstevel@tonic-gate #define MANAGER_CLASS(class) \
820Sstevel@tonic-gate (((class & 0x000F0000) == IBMF_MANAGER_ID))
830Sstevel@tonic-gate #define AGENT_MANAGER_CLASS(class) \
840Sstevel@tonic-gate (((class & 0x000F0000) == IBMF_AGENT_MANAGER_ID))
850Sstevel@tonic-gate #define IS_MANDATORY_CLASS(class) \
860Sstevel@tonic-gate ((class == PERF_AGENT) || (class == BM_AGENT))
870Sstevel@tonic-gate
880Sstevel@tonic-gate char ibmf_client_modname[16];
890Sstevel@tonic-gate
900Sstevel@tonic-gate /*
910Sstevel@tonic-gate * ibmf_i_handle_recv_completion():
920Sstevel@tonic-gate * Process the WQE from the RQ, obtain the management class of the
930Sstevel@tonic-gate * packet and retrieve the corresponding client context
940Sstevel@tonic-gate */
950Sstevel@tonic-gate void
ibmf_i_handle_recv_completion(ibmf_ci_t * cip,ibt_wc_t * wcp)960Sstevel@tonic-gate ibmf_i_handle_recv_completion(ibmf_ci_t *cip, ibt_wc_t *wcp)
970Sstevel@tonic-gate {
980Sstevel@tonic-gate int ret;
990Sstevel@tonic-gate ibmf_client_type_t class;
1000Sstevel@tonic-gate ibmf_client_t *clientp;
1010Sstevel@tonic-gate ib_mad_hdr_t *madhdrp;
1020Sstevel@tonic-gate ibmf_recv_wqe_t *recv_wqep;
1030Sstevel@tonic-gate ibt_recv_wr_t *rwrp;
1040Sstevel@tonic-gate ibmf_qp_handle_t ibmf_qp_handle;
1050Sstevel@tonic-gate struct kmem_cache *kmem_cachep;
1060Sstevel@tonic-gate ibmf_alt_qp_t *altqp;
1070Sstevel@tonic-gate
1080Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4,
1090Sstevel@tonic-gate ibmf_i_handle_recv_completion_start, IBMF_TNF_TRACE, "",
1100Sstevel@tonic-gate "ibmf_i_handle_recv_completion() enter, cip = %p, wcp = %p\n",
1110Sstevel@tonic-gate tnf_opaque, cip, cip, tnf_opaque, wcp, wcp);
1120Sstevel@tonic-gate
1130Sstevel@tonic-gate mutex_enter(&cip->ci_ud_dest_list_mutex);
1140Sstevel@tonic-gate if (cip->ci_ud_dest_list_count < IBMF_UD_DEST_LO_WATER_MARK) {
1150Sstevel@tonic-gate ret = ibmf_ud_dest_tq_disp(cip);
1160Sstevel@tonic-gate if (ret == 0) {
1170Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L3,
1180Sstevel@tonic-gate ibmf_i_handle_recv_completion_err, IBMF_TNF_ERROR,
1190Sstevel@tonic-gate "", "ibmf_i_handle_recv_completion(): %s\n",
1200Sstevel@tonic-gate tnf_string, msg, "taskq dispatch of ud_dest "
1210Sstevel@tonic-gate "population thread failed");
1220Sstevel@tonic-gate }
1230Sstevel@tonic-gate }
1240Sstevel@tonic-gate mutex_exit(&cip->ci_ud_dest_list_mutex);
1250Sstevel@tonic-gate
1260Sstevel@tonic-gate ASSERT(IBMF_IS_RECV_WR_ID(wcp->wc_id));
1270Sstevel@tonic-gate IBMF_RECV_WR_ID_TO_ADDR(wcp->wc_id, recv_wqep);
1280Sstevel@tonic-gate
1290Sstevel@tonic-gate rwrp = &recv_wqep->recv_wr;
1300Sstevel@tonic-gate
1310Sstevel@tonic-gate /* Retrieve the QP handle from the receive WQE context */
1320Sstevel@tonic-gate ibmf_qp_handle = recv_wqep->recv_ibmf_qp_handle;
1330Sstevel@tonic-gate
1340Sstevel@tonic-gate /* Get the WQE kmem cache pointer based on the QP type */
1350Sstevel@tonic-gate if (ibmf_qp_handle == IBMF_QP_HANDLE_DEFAULT) {
1360Sstevel@tonic-gate kmem_cachep = cip->ci_recv_wqes_cache;
1370Sstevel@tonic-gate } else {
1380Sstevel@tonic-gate altqp = (ibmf_alt_qp_t *)ibmf_qp_handle;
1390Sstevel@tonic-gate kmem_cachep = altqp->isq_recv_wqes_cache;
1400Sstevel@tonic-gate }
1410Sstevel@tonic-gate
1420Sstevel@tonic-gate /*
1430Sstevel@tonic-gate * if the wqe is being flushed due to shutting down of the qp, free
1440Sstevel@tonic-gate * the wqe and return.
1450Sstevel@tonic-gate */
1460Sstevel@tonic-gate if (wcp->wc_status == IBT_WC_WR_FLUSHED_ERR) {
1470Sstevel@tonic-gate kmem_free(rwrp->wr_sgl, IBMF_MAX_RQ_WR_SGL_ELEMENTS *
1480Sstevel@tonic-gate sizeof (ibt_wr_ds_t));
1490Sstevel@tonic-gate kmem_cache_free(kmem_cachep, recv_wqep);
1500Sstevel@tonic-gate mutex_enter(&cip->ci_mutex);
1510Sstevel@tonic-gate IBMF_SUB32_PORT_KSTATS(cip, recv_wqes_alloced, 1);
1520Sstevel@tonic-gate mutex_exit(&cip->ci_mutex);
1530Sstevel@tonic-gate if (ibmf_qp_handle == IBMF_QP_HANDLE_DEFAULT) {
1540Sstevel@tonic-gate mutex_enter(&cip->ci_mutex);
1550Sstevel@tonic-gate cip->ci_wqes_alloced--;
1560Sstevel@tonic-gate if (cip->ci_wqes_alloced == 0)
1570Sstevel@tonic-gate cv_signal(&cip->ci_wqes_cv);
1580Sstevel@tonic-gate mutex_exit(&cip->ci_mutex);
1590Sstevel@tonic-gate } else {
1600Sstevel@tonic-gate mutex_enter(&altqp->isq_mutex);
1610Sstevel@tonic-gate altqp->isq_wqes_alloced--;
1620Sstevel@tonic-gate if (altqp->isq_wqes_alloced == 0)
1630Sstevel@tonic-gate cv_signal(&altqp->isq_wqes_cv);
1640Sstevel@tonic-gate mutex_exit(&altqp->isq_mutex);
1650Sstevel@tonic-gate }
1660Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
1670Sstevel@tonic-gate ibmf_i_handle_recv_completion, IBMF_TNF_TRACE,
1680Sstevel@tonic-gate "", "ibmf_i_handle_recv_completion(): %s\n",
1690Sstevel@tonic-gate tnf_string, msg, "recv wqe flushed");
1700Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
1710Sstevel@tonic-gate ibmf_i_handle_recv_completion_end, IBMF_TNF_TRACE,
1720Sstevel@tonic-gate "", "ibmf_i_handle_recv_completion() exit\n");
1730Sstevel@tonic-gate return;
1740Sstevel@tonic-gate }
1750Sstevel@tonic-gate
1760Sstevel@tonic-gate /*
1770Sstevel@tonic-gate * Dynamic Posting of WQEs to the Receive Queue (RQ) of the QP:
1780Sstevel@tonic-gate * If the number of RQ WQEs posted to the QP drops below half
1790Sstevel@tonic-gate * the initial number of RQ WQEs posted to the QP, then, one additional
1800Sstevel@tonic-gate * WQE is posted to the RQ of the QP while processing this CQE.
1810Sstevel@tonic-gate */
1820Sstevel@tonic-gate if (ibmf_qp_handle == IBMF_QP_HANDLE_DEFAULT) {
1830Sstevel@tonic-gate ibmf_qp_t *qpp = recv_wqep->recv_qpp;
1840Sstevel@tonic-gate
1850Sstevel@tonic-gate mutex_enter(&qpp->iq_mutex);
1860Sstevel@tonic-gate qpp->iq_rwqes_posted--;
1870Sstevel@tonic-gate if (qpp->iq_rwqes_posted <= (ibmf_recv_wqes_per_port >> 1)) {
1880Sstevel@tonic-gate mutex_exit(&qpp->iq_mutex);
1890Sstevel@tonic-gate
1900Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3,
1910Sstevel@tonic-gate ibmf_i_handle_recv_compl, IBMF_TNF_TRACE, "",
1920Sstevel@tonic-gate "ibmf_i_handle_recv_compl(): %s, "
1930Sstevel@tonic-gate "QP# = %d\n", tnf_string, msg,
1940Sstevel@tonic-gate "Posting more RQ WQEs",
1950Sstevel@tonic-gate tnf_int, qpnum, qpp->iq_qp_num);
1960Sstevel@tonic-gate
1970Sstevel@tonic-gate /* Post an additional WQE to the RQ */
1980Sstevel@tonic-gate ret = ibmf_i_post_recv_buffer(cip, qpp,
1990Sstevel@tonic-gate B_FALSE, ibmf_qp_handle);
2000Sstevel@tonic-gate if (ret != IBMF_SUCCESS) {
2018442SLida.Horn@Sun.COM IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3,
2028442SLida.Horn@Sun.COM ibmf_i_handle_recv_compl, IBMF_TNF_TRACE,
2038442SLida.Horn@Sun.COM "", "ibmf_i_handle_recv_compl(): %s, "
2048442SLida.Horn@Sun.COM "status = %d\n", tnf_string, msg,
2058442SLida.Horn@Sun.COM "ibmf_i_post_recv_buffer() failed",
2068442SLida.Horn@Sun.COM tnf_int, status, ret);
2070Sstevel@tonic-gate }
2080Sstevel@tonic-gate
2090Sstevel@tonic-gate mutex_enter(&qpp->iq_mutex);
2100Sstevel@tonic-gate }
2110Sstevel@tonic-gate mutex_exit(&qpp->iq_mutex);
2120Sstevel@tonic-gate } else {
2130Sstevel@tonic-gate mutex_enter(&altqp->isq_mutex);
2140Sstevel@tonic-gate altqp->isq_rwqes_posted--;
2150Sstevel@tonic-gate if (altqp->isq_rwqes_posted <= (ibmf_recv_wqes_per_port >> 1)) {
2160Sstevel@tonic-gate mutex_exit(&altqp->isq_mutex);
2170Sstevel@tonic-gate
2180Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3,
2190Sstevel@tonic-gate ibmf_i_handle_recv_compl, IBMF_TNF_TRACE, "",
2200Sstevel@tonic-gate "ibmf_i_handle_recv_compl(): %s, "
2210Sstevel@tonic-gate "QP# = %d\n", tnf_string, msg,
2220Sstevel@tonic-gate "Posting more RQ WQEs",
2230Sstevel@tonic-gate tnf_int, qpnum, altqp->isq_qpn);
2240Sstevel@tonic-gate
2250Sstevel@tonic-gate /* Post an additional WQE to the RQ */
2260Sstevel@tonic-gate ret = ibmf_i_post_recv_buffer(cip, NULL,
2270Sstevel@tonic-gate B_FALSE, ibmf_qp_handle);
2280Sstevel@tonic-gate if (ret != IBMF_SUCCESS) {
2298442SLida.Horn@Sun.COM IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3,
2308442SLida.Horn@Sun.COM ibmf_i_handle_recv_compl, IBMF_TNF_TRACE,
2318442SLida.Horn@Sun.COM "", "ibmf_i_handle_recv_compl(): %s, "
2328442SLida.Horn@Sun.COM "status = %d\n", tnf_string, msg,
2338442SLida.Horn@Sun.COM "ibmf_i_post_recv_buffer() failed",
2348442SLida.Horn@Sun.COM tnf_int, status, ret);
2350Sstevel@tonic-gate }
2360Sstevel@tonic-gate
2370Sstevel@tonic-gate mutex_enter(&altqp->isq_mutex);
2380Sstevel@tonic-gate }
2390Sstevel@tonic-gate mutex_exit(&altqp->isq_mutex);
2400Sstevel@tonic-gate }
2410Sstevel@tonic-gate
2420Sstevel@tonic-gate /*
2430Sstevel@tonic-gate * for all other completion errors, repost the wqe, and if that
2440Sstevel@tonic-gate * fails, free the wqe and return.
2450Sstevel@tonic-gate */
2460Sstevel@tonic-gate if (wcp->wc_status != IBT_WC_SUCCESS) {
2470Sstevel@tonic-gate (void) ibmf_i_repost_recv_buffer(cip, recv_wqep);
2480Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
2490Sstevel@tonic-gate ibmf_i_handle_recv_completion_err, IBMF_TNF_ERROR,
2500Sstevel@tonic-gate "", "ibmf_i_handle_recv_completion(): %s, wc_status = %d\n",
2510Sstevel@tonic-gate tnf_string, msg, "bad completion status received",
2520Sstevel@tonic-gate tnf_uint, wc_status, wcp->wc_status);
2530Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
2540Sstevel@tonic-gate ibmf_i_handle_recv_completion_end, IBMF_TNF_TRACE,
2550Sstevel@tonic-gate "", "ibmf_i_handle_recv_completion() exit\n");
2560Sstevel@tonic-gate return;
2570Sstevel@tonic-gate }
2580Sstevel@tonic-gate
2590Sstevel@tonic-gate /* find the client corresponding to this recv cqe */
2600Sstevel@tonic-gate madhdrp = (ib_mad_hdr_t *)((uintptr_t)recv_wqep->recv_mem +
2610Sstevel@tonic-gate sizeof (ib_grh_t));
2620Sstevel@tonic-gate
2630Sstevel@tonic-gate /* drop packet if MAD Base Version is not as expected */
2640Sstevel@tonic-gate if (madhdrp->BaseVersion != MAD_CLASS_BASE_VERS_1) {
2650Sstevel@tonic-gate (void) ibmf_i_repost_recv_buffer(cip, recv_wqep);
2660Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
2670Sstevel@tonic-gate ibmf_i_handle_recv_completion_err, IBMF_TNF_ERROR,
2680Sstevel@tonic-gate "", "ibmf_i_handle_recv_completion(): %s\n",
2690Sstevel@tonic-gate tnf_string, msg, "bad MAD version");
2700Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
2710Sstevel@tonic-gate ibmf_i_handle_recv_completion_end, IBMF_TNF_TRACE,
2720Sstevel@tonic-gate "", "ibmf_i_handle_recv_completion() exit\n");
2730Sstevel@tonic-gate return;
2740Sstevel@tonic-gate }
2750Sstevel@tonic-gate
2760Sstevel@tonic-gate if (ibmf_i_get_class(madhdrp, recv_wqep->recv_ibmf_qp_handle,
2770Sstevel@tonic-gate wcp->wc_slid, &class) != IBMF_SUCCESS) {
2780Sstevel@tonic-gate /* bad class & type? */
2790Sstevel@tonic-gate #ifdef DEBUG
2800Sstevel@tonic-gate ibmf_i_dump_wcp(cip, wcp, recv_wqep);
2810Sstevel@tonic-gate #endif
2820Sstevel@tonic-gate (void) ibmf_i_repost_recv_buffer(cip, recv_wqep);
2830Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
2840Sstevel@tonic-gate ibmf_i_handle_recv_completion_err, IBMF_TNF_ERROR,
2850Sstevel@tonic-gate "", "ibmf_i_handle_recv_completion(): %s\n",
2860Sstevel@tonic-gate tnf_string, msg, "bad class/type");
2870Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
2880Sstevel@tonic-gate ibmf_i_handle_recv_completion_end, IBMF_TNF_TRACE,
2890Sstevel@tonic-gate "", "ibmf_i_handle_recv_completion() exit\n");
2900Sstevel@tonic-gate return;
2910Sstevel@tonic-gate }
2920Sstevel@tonic-gate
2930Sstevel@tonic-gate ret = ibmf_i_lookup_client_by_mgmt_class(cip, recv_wqep->recv_port_num,
2940Sstevel@tonic-gate class, &clientp);
2950Sstevel@tonic-gate if (ret == IBMF_SUCCESS) {
2960Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*recv_wqep))
2970Sstevel@tonic-gate recv_wqep->recv_client = clientp;
2980Sstevel@tonic-gate recv_wqep->recv_wc = *wcp; /* struct copy */
2990Sstevel@tonic-gate
3000Sstevel@tonic-gate /*
3010Sstevel@tonic-gate * Increment the kstats for the number of active receiver side
3020Sstevel@tonic-gate * callbacks
3030Sstevel@tonic-gate */
3040Sstevel@tonic-gate mutex_enter(&clientp->ic_kstat_mutex);
3050Sstevel@tonic-gate IBMF_ADD32_KSTATS(clientp, recv_cb_active, 1);
3060Sstevel@tonic-gate mutex_exit(&clientp->ic_kstat_mutex);
3070Sstevel@tonic-gate
3080Sstevel@tonic-gate if ((clientp->ic_reg_flags & IBMF_REG_FLAG_NO_OFFLOAD) == 0) {
3090Sstevel@tonic-gate /* Dispatch the taskq thread to do further processing */
3100Sstevel@tonic-gate ret = taskq_dispatch(clientp->ic_recv_taskq,
3110Sstevel@tonic-gate ibmf_i_do_recv_cb, recv_wqep, TQ_NOSLEEP);
3120Sstevel@tonic-gate if (ret == 0) {
3130Sstevel@tonic-gate mutex_enter(&clientp->ic_kstat_mutex);
3140Sstevel@tonic-gate IBMF_SUB32_KSTATS(clientp, recv_cb_active, 1);
3150Sstevel@tonic-gate mutex_exit(&clientp->ic_kstat_mutex);
3160Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
3170Sstevel@tonic-gate ibmf_i_handle_recv_completion_err,
3180Sstevel@tonic-gate IBMF_TNF_ERROR, "",
3190Sstevel@tonic-gate "ibmf_i_handle_recv_completion(): %s\n",
3200Sstevel@tonic-gate tnf_string, msg, "dispatch failed");
3210Sstevel@tonic-gate (void) ibmf_i_repost_recv_buffer(cip,
3220Sstevel@tonic-gate recv_wqep);
3230Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
3240Sstevel@tonic-gate ibmf_i_handle_recv_completion_end,
3250Sstevel@tonic-gate IBMF_TNF_TRACE, "",
3260Sstevel@tonic-gate "ibmf_i_handle_recv_completion() exit\n");
3270Sstevel@tonic-gate return;
3280Sstevel@tonic-gate }
3290Sstevel@tonic-gate } else {
3300Sstevel@tonic-gate ibmf_i_do_recv_cb((void *)recv_wqep);
3310Sstevel@tonic-gate }
3320Sstevel@tonic-gate
3330Sstevel@tonic-gate /*
3340Sstevel@tonic-gate * Decrement the kstats for the number of active receiver side
3350Sstevel@tonic-gate * callbacks
3360Sstevel@tonic-gate */
3370Sstevel@tonic-gate mutex_enter(&clientp->ic_kstat_mutex);
3380Sstevel@tonic-gate IBMF_SUB32_KSTATS(clientp, recv_cb_active, 1);
3390Sstevel@tonic-gate mutex_exit(&clientp->ic_kstat_mutex);
3400Sstevel@tonic-gate
3410Sstevel@tonic-gate } else {
3420Sstevel@tonic-gate /*
3430Sstevel@tonic-gate * A client has not registered to receive MADs of this
3440Sstevel@tonic-gate * management class. IBMF must attempt to load the
3450Sstevel@tonic-gate * client and request a resend of the request MAD.
3460Sstevel@tonic-gate * The name of the client MAD is derived using a
3470Sstevel@tonic-gate * convention described in PSARC case 2003/753.
3480Sstevel@tonic-gate */
3490Sstevel@tonic-gate
3500Sstevel@tonic-gate ibmf_mod_load_args_t *modlargsp;
3510Sstevel@tonic-gate
352*9879SRamaswamy.Tummala@Sun.COM /*
353*9879SRamaswamy.Tummala@Sun.COM * HCA driver handles the Performance management
354*9879SRamaswamy.Tummala@Sun.COM * class MAD's. It registers with the IBMF during early
355*9879SRamaswamy.Tummala@Sun.COM * boot and unregisters during detach and during
356*9879SRamaswamy.Tummala@Sun.COM * HCA unconfigure operation. We come here
357*9879SRamaswamy.Tummala@Sun.COM * 1. Before HCA registers with IBMF
358*9879SRamaswamy.Tummala@Sun.COM * Drop the MAD. Since this is a UD MAD,
359*9879SRamaswamy.Tummala@Sun.COM * sender will resend the request
360*9879SRamaswamy.Tummala@Sun.COM * 2. After HCA unregistered with IBMF during DR operation.
361*9879SRamaswamy.Tummala@Sun.COM * Since HCA is going away, we can safely drop the PMA
362*9879SRamaswamy.Tummala@Sun.COM * MAD's here.
363*9879SRamaswamy.Tummala@Sun.COM * Solaris does not support BM_AGENT and so drop the BM MAD's
364*9879SRamaswamy.Tummala@Sun.COM */
365*9879SRamaswamy.Tummala@Sun.COM if ((class == PERF_AGENT) || (class == BM_AGENT)) {
366*9879SRamaswamy.Tummala@Sun.COM (void) ibmf_i_repost_recv_buffer(cip, recv_wqep);
367*9879SRamaswamy.Tummala@Sun.COM return;
368*9879SRamaswamy.Tummala@Sun.COM }
369*9879SRamaswamy.Tummala@Sun.COM
3700Sstevel@tonic-gate recv_wqep->recv_wc = *wcp; /* struct copy */
3710Sstevel@tonic-gate
3720Sstevel@tonic-gate IBMF_TRACE_3(IBMF_TNF_NODEBUG, DPRINT_L4,
3730Sstevel@tonic-gate ibmf_i_handle_recv_completion_err, IBMF_TNF_ERROR, "",
3740Sstevel@tonic-gate "ibmf_i_handle_recv_completion(): %s, port = %d, "
3750Sstevel@tonic-gate "class = 0x%x\n",
3760Sstevel@tonic-gate tnf_string, msg, "no client registered", tnf_uint, port,
3770Sstevel@tonic-gate recv_wqep->recv_port_num, tnf_opaque, class, class);
3780Sstevel@tonic-gate
3790Sstevel@tonic-gate /* Construct the IBMF client module name */
3800Sstevel@tonic-gate ibmf_get_mod_name(madhdrp->MgmtClass, class,
3810Sstevel@tonic-gate ibmf_client_modname);
3820Sstevel@tonic-gate
3830Sstevel@tonic-gate /* Load the module using a taskq thread */
3840Sstevel@tonic-gate modlargsp = (ibmf_mod_load_args_t *)kmem_zalloc(
3850Sstevel@tonic-gate sizeof (ibmf_mod_load_args_t), KM_NOSLEEP);
3860Sstevel@tonic-gate if (modlargsp != NULL) {
3870Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*modlargsp))
3880Sstevel@tonic-gate modlargsp->cip = cip;
3890Sstevel@tonic-gate modlargsp->recv_wqep = recv_wqep;
3900Sstevel@tonic-gate modlargsp->modname = ibmf_client_modname;
3910Sstevel@tonic-gate modlargsp->ibmf_class = class;
3920Sstevel@tonic-gate ret = taskq_dispatch(ibmf_statep->ibmf_taskq,
3930Sstevel@tonic-gate ibmf_module_load, modlargsp, TQ_NOSLEEP);
3940Sstevel@tonic-gate if (ret == 0) {
3950Sstevel@tonic-gate kmem_free(modlargsp,
3960Sstevel@tonic-gate sizeof (ibmf_mod_load_args_t));
3970Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
3980Sstevel@tonic-gate ibmf_i_handle_recv_completion_error,
3990Sstevel@tonic-gate IBMF_TNF_TRACE, "",
4000Sstevel@tonic-gate "ibmf_i_handle_recv_completion(): Failed "
4010Sstevel@tonic-gate "to dispatch ibmf_module_load taskq\n");
4020Sstevel@tonic-gate (void) ibmf_i_repost_recv_buffer(cip,
4030Sstevel@tonic-gate recv_wqep);
4040Sstevel@tonic-gate }
4050Sstevel@tonic-gate } else {
4060Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
4070Sstevel@tonic-gate ibmf_i_handle_recv_completion_end, IBMF_TNF_TRACE,
4080Sstevel@tonic-gate "", "ibmf_i_handle_recv_completion(): "
4090Sstevel@tonic-gate "Failed to allocate memory for modlargs\n");
4100Sstevel@tonic-gate (void) ibmf_i_repost_recv_buffer(cip, recv_wqep);
4110Sstevel@tonic-gate }
4120Sstevel@tonic-gate }
4130Sstevel@tonic-gate
4140Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
4150Sstevel@tonic-gate ibmf_i_handle_recv_completion_end, IBMF_TNF_TRACE, "",
4160Sstevel@tonic-gate "ibmf_i_handle_recv_completion() exit\n");
4170Sstevel@tonic-gate }
4180Sstevel@tonic-gate
4190Sstevel@tonic-gate /*
4200Sstevel@tonic-gate * ibmf_i_do_recv_cb():
4210Sstevel@tonic-gate * This routine does the following:
4220Sstevel@tonic-gate * o looks for a message in the client's message list
4230Sstevel@tonic-gate * o creates a new message if one does not exist for unsolicited data
4240Sstevel@tonic-gate * o invoke routines to do specific handling for rmpp and non-rmpp cases
4250Sstevel@tonic-gate * o on a failure, the receive WQE is reposted to the RQ
4260Sstevel@tonic-gate */
4270Sstevel@tonic-gate static void
ibmf_i_do_recv_cb(void * taskq_arg)4280Sstevel@tonic-gate ibmf_i_do_recv_cb(void *taskq_arg)
4290Sstevel@tonic-gate {
4300Sstevel@tonic-gate ibt_wc_t *wcp;
4310Sstevel@tonic-gate ibmf_msg_impl_t *msgimplp;
4320Sstevel@tonic-gate ibmf_client_t *clientp;
4330Sstevel@tonic-gate ibmf_addr_info_t addrinfo;
4340Sstevel@tonic-gate ibmf_recv_wqe_t *recv_wqep;
4350Sstevel@tonic-gate ib_grh_t *ib_grh;
4360Sstevel@tonic-gate boolean_t grhpresent;
4370Sstevel@tonic-gate ibmf_qp_handle_t ibmf_qp_handle;
4380Sstevel@tonic-gate ib_mad_hdr_t *mad_hdr;
4390Sstevel@tonic-gate ibmf_rmpp_hdr_t *rmpp_hdr;
4400Sstevel@tonic-gate ibmf_alt_qp_t *qpp;
4410Sstevel@tonic-gate ib_gid_t gid;
4420Sstevel@tonic-gate ib_lid_t lid;
4430Sstevel@tonic-gate int msg_trans_state_flags, msg_flags;
4440Sstevel@tonic-gate uint_t ref_cnt;
4450Sstevel@tonic-gate timeout_id_t msg_rp_unset_id, msg_tr_unset_id;
4460Sstevel@tonic-gate timeout_id_t msg_rp_set_id, msg_tr_set_id;
4470Sstevel@tonic-gate int status;
4480Sstevel@tonic-gate saa_port_t *saa_portp;
4490Sstevel@tonic-gate
4500Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*recv_wqep))
4510Sstevel@tonic-gate
4520Sstevel@tonic-gate /* The taskq_arg argument is a pointer to the receive WQE context */
4530Sstevel@tonic-gate recv_wqep = taskq_arg;
4540Sstevel@tonic-gate
4550Sstevel@tonic-gate /* Retrieve the QP handle from the receive WQE context */
4560Sstevel@tonic-gate ibmf_qp_handle = recv_wqep->recv_ibmf_qp_handle;
4570Sstevel@tonic-gate
4580Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4,
4590Sstevel@tonic-gate ibmf_i_do_recv_cb_start, IBMF_TNF_TRACE, "",
4600Sstevel@tonic-gate "ibmf_i_do_recv_cb() enter, recv_wqep = %p\n",
4610Sstevel@tonic-gate tnf_opaque, recv_wqep, recv_wqep);
4620Sstevel@tonic-gate
4630Sstevel@tonic-gate /* Retrieve the client context pointer from the receive WQE context */
4640Sstevel@tonic-gate clientp = recv_wqep->recv_client;
4650Sstevel@tonic-gate
4660Sstevel@tonic-gate /* Get a pointer to the IBT work completion structure */
4670Sstevel@tonic-gate wcp = &recv_wqep->recv_wc;
4680Sstevel@tonic-gate
4690Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*wcp))
4700Sstevel@tonic-gate
4710Sstevel@tonic-gate /*
4720Sstevel@tonic-gate * Identify the port by the LID or GID depending on whether the
4730Sstevel@tonic-gate * Global Route Header is valid or not
4740Sstevel@tonic-gate */
4750Sstevel@tonic-gate if (wcp->wc_flags & IBT_WC_GRH_PRESENT) {
4760Sstevel@tonic-gate grhpresent = B_TRUE;
4770Sstevel@tonic-gate ib_grh = (ib_grh_t *)recv_wqep->recv_mem;
4780Sstevel@tonic-gate gid.gid_prefix = b2h64(ib_grh->SGID.gid_prefix);
4790Sstevel@tonic-gate gid.gid_guid = b2h64(ib_grh->SGID.gid_guid);
4800Sstevel@tonic-gate } else {
4810Sstevel@tonic-gate grhpresent = B_FALSE;
4820Sstevel@tonic-gate lid = wcp->wc_slid;
4830Sstevel@tonic-gate }
4840Sstevel@tonic-gate
4850Sstevel@tonic-gate /* Get a pointer to the MAD header */
4860Sstevel@tonic-gate mad_hdr = (ib_mad_hdr_t *)((uintptr_t)recv_wqep->recv_mem +
4870Sstevel@tonic-gate sizeof (ib_grh_t));
4880Sstevel@tonic-gate
4890Sstevel@tonic-gate /* Get a pointer to the RMPP header */
4900Sstevel@tonic-gate rmpp_hdr = (ibmf_rmpp_hdr_t *)((uintptr_t)recv_wqep->recv_mem +
4910Sstevel@tonic-gate sizeof (ib_grh_t) + sizeof (ib_mad_hdr_t));
4920Sstevel@tonic-gate
4930Sstevel@tonic-gate IBMF_TRACE_5(IBMF_TNF_DEBUG, DPRINT_L3,
4940Sstevel@tonic-gate ibmf_i_do_recv_cb, IBMF_TNF_TRACE, "",
4950Sstevel@tonic-gate "ibmf_i_do_recv_cb(): %s, tid = %016" PRIx64 ", class = 0x%x, "
4960Sstevel@tonic-gate "attrID = 0x%x, lid = 0x%x\n",
4970Sstevel@tonic-gate tnf_string, msg, "Received MAD", tnf_opaque, tid,
4980Sstevel@tonic-gate b2h64(mad_hdr->TransactionID), tnf_opaque, class,
4990Sstevel@tonic-gate mad_hdr->MgmtClass, tnf_opaque, attr_id,
5000Sstevel@tonic-gate b2h16(mad_hdr->AttributeID), tnf_opaque, remote_lid, lid);
5010Sstevel@tonic-gate
5020Sstevel@tonic-gate /*
5030Sstevel@tonic-gate * Look for the matching message in the client's message list
5040Sstevel@tonic-gate * NOTE: if the message is found, the message reference count will
5050Sstevel@tonic-gate * have been increased by 1.
5060Sstevel@tonic-gate */
5070Sstevel@tonic-gate msgimplp = ibmf_i_find_msg(clientp, b2h64(mad_hdr->TransactionID),
5080Sstevel@tonic-gate mad_hdr->MgmtClass, mad_hdr->R_Method, lid, &gid, grhpresent,
5090Sstevel@tonic-gate rmpp_hdr, IBMF_REG_MSG_LIST);
5100Sstevel@tonic-gate
5110Sstevel@tonic-gate /*
5120Sstevel@tonic-gate * If the message is not on the regular message list, search
5130Sstevel@tonic-gate * for it in the termination message list.
5140Sstevel@tonic-gate */
5150Sstevel@tonic-gate if (msgimplp == NULL) {
5160Sstevel@tonic-gate msgimplp = ibmf_i_find_msg(clientp,
5170Sstevel@tonic-gate b2h64(mad_hdr->TransactionID), mad_hdr->MgmtClass,
5180Sstevel@tonic-gate mad_hdr->R_Method, lid, &gid, grhpresent, rmpp_hdr,
5190Sstevel@tonic-gate IBMF_TERM_MSG_LIST);
5200Sstevel@tonic-gate }
5210Sstevel@tonic-gate
5220Sstevel@tonic-gate if (msgimplp != NULL) {
5230Sstevel@tonic-gate
5240Sstevel@tonic-gate /* if this packet is from the SA */
5250Sstevel@tonic-gate if (clientp->ic_client_info.client_class == SUBN_ADM_MANAGER) {
5260Sstevel@tonic-gate
5270Sstevel@tonic-gate /*
5280Sstevel@tonic-gate * ibmf_saa's callback arg is its saa_portp;
5290Sstevel@tonic-gate * take advantage of this fact to quickly update the
5300Sstevel@tonic-gate * port's SA uptime. ibmf_saa uses the up time to
5310Sstevel@tonic-gate * determine if the SA is still alive
5320Sstevel@tonic-gate */
5330Sstevel@tonic-gate saa_portp = clientp->ic_async_cb_arg;
5340Sstevel@tonic-gate
5350Sstevel@tonic-gate /* update the SA uptime */
5360Sstevel@tonic-gate mutex_enter(&saa_portp->saa_pt_mutex);
5370Sstevel@tonic-gate
5380Sstevel@tonic-gate saa_portp->saa_pt_sa_uptime = gethrtime();
5390Sstevel@tonic-gate
5400Sstevel@tonic-gate mutex_exit(&saa_portp->saa_pt_mutex);
5410Sstevel@tonic-gate }
5420Sstevel@tonic-gate
5430Sstevel@tonic-gate mutex_enter(&msgimplp->im_mutex);
5440Sstevel@tonic-gate
5450Sstevel@tonic-gate /*
5460Sstevel@tonic-gate * Clear timers for transactions of solicited incoming packets
5470Sstevel@tonic-gate */
5480Sstevel@tonic-gate if (msgimplp->im_rp_timeout_id != 0) {
5490Sstevel@tonic-gate ibmf_i_unset_timer(msgimplp, IBMF_RESP_TIMER);
5500Sstevel@tonic-gate }
5510Sstevel@tonic-gate
5520Sstevel@tonic-gate /*
5530Sstevel@tonic-gate * If a MAD is received in the middle of an RMPP receive
5540Sstevel@tonic-gate * transaction, and the MAD's RMPPFlags.Active bit is 0,
5550Sstevel@tonic-gate * drop the MAD
5560Sstevel@tonic-gate */
5570Sstevel@tonic-gate if (ibmf_i_is_rmpp(clientp, ibmf_qp_handle) &&
5580Sstevel@tonic-gate (msgimplp->im_flags & IBMF_MSG_FLAGS_RECV_RMPP) &&
5590Sstevel@tonic-gate ((rmpp_hdr->rmpp_flags & IBMF_RMPP_FLAGS_ACTIVE) == 0)) {
5600Sstevel@tonic-gate mutex_exit(&msgimplp->im_mutex);
5610Sstevel@tonic-gate (void) ibmf_i_repost_recv_buffer(clientp->ic_myci,
5620Sstevel@tonic-gate recv_wqep);
5630Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L3,
5640Sstevel@tonic-gate ibmf_i_do_recv_cb_error, IBMF_TNF_ERROR, "",
5650Sstevel@tonic-gate "ibmf_i_do_recv_cb(): %s, msg = %p\n",
5660Sstevel@tonic-gate tnf_string, msg,
5670Sstevel@tonic-gate "Non-RMPP MAD received in RMPP transaction, "
5680Sstevel@tonic-gate "dropping MAD", tnf_opaque, msgimplp, msgimplp);
5690Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
5700Sstevel@tonic-gate ibmf_i_do_recv_cb_end, IBMF_TNF_TRACE, "",
5710Sstevel@tonic-gate "ibmf_i_do_recv_cb() exit\n");
5720Sstevel@tonic-gate return;
5730Sstevel@tonic-gate }
5740Sstevel@tonic-gate
5750Sstevel@tonic-gate /*
5760Sstevel@tonic-gate * If the message has been marked unitialized or done
5770Sstevel@tonic-gate * release the message mutex and return
5780Sstevel@tonic-gate */
5790Sstevel@tonic-gate if ((msgimplp->im_trans_state_flags &
5800Sstevel@tonic-gate IBMF_TRANS_STATE_FLAG_DONE) ||
5810Sstevel@tonic-gate (msgimplp->im_trans_state_flags &
5820Sstevel@tonic-gate IBMF_TRANS_STATE_FLAG_UNINIT)) {
5830Sstevel@tonic-gate IBMF_MSG_DECR_REFCNT(msgimplp);
5840Sstevel@tonic-gate msg_trans_state_flags = msgimplp->im_trans_state_flags;
5850Sstevel@tonic-gate msg_flags = msgimplp->im_flags;
5860Sstevel@tonic-gate ref_cnt = msgimplp->im_ref_count;
5870Sstevel@tonic-gate mutex_exit(&msgimplp->im_mutex);
5880Sstevel@tonic-gate (void) ibmf_i_repost_recv_buffer(clientp->ic_myci,
5890Sstevel@tonic-gate recv_wqep);
5900Sstevel@tonic-gate /*
5910Sstevel@tonic-gate * This thread may notify the client only if the
5920Sstevel@tonic-gate * transaction is done, the message has been removed
5930Sstevel@tonic-gate * from the client's message list, and the message
5940Sstevel@tonic-gate * reference count is 0.
5950Sstevel@tonic-gate * If the transaction is done, and the message reference
5960Sstevel@tonic-gate * count = 0, there is still a possibility that a
5970Sstevel@tonic-gate * packet could arrive for the message and its reference
5980Sstevel@tonic-gate * count increased if the message is still on the list.
5990Sstevel@tonic-gate * If the message is still on the list, it will be
6000Sstevel@tonic-gate * removed by a call to ibmf_i_client_rem_msg() at
6010Sstevel@tonic-gate * the completion point of the transaction.
6020Sstevel@tonic-gate * So, the reference count should be checked after the
6030Sstevel@tonic-gate * message has been removed.
6040Sstevel@tonic-gate */
6050Sstevel@tonic-gate if ((msg_trans_state_flags &
6060Sstevel@tonic-gate IBMF_TRANS_STATE_FLAG_DONE) &&
6070Sstevel@tonic-gate !(msg_flags & IBMF_MSG_FLAGS_ON_LIST) &&
6080Sstevel@tonic-gate (ref_cnt == 0)) {
6090Sstevel@tonic-gate
6100Sstevel@tonic-gate ibmf_i_notify_sequence(clientp, msgimplp,
6110Sstevel@tonic-gate msg_flags);
6120Sstevel@tonic-gate
6130Sstevel@tonic-gate }
6140Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L3,
6150Sstevel@tonic-gate ibmf_i_do_recv_cb_error, IBMF_TNF_ERROR, "",
6160Sstevel@tonic-gate "ibmf_i_do_recv_cb(): %s, msg = %p\n",
6170Sstevel@tonic-gate tnf_string, msg,
6180Sstevel@tonic-gate "Message already marked for removal, dropping MAD",
6190Sstevel@tonic-gate tnf_opaque, msgimplp, msgimplp);
6200Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
6210Sstevel@tonic-gate ibmf_i_do_recv_cb_end, IBMF_TNF_TRACE, "",
6220Sstevel@tonic-gate "ibmf_i_do_recv_cb() exit\n");
6230Sstevel@tonic-gate return;
6240Sstevel@tonic-gate }
6250Sstevel@tonic-gate } else {
6260Sstevel@tonic-gate /* unsolicited message packet */
6270Sstevel@tonic-gate
6280Sstevel@tonic-gate /*
6290Sstevel@tonic-gate * Check if the client context, the alternate QP context
6300Sstevel@tonic-gate * (if not the default QP), and the incoming MAD support RMPP
6310Sstevel@tonic-gate */
6320Sstevel@tonic-gate if (ibmf_i_is_rmpp(clientp, ibmf_qp_handle) &&
6330Sstevel@tonic-gate (rmpp_hdr->rmpp_flags & IBMF_RMPP_FLAGS_ACTIVE)) {
6340Sstevel@tonic-gate
6350Sstevel@tonic-gate /* Only unsolicited packets should be data seg 1 */
6360Sstevel@tonic-gate if ((rmpp_hdr->rmpp_flags &
6370Sstevel@tonic-gate IBMF_RMPP_FLAGS_FIRST_PKT) == 0) {
6380Sstevel@tonic-gate (void) ibmf_i_repost_recv_buffer(
6390Sstevel@tonic-gate clientp->ic_myci, recv_wqep);
6400Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L3,
6410Sstevel@tonic-gate ibmf_i_do_recv_cb_error, IBMF_TNF_TRACE, "",
6420Sstevel@tonic-gate "ibmf_i_do_recv_cb(): %s\n",
6430Sstevel@tonic-gate tnf_string, msg,
6440Sstevel@tonic-gate "unsolicited rmpp packet not first packet");
6450Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
6460Sstevel@tonic-gate ibmf_i_do_recv_cb_end, IBMF_TNF_TRACE, "",
6470Sstevel@tonic-gate "ibmf_i_do_recv_cb() exit\n");
6480Sstevel@tonic-gate return;
6490Sstevel@tonic-gate }
6500Sstevel@tonic-gate }
6510Sstevel@tonic-gate
6520Sstevel@tonic-gate /*
6530Sstevel@tonic-gate * Before we alloc a message context, check to see if
6540Sstevel@tonic-gate * a callback has been registered with the client
6550Sstevel@tonic-gate * for this unsolicited message.
6560Sstevel@tonic-gate * If one has been registered, increment the recvs active
6570Sstevel@tonic-gate * count to get the teardown routine to wait until
6580Sstevel@tonic-gate * this callback is complete.
6590Sstevel@tonic-gate */
6600Sstevel@tonic-gate if (ibmf_qp_handle == IBMF_QP_HANDLE_DEFAULT) {
6610Sstevel@tonic-gate
6620Sstevel@tonic-gate mutex_enter(&clientp->ic_mutex);
6630Sstevel@tonic-gate if (clientp->ic_recv_cb == NULL) {
6640Sstevel@tonic-gate mutex_exit(&clientp->ic_mutex);
6650Sstevel@tonic-gate (void) ibmf_i_repost_recv_buffer(
6660Sstevel@tonic-gate clientp->ic_myci, recv_wqep);
6670Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
6680Sstevel@tonic-gate ibmf_i_do_recv_cb_error, IBMF_TNF_ERROR, "",
6690Sstevel@tonic-gate "ibmf_i_do_recv_cb(): %s, class %x\n",
6700Sstevel@tonic-gate tnf_string, msg,
6710Sstevel@tonic-gate "ibmf_tear_down_recv_cb already occurred",
6720Sstevel@tonic-gate tnf_opaque, class,
6730Sstevel@tonic-gate clientp->ic_client_info.client_class);
6740Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
6750Sstevel@tonic-gate ibmf_i_do_recv_cb_end, IBMF_TNF_TRACE, "",
6760Sstevel@tonic-gate "ibmf_i_do_recv_cb() exit\n");
6770Sstevel@tonic-gate return;
6780Sstevel@tonic-gate }
6790Sstevel@tonic-gate IBMF_RECV_CB_SETUP(clientp);
6800Sstevel@tonic-gate mutex_exit(&clientp->ic_mutex);
6810Sstevel@tonic-gate } else {
6820Sstevel@tonic-gate qpp = (ibmf_alt_qp_t *)ibmf_qp_handle;
6830Sstevel@tonic-gate
6840Sstevel@tonic-gate mutex_enter(&qpp->isq_mutex);
6850Sstevel@tonic-gate if (qpp->isq_recv_cb == NULL) {
6860Sstevel@tonic-gate mutex_exit(&qpp->isq_mutex);
6870Sstevel@tonic-gate (void) ibmf_i_repost_recv_buffer(
6880Sstevel@tonic-gate clientp->ic_myci, recv_wqep);
6890Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
6900Sstevel@tonic-gate ibmf_i_do_recv_cb_error, IBMF_TNF_ERROR, "",
6910Sstevel@tonic-gate "ibmf_i_do_recv_cb(): %s, class %x\n",
6920Sstevel@tonic-gate tnf_string, msg,
6930Sstevel@tonic-gate "ibmf_tear_down_recv_cb already occurred",
6940Sstevel@tonic-gate tnf_opaque, class,
6950Sstevel@tonic-gate clientp->ic_client_info.client_class);
6960Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
6970Sstevel@tonic-gate ibmf_i_do_recv_cb_end, IBMF_TNF_TRACE, "",
6980Sstevel@tonic-gate "ibmf_i_do_recv_cb() exit\n");
6990Sstevel@tonic-gate return;
7000Sstevel@tonic-gate }
7010Sstevel@tonic-gate IBMF_ALT_RECV_CB_SETUP(qpp);
7020Sstevel@tonic-gate mutex_exit(&qpp->isq_mutex);
7030Sstevel@tonic-gate }
7040Sstevel@tonic-gate
7050Sstevel@tonic-gate /*
7060Sstevel@tonic-gate * Allocate a message context
7070Sstevel@tonic-gate */
7080Sstevel@tonic-gate msgimplp = (ibmf_msg_impl_t *)kmem_zalloc(
7090Sstevel@tonic-gate sizeof (ibmf_msg_impl_t), KM_NOSLEEP);
7100Sstevel@tonic-gate
7110Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*msgimplp))
7120Sstevel@tonic-gate
7130Sstevel@tonic-gate /* If we cannot allocate memory, drop the packet and clean up */
7140Sstevel@tonic-gate if (msgimplp == NULL) {
7150Sstevel@tonic-gate if (ibmf_qp_handle == IBMF_QP_HANDLE_DEFAULT) {
7160Sstevel@tonic-gate mutex_enter(&clientp->ic_mutex);
7170Sstevel@tonic-gate IBMF_RECV_CB_CLEANUP(clientp);
7180Sstevel@tonic-gate mutex_exit(&clientp->ic_mutex);
7190Sstevel@tonic-gate } else {
7200Sstevel@tonic-gate qpp = (ibmf_alt_qp_t *)ibmf_qp_handle;
7210Sstevel@tonic-gate mutex_enter(&qpp->isq_mutex);
7220Sstevel@tonic-gate IBMF_ALT_RECV_CB_CLEANUP(qpp);
7230Sstevel@tonic-gate mutex_exit(&qpp->isq_mutex);
7240Sstevel@tonic-gate }
7250Sstevel@tonic-gate (void) ibmf_i_repost_recv_buffer(clientp->ic_myci,
7260Sstevel@tonic-gate recv_wqep);
7270Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
7280Sstevel@tonic-gate ibmf_i_do_recv_cb_error, IBMF_TNF_ERROR, "",
7290Sstevel@tonic-gate "ibmf_i_do_recv_cb(): %s\n", tnf_string, msg,
7300Sstevel@tonic-gate "mem allocation failure");
7310Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
7320Sstevel@tonic-gate ibmf_i_do_recv_cb_end, IBMF_TNF_TRACE, "",
7330Sstevel@tonic-gate "ibmf_i_do_recv_cb() exit\n");
7340Sstevel@tonic-gate return;
7350Sstevel@tonic-gate }
7360Sstevel@tonic-gate
7370Sstevel@tonic-gate /* Get the port's base LID if it's not in the client context */
7380Sstevel@tonic-gate if ((clientp->ic_base_lid == 0) &&
7390Sstevel@tonic-gate (clientp->ic_qp->iq_qp_num != 0)) {
7400Sstevel@tonic-gate (void) ibt_get_port_state_byguid(
7410Sstevel@tonic-gate clientp->ic_client_info.ci_guid,
7420Sstevel@tonic-gate clientp->ic_client_info.port_num, NULL,
7430Sstevel@tonic-gate &clientp->ic_base_lid);
7440Sstevel@tonic-gate if (clientp->ic_base_lid == 0) {
7450Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
7460Sstevel@tonic-gate ibmf_i_do_recv_cb_error, IBMF_TNF_ERROR, "",
7470Sstevel@tonic-gate "ibmf_i_do_recv_cb(): %s\n",
7480Sstevel@tonic-gate tnf_string, msg, "base_lid is undefined");
7490Sstevel@tonic-gate }
7500Sstevel@tonic-gate }
7510Sstevel@tonic-gate
7520Sstevel@tonic-gate /* Set up address information */
7530Sstevel@tonic-gate addrinfo.ia_local_lid = clientp->ic_base_lid +
7540Sstevel@tonic-gate wcp->wc_path_bits;
7550Sstevel@tonic-gate addrinfo.ia_remote_lid = wcp->wc_slid;
7560Sstevel@tonic-gate addrinfo.ia_remote_qno = wcp->wc_qpn;
7570Sstevel@tonic-gate
7580Sstevel@tonic-gate /* Get the pkey, including the correct partiton membership */
7590Sstevel@tonic-gate if (ibmf_qp_handle == IBMF_QP_HANDLE_DEFAULT) {
7600Sstevel@tonic-gate if (recv_wqep->recv_qpp->iq_qp_num == IBMF_QP1_NUM) {
7610Sstevel@tonic-gate
7620Sstevel@tonic-gate /*
7630Sstevel@tonic-gate * here too we expect the pkey index in the work
7640Sstevel@tonic-gate * completion belongs to a pkey in the pkey
7650Sstevel@tonic-gate * table
7660Sstevel@tonic-gate */
7670Sstevel@tonic-gate status = ibmf_i_pkey_ix_to_key(
7680Sstevel@tonic-gate clientp->ic_myci, recv_wqep->recv_port_num,
7690Sstevel@tonic-gate wcp->wc_pkey_ix, &addrinfo.ia_p_key);
7700Sstevel@tonic-gate if (status != IBMF_SUCCESS) {
7710Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_NODEBUG,
7720Sstevel@tonic-gate DPRINT_L1, ibmf_i_do_recv_cb_error,
7730Sstevel@tonic-gate IBMF_TNF_ERROR, "",
7740Sstevel@tonic-gate "ibmf_i_do_recv_cb(): "
7750Sstevel@tonic-gate "get_pkey failed for ix %d,"
7760Sstevel@tonic-gate "status = %d\n", tnf_uint,
7770Sstevel@tonic-gate pkeyix, wcp->wc_pkey_ix, tnf_uint,
7780Sstevel@tonic-gate ibmf_status, status);
7790Sstevel@tonic-gate mutex_enter(&clientp->ic_mutex);
7800Sstevel@tonic-gate IBMF_RECV_CB_CLEANUP(clientp);
7810Sstevel@tonic-gate mutex_exit(&clientp->ic_mutex);
7820Sstevel@tonic-gate (void) ibmf_i_repost_recv_buffer(
7830Sstevel@tonic-gate clientp->ic_myci, recv_wqep);
7840Sstevel@tonic-gate mutex_destroy(&msgimplp->im_mutex);
7850Sstevel@tonic-gate cv_destroy(&msgimplp->im_trans_cv);
7860Sstevel@tonic-gate kmem_free(msgimplp,
7870Sstevel@tonic-gate sizeof (ibmf_msg_impl_t));
7880Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
7890Sstevel@tonic-gate ibmf_i_do_recv_cb_end,
7900Sstevel@tonic-gate IBMF_TNF_TRACE, "",
7910Sstevel@tonic-gate "ibmf_i_do_recv_cb() exit\n");
7920Sstevel@tonic-gate return;
7930Sstevel@tonic-gate }
7940Sstevel@tonic-gate }
7950Sstevel@tonic-gate addrinfo.ia_q_key = IBMF_MGMT_Q_KEY;
7960Sstevel@tonic-gate } else {
7970Sstevel@tonic-gate qpp = (ibmf_alt_qp_t *)ibmf_qp_handle;
7980Sstevel@tonic-gate
7990Sstevel@tonic-gate /* For alternate QPs, the pkey is in the QP context */
8000Sstevel@tonic-gate mutex_enter(&qpp->isq_mutex);
8010Sstevel@tonic-gate addrinfo.ia_p_key = qpp->isq_pkey;
8020Sstevel@tonic-gate addrinfo.ia_q_key = qpp->isq_qkey;
8030Sstevel@tonic-gate mutex_exit(&qpp->isq_mutex);
8040Sstevel@tonic-gate }
8050Sstevel@tonic-gate
8060Sstevel@tonic-gate addrinfo.ia_service_level = wcp->wc_sl;
8070Sstevel@tonic-gate msgimplp->im_local_addr = addrinfo;
8080Sstevel@tonic-gate
8090Sstevel@tonic-gate /* Initialize the message context */
8100Sstevel@tonic-gate cv_init(&msgimplp->im_trans_cv, NULL, CV_DRIVER, NULL);
8110Sstevel@tonic-gate mutex_init(&msgimplp->im_mutex, NULL, MUTEX_DRIVER, NULL);
8120Sstevel@tonic-gate msgimplp->im_client = clientp;
8130Sstevel@tonic-gate msgimplp->im_qp_hdl = ibmf_qp_handle;
8140Sstevel@tonic-gate msgimplp->im_flags = 0;
8150Sstevel@tonic-gate msgimplp->im_unsolicited = B_TRUE;
8160Sstevel@tonic-gate msgimplp->im_tid = b2h64(mad_hdr->TransactionID);
8170Sstevel@tonic-gate msgimplp->im_mgt_class = mad_hdr->MgmtClass;
8180Sstevel@tonic-gate msgimplp->im_retrans.retrans_retries = IBMF_RETRANS_DEF_RETRIES;
8190Sstevel@tonic-gate msgimplp->im_retrans.retrans_rtv = IBMF_RETRANS_DEF_RTV;
8200Sstevel@tonic-gate msgimplp->im_retrans.retrans_rttv = IBMF_RETRANS_DEF_RTTV;
8210Sstevel@tonic-gate msgimplp->im_retrans.retrans_trans_to =
8220Sstevel@tonic-gate IBMF_RETRANS_DEF_TRANS_TO;
8230Sstevel@tonic-gate msgimplp->im_rmpp_ctx.rmpp_state = IBMF_RMPP_STATE_UNDEFINED;
8240Sstevel@tonic-gate msgimplp->im_rmpp_ctx.rmpp_respt = IBMF_RMPP_DEFAULT_RRESPT;
8250Sstevel@tonic-gate IBMF_MSG_INCR_REFCNT(msgimplp);
8260Sstevel@tonic-gate msgimplp->im_trans_state_flags = IBMF_TRANS_STATE_FLAG_UNINIT;
8270Sstevel@tonic-gate
8280Sstevel@tonic-gate /*
8290Sstevel@tonic-gate * Initialize (and possibly allocate) the IBT UD destination
8300Sstevel@tonic-gate * address handle.
8310Sstevel@tonic-gate */
8320Sstevel@tonic-gate status = ibmf_i_alloc_ud_dest(clientp, msgimplp,
8330Sstevel@tonic-gate &msgimplp->im_ud_dest, B_FALSE);
8340Sstevel@tonic-gate if (status != IBMF_SUCCESS) {
8350Sstevel@tonic-gate if (ibmf_qp_handle == IBMF_QP_HANDLE_DEFAULT) {
8360Sstevel@tonic-gate mutex_enter(&clientp->ic_mutex);
8370Sstevel@tonic-gate IBMF_RECV_CB_CLEANUP(clientp);
8380Sstevel@tonic-gate mutex_exit(&clientp->ic_mutex);
8390Sstevel@tonic-gate } else {
8400Sstevel@tonic-gate qpp = (ibmf_alt_qp_t *)ibmf_qp_handle;
8410Sstevel@tonic-gate mutex_enter(&qpp->isq_mutex);
8420Sstevel@tonic-gate IBMF_ALT_RECV_CB_CLEANUP(qpp);
8430Sstevel@tonic-gate mutex_exit(&qpp->isq_mutex);
8440Sstevel@tonic-gate }
8450Sstevel@tonic-gate (void) ibmf_i_repost_recv_buffer(clientp->ic_myci,
8460Sstevel@tonic-gate recv_wqep);
8470Sstevel@tonic-gate mutex_destroy(&msgimplp->im_mutex);
8480Sstevel@tonic-gate cv_destroy(&msgimplp->im_trans_cv);
8490Sstevel@tonic-gate kmem_free(msgimplp, sizeof (ibmf_msg_impl_t));
8500Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
8510Sstevel@tonic-gate ibmf_i_do_recv_cb_error, IBMF_TNF_ERROR, "",
8520Sstevel@tonic-gate "ibmf_i_do_recv_cb(): %s, status = %d\n",
8530Sstevel@tonic-gate tnf_string, msg, "alloc ah failed", tnf_uint,
8540Sstevel@tonic-gate ibmf_status, status);
8550Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
8560Sstevel@tonic-gate ibmf_i_do_recv_cb_end, IBMF_TNF_TRACE, "",
8570Sstevel@tonic-gate "ibmf_i_do_recv_cb() exit\n");
8580Sstevel@tonic-gate return;
8590Sstevel@tonic-gate }
8600Sstevel@tonic-gate
8610Sstevel@tonic-gate _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*msgimplp))
8620Sstevel@tonic-gate
8630Sstevel@tonic-gate /* add message to client's list */
8640Sstevel@tonic-gate ibmf_i_client_add_msg(clientp, msgimplp);
8650Sstevel@tonic-gate
8660Sstevel@tonic-gate mutex_enter(&msgimplp->im_mutex);
8670Sstevel@tonic-gate
8680Sstevel@tonic-gate /* no one should have touched our state */
8690Sstevel@tonic-gate ASSERT(msgimplp->im_trans_state_flags ==
8700Sstevel@tonic-gate IBMF_TRANS_STATE_FLAG_UNINIT);
8710Sstevel@tonic-gate
8720Sstevel@tonic-gate /* transition out of uninit state */
8730Sstevel@tonic-gate msgimplp->im_trans_state_flags = IBMF_TRANS_STATE_FLAG_INIT;
8740Sstevel@tonic-gate }
8750Sstevel@tonic-gate
8760Sstevel@tonic-gate /* fill in the grh with the contents of the recv wqe */
8770Sstevel@tonic-gate if (grhpresent == B_TRUE) {
8780Sstevel@tonic-gate uint32_t tmp32;
8790Sstevel@tonic-gate
8800Sstevel@tonic-gate msgimplp->im_msg_flags |= IBMF_MSG_FLAGS_GLOBAL_ADDRESS;
8810Sstevel@tonic-gate ib_grh = (ib_grh_t *)recv_wqep->recv_mem;
8820Sstevel@tonic-gate msgimplp->im_global_addr.ig_sender_gid.gid_prefix =
8830Sstevel@tonic-gate b2h64(ib_grh->SGID.gid_prefix);
8840Sstevel@tonic-gate msgimplp->im_global_addr.ig_sender_gid.gid_guid =
8850Sstevel@tonic-gate b2h64(ib_grh->SGID.gid_guid);
8860Sstevel@tonic-gate msgimplp->im_global_addr.ig_recver_gid.gid_prefix =
8870Sstevel@tonic-gate b2h64(ib_grh->DGID.gid_prefix);
8880Sstevel@tonic-gate msgimplp->im_global_addr.ig_recver_gid.gid_guid =
8890Sstevel@tonic-gate b2h64(ib_grh->DGID.gid_guid);
8900Sstevel@tonic-gate /*
8910Sstevel@tonic-gate * swap to get byte order back to wire format on little endian
8920Sstevel@tonic-gate * systems so we can apply the GRH masks
8930Sstevel@tonic-gate */
8940Sstevel@tonic-gate tmp32 = b2h32(ib_grh->IPVer_TC_Flow);
8950Sstevel@tonic-gate msgimplp->im_global_addr.ig_flow_label =
8960Sstevel@tonic-gate tmp32 & IB_GRH_FLOW_LABEL_MASK;
8970Sstevel@tonic-gate msgimplp->im_global_addr.ig_tclass =
8980Sstevel@tonic-gate (tmp32 & IB_GRH_TCLASS_MASK) >> 20;
8990Sstevel@tonic-gate msgimplp->im_global_addr.ig_hop_limit =
9000Sstevel@tonic-gate ib_grh->HopLmt;
9010Sstevel@tonic-gate }
9020Sstevel@tonic-gate
9030Sstevel@tonic-gate /* Perform RMPP or non-RMPP processing */
9040Sstevel@tonic-gate if (ibmf_i_is_rmpp(clientp, ibmf_qp_handle) &&
9050Sstevel@tonic-gate (rmpp_hdr->rmpp_flags & IBMF_RMPP_FLAGS_ACTIVE)) {
9060Sstevel@tonic-gate IBMF_TRACE_5(IBMF_TNF_DEBUG, DPRINT_L3,
9070Sstevel@tonic-gate ibmf_i_do_recv_cb, IBMF_TNF_TRACE, "",
9080Sstevel@tonic-gate "ibmf_i_do_recv_cb(): %s, tid = %016" PRIx64 ","
9090Sstevel@tonic-gate "flags = 0x%x rmpp_type = %d, rmpp_segnum = %d\n",
9100Sstevel@tonic-gate tnf_string, msg, "Handling rmpp MAD",
9110Sstevel@tonic-gate tnf_opaque, tid, b2h64(mad_hdr->TransactionID),
9120Sstevel@tonic-gate tnf_opaque, flags, rmpp_hdr->rmpp_flags,
9130Sstevel@tonic-gate tnf_opaque, type, rmpp_hdr->rmpp_type,
9140Sstevel@tonic-gate tnf_opaque, segment, b2h32(rmpp_hdr->rmpp_segnum));
9150Sstevel@tonic-gate
9160Sstevel@tonic-gate /*
9170Sstevel@tonic-gate * Set the RMPP state to "receiver active" on the first packet
9180Sstevel@tonic-gate * of all RMPP message, and initialize the
9190Sstevel@tonic-gate * the expected segment to 1.
9200Sstevel@tonic-gate */
9210Sstevel@tonic-gate if ((msgimplp->im_rmpp_ctx.rmpp_state ==
9220Sstevel@tonic-gate IBMF_RMPP_STATE_UNDEFINED) &&
9230Sstevel@tonic-gate (rmpp_hdr->rmpp_flags & IBMF_RMPP_FLAGS_FIRST_PKT)) {
9240Sstevel@tonic-gate
9250Sstevel@tonic-gate msgimplp->im_flags |= IBMF_MSG_FLAGS_RECV_RMPP;
9260Sstevel@tonic-gate
9270Sstevel@tonic-gate if (rmpp_hdr->rmpp_type == IBMF_RMPP_TYPE_DATA) {
9280Sstevel@tonic-gate msgimplp->im_rmpp_ctx.rmpp_state =
9290Sstevel@tonic-gate IBMF_RMPP_STATE_RECEVR_ACTIVE;
9300Sstevel@tonic-gate
9310Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3,
9320Sstevel@tonic-gate ibmf_i_do_recv_cb, IBMF_TNF_TRACE, "",
9330Sstevel@tonic-gate "ibmf_i_do_recv_cb(): %s, msgimplp = %p\n",
9340Sstevel@tonic-gate tnf_string, msg, "first RMPP pkt received",
9350Sstevel@tonic-gate tnf_opaque, msgimplp, msgimplp);
9360Sstevel@tonic-gate }
9370Sstevel@tonic-gate
9380Sstevel@tonic-gate msgimplp->im_rmpp_ctx.rmpp_es = 1;
9390Sstevel@tonic-gate msgimplp->im_rmpp_ctx.rmpp_wl = 1;
9400Sstevel@tonic-gate msgimplp->im_rmpp_ctx.rmpp_wf = 1;
9410Sstevel@tonic-gate
9420Sstevel@tonic-gate /* set double-sided transfer flag for certain methods */
9430Sstevel@tonic-gate if (mad_hdr->R_Method == SA_SUBN_ADM_GET_MULTI)
9440Sstevel@tonic-gate msgimplp->im_rmpp_ctx.rmpp_is_ds = B_TRUE;
9450Sstevel@tonic-gate else msgimplp->im_rmpp_ctx.rmpp_is_ds = B_FALSE;
9460Sstevel@tonic-gate
9470Sstevel@tonic-gate msgimplp->im_trans_state_flags |=
9480Sstevel@tonic-gate IBMF_TRANS_STATE_FLAG_RECV_ACTIVE;
9490Sstevel@tonic-gate }
9500Sstevel@tonic-gate
9510Sstevel@tonic-gate if (rmpp_hdr->rmpp_resp_time != IBMF_RMPP_DEFAULT_RRESPT) {
9520Sstevel@tonic-gate msgimplp->im_retrans.retrans_rtv =
9530Sstevel@tonic-gate 1 << rmpp_hdr->rmpp_resp_time;
9540Sstevel@tonic-gate
9550Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3,
9560Sstevel@tonic-gate ibmf_i_do_recv_cb, IBMF_TNF_TRACE, "",
9570Sstevel@tonic-gate "ibmf_i_do_recv_cb: %s, resp_time %d\n",
9580Sstevel@tonic-gate tnf_string, msg, "new resp time received",
9590Sstevel@tonic-gate tnf_uint, resp_time, rmpp_hdr->rmpp_resp_time);
9600Sstevel@tonic-gate }
9610Sstevel@tonic-gate
9620Sstevel@tonic-gate ibmf_i_handle_rmpp(clientp, ibmf_qp_handle, msgimplp,
9630Sstevel@tonic-gate (uchar_t *)((uintptr_t)recv_wqep->recv_mem +
9640Sstevel@tonic-gate sizeof (ib_grh_t)));
9650Sstevel@tonic-gate } else {
9660Sstevel@tonic-gate
9670Sstevel@tonic-gate msgimplp->im_trans_state_flags |=
9680Sstevel@tonic-gate IBMF_TRANS_STATE_FLAG_RECV_ACTIVE;
9690Sstevel@tonic-gate
9700Sstevel@tonic-gate ibmf_i_handle_non_rmpp(clientp, msgimplp,
9710Sstevel@tonic-gate (uchar_t *)((uintptr_t)recv_wqep->recv_mem +
9720Sstevel@tonic-gate sizeof (ib_grh_t)));
9730Sstevel@tonic-gate }
9740Sstevel@tonic-gate
9750Sstevel@tonic-gate msg_rp_unset_id = msg_tr_unset_id = msg_rp_set_id = msg_tr_set_id = 0;
9760Sstevel@tonic-gate
9770Sstevel@tonic-gate /*
9780Sstevel@tonic-gate * Save the transaction state flags and the timeout IDs
9790Sstevel@tonic-gate * before releasing the mutex as they may be changed after that.
9800Sstevel@tonic-gate */
9810Sstevel@tonic-gate msg_trans_state_flags = msgimplp->im_trans_state_flags;
9820Sstevel@tonic-gate msg_flags = msgimplp->im_flags;
9830Sstevel@tonic-gate msg_rp_unset_id = msgimplp->im_rp_unset_timeout_id;
9840Sstevel@tonic-gate msg_tr_unset_id = msgimplp->im_tr_unset_timeout_id;
9850Sstevel@tonic-gate msgimplp->im_rp_unset_timeout_id = 0;
9860Sstevel@tonic-gate msgimplp->im_tr_unset_timeout_id = 0;
9870Sstevel@tonic-gate
9880Sstevel@tonic-gate /*
9890Sstevel@tonic-gate * Decrement the message reference count
9900Sstevel@tonic-gate * This count was incremented either when the message was found
9910Sstevel@tonic-gate * on the client's message list (ibmf_i_find_msg()) or when
9920Sstevel@tonic-gate * a new message was created for unsolicited data
9930Sstevel@tonic-gate */
9940Sstevel@tonic-gate IBMF_MSG_DECR_REFCNT(msgimplp);
9950Sstevel@tonic-gate
9960Sstevel@tonic-gate if (msg_trans_state_flags & IBMF_TRANS_STATE_FLAG_DONE) {
9970Sstevel@tonic-gate if (msgimplp->im_rp_timeout_id != 0) {
9980Sstevel@tonic-gate msg_rp_set_id = msgimplp->im_rp_timeout_id;
9990Sstevel@tonic-gate msgimplp->im_rp_timeout_id = 0;
10000Sstevel@tonic-gate }
10010Sstevel@tonic-gate if (msgimplp->im_tr_timeout_id != 0) {
10020Sstevel@tonic-gate msg_tr_set_id = msgimplp->im_tr_timeout_id;
10030Sstevel@tonic-gate msgimplp->im_tr_timeout_id = 0;
10040Sstevel@tonic-gate }
10050Sstevel@tonic-gate }
10060Sstevel@tonic-gate
10070Sstevel@tonic-gate mutex_exit(&msgimplp->im_mutex);
10080Sstevel@tonic-gate
10090Sstevel@tonic-gate /*
10100Sstevel@tonic-gate * Call untimeout() after releasing the lock because the
10110Sstevel@tonic-gate * lock is acquired in the timeout handler as well. Untimeout()
10120Sstevel@tonic-gate * does not return until the timeout handler has run, if it already
10130Sstevel@tonic-gate * fired, which would result in a deadlock if we did not first
10140Sstevel@tonic-gate * release the im_mutex lock.
10150Sstevel@tonic-gate */
10160Sstevel@tonic-gate if (msg_rp_unset_id != 0) {
10170Sstevel@tonic-gate (void) untimeout(msg_rp_unset_id);
10180Sstevel@tonic-gate }
10190Sstevel@tonic-gate
10200Sstevel@tonic-gate if (msg_tr_unset_id != 0) {
10210Sstevel@tonic-gate (void) untimeout(msg_tr_unset_id);
10220Sstevel@tonic-gate }
10230Sstevel@tonic-gate
10240Sstevel@tonic-gate if (msg_rp_set_id != 0) {
10250Sstevel@tonic-gate (void) untimeout(msg_rp_set_id);
10260Sstevel@tonic-gate }
10270Sstevel@tonic-gate
10280Sstevel@tonic-gate if (msg_tr_set_id != 0) {
10290Sstevel@tonic-gate (void) untimeout(msg_tr_set_id);
10300Sstevel@tonic-gate }
10310Sstevel@tonic-gate
10320Sstevel@tonic-gate /* Increment the kstats for number of messages received */
10330Sstevel@tonic-gate mutex_enter(&clientp->ic_kstat_mutex);
10340Sstevel@tonic-gate IBMF_ADD32_KSTATS(clientp, msgs_received, 1);
10350Sstevel@tonic-gate mutex_exit(&clientp->ic_kstat_mutex);
10360Sstevel@tonic-gate
10370Sstevel@tonic-gate /*
10380Sstevel@tonic-gate * now that we are done gleaning all we want out of the receive
10390Sstevel@tonic-gate * completion, we repost the receive request.
10400Sstevel@tonic-gate */
10410Sstevel@tonic-gate (void) ibmf_i_repost_recv_buffer(clientp->ic_myci, recv_wqep);
10420Sstevel@tonic-gate
10430Sstevel@tonic-gate /*
10440Sstevel@tonic-gate * If the transaction flags indicate a completed transaction,
10450Sstevel@tonic-gate * notify the client
10460Sstevel@tonic-gate */
10470Sstevel@tonic-gate if (msg_trans_state_flags & IBMF_TRANS_STATE_FLAG_DONE) {
10480Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3,
10490Sstevel@tonic-gate ibmf_i_do_recv_cb, IBMF_TNF_TRACE, "",
10500Sstevel@tonic-gate "ibmf_i_do_recv_cb(): %s, msgimplp = %p\n",
10510Sstevel@tonic-gate tnf_string, msg, "notifying client",
10520Sstevel@tonic-gate tnf_opaque, msgimplp, msgimplp);
10530Sstevel@tonic-gate
10540Sstevel@tonic-gate /* Remove the message from the client's message list */
10550Sstevel@tonic-gate ibmf_i_client_rem_msg(clientp, msgimplp, &ref_cnt);
10560Sstevel@tonic-gate
10570Sstevel@tonic-gate /*
10580Sstevel@tonic-gate * Notify the client if the message reference count is zero.
10590Sstevel@tonic-gate * At this point, we know that the transaction is done and
10600Sstevel@tonic-gate * the message has been removed from the client's message list.
10610Sstevel@tonic-gate * So, we only need to make sure the reference count is zero
10620Sstevel@tonic-gate * before notifying the client.
10630Sstevel@tonic-gate */
10640Sstevel@tonic-gate if (ref_cnt == 0) {
10650Sstevel@tonic-gate
10660Sstevel@tonic-gate ibmf_i_notify_sequence(clientp, msgimplp, msg_flags);
10670Sstevel@tonic-gate
10680Sstevel@tonic-gate }
10690Sstevel@tonic-gate }
10700Sstevel@tonic-gate
10710Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4,
10720Sstevel@tonic-gate ibmf_i_do_recv_cb_end, IBMF_TNF_TRACE, "",
10730Sstevel@tonic-gate "ibmf_i_do_recv_cb() exit, msgimplp = %p\n",
10740Sstevel@tonic-gate tnf_opaque, msgimplp, msgimplp);
10750Sstevel@tonic-gate }
10760Sstevel@tonic-gate
10770Sstevel@tonic-gate /*
10780Sstevel@tonic-gate * ibmf_i_handle_non_rmpp():
10790Sstevel@tonic-gate * Handle non-RMPP processing of an incoming IB packet
10800Sstevel@tonic-gate */
10810Sstevel@tonic-gate void
ibmf_i_handle_non_rmpp(ibmf_client_t * clientp,ibmf_msg_impl_t * msgimplp,uchar_t * mad)10820Sstevel@tonic-gate ibmf_i_handle_non_rmpp(ibmf_client_t *clientp, ibmf_msg_impl_t *msgimplp,
10830Sstevel@tonic-gate uchar_t *mad)
10840Sstevel@tonic-gate {
10850Sstevel@tonic-gate ibmf_rmpp_ctx_t *rmpp_ctx = &msgimplp->im_rmpp_ctx;
10860Sstevel@tonic-gate ib_mad_hdr_t *mad_hdr;
10870Sstevel@tonic-gate size_t offset;
10880Sstevel@tonic-gate uchar_t *msgbufp;
10890Sstevel@tonic-gate uint32_t clhdrsz, clhdroff;
10900Sstevel@tonic-gate
10910Sstevel@tonic-gate IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L4,
10920Sstevel@tonic-gate ibmf_i_handle_non_rmpp_start, IBMF_TNF_TRACE, "",
10930Sstevel@tonic-gate "ibmf_i_handle_non_rmpp(): clientp = 0x%p, "
10940Sstevel@tonic-gate "msgp = 0x%p, madp = 0x%p\n", tnf_opaque, clientp, clientp,
10950Sstevel@tonic-gate tnf_opaque, msg, msgimplp, tnf_opaque, mad, mad);
10960Sstevel@tonic-gate
10970Sstevel@tonic-gate ASSERT(MUTEX_HELD(&msgimplp->im_mutex));
10980Sstevel@tonic-gate
10990Sstevel@tonic-gate /* Get the MAD header */
11000Sstevel@tonic-gate mad_hdr = (ib_mad_hdr_t *)mad;
11010Sstevel@tonic-gate
11020Sstevel@tonic-gate /* Determine the MAD's class header size */
11030Sstevel@tonic-gate ibmf_i_mgt_class_to_hdr_sz_off(mad_hdr->MgmtClass, &clhdrsz, &clhdroff);
11040Sstevel@tonic-gate
11050Sstevel@tonic-gate /* Allocate the message receive buffers if not already allocated */
11060Sstevel@tonic-gate if (msgimplp->im_msgbufs_recv.im_bufs_mad_hdr == NULL) {
11070Sstevel@tonic-gate
11080Sstevel@tonic-gate msgimplp->im_msgbufs_recv.im_bufs_mad_hdr =
11090Sstevel@tonic-gate (ib_mad_hdr_t *)kmem_zalloc(IBMF_MAD_SIZE, KM_NOSLEEP);
11100Sstevel@tonic-gate if (msgimplp->im_msgbufs_recv.im_bufs_mad_hdr == NULL) {
11110Sstevel@tonic-gate
11120Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
11130Sstevel@tonic-gate ibmf_i_handle_non_rmpp_err, IBMF_TNF_ERROR, "",
11140Sstevel@tonic-gate "ibmf_i_handle_non_rmpp(): %s\n", tnf_string, msg,
11150Sstevel@tonic-gate "mem allocation failure (non-rmpp payload)");
11160Sstevel@tonic-gate
11170Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
11180Sstevel@tonic-gate ibmf_i_handle_non_rmpp_end, IBMF_TNF_TRACE, "",
11190Sstevel@tonic-gate "ibmf_i_handle_non_rmpp() exit\n");
11200Sstevel@tonic-gate
11210Sstevel@tonic-gate return;
11220Sstevel@tonic-gate }
11230Sstevel@tonic-gate mutex_enter(&clientp->ic_kstat_mutex);
11240Sstevel@tonic-gate IBMF_ADD32_KSTATS(clientp, recv_bufs_alloced, 1);
11250Sstevel@tonic-gate mutex_exit(&clientp->ic_kstat_mutex);
11260Sstevel@tonic-gate }
11270Sstevel@tonic-gate
11280Sstevel@tonic-gate /* Get a pointer to the MAD location in the receive buffer */
11290Sstevel@tonic-gate msgbufp = (uchar_t *)msgimplp->im_msgbufs_recv.im_bufs_mad_hdr;
11300Sstevel@tonic-gate
11310Sstevel@tonic-gate /* Copy the incoming MAD into the receive buffer */
11320Sstevel@tonic-gate bcopy((const void *)mad, (void *)msgbufp, IBMF_MAD_SIZE);
11330Sstevel@tonic-gate
11340Sstevel@tonic-gate /* Get the offset of the class header */
11350Sstevel@tonic-gate offset = sizeof (ib_mad_hdr_t) + clhdroff;
11360Sstevel@tonic-gate
11370Sstevel@tonic-gate /* initialize class header pointer */
11380Sstevel@tonic-gate if (clhdrsz == 0) {
11390Sstevel@tonic-gate msgimplp->im_msgbufs_recv.im_bufs_cl_hdr = NULL;
11400Sstevel@tonic-gate } else {
11410Sstevel@tonic-gate msgimplp->im_msgbufs_recv.im_bufs_cl_hdr =
11420Sstevel@tonic-gate (void *)(msgbufp + offset);
11430Sstevel@tonic-gate }
11440Sstevel@tonic-gate msgimplp->im_msgbufs_recv.im_bufs_cl_hdr_len = clhdrsz;
11450Sstevel@tonic-gate
11460Sstevel@tonic-gate offset += clhdrsz;
11470Sstevel@tonic-gate
11480Sstevel@tonic-gate /* initialize data area pointer */
11490Sstevel@tonic-gate msgimplp->im_msgbufs_recv.im_bufs_cl_data = (void *)(msgbufp + offset);
11500Sstevel@tonic-gate msgimplp->im_msgbufs_recv.im_bufs_cl_data_len = IBMF_MAD_SIZE -
11510Sstevel@tonic-gate sizeof (ib_mad_hdr_t) - clhdroff - clhdrsz;
11520Sstevel@tonic-gate
11530Sstevel@tonic-gate rmpp_ctx->rmpp_state = IBMF_RMPP_STATE_DONE;
11540Sstevel@tonic-gate ibmf_i_terminate_transaction(clientp, msgimplp, IBMF_SUCCESS);
11550Sstevel@tonic-gate
11560Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_handle_non_rmpp_end,
11570Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_handle_non_rmpp() exit\n");
11580Sstevel@tonic-gate }
11590Sstevel@tonic-gate
11600Sstevel@tonic-gate /*
11610Sstevel@tonic-gate * ibmf_i_repost_recv_buffer():
11620Sstevel@tonic-gate * Repost a WQE to the RQ after processing it
11630Sstevel@tonic-gate */
11640Sstevel@tonic-gate /* ARGSUSED */
11650Sstevel@tonic-gate int
ibmf_i_repost_recv_buffer(ibmf_ci_t * cip,ibmf_recv_wqe_t * recv_wqep)11660Sstevel@tonic-gate ibmf_i_repost_recv_buffer(ibmf_ci_t *cip, ibmf_recv_wqe_t *recv_wqep)
11670Sstevel@tonic-gate {
11680Sstevel@tonic-gate int ret;
11690Sstevel@tonic-gate ibt_status_t status;
11700Sstevel@tonic-gate ibmf_qp_handle_t ibmf_qp_handle = recv_wqep->recv_ibmf_qp_handle;
11710Sstevel@tonic-gate struct kmem_cache *kmem_cachep;
11720Sstevel@tonic-gate ibmf_alt_qp_t *altqp;
11730Sstevel@tonic-gate ibmf_qp_t *qpp;
11740Sstevel@tonic-gate
11750Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4,
11760Sstevel@tonic-gate ibmf_i_repost_recv_buffer_start, IBMF_TNF_TRACE, "",
11770Sstevel@tonic-gate "ibmf_i_repost_recv_buffer() enter, cip = %p, rwqep = %p\n",
11780Sstevel@tonic-gate tnf_opaque, cip, cip, tnf_opaque, rwqep, recv_wqep);
11790Sstevel@tonic-gate
11800Sstevel@tonic-gate ASSERT(MUTEX_NOT_HELD(&cip->ci_mutex));
11810Sstevel@tonic-gate
11820Sstevel@tonic-gate /* Get the WQE kmem cache pointer based on the QP type */
11830Sstevel@tonic-gate if (ibmf_qp_handle == IBMF_QP_HANDLE_DEFAULT) {
11840Sstevel@tonic-gate kmem_cachep = cip->ci_recv_wqes_cache;
11850Sstevel@tonic-gate qpp = recv_wqep->recv_qpp;
11860Sstevel@tonic-gate } else {
11870Sstevel@tonic-gate altqp = (ibmf_alt_qp_t *)ibmf_qp_handle;
11880Sstevel@tonic-gate kmem_cachep = altqp->isq_recv_wqes_cache;
11890Sstevel@tonic-gate }
11900Sstevel@tonic-gate
11910Sstevel@tonic-gate /* post recv wqe; free it if the post fails */
11920Sstevel@tonic-gate status = ibt_post_recv(recv_wqep->recv_qp_handle, &recv_wqep->recv_wr,
11930Sstevel@tonic-gate 1, NULL);
11940Sstevel@tonic-gate
11950Sstevel@tonic-gate ret = ibmf_i_ibt_to_ibmf_status(status);
11960Sstevel@tonic-gate if (ret != IBMF_SUCCESS) {
11970Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
11980Sstevel@tonic-gate ibmf_i_repost_recv_buffer_err, IBMF_TNF_ERROR, "",
11990Sstevel@tonic-gate "ibmf_i_repost_recv_buffer(): %s, status = %d\n",
12000Sstevel@tonic-gate tnf_string, msg, "repost_recv failed", tnf_uint,
12010Sstevel@tonic-gate ibt_status, status);
12020Sstevel@tonic-gate kmem_free(recv_wqep->recv_wr.wr_sgl,
12030Sstevel@tonic-gate IBMF_MAX_RQ_WR_SGL_ELEMENTS * sizeof (ibt_wr_ds_t));
12040Sstevel@tonic-gate kmem_cache_free(kmem_cachep, recv_wqep);
12050Sstevel@tonic-gate mutex_enter(&cip->ci_mutex);
12060Sstevel@tonic-gate IBMF_SUB32_PORT_KSTATS(cip, recv_wqes_alloced, 1);
12070Sstevel@tonic-gate mutex_exit(&cip->ci_mutex);
12080Sstevel@tonic-gate if (ibmf_qp_handle == IBMF_QP_HANDLE_DEFAULT) {
12090Sstevel@tonic-gate mutex_enter(&cip->ci_mutex);
12100Sstevel@tonic-gate cip->ci_wqes_alloced--;
12110Sstevel@tonic-gate if (cip->ci_wqes_alloced == 0)
12120Sstevel@tonic-gate cv_signal(&cip->ci_wqes_cv);
12130Sstevel@tonic-gate mutex_exit(&cip->ci_mutex);
12140Sstevel@tonic-gate } else {
12150Sstevel@tonic-gate mutex_enter(&altqp->isq_mutex);
12160Sstevel@tonic-gate altqp->isq_wqes_alloced--;
12170Sstevel@tonic-gate if (altqp->isq_wqes_alloced == 0)
12180Sstevel@tonic-gate cv_signal(&altqp->isq_wqes_cv);
12190Sstevel@tonic-gate mutex_exit(&altqp->isq_mutex);
12200Sstevel@tonic-gate }
12210Sstevel@tonic-gate }
12220Sstevel@tonic-gate
12230Sstevel@tonic-gate if (ibmf_qp_handle == IBMF_QP_HANDLE_DEFAULT) {
12240Sstevel@tonic-gate mutex_enter(&qpp->iq_mutex);
12250Sstevel@tonic-gate qpp->iq_rwqes_posted++;
12260Sstevel@tonic-gate mutex_exit(&qpp->iq_mutex);
12270Sstevel@tonic-gate } else {
12280Sstevel@tonic-gate mutex_enter(&altqp->isq_mutex);
12290Sstevel@tonic-gate altqp->isq_rwqes_posted++;
12300Sstevel@tonic-gate mutex_exit(&altqp->isq_mutex);
12310Sstevel@tonic-gate }
12320Sstevel@tonic-gate
12330Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_repost_recv_buffer_end,
12340Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_repost_recv_buffer() exit\n");
12350Sstevel@tonic-gate return (ret);
12360Sstevel@tonic-gate }
12370Sstevel@tonic-gate
12380Sstevel@tonic-gate /*
12390Sstevel@tonic-gate * ibmf_i_get_class:
12400Sstevel@tonic-gate * Parses the mad header and determines which class should be notified of the
12410Sstevel@tonic-gate * notification.
12420Sstevel@tonic-gate *
12430Sstevel@tonic-gate * Input Argument
12440Sstevel@tonic-gate * madhdrp contents of mad header for the packet
12450Sstevel@tonic-gate *
12460Sstevel@tonic-gate * Output Argument
12470Sstevel@tonic-gate * dest_classp pointer to the class type of the client that should be notified
12480Sstevel@tonic-gate *
12490Sstevel@tonic-gate * Returns
12500Sstevel@tonic-gate * status
12510Sstevel@tonic-gate */
12520Sstevel@tonic-gate static int
ibmf_i_get_class(ib_mad_hdr_t * madhdrp,ibmf_qp_handle_t dest_ibmf_qp_handle,ib_lid_t slid,ibmf_client_type_t * dest_classp)12530Sstevel@tonic-gate ibmf_i_get_class(ib_mad_hdr_t *madhdrp, ibmf_qp_handle_t dest_ibmf_qp_handle,
12540Sstevel@tonic-gate ib_lid_t slid, ibmf_client_type_t *dest_classp)
12550Sstevel@tonic-gate {
12560Sstevel@tonic-gate int method = madhdrp->R_Method;
12570Sstevel@tonic-gate int attrib = b2h16(madhdrp->AttributeID);
12580Sstevel@tonic-gate int class = madhdrp->MgmtClass;
12590Sstevel@tonic-gate uint32_t attrib_mod = b2h32(madhdrp->AttributeModifier);
12600Sstevel@tonic-gate
12610Sstevel@tonic-gate IBMF_TRACE_4(IBMF_TNF_DEBUG, DPRINT_L4,
12620Sstevel@tonic-gate ibmf_i_get_class_start, IBMF_TNF_TRACE, "",
12630Sstevel@tonic-gate "ibmf_i_get_class() enter, class = 0x%x, method = 0x%x, "
12640Sstevel@tonic-gate "attribute = 0x%x, dest_qp_hdl = 0x%p\n",
12650Sstevel@tonic-gate tnf_opaque, class, class,
12660Sstevel@tonic-gate tnf_opaque, method, method,
12670Sstevel@tonic-gate tnf_opaque, attrib, attrib,
12680Sstevel@tonic-gate tnf_opaque, ibmf_qp_handle, dest_ibmf_qp_handle);
12690Sstevel@tonic-gate
12700Sstevel@tonic-gate /* set default for error checking */
12710Sstevel@tonic-gate *dest_classp = 0;
12720Sstevel@tonic-gate
12730Sstevel@tonic-gate /*
12740Sstevel@tonic-gate * Determine the class type
12750Sstevel@tonic-gate */
12760Sstevel@tonic-gate switch (class) {
12770Sstevel@tonic-gate case MAD_MGMT_CLASS_SUBN_LID_ROUTED:
12780Sstevel@tonic-gate case MAD_MGMT_CLASS_SUBN_DIRECT_ROUTE:
12790Sstevel@tonic-gate
12800Sstevel@tonic-gate /*
12810Sstevel@tonic-gate * tavor generates trap by sending mad with slid 0;
12820Sstevel@tonic-gate * deliver this to SMA
12830Sstevel@tonic-gate */
12840Sstevel@tonic-gate if ((method == MAD_METHOD_TRAP) && (slid == 0)) {
12850Sstevel@tonic-gate *dest_classp = SUBN_AGENT;
12860Sstevel@tonic-gate break;
12870Sstevel@tonic-gate }
12880Sstevel@tonic-gate
12890Sstevel@tonic-gate /* this is derived from table 109 of IB Spec 1.1, vol1 */
12900Sstevel@tonic-gate if (attrib == SM_SMINFO_ATTRID || method == MAD_METHOD_TRAP ||
12910Sstevel@tonic-gate method == MAD_METHOD_GET_RESPONSE)
12920Sstevel@tonic-gate *dest_classp = SUBN_MANAGER;
12930Sstevel@tonic-gate else
12940Sstevel@tonic-gate *dest_classp = SUBN_AGENT;
12950Sstevel@tonic-gate
12960Sstevel@tonic-gate break;
12970Sstevel@tonic-gate case MAD_MGMT_CLASS_SUBN_ADM:
12980Sstevel@tonic-gate
12990Sstevel@tonic-gate /*
13000Sstevel@tonic-gate * Deliver to SA client (agent) if packet was sent to default qp
13010Sstevel@tonic-gate * Deliver to ibmf_saa client (manager) if packet was sent to
13020Sstevel@tonic-gate * alternate qp
13030Sstevel@tonic-gate */
13040Sstevel@tonic-gate if (dest_ibmf_qp_handle == IBMF_QP_HANDLE_DEFAULT)
13050Sstevel@tonic-gate *dest_classp = SUBN_ADM_AGENT;
13060Sstevel@tonic-gate else
13070Sstevel@tonic-gate *dest_classp = SUBN_ADM_MANAGER;
13080Sstevel@tonic-gate break;
13090Sstevel@tonic-gate case MAD_MGMT_CLASS_PERF:
13100Sstevel@tonic-gate
13110Sstevel@tonic-gate /* Deliver to PM if response bit is set */
13120Sstevel@tonic-gate if ((method & MAD_RESPONSE_BIT_MASK) == MAD_RESPONSE_BIT)
13130Sstevel@tonic-gate *dest_classp = PERF_MANAGER;
13140Sstevel@tonic-gate else
13150Sstevel@tonic-gate *dest_classp = PERF_AGENT;
13160Sstevel@tonic-gate break;
13170Sstevel@tonic-gate case MAD_MGMT_CLASS_BM:
13180Sstevel@tonic-gate
13190Sstevel@tonic-gate /*
13200Sstevel@tonic-gate * Deliver to BM if response bit is set, packet is a trap,
13210Sstevel@tonic-gate * or packet is a BMSend
13220Sstevel@tonic-gate */
13230Sstevel@tonic-gate if (((method & MAD_RESPONSE_BIT_MASK) == MAD_RESPONSE_BIT) ||
13240Sstevel@tonic-gate (method == MAD_METHOD_TRAP) ||
13250Sstevel@tonic-gate ((method == MAD_METHOD_SEND) &&
13260Sstevel@tonic-gate ((attrib_mod & IBMF_BM_MAD_ATTR_MOD_REQRESP_BIT) ==
13270Sstevel@tonic-gate IBMF_BM_MAD_ATTR_MOD_RESP)))
13280Sstevel@tonic-gate *dest_classp = BM_MANAGER;
13290Sstevel@tonic-gate else
13300Sstevel@tonic-gate *dest_classp = BM_AGENT;
13310Sstevel@tonic-gate
13320Sstevel@tonic-gate break;
13330Sstevel@tonic-gate case MAD_MGMT_CLASS_DEV_MGT:
13340Sstevel@tonic-gate
13350Sstevel@tonic-gate /* Deliver to DM if response bit is set or packet is a trap */
13360Sstevel@tonic-gate if (((method & MAD_RESPONSE_BIT_MASK) == MAD_RESPONSE_BIT) ||
13370Sstevel@tonic-gate (method == MAD_METHOD_TRAP))
13380Sstevel@tonic-gate *dest_classp = DEV_MGT_MANAGER;
13390Sstevel@tonic-gate else
13400Sstevel@tonic-gate *dest_classp = DEV_MGT_AGENT;
13410Sstevel@tonic-gate break;
13420Sstevel@tonic-gate case MAD_MGMT_CLASS_COMM_MGT:
13430Sstevel@tonic-gate *dest_classp = COMM_MGT_MANAGER_AGENT;
13440Sstevel@tonic-gate break;
13450Sstevel@tonic-gate case MAD_MGMT_CLASS_SNMP:
13460Sstevel@tonic-gate *dest_classp = SNMP_MANAGER_AGENT;
13470Sstevel@tonic-gate break;
13480Sstevel@tonic-gate default:
13490Sstevel@tonic-gate
13500Sstevel@tonic-gate if ((class >= MAD_MGMT_CLASS_VENDOR_START) &&
13510Sstevel@tonic-gate (class <= MAD_MGMT_CLASS_VENDOR_END)) {
13520Sstevel@tonic-gate *dest_classp = VENDOR_09_MANAGER_AGENT +
13530Sstevel@tonic-gate (class - MAD_MGMT_CLASS_VENDOR_START);
13540Sstevel@tonic-gate } else if ((class >= MAD_MGMT_CLASS_VENDOR2_START) &&
13550Sstevel@tonic-gate (class <= MAD_MGMT_CLASS_VENDOR2_END)) {
13560Sstevel@tonic-gate *dest_classp = VENDOR_30_MANAGER_AGENT +
13570Sstevel@tonic-gate (class - MAD_MGMT_CLASS_VENDOR2_START);
13580Sstevel@tonic-gate } else if ((class >= MAD_MGMT_CLASS_APPLICATION_START) &&
13590Sstevel@tonic-gate (class <= MAD_MGMT_CLASS_APPLICATION_END)) {
13600Sstevel@tonic-gate *dest_classp = APPLICATION_10_MANAGER_AGENT +
13610Sstevel@tonic-gate (class - MAD_MGMT_CLASS_APPLICATION_START);
13620Sstevel@tonic-gate }
13630Sstevel@tonic-gate
13640Sstevel@tonic-gate break;
13650Sstevel@tonic-gate }
13660Sstevel@tonic-gate
13670Sstevel@tonic-gate if (*dest_classp == 0) {
13680Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
13690Sstevel@tonic-gate ibmf_i_get_class_type_err, IBMF_TNF_TRACE, "",
13700Sstevel@tonic-gate "ibmf_i_get_class(): %s, class = 0x%x\n",
13710Sstevel@tonic-gate tnf_string, msg, "invalid class", tnf_opaque, class, class);
13720Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_get_class_end,
13730Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_get_class() exit\n");
13740Sstevel@tonic-gate return (IBMF_FAILURE);
13750Sstevel@tonic-gate }
13760Sstevel@tonic-gate
13770Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4,
13780Sstevel@tonic-gate ibmf_i_get_class_end, IBMF_TNF_TRACE, "",
13790Sstevel@tonic-gate "ibmf_i_get_class() exit, class = 0x%x\n",
13800Sstevel@tonic-gate tnf_opaque, class, *dest_classp);
13810Sstevel@tonic-gate
13820Sstevel@tonic-gate return (IBMF_SUCCESS);
13830Sstevel@tonic-gate }
13840Sstevel@tonic-gate
13850Sstevel@tonic-gate /*
13860Sstevel@tonic-gate * ibmf_get_mod_name():
13870Sstevel@tonic-gate * Constructs the module name based on the naming convention described in
13880Sstevel@tonic-gate * PSARC case 2003/753.
13890Sstevel@tonic-gate * The name should be "sunwibmgt<MgtClass><a_m>
13900Sstevel@tonic-gate * where:
13910Sstevel@tonic-gate * MgtClass = Management class field in the MAD header.
13920Sstevel@tonic-gate * Two lower-case characters are used to represent
13930Sstevel@tonic-gate * this 8-bit value as 2 hex digits.
13940Sstevel@tonic-gate * a_m = "a" if the client is an agent-only module
13950Sstevel@tonic-gate * "m" if the client is a manager-only module
13960Sstevel@tonic-gate * "" if the client is both agent and manager.
13970Sstevel@tonic-gate *
13980Sstevel@tonic-gate * Input Argument
13990Sstevel@tonic-gate * mad_class management class in the MAD header
14000Sstevel@tonic-gate * class IBMF management class of incoming MAD
14010Sstevel@tonic-gate *
14020Sstevel@tonic-gate * Output Argument
14030Sstevel@tonic-gate * modname pointer to the character array that holds the module name
14040Sstevel@tonic-gate *
14050Sstevel@tonic-gate * Status
14060Sstevel@tonic-gate * None
14070Sstevel@tonic-gate */
14080Sstevel@tonic-gate static void
ibmf_get_mod_name(uint8_t mad_class,ibmf_client_type_t class,char * modname)14090Sstevel@tonic-gate ibmf_get_mod_name(uint8_t mad_class, ibmf_client_type_t class, char *modname)
14100Sstevel@tonic-gate {
14110Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_get_mod_name_start,
14120Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_get_mod_name_qphdl() enter\n");
14130Sstevel@tonic-gate
14140Sstevel@tonic-gate if (AGENT_CLASS(class)) {
14150Sstevel@tonic-gate (void) sprintf(modname, "sunwibmgt%02xa", mad_class);
14160Sstevel@tonic-gate } else if (MANAGER_CLASS(class)) {
14170Sstevel@tonic-gate (void) sprintf(modname, "sunwibmgt%02xm", mad_class);
14180Sstevel@tonic-gate } else {
14190Sstevel@tonic-gate /* AGENT+MANAGER class */
14200Sstevel@tonic-gate (void) sprintf(modname, "sunwibmgt%02x", mad_class);
14210Sstevel@tonic-gate }
14220Sstevel@tonic-gate
14230Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3, ibmf_get_mod_name,
14240Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_get_mod_name(): name = %s\n",
14250Sstevel@tonic-gate tnf_string, msg, modname);
14260Sstevel@tonic-gate
14270Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_get_mod_name_end,
14280Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_get_mod_name() exit\n");
14290Sstevel@tonic-gate }
14300Sstevel@tonic-gate
14310Sstevel@tonic-gate /*
14320Sstevel@tonic-gate * ibmf_send_busy():
14330Sstevel@tonic-gate *
14340Sstevel@tonic-gate * When a MAD request is received for an IB mandatory agent (BMA or PMA),
14350Sstevel@tonic-gate * which has not yet registered with IBMF, IBMF returns a BUSY MAD
14360Sstevel@tonic-gate * to the source of the request to solicit a retry while IBMF attempts
14370Sstevel@tonic-gate * to load the mandatory agent.
14380Sstevel@tonic-gate * A temporary, alternate QP is allocated for the purpose of sending the
14390Sstevel@tonic-gate * MAD. This QP is configured to be in the same partition as the manager
14400Sstevel@tonic-gate * that sent the request.
14410Sstevel@tonic-gate *
14420Sstevel@tonic-gate * Input Argument
14430Sstevel@tonic-gate * modlargsp Pointer to ibmf_mod_load_args_t structure
14440Sstevel@tonic-gate *
14450Sstevel@tonic-gate * Output Argument
14460Sstevel@tonic-gate * None
14470Sstevel@tonic-gate *
14480Sstevel@tonic-gate * Status
14490Sstevel@tonic-gate * None
14500Sstevel@tonic-gate */
14510Sstevel@tonic-gate static void
ibmf_send_busy(ibmf_mod_load_args_t * modlargsp)14520Sstevel@tonic-gate ibmf_send_busy(ibmf_mod_load_args_t *modlargsp)
14530Sstevel@tonic-gate {
14540Sstevel@tonic-gate ibmf_ci_t *cip = modlargsp->cip;
14550Sstevel@tonic-gate ibmf_recv_wqe_t *recv_wqep = modlargsp->recv_wqep;
14560Sstevel@tonic-gate ibt_wr_ds_t sgl[1];
14570Sstevel@tonic-gate ibmf_send_wqe_t *send_wqep;
14580Sstevel@tonic-gate ibt_send_wr_t *swrp;
14590Sstevel@tonic-gate ibmf_msg_impl_t *msgimplp;
14600Sstevel@tonic-gate ibmf_ud_dest_t *ibmf_ud_dest;
14610Sstevel@tonic-gate ibt_ud_dest_t *ud_dest;
14620Sstevel@tonic-gate ib_mad_hdr_t *smadhdrp, *rmadhdrp;
14630Sstevel@tonic-gate ibt_adds_vect_t adds_vec;
14640Sstevel@tonic-gate ibt_wc_t *wcp = &recv_wqep->recv_wc;
14650Sstevel@tonic-gate ibt_status_t ibtstatus;
14660Sstevel@tonic-gate uint_t num_work_reqs;
14670Sstevel@tonic-gate ibt_qp_alloc_attr_t qp_attrs;
14680Sstevel@tonic-gate ibt_qp_info_t qp_modify_attr;
14690Sstevel@tonic-gate ibt_chan_sizes_t qp_sizes;
14700Sstevel@tonic-gate ib_qpn_t qp_num;
14710Sstevel@tonic-gate ibt_qp_hdl_t ibt_qp_handle;
14720Sstevel@tonic-gate ibt_mr_hdl_t mem_hdl;
14730Sstevel@tonic-gate ibt_mr_desc_t mem_desc;
14740Sstevel@tonic-gate ibt_mr_attr_t mem_attr;
14750Sstevel@tonic-gate
14760Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_send_busy_start,
14770Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_send_busy() enter\n");
14780Sstevel@tonic-gate
14790Sstevel@tonic-gate /* setup the qp attrs for the alloc call */
14800Sstevel@tonic-gate qp_attrs.qp_scq_hdl = cip->ci_alt_cq_handle;
14810Sstevel@tonic-gate qp_attrs.qp_rcq_hdl = cip->ci_alt_cq_handle;
14820Sstevel@tonic-gate qp_attrs.qp_pd_hdl = cip->ci_pd;
14830Sstevel@tonic-gate qp_attrs.qp_sizes.cs_sq_sgl = IBMF_MAX_SQ_WR_SGL_ELEMENTS;
14840Sstevel@tonic-gate qp_attrs.qp_sizes.cs_rq_sgl = IBMF_MAX_RQ_WR_SGL_ELEMENTS;
14850Sstevel@tonic-gate qp_attrs.qp_sizes.cs_sq = ibmf_send_wqes_posted_per_qp;
14860Sstevel@tonic-gate qp_attrs.qp_sizes.cs_rq = ibmf_recv_wqes_posted_per_qp;
14870Sstevel@tonic-gate qp_attrs.qp_flags = IBT_ALL_SIGNALED;
14880Sstevel@tonic-gate qp_attrs.qp_alloc_flags = IBT_QP_NO_FLAGS;
14890Sstevel@tonic-gate
14900Sstevel@tonic-gate /* request IBT for a qp with the desired attributes */
14910Sstevel@tonic-gate ibtstatus = ibt_alloc_qp(cip->ci_ci_handle, IBT_UD_RQP,
14920Sstevel@tonic-gate &qp_attrs, &qp_sizes, &qp_num, &ibt_qp_handle);
14930Sstevel@tonic-gate if (ibtstatus != IBT_SUCCESS) {
14940Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1, ibmf_send_busy_err,
14950Sstevel@tonic-gate IBMF_TNF_ERROR, "", "ibmf_send_busy(): %s, status = %d\n",
14960Sstevel@tonic-gate tnf_string, msg, "failed to allocate alternate QP",
14970Sstevel@tonic-gate tnf_int, ibt_status, ibtstatus);
14980Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_send_busy_end,
14990Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_send_busy() exit\n");
15000Sstevel@tonic-gate return;
15010Sstevel@tonic-gate }
15020Sstevel@tonic-gate
15030Sstevel@tonic-gate qp_modify_attr.qp_trans = IBT_UD_SRV;
15040Sstevel@tonic-gate qp_modify_attr.qp_flags = IBT_CEP_NO_FLAGS;
15050Sstevel@tonic-gate qp_modify_attr.qp_transport.ud.ud_qkey = IB_GSI_QKEY;
15060Sstevel@tonic-gate qp_modify_attr.qp_transport.ud.ud_sq_psn = 0;
15070Sstevel@tonic-gate qp_modify_attr.qp_transport.ud.ud_pkey_ix = wcp->wc_pkey_ix;
15080Sstevel@tonic-gate qp_modify_attr.qp_transport.ud.ud_port = recv_wqep->recv_port_num;
15090Sstevel@tonic-gate
15100Sstevel@tonic-gate /* call the IB transport to initialize the QP */
15110Sstevel@tonic-gate ibtstatus = ibt_initialize_qp(ibt_qp_handle, &qp_modify_attr);
15120Sstevel@tonic-gate if (ibtstatus != IBT_SUCCESS) {
15130Sstevel@tonic-gate (void) ibt_free_qp(ibt_qp_handle);
15140Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1, ibmf_send_busy_err,
15150Sstevel@tonic-gate IBMF_TNF_ERROR, "", "ibmf_send_busy(): %s, status = %d\n",
15160Sstevel@tonic-gate tnf_string, msg, "failed to initialize alternate QP",
15170Sstevel@tonic-gate tnf_int, ibt_status, ibtstatus);
15180Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_send_busy_end,
15190Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_send_busy() exit\n");
15200Sstevel@tonic-gate return;
15210Sstevel@tonic-gate }
15220Sstevel@tonic-gate
15230Sstevel@tonic-gate /* allocate the message context */
15240Sstevel@tonic-gate msgimplp = (ibmf_msg_impl_t *)kmem_zalloc(sizeof (ibmf_msg_impl_t),
15250Sstevel@tonic-gate KM_SLEEP);
15260Sstevel@tonic-gate
15270Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*msgimplp))
15280Sstevel@tonic-gate
15290Sstevel@tonic-gate ibmf_i_pop_ud_dest_thread(cip);
15300Sstevel@tonic-gate
15310Sstevel@tonic-gate /*
15320Sstevel@tonic-gate * Get a UD dest structure from the pool, this will not fail
15330Sstevel@tonic-gate * because ibmf_i_pop_ud_dest_thread() calls
15340Sstevel@tonic-gate * ibmf_i_populate_ud_dest_list with the KM_SLEEP flag.
15350Sstevel@tonic-gate */
15360Sstevel@tonic-gate ibmf_ud_dest = ibmf_i_get_ud_dest(cip);
15370Sstevel@tonic-gate
15380Sstevel@tonic-gate msgimplp->im_ibmf_ud_dest = ibmf_ud_dest;
15390Sstevel@tonic-gate msgimplp->im_ud_dest = &ibmf_ud_dest->ud_dest;
15400Sstevel@tonic-gate msgimplp->im_qp_hdl = NULL;
15410Sstevel@tonic-gate
15420Sstevel@tonic-gate /*
15430Sstevel@tonic-gate * Reset send_done to indicate we have not received the completion
15440Sstevel@tonic-gate * for this send yet.
15450Sstevel@tonic-gate */
15460Sstevel@tonic-gate msgimplp->im_trans_state_flags &= ~IBMF_TRANS_STATE_FLAG_SEND_DONE;
15470Sstevel@tonic-gate
15480Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*send_wqep))
15490Sstevel@tonic-gate
15500Sstevel@tonic-gate /*
15510Sstevel@tonic-gate * Allocate resources needed to send a UD packet including the
15520Sstevel@tonic-gate * send WQE context
15530Sstevel@tonic-gate */
15540Sstevel@tonic-gate send_wqep = (ibmf_send_wqe_t *)kmem_zalloc(sizeof (ibmf_send_wqe_t),
15550Sstevel@tonic-gate KM_SLEEP);
15560Sstevel@tonic-gate send_wqep->send_mem = (void *)kmem_zalloc(IBMF_MEM_PER_WQE, KM_SLEEP);
15570Sstevel@tonic-gate
15580Sstevel@tonic-gate mem_attr.mr_vaddr = (ib_vaddr_t)(uintptr_t)send_wqep->send_mem;
15590Sstevel@tonic-gate mem_attr.mr_len = IBMF_MEM_PER_WQE;
15600Sstevel@tonic-gate mem_attr.mr_flags = IBT_MR_SLEEP | IBT_MR_ENABLE_LOCAL_WRITE;
15610Sstevel@tonic-gate mem_attr.mr_as = NULL;
15620Sstevel@tonic-gate
15630Sstevel@tonic-gate /* Register the allocated memory */
15640Sstevel@tonic-gate ibtstatus = ibt_register_mr(cip->ci_ci_handle, cip->ci_pd, &mem_attr,
15650Sstevel@tonic-gate &mem_hdl, &mem_desc);
15660Sstevel@tonic-gate if (ibtstatus != IBT_SUCCESS) {
15678442SLida.Horn@Sun.COM kmem_free(send_wqep->send_mem, IBMF_MEM_PER_WQE);
15680Sstevel@tonic-gate kmem_free(send_wqep, sizeof (ibmf_send_wqe_t));
15690Sstevel@tonic-gate ibmf_i_put_ud_dest(cip, msgimplp->im_ibmf_ud_dest);
15700Sstevel@tonic-gate kmem_free(msgimplp, sizeof (ibmf_msg_impl_t));
15710Sstevel@tonic-gate (void) ibt_free_qp(ibt_qp_handle);
15720Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1, ibmf_send_busy_err,
15730Sstevel@tonic-gate IBMF_TNF_ERROR, "", "ibmf_send_busy(): %s, status = %d\n",
15740Sstevel@tonic-gate tnf_string, msg, "failed to register memory",
15750Sstevel@tonic-gate tnf_int, ibt_status, ibtstatus);
15760Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_send_busy_end,
15770Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_send_busy() exit\n");
15780Sstevel@tonic-gate return;
15790Sstevel@tonic-gate }
15800Sstevel@tonic-gate
15810Sstevel@tonic-gate send_wqep->send_sg_lkey = mem_desc.md_lkey;
15820Sstevel@tonic-gate send_wqep->send_mem_hdl = mem_hdl;
15830Sstevel@tonic-gate
15840Sstevel@tonic-gate swrp = &send_wqep->send_wr;
15850Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*swrp))
15860Sstevel@tonic-gate
15870Sstevel@tonic-gate /* use send wqe pointer as the WR ID */
15880Sstevel@tonic-gate swrp->wr_id = (ibt_wrid_t)(uintptr_t)send_wqep;
15890Sstevel@tonic-gate ASSERT(swrp->wr_id != NULL);
15900Sstevel@tonic-gate swrp->wr_flags = IBT_WR_NO_FLAGS;
15910Sstevel@tonic-gate swrp->wr_opcode = IBT_WRC_SEND;
15920Sstevel@tonic-gate swrp->wr_trans = IBT_UD_SRV;
15930Sstevel@tonic-gate
15940Sstevel@tonic-gate send_wqep->send_client = NULL;
15950Sstevel@tonic-gate send_wqep->send_msg = msgimplp;
15960Sstevel@tonic-gate
15970Sstevel@tonic-gate /* Initialize the scatter-gather list */
15980Sstevel@tonic-gate sgl[0].ds_va = (ib_vaddr_t)(uintptr_t)send_wqep->send_mem;
15990Sstevel@tonic-gate sgl[0].ds_key = send_wqep->send_sg_lkey;
16000Sstevel@tonic-gate sgl[0].ds_len = IBMF_MAD_SIZE;
16010Sstevel@tonic-gate
16020Sstevel@tonic-gate wcp = &recv_wqep->recv_wc;
16030Sstevel@tonic-gate
16040Sstevel@tonic-gate /* Initialize the address vector */
16050Sstevel@tonic-gate adds_vec.av_send_grh = B_FALSE;
16060Sstevel@tonic-gate adds_vec.av_dlid = wcp->wc_slid;
16070Sstevel@tonic-gate adds_vec.av_src_path = wcp->wc_path_bits;
16080Sstevel@tonic-gate adds_vec.av_srvl = 0;
16090Sstevel@tonic-gate adds_vec.av_srate = IBT_SRATE_1X;
16100Sstevel@tonic-gate adds_vec.av_port_num = recv_wqep->recv_port_num;
16110Sstevel@tonic-gate
16120Sstevel@tonic-gate ud_dest = msgimplp->im_ud_dest;
16130Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*ud_dest))
16140Sstevel@tonic-gate ud_dest->ud_qkey = IB_GSI_QKEY;
16150Sstevel@tonic-gate ud_dest->ud_dst_qpn = wcp->wc_qpn;
16160Sstevel@tonic-gate
16170Sstevel@tonic-gate /* modify the address handle with the address vector information */
16180Sstevel@tonic-gate ibtstatus = ibt_modify_ah(cip->ci_ci_handle, ud_dest->ud_ah, &adds_vec);
16190Sstevel@tonic-gate if (ibtstatus != IBT_SUCCESS) {
16200Sstevel@tonic-gate (void) ibt_deregister_mr(cip->ci_ci_handle, mem_hdl);
16218523SLida.Horn@Sun.COM kmem_free(send_wqep->send_mem, IBMF_MEM_PER_WQE);
16220Sstevel@tonic-gate kmem_free(send_wqep, sizeof (ibmf_send_wqe_t));
16230Sstevel@tonic-gate ibmf_i_put_ud_dest(cip, msgimplp->im_ibmf_ud_dest);
16240Sstevel@tonic-gate kmem_free(msgimplp, sizeof (ibmf_msg_impl_t));
16250Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1, ibmf_send_busy_err,
16260Sstevel@tonic-gate IBMF_TNF_ERROR, "", "ibmf_send_busy(): %s, status = %d\n",
16270Sstevel@tonic-gate tnf_string, msg, "ibt modify ah failed", tnf_uint,
16280Sstevel@tonic-gate ibt_status, ibtstatus);
16290Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_send_busy_end,
16300Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_send_busy(() exit\n");
16310Sstevel@tonic-gate return;
16320Sstevel@tonic-gate }
16330Sstevel@tonic-gate
16340Sstevel@tonic-gate bzero(send_wqep->send_mem, IBMF_MAD_SIZE);
16350Sstevel@tonic-gate
16360Sstevel@tonic-gate rmadhdrp = (ib_mad_hdr_t *)((uintptr_t)recv_wqep->recv_mem +
16370Sstevel@tonic-gate sizeof (ib_grh_t));
16380Sstevel@tonic-gate smadhdrp = (ib_mad_hdr_t *)send_wqep->send_mem;
16390Sstevel@tonic-gate
16400Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*rmadhdrp))
16410Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*smadhdrp))
16420Sstevel@tonic-gate
16430Sstevel@tonic-gate /* Set up the MAD header */
16440Sstevel@tonic-gate smadhdrp->BaseVersion = rmadhdrp->BaseVersion;
16450Sstevel@tonic-gate smadhdrp->MgmtClass = rmadhdrp->MgmtClass;
16460Sstevel@tonic-gate smadhdrp->ClassVersion = rmadhdrp->ClassVersion;
16470Sstevel@tonic-gate smadhdrp->R_Method = MAD_METHOD_GET_RESPONSE;
16480Sstevel@tonic-gate smadhdrp->Status = MAD_STATUS_BUSY;
16490Sstevel@tonic-gate smadhdrp->TransactionID = rmadhdrp->TransactionID;
16500Sstevel@tonic-gate smadhdrp->AttributeID = rmadhdrp->AttributeID;
16510Sstevel@tonic-gate smadhdrp->AttributeModifier = rmadhdrp->AttributeModifier;
16520Sstevel@tonic-gate
16530Sstevel@tonic-gate swrp->wr_sgl = sgl;
16540Sstevel@tonic-gate swrp->wr_nds = 1;
16550Sstevel@tonic-gate swrp->wr.ud.udwr_dest = msgimplp->im_ud_dest;
16560Sstevel@tonic-gate send_wqep->send_port_num = recv_wqep->recv_port_num;
16570Sstevel@tonic-gate send_wqep->send_qp_handle = ibt_qp_handle;
16580Sstevel@tonic-gate send_wqep->send_ibmf_qp_handle = NULL;
16590Sstevel@tonic-gate
16600Sstevel@tonic-gate /* Post the MAD to the IBT layer */
16610Sstevel@tonic-gate num_work_reqs = 1;
16620Sstevel@tonic-gate
16630Sstevel@tonic-gate ibtstatus = ibt_post_send(ibt_qp_handle, &send_wqep->send_wr,
16640Sstevel@tonic-gate num_work_reqs, NULL);
16650Sstevel@tonic-gate if (ibtstatus != IBT_SUCCESS) {
16660Sstevel@tonic-gate (void) ibt_deregister_mr(cip->ci_ci_handle, mem_hdl);
16678523SLida.Horn@Sun.COM kmem_free(send_wqep->send_mem, IBMF_MEM_PER_WQE);
16680Sstevel@tonic-gate kmem_free(send_wqep, sizeof (ibmf_send_wqe_t));
16690Sstevel@tonic-gate ibmf_i_put_ud_dest(cip, msgimplp->im_ibmf_ud_dest);
16700Sstevel@tonic-gate kmem_free(msgimplp, sizeof (ibmf_msg_impl_t));
16710Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
16720Sstevel@tonic-gate ibmf_send_busy_err, IBMF_TNF_TRACE, "",
16730Sstevel@tonic-gate "ibmf_send_busy(): %s, status = %d\n", tnf_string, msg,
16740Sstevel@tonic-gate "post send failure", tnf_uint, ibt_status, ibtstatus);
16750Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_send_busy_end,
16760Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_send_busy(() exit\n");
16770Sstevel@tonic-gate return;
16780Sstevel@tonic-gate }
16790Sstevel@tonic-gate
16800Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_send_busy_end,
16810Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_send_busy() exit\n");
16820Sstevel@tonic-gate }
16830Sstevel@tonic-gate
16840Sstevel@tonic-gate /*
16850Sstevel@tonic-gate * ibmf_module_load():
16860Sstevel@tonic-gate * This function attempts to load a client module that has not yet
16870Sstevel@tonic-gate * registered with IBMF at the time a request MAD arrives for it.
16880Sstevel@tonic-gate * Prior to loading the module, it sends a busy MAD to the sender of
16890Sstevel@tonic-gate * the request MAD, this soliciting a resend of the request MAD.
16900Sstevel@tonic-gate *
16910Sstevel@tonic-gate * Input Argument
16920Sstevel@tonic-gate * modlargsp Pointer to ibmf_mod_load_args_t structure
16930Sstevel@tonic-gate *
16940Sstevel@tonic-gate * Output Argument
16950Sstevel@tonic-gate * None
16960Sstevel@tonic-gate *
16970Sstevel@tonic-gate * Status
16980Sstevel@tonic-gate * None
16990Sstevel@tonic-gate */
17000Sstevel@tonic-gate static void
ibmf_module_load(void * taskq_arg)17010Sstevel@tonic-gate ibmf_module_load(void *taskq_arg)
17020Sstevel@tonic-gate {
17030Sstevel@tonic-gate char *modname;
17040Sstevel@tonic-gate ibmf_mod_load_args_t *modlargsp = (ibmf_mod_load_args_t *)taskq_arg;
17050Sstevel@tonic-gate ibmf_ci_t *cip = modlargsp->cip;
17060Sstevel@tonic-gate ibmf_recv_wqe_t *recv_wqep = modlargsp->recv_wqep;
17070Sstevel@tonic-gate ibmf_client_type_t class = modlargsp->ibmf_class;
17080Sstevel@tonic-gate
17090Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_module_load_start,
17100Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_module_load_busy() enter\n");
17110Sstevel@tonic-gate modname = modlargsp->modname;
17120Sstevel@tonic-gate
17130Sstevel@tonic-gate if (IS_MANDATORY_CLASS(class)) {
17140Sstevel@tonic-gate ibmf_send_busy(modlargsp);
17150Sstevel@tonic-gate }
17160Sstevel@tonic-gate
17170Sstevel@tonic-gate if (modload("misc", modname) < 0) {
17180Sstevel@tonic-gate (void) ibmf_i_repost_recv_buffer(cip, recv_wqep);
17190Sstevel@tonic-gate kmem_free(modlargsp, sizeof (ibmf_mod_load_args_t));
17200Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L1, ibmf_module_load_error,
17210Sstevel@tonic-gate IBMF_TNF_TRACE, "",
17220Sstevel@tonic-gate "ibmf_module_load(): modload failed for %s\n",
17230Sstevel@tonic-gate tnf_string, module, modname);
17240Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_module_load_end,
17250Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_module_load() exit\n");
17260Sstevel@tonic-gate return;
17270Sstevel@tonic-gate }
17280Sstevel@tonic-gate
17290Sstevel@tonic-gate (void) ibmf_i_repost_recv_buffer(cip, recv_wqep);
17300Sstevel@tonic-gate
17310Sstevel@tonic-gate kmem_free(modlargsp, sizeof (ibmf_mod_load_args_t));
17320Sstevel@tonic-gate
17330Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_module_load_end,
17340Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_module_load_busy() exit\n");
17350Sstevel@tonic-gate }
1736