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
58580SBill.Taylor@Sun.COM * Common Development and Distribution License (the "License").
68580SBill.Taylor@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 */
21*12787SLida.Horn@Oracle.COM
220Sstevel@tonic-gate /*
23*12787SLida.Horn@Oracle.COM * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate /*
270Sstevel@tonic-gate * This file implements the client interfaces of the IBMF.
280Sstevel@tonic-gate */
290Sstevel@tonic-gate
300Sstevel@tonic-gate #include <sys/ib/mgt/ibmf/ibmf_impl.h>
310Sstevel@tonic-gate #include <sys/ib/mgt/ib_mad.h>
320Sstevel@tonic-gate
330Sstevel@tonic-gate extern ibmf_state_t *ibmf_statep;
340Sstevel@tonic-gate
350Sstevel@tonic-gate /* global settable */
360Sstevel@tonic-gate int ibmf_send_wqes_per_port = IBMF_MAX_SQ_WRE;
370Sstevel@tonic-gate int ibmf_recv_wqes_per_port = IBMF_MAX_RQ_WRE;
380Sstevel@tonic-gate int ibmf_send_wqes_posted_per_qp = IBMF_MAX_POSTED_SQ_PER_QP;
390Sstevel@tonic-gate int ibmf_recv_wqes_posted_per_qp = IBMF_MAX_POSTED_RQ_PER_QP;
400Sstevel@tonic-gate
410Sstevel@tonic-gate int ibmf_taskq_max_tasks = 1024;
420Sstevel@tonic-gate
430Sstevel@tonic-gate int ibmf_trace_level = DPRINT_L0;
440Sstevel@tonic-gate
450Sstevel@tonic-gate #define IBMF_MAD_CL_HDR_OFF_1 0
460Sstevel@tonic-gate #define IBMF_MAD_CL_HDR_OFF_2 12
470Sstevel@tonic-gate #define IBMF_MAD_CL_HDR_SZ_1 40
480Sstevel@tonic-gate #define IBMF_MAD_CL_HDR_SZ_2 20
490Sstevel@tonic-gate #define IBMF_MAD_CL_HDR_SZ_3 0
500Sstevel@tonic-gate #define IBMF_MAD_CL_HDR_SZ_4 4
510Sstevel@tonic-gate
520Sstevel@tonic-gate #define IBMF_VALID_CLIENT_TYPE(client_type) \
530Sstevel@tonic-gate ((client_type) == SUBN_AGENT || \
540Sstevel@tonic-gate (client_type) == SUBN_MANAGER || \
550Sstevel@tonic-gate (client_type) == SUBN_ADM_AGENT || \
560Sstevel@tonic-gate (client_type) == SUBN_ADM_MANAGER || \
570Sstevel@tonic-gate (client_type) == PERF_AGENT || \
580Sstevel@tonic-gate (client_type) == PERF_MANAGER || \
590Sstevel@tonic-gate (client_type) == BM_AGENT || \
600Sstevel@tonic-gate (client_type) == BM_MANAGER || \
610Sstevel@tonic-gate (client_type) == DEV_MGT_AGENT || \
620Sstevel@tonic-gate (client_type) == DEV_MGT_MANAGER || \
630Sstevel@tonic-gate (client_type) == COMM_MGT_MANAGER_AGENT || \
640Sstevel@tonic-gate (client_type) == SNMP_MANAGER_AGENT || \
650Sstevel@tonic-gate (client_type) == VENDOR_09_MANAGER_AGENT || \
660Sstevel@tonic-gate (client_type) == VENDOR_0A_MANAGER_AGENT || \
670Sstevel@tonic-gate (client_type) == VENDOR_0B_MANAGER_AGENT || \
680Sstevel@tonic-gate (client_type) == VENDOR_0C_MANAGER_AGENT || \
690Sstevel@tonic-gate (client_type) == VENDOR_0D_MANAGER_AGENT || \
700Sstevel@tonic-gate (client_type) == VENDOR_0E_MANAGER_AGENT || \
710Sstevel@tonic-gate (client_type) == VENDOR_0F_MANAGER_AGENT || \
720Sstevel@tonic-gate (client_type) == VENDOR_30_MANAGER_AGENT || \
730Sstevel@tonic-gate (client_type) == VENDOR_31_MANAGER_AGENT || \
740Sstevel@tonic-gate (client_type) == VENDOR_32_MANAGER_AGENT || \
750Sstevel@tonic-gate (client_type) == VENDOR_33_MANAGER_AGENT || \
760Sstevel@tonic-gate (client_type) == VENDOR_34_MANAGER_AGENT || \
770Sstevel@tonic-gate (client_type) == VENDOR_35_MANAGER_AGENT || \
780Sstevel@tonic-gate (client_type) == VENDOR_36_MANAGER_AGENT || \
790Sstevel@tonic-gate (client_type) == VENDOR_37_MANAGER_AGENT || \
800Sstevel@tonic-gate (client_type) == VENDOR_38_MANAGER_AGENT || \
810Sstevel@tonic-gate (client_type) == VENDOR_39_MANAGER_AGENT || \
820Sstevel@tonic-gate (client_type) == VENDOR_3A_MANAGER_AGENT || \
830Sstevel@tonic-gate (client_type) == VENDOR_3B_MANAGER_AGENT || \
840Sstevel@tonic-gate (client_type) == VENDOR_3C_MANAGER_AGENT || \
850Sstevel@tonic-gate (client_type) == VENDOR_3D_MANAGER_AGENT || \
860Sstevel@tonic-gate (client_type) == VENDOR_3E_MANAGER_AGENT || \
870Sstevel@tonic-gate (client_type) == VENDOR_3F_MANAGER_AGENT || \
880Sstevel@tonic-gate (client_type) == VENDOR_40_MANAGER_AGENT || \
890Sstevel@tonic-gate (client_type) == VENDOR_41_MANAGER_AGENT || \
900Sstevel@tonic-gate (client_type) == VENDOR_42_MANAGER_AGENT || \
910Sstevel@tonic-gate (client_type) == VENDOR_43_MANAGER_AGENT || \
920Sstevel@tonic-gate (client_type) == VENDOR_44_MANAGER_AGENT || \
930Sstevel@tonic-gate (client_type) == VENDOR_45_MANAGER_AGENT || \
940Sstevel@tonic-gate (client_type) == VENDOR_46_MANAGER_AGENT || \
950Sstevel@tonic-gate (client_type) == VENDOR_47_MANAGER_AGENT || \
960Sstevel@tonic-gate (client_type) == VENDOR_48_MANAGER_AGENT || \
970Sstevel@tonic-gate (client_type) == VENDOR_49_MANAGER_AGENT || \
980Sstevel@tonic-gate (client_type) == VENDOR_4A_MANAGER_AGENT || \
990Sstevel@tonic-gate (client_type) == VENDOR_4B_MANAGER_AGENT || \
1000Sstevel@tonic-gate (client_type) == VENDOR_4C_MANAGER_AGENT || \
1010Sstevel@tonic-gate (client_type) == VENDOR_4D_MANAGER_AGENT || \
1020Sstevel@tonic-gate (client_type) == VENDOR_4E_MANAGER_AGENT || \
1030Sstevel@tonic-gate (client_type) == VENDOR_4F_MANAGER_AGENT || \
1040Sstevel@tonic-gate (client_type) == APPLICATION_10_MANAGER_AGENT || \
1050Sstevel@tonic-gate (client_type) == APPLICATION_11_MANAGER_AGENT || \
1060Sstevel@tonic-gate (client_type) == APPLICATION_12_MANAGER_AGENT || \
1070Sstevel@tonic-gate (client_type) == APPLICATION_13_MANAGER_AGENT || \
1080Sstevel@tonic-gate (client_type) == APPLICATION_14_MANAGER_AGENT || \
1090Sstevel@tonic-gate (client_type) == APPLICATION_15_MANAGER_AGENT || \
1100Sstevel@tonic-gate (client_type) == APPLICATION_16_MANAGER_AGENT || \
1110Sstevel@tonic-gate (client_type) == APPLICATION_17_MANAGER_AGENT || \
1120Sstevel@tonic-gate (client_type) == APPLICATION_18_MANAGER_AGENT || \
1130Sstevel@tonic-gate (client_type) == APPLICATION_19_MANAGER_AGENT || \
1140Sstevel@tonic-gate (client_type) == APPLICATION_1A_MANAGER_AGENT || \
1150Sstevel@tonic-gate (client_type) == APPLICATION_1B_MANAGER_AGENT || \
1160Sstevel@tonic-gate (client_type) == APPLICATION_1C_MANAGER_AGENT || \
1170Sstevel@tonic-gate (client_type) == APPLICATION_1D_MANAGER_AGENT || \
1180Sstevel@tonic-gate (client_type) == APPLICATION_1E_MANAGER_AGENT || \
1190Sstevel@tonic-gate (client_type) == APPLICATION_1F_MANAGER_AGENT || \
1200Sstevel@tonic-gate (client_type) == APPLICATION_20_MANAGER_AGENT || \
1210Sstevel@tonic-gate (client_type) == APPLICATION_21_MANAGER_AGENT || \
1220Sstevel@tonic-gate (client_type) == APPLICATION_22_MANAGER_AGENT || \
1230Sstevel@tonic-gate (client_type) == APPLICATION_23_MANAGER_AGENT || \
1240Sstevel@tonic-gate (client_type) == APPLICATION_24_MANAGER_AGENT || \
1250Sstevel@tonic-gate (client_type) == APPLICATION_25_MANAGER_AGENT || \
1260Sstevel@tonic-gate (client_type) == APPLICATION_26_MANAGER_AGENT || \
1270Sstevel@tonic-gate (client_type) == APPLICATION_27_MANAGER_AGENT || \
1280Sstevel@tonic-gate (client_type) == APPLICATION_28_MANAGER_AGENT || \
1290Sstevel@tonic-gate (client_type) == APPLICATION_29_MANAGER_AGENT || \
1300Sstevel@tonic-gate (client_type) == APPLICATION_2A_MANAGER_AGENT || \
1310Sstevel@tonic-gate (client_type) == APPLICATION_2B_MANAGER_AGENT || \
1320Sstevel@tonic-gate (client_type) == APPLICATION_2C_MANAGER_AGENT || \
1330Sstevel@tonic-gate (client_type) == APPLICATION_2D_MANAGER_AGENT || \
1340Sstevel@tonic-gate (client_type) == APPLICATION_2E_MANAGER_AGENT || \
1350Sstevel@tonic-gate (client_type) == APPLICATION_2F_MANAGER_AGENT || \
1360Sstevel@tonic-gate (client_type) == UNIVERSAL_CLASS)
1370Sstevel@tonic-gate
1380Sstevel@tonic-gate static ibmf_ci_t *ibmf_i_lookup_ci(ib_guid_t ci_guid);
1390Sstevel@tonic-gate static int ibmf_i_init_ci(ibmf_register_info_t *client_infop,
1400Sstevel@tonic-gate ibmf_ci_t *cip);
1410Sstevel@tonic-gate static void ibmf_i_uninit_ci(ibmf_ci_t *cip);
1420Sstevel@tonic-gate static void ibmf_i_init_ci_done(ibmf_ci_t *cip);
1430Sstevel@tonic-gate static void ibmf_i_uninit_ci_done(ibmf_ci_t *cip);
1440Sstevel@tonic-gate static int ibmf_i_init_qp(ibmf_ci_t *ibmf_cip, ibmf_qp_t *qpp);
1450Sstevel@tonic-gate static void ibmf_i_uninit_qp(ibmf_ci_t *ibmf_cip, ibmf_qp_t *qpp);
1460Sstevel@tonic-gate static int ibmf_i_init_cqs(ibmf_ci_t *cip);
1470Sstevel@tonic-gate static void ibmf_i_fini_cqs(ibmf_ci_t *cip);
1480Sstevel@tonic-gate static void ibmf_i_init_qplist(ibmf_ci_t *ibmf_cip);
1490Sstevel@tonic-gate static void ibmf_i_fini_qplist(ibmf_ci_t *ibmf_cip);
1500Sstevel@tonic-gate static int ibmf_i_lookup_client_by_info(ibmf_ci_t *ibmf_cip,
1510Sstevel@tonic-gate ibmf_register_info_t *ir_client, ibmf_client_t **clientpp);
1520Sstevel@tonic-gate
1530Sstevel@tonic-gate /*
1540Sstevel@tonic-gate * ibmf_init():
1550Sstevel@tonic-gate * Initializes module state and registers with the IBT framework.
1560Sstevel@tonic-gate * Returns 0 if initialization was successful, else returns non-zero.
1570Sstevel@tonic-gate */
1580Sstevel@tonic-gate int
ibmf_init(void)1590Sstevel@tonic-gate ibmf_init(void)
1600Sstevel@tonic-gate {
1610Sstevel@tonic-gate ibt_status_t status;
1620Sstevel@tonic-gate ibt_clnt_hdl_t ibmf_ibt_handle;
1630Sstevel@tonic-gate
1640Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_init_start,
1650Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_init() enter\n");
1660Sstevel@tonic-gate
1670Sstevel@tonic-gate /* setup the IBT module information */
1688580SBill.Taylor@Sun.COM ibmf_statep->ibmf_ibt_modinfo.mi_ibt_version = IBTI_V_CURR;
1690Sstevel@tonic-gate ibmf_statep->ibmf_ibt_modinfo.mi_clnt_class = IBT_IBMA;
1700Sstevel@tonic-gate ibmf_statep->ibmf_ibt_modinfo.mi_async_handler
1710Sstevel@tonic-gate = ibmf_ibt_async_handler;
1720Sstevel@tonic-gate ibmf_statep->ibmf_ibt_modinfo.mi_reserved = NULL;
1730Sstevel@tonic-gate ibmf_statep->ibmf_ibt_modinfo.mi_clnt_name = "ibmf";
1740Sstevel@tonic-gate
1750Sstevel@tonic-gate /* setup a connection to IB transport layer (IBTF) */
1760Sstevel@tonic-gate status = ibt_attach(&ibmf_statep->ibmf_ibt_modinfo, (void *)NULL,
1770Sstevel@tonic-gate (void *)NULL, (void *)&ibmf_ibt_handle);
1780Sstevel@tonic-gate if (status != IBT_SUCCESS) {
1790Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1, ibmf_init_err,
1800Sstevel@tonic-gate IBMF_TNF_ERROR, "", "%s, status = %d\n", tnf_string, msg,
1810Sstevel@tonic-gate "ibt attach failed", tnf_uint, status, status);
1820Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_init_end,
1830Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_init() exit\n");
1840Sstevel@tonic-gate return (1);
1850Sstevel@tonic-gate }
1860Sstevel@tonic-gate
1870Sstevel@tonic-gate /* initialize the IBMF state context */
1880Sstevel@tonic-gate ibmf_statep->ibmf_ibt_handle = ibmf_ibt_handle;
1890Sstevel@tonic-gate ibmf_statep->ibmf_ci_list = (ibmf_ci_t *)NULL;
1900Sstevel@tonic-gate ibmf_statep->ibmf_ci_list_tail = (ibmf_ci_t *)NULL;
1910Sstevel@tonic-gate mutex_init(&ibmf_statep->ibmf_mutex, NULL, MUTEX_DRIVER, NULL);
1920Sstevel@tonic-gate ibmf_statep->ibmf_cq_handler = ibmf_i_mad_completions;
1930Sstevel@tonic-gate
1940Sstevel@tonic-gate ibmf_statep->ibmf_taskq = taskq_create("ibmf_taskq", IBMF_TASKQ_1THREAD,
1950Sstevel@tonic-gate MINCLSYSPRI, 1, ibmf_taskq_max_tasks, TASKQ_PREPOPULATE);
1960Sstevel@tonic-gate
1970Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_init_end,
1980Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_init() exit\n");
1990Sstevel@tonic-gate
2000Sstevel@tonic-gate return (0);
2010Sstevel@tonic-gate }
2020Sstevel@tonic-gate
2030Sstevel@tonic-gate /*
2040Sstevel@tonic-gate * ibmf_fini():
2050Sstevel@tonic-gate * Cleans up module state resources and unregisters from IBT framework.
2060Sstevel@tonic-gate */
2070Sstevel@tonic-gate int
ibmf_fini(void)2080Sstevel@tonic-gate ibmf_fini(void)
2090Sstevel@tonic-gate {
2100Sstevel@tonic-gate ibmf_ci_t *cip;
2110Sstevel@tonic-gate ibmf_ci_t *tcip;
2120Sstevel@tonic-gate ibt_status_t status;
2130Sstevel@tonic-gate
2140Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_fini_start,
2150Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_fini() enter\n");
2160Sstevel@tonic-gate
2170Sstevel@tonic-gate ASSERT(MUTEX_NOT_HELD(&ibmf_statep->ibmf_mutex));
2180Sstevel@tonic-gate
2190Sstevel@tonic-gate mutex_enter(&ibmf_statep->ibmf_mutex);
2200Sstevel@tonic-gate
2210Sstevel@tonic-gate /* free all the Channel Interface (CI) context structures */
2220Sstevel@tonic-gate cip = ibmf_statep->ibmf_ci_list;
2230Sstevel@tonic-gate tcip = NULL;
2240Sstevel@tonic-gate while (cip != (ibmf_ci_t *)NULL) {
2250Sstevel@tonic-gate
2260Sstevel@tonic-gate mutex_enter(&cip->ci_mutex);
2270Sstevel@tonic-gate ASSERT((cip->ci_state == IBMF_CI_STATE_PRESENT && cip->ci_ref ==
2280Sstevel@tonic-gate 0) || (cip->ci_state == IBMF_CI_STATE_GONE));
2290Sstevel@tonic-gate ASSERT(cip->ci_init_state == IBMF_CI_INIT_HCA_LINKED);
2300Sstevel@tonic-gate ASSERT(cip->ci_qp_list == NULL && cip->ci_qp_list_tail == NULL);
2310Sstevel@tonic-gate if (tcip != (ibmf_ci_t *)NULL)
2320Sstevel@tonic-gate tcip->ci_next = cip->ci_next;
2330Sstevel@tonic-gate if (ibmf_statep->ibmf_ci_list_tail == cip)
2340Sstevel@tonic-gate ibmf_statep->ibmf_ci_list_tail = NULL;
2350Sstevel@tonic-gate if (ibmf_statep->ibmf_ci_list == cip)
2360Sstevel@tonic-gate ibmf_statep->ibmf_ci_list = cip->ci_next;
2370Sstevel@tonic-gate tcip = cip->ci_next;
2380Sstevel@tonic-gate mutex_exit(&cip->ci_mutex);
2390Sstevel@tonic-gate /* free up the ci structure */
2400Sstevel@tonic-gate if (cip->ci_port_kstatp != NULL) {
2410Sstevel@tonic-gate kstat_delete(cip->ci_port_kstatp);
2420Sstevel@tonic-gate }
2430Sstevel@tonic-gate mutex_destroy(&cip->ci_mutex);
2440Sstevel@tonic-gate mutex_destroy(&cip->ci_clients_mutex);
2450Sstevel@tonic-gate mutex_destroy(&cip->ci_wqe_mutex);
2460Sstevel@tonic-gate cv_destroy(&cip->ci_state_cv);
2470Sstevel@tonic-gate cv_destroy(&cip->ci_wqes_cv);
2480Sstevel@tonic-gate kmem_free((void *) cip, sizeof (ibmf_ci_t));
2490Sstevel@tonic-gate cip = tcip;
2500Sstevel@tonic-gate }
2510Sstevel@tonic-gate
2520Sstevel@tonic-gate ASSERT(ibmf_statep->ibmf_ci_list == NULL);
2530Sstevel@tonic-gate ASSERT(ibmf_statep->ibmf_ci_list_tail == NULL);
2540Sstevel@tonic-gate
2550Sstevel@tonic-gate taskq_destroy(ibmf_statep->ibmf_taskq);
2560Sstevel@tonic-gate
2570Sstevel@tonic-gate mutex_exit(&ibmf_statep->ibmf_mutex);
2580Sstevel@tonic-gate
2590Sstevel@tonic-gate /* detach from IBTF */
2600Sstevel@tonic-gate status = ibt_detach(ibmf_statep->ibmf_ibt_handle);
2610Sstevel@tonic-gate if (status != IBT_SUCCESS) {
2620Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1, ibmf_fini_err,
2630Sstevel@tonic-gate IBMF_TNF_ERROR, "", "%s, status = %d\n", tnf_string, msg,
2640Sstevel@tonic-gate "ibt detach error", tnf_uint, status, status);
2650Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_fini_end,
2660Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_fini() exit\n");
2670Sstevel@tonic-gate return (1);
2680Sstevel@tonic-gate }
2690Sstevel@tonic-gate
2700Sstevel@tonic-gate mutex_destroy(&ibmf_statep->ibmf_mutex);
2710Sstevel@tonic-gate
2720Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_fini_end,
2730Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_fini() exit\n");
2740Sstevel@tonic-gate
2750Sstevel@tonic-gate return (0);
2760Sstevel@tonic-gate }
2770Sstevel@tonic-gate
2780Sstevel@tonic-gate /*
2790Sstevel@tonic-gate * ibmf_i_validate_class_mask():
2800Sstevel@tonic-gate * Checks client type value in client information structure.
2810Sstevel@tonic-gate */
2820Sstevel@tonic-gate int
ibmf_i_validate_class_mask(ibmf_register_info_t * client_infop)2830Sstevel@tonic-gate ibmf_i_validate_class_mask(ibmf_register_info_t *client_infop)
2840Sstevel@tonic-gate {
2850Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4,
2860Sstevel@tonic-gate ibmf_i_validate_class_mask_start, IBMF_TNF_TRACE, "",
2870Sstevel@tonic-gate "ibmf_i_validate_class_mask() enter, client_infop = %p\n",
2880Sstevel@tonic-gate tnf_opaque, client_infop, client_infop);
2890Sstevel@tonic-gate
2900Sstevel@tonic-gate if (IBMF_VALID_CLIENT_TYPE(client_infop->ir_client_class) == B_FALSE) {
2910Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
2920Sstevel@tonic-gate ibmf_i_validate_class_mask_err, IBMF_TNF_ERROR, "",
2930Sstevel@tonic-gate "%s, class = %x\n", tnf_string, msg,
2940Sstevel@tonic-gate "invalid class", tnf_uint, class,
2950Sstevel@tonic-gate client_infop->ir_client_class);
2960Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
2970Sstevel@tonic-gate ibmf_i_validate_class_mask_end, IBMF_TNF_TRACE, "",
2980Sstevel@tonic-gate "ibmf_i_validate_class_mask() exit\n");
2990Sstevel@tonic-gate return (IBMF_BAD_CLASS);
3000Sstevel@tonic-gate }
3010Sstevel@tonic-gate
3020Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_validate_class_mask_end,
3030Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_validate_class_mask() exit\n");
3040Sstevel@tonic-gate return (IBMF_SUCCESS);
3050Sstevel@tonic-gate }
3060Sstevel@tonic-gate
3070Sstevel@tonic-gate /*
3080Sstevel@tonic-gate * ibmf_i_validate_ci_guid_and_port():
3090Sstevel@tonic-gate * Checks validity of port number and HCA GUID at client
3100Sstevel@tonic-gate * registration time.
3110Sstevel@tonic-gate */
3120Sstevel@tonic-gate int
ibmf_i_validate_ci_guid_and_port(ib_guid_t hca_guid,uint8_t port_num)3130Sstevel@tonic-gate ibmf_i_validate_ci_guid_and_port(ib_guid_t hca_guid, uint8_t port_num)
3140Sstevel@tonic-gate {
3150Sstevel@tonic-gate ibt_status_t status;
3160Sstevel@tonic-gate ibt_hca_attr_t hca_attrs;
3170Sstevel@tonic-gate
3180Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4,
3190Sstevel@tonic-gate ibmf_i_validate_ci_guid_and_port_start, IBMF_TNF_TRACE, "",
3200Sstevel@tonic-gate "ibmf_i_validate_ci_guid_and_port() enter, hca_guid = %x, "
3210Sstevel@tonic-gate "port_num = %d\n", tnf_opaque, hca_guid, hca_guid,
3220Sstevel@tonic-gate tnf_uint, port_num, port_num);
3230Sstevel@tonic-gate
3240Sstevel@tonic-gate /* check for incorrect port number specification */
3250Sstevel@tonic-gate if (port_num == 0) {
3260Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_NODEBUG, 1,
3270Sstevel@tonic-gate ibmf_i_validate_ci_guid_and_port_err, IBMF_TNF_ERROR, "",
3280Sstevel@tonic-gate "%s\n", tnf_string, msg, "port num is 0");
3290Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
3300Sstevel@tonic-gate ibmf_i_validate_ci_guid_and_port_end, IBMF_TNF_TRACE, "",
3310Sstevel@tonic-gate "ibmf_i_validate_ci_guid_and_port() exit\n");
3320Sstevel@tonic-gate return (IBMF_BAD_PORT);
3330Sstevel@tonic-gate }
3340Sstevel@tonic-gate
3350Sstevel@tonic-gate /* call IB transport layer for HCA attributes */
3360Sstevel@tonic-gate status = ibt_query_hca_byguid(hca_guid, &hca_attrs);
3370Sstevel@tonic-gate if (status != IBT_SUCCESS) {
3380Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
3390Sstevel@tonic-gate ibmf_i_validate_ci_guid_and_port_err,
3400Sstevel@tonic-gate IBMF_TNF_ERROR, "", "%s, status = %d\n", tnf_string, msg,
3410Sstevel@tonic-gate "query_hca_guid failed", tnf_uint, status, status);
3420Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
3430Sstevel@tonic-gate ibmf_i_validate_ci_guid_and_port_end, IBMF_TNF_TRACE, "",
3440Sstevel@tonic-gate "ibmf_i_validate_ci_guid_and_port() exit\n");
3450Sstevel@tonic-gate return (IBMF_BAD_NODE);
3460Sstevel@tonic-gate }
3470Sstevel@tonic-gate
3480Sstevel@tonic-gate /* check if the specified port number is within the HCAs range */
3490Sstevel@tonic-gate if (port_num > hca_attrs.hca_nports) {
3500Sstevel@tonic-gate IBMF_TRACE_3(IBMF_TNF_NODEBUG, 1,
3510Sstevel@tonic-gate ibmf_i_validate_ci_guid_and_port_err, IBMF_TNF_ERROR, "",
3520Sstevel@tonic-gate "%s, num = %d, hca_ports = %d\n",
3530Sstevel@tonic-gate tnf_string, msg, "port num > valid ports",
3540Sstevel@tonic-gate tnf_uint, num, port_num, tnf_uint, hca_nports,
3550Sstevel@tonic-gate hca_attrs.hca_nports);
3560Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
3570Sstevel@tonic-gate ibmf_i_validate_ci_guid_and_port_end, IBMF_TNF_TRACE, "",
3580Sstevel@tonic-gate "ibmf_i_validate_ci_guid_and_port() exit\n");
3590Sstevel@tonic-gate return (IBMF_BAD_PORT);
3600Sstevel@tonic-gate }
3610Sstevel@tonic-gate
3620Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
3630Sstevel@tonic-gate ibmf_i_validate_ci_guid_and_port_end, IBMF_TNF_TRACE, "",
3640Sstevel@tonic-gate "ibmf_i_validate_ci_guid_and_port() exit\n");
3650Sstevel@tonic-gate return (IBMF_SUCCESS);
3660Sstevel@tonic-gate }
3670Sstevel@tonic-gate
3680Sstevel@tonic-gate /*
3690Sstevel@tonic-gate * ibmf_i_lookup_ci():
3700Sstevel@tonic-gate * Lookup the ci and return if found. If the CI is not found, returns
3710Sstevel@tonic-gate * NULL.
3720Sstevel@tonic-gate */
3730Sstevel@tonic-gate static ibmf_ci_t *
ibmf_i_lookup_ci(ib_guid_t ci_guid)3740Sstevel@tonic-gate ibmf_i_lookup_ci(ib_guid_t ci_guid)
3750Sstevel@tonic-gate {
3760Sstevel@tonic-gate ibmf_ci_t *cip = NULL;
3770Sstevel@tonic-gate
3780Sstevel@tonic-gate ASSERT(MUTEX_NOT_HELD(&ibmf_statep->ibmf_mutex));
3790Sstevel@tonic-gate
3800Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_lookup_ci_start,
3810Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_lookup_ci(): enter, guid = 0x%x\n",
3820Sstevel@tonic-gate tnf_uint64, guid, ci_guid);
3830Sstevel@tonic-gate
3840Sstevel@tonic-gate /* walk the CI list looking for one that matches the provided GUID */
3850Sstevel@tonic-gate mutex_enter(&ibmf_statep->ibmf_mutex);
3860Sstevel@tonic-gate cip = ibmf_statep->ibmf_ci_list;
3870Sstevel@tonic-gate while (cip != (ibmf_ci_t *)NULL) {
3880Sstevel@tonic-gate if (ci_guid == cip->ci_node_guid) {
3890Sstevel@tonic-gate /* found it in our list */
3900Sstevel@tonic-gate break;
3910Sstevel@tonic-gate }
3920Sstevel@tonic-gate cip = cip->ci_next;
3930Sstevel@tonic-gate }
3940Sstevel@tonic-gate mutex_exit(&ibmf_statep->ibmf_mutex);
3950Sstevel@tonic-gate
3960Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_lookup_ci_end,
3970Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_lookup_ci() exit\n");
3980Sstevel@tonic-gate
3990Sstevel@tonic-gate return (cip);
4000Sstevel@tonic-gate }
4010Sstevel@tonic-gate
4020Sstevel@tonic-gate /*
4030Sstevel@tonic-gate * ibmf_i_get_ci():
4040Sstevel@tonic-gate * Get the CI structure based on the HCA GUID from a list if it exists.
4050Sstevel@tonic-gate * If the CI structure does not exist, and the HCA GUID is valid,
4060Sstevel@tonic-gate * create a new CI structure and add it to the list.
4070Sstevel@tonic-gate */
4080Sstevel@tonic-gate int
ibmf_i_get_ci(ibmf_register_info_t * client_infop,ibmf_ci_t ** cipp)4090Sstevel@tonic-gate ibmf_i_get_ci(ibmf_register_info_t *client_infop, ibmf_ci_t **cipp)
4100Sstevel@tonic-gate {
4110Sstevel@tonic-gate ibmf_ci_t *cip;
4120Sstevel@tonic-gate ibt_status_t status;
4130Sstevel@tonic-gate boolean_t invalid = B_FALSE;
4140Sstevel@tonic-gate ibt_hca_attr_t hca_attrs;
4150Sstevel@tonic-gate ibmf_port_kstat_t *ksp;
4160Sstevel@tonic-gate
4170Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_get_ci_start,
4180Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_get_ci() enter, clinfop = %p\n",
4190Sstevel@tonic-gate tnf_opaque, client_infop, client_infop);
4200Sstevel@tonic-gate
4210Sstevel@tonic-gate /* look for a CI context with a matching GUID */
4220Sstevel@tonic-gate cip = ibmf_i_lookup_ci(client_infop->ir_ci_guid);
4230Sstevel@tonic-gate
4240Sstevel@tonic-gate if (cip == NULL) {
4250Sstevel@tonic-gate
4260Sstevel@tonic-gate /*
4270Sstevel@tonic-gate * attempt to create the ci. First, verify the ci exists.
4280Sstevel@tonic-gate * If it exists, allocate ci memory and insert in the ci list.
4290Sstevel@tonic-gate * It is possible that some other thread raced with us
4300Sstevel@tonic-gate * and inserted created ci while we are blocked in
4310Sstevel@tonic-gate * allocating memory. Check for that case and if that is indeed
4320Sstevel@tonic-gate * the case, free up what we allocated and try to get a
4330Sstevel@tonic-gate * reference count on the ci that the other thread added.
4340Sstevel@tonic-gate */
4350Sstevel@tonic-gate status = ibt_query_hca_byguid(client_infop->ir_ci_guid,
4360Sstevel@tonic-gate &hca_attrs);
4370Sstevel@tonic-gate if (status == IBT_SUCCESS) {
4380Sstevel@tonic-gate
4390Sstevel@tonic-gate ibmf_ci_t *tcip;
4400Sstevel@tonic-gate char buf[128];
4410Sstevel@tonic-gate
4420Sstevel@tonic-gate /* allocate memory for the CI structure */
4430Sstevel@tonic-gate cip = (ibmf_ci_t *)kmem_zalloc(sizeof (ibmf_ci_t),
4440Sstevel@tonic-gate KM_SLEEP);
4450Sstevel@tonic-gate
4460Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*cip))
4470Sstevel@tonic-gate
4480Sstevel@tonic-gate mutex_init(&cip->ci_mutex, NULL, MUTEX_DRIVER, NULL);
4490Sstevel@tonic-gate mutex_init(&cip->ci_clients_mutex, NULL, MUTEX_DRIVER,
4500Sstevel@tonic-gate NULL);
4510Sstevel@tonic-gate mutex_init(&cip->ci_wqe_mutex, NULL, MUTEX_DRIVER,
4520Sstevel@tonic-gate NULL);
4530Sstevel@tonic-gate cv_init(&cip->ci_state_cv, NULL, CV_DRIVER, NULL);
4540Sstevel@tonic-gate cv_init(&cip->ci_wqes_cv, NULL, CV_DRIVER, NULL);
4550Sstevel@tonic-gate
4560Sstevel@tonic-gate (void) sprintf(buf, "r%08X",
4570Sstevel@tonic-gate (uint32_t)client_infop->ir_ci_guid);
4580Sstevel@tonic-gate mutex_enter(&cip->ci_mutex);
4590Sstevel@tonic-gate
4600Sstevel@tonic-gate cip->ci_state = IBMF_CI_STATE_PRESENT;
4610Sstevel@tonic-gate cip->ci_node_guid = client_infop->ir_ci_guid;
4620Sstevel@tonic-gate
4630Sstevel@tonic-gate /* set up per CI kstats */
4640Sstevel@tonic-gate (void) sprintf(buf, "ibmf_%016" PRIx64 "_%d_stat",
4650Sstevel@tonic-gate client_infop->ir_ci_guid,
4660Sstevel@tonic-gate client_infop->ir_port_num);
4670Sstevel@tonic-gate if ((cip->ci_port_kstatp = kstat_create("ibmf", 0, buf,
4680Sstevel@tonic-gate "misc", KSTAT_TYPE_NAMED,
4690Sstevel@tonic-gate sizeof (ibmf_port_kstat_t) / sizeof (kstat_named_t),
4700Sstevel@tonic-gate KSTAT_FLAG_WRITABLE)) == NULL) {
4710Sstevel@tonic-gate mutex_exit(&cip->ci_mutex);
4720Sstevel@tonic-gate mutex_destroy(&cip->ci_mutex);
4730Sstevel@tonic-gate mutex_destroy(&cip->ci_clients_mutex);
4740Sstevel@tonic-gate mutex_destroy(&cip->ci_wqe_mutex);
4750Sstevel@tonic-gate cv_destroy(&cip->ci_state_cv);
4760Sstevel@tonic-gate cv_destroy(&cip->ci_wqes_cv);
4770Sstevel@tonic-gate kmem_free((void *)cip, sizeof (ibmf_ci_t));
4780Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
4790Sstevel@tonic-gate ibmf_i_get_ci_err, IBMF_TNF_ERROR, "",
4800Sstevel@tonic-gate "%s\n", tnf_string, msg,
4810Sstevel@tonic-gate "kstat create failed");
4820Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
4830Sstevel@tonic-gate ibmf_i_get_ci_end, IBMF_TNF_TRACE, "",
4840Sstevel@tonic-gate "ibmf_i_get_ci() exit\n");
4850Sstevel@tonic-gate return (IBMF_NO_RESOURCES);
4860Sstevel@tonic-gate }
4870Sstevel@tonic-gate ksp = (ibmf_port_kstat_t *)cip->ci_port_kstatp->ks_data;
4880Sstevel@tonic-gate kstat_named_init(&ksp->clients_registered,
4890Sstevel@tonic-gate "clients_registered", KSTAT_DATA_UINT32);
4900Sstevel@tonic-gate kstat_named_init(&ksp->client_regs_failed,
4910Sstevel@tonic-gate "client_registrations_failed", KSTAT_DATA_UINT32);
4920Sstevel@tonic-gate kstat_named_init(&ksp->send_wqes_alloced,
4930Sstevel@tonic-gate "send_wqes_allocated", KSTAT_DATA_UINT32);
4940Sstevel@tonic-gate kstat_named_init(&ksp->recv_wqes_alloced,
4950Sstevel@tonic-gate "receive_wqes_allocated", KSTAT_DATA_UINT32);
4960Sstevel@tonic-gate kstat_named_init(&ksp->swqe_allocs_failed,
4970Sstevel@tonic-gate "send_wqe_allocs_failed", KSTAT_DATA_UINT32);
4980Sstevel@tonic-gate kstat_named_init(&ksp->rwqe_allocs_failed,
4990Sstevel@tonic-gate "recv_wqe_allocs_failed", KSTAT_DATA_UINT32);
5000Sstevel@tonic-gate kstat_install(cip->ci_port_kstatp);
5010Sstevel@tonic-gate
5020Sstevel@tonic-gate mutex_exit(&cip->ci_mutex);
5030Sstevel@tonic-gate
5040Sstevel@tonic-gate mutex_enter(&ibmf_statep->ibmf_mutex);
5050Sstevel@tonic-gate
5060Sstevel@tonic-gate tcip = ibmf_statep->ibmf_ci_list;
5070Sstevel@tonic-gate while (tcip != (ibmf_ci_t *)NULL) {
5080Sstevel@tonic-gate if (client_infop->ir_ci_guid ==
5090Sstevel@tonic-gate tcip->ci_node_guid) {
5100Sstevel@tonic-gate /* found it in our list */
5110Sstevel@tonic-gate break;
5120Sstevel@tonic-gate }
5130Sstevel@tonic-gate tcip = tcip->ci_next;
5140Sstevel@tonic-gate }
5150Sstevel@tonic-gate
5160Sstevel@tonic-gate /* if the ci isn't on the list, add it */
5170Sstevel@tonic-gate if (tcip == NULL) {
5180Sstevel@tonic-gate cip->ci_next = NULL;
5190Sstevel@tonic-gate
5200Sstevel@tonic-gate _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*cip))
5210Sstevel@tonic-gate
5220Sstevel@tonic-gate if (ibmf_statep->ibmf_ci_list_tail != NULL)
5230Sstevel@tonic-gate ibmf_statep->ibmf_ci_list_tail->
5240Sstevel@tonic-gate ci_next = cip;
5250Sstevel@tonic-gate if (ibmf_statep->ibmf_ci_list == NULL)
5260Sstevel@tonic-gate ibmf_statep->ibmf_ci_list = cip;
5270Sstevel@tonic-gate ibmf_statep->ibmf_ci_list_tail = cip;
5280Sstevel@tonic-gate
5290Sstevel@tonic-gate mutex_enter(&cip->ci_mutex);
5300Sstevel@tonic-gate cip->ci_init_state |= IBMF_CI_INIT_HCA_LINKED;
5310Sstevel@tonic-gate mutex_exit(&cip->ci_mutex);
5320Sstevel@tonic-gate
5330Sstevel@tonic-gate } else {
5340Sstevel@tonic-gate /* free cip and set it to the one on the list */
5350Sstevel@tonic-gate kstat_delete(cip->ci_port_kstatp);
5360Sstevel@tonic-gate mutex_destroy(&cip->ci_mutex);
5370Sstevel@tonic-gate mutex_destroy(&cip->ci_clients_mutex);
5380Sstevel@tonic-gate mutex_destroy(&cip->ci_wqe_mutex);
5390Sstevel@tonic-gate cv_destroy(&cip->ci_state_cv);
5400Sstevel@tonic-gate cv_destroy(&cip->ci_wqes_cv);
5410Sstevel@tonic-gate kmem_free((void *)cip, sizeof (ibmf_ci_t));
5420Sstevel@tonic-gate
5430Sstevel@tonic-gate _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*cip))
5440Sstevel@tonic-gate
5450Sstevel@tonic-gate cip = tcip;
5460Sstevel@tonic-gate }
5470Sstevel@tonic-gate mutex_exit(&ibmf_statep->ibmf_mutex);
5480Sstevel@tonic-gate } else {
5490Sstevel@tonic-gate /* we didn't find it and the CI doesn't exist */
5500Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L1,
5510Sstevel@tonic-gate ibmf_i_get_ci_err, IBMF_TNF_ERROR, "", "%s\n",
5520Sstevel@tonic-gate tnf_string, msg, "GUID doesn't exist");
5530Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
5540Sstevel@tonic-gate ibmf_i_get_ci_end, IBMF_TNF_TRACE, "",
5550Sstevel@tonic-gate "ibmf_i_get_ci() exit\n");
5560Sstevel@tonic-gate return (IBMF_TRANSPORT_FAILURE);
5570Sstevel@tonic-gate }
5580Sstevel@tonic-gate }
5590Sstevel@tonic-gate
5600Sstevel@tonic-gate ASSERT(cip != NULL);
5610Sstevel@tonic-gate
5620Sstevel@tonic-gate /*
5630Sstevel@tonic-gate * We now have a CI context structure, either found it on the list,
5640Sstevel@tonic-gate * or created it.
5650Sstevel@tonic-gate * We now proceed to intialize the CI context.
5660Sstevel@tonic-gate */
5670Sstevel@tonic-gate for (;;) {
5680Sstevel@tonic-gate mutex_enter(&cip->ci_mutex);
5690Sstevel@tonic-gate
5700Sstevel@tonic-gate /* CI is INITED & no state change in progress; we are all set */
5710Sstevel@tonic-gate if (cip->ci_state == IBMF_CI_STATE_INITED && (cip->
5720Sstevel@tonic-gate ci_state_flags & (IBMF_CI_STATE_INVALIDATING |
5730Sstevel@tonic-gate IBMF_CI_STATE_UNINITING)) == 0) {
5740Sstevel@tonic-gate
5750Sstevel@tonic-gate cip->ci_ref++;
5760Sstevel@tonic-gate mutex_exit(&cip->ci_mutex);
5770Sstevel@tonic-gate
5780Sstevel@tonic-gate break;
5790Sstevel@tonic-gate }
5800Sstevel@tonic-gate
5810Sstevel@tonic-gate /* CI is PRESENT; transition it to INITED */
5820Sstevel@tonic-gate if (cip->ci_state == IBMF_CI_STATE_PRESENT && (cip->
5830Sstevel@tonic-gate ci_state_flags & (IBMF_CI_STATE_INVALIDATING |
5840Sstevel@tonic-gate IBMF_CI_STATE_INITING)) == 0) {
5850Sstevel@tonic-gate
5860Sstevel@tonic-gate /* mark state as initing and init the ci */
5870Sstevel@tonic-gate cip->ci_state_flags |= IBMF_CI_STATE_INITING;
5880Sstevel@tonic-gate mutex_exit(&cip->ci_mutex);
5890Sstevel@tonic-gate
5900Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*cip))
5910Sstevel@tonic-gate
5920Sstevel@tonic-gate if (ibmf_i_init_ci(client_infop, cip) != IBMF_SUCCESS) {
5930Sstevel@tonic-gate invalid = B_TRUE;
5940Sstevel@tonic-gate break;
5950Sstevel@tonic-gate }
5960Sstevel@tonic-gate
5970Sstevel@tonic-gate _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*cip))
5980Sstevel@tonic-gate
5990Sstevel@tonic-gate continue;
6000Sstevel@tonic-gate }
6010Sstevel@tonic-gate
6020Sstevel@tonic-gate /*
6030Sstevel@tonic-gate * If CI is GONE and no validation is in progress, we should
6040Sstevel@tonic-gate * return failure. Also, if CI is INITED but in the process of
6050Sstevel@tonic-gate * being made GONE (ie., a hot remove in progress), return
6060Sstevel@tonic-gate * failure.
6070Sstevel@tonic-gate */
6080Sstevel@tonic-gate if ((cip->ci_state == IBMF_CI_STATE_GONE && (cip->
6090Sstevel@tonic-gate ci_state_flags & IBMF_CI_STATE_VALIDATING) == 0) ||
6100Sstevel@tonic-gate (cip->ci_state == IBMF_CI_STATE_INITED && (cip->
6110Sstevel@tonic-gate ci_state_flags & IBMF_CI_STATE_INVALIDATING) != 0)) {
6120Sstevel@tonic-gate
6130Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
6140Sstevel@tonic-gate ibmf_i_get_ci_err, IBMF_TNF_ERROR, "",
6150Sstevel@tonic-gate "ci_state = %x, ci_state_flags = %x\n",
6160Sstevel@tonic-gate tnf_opaque, cip->ci_state, cip->ci_state,
6170Sstevel@tonic-gate tnf_opaque, cip->ci_state_flags,
6180Sstevel@tonic-gate cip->ci_state_flags);
6190Sstevel@tonic-gate
6200Sstevel@tonic-gate invalid = B_TRUE;
6210Sstevel@tonic-gate mutex_exit(&cip->ci_mutex);
6220Sstevel@tonic-gate
6230Sstevel@tonic-gate break;
6240Sstevel@tonic-gate }
6250Sstevel@tonic-gate
6260Sstevel@tonic-gate /* a state change in progress; block waiting for state change */
6270Sstevel@tonic-gate if (cip->ci_state_flags & IBMF_CI_STATE_VALIDATING)
6280Sstevel@tonic-gate cip->ci_state_flags |= IBMF_CI_STATE_VALIDATE_WAIT;
6290Sstevel@tonic-gate else if (cip->ci_state_flags & IBMF_CI_STATE_INITING)
6300Sstevel@tonic-gate cip->ci_state_flags |= IBMF_CI_STATE_INIT_WAIT;
6310Sstevel@tonic-gate else if (cip->ci_state_flags & IBMF_CI_STATE_UNINITING)
6320Sstevel@tonic-gate cip->ci_state_flags |= IBMF_CI_STATE_UNINIT_WAIT;
6330Sstevel@tonic-gate
6340Sstevel@tonic-gate cv_wait(&cip->ci_state_cv, &cip->ci_mutex);
6350Sstevel@tonic-gate
6360Sstevel@tonic-gate mutex_exit(&cip->ci_mutex);
6370Sstevel@tonic-gate }
6380Sstevel@tonic-gate
6390Sstevel@tonic-gate if (invalid == B_TRUE) {
6400Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_NODEBUG, DPRINT_L2, ibmf_i_get_ci_err,
6410Sstevel@tonic-gate IBMF_TNF_ERROR, "", "ibmf_i_get_ci() error\n");
6420Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_get_ci_end,
6430Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_get_ci() exit\n");
6440Sstevel@tonic-gate return (IBMF_FAILURE);
6450Sstevel@tonic-gate }
6460Sstevel@tonic-gate
6470Sstevel@tonic-gate if (cip != NULL) {
6480Sstevel@tonic-gate *cipp = cip;
6490Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_get_ci_end,
6500Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_get_ci() exit\n");
6510Sstevel@tonic-gate return (IBMF_SUCCESS);
6520Sstevel@tonic-gate } else {
6530Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_get_ci_end,
6540Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_get_ci() exit\n");
6550Sstevel@tonic-gate return (IBMF_FAILURE);
6560Sstevel@tonic-gate }
6570Sstevel@tonic-gate }
6580Sstevel@tonic-gate
6590Sstevel@tonic-gate /*
6600Sstevel@tonic-gate * ibmf_i_release_ci():
6610Sstevel@tonic-gate * Drop the reference count for the CI.
6620Sstevel@tonic-gate */
6630Sstevel@tonic-gate void
ibmf_i_release_ci(ibmf_ci_t * cip)6640Sstevel@tonic-gate ibmf_i_release_ci(ibmf_ci_t *cip)
6650Sstevel@tonic-gate {
6660Sstevel@tonic-gate uint_t ref;
6670Sstevel@tonic-gate
6680Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_release_ci_start,
6690Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_release_ci() enter, cip = %p\n",
6700Sstevel@tonic-gate tnf_opaque, cip, cip);
6710Sstevel@tonic-gate
6720Sstevel@tonic-gate ASSERT(MUTEX_NOT_HELD(&cip->ci_mutex));
6730Sstevel@tonic-gate
6740Sstevel@tonic-gate mutex_enter(&cip->ci_mutex);
6750Sstevel@tonic-gate ref = cip->ci_ref--;
6760Sstevel@tonic-gate if (ref == 1) {
6770Sstevel@tonic-gate ASSERT(cip->ci_state == IBMF_CI_STATE_INITED);
6780Sstevel@tonic-gate cip->ci_state_flags |= IBMF_CI_STATE_UNINITING;
6790Sstevel@tonic-gate }
6800Sstevel@tonic-gate mutex_exit(&cip->ci_mutex);
6810Sstevel@tonic-gate
6820Sstevel@tonic-gate if (ref == 1) {
6830Sstevel@tonic-gate ibmf_i_uninit_ci(cip);
6840Sstevel@tonic-gate }
6850Sstevel@tonic-gate
6860Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_release_ci_end,
6870Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_release_ci() exit\n");
6880Sstevel@tonic-gate }
6890Sstevel@tonic-gate
6900Sstevel@tonic-gate /*
6910Sstevel@tonic-gate * ibmf_i_init_ci():
6920Sstevel@tonic-gate * Initialize the CI structure by setting up the HCA, allocating
6930Sstevel@tonic-gate * protection domains, completion queues, a pool of WQEs.
6940Sstevel@tonic-gate */
6950Sstevel@tonic-gate /* ARGSUSED */
6960Sstevel@tonic-gate static int
ibmf_i_init_ci(ibmf_register_info_t * client_infop,ibmf_ci_t * cip)6970Sstevel@tonic-gate ibmf_i_init_ci(ibmf_register_info_t *client_infop, ibmf_ci_t *cip)
6980Sstevel@tonic-gate {
6990Sstevel@tonic-gate ibt_pd_hdl_t pd;
7000Sstevel@tonic-gate ibt_status_t status;
7010Sstevel@tonic-gate ib_guid_t ci_guid;
7020Sstevel@tonic-gate ibt_hca_attr_t hca_attrs;
7030Sstevel@tonic-gate ibt_hca_hdl_t hca_handle;
7040Sstevel@tonic-gate ibt_pd_flags_t pd_flags = IBT_PD_NO_FLAGS;
7050Sstevel@tonic-gate boolean_t error = B_FALSE;
7060Sstevel@tonic-gate int ibmfstatus = IBMF_SUCCESS;
7070Sstevel@tonic-gate char errmsg[128];
7080Sstevel@tonic-gate
7090Sstevel@tonic-gate _NOTE(ASSUMING_PROTECTED(*cip))
7100Sstevel@tonic-gate
7110Sstevel@tonic-gate ASSERT(MUTEX_NOT_HELD(&ibmf_statep->ibmf_mutex));
7120Sstevel@tonic-gate ASSERT(MUTEX_NOT_HELD(&cip->ci_mutex));
7130Sstevel@tonic-gate
7140Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_ci_start,
7150Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_init_ci() enter, cip = %p\n",
7160Sstevel@tonic-gate tnf_opaque, ibmf_ci, cip);
7170Sstevel@tonic-gate
7180Sstevel@tonic-gate mutex_enter(&cip->ci_mutex);
7190Sstevel@tonic-gate ci_guid = cip->ci_node_guid;
7200Sstevel@tonic-gate ASSERT(cip->ci_state == IBMF_CI_STATE_PRESENT);
7210Sstevel@tonic-gate ASSERT((cip->ci_state_flags & IBMF_CI_STATE_INITING) != 0);
7220Sstevel@tonic-gate mutex_exit(&cip->ci_mutex);
7230Sstevel@tonic-gate
7240Sstevel@tonic-gate /* set up a connection to the HCA specified by the GUID */
7250Sstevel@tonic-gate status = ibt_open_hca(ibmf_statep->ibmf_ibt_handle, ci_guid,
7260Sstevel@tonic-gate &hca_handle);
7270Sstevel@tonic-gate ASSERT(status != IBT_HCA_IN_USE);
7280Sstevel@tonic-gate if (status != IBT_SUCCESS) {
7290Sstevel@tonic-gate ibmf_i_init_ci_done(cip);
7300Sstevel@tonic-gate (void) sprintf(errmsg, "ibt open hca failed, status = 0x%x",
7310Sstevel@tonic-gate status);
7320Sstevel@tonic-gate error = B_TRUE;
7330Sstevel@tonic-gate ibmfstatus = IBMF_TRANSPORT_FAILURE;
7340Sstevel@tonic-gate goto bail;
7350Sstevel@tonic-gate }
7360Sstevel@tonic-gate
7370Sstevel@tonic-gate /* get the HCA attributes */
7380Sstevel@tonic-gate status = ibt_query_hca(hca_handle, &hca_attrs);
7390Sstevel@tonic-gate if (status != IBT_SUCCESS) {
7400Sstevel@tonic-gate (void) ibt_close_hca(hca_handle);
7410Sstevel@tonic-gate ibmf_i_init_ci_done(cip);
7420Sstevel@tonic-gate (void) sprintf(errmsg, "ibt query hca failed, status = 0x%x",
7430Sstevel@tonic-gate status);
7440Sstevel@tonic-gate error = B_TRUE;
7450Sstevel@tonic-gate ibmfstatus = IBMF_TRANSPORT_FAILURE;
7460Sstevel@tonic-gate goto bail;
7470Sstevel@tonic-gate }
7480Sstevel@tonic-gate
7490Sstevel@tonic-gate /* allocate a Protection Domain */
7500Sstevel@tonic-gate status = ibt_alloc_pd(hca_handle, pd_flags, &pd);
7510Sstevel@tonic-gate if (status != IBT_SUCCESS) {
7520Sstevel@tonic-gate (void) ibt_close_hca(hca_handle);
7530Sstevel@tonic-gate ibmf_i_init_ci_done(cip);
7540Sstevel@tonic-gate (void) sprintf(errmsg, "alloc PD failed, status = 0x%x",
7550Sstevel@tonic-gate status);
7560Sstevel@tonic-gate error = B_TRUE;
7570Sstevel@tonic-gate ibmfstatus = IBMF_TRANSPORT_FAILURE;
7580Sstevel@tonic-gate goto bail;
7590Sstevel@tonic-gate }
7600Sstevel@tonic-gate
7610Sstevel@tonic-gate /* init the ci */
7620Sstevel@tonic-gate mutex_enter(&cip->ci_mutex);
7630Sstevel@tonic-gate cip->ci_nports = hca_attrs.hca_nports;
7640Sstevel@tonic-gate cip->ci_vendor_id = hca_attrs.hca_vendor_id;
7650Sstevel@tonic-gate cip->ci_device_id = hca_attrs.hca_device_id;
7660Sstevel@tonic-gate cip->ci_ci_handle = hca_handle;
7670Sstevel@tonic-gate cip->ci_pd = pd;
7680Sstevel@tonic-gate cip->ci_init_state |= IBMF_CI_INIT_HCA_INITED;
7690Sstevel@tonic-gate mutex_exit(&cip->ci_mutex);
7700Sstevel@tonic-gate
7710Sstevel@tonic-gate /* initialize cqs */
7720Sstevel@tonic-gate if (ibmf_i_init_cqs(cip) != IBMF_SUCCESS) {
7730Sstevel@tonic-gate (void) ibt_free_pd(cip->ci_ci_handle, cip->ci_pd);
7740Sstevel@tonic-gate mutex_enter(&cip->ci_mutex);
7750Sstevel@tonic-gate cip->ci_init_state &= ~IBMF_CI_INIT_HCA_INITED;
7760Sstevel@tonic-gate mutex_exit(&cip->ci_mutex);
7770Sstevel@tonic-gate (void) ibt_close_hca(cip->ci_ci_handle);
7780Sstevel@tonic-gate ibmf_i_init_ci_done(cip);
7790Sstevel@tonic-gate (void) sprintf(errmsg, "init CQs failed");
7800Sstevel@tonic-gate error = B_TRUE;
7810Sstevel@tonic-gate ibmfstatus = IBMF_FAILURE;
7820Sstevel@tonic-gate goto bail;
7830Sstevel@tonic-gate }
7840Sstevel@tonic-gate
7850Sstevel@tonic-gate /* initialize wqes */
7860Sstevel@tonic-gate if (ibmf_i_init_wqes(cip) != IBMF_SUCCESS) {
7870Sstevel@tonic-gate ibmf_i_fini_cqs(cip);
7880Sstevel@tonic-gate (void) ibt_free_pd(cip->ci_ci_handle, cip->ci_pd);
7890Sstevel@tonic-gate mutex_enter(&cip->ci_mutex);
7900Sstevel@tonic-gate cip->ci_init_state &= ~IBMF_CI_INIT_HCA_INITED;
7910Sstevel@tonic-gate mutex_exit(&cip->ci_mutex);
7920Sstevel@tonic-gate (void) ibt_close_hca(cip->ci_ci_handle);
7930Sstevel@tonic-gate ibmf_i_init_ci_done(cip);
7940Sstevel@tonic-gate (void) sprintf(errmsg, "init WQEs failed");
7950Sstevel@tonic-gate error = B_TRUE;
7960Sstevel@tonic-gate ibmfstatus = IBMF_FAILURE;
7970Sstevel@tonic-gate goto bail;
7980Sstevel@tonic-gate }
7990Sstevel@tonic-gate
8000Sstevel@tonic-gate /* initialize the UD destination structure pool */
8010Sstevel@tonic-gate ibmf_i_init_ud_dest(cip);
8020Sstevel@tonic-gate
8030Sstevel@tonic-gate /* initialize the QP list */
8040Sstevel@tonic-gate ibmf_i_init_qplist(cip);
8050Sstevel@tonic-gate
8060Sstevel@tonic-gate /* initialize condition variable, state, and enable CQ notification */
8070Sstevel@tonic-gate cip->ci_init_state |= IBMF_CI_INIT_MUTEX_CV_INITED;
8080Sstevel@tonic-gate (void) ibt_enable_cq_notify(cip->ci_cq_handle, IBT_NEXT_COMPLETION);
8090Sstevel@tonic-gate (void) ibt_enable_cq_notify(cip->ci_alt_cq_handle, IBT_NEXT_COMPLETION);
8100Sstevel@tonic-gate
8110Sstevel@tonic-gate /* set state to INITED */
8120Sstevel@tonic-gate mutex_enter(&cip->ci_mutex);
8130Sstevel@tonic-gate cip->ci_state = IBMF_CI_STATE_INITED;
8140Sstevel@tonic-gate mutex_exit(&cip->ci_mutex);
8150Sstevel@tonic-gate
8160Sstevel@tonic-gate /* wake up waiters blocked on an initialization done event */
8170Sstevel@tonic-gate ibmf_i_init_ci_done(cip);
8180Sstevel@tonic-gate
8190Sstevel@tonic-gate bail:
8200Sstevel@tonic-gate if (error) {
8210Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1, ibmf_i_init_ci_err,
8220Sstevel@tonic-gate IBMF_TNF_ERROR, "", "%s, status = %d\n", tnf_string, msg,
8230Sstevel@tonic-gate errmsg, tnf_uint, ibmfstatus, ibmfstatus);
8240Sstevel@tonic-gate }
8250Sstevel@tonic-gate
8260Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_ci_end,
8270Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_init_ci() exit, cip = %p\n",
8280Sstevel@tonic-gate tnf_opaque, ibmf_ci, cip);
8290Sstevel@tonic-gate
8300Sstevel@tonic-gate return (ibmfstatus);
8310Sstevel@tonic-gate }
8320Sstevel@tonic-gate
8330Sstevel@tonic-gate /*
8340Sstevel@tonic-gate * ibmf_i_uninit_ci():
835*12787SLida.Horn@Oracle.COM * Free up the resources allocated when initializing the CI structure.
8360Sstevel@tonic-gate */
8370Sstevel@tonic-gate static void
ibmf_i_uninit_ci(ibmf_ci_t * cip)8380Sstevel@tonic-gate ibmf_i_uninit_ci(ibmf_ci_t *cip)
8390Sstevel@tonic-gate {
8400Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_uninit_ci_start,
8410Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_uninit_ci() enter, cip = %p\n",
8420Sstevel@tonic-gate tnf_opaque, cip, cip);
8430Sstevel@tonic-gate
8440Sstevel@tonic-gate ASSERT(MUTEX_HELD(&cip->ci_mutex) == 0);
8450Sstevel@tonic-gate
8460Sstevel@tonic-gate /* clean up the QP list */
8470Sstevel@tonic-gate ibmf_i_fini_qplist(cip);
8480Sstevel@tonic-gate
8490Sstevel@tonic-gate /* empty completions directly */
8500Sstevel@tonic-gate ibmf_i_mad_completions(cip->ci_cq_handle, (void*)cip);
8510Sstevel@tonic-gate ibmf_i_mad_completions(cip->ci_alt_cq_handle, (void*)cip);
8520Sstevel@tonic-gate
8530Sstevel@tonic-gate mutex_enter(&cip->ci_mutex);
8540Sstevel@tonic-gate if (cip->ci_init_state & IBMF_CI_INIT_MUTEX_CV_INITED) {
8550Sstevel@tonic-gate cip->ci_init_state &= ~IBMF_CI_INIT_MUTEX_CV_INITED;
8560Sstevel@tonic-gate }
8570Sstevel@tonic-gate mutex_exit(&cip->ci_mutex);
8580Sstevel@tonic-gate
8590Sstevel@tonic-gate /* clean up the UD destination structure pool */
8600Sstevel@tonic-gate ibmf_i_fini_ud_dest(cip);
8610Sstevel@tonic-gate
8620Sstevel@tonic-gate /* clean up any WQE caches */
8630Sstevel@tonic-gate ibmf_i_fini_wqes(cip);
8640Sstevel@tonic-gate
8650Sstevel@tonic-gate /* free up the completion queues */
8660Sstevel@tonic-gate ibmf_i_fini_cqs(cip);
8670Sstevel@tonic-gate
8680Sstevel@tonic-gate /* free up the protection domain */
8690Sstevel@tonic-gate (void) ibt_free_pd(cip->ci_ci_handle, cip->ci_pd);
8700Sstevel@tonic-gate
8710Sstevel@tonic-gate /* close the HCA connection */
8720Sstevel@tonic-gate (void) ibt_close_hca(cip->ci_ci_handle);
8730Sstevel@tonic-gate
8740Sstevel@tonic-gate /* set state down to PRESENT */
8750Sstevel@tonic-gate mutex_enter(&cip->ci_mutex);
8760Sstevel@tonic-gate cip->ci_init_state &= ~IBMF_CI_INIT_HCA_INITED;
8770Sstevel@tonic-gate cip->ci_state = IBMF_CI_STATE_PRESENT;
8780Sstevel@tonic-gate mutex_exit(&cip->ci_mutex);
8790Sstevel@tonic-gate
8800Sstevel@tonic-gate /* wake up waiters blocked on an un-initialization done event */
8810Sstevel@tonic-gate ibmf_i_uninit_ci_done(cip);
8820Sstevel@tonic-gate
8830Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_uninit_ci_end,
8840Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_uninit_ci() exit\n");
8850Sstevel@tonic-gate }
8860Sstevel@tonic-gate
8870Sstevel@tonic-gate /*
8880Sstevel@tonic-gate * ibmf_i_init_ci_done():
8890Sstevel@tonic-gate * Mark CI initialization as "done", and wake up any waiters.
8900Sstevel@tonic-gate */
8910Sstevel@tonic-gate static void
ibmf_i_init_ci_done(ibmf_ci_t * cip)8920Sstevel@tonic-gate ibmf_i_init_ci_done(ibmf_ci_t *cip)
8930Sstevel@tonic-gate {
8940Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_ci_done_start,
8950Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_init_ci_done() enter, cip = %p\n",
8960Sstevel@tonic-gate tnf_opaque, cip, cip);
8970Sstevel@tonic-gate
8980Sstevel@tonic-gate mutex_enter(&cip->ci_mutex);
8990Sstevel@tonic-gate cip->ci_state_flags &= ~IBMF_CI_STATE_INITING;
9000Sstevel@tonic-gate if (cip->ci_state_flags & IBMF_CI_STATE_INIT_WAIT) {
9010Sstevel@tonic-gate cip->ci_state_flags &= ~IBMF_CI_STATE_INIT_WAIT;
9020Sstevel@tonic-gate cv_broadcast(&cip->ci_state_cv);
9030Sstevel@tonic-gate }
9040Sstevel@tonic-gate mutex_exit(&cip->ci_mutex);
9050Sstevel@tonic-gate
9060Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_ci_done_end,
9070Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_init_ci_done() exit\n");
9080Sstevel@tonic-gate }
9090Sstevel@tonic-gate
9100Sstevel@tonic-gate /*
9110Sstevel@tonic-gate * ibmf_i_uninit_ci_done():
9120Sstevel@tonic-gate * Mark CI uninitialization as "done", and wake up any waiters.
9130Sstevel@tonic-gate */
9140Sstevel@tonic-gate static void
ibmf_i_uninit_ci_done(ibmf_ci_t * cip)9150Sstevel@tonic-gate ibmf_i_uninit_ci_done(ibmf_ci_t *cip)
9160Sstevel@tonic-gate {
9170Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_uninit_ci_done_start,
9180Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_uninit_ci_done() enter, cip = %p\n",
9190Sstevel@tonic-gate tnf_opaque, cip, cip);
9200Sstevel@tonic-gate
9210Sstevel@tonic-gate mutex_enter(&cip->ci_mutex);
9220Sstevel@tonic-gate cip->ci_state_flags &= ~IBMF_CI_STATE_UNINITING;
9230Sstevel@tonic-gate if (cip->ci_state_flags & IBMF_CI_STATE_UNINIT_WAIT) {
9240Sstevel@tonic-gate cip->ci_state_flags &= ~IBMF_CI_STATE_UNINIT_WAIT;
9250Sstevel@tonic-gate cv_broadcast(&cip->ci_state_cv);
9260Sstevel@tonic-gate }
9270Sstevel@tonic-gate mutex_exit(&cip->ci_mutex);
9280Sstevel@tonic-gate
9290Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_uninit_ci_done_end,
9300Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_uninit_ci_done() exit\n");
9310Sstevel@tonic-gate }
9320Sstevel@tonic-gate
9330Sstevel@tonic-gate /*
9340Sstevel@tonic-gate * ibmf_i_init_cqs():
9350Sstevel@tonic-gate * Allocate a completion queue and set the CQ handler.
9360Sstevel@tonic-gate */
9370Sstevel@tonic-gate static int
ibmf_i_init_cqs(ibmf_ci_t * cip)9380Sstevel@tonic-gate ibmf_i_init_cqs(ibmf_ci_t *cip)
9390Sstevel@tonic-gate {
9400Sstevel@tonic-gate ibt_status_t status;
9410Sstevel@tonic-gate ibt_cq_attr_t cq_attrs;
9420Sstevel@tonic-gate ibt_cq_hdl_t cq_handle;
9430Sstevel@tonic-gate uint32_t num_entries;
9440Sstevel@tonic-gate
9450Sstevel@tonic-gate ASSERT(MUTEX_NOT_HELD(&cip->ci_mutex));
9460Sstevel@tonic-gate
9470Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_cqs_start,
9480Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_init_cqs() enter, cip = %p\n",
9490Sstevel@tonic-gate tnf_opaque, cip, cip);
9500Sstevel@tonic-gate
9510Sstevel@tonic-gate /*
9520Sstevel@tonic-gate * Allocate completion queue handle.
9530Sstevel@tonic-gate * The CQ size should be a 2^n - 1 value to avoid excess CQ allocation
9540Sstevel@tonic-gate * as done by some HCAs when the CQ size is specified as a 2^n
9550Sstevel@tonic-gate * quantity.
9560Sstevel@tonic-gate */
9570Sstevel@tonic-gate cq_attrs.cq_size = (cip->ci_nports * (ibmf_send_wqes_posted_per_qp +
9580Sstevel@tonic-gate ibmf_recv_wqes_posted_per_qp)) - 1;
9590Sstevel@tonic-gate
9600Sstevel@tonic-gate cq_attrs.cq_sched = NULL;
9610Sstevel@tonic-gate cq_attrs.cq_flags = 0;
9620Sstevel@tonic-gate
9630Sstevel@tonic-gate /* Get the CQ handle for the special QPs */
9640Sstevel@tonic-gate status = ibt_alloc_cq(cip->ci_ci_handle, &cq_attrs,
9650Sstevel@tonic-gate &cq_handle, &num_entries);
9660Sstevel@tonic-gate if (status != IBT_SUCCESS) {
9670Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1, ibmf_i_init_cqs_err,
9680Sstevel@tonic-gate IBMF_TNF_ERROR, "", "%s, status = %d\n", tnf_string, msg,
9690Sstevel@tonic-gate "ibt_alloc_cq failed", tnf_uint, ibt_status, status);
9700Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_cqs_end,
9710Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_init_cqs() exit\n");
9720Sstevel@tonic-gate return (IBMF_TRANSPORT_FAILURE);
9730Sstevel@tonic-gate }
9740Sstevel@tonic-gate ibt_set_cq_handler(cq_handle, ibmf_statep->ibmf_cq_handler, cip);
9750Sstevel@tonic-gate cip->ci_cq_handle = cq_handle;
9760Sstevel@tonic-gate
9770Sstevel@tonic-gate /* Get the CQ handle for the alternate QPs */
9780Sstevel@tonic-gate status = ibt_alloc_cq(cip->ci_ci_handle, &cq_attrs,
9790Sstevel@tonic-gate &cq_handle, &num_entries);
9800Sstevel@tonic-gate if (status != IBT_SUCCESS) {
9810Sstevel@tonic-gate (void) ibt_free_cq(cip->ci_cq_handle);
9820Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1, ibmf_i_init_cqs_err,
9830Sstevel@tonic-gate IBMF_TNF_ERROR, "", "%s, status = %d\n", tnf_string, msg,
9840Sstevel@tonic-gate "ibt_alloc_cq failed", tnf_uint, ibt_status, status);
9850Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_cqs_end,
9860Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_init_cqs() exit\n");
9870Sstevel@tonic-gate return (IBMF_TRANSPORT_FAILURE);
9880Sstevel@tonic-gate }
9890Sstevel@tonic-gate ibt_set_cq_handler(cq_handle, ibmf_statep->ibmf_cq_handler, cip);
9900Sstevel@tonic-gate cip->ci_alt_cq_handle = cq_handle;
9910Sstevel@tonic-gate
9920Sstevel@tonic-gate /* set state to CQ INITED */
9930Sstevel@tonic-gate mutex_enter(&cip->ci_mutex);
9940Sstevel@tonic-gate cip->ci_init_state |= IBMF_CI_INIT_CQ_INITED;
9950Sstevel@tonic-gate mutex_exit(&cip->ci_mutex);
9960Sstevel@tonic-gate
9970Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_cqs_end,
9980Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_init_cqs() exit\n");
9990Sstevel@tonic-gate
10000Sstevel@tonic-gate return (IBMF_SUCCESS);
10010Sstevel@tonic-gate }
10020Sstevel@tonic-gate
10030Sstevel@tonic-gate /*
10040Sstevel@tonic-gate * ibmf_i_fini_cqs():
10050Sstevel@tonic-gate * Free up the completion queue
10060Sstevel@tonic-gate */
10070Sstevel@tonic-gate static void
ibmf_i_fini_cqs(ibmf_ci_t * cip)10080Sstevel@tonic-gate ibmf_i_fini_cqs(ibmf_ci_t *cip)
10090Sstevel@tonic-gate {
10100Sstevel@tonic-gate ibt_status_t status;
10110Sstevel@tonic-gate uint_t ci_init_state;
10120Sstevel@tonic-gate
10130Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_fini_cqs_start,
10140Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_fini_cqs() enter, cip = %p\n",
10150Sstevel@tonic-gate tnf_opaque, cip, cip);
10160Sstevel@tonic-gate
10170Sstevel@tonic-gate mutex_enter(&cip->ci_mutex);
10180Sstevel@tonic-gate ci_init_state = cip->ci_init_state;
10190Sstevel@tonic-gate cip->ci_init_state &= ~IBMF_CI_INIT_CQ_INITED;
10200Sstevel@tonic-gate mutex_exit(&cip->ci_mutex);
10210Sstevel@tonic-gate
10220Sstevel@tonic-gate if (ci_init_state & IBMF_CI_INIT_CQ_INITED) {
10230Sstevel@tonic-gate status = ibt_free_cq(cip->ci_alt_cq_handle);
10240Sstevel@tonic-gate if (status != IBT_SUCCESS) {
10250Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L3,
10260Sstevel@tonic-gate ibmf_i_fini_cqs_err, IBMF_TNF_ERROR, "",
10270Sstevel@tonic-gate "%s, status = %d\n", tnf_string, msg,
10280Sstevel@tonic-gate "ibt free cqs failed", tnf_uint, status, status);
10290Sstevel@tonic-gate }
10300Sstevel@tonic-gate
10310Sstevel@tonic-gate status = ibt_free_cq(cip->ci_cq_handle);
10320Sstevel@tonic-gate if (status != IBT_SUCCESS) {
10330Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L3,
10340Sstevel@tonic-gate ibmf_i_fini_cqs_err, IBMF_TNF_ERROR, "",
10350Sstevel@tonic-gate "%s, status = %d\n", tnf_string, msg,
10360Sstevel@tonic-gate "ibt free cqs failed", tnf_uint, status, status);
10370Sstevel@tonic-gate }
10380Sstevel@tonic-gate }
10390Sstevel@tonic-gate
10400Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_fini_cqs_end,
10410Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_fini_cqs() exit");
10420Sstevel@tonic-gate }
10430Sstevel@tonic-gate
10440Sstevel@tonic-gate /*
10450Sstevel@tonic-gate * ibmf_i_init_qplist():
10460Sstevel@tonic-gate * Set the QP list inited state flag
10470Sstevel@tonic-gate */
10480Sstevel@tonic-gate static void
ibmf_i_init_qplist(ibmf_ci_t * ibmf_cip)10490Sstevel@tonic-gate ibmf_i_init_qplist(ibmf_ci_t *ibmf_cip)
10500Sstevel@tonic-gate {
10510Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_qplist_start,
10520Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_init_qplist() enter, cip = %p\n",
10530Sstevel@tonic-gate tnf_opaque, cip, ibmf_cip);
10540Sstevel@tonic-gate
10550Sstevel@tonic-gate mutex_enter(&ibmf_cip->ci_mutex);
10560Sstevel@tonic-gate ASSERT((ibmf_cip->ci_init_state & IBMF_CI_INIT_QP_LIST_INITED) == 0);
10570Sstevel@tonic-gate ASSERT(ibmf_cip->ci_qp_list == NULL && ibmf_cip->ci_qp_list_tail ==
10580Sstevel@tonic-gate NULL);
10590Sstevel@tonic-gate cv_init(&ibmf_cip->ci_qp_cv, NULL, CV_DRIVER, NULL);
10600Sstevel@tonic-gate ibmf_cip->ci_init_state |= IBMF_CI_INIT_QP_LIST_INITED;
10610Sstevel@tonic-gate mutex_exit(&ibmf_cip->ci_mutex);
10620Sstevel@tonic-gate
10630Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_qplist_end,
10640Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_init_qplist() exit\n");
10650Sstevel@tonic-gate }
10660Sstevel@tonic-gate
10670Sstevel@tonic-gate /*
10680Sstevel@tonic-gate * ibmf_i_fini_qplist():
10690Sstevel@tonic-gate * Clean up the QP list
10700Sstevel@tonic-gate */
10710Sstevel@tonic-gate static void
ibmf_i_fini_qplist(ibmf_ci_t * ibmf_cip)10720Sstevel@tonic-gate ibmf_i_fini_qplist(ibmf_ci_t *ibmf_cip)
10730Sstevel@tonic-gate {
10740Sstevel@tonic-gate ibmf_qp_t *qpp;
10750Sstevel@tonic-gate ibmf_alt_qp_t *altqpp;
10760Sstevel@tonic-gate ibt_status_t status;
10770Sstevel@tonic-gate
10780Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_fini_qplist_start,
10790Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_fini_qplist() enter, cip = %p\n",
10800Sstevel@tonic-gate tnf_opaque, cip, ibmf_cip);
10810Sstevel@tonic-gate
10820Sstevel@tonic-gate mutex_enter(&ibmf_cip->ci_mutex);
10830Sstevel@tonic-gate
10840Sstevel@tonic-gate if ((ibmf_cip->ci_init_state & IBMF_CI_INIT_QP_LIST_INITED) != 0) {
10850Sstevel@tonic-gate
10860Sstevel@tonic-gate /* walk through the qp list and free the memory */
10870Sstevel@tonic-gate qpp = ibmf_cip->ci_qp_list;
10880Sstevel@tonic-gate while (qpp != NULL) {
10890Sstevel@tonic-gate /* Remove qpp from the list */
10900Sstevel@tonic-gate ibmf_cip->ci_qp_list = qpp->iq_next;
10910Sstevel@tonic-gate
10920Sstevel@tonic-gate ASSERT(qpp->iq_qp_ref == 0);
10930Sstevel@tonic-gate ASSERT(qpp->iq_flags == IBMF_QP_FLAGS_INVALID);
10940Sstevel@tonic-gate mutex_exit(&ibmf_cip->ci_mutex);
10950Sstevel@tonic-gate if (qpp->iq_qp_handle != NULL) {
10960Sstevel@tonic-gate /* Flush the special QP */
10970Sstevel@tonic-gate status = ibt_flush_qp(qpp->iq_qp_handle);
10980Sstevel@tonic-gate if (status != IBT_SUCCESS) {
10990Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_NODEBUG,
11000Sstevel@tonic-gate DPRINT_L1, ibmf_i_fini_qplist_err,
11010Sstevel@tonic-gate IBMF_TNF_ERROR, "",
11020Sstevel@tonic-gate "%s, status = %d\n", tnf_string,
11030Sstevel@tonic-gate msg, "ibt_flush_qp returned error",
11040Sstevel@tonic-gate tnf_int, status, status);
11050Sstevel@tonic-gate }
11060Sstevel@tonic-gate
11070Sstevel@tonic-gate /* Grab the ci_mutex mutex before waiting */
11080Sstevel@tonic-gate mutex_enter(&ibmf_cip->ci_mutex);
11090Sstevel@tonic-gate
11100Sstevel@tonic-gate /* Wait if WQEs for special QPs are alloced */
11110Sstevel@tonic-gate while (ibmf_cip->ci_wqes_alloced != 0) {
11120Sstevel@tonic-gate cv_wait(&ibmf_cip->ci_wqes_cv,
11130Sstevel@tonic-gate &ibmf_cip->ci_mutex);
11140Sstevel@tonic-gate }
11150Sstevel@tonic-gate
11160Sstevel@tonic-gate mutex_exit(&ibmf_cip->ci_mutex);
11170Sstevel@tonic-gate
11180Sstevel@tonic-gate /* Free the special QP */
11190Sstevel@tonic-gate status = ibt_free_qp(qpp->iq_qp_handle);
11200Sstevel@tonic-gate if (status != IBT_SUCCESS) {
11210Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_NODEBUG,
11220Sstevel@tonic-gate DPRINT_L1, ibmf_i_fini_qplist_err,
11230Sstevel@tonic-gate IBMF_TNF_ERROR, "",
11240Sstevel@tonic-gate "%s, status = %d\n", tnf_string,
11250Sstevel@tonic-gate msg, "ibt_free_qp returned error",
11260Sstevel@tonic-gate tnf_int, status, status);
11270Sstevel@tonic-gate }
11280Sstevel@tonic-gate }
11290Sstevel@tonic-gate mutex_destroy(&qpp->iq_mutex);
11300Sstevel@tonic-gate kmem_free((void *)qpp, sizeof (ibmf_qp_t));
11310Sstevel@tonic-gate
11320Sstevel@tonic-gate /* Grab the mutex again before accessing the QP list */
11330Sstevel@tonic-gate mutex_enter(&ibmf_cip->ci_mutex);
11340Sstevel@tonic-gate qpp = ibmf_cip->ci_qp_list;
11350Sstevel@tonic-gate }
11360Sstevel@tonic-gate
11370Sstevel@tonic-gate cv_destroy(&ibmf_cip->ci_qp_cv);
11380Sstevel@tonic-gate
11390Sstevel@tonic-gate ibmf_cip->ci_qp_list = ibmf_cip->ci_qp_list_tail = NULL;
11400Sstevel@tonic-gate ibmf_cip->ci_init_state &= ~IBMF_CI_INIT_QP_LIST_INITED;
11410Sstevel@tonic-gate
11420Sstevel@tonic-gate altqpp = ibmf_cip->ci_alt_qp_list;
11430Sstevel@tonic-gate while (altqpp != NULL) {
11440Sstevel@tonic-gate /* Remove altqpp from the list */
11450Sstevel@tonic-gate ibmf_cip->ci_alt_qp_list = altqpp->isq_next;
11460Sstevel@tonic-gate mutex_exit(&ibmf_cip->ci_mutex);
11470Sstevel@tonic-gate
11480Sstevel@tonic-gate if (altqpp->isq_qp_handle != NULL) {
11490Sstevel@tonic-gate /* Flush the special QP */
11500Sstevel@tonic-gate status = ibt_flush_qp(altqpp->isq_qp_handle);
11510Sstevel@tonic-gate if (status != IBT_SUCCESS) {
11520Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_NODEBUG,
11530Sstevel@tonic-gate DPRINT_L1, ibmf_i_fini_qplist_err,
11540Sstevel@tonic-gate IBMF_TNF_ERROR, "",
11550Sstevel@tonic-gate "%s, status = %d\n", tnf_string,
11560Sstevel@tonic-gate msg, "ibt_flush_qp returned error",
11570Sstevel@tonic-gate tnf_int, status, status);
11580Sstevel@tonic-gate }
11590Sstevel@tonic-gate
11600Sstevel@tonic-gate /* Free the special QP */
11610Sstevel@tonic-gate status = ibt_free_qp(altqpp->isq_qp_handle);
11620Sstevel@tonic-gate if (status != IBT_SUCCESS) {
11630Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_NODEBUG,
11640Sstevel@tonic-gate DPRINT_L1, ibmf_i_fini_qplist_err,
11650Sstevel@tonic-gate IBMF_TNF_ERROR, "",
11660Sstevel@tonic-gate "%s, status = %d\n", tnf_string,
11670Sstevel@tonic-gate msg, "ibt_free_qp returned error",
11680Sstevel@tonic-gate tnf_int, status, status);
11690Sstevel@tonic-gate }
11700Sstevel@tonic-gate }
11710Sstevel@tonic-gate mutex_destroy(&altqpp->isq_mutex);
11720Sstevel@tonic-gate kmem_free((void *)altqpp, sizeof (ibmf_alt_qp_t));
11730Sstevel@tonic-gate
11740Sstevel@tonic-gate /* Grab the mutex again before accessing the QP list */
11750Sstevel@tonic-gate mutex_enter(&ibmf_cip->ci_mutex);
11760Sstevel@tonic-gate altqpp = ibmf_cip->ci_alt_qp_list;
11770Sstevel@tonic-gate }
11780Sstevel@tonic-gate }
11790Sstevel@tonic-gate
11800Sstevel@tonic-gate mutex_exit(&ibmf_cip->ci_mutex);
11810Sstevel@tonic-gate
11820Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_fini_qplist_end,
11830Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_fini_qplist() exit\n");
11840Sstevel@tonic-gate }
11850Sstevel@tonic-gate
11860Sstevel@tonic-gate /*
11870Sstevel@tonic-gate * ibmf_i_alloc_client():
11880Sstevel@tonic-gate * Allocate and initialize the client structure.
11890Sstevel@tonic-gate */
11900Sstevel@tonic-gate int
ibmf_i_alloc_client(ibmf_register_info_t * client_infop,uint_t flags,ibmf_client_t ** clientpp)11910Sstevel@tonic-gate ibmf_i_alloc_client(ibmf_register_info_t *client_infop, uint_t flags,
11920Sstevel@tonic-gate ibmf_client_t **clientpp)
11930Sstevel@tonic-gate {
11940Sstevel@tonic-gate ibmf_client_t *ibmf_clientp;
11950Sstevel@tonic-gate char buf[128];
11960Sstevel@tonic-gate ibmf_kstat_t *ksp;
11970Sstevel@tonic-gate
11980Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_alloc_client_start,
11990Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_alloc_client() enter, "
12000Sstevel@tonic-gate "client_infop = %p\n", tnf_opaque, client_infop, client_infop);
12010Sstevel@tonic-gate
12020Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*ibmf_clientp))
12030Sstevel@tonic-gate
12040Sstevel@tonic-gate /* allocate memory for ibmf_client and initialize it */
12050Sstevel@tonic-gate ibmf_clientp = kmem_zalloc(sizeof (ibmf_client_t), KM_SLEEP);
12060Sstevel@tonic-gate mutex_init(&ibmf_clientp->ic_mutex, NULL, MUTEX_DRIVER, NULL);
12070Sstevel@tonic-gate mutex_init(&ibmf_clientp->ic_msg_mutex, NULL, MUTEX_DRIVER, NULL);
12080Sstevel@tonic-gate mutex_init(&ibmf_clientp->ic_kstat_mutex, NULL, MUTEX_DRIVER, NULL);
12090Sstevel@tonic-gate cv_init(&ibmf_clientp->ic_recv_cb_teardown_cv, NULL, CV_DRIVER, NULL);
12100Sstevel@tonic-gate
12110Sstevel@tonic-gate (void) sprintf(buf, "s%08X_0x%08X",
12120Sstevel@tonic-gate (uint32_t)client_infop->ir_ci_guid, client_infop->ir_client_class);
12130Sstevel@tonic-gate
12140Sstevel@tonic-gate /* create a taskq to handle send completions based on reg flags */
12150Sstevel@tonic-gate if ((flags & IBMF_REG_FLAG_NO_OFFLOAD) == 0) {
12160Sstevel@tonic-gate if (flags & IBMF_REG_FLAG_SINGLE_OFFLOAD)
12170Sstevel@tonic-gate ibmf_clientp->ic_send_taskq = taskq_create(buf,
12180Sstevel@tonic-gate IBMF_TASKQ_1THREAD, MINCLSYSPRI, 1,
12190Sstevel@tonic-gate ibmf_taskq_max_tasks, TASKQ_PREPOPULATE);
12200Sstevel@tonic-gate else
12210Sstevel@tonic-gate ibmf_clientp->ic_send_taskq = taskq_create(buf,
12220Sstevel@tonic-gate IBMF_TASKQ_NTHREADS, MINCLSYSPRI, 1,
12230Sstevel@tonic-gate ibmf_taskq_max_tasks,
12240Sstevel@tonic-gate TASKQ_DYNAMIC | TASKQ_PREPOPULATE);
12250Sstevel@tonic-gate if (ibmf_clientp->ic_send_taskq == NULL) {
12260Sstevel@tonic-gate cv_destroy(&ibmf_clientp->ic_recv_cb_teardown_cv);
12270Sstevel@tonic-gate mutex_destroy(&ibmf_clientp->ic_mutex);
12280Sstevel@tonic-gate mutex_destroy(&ibmf_clientp->ic_msg_mutex);
12290Sstevel@tonic-gate mutex_destroy(&ibmf_clientp->ic_kstat_mutex);
12300Sstevel@tonic-gate kmem_free((void *)ibmf_clientp, sizeof (ibmf_client_t));
12310Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
12320Sstevel@tonic-gate ibmf_i_alloc_client_err, IBMF_TNF_ERROR, "", "%s\n",
12330Sstevel@tonic-gate tnf_string, msg, buf);
12340Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
12350Sstevel@tonic-gate ibmf_i_alloc_client_end, IBMF_TNF_TRACE, "",
12360Sstevel@tonic-gate "ibmf_i_alloc_client() exit\n");
12370Sstevel@tonic-gate return (IBMF_NO_RESOURCES);
12380Sstevel@tonic-gate }
12390Sstevel@tonic-gate }
12400Sstevel@tonic-gate ibmf_clientp->ic_init_state_class |= IBMF_CI_INIT_SEND_TASKQ_DONE;
12410Sstevel@tonic-gate
12420Sstevel@tonic-gate (void) sprintf(buf, "r%08X_0x%08X",
12430Sstevel@tonic-gate (uint32_t)client_infop->ir_ci_guid, client_infop->ir_client_class);
12440Sstevel@tonic-gate
12450Sstevel@tonic-gate /* create a taskq to handle receive completions on reg flags */
12460Sstevel@tonic-gate if ((flags & IBMF_REG_FLAG_NO_OFFLOAD) == 0) {
12470Sstevel@tonic-gate if (flags & IBMF_REG_FLAG_SINGLE_OFFLOAD)
12480Sstevel@tonic-gate ibmf_clientp->ic_recv_taskq = taskq_create(buf,
12490Sstevel@tonic-gate IBMF_TASKQ_1THREAD, MINCLSYSPRI, 1,
12500Sstevel@tonic-gate ibmf_taskq_max_tasks, TASKQ_PREPOPULATE);
12510Sstevel@tonic-gate else
12520Sstevel@tonic-gate ibmf_clientp->ic_recv_taskq = taskq_create(buf,
12530Sstevel@tonic-gate IBMF_TASKQ_NTHREADS, MINCLSYSPRI, 1,
12540Sstevel@tonic-gate ibmf_taskq_max_tasks,
12550Sstevel@tonic-gate TASKQ_DYNAMIC | TASKQ_PREPOPULATE);
12560Sstevel@tonic-gate if (ibmf_clientp->ic_recv_taskq == NULL) {
12570Sstevel@tonic-gate cv_destroy(&ibmf_clientp->ic_recv_cb_teardown_cv);
12580Sstevel@tonic-gate mutex_destroy(&ibmf_clientp->ic_mutex);
12590Sstevel@tonic-gate mutex_destroy(&ibmf_clientp->ic_msg_mutex);
12600Sstevel@tonic-gate mutex_destroy(&ibmf_clientp->ic_kstat_mutex);
12610Sstevel@tonic-gate taskq_destroy(ibmf_clientp->ic_send_taskq);
12620Sstevel@tonic-gate kmem_free((void *)ibmf_clientp, sizeof (ibmf_client_t));
12630Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
12640Sstevel@tonic-gate ibmf_i_alloc_client_err, IBMF_TNF_ERROR, "", "%s\n",
12650Sstevel@tonic-gate tnf_string, msg, buf);
12660Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
12670Sstevel@tonic-gate ibmf_i_alloc_client_end, IBMF_TNF_TRACE, "",
12680Sstevel@tonic-gate "ibmf_i_alloc_client() exit\n");
12690Sstevel@tonic-gate return (IBMF_NO_RESOURCES);
12700Sstevel@tonic-gate }
12710Sstevel@tonic-gate }
12720Sstevel@tonic-gate ibmf_clientp->ic_init_state_class |= IBMF_CI_INIT_RECV_TASKQ_DONE;
12730Sstevel@tonic-gate ibmf_clientp->ic_client_info.ci_guid = client_infop->ir_ci_guid;
12740Sstevel@tonic-gate ibmf_clientp->ic_client_info.port_num = client_infop->ir_port_num;
12750Sstevel@tonic-gate
12760Sstevel@tonic-gate /* Get the base LID */
12770Sstevel@tonic-gate (void) ibt_get_port_state_byguid(ibmf_clientp->ic_client_info.ci_guid,
12780Sstevel@tonic-gate ibmf_clientp->ic_client_info.port_num, NULL,
12790Sstevel@tonic-gate &ibmf_clientp->ic_base_lid);
12800Sstevel@tonic-gate
12810Sstevel@tonic-gate ibmf_clientp->ic_client_info.client_class =
12820Sstevel@tonic-gate client_infop->ir_client_class;
12830Sstevel@tonic-gate
12840Sstevel@tonic-gate /* set up the per client ibmf kstats */
12850Sstevel@tonic-gate (void) sprintf(buf, "ibmf_%016" PRIx64 "_%d_%X_stat",
12860Sstevel@tonic-gate client_infop->ir_ci_guid, client_infop->ir_port_num,
12870Sstevel@tonic-gate client_infop->ir_client_class);
12880Sstevel@tonic-gate if ((ibmf_clientp->ic_kstatp = kstat_create("ibmf", 0, buf, "misc",
12890Sstevel@tonic-gate KSTAT_TYPE_NAMED, sizeof (ibmf_kstat_t) / sizeof (kstat_named_t),
12900Sstevel@tonic-gate KSTAT_FLAG_WRITABLE)) == NULL) {
12910Sstevel@tonic-gate cv_destroy(&ibmf_clientp->ic_recv_cb_teardown_cv);
12920Sstevel@tonic-gate mutex_destroy(&ibmf_clientp->ic_mutex);
12930Sstevel@tonic-gate mutex_destroy(&ibmf_clientp->ic_msg_mutex);
12940Sstevel@tonic-gate mutex_destroy(&ibmf_clientp->ic_kstat_mutex);
12950Sstevel@tonic-gate if ((flags & IBMF_REG_FLAG_NO_OFFLOAD) == 0) {
12960Sstevel@tonic-gate taskq_destroy(ibmf_clientp->ic_send_taskq);
12970Sstevel@tonic-gate taskq_destroy(ibmf_clientp->ic_recv_taskq);
12980Sstevel@tonic-gate }
12990Sstevel@tonic-gate kmem_free((void *)ibmf_clientp, sizeof (ibmf_client_t));
13000Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
13010Sstevel@tonic-gate ibmf_i_alloc_client_err, IBMF_TNF_ERROR, "", "%s\n",
13020Sstevel@tonic-gate tnf_string, msg, "kstat creation failed");
13030Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
13040Sstevel@tonic-gate ibmf_i_alloc_client_end, IBMF_TNF_TRACE, "",
13050Sstevel@tonic-gate "ibmf_i_alloc_client() exit\n");
13060Sstevel@tonic-gate return (IBMF_NO_RESOURCES);
13070Sstevel@tonic-gate }
13080Sstevel@tonic-gate ksp = (ibmf_kstat_t *)ibmf_clientp->ic_kstatp->ks_data;
13090Sstevel@tonic-gate kstat_named_init(&ksp->msgs_alloced, "messages_allocated",
13100Sstevel@tonic-gate KSTAT_DATA_UINT32);
13110Sstevel@tonic-gate kstat_named_init(&ksp->msgs_active, "messages_active",
13120Sstevel@tonic-gate KSTAT_DATA_UINT32);
13130Sstevel@tonic-gate kstat_named_init(&ksp->msgs_sent, "messages_sent", KSTAT_DATA_UINT32);
13140Sstevel@tonic-gate kstat_named_init(&ksp->msgs_received, "messages_received",
13150Sstevel@tonic-gate KSTAT_DATA_UINT32);
13160Sstevel@tonic-gate kstat_named_init(&ksp->sends_active, "sends_active", KSTAT_DATA_UINT32);
13170Sstevel@tonic-gate kstat_named_init(&ksp->recvs_active, "receives_active",
13180Sstevel@tonic-gate KSTAT_DATA_UINT32);
13190Sstevel@tonic-gate kstat_named_init(&ksp->ud_dests_alloced, "ud_dests_allocated",
13200Sstevel@tonic-gate KSTAT_DATA_UINT32);
13210Sstevel@tonic-gate kstat_named_init(&ksp->alt_qps_alloced, "alt_qps_allocated",
13220Sstevel@tonic-gate KSTAT_DATA_UINT32);
13230Sstevel@tonic-gate kstat_named_init(&ksp->send_cb_active, "send_callbacks_active",
13240Sstevel@tonic-gate KSTAT_DATA_UINT32);
13250Sstevel@tonic-gate kstat_named_init(&ksp->recv_cb_active, "receive_callbacks_active",
13260Sstevel@tonic-gate KSTAT_DATA_UINT32);
13270Sstevel@tonic-gate kstat_named_init(&ksp->recv_bufs_alloced, "receive_bufs_allocated",
13280Sstevel@tonic-gate KSTAT_DATA_UINT32);
13290Sstevel@tonic-gate kstat_named_init(&ksp->msg_allocs_failed, "msg_allocs_failed",
13300Sstevel@tonic-gate KSTAT_DATA_UINT32);
13310Sstevel@tonic-gate kstat_named_init(&ksp->uddest_allocs_failed, "uddest_allocs_failed",
13320Sstevel@tonic-gate KSTAT_DATA_UINT32);
13330Sstevel@tonic-gate kstat_named_init(&ksp->alt_qp_allocs_failed, "alt_qp_allocs_failed",
13340Sstevel@tonic-gate KSTAT_DATA_UINT32);
13350Sstevel@tonic-gate kstat_named_init(&ksp->send_pkt_failed, "send_pkt_failed",
13360Sstevel@tonic-gate KSTAT_DATA_UINT32);
13370Sstevel@tonic-gate kstat_named_init(&ksp->rmpp_errors, "rmpp_errors",
13380Sstevel@tonic-gate KSTAT_DATA_UINT32);
13390Sstevel@tonic-gate
13400Sstevel@tonic-gate kstat_install(ibmf_clientp->ic_kstatp);
13410Sstevel@tonic-gate
13420Sstevel@tonic-gate *clientpp = ibmf_clientp;
13430Sstevel@tonic-gate
13440Sstevel@tonic-gate _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*ibmf_clientp))
13450Sstevel@tonic-gate
13460Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_alloc_client_end,
13470Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_alloc_client() exit\n");
13480Sstevel@tonic-gate
13490Sstevel@tonic-gate return (IBMF_SUCCESS);
13500Sstevel@tonic-gate }
13510Sstevel@tonic-gate
13520Sstevel@tonic-gate /*
13530Sstevel@tonic-gate * ibmf_i_free_client():
13540Sstevel@tonic-gate * Free up the client structure and release resources
13550Sstevel@tonic-gate */
13560Sstevel@tonic-gate void
ibmf_i_free_client(ibmf_client_t * clientp)13570Sstevel@tonic-gate ibmf_i_free_client(ibmf_client_t *clientp)
13580Sstevel@tonic-gate {
13590Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_free_client_start,
13600Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_free_client() enter, clientp = %p\n",
13610Sstevel@tonic-gate tnf_opaque, clientp, clientp);
13620Sstevel@tonic-gate
13630Sstevel@tonic-gate /* delete the general ibmf kstats */
13640Sstevel@tonic-gate if (clientp->ic_kstatp != NULL) {
13650Sstevel@tonic-gate kstat_delete(clientp->ic_kstatp);
13660Sstevel@tonic-gate clientp->ic_kstatp = NULL;
13670Sstevel@tonic-gate }
13680Sstevel@tonic-gate
13690Sstevel@tonic-gate /* release references and destroy the resources */
13700Sstevel@tonic-gate if (clientp->ic_init_state_class & IBMF_CI_INIT_SEND_TASKQ_DONE) {
13710Sstevel@tonic-gate if ((clientp->ic_reg_flags & IBMF_REG_FLAG_NO_OFFLOAD) == 0) {
13720Sstevel@tonic-gate taskq_destroy(clientp->ic_send_taskq);
13730Sstevel@tonic-gate }
13740Sstevel@tonic-gate clientp->ic_init_state_class &= ~IBMF_CI_INIT_SEND_TASKQ_DONE;
13750Sstevel@tonic-gate }
13760Sstevel@tonic-gate
13770Sstevel@tonic-gate if (clientp->ic_init_state_class & IBMF_CI_INIT_RECV_TASKQ_DONE) {
13780Sstevel@tonic-gate if ((clientp->ic_reg_flags & IBMF_REG_FLAG_NO_OFFLOAD) == 0) {
13790Sstevel@tonic-gate taskq_destroy(clientp->ic_recv_taskq);
13800Sstevel@tonic-gate }
13810Sstevel@tonic-gate clientp->ic_init_state_class &= ~IBMF_CI_INIT_RECV_TASKQ_DONE;
13820Sstevel@tonic-gate }
13830Sstevel@tonic-gate
13840Sstevel@tonic-gate mutex_destroy(&clientp->ic_mutex);
13850Sstevel@tonic-gate mutex_destroy(&clientp->ic_msg_mutex);
13860Sstevel@tonic-gate mutex_destroy(&clientp->ic_kstat_mutex);
13870Sstevel@tonic-gate cv_destroy(&clientp->ic_recv_cb_teardown_cv);
13880Sstevel@tonic-gate kmem_free((void *)clientp, sizeof (ibmf_client_t));
13890Sstevel@tonic-gate
13900Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_free_client_end,
13910Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_free_client() exit\n");
13920Sstevel@tonic-gate }
13930Sstevel@tonic-gate
13940Sstevel@tonic-gate /*
13950Sstevel@tonic-gate * ibmf_i_validate_classes_and_port():
13960Sstevel@tonic-gate * Validate the class type and get the client structure
13970Sstevel@tonic-gate */
13980Sstevel@tonic-gate int
ibmf_i_validate_classes_and_port(ibmf_ci_t * ibmf_cip,ibmf_register_info_t * client_infop)13990Sstevel@tonic-gate ibmf_i_validate_classes_and_port(ibmf_ci_t *ibmf_cip,
14000Sstevel@tonic-gate ibmf_register_info_t *client_infop)
14010Sstevel@tonic-gate {
14020Sstevel@tonic-gate ibmf_client_t *ibmf_clientp;
14030Sstevel@tonic-gate int status;
14040Sstevel@tonic-gate
14050Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4,
14060Sstevel@tonic-gate ibmf_i_validate_classes_and_port_start, IBMF_TNF_TRACE, "",
14070Sstevel@tonic-gate "ibmf_i_validate_classes_and_port() enter, cip = %p, "
14080Sstevel@tonic-gate "clientp = %p\n", tnf_opaque, cip, ibmf_cip,
14090Sstevel@tonic-gate tnf_opaque, client_infop, client_infop);
14100Sstevel@tonic-gate
14110Sstevel@tonic-gate /*
14120Sstevel@tonic-gate * the Solaris implementation of IBMF does not support
14130Sstevel@tonic-gate * the UNIVERSAL_CLASS
14140Sstevel@tonic-gate */
14150Sstevel@tonic-gate if (client_infop->ir_client_class == UNIVERSAL_CLASS) {
14160Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
14170Sstevel@tonic-gate ibmf_i_validate_classes_and_port_err, IBMF_TNF_ERROR, "",
14180Sstevel@tonic-gate "%s\n", tnf_string, msg,
14190Sstevel@tonic-gate "UNIVERSAL class is not supported");
14200Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
14210Sstevel@tonic-gate ibmf_i_validate_classes_and_port_end, IBMF_TNF_TRACE, "",
14220Sstevel@tonic-gate "ibmf_i_validate_classes_and_port() exit\n");
14230Sstevel@tonic-gate return (IBMF_NOT_SUPPORTED);
14240Sstevel@tonic-gate }
14250Sstevel@tonic-gate
14260Sstevel@tonic-gate /*
14270Sstevel@tonic-gate * Check if the client context already exists on the list
14280Sstevel@tonic-gate * maintained in the CI context. If it is, then the client class
14290Sstevel@tonic-gate * has already been registered for.
14300Sstevel@tonic-gate */
14310Sstevel@tonic-gate status = ibmf_i_lookup_client_by_info(ibmf_cip, client_infop,
14320Sstevel@tonic-gate &ibmf_clientp);
14330Sstevel@tonic-gate if (status != IBMF_SUCCESS) {
14340Sstevel@tonic-gate /* client class has not been previously registered for */
14350Sstevel@tonic-gate status = IBMF_SUCCESS;
14360Sstevel@tonic-gate } else {
14370Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
14380Sstevel@tonic-gate ibmf_i_validate_classes_and_port_err, IBMF_TNF_ERROR, "",
14390Sstevel@tonic-gate "client already registered, class = 0x%X\n",
14400Sstevel@tonic-gate tnf_uint, class, client_infop->ir_client_class);
14410Sstevel@tonic-gate status = IBMF_PORT_IN_USE;
14420Sstevel@tonic-gate }
14430Sstevel@tonic-gate
14440Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
14450Sstevel@tonic-gate ibmf_i_validate_classes_and_port_end, IBMF_TNF_TRACE, "",
14460Sstevel@tonic-gate "ibmf_i_validate_classes_and_port() exit\n");
14470Sstevel@tonic-gate return (status);
14480Sstevel@tonic-gate }
14490Sstevel@tonic-gate
14500Sstevel@tonic-gate /*
14510Sstevel@tonic-gate * ibmf_i_lookup_client_by_info():
14520Sstevel@tonic-gate * Get the client structure from the list
14530Sstevel@tonic-gate */
14540Sstevel@tonic-gate static int
ibmf_i_lookup_client_by_info(ibmf_ci_t * ibmf_cip,ibmf_register_info_t * ir_client,ibmf_client_t ** clientpp)14550Sstevel@tonic-gate ibmf_i_lookup_client_by_info(ibmf_ci_t *ibmf_cip,
14560Sstevel@tonic-gate ibmf_register_info_t *ir_client, ibmf_client_t **clientpp)
14570Sstevel@tonic-gate {
14580Sstevel@tonic-gate ibmf_client_t *clientp;
14590Sstevel@tonic-gate
14600Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4,
14610Sstevel@tonic-gate ibmf_i_lookup_client_by_info_start, IBMF_TNF_TRACE, "",
14620Sstevel@tonic-gate "ibmf_i_lookup_client_by_info() enter, cip = %p, clientinfo = %p\n",
14630Sstevel@tonic-gate tnf_opaque, cip, ibmf_cip, tnf_opaque, clientinfo, ir_client);
14640Sstevel@tonic-gate
14650Sstevel@tonic-gate ASSERT(MUTEX_NOT_HELD(&ibmf_cip->ci_clients_mutex));
14660Sstevel@tonic-gate
14670Sstevel@tonic-gate /*
14680Sstevel@tonic-gate * walk the CI's client list searching for one with the specified class
14690Sstevel@tonic-gate */
14700Sstevel@tonic-gate mutex_enter(&ibmf_cip->ci_clients_mutex);
14710Sstevel@tonic-gate clientp = ibmf_cip->ci_clients;
14720Sstevel@tonic-gate while (clientp != NULL) {
14730Sstevel@tonic-gate ibmf_client_info_t *tmp = &clientp->ic_client_info;
14740Sstevel@tonic-gate if (tmp->client_class == ir_client->ir_client_class &&
14750Sstevel@tonic-gate ir_client->ir_client_class != UNIVERSAL_CLASS &&
14760Sstevel@tonic-gate tmp->ci_guid == ir_client->ir_ci_guid &&
14770Sstevel@tonic-gate tmp->port_num == ir_client->ir_port_num) {
14780Sstevel@tonic-gate /* found our match */
14790Sstevel@tonic-gate break;
14800Sstevel@tonic-gate }
14810Sstevel@tonic-gate clientp = clientp->ic_next;
14820Sstevel@tonic-gate }
14830Sstevel@tonic-gate mutex_exit(&ibmf_cip->ci_clients_mutex);
14840Sstevel@tonic-gate
14850Sstevel@tonic-gate if (clientp != NULL) {
14860Sstevel@tonic-gate *clientpp = clientp;
14870Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4,
14880Sstevel@tonic-gate ibmf_i_lookup_client_by_info_end, IBMF_TNF_TRACE, "",
14890Sstevel@tonic-gate "ibmf_i_lookup_client_by_info(): clientp = %p\n",
14900Sstevel@tonic-gate tnf_opaque, clientp, clientp);
14910Sstevel@tonic-gate return (IBMF_SUCCESS);
14920Sstevel@tonic-gate } else {
14930Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
14940Sstevel@tonic-gate ibmf_i_lookup_client_by_info_end, IBMF_TNF_TRACE, "",
14950Sstevel@tonic-gate "ibmf_i_lookup_client_by_info() exit\n");
14960Sstevel@tonic-gate return (IBMF_FAILURE);
14970Sstevel@tonic-gate }
14980Sstevel@tonic-gate }
14990Sstevel@tonic-gate
15000Sstevel@tonic-gate /*
15010Sstevel@tonic-gate * ibmf_i_add_client():
15020Sstevel@tonic-gate * Add a new client to the client list
15030Sstevel@tonic-gate */
15040Sstevel@tonic-gate void
ibmf_i_add_client(ibmf_ci_t * ibmf_cip,ibmf_client_t * ibmf_clientp)15050Sstevel@tonic-gate ibmf_i_add_client(ibmf_ci_t *ibmf_cip, ibmf_client_t *ibmf_clientp)
15060Sstevel@tonic-gate {
15070Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_add_start,
15080Sstevel@tonic-gate IBMF_TNF_TRACE, "",
15090Sstevel@tonic-gate "ibmf_i_add_client() enter, cip = %p, clientp = %p\n",
15100Sstevel@tonic-gate tnf_opaque, ibmf_ci, ibmf_cip, tnf_opaque, client, ibmf_clientp);
15110Sstevel@tonic-gate
15120Sstevel@tonic-gate ASSERT(MUTEX_NOT_HELD(&ibmf_cip->ci_clients_mutex));
15130Sstevel@tonic-gate
15140Sstevel@tonic-gate mutex_enter(&ibmf_cip->ci_clients_mutex);
15150Sstevel@tonic-gate ibmf_clientp->ic_next = NULL;
15160Sstevel@tonic-gate ibmf_clientp->ic_prev = ibmf_cip->ci_clients_last;
15170Sstevel@tonic-gate if (ibmf_cip->ci_clients == NULL) {
15180Sstevel@tonic-gate ibmf_cip->ci_clients = ibmf_clientp;
15190Sstevel@tonic-gate }
15200Sstevel@tonic-gate if (ibmf_cip->ci_clients_last) {
15210Sstevel@tonic-gate ibmf_cip->ci_clients_last->ic_next = ibmf_clientp;
15220Sstevel@tonic-gate }
15230Sstevel@tonic-gate ibmf_cip->ci_clients_last = ibmf_clientp;
15240Sstevel@tonic-gate mutex_exit(&ibmf_cip->ci_clients_mutex);
15250Sstevel@tonic-gate
15260Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_add_end,
15270Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_add_client() exit\n");
15280Sstevel@tonic-gate }
15290Sstevel@tonic-gate
15300Sstevel@tonic-gate /*
15310Sstevel@tonic-gate * ibmf_i_delete_client():
15320Sstevel@tonic-gate * Delete a client from the client list
15330Sstevel@tonic-gate */
15340Sstevel@tonic-gate void
ibmf_i_delete_client(ibmf_ci_t * ibmf_cip,ibmf_client_t * ibmf_clientp)15350Sstevel@tonic-gate ibmf_i_delete_client(ibmf_ci_t *ibmf_cip, ibmf_client_t *ibmf_clientp)
15360Sstevel@tonic-gate {
15370Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_delete_client_start,
15380Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_delete_client() enter, "
15390Sstevel@tonic-gate "ibmf_i_delete_client() enter, cip = %p, clientp = %p\n",
15400Sstevel@tonic-gate tnf_opaque, ibmf_ci, ibmf_cip, tnf_opaque, client, ibmf_clientp);
15410Sstevel@tonic-gate
15420Sstevel@tonic-gate ASSERT(MUTEX_NOT_HELD(&ibmf_cip->ci_clients_mutex));
15430Sstevel@tonic-gate
15440Sstevel@tonic-gate mutex_enter(&ibmf_cip->ci_clients_mutex);
15450Sstevel@tonic-gate if (ibmf_clientp->ic_next)
15460Sstevel@tonic-gate ibmf_clientp->ic_next->ic_prev = ibmf_clientp->ic_prev;
15470Sstevel@tonic-gate
15480Sstevel@tonic-gate if (ibmf_clientp->ic_prev)
15490Sstevel@tonic-gate ibmf_clientp->ic_prev->ic_next = ibmf_clientp->ic_next;
15500Sstevel@tonic-gate
15510Sstevel@tonic-gate if (ibmf_cip->ci_clients == ibmf_clientp) {
15520Sstevel@tonic-gate ibmf_cip->ci_clients = ibmf_clientp->ic_next;
15530Sstevel@tonic-gate }
15540Sstevel@tonic-gate if (ibmf_cip->ci_clients_last == ibmf_clientp) {
15550Sstevel@tonic-gate ibmf_cip->ci_clients_last = ibmf_clientp->ic_prev;
15560Sstevel@tonic-gate }
15570Sstevel@tonic-gate mutex_exit(&ibmf_cip->ci_clients_mutex);
15580Sstevel@tonic-gate
15590Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_delete_client_end,
15600Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_delete_client() exit\n");
15610Sstevel@tonic-gate }
15620Sstevel@tonic-gate
15630Sstevel@tonic-gate /*
15640Sstevel@tonic-gate * ibmf_i_get_qp():
15650Sstevel@tonic-gate * Get the QP structure based on the client class
15660Sstevel@tonic-gate */
15670Sstevel@tonic-gate int
ibmf_i_get_qp(ibmf_ci_t * ibmf_cip,uint_t port_num,ibmf_client_type_t class,ibmf_qp_t ** qppp)15680Sstevel@tonic-gate ibmf_i_get_qp(ibmf_ci_t *ibmf_cip, uint_t port_num, ibmf_client_type_t class,
15690Sstevel@tonic-gate ibmf_qp_t **qppp)
15700Sstevel@tonic-gate {
15710Sstevel@tonic-gate ibmf_qp_t *qpp;
15720Sstevel@tonic-gate int qp_num, status = IBMF_SUCCESS;
15730Sstevel@tonic-gate
15740Sstevel@tonic-gate IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_get_qp_start,
15750Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_get_qp() enter, cip = %p, "
15760Sstevel@tonic-gate "port = %d, class = %x\n", tnf_opaque, ibmf_ci, ibmf_cip,
15770Sstevel@tonic-gate tnf_int, port, port_num, tnf_opaque, class, class);
15780Sstevel@tonic-gate
15790Sstevel@tonic-gate ASSERT(MUTEX_NOT_HELD(&ibmf_cip->ci_mutex));
15800Sstevel@tonic-gate
15810Sstevel@tonic-gate mutex_enter(&ibmf_cip->ci_mutex);
15820Sstevel@tonic-gate
15830Sstevel@tonic-gate /*
15840Sstevel@tonic-gate * walk through the list of qps on this ci, looking for one that
15850Sstevel@tonic-gate * corresponds to the type and class the caller is interested in.
15860Sstevel@tonic-gate * If it is not there, we need allocate it from the transport. Since
15870Sstevel@tonic-gate * qp0 & qp1 can only be allocated once, we maintain a reference count
15880Sstevel@tonic-gate * and call the transport for allocation iff the ref count is 0.
15890Sstevel@tonic-gate */
15900Sstevel@tonic-gate qp_num = (class == SUBN_AGENT || class == SUBN_MANAGER) ? 0 : 1;
15910Sstevel@tonic-gate
15920Sstevel@tonic-gate qpp = ibmf_cip->ci_qp_list;
15930Sstevel@tonic-gate while (qpp != NULL) {
15940Sstevel@tonic-gate if (port_num == qpp->iq_port_num && qp_num == qpp->iq_qp_num)
15950Sstevel@tonic-gate break;
15960Sstevel@tonic-gate qpp = qpp->iq_next;
15970Sstevel@tonic-gate }
15980Sstevel@tonic-gate
15990Sstevel@tonic-gate if (qpp == NULL) {
16000Sstevel@tonic-gate /*
16010Sstevel@tonic-gate * allocate qp and add it the qp list; recheck to
16020Sstevel@tonic-gate * catch races
16030Sstevel@tonic-gate */
16040Sstevel@tonic-gate ibmf_qp_t *tqpp;
16050Sstevel@tonic-gate
16060Sstevel@tonic-gate mutex_exit(&ibmf_cip->ci_mutex);
16070Sstevel@tonic-gate
16080Sstevel@tonic-gate tqpp = (ibmf_qp_t *)kmem_zalloc(sizeof (ibmf_qp_t), KM_SLEEP);
16090Sstevel@tonic-gate
16100Sstevel@tonic-gate /* check the list under lock */
16110Sstevel@tonic-gate mutex_enter(&ibmf_cip->ci_mutex);
16120Sstevel@tonic-gate
16130Sstevel@tonic-gate qpp = ibmf_cip->ci_qp_list;
16140Sstevel@tonic-gate while (qpp != NULL) {
16150Sstevel@tonic-gate if (port_num == qpp->iq_port_num && qp_num ==
16160Sstevel@tonic-gate qpp->iq_qp_num)
16170Sstevel@tonic-gate break;
16180Sstevel@tonic-gate qpp = qpp->iq_next;
16190Sstevel@tonic-gate }
16200Sstevel@tonic-gate
16210Sstevel@tonic-gate if (qpp != NULL) {
16220Sstevel@tonic-gate /* some one raced past us and added to the list */
16230Sstevel@tonic-gate kmem_free((void *)tqpp, sizeof (ibmf_qp_t));
16240Sstevel@tonic-gate } else {
16250Sstevel@tonic-gate /* add this to the qp list */
16260Sstevel@tonic-gate qpp = tqpp;
16270Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*qpp))
16280Sstevel@tonic-gate qpp->iq_next = NULL;
16290Sstevel@tonic-gate if (ibmf_cip->ci_qp_list == NULL)
16300Sstevel@tonic-gate ibmf_cip->ci_qp_list = qpp;
16310Sstevel@tonic-gate if (ibmf_cip->ci_qp_list_tail != NULL)
16320Sstevel@tonic-gate ibmf_cip->ci_qp_list_tail->iq_next = qpp;
16330Sstevel@tonic-gate ibmf_cip->ci_qp_list_tail = qpp;
16340Sstevel@tonic-gate qpp->iq_port_num = port_num;
16350Sstevel@tonic-gate qpp->iq_qp_num = qp_num;
16360Sstevel@tonic-gate qpp->iq_flags = IBMF_QP_FLAGS_INVALID;
16370Sstevel@tonic-gate mutex_init(&qpp->iq_mutex, NULL, MUTEX_DRIVER, NULL);
16380Sstevel@tonic-gate }
16390Sstevel@tonic-gate }
16400Sstevel@tonic-gate
16410Sstevel@tonic-gate /* we now have a QP context */
16420Sstevel@tonic-gate for (;;) {
16430Sstevel@tonic-gate if (qpp->iq_flags == IBMF_QP_FLAGS_INITING) {
16440Sstevel@tonic-gate
16450Sstevel@tonic-gate /* block till qp is in VALID state */
16460Sstevel@tonic-gate cv_wait(&ibmf_cip->ci_qp_cv, &ibmf_cip->ci_mutex);
16470Sstevel@tonic-gate continue;
16480Sstevel@tonic-gate
16490Sstevel@tonic-gate }
16500Sstevel@tonic-gate
16510Sstevel@tonic-gate if (qpp->iq_flags == IBMF_QP_FLAGS_UNINITING) {
16520Sstevel@tonic-gate
16530Sstevel@tonic-gate /* block till qp is in INVALID state */
16540Sstevel@tonic-gate cv_wait(&ibmf_cip->ci_qp_cv, &ibmf_cip->ci_mutex);
16550Sstevel@tonic-gate continue;
16560Sstevel@tonic-gate }
16570Sstevel@tonic-gate
16580Sstevel@tonic-gate if (qpp->iq_flags == IBMF_QP_FLAGS_INVALID) {
16590Sstevel@tonic-gate if ((status = ibmf_i_init_qp(ibmf_cip, qpp)) !=
16600Sstevel@tonic-gate IBMF_SUCCESS) {
16610Sstevel@tonic-gate ibmf_qp_t *tqpp;
16620Sstevel@tonic-gate
16630Sstevel@tonic-gate /*
16640Sstevel@tonic-gate * Remove the QP context from the CI's list.
16650Sstevel@tonic-gate * Only initialized QPs should be on the list.
16660Sstevel@tonic-gate * We know that this QP is on the list, so
16670Sstevel@tonic-gate * the list is not empty.
16680Sstevel@tonic-gate */
16690Sstevel@tonic-gate tqpp = ibmf_cip->ci_qp_list;
16700Sstevel@tonic-gate if (tqpp == qpp) {
16710Sstevel@tonic-gate /* Only QP context on the list */
16720Sstevel@tonic-gate ibmf_cip->ci_qp_list = NULL;
16730Sstevel@tonic-gate ibmf_cip->ci_qp_list_tail = NULL;
16740Sstevel@tonic-gate }
16750Sstevel@tonic-gate
16760Sstevel@tonic-gate /* Find the QP context before the last one */
16770Sstevel@tonic-gate if (tqpp != qpp) {
16780Sstevel@tonic-gate while (tqpp->iq_next != qpp) {
16790Sstevel@tonic-gate tqpp = tqpp->iq_next;
16800Sstevel@tonic-gate }
16810Sstevel@tonic-gate
16820Sstevel@tonic-gate /*
16830Sstevel@tonic-gate * We are at the second last element of
16840Sstevel@tonic-gate * the list. Readjust the tail pointer.
16850Sstevel@tonic-gate * Remove the last element from the
16860Sstevel@tonic-gate * list.
16870Sstevel@tonic-gate */
16880Sstevel@tonic-gate tqpp->iq_next = NULL;
16890Sstevel@tonic-gate ibmf_cip->ci_qp_list_tail = tqpp;
16900Sstevel@tonic-gate }
16910Sstevel@tonic-gate
16920Sstevel@tonic-gate /* Free up the QP context */
16930Sstevel@tonic-gate kmem_free((void *)qpp, sizeof (ibmf_qp_t));
16940Sstevel@tonic-gate
16950Sstevel@tonic-gate break;
16960Sstevel@tonic-gate }
16970Sstevel@tonic-gate continue;
16980Sstevel@tonic-gate }
16990Sstevel@tonic-gate
17000Sstevel@tonic-gate if (qpp->iq_flags == IBMF_QP_FLAGS_INITED) {
17010Sstevel@tonic-gate qpp->iq_qp_ref++;
17020Sstevel@tonic-gate break;
17030Sstevel@tonic-gate }
17040Sstevel@tonic-gate }
17050Sstevel@tonic-gate
17060Sstevel@tonic-gate _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*qpp))
17070Sstevel@tonic-gate
17080Sstevel@tonic-gate mutex_exit(&ibmf_cip->ci_mutex);
17090Sstevel@tonic-gate
17100Sstevel@tonic-gate if (status == IBMF_SUCCESS) {
17110Sstevel@tonic-gate *qppp = qpp;
17120Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_get_qp_end,
17130Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_get_qp() exit "
17140Sstevel@tonic-gate "qp_handle = %p\n", tnf_opaque, qp_handle, qpp);
17150Sstevel@tonic-gate return (IBMF_SUCCESS);
17160Sstevel@tonic-gate } else {
17170Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1, ibmf_i_get_qp_err,
17180Sstevel@tonic-gate IBMF_TNF_ERROR, "", "%s\n", tnf_string, msg,
17190Sstevel@tonic-gate "ibmf_i_get_qp(): qp_not found");
17200Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_get_qp_end,
17210Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_get_qp() exit\n");
17220Sstevel@tonic-gate return (status);
17230Sstevel@tonic-gate }
17240Sstevel@tonic-gate }
17250Sstevel@tonic-gate
17260Sstevel@tonic-gate /*
17270Sstevel@tonic-gate * ibmf_i_release_qp():
17280Sstevel@tonic-gate * Drop the reference count on the QP structure
17290Sstevel@tonic-gate */
17300Sstevel@tonic-gate void
ibmf_i_release_qp(ibmf_ci_t * ibmf_cip,ibmf_qp_t ** qppp)17310Sstevel@tonic-gate ibmf_i_release_qp(ibmf_ci_t *ibmf_cip, ibmf_qp_t **qppp)
17320Sstevel@tonic-gate {
17330Sstevel@tonic-gate ibmf_qp_t *qpp;
17340Sstevel@tonic-gate
17350Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_release_qp_start,
17360Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_release_qp() enter, cip = %p, "
17370Sstevel@tonic-gate "qpp = %p\n", tnf_opaque, cip, ibmf_cip, tnf_opaque, qpp, *qppp);
17380Sstevel@tonic-gate
17390Sstevel@tonic-gate ASSERT(MUTEX_NOT_HELD(&ibmf_cip->ci_mutex));
17400Sstevel@tonic-gate
17410Sstevel@tonic-gate mutex_enter(&ibmf_cip->ci_mutex);
17420Sstevel@tonic-gate qpp = *qppp;
17430Sstevel@tonic-gate qpp->iq_qp_ref--;
17440Sstevel@tonic-gate if (qpp->iq_qp_ref == 0)
17450Sstevel@tonic-gate ibmf_i_uninit_qp(ibmf_cip, qpp);
17460Sstevel@tonic-gate mutex_exit(&ibmf_cip->ci_mutex);
17470Sstevel@tonic-gate
17480Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_release_qp_end,
17490Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_release_qp() exit\n");
17500Sstevel@tonic-gate }
17510Sstevel@tonic-gate
17520Sstevel@tonic-gate /*
17530Sstevel@tonic-gate * ibmf_i_init_qp():
17540Sstevel@tonic-gate * Set up the QP context, request a QP from the IBT framework
17550Sstevel@tonic-gate * and initialize it
17560Sstevel@tonic-gate */
17570Sstevel@tonic-gate static int
ibmf_i_init_qp(ibmf_ci_t * ibmf_cip,ibmf_qp_t * qpp)17580Sstevel@tonic-gate ibmf_i_init_qp(ibmf_ci_t *ibmf_cip, ibmf_qp_t *qpp)
17590Sstevel@tonic-gate {
17600Sstevel@tonic-gate ibt_sqp_type_t qp_type;
17610Sstevel@tonic-gate ibt_qp_alloc_attr_t qp_attrs;
17620Sstevel@tonic-gate ibt_qp_hdl_t qp_handle;
17630Sstevel@tonic-gate ibt_qp_info_t qp_modify_attr;
17640Sstevel@tonic-gate ibt_status_t ibt_status;
17650Sstevel@tonic-gate int i, status;
17660Sstevel@tonic-gate
17670Sstevel@tonic-gate IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_qp_start,
17680Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_init_qp() enter, cip = %p, "
17690Sstevel@tonic-gate "port = %d, qp = %d\n", tnf_opaque, ibmf_ci, ibmf_cip, tnf_int,
17700Sstevel@tonic-gate port, qpp->iq_port_num, tnf_int, num, qpp->iq_qp_num);
17710Sstevel@tonic-gate
17720Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(qpp->iq_qp_handle))
17730Sstevel@tonic-gate
17740Sstevel@tonic-gate ASSERT(MUTEX_HELD(&ibmf_cip->ci_mutex));
17750Sstevel@tonic-gate
17760Sstevel@tonic-gate qpp->iq_flags = IBMF_QP_FLAGS_INITING;
17770Sstevel@tonic-gate mutex_exit(&ibmf_cip->ci_mutex);
17780Sstevel@tonic-gate if (qpp->iq_qp_handle) { /* closed but not yet freed */
17790Sstevel@tonic-gate ibt_status = ibt_free_qp(qpp->iq_qp_handle);
17800Sstevel@tonic-gate if (ibt_status != IBT_SUCCESS) {
17810Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
17820Sstevel@tonic-gate ibmf_i_init_qp_err, IBMF_TNF_ERROR, "",
17830Sstevel@tonic-gate "%s, status = %d\n", tnf_string, msg,
17840Sstevel@tonic-gate "ibt_free_qp returned error",
17850Sstevel@tonic-gate tnf_uint, ibt_status, ibt_status);
17860Sstevel@tonic-gate }
17870Sstevel@tonic-gate qpp->iq_qp_handle = NULL;
17880Sstevel@tonic-gate }
17890Sstevel@tonic-gate ASSERT(qpp->iq_qp_num == 0 || qpp->iq_qp_num == 1);
17900Sstevel@tonic-gate if (qpp->iq_qp_num == 0)
17910Sstevel@tonic-gate qp_type = IBT_SMI_SQP;
17920Sstevel@tonic-gate else
17930Sstevel@tonic-gate qp_type = IBT_GSI_SQP;
17940Sstevel@tonic-gate qp_attrs.qp_scq_hdl = ibmf_cip->ci_cq_handle;
17950Sstevel@tonic-gate qp_attrs.qp_rcq_hdl = ibmf_cip->ci_cq_handle;
17960Sstevel@tonic-gate qp_attrs.qp_pd_hdl = ibmf_cip->ci_pd;
17970Sstevel@tonic-gate qp_attrs.qp_sizes.cs_sq_sgl = 1;
17980Sstevel@tonic-gate qp_attrs.qp_sizes.cs_rq_sgl = IBMF_MAX_RQ_WR_SGL_ELEMENTS;
17990Sstevel@tonic-gate qp_attrs.qp_sizes.cs_sq = ibmf_send_wqes_posted_per_qp;
18000Sstevel@tonic-gate qp_attrs.qp_sizes.cs_rq = ibmf_recv_wqes_posted_per_qp;
18010Sstevel@tonic-gate qp_attrs.qp_flags = IBT_ALL_SIGNALED;
18020Sstevel@tonic-gate qp_attrs.qp_alloc_flags = IBT_QP_NO_FLAGS;
18030Sstevel@tonic-gate
18040Sstevel@tonic-gate /* call the IB transport to allocate a special QP */
18050Sstevel@tonic-gate ibt_status = ibt_alloc_special_qp(ibmf_cip->ci_ci_handle,
18060Sstevel@tonic-gate qpp->iq_port_num, qp_type, &qp_attrs, NULL, &qp_handle);
18070Sstevel@tonic-gate if (ibt_status != IBT_SUCCESS) {
18080Sstevel@tonic-gate mutex_enter(&ibmf_cip->ci_mutex);
18090Sstevel@tonic-gate qpp->iq_flags = IBMF_QP_FLAGS_INVALID;
18100Sstevel@tonic-gate cv_broadcast(&ibmf_cip->ci_qp_cv);
18110Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1, ibmf_i_init_qp_err,
18120Sstevel@tonic-gate IBMF_TNF_ERROR, "", "ibmf_i_init_qp() error status = %d\n",
18130Sstevel@tonic-gate tnf_uint, ibt_status, ibt_status);
18140Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_qp_end,
18150Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_init_qp() exit\n");
18160Sstevel@tonic-gate return (IBMF_TRANSPORT_FAILURE);
18170Sstevel@tonic-gate }
18180Sstevel@tonic-gate
18190Sstevel@tonic-gate /* initialize qpp */
18200Sstevel@tonic-gate qpp->iq_qp_handle = qp_handle;
18210Sstevel@tonic-gate qp_modify_attr.qp_trans = IBT_UD_SRV;
18220Sstevel@tonic-gate qp_modify_attr.qp_flags = IBT_CEP_NO_FLAGS;
18230Sstevel@tonic-gate
18240Sstevel@tonic-gate /* get the pkey index for the specified pkey */
18250Sstevel@tonic-gate if (ibmf_i_get_pkeyix(ibmf_cip->ci_ci_handle, IBMF_P_KEY_DEF_LIMITED,
18260Sstevel@tonic-gate qpp->iq_port_num, &qp_modify_attr.qp_transport.ud.ud_pkey_ix) !=
18270Sstevel@tonic-gate IBMF_SUCCESS) {
18280Sstevel@tonic-gate ibt_status = ibt_free_qp(qpp->iq_qp_handle);
18290Sstevel@tonic-gate if (ibt_status != IBT_SUCCESS) {
18300Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
18310Sstevel@tonic-gate ibmf_i_init_qp_err, IBMF_TNF_ERROR, "",
18320Sstevel@tonic-gate "%s, status = %d\n", tnf_string, msg,
18330Sstevel@tonic-gate "ibt_free_qp returned error",
18340Sstevel@tonic-gate tnf_uint, ibt_status, ibt_status);
18350Sstevel@tonic-gate }
18360Sstevel@tonic-gate mutex_enter(&ibmf_cip->ci_mutex);
18370Sstevel@tonic-gate qpp->iq_flags = IBMF_QP_FLAGS_INVALID;
18380Sstevel@tonic-gate cv_broadcast(&ibmf_cip->ci_qp_cv);
18390Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_NODEBUG, DPRINT_L1, ibmf_i_init_qp_err,
18400Sstevel@tonic-gate IBMF_TNF_ERROR, "", "ibmf_init_qp(): failed to get "
18410Sstevel@tonic-gate "pkey index\n");
18420Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_qp_end,
18430Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_init_qp() exit\n");
18440Sstevel@tonic-gate return (IBMF_FAILURE);
18450Sstevel@tonic-gate }
18460Sstevel@tonic-gate qp_modify_attr.qp_transport.ud.ud_sq_psn = 0;
18470Sstevel@tonic-gate qp_modify_attr.qp_transport.ud.ud_port = qpp->iq_port_num;
18480Sstevel@tonic-gate qp_modify_attr.qp_transport.ud.ud_qkey = IBMF_MGMT_Q_KEY;
18490Sstevel@tonic-gate
18500Sstevel@tonic-gate /* call the IB transport to initialize the QP */
18510Sstevel@tonic-gate ibt_status = ibt_initialize_qp(qp_handle, &qp_modify_attr);
18520Sstevel@tonic-gate if (ibt_status != IBT_SUCCESS) {
18530Sstevel@tonic-gate ibt_status = ibt_free_qp(qpp->iq_qp_handle);
18540Sstevel@tonic-gate if (ibt_status != IBT_SUCCESS) {
18550Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
18560Sstevel@tonic-gate ibmf_i_init_qp_err, IBMF_TNF_ERROR, "",
18570Sstevel@tonic-gate "%s, status = %d\n", tnf_string, msg,
18580Sstevel@tonic-gate "ibt_free_qp returned error",
18590Sstevel@tonic-gate tnf_uint, ibt_status, ibt_status);
18600Sstevel@tonic-gate }
18610Sstevel@tonic-gate mutex_enter(&ibmf_cip->ci_mutex);
18620Sstevel@tonic-gate qpp->iq_flags = IBMF_QP_FLAGS_INVALID;
18630Sstevel@tonic-gate cv_broadcast(&ibmf_cip->ci_qp_cv);
18640Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1, ibmf_i_init_qp_err,
18650Sstevel@tonic-gate IBMF_TNF_ERROR, "", "ibmf_init_qp(): error status = %d\n",
18660Sstevel@tonic-gate tnf_uint, ibt_status, ibt_status);
18670Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_qp_end,
18680Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_init_qp() exit\n");
18690Sstevel@tonic-gate return (IBMF_TRANSPORT_FAILURE);
18700Sstevel@tonic-gate }
18710Sstevel@tonic-gate
18720Sstevel@tonic-gate /* post receive wqes to the RQ to handle unsolicited inbound packets */
18730Sstevel@tonic-gate for (i = 0; i < ibmf_recv_wqes_per_port; i++) {
18740Sstevel@tonic-gate status = ibmf_i_post_recv_buffer(ibmf_cip, qpp,
18750Sstevel@tonic-gate B_TRUE, IBMF_QP_HANDLE_DEFAULT);
18760Sstevel@tonic-gate if (status != IBMF_SUCCESS) {
18770Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L1,
18780Sstevel@tonic-gate ibmf_i_init_qp, IBMF_TNF_TRACE, "",
18790Sstevel@tonic-gate "%s\n", tnf_string, msg, "ibmf_i_init_qp(): "
18800Sstevel@tonic-gate "ibmf_i_post_recv_buffer() failed");
18810Sstevel@tonic-gate }
18820Sstevel@tonic-gate }
18830Sstevel@tonic-gate mutex_enter(&ibmf_cip->ci_mutex);
18840Sstevel@tonic-gate
18850Sstevel@tonic-gate /* set the state and signal blockers */
18860Sstevel@tonic-gate qpp->iq_flags = IBMF_QP_FLAGS_INITED;
18870Sstevel@tonic-gate cv_broadcast(&ibmf_cip->ci_qp_cv);
18880Sstevel@tonic-gate
18890Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_qp_end,
18900Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_init_qp() exit\n");
18910Sstevel@tonic-gate return (IBMF_SUCCESS);
18920Sstevel@tonic-gate }
18930Sstevel@tonic-gate
18940Sstevel@tonic-gate /*
18950Sstevel@tonic-gate * ibmf_i_uninit_qp():
18960Sstevel@tonic-gate * Invalidate the QP context
18970Sstevel@tonic-gate */
18980Sstevel@tonic-gate static void
ibmf_i_uninit_qp(ibmf_ci_t * ibmf_cip,ibmf_qp_t * qpp)18990Sstevel@tonic-gate ibmf_i_uninit_qp(ibmf_ci_t *ibmf_cip, ibmf_qp_t *qpp)
19000Sstevel@tonic-gate {
19010Sstevel@tonic-gate ibt_status_t status;
19020Sstevel@tonic-gate
19030Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_uninit_qp_start,
19040Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_uninit_qp() enter, cip = %p "
19050Sstevel@tonic-gate "qpp = %p\n", tnf_opaque, cip, ibmf_cip, tnf_opaque, qpp, qpp);
19060Sstevel@tonic-gate
19070Sstevel@tonic-gate ASSERT(MUTEX_HELD(&ibmf_cip->ci_mutex));
19080Sstevel@tonic-gate
19090Sstevel@tonic-gate /* mark the state as uniniting */
19100Sstevel@tonic-gate ASSERT(qpp->iq_qp_ref == 0);
19110Sstevel@tonic-gate qpp->iq_flags = IBMF_QP_FLAGS_UNINITING;
19120Sstevel@tonic-gate mutex_exit(&ibmf_cip->ci_mutex);
19130Sstevel@tonic-gate
19140Sstevel@tonic-gate /* note: we ignore error values from ibt_flush_qp */
19150Sstevel@tonic-gate status = ibt_flush_qp(qpp->iq_qp_handle);
19160Sstevel@tonic-gate if (status != IBT_SUCCESS) {
19170Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L2,
19180Sstevel@tonic-gate ibmf_i_uninit_qp_err, IBMF_TNF_ERROR, "",
19190Sstevel@tonic-gate "ibmf_i_uninit_qp(): %s, status = %d\n", tnf_string, msg,
19200Sstevel@tonic-gate "ibt_flush_qp returned error", tnf_int, status, status);
19210Sstevel@tonic-gate }
19220Sstevel@tonic-gate
19230Sstevel@tonic-gate /* mark state as INVALID and signal any blockers */
19240Sstevel@tonic-gate mutex_enter(&ibmf_cip->ci_mutex);
19250Sstevel@tonic-gate qpp->iq_flags = IBMF_QP_FLAGS_INVALID;
19260Sstevel@tonic-gate cv_broadcast(&ibmf_cip->ci_qp_cv);
19270Sstevel@tonic-gate
19280Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_uninit_qp_end,
19290Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_uninit_qp() exit\n");
19300Sstevel@tonic-gate }
19310Sstevel@tonic-gate
19320Sstevel@tonic-gate /*
19330Sstevel@tonic-gate * ibmf_i_alloc_msg():
19340Sstevel@tonic-gate * Allocate and set up a message context
19350Sstevel@tonic-gate */
19360Sstevel@tonic-gate int
ibmf_i_alloc_msg(ibmf_client_t * clientp,ibmf_msg_impl_t ** msgp,int km_flags)19370Sstevel@tonic-gate ibmf_i_alloc_msg(ibmf_client_t *clientp, ibmf_msg_impl_t **msgp, int km_flags)
19380Sstevel@tonic-gate {
19390Sstevel@tonic-gate ibmf_msg_impl_t *msgimplp;
19400Sstevel@tonic-gate
19410Sstevel@tonic-gate IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L4,
19420Sstevel@tonic-gate ibmf_i_alloc_msg_start, IBMF_TNF_TRACE, "",
19430Sstevel@tonic-gate "ibmf_i_alloc_msg() enter, clientp = %p, msg = %p, "
19440Sstevel@tonic-gate " kmflags = %d\n", tnf_opaque, clientp, clientp, tnf_opaque, msg,
19450Sstevel@tonic-gate *msgp, tnf_int, km_flags, km_flags);
19460Sstevel@tonic-gate
19470Sstevel@tonic-gate /* allocate the message context */
19480Sstevel@tonic-gate msgimplp = (ibmf_msg_impl_t *)kmem_zalloc(sizeof (ibmf_msg_impl_t),
19490Sstevel@tonic-gate km_flags);
19500Sstevel@tonic-gate if (msgimplp != NULL) {
19510Sstevel@tonic-gate if (km_flags == KM_SLEEP) {
19520Sstevel@tonic-gate ibmf_i_pop_ud_dest_thread(clientp->ic_myci);
19530Sstevel@tonic-gate }
19540Sstevel@tonic-gate } else {
19550Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
19560Sstevel@tonic-gate ibmf_i_alloc_msg_err, IBMF_TNF_ERROR, "",
19570Sstevel@tonic-gate "ibmf_i_alloc_msg(): %s\n",
19580Sstevel@tonic-gate tnf_string, msg, "kmem_xalloc failed");
19590Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_alloc_msg_end,
19600Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_alloc_msg() exit\n");
19610Sstevel@tonic-gate return (IBMF_NO_RESOURCES);
19620Sstevel@tonic-gate }
19630Sstevel@tonic-gate
19640Sstevel@tonic-gate *msgp = msgimplp;
19650Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_alloc_msg_end,
19660Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_alloc_msg() exit\n");
19670Sstevel@tonic-gate return (IBMF_SUCCESS);
19680Sstevel@tonic-gate }
19690Sstevel@tonic-gate
19700Sstevel@tonic-gate /*
19710Sstevel@tonic-gate * ibmf_i_free_msg():
19720Sstevel@tonic-gate * frees up all buffers allocated by IBMF for
19730Sstevel@tonic-gate * this message context, and then frees up the context
19740Sstevel@tonic-gate */
19750Sstevel@tonic-gate void
ibmf_i_free_msg(ibmf_msg_impl_t * msgimplp)19760Sstevel@tonic-gate ibmf_i_free_msg(ibmf_msg_impl_t *msgimplp)
19770Sstevel@tonic-gate {
19780Sstevel@tonic-gate ibmf_msg_bufs_t *msgbufp = &msgimplp->im_msgbufs_recv;
19790Sstevel@tonic-gate ibmf_client_t *clientp = (ibmf_client_t *)msgimplp->im_client;
19800Sstevel@tonic-gate uint32_t cl_hdr_sz, cl_hdr_off;
19810Sstevel@tonic-gate
19820Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4,
19830Sstevel@tonic-gate ibmf_i_free_msg_start, IBMF_TNF_TRACE, "",
19840Sstevel@tonic-gate "ibmf_i_free_msg() enter, msg = %p\n", tnf_opaque, msg, msgimplp);
19850Sstevel@tonic-gate
19860Sstevel@tonic-gate /* free up the UD destination resource */
19870Sstevel@tonic-gate if (msgimplp->im_ibmf_ud_dest != NULL) {
19880Sstevel@tonic-gate ibmf_i_free_ud_dest(clientp, msgimplp);
19890Sstevel@tonic-gate ibmf_i_clean_ud_dest_list(clientp->ic_myci, B_FALSE);
19900Sstevel@tonic-gate }
19910Sstevel@tonic-gate
19920Sstevel@tonic-gate /* free up the receive buffer if allocated previously */
19930Sstevel@tonic-gate if (msgbufp->im_bufs_mad_hdr != NULL) {
19940Sstevel@tonic-gate ibmf_i_mgt_class_to_hdr_sz_off(
19950Sstevel@tonic-gate msgbufp->im_bufs_mad_hdr->MgmtClass,
19960Sstevel@tonic-gate &cl_hdr_sz, &cl_hdr_off);
19970Sstevel@tonic-gate kmem_free(msgbufp->im_bufs_mad_hdr, sizeof (ib_mad_hdr_t) +
19980Sstevel@tonic-gate cl_hdr_off + msgbufp->im_bufs_cl_hdr_len +
19990Sstevel@tonic-gate msgbufp->im_bufs_cl_data_len);
20000Sstevel@tonic-gate mutex_enter(&clientp->ic_kstat_mutex);
20010Sstevel@tonic-gate IBMF_SUB32_KSTATS(clientp, recv_bufs_alloced, 1);
20020Sstevel@tonic-gate mutex_exit(&clientp->ic_kstat_mutex);
20030Sstevel@tonic-gate }
20040Sstevel@tonic-gate
20050Sstevel@tonic-gate /* destroy the message mutex */
20060Sstevel@tonic-gate mutex_destroy(&msgimplp->im_mutex);
20070Sstevel@tonic-gate
20080Sstevel@tonic-gate /* free the message context */
20090Sstevel@tonic-gate kmem_free(msgimplp, sizeof (ibmf_msg_impl_t));
20100Sstevel@tonic-gate
20110Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_free_msg_end,
20120Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_free_msg() exit\n");
20130Sstevel@tonic-gate }
20140Sstevel@tonic-gate
20150Sstevel@tonic-gate /*
20160Sstevel@tonic-gate * ibmf_i_msg_transport():
20170Sstevel@tonic-gate * Send a message posted by the IBMF client using the RMPP protocol
20180Sstevel@tonic-gate * if specified
20190Sstevel@tonic-gate */
20200Sstevel@tonic-gate int
ibmf_i_msg_transport(ibmf_client_t * clientp,ibmf_qp_handle_t ibmf_qp_handle,ibmf_msg_impl_t * msgimplp,int blocking)20210Sstevel@tonic-gate ibmf_i_msg_transport(ibmf_client_t *clientp, ibmf_qp_handle_t ibmf_qp_handle,
20220Sstevel@tonic-gate ibmf_msg_impl_t *msgimplp, int blocking)
20230Sstevel@tonic-gate {
20240Sstevel@tonic-gate ib_mad_hdr_t *madhdrp;
20250Sstevel@tonic-gate ibmf_msg_bufs_t *msgbufp, *smsgbufp;
20260Sstevel@tonic-gate uint32_t cl_hdr_sz, cl_hdr_off;
20270Sstevel@tonic-gate boolean_t isDS = 0; /* double sided (sequenced) transaction */
20280Sstevel@tonic-gate boolean_t error = B_FALSE;
20290Sstevel@tonic-gate int status = IBMF_SUCCESS;
20300Sstevel@tonic-gate uint_t refcnt;
20310Sstevel@tonic-gate char errmsg[128];
20320Sstevel@tonic-gate timeout_id_t msg_rp_unset_id, msg_tr_unset_id;
20330Sstevel@tonic-gate
20340Sstevel@tonic-gate IBMF_TRACE_4(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_msg_transport_start,
20350Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_msg_transport(): clientp = 0x%p, "
20360Sstevel@tonic-gate "qphdl = 0x%p, msgp = 0x%p, block = %d\n",
20370Sstevel@tonic-gate tnf_opaque, clientp, clientp, tnf_opaque, qphdl, ibmf_qp_handle,
20380Sstevel@tonic-gate tnf_opaque, msg, msgimplp, tnf_uint, block, blocking);
20390Sstevel@tonic-gate
20400Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*msgimplp, *msgbufp))
20410Sstevel@tonic-gate
20420Sstevel@tonic-gate mutex_enter(&msgimplp->im_mutex);
20430Sstevel@tonic-gate
20440Sstevel@tonic-gate madhdrp = msgimplp->im_msgbufs_send.im_bufs_mad_hdr;
20450Sstevel@tonic-gate msgbufp = &msgimplp->im_msgbufs_recv;
20460Sstevel@tonic-gate smsgbufp = &msgimplp->im_msgbufs_send;
20470Sstevel@tonic-gate
20480Sstevel@tonic-gate /*
20490Sstevel@tonic-gate * check if transp_op_flags specify that the transaction is
20500Sstevel@tonic-gate * a single packet, then the size of the message header + data
20510Sstevel@tonic-gate * does not exceed 256 bytes
20520Sstevel@tonic-gate */
20530Sstevel@tonic-gate if ((msgimplp->im_transp_op_flags & IBMF_MSG_TRANS_FLAG_RMPP) == 0) {
20540Sstevel@tonic-gate ibmf_i_mgt_class_to_hdr_sz_off(
20550Sstevel@tonic-gate smsgbufp->im_bufs_mad_hdr->MgmtClass,
20560Sstevel@tonic-gate &cl_hdr_sz, &cl_hdr_off);
20570Sstevel@tonic-gate
20580Sstevel@tonic-gate if ((sizeof (ib_mad_hdr_t) + cl_hdr_off +
20590Sstevel@tonic-gate smsgbufp->im_bufs_cl_hdr_len +
20600Sstevel@tonic-gate smsgbufp->im_bufs_cl_data_len) > IBMF_MAD_SIZE) {
20610Sstevel@tonic-gate mutex_exit(&msgimplp->im_mutex);
20620Sstevel@tonic-gate (void) sprintf(errmsg,
20630Sstevel@tonic-gate "Non-RMPP message size is too large");
20640Sstevel@tonic-gate error = B_TRUE;
20650Sstevel@tonic-gate status = IBMF_BAD_SIZE;
20660Sstevel@tonic-gate goto bail;
20670Sstevel@tonic-gate }
20680Sstevel@tonic-gate }
20690Sstevel@tonic-gate
20700Sstevel@tonic-gate /* more message context initialization */
20710Sstevel@tonic-gate msgimplp->im_qp_hdl = ibmf_qp_handle;
20720Sstevel@tonic-gate msgimplp->im_tid = b2h64(madhdrp->TransactionID);
20730Sstevel@tonic-gate msgimplp->im_mgt_class = madhdrp->MgmtClass;
20740Sstevel@tonic-gate msgimplp->im_unsolicited = B_FALSE;
20750Sstevel@tonic-gate msgimplp->im_trans_state_flags = IBMF_TRANS_STATE_FLAG_UNINIT;
2076268Ssandipb bzero(&msgimplp->im_rmpp_ctx, sizeof (ibmf_rmpp_ctx_t));
20770Sstevel@tonic-gate msgimplp->im_rmpp_ctx.rmpp_state = IBMF_RMPP_STATE_UNDEFINED;
20780Sstevel@tonic-gate msgimplp->im_rmpp_ctx.rmpp_respt = IBMF_RMPP_DEFAULT_RRESPT;
20790Sstevel@tonic-gate msgimplp->im_rmpp_ctx.rmpp_retry_cnt = 0;
2080268Ssandipb msgimplp->im_ref_count = 0;
2081268Ssandipb msgimplp->im_pending_send_compls = 0;
20820Sstevel@tonic-gate IBMF_MSG_INCR_REFCNT(msgimplp);
20830Sstevel@tonic-gate if (msgimplp->im_retrans.retrans_retries == 0)
20840Sstevel@tonic-gate msgimplp->im_retrans.retrans_retries = IBMF_RETRANS_DEF_RETRIES;
20850Sstevel@tonic-gate if (msgimplp->im_retrans.retrans_rtv == 0)
20860Sstevel@tonic-gate msgimplp->im_retrans.retrans_rtv = IBMF_RETRANS_DEF_RTV;
20870Sstevel@tonic-gate if (msgimplp->im_retrans.retrans_rttv == 0)
20880Sstevel@tonic-gate msgimplp->im_retrans.retrans_rttv = IBMF_RETRANS_DEF_RTTV;
20890Sstevel@tonic-gate
20900Sstevel@tonic-gate IBMF_TRACE_5(IBMF_TNF_DEBUG, DPRINT_L3, ibmf_i_msg_transport,
20910Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_msg_transport(): %s, msgp = 0x%p, "
20920Sstevel@tonic-gate "class = 0x%x, method = 0x%x, attributeID = 0x%x\n",
20930Sstevel@tonic-gate tnf_string, msg, "Added message", tnf_opaque, msgimplp,
20940Sstevel@tonic-gate msgimplp, tnf_opaque, class, msgimplp->im_mgt_class, tnf_opaque,
20950Sstevel@tonic-gate method, madhdrp->R_Method, tnf_opaque, attrib_id,
20960Sstevel@tonic-gate b2h16(madhdrp->AttributeID));
20970Sstevel@tonic-gate
20980Sstevel@tonic-gate IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L3, ibmf_i_msg_transport,
20990Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_msg_transport(): msgp = 0x%p, "
21000Sstevel@tonic-gate "TID = 0x%p, transp_op_flags = 0x%x\n",
21010Sstevel@tonic-gate tnf_opaque, msgimplp, msgimplp, tnf_opaque, tid, msgimplp->im_tid,
21020Sstevel@tonic-gate tnf_uint, transp_op_flags, msgimplp->im_transp_op_flags);
21030Sstevel@tonic-gate
21040Sstevel@tonic-gate /*
21050Sstevel@tonic-gate * Do not allow reuse of a message where the receive buffers are
21060Sstevel@tonic-gate * being used as send buffers if this is a sequenced transaction
21070Sstevel@tonic-gate */
21080Sstevel@tonic-gate if ((madhdrp == msgbufp->im_bufs_mad_hdr) &&
21090Sstevel@tonic-gate (msgimplp->im_transp_op_flags & IBMF_MSG_TRANS_FLAG_SEQ)) {
21100Sstevel@tonic-gate IBMF_MSG_DECR_REFCNT(msgimplp);
21110Sstevel@tonic-gate mutex_exit(&msgimplp->im_mutex);
21120Sstevel@tonic-gate (void) sprintf(errmsg,
21130Sstevel@tonic-gate "Send and Recv buffers are the same for sequenced"
21140Sstevel@tonic-gate " transaction");
21150Sstevel@tonic-gate error = B_TRUE;
21160Sstevel@tonic-gate status = IBMF_REQ_INVALID;
21170Sstevel@tonic-gate goto bail;
21180Sstevel@tonic-gate }
21190Sstevel@tonic-gate
21200Sstevel@tonic-gate /* set transaction flags */
21210Sstevel@tonic-gate if (msgimplp->im_transp_op_flags & IBMF_MSG_TRANS_FLAG_SEQ)
21220Sstevel@tonic-gate msgimplp->im_flags |= IBMF_MSG_FLAGS_SEQUENCED;
21230Sstevel@tonic-gate
21240Sstevel@tonic-gate if (msgimplp->im_transp_op_flags & IBMF_MSG_TRANS_FLAG_RMPP)
21250Sstevel@tonic-gate msgimplp->im_flags |= IBMF_MSG_FLAGS_SEND_RMPP;
21260Sstevel@tonic-gate else
21270Sstevel@tonic-gate msgimplp->im_flags |= IBMF_MSG_FLAGS_NOT_RMPP;
21280Sstevel@tonic-gate
21290Sstevel@tonic-gate /* free recv buffers if this is a reused message */
21300Sstevel@tonic-gate if ((msgbufp->im_bufs_mad_hdr != NULL) &&
21310Sstevel@tonic-gate (msgimplp->im_transp_op_flags & IBMF_MSG_TRANS_FLAG_SEQ)) {
21320Sstevel@tonic-gate
21330Sstevel@tonic-gate IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L3, ibmf_i_msg_transport,
21340Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_msg_transport(): %s, "
21350Sstevel@tonic-gate "msgp = 0x%p, mad_hdrp = 0x%p\n", tnf_string, msg,
21360Sstevel@tonic-gate "Freeing recv buffer for reused message",
21370Sstevel@tonic-gate tnf_opaque, msgimplp, msgimplp,
21380Sstevel@tonic-gate tnf_opaque, mad_hdr, msgbufp->im_bufs_mad_hdr);
21390Sstevel@tonic-gate
21400Sstevel@tonic-gate ibmf_i_mgt_class_to_hdr_sz_off(
21410Sstevel@tonic-gate msgbufp->im_bufs_mad_hdr->MgmtClass,
21420Sstevel@tonic-gate &cl_hdr_sz, &cl_hdr_off);
21430Sstevel@tonic-gate
21440Sstevel@tonic-gate kmem_free(msgbufp->im_bufs_mad_hdr, sizeof (ib_mad_hdr_t) +
21450Sstevel@tonic-gate cl_hdr_off + msgbufp->im_bufs_cl_hdr_len +
21460Sstevel@tonic-gate msgbufp->im_bufs_cl_data_len);
21470Sstevel@tonic-gate
21480Sstevel@tonic-gate msgbufp->im_bufs_mad_hdr = NULL;
21490Sstevel@tonic-gate msgbufp->im_bufs_cl_hdr = NULL;
21500Sstevel@tonic-gate msgbufp->im_bufs_cl_hdr_len = 0;
21510Sstevel@tonic-gate msgbufp->im_bufs_cl_data = NULL;
21520Sstevel@tonic-gate msgbufp->im_bufs_cl_data_len = 0;
21530Sstevel@tonic-gate }
21540Sstevel@tonic-gate
21550Sstevel@tonic-gate mutex_exit(&msgimplp->im_mutex);
21560Sstevel@tonic-gate
21570Sstevel@tonic-gate /* initialize (and possibly allocate) the address handle */
21580Sstevel@tonic-gate status = ibmf_i_alloc_ud_dest(clientp, msgimplp,
21590Sstevel@tonic-gate &msgimplp->im_ud_dest, blocking);
21600Sstevel@tonic-gate if (status != IBMF_SUCCESS) {
21610Sstevel@tonic-gate (void) sprintf(errmsg, "ibmf_i_alloc_ud_dest() failed");
21620Sstevel@tonic-gate error = B_TRUE;
21630Sstevel@tonic-gate goto bail;
21640Sstevel@tonic-gate }
21650Sstevel@tonic-gate
21660Sstevel@tonic-gate _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*msgimplp, *msgbufp))
21670Sstevel@tonic-gate
21680Sstevel@tonic-gate /* add the message to the client context's message list */
21690Sstevel@tonic-gate ibmf_i_client_add_msg(clientp, msgimplp);
21700Sstevel@tonic-gate
21710Sstevel@tonic-gate mutex_enter(&msgimplp->im_mutex);
21720Sstevel@tonic-gate
21730Sstevel@tonic-gate /* no one should have touched our state */
21740Sstevel@tonic-gate ASSERT(msgimplp->im_trans_state_flags == IBMF_TRANS_STATE_FLAG_UNINIT);
21750Sstevel@tonic-gate
21760Sstevel@tonic-gate /* transition out of uninit state */
21770Sstevel@tonic-gate msgimplp->im_trans_state_flags = IBMF_TRANS_STATE_FLAG_INIT;
21780Sstevel@tonic-gate
21790Sstevel@tonic-gate IBMF_TRACE_5(IBMF_TNF_DEBUG, DPRINT_L3, ibmf_i_msg_transport,
21800Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_msg_transport(): msgp = 0x%p, "
21810Sstevel@tonic-gate "local_lid = 0x%x, remote_lid = 0x%x, remote_qpn = 0x%x, "
21820Sstevel@tonic-gate "block = %d\n", tnf_opaque, msgp, msgimplp,
21830Sstevel@tonic-gate tnf_uint, local_lid, msgimplp->im_local_addr.ia_local_lid,
21840Sstevel@tonic-gate tnf_uint, remote_lid, msgimplp->im_local_addr.ia_remote_lid,
21850Sstevel@tonic-gate tnf_uint, remote_qpn, msgimplp->im_local_addr.ia_remote_qno,
21860Sstevel@tonic-gate tnf_uint, blocking, blocking);
21870Sstevel@tonic-gate
21880Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3, ibmf_i_msg_transport,
21890Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_msg_transport(): "
21900Sstevel@tonic-gate "unsetting timer %p %d\n", tnf_opaque, msgimplp, msgimplp,
21910Sstevel@tonic-gate tnf_opaque, timeout_id, msgimplp->im_rp_timeout_id);
21920Sstevel@tonic-gate
21930Sstevel@tonic-gate ASSERT(msgimplp->im_rp_timeout_id == 0);
21940Sstevel@tonic-gate ASSERT(msgimplp->im_tr_timeout_id == 0);
21950Sstevel@tonic-gate
21960Sstevel@tonic-gate if ((msgimplp->im_transp_op_flags & IBMF_MSG_TRANS_FLAG_RMPP) == 0) {
21970Sstevel@tonic-gate
21980Sstevel@tonic-gate /* Non-RMPP transaction */
21990Sstevel@tonic-gate
22000Sstevel@tonic-gate status = ibmf_i_send_single_pkt(clientp, ibmf_qp_handle,
22010Sstevel@tonic-gate msgimplp, blocking);
22020Sstevel@tonic-gate if (status != IBMF_SUCCESS) {
22030Sstevel@tonic-gate IBMF_MSG_DECR_REFCNT(msgimplp);
22040Sstevel@tonic-gate mutex_exit(&msgimplp->im_mutex);
22050Sstevel@tonic-gate ibmf_i_client_rem_msg(clientp, msgimplp, &refcnt);
22060Sstevel@tonic-gate (void) sprintf(errmsg, "Single packet send failed");
22070Sstevel@tonic-gate error = B_TRUE;
22080Sstevel@tonic-gate goto bail;
22090Sstevel@tonic-gate }
22100Sstevel@tonic-gate
22110Sstevel@tonic-gate } else if (msgimplp->im_transp_op_flags & IBMF_MSG_TRANS_FLAG_RMPP) {
22120Sstevel@tonic-gate
22130Sstevel@tonic-gate /* RMPP transaction */
22140Sstevel@tonic-gate
22150Sstevel@tonic-gate /* check if client supports RMPP traffic */
22160Sstevel@tonic-gate if ((clientp->ic_reg_flags & IBMF_REG_FLAG_RMPP) == 0) {
22170Sstevel@tonic-gate IBMF_MSG_DECR_REFCNT(msgimplp);
22180Sstevel@tonic-gate mutex_exit(&msgimplp->im_mutex);
22190Sstevel@tonic-gate ibmf_i_client_rem_msg(clientp, msgimplp, &refcnt);
22200Sstevel@tonic-gate (void) sprintf(errmsg, "Class does not support RMPP");
22210Sstevel@tonic-gate error = B_TRUE;
22220Sstevel@tonic-gate status = IBMF_BAD_RMPP_OPT;
22230Sstevel@tonic-gate goto bail;
22240Sstevel@tonic-gate }
22250Sstevel@tonic-gate
22260Sstevel@tonic-gate /* for non-special QPs, check if QP supports RMPP traffic */
22270Sstevel@tonic-gate if (ibmf_qp_handle != IBMF_QP_HANDLE_DEFAULT &&
22280Sstevel@tonic-gate (((ibmf_alt_qp_t *)ibmf_qp_handle)->isq_supports_rmpp ==
22290Sstevel@tonic-gate B_FALSE)) {
22300Sstevel@tonic-gate IBMF_MSG_DECR_REFCNT(msgimplp);
22310Sstevel@tonic-gate mutex_exit(&msgimplp->im_mutex);
22320Sstevel@tonic-gate ibmf_i_client_rem_msg(clientp, msgimplp, &refcnt);
22330Sstevel@tonic-gate (void) sprintf(errmsg, "QP does not support RMPP");
22340Sstevel@tonic-gate error = B_TRUE;
22350Sstevel@tonic-gate status = IBMF_BAD_RMPP_OPT;
22360Sstevel@tonic-gate goto bail;
22370Sstevel@tonic-gate }
22380Sstevel@tonic-gate
22390Sstevel@tonic-gate /* check if transaction is "double sided" (send and receive) */
22400Sstevel@tonic-gate if (msgimplp->im_transp_op_flags & IBMF_MSG_TRANS_FLAG_SEQ)
22410Sstevel@tonic-gate isDS = 1;
22420Sstevel@tonic-gate
22430Sstevel@tonic-gate status = ibmf_i_send_rmpp_pkts(clientp, ibmf_qp_handle,
22440Sstevel@tonic-gate msgimplp, isDS, blocking);
22450Sstevel@tonic-gate if (status != IBMF_SUCCESS) {
22460Sstevel@tonic-gate IBMF_MSG_DECR_REFCNT(msgimplp);
22470Sstevel@tonic-gate mutex_exit(&msgimplp->im_mutex);
22480Sstevel@tonic-gate ibmf_i_client_rem_msg(clientp, msgimplp, &refcnt);
22490Sstevel@tonic-gate (void) sprintf(errmsg, "RMPP packets send failed");
22500Sstevel@tonic-gate error = B_TRUE;
22510Sstevel@tonic-gate goto bail;
22520Sstevel@tonic-gate }
22530Sstevel@tonic-gate }
22540Sstevel@tonic-gate
22550Sstevel@tonic-gate /*
22560Sstevel@tonic-gate * decrement the reference count so notify_client() can remove the
22570Sstevel@tonic-gate * message when it's ready
22580Sstevel@tonic-gate */
22590Sstevel@tonic-gate IBMF_MSG_DECR_REFCNT(msgimplp);
22600Sstevel@tonic-gate
22610Sstevel@tonic-gate /* check if the transaction is a blocking transaction */
22620Sstevel@tonic-gate if (blocking && ((msgimplp->im_trans_state_flags &
22630Sstevel@tonic-gate IBMF_TRANS_STATE_FLAG_SIGNALED) == 0)) {
22640Sstevel@tonic-gate
22650Sstevel@tonic-gate /* indicate that the tranaction is waiting */
22660Sstevel@tonic-gate msgimplp->im_trans_state_flags |= IBMF_TRANS_STATE_FLAG_WAIT;
22670Sstevel@tonic-gate
22680Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3, ibmf_i_msg_transport,
22690Sstevel@tonic-gate IBMF_TNF_TRACE, "",
22700Sstevel@tonic-gate "ibmf_i_msg_transport(): %s, msgp = 0x%p\n",
22710Sstevel@tonic-gate tnf_string, msg, "blocking for completion",
22720Sstevel@tonic-gate tnf_opaque, msgimplp, msgimplp);
22730Sstevel@tonic-gate
22740Sstevel@tonic-gate /* wait for transaction completion */
22750Sstevel@tonic-gate cv_wait(&msgimplp->im_trans_cv, &msgimplp->im_mutex);
22760Sstevel@tonic-gate
22770Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3, ibmf_i_msg_transport,
22780Sstevel@tonic-gate IBMF_TNF_TRACE, "",
22790Sstevel@tonic-gate "ibmf_i_msg_transport(): %s, msgp = 0x%p\n",
22800Sstevel@tonic-gate tnf_string, msg, "unblocking for completion",
22810Sstevel@tonic-gate tnf_opaque, msgimplp, msgimplp);
22820Sstevel@tonic-gate
22830Sstevel@tonic-gate /* clean up flags */
22840Sstevel@tonic-gate msgimplp->im_trans_state_flags &= ~IBMF_TRANS_STATE_FLAG_WAIT;
22850Sstevel@tonic-gate msgimplp->im_flags &= ~IBMF_MSG_FLAGS_BUSY;
22860Sstevel@tonic-gate
22870Sstevel@tonic-gate if (msgimplp->im_msg_status != IBMF_SUCCESS) {
22880Sstevel@tonic-gate
22890Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
22900Sstevel@tonic-gate ibmf_i_msg_transport_err, IBMF_TNF_ERROR, "",
22910Sstevel@tonic-gate "ibmf_i_msg_transport(): msg_status = %d\n",
22920Sstevel@tonic-gate tnf_uint, msgstatus, msgimplp->im_msg_status);
22930Sstevel@tonic-gate
22940Sstevel@tonic-gate status = msgimplp->im_msg_status;
22950Sstevel@tonic-gate }
22960Sstevel@tonic-gate } else if (blocking && (msgimplp->im_trans_state_flags &
22970Sstevel@tonic-gate IBMF_TRANS_STATE_FLAG_SIGNALED)) {
22980Sstevel@tonic-gate msgimplp->im_flags &= ~IBMF_MSG_FLAGS_BUSY;
22990Sstevel@tonic-gate
23000Sstevel@tonic-gate if (msgimplp->im_msg_status != IBMF_SUCCESS) {
23010Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
23020Sstevel@tonic-gate ibmf_i_msg_transport_err, IBMF_TNF_ERROR, "",
23030Sstevel@tonic-gate "ibmf_i_msg_transport(): msg_status = %d\n",
23040Sstevel@tonic-gate tnf_uint, msgstatus, msgimplp->im_msg_status);
23050Sstevel@tonic-gate status = msgimplp->im_msg_status;
23060Sstevel@tonic-gate }
23070Sstevel@tonic-gate }
23080Sstevel@tonic-gate
23090Sstevel@tonic-gate msg_rp_unset_id = msg_tr_unset_id = 0;
23100Sstevel@tonic-gate msg_rp_unset_id = msgimplp->im_rp_unset_timeout_id;
23110Sstevel@tonic-gate msg_tr_unset_id = msgimplp->im_tr_unset_timeout_id;
23120Sstevel@tonic-gate msgimplp->im_rp_unset_timeout_id = 0;
23130Sstevel@tonic-gate msgimplp->im_tr_unset_timeout_id = 0;
23140Sstevel@tonic-gate
23150Sstevel@tonic-gate mutex_exit(&msgimplp->im_mutex);
23160Sstevel@tonic-gate
23170Sstevel@tonic-gate /* Unset the timers */
23180Sstevel@tonic-gate if (msg_rp_unset_id != 0) {
23190Sstevel@tonic-gate (void) untimeout(msg_rp_unset_id);
23200Sstevel@tonic-gate }
23210Sstevel@tonic-gate
23220Sstevel@tonic-gate if (msg_tr_unset_id != 0) {
23230Sstevel@tonic-gate (void) untimeout(msg_tr_unset_id);
23240Sstevel@tonic-gate }
23250Sstevel@tonic-gate
23260Sstevel@tonic-gate /* increment kstats of the number of sent messages */
23270Sstevel@tonic-gate mutex_enter(&clientp->ic_kstat_mutex);
23280Sstevel@tonic-gate IBMF_ADD32_KSTATS(clientp, msgs_sent, 1);
23290Sstevel@tonic-gate mutex_exit(&clientp->ic_kstat_mutex);
23300Sstevel@tonic-gate
23310Sstevel@tonic-gate bail:
23320Sstevel@tonic-gate if (error) {
23330Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
23340Sstevel@tonic-gate ibmf_i_msg_transport_err, IBMF_TNF_ERROR, "",
23350Sstevel@tonic-gate "ibmf_i_msg_transport(): %s, msgp = 0x%p\n",
23360Sstevel@tonic-gate tnf_string, msg, errmsg, tnf_opaque, msgimplp, msgimplp);
23370Sstevel@tonic-gate }
23380Sstevel@tonic-gate
23390Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_msg_transport_end,
23400Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_msg_transport() exit, status = %d\n",
23410Sstevel@tonic-gate tnf_uint, status, status);
23420Sstevel@tonic-gate
23430Sstevel@tonic-gate return (status);
23440Sstevel@tonic-gate }
23450Sstevel@tonic-gate
23460Sstevel@tonic-gate /*
23470Sstevel@tonic-gate * ibmf_i_init_msg():
23480Sstevel@tonic-gate * Initialize the message fields
23490Sstevel@tonic-gate */
23500Sstevel@tonic-gate void
ibmf_i_init_msg(ibmf_msg_impl_t * msgimplp,ibmf_msg_cb_t trans_cb,void * trans_cb_arg,ibmf_retrans_t * retrans,boolean_t block)23510Sstevel@tonic-gate ibmf_i_init_msg(ibmf_msg_impl_t *msgimplp, ibmf_msg_cb_t trans_cb,
23520Sstevel@tonic-gate void *trans_cb_arg, ibmf_retrans_t *retrans, boolean_t block)
23530Sstevel@tonic-gate {
23540Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_msg_start,
23550Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_init_msg() enter\n");
23560Sstevel@tonic-gate
23570Sstevel@tonic-gate _NOTE(ASSUMING_PROTECTED(msgimplp->im_trans_cb,
23580Sstevel@tonic-gate msgimplp->im_trans_cb_arg))
23590Sstevel@tonic-gate
23600Sstevel@tonic-gate if (block == B_TRUE)
23610Sstevel@tonic-gate msgimplp->im_msg_flags |= IBMF_MSG_FLAGS_BLOCKING;
23620Sstevel@tonic-gate msgimplp->im_trans_cb = trans_cb;
23630Sstevel@tonic-gate msgimplp->im_trans_cb_arg = trans_cb_arg;
23640Sstevel@tonic-gate
2365268Ssandipb bzero(&msgimplp->im_retrans, sizeof (ibmf_retrans_t));
23660Sstevel@tonic-gate if (retrans != NULL) {
23670Sstevel@tonic-gate bcopy((void *)retrans, (void *)&msgimplp->im_retrans,
23680Sstevel@tonic-gate sizeof (ibmf_retrans_t));
23690Sstevel@tonic-gate }
23700Sstevel@tonic-gate
23710Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_msg_end,
23720Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_init_msg() exit\n");
23730Sstevel@tonic-gate }
23740Sstevel@tonic-gate
23750Sstevel@tonic-gate /*
23760Sstevel@tonic-gate * ibmf_i_alloc_qp():
23770Sstevel@tonic-gate * Allocate a QP context for the alternate QPs
23780Sstevel@tonic-gate */
23790Sstevel@tonic-gate int
ibmf_i_alloc_qp(ibmf_client_t * clientp,ib_pkey_t p_key,ib_qkey_t q_key,uint_t flags,ibmf_qp_handle_t * ibmf_qp_handlep)23800Sstevel@tonic-gate ibmf_i_alloc_qp(ibmf_client_t *clientp, ib_pkey_t p_key, ib_qkey_t q_key,
23810Sstevel@tonic-gate uint_t flags, ibmf_qp_handle_t *ibmf_qp_handlep)
23820Sstevel@tonic-gate {
23830Sstevel@tonic-gate ibmf_ci_t *ibmf_cip = clientp->ic_myci;
23840Sstevel@tonic-gate ibt_qp_alloc_attr_t qp_attrs;
23850Sstevel@tonic-gate ibt_qp_info_t qp_modify_attr;
23860Sstevel@tonic-gate ibmf_alt_qp_t *qp_ctx;
23870Sstevel@tonic-gate uint16_t pkey_ix;
23880Sstevel@tonic-gate ibt_status_t ibt_status;
23890Sstevel@tonic-gate int i, blocking;
23900Sstevel@tonic-gate boolean_t error = B_FALSE;
23910Sstevel@tonic-gate int status = IBMF_SUCCESS;
23920Sstevel@tonic-gate char errmsg[128];
23930Sstevel@tonic-gate
23940Sstevel@tonic-gate
23950Sstevel@tonic-gate IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L4,
23960Sstevel@tonic-gate ibmf_i_alloc_qp_start, IBMF_TNF_TRACE, "",
23970Sstevel@tonic-gate "ibmf_i_alloc_qp() enter, clientp = %p, pkey = %x, qkey = %x \n",
23980Sstevel@tonic-gate tnf_opaque, clientp, clientp, tnf_uint, p_key, p_key,
23990Sstevel@tonic-gate tnf_uint, q_key, q_key);
24000Sstevel@tonic-gate
24010Sstevel@tonic-gate /*
24020Sstevel@tonic-gate * get the pkey index associated with this pkey if present in table
24030Sstevel@tonic-gate */
24040Sstevel@tonic-gate if (ibmf_i_get_pkeyix(clientp->ic_ci_handle, p_key,
24050Sstevel@tonic-gate clientp->ic_client_info.port_num, &pkey_ix) != IBMF_SUCCESS) {
24060Sstevel@tonic-gate (void) sprintf(errmsg, "pkey not in table, pkey = %x", p_key);
24070Sstevel@tonic-gate error = B_TRUE;
24080Sstevel@tonic-gate status = IBMF_FAILURE;
24090Sstevel@tonic-gate goto bail;
24100Sstevel@tonic-gate }
24110Sstevel@tonic-gate
24120Sstevel@tonic-gate /* allocate QP context memory */
24130Sstevel@tonic-gate qp_ctx = (ibmf_alt_qp_t *)kmem_zalloc(sizeof (ibmf_alt_qp_t),
24140Sstevel@tonic-gate (flags & IBMF_ALLOC_SLEEP) ? KM_SLEEP : KM_NOSLEEP);
24150Sstevel@tonic-gate if (qp_ctx == NULL) {
24160Sstevel@tonic-gate (void) sprintf(errmsg, "failed to kmem_zalloc qp ctx");
24170Sstevel@tonic-gate error = B_TRUE;
24180Sstevel@tonic-gate status = IBMF_NO_RESOURCES;
24190Sstevel@tonic-gate goto bail;
24200Sstevel@tonic-gate }
24210Sstevel@tonic-gate
24220Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*qp_ctx));
24230Sstevel@tonic-gate
24240Sstevel@tonic-gate /* setup the qp attrs for the alloc call */
24250Sstevel@tonic-gate qp_attrs.qp_scq_hdl = ibmf_cip->ci_alt_cq_handle;
24260Sstevel@tonic-gate qp_attrs.qp_rcq_hdl = ibmf_cip->ci_alt_cq_handle;
24270Sstevel@tonic-gate qp_attrs.qp_pd_hdl = ibmf_cip->ci_pd;
24280Sstevel@tonic-gate qp_attrs.qp_sizes.cs_sq_sgl = IBMF_MAX_SQ_WR_SGL_ELEMENTS;
24290Sstevel@tonic-gate qp_attrs.qp_sizes.cs_rq_sgl = IBMF_MAX_RQ_WR_SGL_ELEMENTS;
24300Sstevel@tonic-gate qp_attrs.qp_sizes.cs_sq = ibmf_send_wqes_posted_per_qp;
24310Sstevel@tonic-gate qp_attrs.qp_sizes.cs_rq = ibmf_recv_wqes_posted_per_qp;
24320Sstevel@tonic-gate qp_attrs.qp_flags = IBT_ALL_SIGNALED;
24330Sstevel@tonic-gate qp_attrs.qp_alloc_flags = IBT_QP_NO_FLAGS;
24340Sstevel@tonic-gate
24350Sstevel@tonic-gate /* request IBT for a qp with the desired attributes */
24360Sstevel@tonic-gate ibt_status = ibt_alloc_qp(clientp->ic_ci_handle, IBT_UD_RQP,
24370Sstevel@tonic-gate &qp_attrs, &qp_ctx->isq_qp_sizes, &qp_ctx->isq_qpn,
24380Sstevel@tonic-gate &qp_ctx->isq_qp_handle);
24390Sstevel@tonic-gate if (ibt_status != IBT_SUCCESS) {
24400Sstevel@tonic-gate kmem_free(qp_ctx, sizeof (ibmf_alt_qp_t));
24410Sstevel@tonic-gate (void) sprintf(errmsg, "failed to alloc qp, status = %d",
24420Sstevel@tonic-gate ibt_status);
24430Sstevel@tonic-gate error = B_TRUE;
24440Sstevel@tonic-gate status = IBMF_NO_RESOURCES;
24450Sstevel@tonic-gate goto bail;
24460Sstevel@tonic-gate }
24470Sstevel@tonic-gate
24480Sstevel@tonic-gate qp_modify_attr.qp_trans = IBT_UD_SRV;
24490Sstevel@tonic-gate qp_modify_attr.qp_flags = IBT_CEP_NO_FLAGS;
24500Sstevel@tonic-gate qp_modify_attr.qp_transport.ud.ud_qkey = q_key;
24510Sstevel@tonic-gate qp_modify_attr.qp_transport.ud.ud_sq_psn = 0;
24520Sstevel@tonic-gate qp_modify_attr.qp_transport.ud.ud_pkey_ix = pkey_ix;
24530Sstevel@tonic-gate qp_modify_attr.qp_transport.ud.ud_port =
24540Sstevel@tonic-gate clientp->ic_client_info.port_num;
24550Sstevel@tonic-gate
24560Sstevel@tonic-gate /* Set up the client handle in the QP context */
24570Sstevel@tonic-gate qp_ctx->isq_client_hdl = clientp;
24580Sstevel@tonic-gate
24590Sstevel@tonic-gate /* call the IB transport to initialize the QP */
24600Sstevel@tonic-gate ibt_status = ibt_initialize_qp(qp_ctx->isq_qp_handle, &qp_modify_attr);
24610Sstevel@tonic-gate if (ibt_status != IBT_SUCCESS) {
24620Sstevel@tonic-gate (void) ibt_free_qp(qp_ctx->isq_qp_handle);
24630Sstevel@tonic-gate kmem_free(qp_ctx, sizeof (ibmf_alt_qp_t));
24640Sstevel@tonic-gate (void) sprintf(errmsg, "failed to initialize qp, status = %d",
24650Sstevel@tonic-gate ibt_status);
24660Sstevel@tonic-gate error = B_TRUE;
24670Sstevel@tonic-gate status = IBMF_NO_RESOURCES;
24680Sstevel@tonic-gate goto bail;
24690Sstevel@tonic-gate }
24700Sstevel@tonic-gate
24710Sstevel@tonic-gate /* Set up the WQE caches */
24720Sstevel@tonic-gate status = ibmf_i_init_altqp_wqes(qp_ctx);
24730Sstevel@tonic-gate if (status != IBMF_SUCCESS) {
24740Sstevel@tonic-gate (void) ibt_free_qp(qp_ctx->isq_qp_handle);
24750Sstevel@tonic-gate kmem_free(qp_ctx, sizeof (ibmf_alt_qp_t));
24760Sstevel@tonic-gate (void) sprintf(errmsg, "failed to init wqe caches, status = %d",
24770Sstevel@tonic-gate status);
24780Sstevel@tonic-gate error = B_TRUE;
24790Sstevel@tonic-gate goto bail;
24800Sstevel@tonic-gate }
24810Sstevel@tonic-gate
24820Sstevel@tonic-gate qp_ctx->isq_next = NULL;
24830Sstevel@tonic-gate qp_ctx->isq_pkey = p_key;
24840Sstevel@tonic-gate qp_ctx->isq_qkey = q_key;
24850Sstevel@tonic-gate qp_ctx->isq_port_num = clientp->ic_client_info.port_num;
24860Sstevel@tonic-gate mutex_init(&qp_ctx->isq_mutex, NULL, MUTEX_DRIVER, NULL);
24870Sstevel@tonic-gate mutex_init(&qp_ctx->isq_wqe_mutex, NULL, MUTEX_DRIVER, NULL);
24880Sstevel@tonic-gate cv_init(&qp_ctx->isq_recv_cb_teardown_cv, NULL, CV_DRIVER, NULL);
24890Sstevel@tonic-gate cv_init(&qp_ctx->isq_sqd_cv, NULL, CV_DRIVER, NULL);
24900Sstevel@tonic-gate cv_init(&qp_ctx->isq_wqes_cv, NULL, CV_DRIVER, NULL);
24910Sstevel@tonic-gate
24920Sstevel@tonic-gate _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*qp_ctx));
24930Sstevel@tonic-gate
24940Sstevel@tonic-gate /* add alt qp to the list in CI context */
24950Sstevel@tonic-gate mutex_enter(&ibmf_cip->ci_mutex);
24960Sstevel@tonic-gate if (ibmf_cip->ci_alt_qp_list == NULL) {
24970Sstevel@tonic-gate ibmf_cip->ci_alt_qp_list = qp_ctx;
24980Sstevel@tonic-gate } else {
24990Sstevel@tonic-gate ibmf_alt_qp_t *qpp;
25000Sstevel@tonic-gate
25010Sstevel@tonic-gate qpp = ibmf_cip->ci_alt_qp_list;
25020Sstevel@tonic-gate while (qpp->isq_next != NULL) {
25030Sstevel@tonic-gate qpp = qpp->isq_next;
25040Sstevel@tonic-gate }
25050Sstevel@tonic-gate qpp->isq_next = qp_ctx;
25060Sstevel@tonic-gate }
25070Sstevel@tonic-gate mutex_exit(&ibmf_cip->ci_mutex);
25080Sstevel@tonic-gate
25090Sstevel@tonic-gate *ibmf_qp_handlep = (ibmf_qp_handle_t)qp_ctx;
25100Sstevel@tonic-gate
25110Sstevel@tonic-gate if (flags & IBMF_ALLOC_SLEEP)
25120Sstevel@tonic-gate blocking = 1;
25130Sstevel@tonic-gate else
25140Sstevel@tonic-gate blocking = 0;
25150Sstevel@tonic-gate
25160Sstevel@tonic-gate /* post the max number of buffers to RQ */
25170Sstevel@tonic-gate for (i = 0; i < ibmf_recv_wqes_per_port; i++) {
25180Sstevel@tonic-gate status = ibmf_i_post_recv_buffer(ibmf_cip, clientp->ic_qp,
25190Sstevel@tonic-gate blocking, *ibmf_qp_handlep);
25200Sstevel@tonic-gate if (status != IBMF_SUCCESS) {
25210Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3,
25220Sstevel@tonic-gate ibmf_i_alloc_qp, IBMF_TNF_TRACE, "",
25230Sstevel@tonic-gate "ibmf_i_alloc_qp(): %s, status = %d\n",
25240Sstevel@tonic-gate tnf_string, msg, "ibmf_i_post_recv_buffer() failed",
25250Sstevel@tonic-gate tnf_int, status, status);
25260Sstevel@tonic-gate }
25270Sstevel@tonic-gate }
25280Sstevel@tonic-gate
25290Sstevel@tonic-gate mutex_enter(&clientp->ic_kstat_mutex);
25300Sstevel@tonic-gate IBMF_ADD32_KSTATS(clientp, alt_qps_alloced, 1);
25310Sstevel@tonic-gate mutex_exit(&clientp->ic_kstat_mutex);
25320Sstevel@tonic-gate
25330Sstevel@tonic-gate bail:
25340Sstevel@tonic-gate if (error) {
25350Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
25360Sstevel@tonic-gate ibmf_i_alloc_qp_err, IBMF_TNF_TRACE, "",
25370Sstevel@tonic-gate "ibmf_i_alloc_qp(): %s\n", tnf_string, msg, errmsg);
25380Sstevel@tonic-gate }
25390Sstevel@tonic-gate
25400Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_alloc_qp_end,
25410Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_alloc_qp() exit, qp = %p\n",
25420Sstevel@tonic-gate tnf_opaque, qp_handlep, *ibmf_qp_handlep);
25430Sstevel@tonic-gate return (status);
25440Sstevel@tonic-gate }
25450Sstevel@tonic-gate
25460Sstevel@tonic-gate /*
25470Sstevel@tonic-gate * ibmf_i_free_qp():
25480Sstevel@tonic-gate * Free an alternate QP context
25490Sstevel@tonic-gate */
25500Sstevel@tonic-gate /* ARGSUSED */
25510Sstevel@tonic-gate int
ibmf_i_free_qp(ibmf_qp_handle_t ibmf_qp_handle,uint_t flags)25520Sstevel@tonic-gate ibmf_i_free_qp(ibmf_qp_handle_t ibmf_qp_handle, uint_t flags)
25530Sstevel@tonic-gate {
25540Sstevel@tonic-gate ibmf_alt_qp_t *qp_ctx = (ibmf_alt_qp_t *)ibmf_qp_handle;
25550Sstevel@tonic-gate ibmf_client_t *clientp = qp_ctx->isq_client_hdl;
25560Sstevel@tonic-gate ibmf_ci_t *ibmf_cip = qp_ctx->isq_client_hdl->ic_myci;
25570Sstevel@tonic-gate ibmf_alt_qp_t *qpp, *pqpp;
25580Sstevel@tonic-gate ibt_status_t ibt_status;
25590Sstevel@tonic-gate
25600Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4,
25610Sstevel@tonic-gate ibmf_i_free_qp_start, IBMF_TNF_TRACE, "",
25620Sstevel@tonic-gate "ibmf_i_free_qp() enter, qp_hdl = %p, flags = %x\n",
25630Sstevel@tonic-gate tnf_opaque, qp_hdl, ibmf_qp_handle, tnf_uint, flags, flags);
25640Sstevel@tonic-gate
25650Sstevel@tonic-gate /* remove qp from the list in CI context */
25660Sstevel@tonic-gate
25670Sstevel@tonic-gate mutex_enter(&ibmf_cip->ci_mutex);
25680Sstevel@tonic-gate qpp = ibmf_cip->ci_alt_qp_list;
25690Sstevel@tonic-gate ASSERT(qpp != NULL);
25700Sstevel@tonic-gate if (qpp == qp_ctx) {
25710Sstevel@tonic-gate ibmf_cip->ci_alt_qp_list = qpp->isq_next;
25720Sstevel@tonic-gate } else {
25730Sstevel@tonic-gate while (qpp != NULL) {
25740Sstevel@tonic-gate if (qpp == qp_ctx)
25750Sstevel@tonic-gate break;
25760Sstevel@tonic-gate pqpp = qpp;
25770Sstevel@tonic-gate qpp = qpp->isq_next;
25780Sstevel@tonic-gate }
25790Sstevel@tonic-gate ASSERT(qpp != NULL);
25800Sstevel@tonic-gate pqpp->isq_next = qpp->isq_next;
25810Sstevel@tonic-gate }
25820Sstevel@tonic-gate
25830Sstevel@tonic-gate mutex_exit(&ibmf_cip->ci_mutex);
25840Sstevel@tonic-gate
25850Sstevel@tonic-gate /* flush the WQEs in the QP queues */
25860Sstevel@tonic-gate ibt_status = ibt_flush_qp(qp_ctx->isq_qp_handle);
25870Sstevel@tonic-gate if (ibt_status != IBT_SUCCESS) {
25880Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
25890Sstevel@tonic-gate ibmf_i_free_qp_err, IBMF_TNF_TRACE, "",
25900Sstevel@tonic-gate "ibmf_i_free_qp(): %s, status = %d\n",
25910Sstevel@tonic-gate tnf_string, msg, "failed to close qp",
25920Sstevel@tonic-gate tnf_uint, ibt_status, ibt_status);
25930Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_free_qp_end,
25940Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_free_qp() exit\n");
25950Sstevel@tonic-gate return (IBMF_TRANSPORT_FAILURE);
25960Sstevel@tonic-gate }
25970Sstevel@tonic-gate
25980Sstevel@tonic-gate /* Call the MAD completion handler */
25990Sstevel@tonic-gate ibmf_i_mad_completions(ibmf_cip->ci_alt_cq_handle, (void*)ibmf_cip);
26000Sstevel@tonic-gate
26010Sstevel@tonic-gate /* Wait here for all WQE owned by this QP to get freed */
26020Sstevel@tonic-gate mutex_enter(&qpp->isq_mutex);
26030Sstevel@tonic-gate while (qpp->isq_wqes_alloced != 0) {
26040Sstevel@tonic-gate cv_wait(&qpp->isq_wqes_cv, &qpp->isq_mutex);
26050Sstevel@tonic-gate }
26060Sstevel@tonic-gate mutex_exit(&qpp->isq_mutex);
26070Sstevel@tonic-gate
26080Sstevel@tonic-gate cv_destroy(&qp_ctx->isq_recv_cb_teardown_cv);
26090Sstevel@tonic-gate cv_destroy(&qp_ctx->isq_sqd_cv);
26100Sstevel@tonic-gate cv_destroy(&qp_ctx->isq_wqes_cv);
26110Sstevel@tonic-gate
26120Sstevel@tonic-gate /* call the IB transport to free the QP */
26130Sstevel@tonic-gate ibt_status = ibt_free_qp(qp_ctx->isq_qp_handle);
26140Sstevel@tonic-gate if (ibt_status != IBT_SUCCESS) {
26150Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
26160Sstevel@tonic-gate ibmf_i_free_qp_err, IBMF_TNF_TRACE, "",
26170Sstevel@tonic-gate "ibmf_i_free_qp(): %s, status = %d\n",
26180Sstevel@tonic-gate tnf_string, msg, "failed to free qp",
26190Sstevel@tonic-gate tnf_uint, ibt_status, ibt_status);
26200Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_free_qp_end,
26210Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_free_qp() exit\n");
26220Sstevel@tonic-gate return (IBMF_TRANSPORT_FAILURE);
26230Sstevel@tonic-gate }
26240Sstevel@tonic-gate
26250Sstevel@tonic-gate /* Clean up the WQE caches */
26260Sstevel@tonic-gate ibmf_i_fini_altqp_wqes(qp_ctx);
26270Sstevel@tonic-gate mutex_destroy(&qp_ctx->isq_wqe_mutex);
26280Sstevel@tonic-gate mutex_destroy(&qp_ctx->isq_mutex);
26290Sstevel@tonic-gate
26300Sstevel@tonic-gate mutex_enter(&clientp->ic_kstat_mutex);
26310Sstevel@tonic-gate IBMF_SUB32_KSTATS(clientp, alt_qps_alloced, 1);
26320Sstevel@tonic-gate mutex_exit(&clientp->ic_kstat_mutex);
26330Sstevel@tonic-gate
26340Sstevel@tonic-gate kmem_free(qp_ctx, sizeof (ibmf_alt_qp_t));
26350Sstevel@tonic-gate
26360Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_free_qp_end,
26370Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_free_qp() exit\n");
26380Sstevel@tonic-gate
26390Sstevel@tonic-gate return (IBMF_SUCCESS);
26400Sstevel@tonic-gate }
26410Sstevel@tonic-gate
26420Sstevel@tonic-gate /*
26430Sstevel@tonic-gate * ibmf_i_query_qp():
26440Sstevel@tonic-gate * Query an alternate QP context
26450Sstevel@tonic-gate */
26460Sstevel@tonic-gate /* ARGSUSED */
26470Sstevel@tonic-gate int
ibmf_i_query_qp(ibmf_qp_handle_t ibmf_qp_handle,uint_t flags,uint_t * qp_nump,ib_pkey_t * p_keyp,ib_qkey_t * q_keyp,uint8_t * portnump)26480Sstevel@tonic-gate ibmf_i_query_qp(ibmf_qp_handle_t ibmf_qp_handle, uint_t flags,
26490Sstevel@tonic-gate uint_t *qp_nump, ib_pkey_t *p_keyp, ib_qkey_t *q_keyp, uint8_t *portnump)
26500Sstevel@tonic-gate {
26510Sstevel@tonic-gate ibt_qp_query_attr_t qp_query;
26520Sstevel@tonic-gate ibmf_alt_qp_t *qp_ctx = (ibmf_alt_qp_t *)ibmf_qp_handle;
26530Sstevel@tonic-gate uint16_t pkey_ix;
26540Sstevel@tonic-gate ibt_status_t ibt_status;
26550Sstevel@tonic-gate
26560Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4,
26570Sstevel@tonic-gate ibmf_i_free_qp_start, IBMF_TNF_TRACE, "",
26580Sstevel@tonic-gate "ibmf_i_free_qp() enter, qp_hdl = %p, flags = %x\n",
26590Sstevel@tonic-gate tnf_opaque, qp_hdl, ibmf_qp_handle, tnf_uint, flags, flags);
26600Sstevel@tonic-gate
26610Sstevel@tonic-gate ibt_status = ibt_query_qp(qp_ctx->isq_qp_handle, &qp_query);
26620Sstevel@tonic-gate if (ibt_status != IBT_SUCCESS) {
26630Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
26640Sstevel@tonic-gate ibmf_i_query_qp_err, IBMF_TNF_TRACE, "",
26650Sstevel@tonic-gate "ibmf_i_query_qp(): %s, status = %d\n",
26660Sstevel@tonic-gate tnf_string, msg, "failed to query qp",
26670Sstevel@tonic-gate tnf_uint, ibt_status, ibt_status);
26680Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_query_qp_end,
26690Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_query_qp() exit\n");
26700Sstevel@tonic-gate return (IBMF_TRANSPORT_FAILURE);
26710Sstevel@tonic-gate }
26720Sstevel@tonic-gate
26730Sstevel@tonic-gate /* move the desired attributes into the locations provided */
26740Sstevel@tonic-gate *qp_nump = qp_query.qp_qpn;
26750Sstevel@tonic-gate *q_keyp = qp_query.qp_info.qp_transport.ud.ud_qkey;
26760Sstevel@tonic-gate *portnump = qp_query.qp_info.qp_transport.ud.ud_port;
26770Sstevel@tonic-gate
26780Sstevel@tonic-gate pkey_ix = qp_query.qp_info.qp_transport.ud.ud_pkey_ix;
26790Sstevel@tonic-gate
26800Sstevel@tonic-gate /* get the pkey based on the pkey_ix */
26810Sstevel@tonic-gate ibt_status = ibt_index2pkey(qp_ctx->isq_client_hdl->ic_ci_handle,
26820Sstevel@tonic-gate *portnump, pkey_ix, p_keyp);
26830Sstevel@tonic-gate if (ibt_status != IBT_SUCCESS) {
26840Sstevel@tonic-gate IBMF_TRACE_3(IBMF_TNF_NODEBUG, DPRINT_L1,
26850Sstevel@tonic-gate ibmf_i_query_qp_err, IBMF_TNF_TRACE, "",
26860Sstevel@tonic-gate "ibmf_i_query_qp(): %s, pkey_ix = %d, status = %d\n",
26870Sstevel@tonic-gate tnf_string, msg, "failed to get pkey from index",
26880Sstevel@tonic-gate tnf_uint, pkey_ix, pkey_ix,
26890Sstevel@tonic-gate tnf_uint, ibt_status, ibt_status);
26900Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_query_qp_end,
26910Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_query_qp() exit\n");
26920Sstevel@tonic-gate return (IBMF_TRANSPORT_FAILURE);
26930Sstevel@tonic-gate }
26940Sstevel@tonic-gate
26950Sstevel@tonic-gate IBMF_TRACE_4(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_query_qp_end,
26960Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_query_qp() exit, qp_num = 0x%x, "
26970Sstevel@tonic-gate "pkey = 0x%x, qkey = 0x%x, portnum = %d\n",
26980Sstevel@tonic-gate tnf_uint, qp_num, *qp_nump, tnf_uint, pkey, *p_keyp,
26990Sstevel@tonic-gate tnf_uint, qkey, *q_keyp, tnf_uint, portnum, *portnump);
27000Sstevel@tonic-gate
27010Sstevel@tonic-gate return (IBMF_SUCCESS);
27020Sstevel@tonic-gate }
27030Sstevel@tonic-gate
27040Sstevel@tonic-gate /*
27050Sstevel@tonic-gate * ibmf_i_modify_qp():
27060Sstevel@tonic-gate * Modify an alternate QP context
27070Sstevel@tonic-gate */
27080Sstevel@tonic-gate /* ARGSUSED */
27090Sstevel@tonic-gate int
ibmf_i_modify_qp(ibmf_qp_handle_t ibmf_qp_handle,ib_pkey_t p_key,ib_qkey_t q_key,uint_t flags)27100Sstevel@tonic-gate ibmf_i_modify_qp(ibmf_qp_handle_t ibmf_qp_handle, ib_pkey_t p_key,
27110Sstevel@tonic-gate ib_qkey_t q_key, uint_t flags)
27120Sstevel@tonic-gate {
27130Sstevel@tonic-gate ibmf_alt_qp_t *qp_ctx = (ibmf_alt_qp_t *)ibmf_qp_handle;
27140Sstevel@tonic-gate ibmf_client_t *clientp = qp_ctx->isq_client_hdl;
27150Sstevel@tonic-gate ibmf_ci_t *ibmf_cip = clientp->ic_myci;
27160Sstevel@tonic-gate ibmf_alt_qp_t *qpp;
27170Sstevel@tonic-gate ibt_qp_info_t qp_mod;
27180Sstevel@tonic-gate ibt_cep_modify_flags_t qp_mod_flags;
27190Sstevel@tonic-gate ibt_queue_sizes_t actual_sz;
27200Sstevel@tonic-gate uint16_t pkey_ix;
27210Sstevel@tonic-gate ibt_status_t ibt_status;
27220Sstevel@tonic-gate
27230Sstevel@tonic-gate IBMF_TRACE_4(IBMF_TNF_DEBUG, DPRINT_L4,
27240Sstevel@tonic-gate ibmf_i_modify_qp_start, IBMF_TNF_TRACE, "",
27250Sstevel@tonic-gate "ibmf_i_modify_qp() enter, qp_hdl = %p, flags = %x, pkey = 0x%x, "
27260Sstevel@tonic-gate "qkey = 0x%x\n", tnf_opaque, qp_hdl, ibmf_qp_handle,
27270Sstevel@tonic-gate tnf_uint, flags, flags, tnf_uint, p_key, p_key,
27280Sstevel@tonic-gate tnf_uint, q_key, q_key);
27290Sstevel@tonic-gate
27300Sstevel@tonic-gate /*
27310Sstevel@tonic-gate * get the pkey index associated with this pkey if present in table
27320Sstevel@tonic-gate */
27330Sstevel@tonic-gate if (ibmf_i_get_pkeyix(clientp->ic_ci_handle, p_key,
27340Sstevel@tonic-gate clientp->ic_client_info.port_num, &pkey_ix) != IBMF_SUCCESS) {
27350Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
27360Sstevel@tonic-gate ibmf_i_modify_qp_err, IBMF_TNF_TRACE, "",
27370Sstevel@tonic-gate "ibmf_i_modify_qp(): %s, pkey = %x\n",
27380Sstevel@tonic-gate tnf_string, msg, "pkey not in table",
27390Sstevel@tonic-gate tnf_uint, pkey, p_key);
27400Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_modify_qp_end,
27410Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_modify_qp() exit\n");
27420Sstevel@tonic-gate return (IBMF_FAILURE);
27430Sstevel@tonic-gate }
27440Sstevel@tonic-gate
27450Sstevel@tonic-gate /* Find the QP context in the CI QP context list */
27460Sstevel@tonic-gate mutex_enter(&ibmf_cip->ci_mutex);
27470Sstevel@tonic-gate qpp = ibmf_cip->ci_alt_qp_list;
27480Sstevel@tonic-gate while (qpp != NULL) {
27490Sstevel@tonic-gate if (qpp == qp_ctx) {
27500Sstevel@tonic-gate break;
27510Sstevel@tonic-gate }
27520Sstevel@tonic-gate qpp = qpp->isq_next;
27530Sstevel@tonic-gate }
27540Sstevel@tonic-gate
27550Sstevel@tonic-gate if (qpp == NULL) {
27560Sstevel@tonic-gate mutex_exit(&ibmf_cip->ci_mutex);
27570Sstevel@tonic-gate
27580Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
27590Sstevel@tonic-gate ibmf_i_modify_qp_err, IBMF_TNF_TRACE, "",
27600Sstevel@tonic-gate "ibmf_i_modify_qp(): %s\n",
27610Sstevel@tonic-gate tnf_string, msg, "QP not in altqp list");
27620Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_modify_qp_end,
27630Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_modify_qp() exit\n");
27640Sstevel@tonic-gate return (IBMF_BAD_QP_HANDLE);
27650Sstevel@tonic-gate
27660Sstevel@tonic-gate } else {
27670Sstevel@tonic-gate
27680Sstevel@tonic-gate mutex_enter(&qp_ctx->isq_mutex);
27690Sstevel@tonic-gate }
27700Sstevel@tonic-gate
27710Sstevel@tonic-gate mutex_exit(&ibmf_cip->ci_mutex);
27720Sstevel@tonic-gate
27730Sstevel@tonic-gate /*
27740Sstevel@tonic-gate * Transition the QP to SQD state
27750Sstevel@tonic-gate */
27760Sstevel@tonic-gate bzero(&qp_mod, sizeof (ibt_qp_info_t));
27770Sstevel@tonic-gate qp_mod.qp_trans = IBT_UD_SRV;
27780Sstevel@tonic-gate qp_mod.qp_state = IBT_STATE_SQD;
27790Sstevel@tonic-gate qp_mod_flags = IBT_CEP_SET_STATE | IBT_CEP_SET_SQD_EVENT;
27800Sstevel@tonic-gate ibt_status = ibt_modify_qp(qp_ctx->isq_qp_handle, qp_mod_flags,
27810Sstevel@tonic-gate &qp_mod, &actual_sz);
27820Sstevel@tonic-gate if (ibt_status != IBT_SUCCESS) {
27830Sstevel@tonic-gate mutex_exit(&qp_ctx->isq_mutex);
27840Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
27850Sstevel@tonic-gate ibmf_i_modify_qp_err, IBMF_TNF_TRACE, "",
27860Sstevel@tonic-gate "ibmf_i_modify_qp(): %s, qp_hdl = %p\n",
27870Sstevel@tonic-gate tnf_string, msg, "QP transition RTS to SQD failed",
27880Sstevel@tonic-gate tnf_opaque, qp_handle, qp_ctx->isq_qp_handle);
27890Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_modify_qp_end,
27900Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_modify_qp() exit\n");
27910Sstevel@tonic-gate return (IBMF_TRANSPORT_FAILURE);
27920Sstevel@tonic-gate }
27930Sstevel@tonic-gate
27940Sstevel@tonic-gate /*
27950Sstevel@tonic-gate * Wait for an event indicating that the QP is in SQD state
27960Sstevel@tonic-gate */
27970Sstevel@tonic-gate cv_wait(&qp_ctx->isq_sqd_cv, &qp_ctx->isq_mutex);
27980Sstevel@tonic-gate
27990Sstevel@tonic-gate /* Setup QP modification information for transition to RTS state */
28000Sstevel@tonic-gate bzero(&qp_mod, sizeof (ibt_qp_info_t));
28010Sstevel@tonic-gate qp_mod.qp_trans = IBT_UD_SRV;
28020Sstevel@tonic-gate qp_mod.qp_state = IBT_STATE_RTS;
28030Sstevel@tonic-gate qp_mod.qp_current_state = IBT_STATE_SQD;
28040Sstevel@tonic-gate qp_mod.qp_transport.ud.ud_pkey_ix = pkey_ix;
28050Sstevel@tonic-gate qp_mod.qp_transport.ud.ud_qkey = q_key;
28060Sstevel@tonic-gate qp_mod_flags = IBT_CEP_SET_STATE | IBT_CEP_SET_PKEY_IX |
28070Sstevel@tonic-gate IBT_CEP_SET_QKEY;
28080Sstevel@tonic-gate
28090Sstevel@tonic-gate /*
28100Sstevel@tonic-gate * transition the QP back to RTS state to allow
28110Sstevel@tonic-gate * modification of the pkey and qkey
28120Sstevel@tonic-gate */
28130Sstevel@tonic-gate
28140Sstevel@tonic-gate ibt_status = ibt_modify_qp(qp_ctx->isq_qp_handle, qp_mod_flags,
28150Sstevel@tonic-gate &qp_mod, &actual_sz);
28160Sstevel@tonic-gate if (ibt_status != IBT_SUCCESS) {
28170Sstevel@tonic-gate mutex_exit(&qp_ctx->isq_mutex);
28180Sstevel@tonic-gate IBMF_TRACE_3(IBMF_TNF_NODEBUG, DPRINT_L1,
28190Sstevel@tonic-gate ibmf_i_modify_qp_err, IBMF_TNF_TRACE, "",
28200Sstevel@tonic-gate "ibmf_i_modify_qp(): %s, qp_hdl = %p, status = %d\n",
28210Sstevel@tonic-gate tnf_string, msg, "QP transition SQD to RTS failed",
28220Sstevel@tonic-gate tnf_opaque, qp_handle, qp_ctx->isq_qp_handle,
28230Sstevel@tonic-gate tnf_uint, ibt_status, ibt_status);
28240Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_modify_qp_end,
28250Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_modify_qp() exit\n");
28260Sstevel@tonic-gate return (IBMF_TRANSPORT_FAILURE);
28270Sstevel@tonic-gate }
28280Sstevel@tonic-gate
28290Sstevel@tonic-gate qp_ctx->isq_pkey = p_key;
28300Sstevel@tonic-gate qp_ctx->isq_qkey = q_key;
28310Sstevel@tonic-gate mutex_exit(&qp_ctx->isq_mutex);
28320Sstevel@tonic-gate
28330Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_modify_qp_end,
28340Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_modify_qp() exit\n");
28350Sstevel@tonic-gate return (IBMF_SUCCESS);
28360Sstevel@tonic-gate }
28370Sstevel@tonic-gate
28380Sstevel@tonic-gate /*
28390Sstevel@tonic-gate * ibmf_i_post_recv_buffer():
28400Sstevel@tonic-gate * Post a WQE to the RQ of the specified QP
28410Sstevel@tonic-gate */
28420Sstevel@tonic-gate int
ibmf_i_post_recv_buffer(ibmf_ci_t * cip,ibmf_qp_t * qpp,boolean_t block,ibmf_qp_handle_t ibmf_qp_handle)28430Sstevel@tonic-gate ibmf_i_post_recv_buffer(ibmf_ci_t *cip, ibmf_qp_t *qpp, boolean_t block,
28440Sstevel@tonic-gate ibmf_qp_handle_t ibmf_qp_handle)
28450Sstevel@tonic-gate {
28460Sstevel@tonic-gate int ret;
28470Sstevel@tonic-gate ibt_wr_ds_t *sgl;
28480Sstevel@tonic-gate ibt_status_t status;
28490Sstevel@tonic-gate ibmf_recv_wqe_t *recv_wqep;
28500Sstevel@tonic-gate ibt_qp_hdl_t ibt_qp_handle;
28510Sstevel@tonic-gate struct kmem_cache *kmem_cachep;
28520Sstevel@tonic-gate ibmf_alt_qp_t *altqp;
28530Sstevel@tonic-gate
28540Sstevel@tonic-gate IBMF_TRACE_4(IBMF_TNF_DEBUG, DPRINT_L4,
28550Sstevel@tonic-gate ibmf_i_post_recv_buffer_start, IBMF_TNF_TRACE, "",
28560Sstevel@tonic-gate "ibmf_i_post_recv_buffer() enter, cip = %p, qpp = %p, "
28570Sstevel@tonic-gate "qp_hdl = %p, block = %d\n", tnf_opaque, cip, cip,
28580Sstevel@tonic-gate tnf_opaque, qpp, qpp, tnf_opaque, qp_hdl, ibmf_qp_handle,
28590Sstevel@tonic-gate tnf_uint, block, block);
28600Sstevel@tonic-gate
28610Sstevel@tonic-gate /*
28620Sstevel@tonic-gate * if we haven't hit the max wqes per qp, attempt to allocate a recv
28630Sstevel@tonic-gate * wqe and post it to the recv queue.
28640Sstevel@tonic-gate * It is possible for more than one thread to get through this
28650Sstevel@tonic-gate * check below and post wqes that could push us above the
28660Sstevel@tonic-gate * ibmf_recv_wqes_posted_per_qp. We catch that case when the recv
28670Sstevel@tonic-gate * completion is signaled.
28680Sstevel@tonic-gate */
28690Sstevel@tonic-gate ASSERT(MUTEX_NOT_HELD(&cip->ci_mutex));
28700Sstevel@tonic-gate
28710Sstevel@tonic-gate /* Get the WQE kmem cache pointer based on the QP type */
28720Sstevel@tonic-gate if (ibmf_qp_handle == IBMF_QP_HANDLE_DEFAULT)
28730Sstevel@tonic-gate kmem_cachep = cip->ci_recv_wqes_cache;
28740Sstevel@tonic-gate else {
28750Sstevel@tonic-gate altqp = (ibmf_alt_qp_t *)ibmf_qp_handle;
28760Sstevel@tonic-gate kmem_cachep = altqp->isq_recv_wqes_cache;
28770Sstevel@tonic-gate }
28780Sstevel@tonic-gate
28790Sstevel@tonic-gate /* allocate a receive WQE from the receive WQE kmem cache */
28800Sstevel@tonic-gate recv_wqep = kmem_cache_alloc(kmem_cachep,
28810Sstevel@tonic-gate (block == B_TRUE ? KM_SLEEP : KM_NOSLEEP));
28820Sstevel@tonic-gate if (recv_wqep == NULL) {
28830Sstevel@tonic-gate /*
28840Sstevel@tonic-gate * Attempt to extend the cache and then retry the
28850Sstevel@tonic-gate * kmem_cache_alloc()
28860Sstevel@tonic-gate */
28870Sstevel@tonic-gate if (ibmf_i_extend_wqe_cache(cip, ibmf_qp_handle, block) ==
28880Sstevel@tonic-gate IBMF_NO_RESOURCES) {
28890Sstevel@tonic-gate mutex_enter(&cip->ci_mutex);
28900Sstevel@tonic-gate IBMF_ADD32_PORT_KSTATS(cip, rwqe_allocs_failed, 1);
28910Sstevel@tonic-gate mutex_exit(&cip->ci_mutex);
28920Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
28930Sstevel@tonic-gate ibmf_i_post_recv_buffer_err, IBMF_TNF_ERROR, "",
28940Sstevel@tonic-gate "ibmf_i_post_recv_buffer(): %s, status = %d\n",
28950Sstevel@tonic-gate tnf_string, msg, "alloc recv_wqe failed",
28960Sstevel@tonic-gate tnf_int, ibmf_status, IBMF_NO_RESOURCES);
28970Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
28980Sstevel@tonic-gate ibmf_i_post_recv_buffer_end, IBMF_TNF_TRACE, "",
28990Sstevel@tonic-gate "ibmf_i_post_recv_buffer() exit\n");
29000Sstevel@tonic-gate return (IBMF_NO_RESOURCES);
29010Sstevel@tonic-gate } else {
29020Sstevel@tonic-gate recv_wqep = kmem_cache_alloc(kmem_cachep,
29030Sstevel@tonic-gate (block == B_TRUE ? KM_SLEEP : KM_NOSLEEP));
29040Sstevel@tonic-gate if (recv_wqep == NULL) {
29050Sstevel@tonic-gate /* Allocation failed again. Give up here. */
29060Sstevel@tonic-gate mutex_enter(&cip->ci_mutex);
29070Sstevel@tonic-gate IBMF_ADD32_PORT_KSTATS(cip, rwqe_allocs_failed,
29080Sstevel@tonic-gate 1);
29090Sstevel@tonic-gate mutex_exit(&cip->ci_mutex);
29100Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
29110Sstevel@tonic-gate ibmf_i_post_recv_buffer_err,
29120Sstevel@tonic-gate IBMF_TNF_ERROR, "",
29130Sstevel@tonic-gate "ibmf_i_post_recv_buffer(): %s, "
29140Sstevel@tonic-gate "status = %d\n",
29150Sstevel@tonic-gate tnf_string, msg, "alloc recv_wqe failed",
29160Sstevel@tonic-gate tnf_int, ibmf_status, IBMF_NO_RESOURCES);
29170Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
29180Sstevel@tonic-gate ibmf_i_post_recv_buffer_end,
29190Sstevel@tonic-gate IBMF_TNF_TRACE, "",
29200Sstevel@tonic-gate "ibmf_i_post_recv_buffer() exit\n");
29210Sstevel@tonic-gate return (IBMF_NO_RESOURCES);
29220Sstevel@tonic-gate }
29230Sstevel@tonic-gate }
29240Sstevel@tonic-gate }
29250Sstevel@tonic-gate
29260Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*recv_wqep))
29270Sstevel@tonic-gate
29280Sstevel@tonic-gate /*
29290Sstevel@tonic-gate * if the qp handle provided in ibmf_send_pkt() or
29300Sstevel@tonic-gate * ibmf_setup_recv_cb() is not the default qp handle
29310Sstevel@tonic-gate * for this client, then the wqe must be queued on this qp,
29320Sstevel@tonic-gate * else use the default qp handle set up during ibmf_register()
29330Sstevel@tonic-gate */
29340Sstevel@tonic-gate if (ibmf_qp_handle == IBMF_QP_HANDLE_DEFAULT) {
29350Sstevel@tonic-gate ibt_qp_handle = qpp->iq_qp_handle;
29360Sstevel@tonic-gate } else {
29370Sstevel@tonic-gate ibt_qp_handle =
29380Sstevel@tonic-gate ((ibmf_alt_qp_t *)ibmf_qp_handle)->isq_qp_handle;
29390Sstevel@tonic-gate }
29400Sstevel@tonic-gate
29410Sstevel@tonic-gate /* allocate memory for the scatter-gather list */
29420Sstevel@tonic-gate sgl = kmem_zalloc(IBMF_MAX_RQ_WR_SGL_ELEMENTS * sizeof (ibt_wr_ds_t),
29430Sstevel@tonic-gate (block == B_TRUE) ? KM_SLEEP : KM_NOSLEEP);
29440Sstevel@tonic-gate if (sgl == NULL) {
29450Sstevel@tonic-gate kmem_cache_free(kmem_cachep, recv_wqep);
29460Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
29470Sstevel@tonic-gate ibmf_i_post_recv_buffer_err, IBMF_TNF_ERROR, "",
29480Sstevel@tonic-gate "ibmf_i_post_recv_buffer(): %s\n",
29490Sstevel@tonic-gate tnf_string, msg, "failed to kmem_zalloc qp ctx");
29500Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
29510Sstevel@tonic-gate ibmf_i_post_recv_buffer_end, IBMF_TNF_TRACE, "",
29520Sstevel@tonic-gate "ibmf_i_post_recv_buffer() exit\n");
29530Sstevel@tonic-gate return (IBMF_NO_RESOURCES);
29540Sstevel@tonic-gate }
29550Sstevel@tonic-gate
29560Sstevel@tonic-gate /* initialize it */
29570Sstevel@tonic-gate ibmf_i_init_recv_wqe(qpp, sgl, recv_wqep, ibt_qp_handle,
29580Sstevel@tonic-gate ibmf_qp_handle);
29590Sstevel@tonic-gate
29600Sstevel@tonic-gate _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*recv_wqep))
29610Sstevel@tonic-gate
29620Sstevel@tonic-gate /* and post it */
29630Sstevel@tonic-gate status = ibt_post_recv(recv_wqep->recv_qp_handle, &recv_wqep->recv_wr,
29640Sstevel@tonic-gate 1, NULL);
29650Sstevel@tonic-gate
29660Sstevel@tonic-gate ret = ibmf_i_ibt_to_ibmf_status(status);
29670Sstevel@tonic-gate if (ret != IBMF_SUCCESS) {
29680Sstevel@tonic-gate kmem_free(sgl, IBMF_MAX_RQ_WR_SGL_ELEMENTS *
29690Sstevel@tonic-gate sizeof (ibt_wr_ds_t));
29700Sstevel@tonic-gate kmem_cache_free(kmem_cachep, recv_wqep);
29710Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
29720Sstevel@tonic-gate ibmf_i_post_recv_buffer_err, IBMF_TNF_ERROR, "",
29730Sstevel@tonic-gate "ibmf_i_post_recv_buffer(): %s, status = %d\n",
29740Sstevel@tonic-gate tnf_string, msg, "ibt_post_recv failed",
29750Sstevel@tonic-gate tnf_uint, ibt_status, status);
29760Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
29770Sstevel@tonic-gate ibmf_i_post_recv_buffer_end, IBMF_TNF_TRACE, "",
29780Sstevel@tonic-gate "ibmf_i_post_recv_buffer() exit\n");
29790Sstevel@tonic-gate return (ret);
29800Sstevel@tonic-gate }
29810Sstevel@tonic-gate
29820Sstevel@tonic-gate mutex_enter(&cip->ci_mutex);
29830Sstevel@tonic-gate IBMF_ADD32_PORT_KSTATS(cip, recv_wqes_alloced, 1);
29840Sstevel@tonic-gate mutex_exit(&cip->ci_mutex);
29850Sstevel@tonic-gate if (ibmf_qp_handle == IBMF_QP_HANDLE_DEFAULT) {
29860Sstevel@tonic-gate mutex_enter(&qpp->iq_mutex);
29870Sstevel@tonic-gate qpp->iq_rwqes_posted++;
29880Sstevel@tonic-gate mutex_exit(&qpp->iq_mutex);
29890Sstevel@tonic-gate mutex_enter(&cip->ci_mutex);
29900Sstevel@tonic-gate cip->ci_wqes_alloced++;
29910Sstevel@tonic-gate mutex_exit(&cip->ci_mutex);
29920Sstevel@tonic-gate } else {
29930Sstevel@tonic-gate mutex_enter(&altqp->isq_mutex);
29940Sstevel@tonic-gate altqp->isq_wqes_alloced++;
29950Sstevel@tonic-gate altqp->isq_rwqes_posted++;
29960Sstevel@tonic-gate mutex_exit(&altqp->isq_mutex);
29970Sstevel@tonic-gate }
29980Sstevel@tonic-gate
29990Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_post_recv_buffer_end,
30000Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_post_recv_buffer() exit\n");
30010Sstevel@tonic-gate
30020Sstevel@tonic-gate return (ret);
30030Sstevel@tonic-gate }
30040Sstevel@tonic-gate
30050Sstevel@tonic-gate /*
30060Sstevel@tonic-gate * ibmf_i_mgt_class_to_hdr_sz_off():
30070Sstevel@tonic-gate * Determine class header offser and size for management classes
30080Sstevel@tonic-gate */
30090Sstevel@tonic-gate void
ibmf_i_mgt_class_to_hdr_sz_off(uint32_t mgt_class,uint32_t * szp,uint32_t * offp)30100Sstevel@tonic-gate ibmf_i_mgt_class_to_hdr_sz_off(uint32_t mgt_class, uint32_t *szp,
30110Sstevel@tonic-gate uint32_t *offp)
30120Sstevel@tonic-gate {
30130Sstevel@tonic-gate uint32_t hdr_sz = 0, hdr_off = 0;
30140Sstevel@tonic-gate
30150Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4,
30160Sstevel@tonic-gate ibmf_i_mgt_class_to_hdr_sz_off_start, IBMF_TNF_TRACE, "",
30170Sstevel@tonic-gate "ibmf_i_mgt_class_to_hdr_sz_off(): mgt_class = 0x%x\n",
30180Sstevel@tonic-gate tnf_uint, mgt_class, mgt_class);
30190Sstevel@tonic-gate
30200Sstevel@tonic-gate switch (mgt_class) {
30210Sstevel@tonic-gate case MAD_MGMT_CLASS_SUBN_LID_ROUTED :
30220Sstevel@tonic-gate case MAD_MGMT_CLASS_SUBN_DIRECT_ROUTE :
30230Sstevel@tonic-gate case MAD_MGMT_CLASS_PERF :
30240Sstevel@tonic-gate case MAD_MGMT_CLASS_BM :
30250Sstevel@tonic-gate case MAD_MGMT_CLASS_DEV_MGT :
30260Sstevel@tonic-gate case MAD_MGMT_CLASS_SNMP :
3027*12787SLida.Horn@Oracle.COM case MAD_MGMT_CLASS_COMM_MGT:
30280Sstevel@tonic-gate hdr_sz = IBMF_MAD_CL_HDR_SZ_1;
30290Sstevel@tonic-gate hdr_off = IBMF_MAD_CL_HDR_OFF_1;
30300Sstevel@tonic-gate break;
30310Sstevel@tonic-gate case MAD_MGMT_CLASS_SUBN_ADM :
30320Sstevel@tonic-gate hdr_sz = IBMF_MAD_CL_HDR_SZ_2;
30330Sstevel@tonic-gate hdr_off = IBMF_MAD_CL_HDR_OFF_2;
30340Sstevel@tonic-gate break;
3035*12787SLida.Horn@Oracle.COM default:
3036*12787SLida.Horn@Oracle.COM if (((mgt_class >= MAD_MGMT_CLASS_VENDOR_START) &&
3037*12787SLida.Horn@Oracle.COM (mgt_class <= MAD_MGMT_CLASS_VENDOR_END)) ||
3038*12787SLida.Horn@Oracle.COM ((mgt_class >= MAD_MGMT_CLASS_APPLICATION_START) &&
3039*12787SLida.Horn@Oracle.COM (mgt_class <= MAD_MGMT_CLASS_APPLICATION_END))) {
3040*12787SLida.Horn@Oracle.COM hdr_sz = IBMF_MAD_CL_HDR_SZ_3;
3041*12787SLida.Horn@Oracle.COM hdr_off = IBMF_MAD_CL_HDR_OFF_1;
3042*12787SLida.Horn@Oracle.COM } else if ((mgt_class >= MAD_MGMT_CLASS_VENDOR2_START) &&
3043*12787SLida.Horn@Oracle.COM (mgt_class <= MAD_MGMT_CLASS_VENDOR2_END)) {
3044*12787SLida.Horn@Oracle.COM hdr_sz = IBMF_MAD_CL_HDR_SZ_4;
3045*12787SLida.Horn@Oracle.COM hdr_off = IBMF_MAD_CL_HDR_OFF_2;
3046*12787SLida.Horn@Oracle.COM } else {
3047*12787SLida.Horn@Oracle.COM IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4,
3048*12787SLida.Horn@Oracle.COM ibmf_i_mgt_class_to_hdr_sz_off_start,
3049*12787SLida.Horn@Oracle.COM IBMF_TNF_TRACE, "",
3050*12787SLida.Horn@Oracle.COM "ibmf_i_mgt_class_to_hdr_sz_off():"
3051*12787SLida.Horn@Oracle.COM "got illegal management class = 0x%x\n",
3052*12787SLida.Horn@Oracle.COM tnf_uint, mgt_class, mgt_class);
3053*12787SLida.Horn@Oracle.COM }
3054*12787SLida.Horn@Oracle.COM break;
30550Sstevel@tonic-gate }
30560Sstevel@tonic-gate
3057*12787SLida.Horn@Oracle.COM
30580Sstevel@tonic-gate
30590Sstevel@tonic-gate *szp = hdr_sz;
30600Sstevel@tonic-gate *offp = hdr_off;
30610Sstevel@tonic-gate
30620Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4,
30630Sstevel@tonic-gate ibmf_i_mgt_class_to_hdr_sz_off_end, IBMF_TNF_TRACE, "",
30640Sstevel@tonic-gate "ibmf_i_mgt_class_to_hdr_sz_off() exit,hdr_sz = %d, hdr_off = %d\n",
30650Sstevel@tonic-gate tnf_uint, hdr_sz, hdr_sz, tnf_uint, hdr_off, hdr_off);
30660Sstevel@tonic-gate }
30670Sstevel@tonic-gate
30680Sstevel@tonic-gate /*
30690Sstevel@tonic-gate * ibmf_i_lookup_client_by_mgmt_class():
30700Sstevel@tonic-gate * Lookup the client context based on the management class of
30710Sstevel@tonic-gate * the incoming packet
30720Sstevel@tonic-gate */
30730Sstevel@tonic-gate int
ibmf_i_lookup_client_by_mgmt_class(ibmf_ci_t * ibmf_cip,int port_num,ibmf_client_type_t class,ibmf_client_t ** clientpp)30740Sstevel@tonic-gate ibmf_i_lookup_client_by_mgmt_class(ibmf_ci_t *ibmf_cip, int port_num,
30750Sstevel@tonic-gate ibmf_client_type_t class, ibmf_client_t **clientpp)
30760Sstevel@tonic-gate {
30770Sstevel@tonic-gate ibmf_client_t *clientp;
30780Sstevel@tonic-gate ibmf_client_info_t *client_infop;
30790Sstevel@tonic-gate
30800Sstevel@tonic-gate IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L4,
30810Sstevel@tonic-gate ibmf_i_lookup_client_by_mgmt_class_start, IBMF_TNF_TRACE, "",
30820Sstevel@tonic-gate "ibmf_i_lookup_client_by_mgmt_class() enter, cip = %p, "
30830Sstevel@tonic-gate "port_num = %d, class = 0x%x\n", tnf_opaque, cip, ibmf_cip,
30840Sstevel@tonic-gate tnf_int, port, port_num, tnf_opaque, class, class);
30850Sstevel@tonic-gate
30860Sstevel@tonic-gate ASSERT(MUTEX_NOT_HELD(&ibmf_cip->ci_clients_mutex));
30870Sstevel@tonic-gate
30880Sstevel@tonic-gate mutex_enter(&ibmf_cip->ci_clients_mutex);
30890Sstevel@tonic-gate
30900Sstevel@tonic-gate clientp = ibmf_cip->ci_clients;
30910Sstevel@tonic-gate
30920Sstevel@tonic-gate /* walk client context list looking for class/portnum match */
30930Sstevel@tonic-gate while (clientp != NULL) {
30940Sstevel@tonic-gate client_infop = &clientp->ic_client_info;
30950Sstevel@tonic-gate if (class == client_infop->client_class &&
30960Sstevel@tonic-gate port_num == client_infop->port_num) {
30970Sstevel@tonic-gate /* found our match */
30980Sstevel@tonic-gate break;
30990Sstevel@tonic-gate }
31000Sstevel@tonic-gate clientp = clientp->ic_next;
31010Sstevel@tonic-gate }
31020Sstevel@tonic-gate
31030Sstevel@tonic-gate mutex_exit(&ibmf_cip->ci_clients_mutex);
31040Sstevel@tonic-gate
31050Sstevel@tonic-gate if (clientp != NULL) {
31060Sstevel@tonic-gate *clientpp = clientp;
31070Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4,
31080Sstevel@tonic-gate ibmf_i_lookup_client_by_mgmt_class_end, IBMF_TNF_TRACE, "",
31090Sstevel@tonic-gate "ibmf_i_lookup_client_by_mgmt_class() exit, clp = %p\n",
31100Sstevel@tonic-gate tnf_opaque, clientp, clientp);
31110Sstevel@tonic-gate return (IBMF_SUCCESS);
31120Sstevel@tonic-gate } else {
31130Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
31140Sstevel@tonic-gate ibmf_i_lookup_client_by_mgmt_class_end, IBMF_TNF_TRACE, "",
31150Sstevel@tonic-gate "ibmf_i_lookup_client_by_mgmt_class() failure exit\n");
31160Sstevel@tonic-gate return (IBMF_FAILURE);
31170Sstevel@tonic-gate }
31180Sstevel@tonic-gate }
31190Sstevel@tonic-gate
31200Sstevel@tonic-gate /*
31210Sstevel@tonic-gate * ibmf_i_get_pkeyix():
31220Sstevel@tonic-gate * Get the pkey index of the pkey in the pkey table of the specified
31230Sstevel@tonic-gate * port. Take into account the partition membership.
31240Sstevel@tonic-gate */
31250Sstevel@tonic-gate int
ibmf_i_get_pkeyix(ibt_hca_hdl_t hca_handle,ib_pkey_t pkey,uint8_t port,ib_pkey_t * pkeyixp)31260Sstevel@tonic-gate ibmf_i_get_pkeyix(ibt_hca_hdl_t hca_handle, ib_pkey_t pkey, uint8_t port,
31270Sstevel@tonic-gate ib_pkey_t *pkeyixp)
31280Sstevel@tonic-gate {
31290Sstevel@tonic-gate ib_pkey_t tpkey;
31300Sstevel@tonic-gate ibt_status_t ibt_status;
31310Sstevel@tonic-gate
31320Sstevel@tonic-gate IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_get_pkeyix_start,
31330Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_get_pkeyix() enter, hcahdl = %p, "
31340Sstevel@tonic-gate "pkey = 0x%x, port = %d\n", tnf_opaque, hcahdl, hca_handle,
31350Sstevel@tonic-gate tnf_int, pkey, pkey, tnf_int, port, port);
31360Sstevel@tonic-gate
31370Sstevel@tonic-gate /*
31380Sstevel@tonic-gate * If the client specifies the FULL membership pkey and the
31390Sstevel@tonic-gate * pkey is not in the table, this function should fail.
31400Sstevel@tonic-gate */
31410Sstevel@tonic-gate if (pkey & IBMF_PKEY_MEMBERSHIP_MASK) {
31420Sstevel@tonic-gate ibt_status = ibt_pkey2index(hca_handle, port,
31430Sstevel@tonic-gate pkey, pkeyixp);
31440Sstevel@tonic-gate if (ibt_status != IBT_SUCCESS) {
31450Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
31460Sstevel@tonic-gate ibmf_i_get_pkeyix_err, IBMF_TNF_ERROR, "",
31470Sstevel@tonic-gate "ibmf_i_get_pkeyix() error status = %d\n",
31480Sstevel@tonic-gate tnf_uint, ibt_status, ibt_status);
31490Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
31500Sstevel@tonic-gate ibmf_i_get_pkeyix_end, IBMF_TNF_TRACE, "",
31510Sstevel@tonic-gate "ibmf_i_get_pkeyix() exit\n");
31520Sstevel@tonic-gate return (IBMF_TRANSPORT_FAILURE);
31530Sstevel@tonic-gate }
31540Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_get_pkeyix_end,
31550Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_get_pkeyix() exit\n");
31560Sstevel@tonic-gate return (IBMF_SUCCESS);
31570Sstevel@tonic-gate }
31580Sstevel@tonic-gate
31590Sstevel@tonic-gate /*
31600Sstevel@tonic-gate * Limited member pkey processing
31610Sstevel@tonic-gate * Check if this limited member pkey is in the pkey table
31620Sstevel@tonic-gate */
31630Sstevel@tonic-gate ibt_status = ibt_pkey2index(hca_handle, port, pkey, pkeyixp);
31640Sstevel@tonic-gate if (ibt_status == IBT_SUCCESS) {
31650Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
31660Sstevel@tonic-gate ibmf_i_get_pkeyix_end, IBMF_TNF_TRACE, "",
31670Sstevel@tonic-gate "ibmf_i_get_pkeyix() exit\n");
31680Sstevel@tonic-gate return (IBMF_SUCCESS);
31690Sstevel@tonic-gate }
31700Sstevel@tonic-gate
31710Sstevel@tonic-gate /*
31720Sstevel@tonic-gate * Could not find the limited member version of the pkey.
31730Sstevel@tonic-gate * Now check if the full member version of the pkey is in the
31740Sstevel@tonic-gate * pkey table. If not, fail the call.
31750Sstevel@tonic-gate */
31760Sstevel@tonic-gate tpkey = pkey | IBMF_PKEY_MEMBERSHIP_MASK;
31770Sstevel@tonic-gate ibt_status = ibt_pkey2index(hca_handle, port, tpkey, pkeyixp);
31780Sstevel@tonic-gate if (ibt_status != IBT_SUCCESS) {
31790Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
31800Sstevel@tonic-gate ibmf_i_get_pkeyix_err, IBMF_TNF_ERROR, "",
31810Sstevel@tonic-gate "ibmf_i_get_pkeyix() error status = %d\n",
31820Sstevel@tonic-gate tnf_uint, ibt_status, ibt_status);
31830Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
31840Sstevel@tonic-gate ibmf_i_get_pkeyix_end, IBMF_TNF_TRACE, "",
31850Sstevel@tonic-gate "ibmf_i_get_pkeyix() exit\n");
31860Sstevel@tonic-gate return (IBMF_TRANSPORT_FAILURE);
31870Sstevel@tonic-gate }
31880Sstevel@tonic-gate
31890Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_get_pkeyix_end,
31900Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_get_pkeyix(): pkey_ix = %d\n",
31910Sstevel@tonic-gate tnf_int, pkeyix, *pkeyixp);
31920Sstevel@tonic-gate return (IBMF_SUCCESS);
31930Sstevel@tonic-gate }
31940Sstevel@tonic-gate
31950Sstevel@tonic-gate /*
31960Sstevel@tonic-gate * ibmf_i_pkey_ix_to_key():
31970Sstevel@tonic-gate * Figure out pkey from pkey index
31980Sstevel@tonic-gate */
31990Sstevel@tonic-gate int
ibmf_i_pkey_ix_to_key(ibmf_ci_t * cip,uint_t port_num,uint_t pkey_ix,ib_pkey_t * pkeyp)32000Sstevel@tonic-gate ibmf_i_pkey_ix_to_key(ibmf_ci_t *cip, uint_t port_num, uint_t pkey_ix,
32010Sstevel@tonic-gate ib_pkey_t *pkeyp)
32020Sstevel@tonic-gate {
32030Sstevel@tonic-gate ibt_status_t ibt_status;
32040Sstevel@tonic-gate
32050Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_pkey_ix_to_key_start,
32060Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_pkey_ix_to_key() enter\n");
32070Sstevel@tonic-gate
32080Sstevel@tonic-gate ibt_status = ibt_index2pkey(cip->ci_ci_handle, port_num, pkey_ix,
32090Sstevel@tonic-gate pkeyp);
32100Sstevel@tonic-gate if (ibt_status != IBT_SUCCESS) {
32110Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
32120Sstevel@tonic-gate ibmf_i_pkey_ix_to_key, IBMF_TNF_TRACE, "",
32130Sstevel@tonic-gate "ibmf_i_pkey_ix_to_key(): ibt_index2pkey failed for "
32140Sstevel@tonic-gate " pkey index %d \n", tnf_uint, pkey_ix, pkey_ix);
32150Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
32160Sstevel@tonic-gate ibmf_i_pkey_ix_to_key_end,
32170Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_pkey_ix_to_key() exit\n");
32180Sstevel@tonic-gate return (IBMF_TRANSPORT_FAILURE);
32190Sstevel@tonic-gate }
32200Sstevel@tonic-gate
32210Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_pkey_ix_to_key_end,
32220Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_pkey_ix_to_key() exit\n");
32230Sstevel@tonic-gate
32240Sstevel@tonic-gate return (IBMF_SUCCESS);
32250Sstevel@tonic-gate }
32260Sstevel@tonic-gate
32270Sstevel@tonic-gate /*
32280Sstevel@tonic-gate * ibmf_i_ibt_to_ibmf_status():
32290Sstevel@tonic-gate * Map IBT return code to IBMF return code
32300Sstevel@tonic-gate */
32310Sstevel@tonic-gate int
ibmf_i_ibt_to_ibmf_status(ibt_status_t ibt_status)32320Sstevel@tonic-gate ibmf_i_ibt_to_ibmf_status(ibt_status_t ibt_status)
32330Sstevel@tonic-gate {
32340Sstevel@tonic-gate int ibmf_status;
32350Sstevel@tonic-gate
32360Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_ibt_to_ibmf_status_start,
32370Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_ibt_to_ibmf_status() enter, "
32380Sstevel@tonic-gate "status = %d\n", tnf_uint, ibt_status, ibt_status);
32390Sstevel@tonic-gate
32400Sstevel@tonic-gate switch (ibt_status) {
32410Sstevel@tonic-gate
32420Sstevel@tonic-gate case IBT_SUCCESS:
32430Sstevel@tonic-gate ibmf_status = IBMF_SUCCESS;
32440Sstevel@tonic-gate break;
32450Sstevel@tonic-gate
32460Sstevel@tonic-gate case IBT_INSUFF_KERNEL_RESOURCE:
32470Sstevel@tonic-gate case IBT_INSUFF_RESOURCE:
32480Sstevel@tonic-gate case IBT_QP_FULL:
32490Sstevel@tonic-gate ibmf_status = IBMF_NO_RESOURCES;
32500Sstevel@tonic-gate break;
32510Sstevel@tonic-gate
32520Sstevel@tonic-gate case IBT_HCA_IN_USE:
32530Sstevel@tonic-gate case IBT_QP_IN_USE:
32540Sstevel@tonic-gate case IBT_CQ_BUSY:
32550Sstevel@tonic-gate case IBT_PD_IN_USE:
32560Sstevel@tonic-gate case IBT_MR_IN_USE:
32570Sstevel@tonic-gate ibmf_status = IBMF_BUSY;
32580Sstevel@tonic-gate break;
32590Sstevel@tonic-gate
32600Sstevel@tonic-gate default:
32610Sstevel@tonic-gate ibmf_status = IBMF_FAILURE;
32620Sstevel@tonic-gate break;
32630Sstevel@tonic-gate }
32640Sstevel@tonic-gate
32650Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_ibt_to_ibmf_status_end,
32660Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_i_ibt_to_ibmf_status() exit, "
32670Sstevel@tonic-gate "ibt_status = %d, ibmf_status = %d\n", tnf_uint, ibt_status,
32680Sstevel@tonic-gate ibt_status, tnf_int, ibmf_status, ibmf_status);
32690Sstevel@tonic-gate
32700Sstevel@tonic-gate return (ibmf_status);
32710Sstevel@tonic-gate }
32720Sstevel@tonic-gate
32730Sstevel@tonic-gate /*
32740Sstevel@tonic-gate * ibmf_i_ibt_wc_to_ibmf_status():
32750Sstevel@tonic-gate * Map work completion code to IBMF return code
32760Sstevel@tonic-gate */
32770Sstevel@tonic-gate int
ibmf_i_ibt_wc_to_ibmf_status(ibt_wc_status_t ibt_wc_status)32780Sstevel@tonic-gate ibmf_i_ibt_wc_to_ibmf_status(ibt_wc_status_t ibt_wc_status)
32790Sstevel@tonic-gate {
32800Sstevel@tonic-gate int ibmf_status;
32810Sstevel@tonic-gate
32820Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4,
32830Sstevel@tonic-gate ibmf_i_ibt_wc_to_ibmf_status_start, IBMF_TNF_TRACE, "",
32840Sstevel@tonic-gate "ibmf_i_ibt_to_ibmf_status() enter, status = %d\n",
32850Sstevel@tonic-gate tnf_uint, ibt_wc_status, ibt_wc_status);
32860Sstevel@tonic-gate
32870Sstevel@tonic-gate switch (ibt_wc_status) {
32880Sstevel@tonic-gate
32890Sstevel@tonic-gate case IBT_WC_SUCCESS:
32900Sstevel@tonic-gate ibmf_status = IBMF_SUCCESS;
32910Sstevel@tonic-gate break;
32920Sstevel@tonic-gate
32930Sstevel@tonic-gate default:
32940Sstevel@tonic-gate ibmf_status = IBMF_FAILURE;
32950Sstevel@tonic-gate break;
32960Sstevel@tonic-gate }
32970Sstevel@tonic-gate
32980Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4,
32990Sstevel@tonic-gate ibmf_i_ibt_wc_to_ibmf_status_end, IBMF_TNF_TRACE, "",
33000Sstevel@tonic-gate "ibmf_i_ibt_to_ibmf_status() exit, wc_status = %d, "
33010Sstevel@tonic-gate "ibmf_status = %d\n", tnf_uint, ibt_wc_status,
33020Sstevel@tonic-gate ibt_wc_status, tnf_int, ibmf_status, ibmf_status);
33030Sstevel@tonic-gate
33040Sstevel@tonic-gate return (ibmf_status);
33050Sstevel@tonic-gate }
33060Sstevel@tonic-gate
33070Sstevel@tonic-gate /*
33080Sstevel@tonic-gate * ibmf_i_is_ibmf_handle_valid():
33090Sstevel@tonic-gate * Validate the ibmf handle
33100Sstevel@tonic-gate */
33110Sstevel@tonic-gate int
ibmf_i_is_ibmf_handle_valid(ibmf_handle_t ibmf_handle)33120Sstevel@tonic-gate ibmf_i_is_ibmf_handle_valid(ibmf_handle_t ibmf_handle)
33130Sstevel@tonic-gate {
33140Sstevel@tonic-gate ibmf_ci_t *cip;
33150Sstevel@tonic-gate ibmf_client_t *clp, *clientp = (ibmf_client_t *)ibmf_handle;
33160Sstevel@tonic-gate
33170Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
33180Sstevel@tonic-gate ibmf_i_is_ibmf_handle_valid_start, IBMF_TNF_TRACE, "",
33190Sstevel@tonic-gate "ibmf_i_is_ibmf_handle_valid() enter\n");
33200Sstevel@tonic-gate
33210Sstevel@tonic-gate mutex_enter(&ibmf_statep->ibmf_mutex);
33220Sstevel@tonic-gate
33230Sstevel@tonic-gate cip = ibmf_statep->ibmf_ci_list;
33240Sstevel@tonic-gate
33250Sstevel@tonic-gate /* iterate through all the channel interace contexts */
33260Sstevel@tonic-gate while (cip != NULL) {
33270Sstevel@tonic-gate
33280Sstevel@tonic-gate mutex_enter(&cip->ci_clients_mutex);
33290Sstevel@tonic-gate
33300Sstevel@tonic-gate clp = cip->ci_clients;
33310Sstevel@tonic-gate
33320Sstevel@tonic-gate /* search all registration contexts for this ci */
33330Sstevel@tonic-gate while (clp != NULL) {
33340Sstevel@tonic-gate if (clp == clientp)
33350Sstevel@tonic-gate break;
33360Sstevel@tonic-gate clp = clp->ic_next;
33370Sstevel@tonic-gate }
33380Sstevel@tonic-gate
33390Sstevel@tonic-gate mutex_exit(&cip->ci_clients_mutex);
33400Sstevel@tonic-gate
33410Sstevel@tonic-gate if (clp == clientp) {
33420Sstevel@tonic-gate /* ci found */
33430Sstevel@tonic-gate break;
33440Sstevel@tonic-gate } else {
33450Sstevel@tonic-gate /* ci not found, move onto next ci */
33460Sstevel@tonic-gate cip = cip->ci_next;
33470Sstevel@tonic-gate }
33480Sstevel@tonic-gate }
33490Sstevel@tonic-gate
33500Sstevel@tonic-gate mutex_exit(&ibmf_statep->ibmf_mutex);
33510Sstevel@tonic-gate
33520Sstevel@tonic-gate if (cip != NULL) {
33530Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
33540Sstevel@tonic-gate ibmf_i_is_ibmf_handle_valid_end, IBMF_TNF_TRACE, "",
33550Sstevel@tonic-gate "ibmf_i_is_ibmf_handle_valid() exit\n");
33560Sstevel@tonic-gate return (IBMF_SUCCESS);
33570Sstevel@tonic-gate } else {
33580Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
33590Sstevel@tonic-gate ibmf_i_is_ibmf_handle_valid_end, IBMF_TNF_TRACE, "",
33600Sstevel@tonic-gate "ibmf_i_is_ibmf_handle_valid() failure exit\n");
33610Sstevel@tonic-gate return (IBMF_FAILURE);
33620Sstevel@tonic-gate }
33630Sstevel@tonic-gate }
33640Sstevel@tonic-gate
33650Sstevel@tonic-gate /*
33660Sstevel@tonic-gate * ibmf_i_is_qp_handle_valid():
33670Sstevel@tonic-gate * Validate the QP handle
33680Sstevel@tonic-gate */
33690Sstevel@tonic-gate int
ibmf_i_is_qp_handle_valid(ibmf_handle_t ibmf_handle,ibmf_qp_handle_t ibmf_qp_handle)33700Sstevel@tonic-gate ibmf_i_is_qp_handle_valid(ibmf_handle_t ibmf_handle,
33710Sstevel@tonic-gate ibmf_qp_handle_t ibmf_qp_handle)
33720Sstevel@tonic-gate {
33730Sstevel@tonic-gate ibmf_client_t *clientp = (ibmf_client_t *)ibmf_handle;
33740Sstevel@tonic-gate ibmf_alt_qp_t *alt_qp, *qpp = (ibmf_alt_qp_t *)ibmf_qp_handle;
33750Sstevel@tonic-gate ibmf_ci_t *cip = clientp->ic_myci;
33760Sstevel@tonic-gate
33770Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
33780Sstevel@tonic-gate ibmf_i_is_qp_handle_valid_start, IBMF_TNF_TRACE, "",
33790Sstevel@tonic-gate "ibmf_i_is_qp_handle_valid() enter\n");
33800Sstevel@tonic-gate
33810Sstevel@tonic-gate /* the default qp handle is always valid */
33820Sstevel@tonic-gate if (ibmf_qp_handle == IBMF_QP_HANDLE_DEFAULT)
33830Sstevel@tonic-gate return (IBMF_SUCCESS);
33840Sstevel@tonic-gate
33850Sstevel@tonic-gate mutex_enter(&cip->ci_mutex);
33860Sstevel@tonic-gate
33870Sstevel@tonic-gate alt_qp = cip->ci_alt_qp_list;
33880Sstevel@tonic-gate
33890Sstevel@tonic-gate while (alt_qp != NULL) {
33900Sstevel@tonic-gate if (alt_qp == qpp) {
33910Sstevel@tonic-gate /* qp handle found */
33920Sstevel@tonic-gate break;
33930Sstevel@tonic-gate } else {
33940Sstevel@tonic-gate /* qp handle not found, get next qp on list */
33950Sstevel@tonic-gate alt_qp = alt_qp->isq_next;
33960Sstevel@tonic-gate }
33970Sstevel@tonic-gate }
33980Sstevel@tonic-gate
33990Sstevel@tonic-gate mutex_exit(&cip->ci_mutex);
34000Sstevel@tonic-gate
34010Sstevel@tonic-gate if (alt_qp != NULL) {
34020Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
34030Sstevel@tonic-gate ibmf_i_is_qp_handle_valid_end, IBMF_TNF_TRACE, "",
34040Sstevel@tonic-gate "ibmf_i_is_qp_handle_valid() exit\n");
34050Sstevel@tonic-gate return (IBMF_SUCCESS);
34060Sstevel@tonic-gate } else {
34070Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
34080Sstevel@tonic-gate ibmf_i_is_qp_handle_valid_end, IBMF_TNF_TRACE, "",
34090Sstevel@tonic-gate "ibmf_i_is_qp_handle_valid() failure exit\n");
34100Sstevel@tonic-gate return (IBMF_FAILURE);
34110Sstevel@tonic-gate }
34120Sstevel@tonic-gate }
34130Sstevel@tonic-gate
34140Sstevel@tonic-gate void
ibmf_dprintf(int l,const char * fmt,...)34150Sstevel@tonic-gate ibmf_dprintf(int l, const char *fmt, ...)
34160Sstevel@tonic-gate {
34170Sstevel@tonic-gate va_list ap;
34180Sstevel@tonic-gate
34190Sstevel@tonic-gate if ((l) > ibmf_trace_level) {
34200Sstevel@tonic-gate
34210Sstevel@tonic-gate return;
34220Sstevel@tonic-gate }
34230Sstevel@tonic-gate
34240Sstevel@tonic-gate va_start(ap, fmt);
34250Sstevel@tonic-gate (void) vprintf(fmt, ap);
34260Sstevel@tonic-gate va_end(ap);
34270Sstevel@tonic-gate }
34280Sstevel@tonic-gate
34290Sstevel@tonic-gate /*
34300Sstevel@tonic-gate * ibmf_setup_term_ctx():
34310Sstevel@tonic-gate * Sets up a message context that is the duplicate of the one
34320Sstevel@tonic-gate * passed in the regmsgimplp argument. The duplicate message context
34330Sstevel@tonic-gate * is not visible to the client. It is managed internally by ibmf
34340Sstevel@tonic-gate * to process the RMPP receiver termination flow logic for the
34350Sstevel@tonic-gate * transaction while the client is notified of the completion of the
34360Sstevel@tonic-gate * same transaction (i.e. all the solicited data has been received).
34370Sstevel@tonic-gate */
34380Sstevel@tonic-gate int
ibmf_setup_term_ctx(ibmf_client_t * clientp,ibmf_msg_impl_t * regmsgimplp)34390Sstevel@tonic-gate ibmf_setup_term_ctx(ibmf_client_t *clientp, ibmf_msg_impl_t *regmsgimplp)
34400Sstevel@tonic-gate {
34410Sstevel@tonic-gate ibmf_msg_impl_t *msgimplp;
34420Sstevel@tonic-gate size_t offset;
34430Sstevel@tonic-gate uint32_t cl_hdr_sz, cl_hdr_off;
34440Sstevel@tonic-gate int status;
34450Sstevel@tonic-gate
34460Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
34470Sstevel@tonic-gate ibmf_setup_term_ctx_start, IBMF_TNF_TRACE, "",
34480Sstevel@tonic-gate "ibmf_setup_term_ctx() enter\n");
34490Sstevel@tonic-gate
34500Sstevel@tonic-gate /*
34510Sstevel@tonic-gate * Allocate the termination message context
34520Sstevel@tonic-gate */
34530Sstevel@tonic-gate msgimplp = (ibmf_msg_impl_t *)kmem_zalloc(sizeof (ibmf_msg_impl_t),
34540Sstevel@tonic-gate KM_NOSLEEP);
34550Sstevel@tonic-gate if (msgimplp == NULL) {
34560Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
34570Sstevel@tonic-gate ibmf_setup_term_ctx_error, IBMF_TNF_ERROR, "",
34580Sstevel@tonic-gate "ibmf_setup_term_ctx(): %s\n", tnf_string, msg,
34590Sstevel@tonic-gate "message mem allocation failure");
34600Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
34610Sstevel@tonic-gate ibmf_setup_term_ctx_end, IBMF_TNF_TRACE, "",
34620Sstevel@tonic-gate "ibmf_setup_term_ctx() exit\n");
34630Sstevel@tonic-gate return (IBMF_NO_RESOURCES);
34640Sstevel@tonic-gate }
34650Sstevel@tonic-gate
34660Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*msgimplp))
34670Sstevel@tonic-gate
34680Sstevel@tonic-gate /* Copy the message context to the termination message structure */
34690Sstevel@tonic-gate *msgimplp = *regmsgimplp;
34700Sstevel@tonic-gate
34710Sstevel@tonic-gate /* Initialize the message mutex */
34720Sstevel@tonic-gate mutex_init(&msgimplp->im_mutex, NULL, MUTEX_DRIVER, NULL);
34730Sstevel@tonic-gate
34740Sstevel@tonic-gate /*
34750Sstevel@tonic-gate * Allocate enough memory for the MAD header only.
34760Sstevel@tonic-gate */
34770Sstevel@tonic-gate msgimplp->im_msgbufs_recv.im_bufs_mad_hdr =
34780Sstevel@tonic-gate (ib_mad_hdr_t *)kmem_zalloc(IBMF_MAD_SIZE, KM_NOSLEEP);
34790Sstevel@tonic-gate if (msgimplp->im_msgbufs_recv.im_bufs_mad_hdr == NULL) {
34800Sstevel@tonic-gate kmem_free(msgimplp, sizeof (ibmf_msg_impl_t));
34810Sstevel@tonic-gate IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
34820Sstevel@tonic-gate ibmf_setup_term_ctx_error, IBMF_TNF_ERROR, "",
34830Sstevel@tonic-gate "ibmf_setup_term_ctx(): %s\n", tnf_string, msg,
34840Sstevel@tonic-gate "recv buf mem allocation failure");
34850Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
34860Sstevel@tonic-gate ibmf_setup_term_ctx_end, IBMF_TNF_TRACE, "",
34870Sstevel@tonic-gate "ibmf_setup_term_ctx() exit\n");
34880Sstevel@tonic-gate return (IBMF_NO_RESOURCES);
34890Sstevel@tonic-gate }
34900Sstevel@tonic-gate
34910Sstevel@tonic-gate /* Copy over just the MAD header contents */
34920Sstevel@tonic-gate bcopy((const void *)regmsgimplp->im_msgbufs_recv.im_bufs_mad_hdr,
34930Sstevel@tonic-gate (void *)msgimplp->im_msgbufs_recv.im_bufs_mad_hdr,
34940Sstevel@tonic-gate sizeof (ib_mad_hdr_t));
34950Sstevel@tonic-gate
34960Sstevel@tonic-gate offset = sizeof (ib_mad_hdr_t);
34970Sstevel@tonic-gate ibmf_i_mgt_class_to_hdr_sz_off(
34980Sstevel@tonic-gate regmsgimplp->im_msgbufs_recv.im_bufs_mad_hdr->MgmtClass,
34990Sstevel@tonic-gate &cl_hdr_sz, &cl_hdr_off);
35000Sstevel@tonic-gate offset += cl_hdr_off;
35010Sstevel@tonic-gate
35020Sstevel@tonic-gate /*
35030Sstevel@tonic-gate * Copy the management class header
35040Sstevel@tonic-gate */
35050Sstevel@tonic-gate msgimplp->im_msgbufs_recv.im_bufs_cl_hdr =
35060Sstevel@tonic-gate (uchar_t *)msgimplp->im_msgbufs_recv.im_bufs_mad_hdr + offset;
35070Sstevel@tonic-gate msgimplp->im_msgbufs_recv.im_bufs_cl_hdr_len =
35080Sstevel@tonic-gate regmsgimplp->im_msgbufs_recv.im_bufs_cl_hdr_len;
35090Sstevel@tonic-gate bcopy((void *)regmsgimplp->im_msgbufs_recv.im_bufs_cl_hdr,
35100Sstevel@tonic-gate (void *)msgimplp->im_msgbufs_recv.im_bufs_cl_hdr,
35110Sstevel@tonic-gate regmsgimplp->im_msgbufs_recv.im_bufs_cl_hdr_len);
35120Sstevel@tonic-gate
35130Sstevel@tonic-gate /*
35140Sstevel@tonic-gate * Clear the termination message timers copied from the regular message
35150Sstevel@tonic-gate * since ibmf_i_set_timer() expects them to be cleared.
35160Sstevel@tonic-gate */
35170Sstevel@tonic-gate msgimplp->im_rp_timeout_id = 0;
35180Sstevel@tonic-gate msgimplp->im_tr_timeout_id = 0;
35190Sstevel@tonic-gate
35200Sstevel@tonic-gate /* Mark this message as being in a receiver RMPP mode */
35210Sstevel@tonic-gate msgimplp->im_flags |= IBMF_MSG_FLAGS_RECV_RMPP;
35220Sstevel@tonic-gate
35230Sstevel@tonic-gate /* Mark this message as being a "termination flow" message */
35240Sstevel@tonic-gate msgimplp->im_flags |= IBMF_MSG_FLAGS_TERMINATION;
35250Sstevel@tonic-gate
35260Sstevel@tonic-gate /*
35270Sstevel@tonic-gate * Clear the IBMF_MSG_FLAGS_SET_TERMINATION copied over from the regular
35280Sstevel@tonic-gate * message.
35290Sstevel@tonic-gate */
35300Sstevel@tonic-gate msgimplp->im_flags &= ~IBMF_MSG_FLAGS_SET_TERMINATION;
35310Sstevel@tonic-gate
35320Sstevel@tonic-gate /*
35330Sstevel@tonic-gate * Clear the trans_state RECV_DONE and DONE flags so that the
35340Sstevel@tonic-gate * protocol continues with the termination message context.
35350Sstevel@tonic-gate */
35360Sstevel@tonic-gate msgimplp->im_trans_state_flags &= ~IBMF_TRANS_STATE_FLAG_RECV_DONE;
35370Sstevel@tonic-gate msgimplp->im_trans_state_flags &= ~IBMF_TRANS_STATE_FLAG_DONE;
35380Sstevel@tonic-gate
35390Sstevel@tonic-gate /* Clear out references to the old UD dest handles */
35400Sstevel@tonic-gate msgimplp->im_ibmf_ud_dest = NULL;
35410Sstevel@tonic-gate msgimplp->im_ud_dest = NULL;
35420Sstevel@tonic-gate
35430Sstevel@tonic-gate /*
35440Sstevel@tonic-gate * Request new UD dest resources for the termination phase.
35450Sstevel@tonic-gate * The old UD dest resources are freed when the IBMF client
35460Sstevel@tonic-gate * calls ibmf_free_msg(), so they cannot be relied on to exist
35470Sstevel@tonic-gate * when the RMPP termination loop completes.
35480Sstevel@tonic-gate */
35490Sstevel@tonic-gate status = ibmf_i_alloc_ud_dest(clientp, msgimplp, &msgimplp->im_ud_dest,
35500Sstevel@tonic-gate B_FALSE);
35510Sstevel@tonic-gate if (status != IBMF_SUCCESS) {
35520Sstevel@tonic-gate kmem_free(msgimplp, sizeof (ibmf_msg_impl_t));
35530Sstevel@tonic-gate IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
35540Sstevel@tonic-gate ibmf_setup_term_ctx_err, IBMF_TNF_ERROR, "",
35550Sstevel@tonic-gate "ibmf_setup_term_ctx(): %s, status = %d\n",
35560Sstevel@tonic-gate tnf_string, msg, "UD destination resource allocation"
35570Sstevel@tonic-gate " failed", tnf_int, ibmf_status, status);
35580Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
35590Sstevel@tonic-gate ibmf_setup_term_ctx_end, IBMF_TNF_TRACE, "",
35600Sstevel@tonic-gate "ibmf_setup_term_ctx() exit\n");
35610Sstevel@tonic-gate return (status);
35620Sstevel@tonic-gate }
35630Sstevel@tonic-gate
35640Sstevel@tonic-gate /*
35650Sstevel@tonic-gate * Add the message to the termination client list by virtue of
35660Sstevel@tonic-gate * having the IBMF_MSG_FLAGS_TERMINATION "im_flags" flag set.
35670Sstevel@tonic-gate */
35680Sstevel@tonic-gate ibmf_i_client_add_msg(clientp, msgimplp);
35690Sstevel@tonic-gate
35700Sstevel@tonic-gate /*
35710Sstevel@tonic-gate * Increase the "allocted messages" count so that the client
35720Sstevel@tonic-gate * does not unregister before this message has been freed.
35730Sstevel@tonic-gate * This is necessary because we want the client context to
35740Sstevel@tonic-gate * be around when the receive timeout expires for this termination
35750Sstevel@tonic-gate * loop, otherwise the code will access freed memory and crash.
35760Sstevel@tonic-gate */
35770Sstevel@tonic-gate mutex_enter(&clientp->ic_mutex);
35780Sstevel@tonic-gate clientp->ic_msgs_alloced++;
35790Sstevel@tonic-gate mutex_exit(&clientp->ic_mutex);
35800Sstevel@tonic-gate
35810Sstevel@tonic-gate mutex_enter(&msgimplp->im_mutex);
35820Sstevel@tonic-gate /* Set the response timer for the termination message. */
35830Sstevel@tonic-gate ibmf_i_set_timer(ibmf_i_recv_timeout, msgimplp, IBMF_RESP_TIMER);
35840Sstevel@tonic-gate mutex_exit(&msgimplp->im_mutex);
35850Sstevel@tonic-gate
35860Sstevel@tonic-gate IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_setup_term_ctx_end,
35870Sstevel@tonic-gate IBMF_TNF_TRACE, "", "ibmf_setup_term_ctx() exit\n");
35880Sstevel@tonic-gate
35890Sstevel@tonic-gate return (IBMF_SUCCESS);
35900Sstevel@tonic-gate }
3591