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
51495Shiremath * Common Development and Distribution License (the "License").
61495Shiremath * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
228580SBill.Taylor@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate /*
270Sstevel@tonic-gate * ibcm_impl.c
280Sstevel@tonic-gate *
290Sstevel@tonic-gate * contains internal functions of IB CM module.
300Sstevel@tonic-gate *
310Sstevel@tonic-gate * TBD:
320Sstevel@tonic-gate * 1. HCA CATASTROPHIC/RECOVERED not handled yet
330Sstevel@tonic-gate */
340Sstevel@tonic-gate
350Sstevel@tonic-gate #include <sys/ib/mgt/ibcm/ibcm_impl.h>
360Sstevel@tonic-gate #include <sys/disp.h>
370Sstevel@tonic-gate
380Sstevel@tonic-gate
390Sstevel@tonic-gate /* function prototypes */
400Sstevel@tonic-gate static ibcm_status_t ibcm_init(void);
410Sstevel@tonic-gate static ibcm_status_t ibcm_fini(void);
420Sstevel@tonic-gate
43*9913SShantkumar.Hiremath@Sun.COM /* Routines to initialize and destroy CM global locks and CVs */
440Sstevel@tonic-gate static void ibcm_init_locks(void);
450Sstevel@tonic-gate static void ibcm_fini_locks(void);
460Sstevel@tonic-gate
470Sstevel@tonic-gate /* Routines that initialize/teardown CM's global hca structures */
480Sstevel@tonic-gate static void ibcm_init_hcas();
490Sstevel@tonic-gate static ibcm_status_t ibcm_fini_hcas();
500Sstevel@tonic-gate
510Sstevel@tonic-gate static void ibcm_init_classportinfo();
520Sstevel@tonic-gate static void ibcm_stop_timeout_thread();
530Sstevel@tonic-gate
540Sstevel@tonic-gate /* Routines that handle HCA attach/detach asyncs */
550Sstevel@tonic-gate static void ibcm_hca_attach(ib_guid_t);
560Sstevel@tonic-gate static ibcm_status_t ibcm_hca_detach(ibcm_hca_info_t *);
570Sstevel@tonic-gate
580Sstevel@tonic-gate /* Routines that initialize the HCA's port related fields */
590Sstevel@tonic-gate static ibt_status_t ibcm_hca_init_port(ibcm_hca_info_t *hcap,
600Sstevel@tonic-gate uint8_t port_index);
610Sstevel@tonic-gate static ibcm_status_t ibcm_hca_fini_port(ibcm_hca_info_t *hcap,
620Sstevel@tonic-gate uint8_t port_index);
630Sstevel@tonic-gate
64557Shiremath static void ibcm_rc_flow_control_init(void);
65557Shiremath static void ibcm_rc_flow_control_fini(void);
66557Shiremath
670Sstevel@tonic-gate /*
680Sstevel@tonic-gate * Routines that check if hca's avl trees and sidr lists are free of any
690Sstevel@tonic-gate * active client resources ie., RC or UD state structures in certain states
700Sstevel@tonic-gate */
710Sstevel@tonic-gate static ibcm_status_t ibcm_check_avl_clean(ibcm_hca_info_t *hcap);
720Sstevel@tonic-gate static ibcm_status_t ibcm_check_sidr_clean(ibcm_hca_info_t *hcap);
730Sstevel@tonic-gate
740Sstevel@tonic-gate /* Add a new hca structure to CM's global hca list */
750Sstevel@tonic-gate static ibcm_hca_info_t *ibcm_add_hca_entry(ib_guid_t hcaguid, uint_t nports);
760Sstevel@tonic-gate
770Sstevel@tonic-gate static void ibcm_comm_est_handler(ibt_async_event_t *);
780Sstevel@tonic-gate void ibcm_async_handler(void *, ibt_hca_hdl_t,
790Sstevel@tonic-gate ibt_async_code_t, ibt_async_event_t *);
800Sstevel@tonic-gate
810Sstevel@tonic-gate /* Global variables */
820Sstevel@tonic-gate char cmlog[] = "ibcm"; /* for debug log messages */
830Sstevel@tonic-gate ibt_clnt_hdl_t ibcm_ibt_handle; /* IBT handle */
840Sstevel@tonic-gate kmutex_t ibcm_svc_info_lock; /* list lock */
850Sstevel@tonic-gate kcondvar_t ibcm_svc_info_cv; /* cv for deregister */
860Sstevel@tonic-gate kmutex_t ibcm_recv_mutex;
870Sstevel@tonic-gate avl_tree_t ibcm_svc_avl_tree;
880Sstevel@tonic-gate taskq_t *ibcm_taskq = NULL;
890Sstevel@tonic-gate int taskq_dispatch_fail_cnt;
900Sstevel@tonic-gate
91*9913SShantkumar.Hiremath@Sun.COM kmutex_t ibcm_mcglist_lock; /* MCG list lock */
920Sstevel@tonic-gate kmutex_t ibcm_trace_mutex; /* Trace mutex */
930Sstevel@tonic-gate kmutex_t ibcm_trace_print_mutex; /* Trace print mutex */
940Sstevel@tonic-gate int ibcm_conn_max_trcnt = IBCM_MAX_CONN_TRCNT;
950Sstevel@tonic-gate
961093Shiremath int ibcm_enable_trace = 2; /* Trace level 4 by default */
971093Shiremath int ibcm_dtrace = 0; /* conditionally enable more dtrace */
980Sstevel@tonic-gate
990Sstevel@tonic-gate _NOTE(MUTEX_PROTECTS_DATA(ibcm_svc_info_lock, ibcm_svc_info_s::{svc_bind_list
1000Sstevel@tonic-gate svc_ref_cnt svc_to_delete}))
1010Sstevel@tonic-gate
1020Sstevel@tonic-gate _NOTE(MUTEX_PROTECTS_DATA(ibcm_svc_info_lock, ibcm_svc_bind_s::{sbind_link}))
1030Sstevel@tonic-gate
1040Sstevel@tonic-gate _NOTE(MUTEX_PROTECTS_DATA(ibcm_trace_mutex, ibcm_conn_trace_s))
1050Sstevel@tonic-gate
1060Sstevel@tonic-gate _NOTE(DATA_READABLE_WITHOUT_LOCK(ibcm_conn_trace_s))
1070Sstevel@tonic-gate
1080Sstevel@tonic-gate _NOTE(MUTEX_PROTECTS_DATA(ibcm_trace_print_mutex, ibcm_debug_buf))
1090Sstevel@tonic-gate
1100Sstevel@tonic-gate _NOTE(DATA_READABLE_WITHOUT_LOCK(ibcm_debug_buf))
1110Sstevel@tonic-gate
1120Sstevel@tonic-gate /*
1130Sstevel@tonic-gate * Initial state is INIT. All hca dr's return success immediately in this
1140Sstevel@tonic-gate * state, without adding or deleting any hca's to CM.
1150Sstevel@tonic-gate */
1160Sstevel@tonic-gate ibcm_finit_state_t ibcm_finit_state = IBCM_FINIT_INIT;
1170Sstevel@tonic-gate
1180Sstevel@tonic-gate /* mutex and cv to manage hca's reference and resource count(s) */
1190Sstevel@tonic-gate kmutex_t ibcm_global_hca_lock;
1200Sstevel@tonic-gate kcondvar_t ibcm_global_hca_cv;
1210Sstevel@tonic-gate
1220Sstevel@tonic-gate /* mutex and cv to sa session open */
1230Sstevel@tonic-gate kmutex_t ibcm_sa_open_lock;
1240Sstevel@tonic-gate kcondvar_t ibcm_sa_open_cv;
1250Sstevel@tonic-gate int ibcm_sa_timeout_delay = 1; /* in ticks */
1260Sstevel@tonic-gate _NOTE(MUTEX_PROTECTS_DATA(ibcm_sa_open_lock,
1270Sstevel@tonic-gate ibcm_port_info_s::{port_ibmf_saa_hdl port_saa_open_in_progress}))
1280Sstevel@tonic-gate
1290Sstevel@tonic-gate _NOTE(DATA_READABLE_WITHOUT_LOCK(ibcm_port_info_s::{port_ibmf_saa_hdl}))
1300Sstevel@tonic-gate
1310Sstevel@tonic-gate /* serialize sm notice callbacks */
1320Sstevel@tonic-gate kmutex_t ibcm_sm_notice_serialize_lock;
1330Sstevel@tonic-gate
1340Sstevel@tonic-gate _NOTE(LOCK_ORDER(ibcm_sm_notice_serialize_lock ibcm_global_hca_lock))
1350Sstevel@tonic-gate
1360Sstevel@tonic-gate _NOTE(MUTEX_PROTECTS_DATA(ibcm_global_hca_lock, ibcm_hca_info_s::{hca_state
1370Sstevel@tonic-gate hca_svc_cnt hca_acc_cnt hca_res_cnt hca_next}))
1380Sstevel@tonic-gate
1390Sstevel@tonic-gate _NOTE(MUTEX_PROTECTS_DATA(ibcm_global_hca_lock,
1400Sstevel@tonic-gate ibcm_port_info_s::{port_ibmf_hdl}))
1410Sstevel@tonic-gate
1420Sstevel@tonic-gate _NOTE(MUTEX_PROTECTS_DATA(ibcm_sm_notice_serialize_lock,
1430Sstevel@tonic-gate ibcm_port_info_s::{port_event_status}))
1440Sstevel@tonic-gate
1450Sstevel@tonic-gate _NOTE(DATA_READABLE_WITHOUT_LOCK(ibcm_hca_info_s::{hca_state}))
1460Sstevel@tonic-gate _NOTE(DATA_READABLE_WITHOUT_LOCK(
1470Sstevel@tonic-gate ibcm_hca_info_s::{hca_port_info.port_ibmf_hdl}))
1480Sstevel@tonic-gate
1490Sstevel@tonic-gate /* mutex for CM's qp list management */
1500Sstevel@tonic-gate kmutex_t ibcm_qp_list_lock;
1510Sstevel@tonic-gate
1520Sstevel@tonic-gate _NOTE(MUTEX_PROTECTS_DATA(ibcm_qp_list_lock, ibcm_port_info_s::{port_qplist}))
1530Sstevel@tonic-gate _NOTE(MUTEX_PROTECTS_DATA(ibcm_qp_list_lock, ibcm_qp_list_s))
1540Sstevel@tonic-gate _NOTE(MUTEX_PROTECTS_DATA(ibcm_qp_list_lock, ibcm_qp_list_s))
1550Sstevel@tonic-gate
1560Sstevel@tonic-gate kcondvar_t ibcm_timeout_list_cv;
1570Sstevel@tonic-gate kcondvar_t ibcm_timeout_thread_done_cv;
1580Sstevel@tonic-gate kt_did_t ibcm_timeout_thread_did;
1590Sstevel@tonic-gate ibcm_state_data_t *ibcm_timeout_list_hdr, *ibcm_timeout_list_tail;
1600Sstevel@tonic-gate ibcm_ud_state_data_t *ibcm_ud_timeout_list_hdr, *ibcm_ud_timeout_list_tail;
1610Sstevel@tonic-gate kmutex_t ibcm_timeout_list_lock;
1620Sstevel@tonic-gate uint8_t ibcm_timeout_list_flags = 0;
1630Sstevel@tonic-gate pri_t ibcm_timeout_thread_pri = MINCLSYSPRI;
1640Sstevel@tonic-gate
1650Sstevel@tonic-gate _NOTE(MUTEX_PROTECTS_DATA(ibcm_timeout_list_lock,
1660Sstevel@tonic-gate ibcm_state_data_s::timeout_next))
1670Sstevel@tonic-gate
1680Sstevel@tonic-gate _NOTE(MUTEX_PROTECTS_DATA(ibcm_timeout_list_lock,
1690Sstevel@tonic-gate ibcm_ud_state_data_s::ud_timeout_next))
1700Sstevel@tonic-gate
1711093Shiremath /*
1721093Shiremath * Flow control logic for open_rc_channel uses the following.
1731093Shiremath */
1741093Shiremath
1751093Shiremath struct ibcm_open_s {
1761093Shiremath kmutex_t mutex;
1771093Shiremath kcondvar_t cv;
1781093Shiremath uint8_t task_running;
1791093Shiremath uint_t queued;
1801093Shiremath uint_t exit_deferred;
1811093Shiremath uint_t in_progress;
1821093Shiremath uint_t in_progress_max;
1831093Shiremath uint_t sends;
1841093Shiremath uint_t sends_max;
1851093Shiremath uint_t sends_lowat;
1861093Shiremath uint_t sends_hiwat;
1871093Shiremath ibcm_state_data_t *tail;
1881093Shiremath ibcm_state_data_t head;
1891093Shiremath } ibcm_open;
1901093Shiremath
1911093Shiremath /*
1921093Shiremath * Flow control logic for SA access and close_rc_channel calls follows.
1931093Shiremath */
1941093Shiremath
1951093Shiremath int ibcm_close_simul_max = 12;
1961093Shiremath int ibcm_lapr_simul_max = 12;
1971093Shiremath int ibcm_saa_simul_max = 8;
1981093Shiremath
1991093Shiremath typedef struct ibcm_flow1_s {
2001093Shiremath struct ibcm_flow1_s *link;
2011093Shiremath kcondvar_t cv;
2021093Shiremath uint8_t waiters; /* 1 to IBCM_FLOW_SIMUL_MAX */
2031093Shiremath } ibcm_flow1_t;
2041093Shiremath
2051093Shiremath typedef struct ibcm_flow_s {
2061093Shiremath ibcm_flow1_t *list;
2071093Shiremath uint_t simul; /* #requests currently outstanding */
2081093Shiremath uint_t simul_max;
2091093Shiremath uint_t waiters_per_chunk;
2101093Shiremath uint_t lowat;
2111093Shiremath uint_t lowat_default;
2121093Shiremath /* statistics */
2131093Shiremath uint_t total;
2141093Shiremath } ibcm_flow_t;
2151093Shiremath
2161093Shiremath ibcm_flow_t ibcm_saa_flow;
2171093Shiremath ibcm_flow_t ibcm_close_flow;
2181093Shiremath ibcm_flow_t ibcm_lapr_flow;
2191093Shiremath
2203241Shiremath /* NONBLOCKING close requests are queued */
2213241Shiremath struct ibcm_close_s {
2223241Shiremath kmutex_t mutex;
2233241Shiremath ibcm_state_data_t *tail;
2243241Shiremath ibcm_state_data_t head;
2253241Shiremath } ibcm_close;
2263241Shiremath
2270Sstevel@tonic-gate static ibt_clnt_modinfo_t ibcm_ibt_modinfo = { /* Client's modinfop */
2288580SBill.Taylor@Sun.COM IBTI_V_CURR,
2290Sstevel@tonic-gate IBT_CM,
2300Sstevel@tonic-gate ibcm_async_handler,
2310Sstevel@tonic-gate NULL,
2320Sstevel@tonic-gate "IBCM"
2330Sstevel@tonic-gate };
2340Sstevel@tonic-gate
2350Sstevel@tonic-gate /* IBCM's list of HCAs registered with it */
2360Sstevel@tonic-gate static ibcm_hca_info_t *ibcm_hca_listp = NULL; /* CM's HCA list */
2370Sstevel@tonic-gate
2380Sstevel@tonic-gate /* Array of CM state call table functions */
2390Sstevel@tonic-gate ibcm_state_handler_t ibcm_sm_funcs_tbl[] = {
2400Sstevel@tonic-gate ibcm_process_req_msg,
2410Sstevel@tonic-gate ibcm_process_mra_msg,
2420Sstevel@tonic-gate ibcm_process_rej_msg,
2430Sstevel@tonic-gate ibcm_process_rep_msg,
2440Sstevel@tonic-gate ibcm_process_rtu_msg,
2450Sstevel@tonic-gate ibcm_process_dreq_msg,
2460Sstevel@tonic-gate ibcm_process_drep_msg,
2470Sstevel@tonic-gate ibcm_process_sidr_req_msg,
2480Sstevel@tonic-gate ibcm_process_sidr_rep_msg,
2490Sstevel@tonic-gate ibcm_process_lap_msg,
2500Sstevel@tonic-gate ibcm_process_apr_msg
2510Sstevel@tonic-gate };
2520Sstevel@tonic-gate
2530Sstevel@tonic-gate /* the following globals are CM tunables */
2540Sstevel@tonic-gate ibt_rnr_nak_time_t ibcm_default_rnr_nak_time = IBT_RNR_NAK_655ms;
2550Sstevel@tonic-gate
256*9913SShantkumar.Hiremath@Sun.COM uint8_t ibcm_max_retries = IBCM_MAX_RETRIES;
2570Sstevel@tonic-gate clock_t ibcm_local_processing_time = IBCM_LOCAL_RESPONSE_TIME;
2580Sstevel@tonic-gate clock_t ibcm_remote_response_time = IBCM_REMOTE_RESPONSE_TIME;
2590Sstevel@tonic-gate ib_time_t ibcm_max_sidr_rep_proctime = IBCM_MAX_SIDR_PROCESS_TIME;
2600Sstevel@tonic-gate ib_time_t ibcm_max_sidr_pktlife_time = IBCM_MAX_SIDR_PKT_LIFE_TIME;
2610Sstevel@tonic-gate
2620Sstevel@tonic-gate ib_time_t ibcm_max_sidr_rep_store_time = 18;
2638695SRajkumar.Sivaprakasam@Sun.COM uint32_t ibcm_wait_for_acc_cnt_timeout = 2000000; /* 2 sec */
2640Sstevel@tonic-gate
2650Sstevel@tonic-gate ib_time_t ibcm_max_ib_pkt_lt = IBCM_MAX_IB_PKT_LT;
2660Sstevel@tonic-gate ib_time_t ibcm_max_ib_mad_pkt_lt = IBCM_MAX_IB_MAD_PKT_LT;
2670Sstevel@tonic-gate
2680Sstevel@tonic-gate /*
2690Sstevel@tonic-gate * This delay accounts for time involved in various activities as follows :
2700Sstevel@tonic-gate *
2710Sstevel@tonic-gate * IBMF delays for posting the MADs in non-blocking mode
2720Sstevel@tonic-gate * IBMF delays for receiving the MADs and delivering to CM
2730Sstevel@tonic-gate * CM delays in processing the MADs before invoking client handlers,
2740Sstevel@tonic-gate * Any other delays associated with HCA driver in processing the MADs and
2750Sstevel@tonic-gate * other subsystems that CM may invoke (ex : SA, HCA driver)
2760Sstevel@tonic-gate */
2770Sstevel@tonic-gate uint32_t ibcm_sw_delay = 1000; /* 1000us / 1ms */
2780Sstevel@tonic-gate uint32_t ibcm_max_sa_retries = IBCM_MAX_SA_RETRIES + 1;
2790Sstevel@tonic-gate
2800Sstevel@tonic-gate /* approx boot time */
2810Sstevel@tonic-gate uint32_t ibcm_adj_btime = 4; /* 4 seconds */
2820Sstevel@tonic-gate
2830Sstevel@tonic-gate /*
2840Sstevel@tonic-gate * The information in ibcm_clpinfo is kept in wireformat and is setup at
2850Sstevel@tonic-gate * init time, and used read-only after that
2860Sstevel@tonic-gate */
2870Sstevel@tonic-gate ibcm_classportinfo_msg_t ibcm_clpinfo;
2880Sstevel@tonic-gate
2890Sstevel@tonic-gate char *event_str[] = {
2900Sstevel@tonic-gate "NEVER SEE THIS ",
2910Sstevel@tonic-gate "SESSION_ID ",
2920Sstevel@tonic-gate "CHAN_HDL ",
2930Sstevel@tonic-gate "LOCAL_COMID/HCA/PORT ",
2940Sstevel@tonic-gate "LOCAL_QPN ",
2950Sstevel@tonic-gate "REMOTE_COMID/HCA ",
2960Sstevel@tonic-gate "REMOTE_QPN ",
2970Sstevel@tonic-gate "BASE_TIME ",
2980Sstevel@tonic-gate "INCOMING_REQ ",
2990Sstevel@tonic-gate "INCOMING_REP ",
3000Sstevel@tonic-gate "INCOMING_RTU ",
3010Sstevel@tonic-gate "INCOMING_COMEST ",
3020Sstevel@tonic-gate "INCOMING_MRA ",
3030Sstevel@tonic-gate "INCOMING_REJ ",
3040Sstevel@tonic-gate "INCOMING_LAP ",
3050Sstevel@tonic-gate "INCOMING_APR ",
3060Sstevel@tonic-gate "INCOMING_DREQ ",
3070Sstevel@tonic-gate "INCOMING_DREP ",
3080Sstevel@tonic-gate "OUTGOING_REQ ",
3090Sstevel@tonic-gate "OUTGOING_REP ",
3100Sstevel@tonic-gate "OUTGOING_RTU ",
3110Sstevel@tonic-gate "OUTGOING_LAP ",
3120Sstevel@tonic-gate "OUTGOING_APR ",
3130Sstevel@tonic-gate "OUTGOING_MRA ",
3140Sstevel@tonic-gate "OUTGOING_REJ ",
3150Sstevel@tonic-gate "OUTGOING_DREQ ",
3160Sstevel@tonic-gate "OUTGOING_DREP ",
3170Sstevel@tonic-gate "REQ_POST_COMPLETE ",
3180Sstevel@tonic-gate "REP_POST_COMPLETE ",
3190Sstevel@tonic-gate "RTU_POST_COMPLETE ",
3200Sstevel@tonic-gate "MRA_POST_COMPLETE ",
3210Sstevel@tonic-gate "REJ_POST_COMPLETE ",
3220Sstevel@tonic-gate "LAP_POST_COMPLETE ",
3230Sstevel@tonic-gate "APR_POST_COMPLETE ",
3240Sstevel@tonic-gate "DREQ_POST_COMPLETE ",
3250Sstevel@tonic-gate "DREP_POST_COMPLETE ",
3260Sstevel@tonic-gate "TIMEOUT_REP ",
3270Sstevel@tonic-gate "CALLED_REQ_RCVD_EVENT ",
3280Sstevel@tonic-gate "RET_REQ_RCVD_EVENT ",
3290Sstevel@tonic-gate "CALLED_REP_RCVD_EVENT ",
3300Sstevel@tonic-gate "RET_REP_RCVD_EVENT ",
3310Sstevel@tonic-gate "CALLED_CONN_EST_EVENT ",
3320Sstevel@tonic-gate "RET_CONN_EST_EVENT ",
3330Sstevel@tonic-gate "CALLED_CONN_FAIL_EVENT ",
3340Sstevel@tonic-gate "RET_CONN_FAIL_EVENT ",
3350Sstevel@tonic-gate "CALLED_CONN_CLOSE_EVENT ",
3360Sstevel@tonic-gate "RET_CONN_CLOSE_EVENT ",
3370Sstevel@tonic-gate "INIT_INIT ",
3380Sstevel@tonic-gate "INIT_INIT_FAIL ",
3390Sstevel@tonic-gate "INIT_RTR ",
3400Sstevel@tonic-gate "INIT_RTR_FAIL ",
3410Sstevel@tonic-gate "RTR_RTS ",
3420Sstevel@tonic-gate "RTR_RTS_FAIL ",
3430Sstevel@tonic-gate "RTS_RTS ",
3440Sstevel@tonic-gate "RTS_RTS_FAIL ",
3450Sstevel@tonic-gate "TO_ERROR ",
3460Sstevel@tonic-gate "ERROR_FAIL ",
3470Sstevel@tonic-gate "SET_ALT ",
3480Sstevel@tonic-gate "SET_ALT_FAIL ",
3490Sstevel@tonic-gate "STALE_DETECT ",
3501093Shiremath "OUTGOING_REQ_RETRY ",
3511093Shiremath "OUTGOING_REP_RETRY ",
3521093Shiremath "OUTGOING_LAP_RETRY ",
3531093Shiremath "OUTGOING_MRA_RETRY ",
3541093Shiremath "OUTGOING_DREQ_RETRY ",
3550Sstevel@tonic-gate "NEVER SEE THIS "
3560Sstevel@tonic-gate };
3570Sstevel@tonic-gate
3580Sstevel@tonic-gate char ibcm_debug_buf[IBCM_DEBUG_BUF_SIZE];
3590Sstevel@tonic-gate
3600Sstevel@tonic-gate _NOTE(SCHEME_PROTECTS_DATA("used in a localized function consistently",
3610Sstevel@tonic-gate ibcm_debug_buf))
3620Sstevel@tonic-gate _NOTE(READ_ONLY_DATA(ibcm_taskq))
3630Sstevel@tonic-gate
3640Sstevel@tonic-gate _NOTE(MUTEX_PROTECTS_DATA(ibcm_timeout_list_lock, ibcm_timeout_list_flags))
3650Sstevel@tonic-gate _NOTE(MUTEX_PROTECTS_DATA(ibcm_timeout_list_lock, ibcm_timeout_list_hdr))
3660Sstevel@tonic-gate _NOTE(MUTEX_PROTECTS_DATA(ibcm_timeout_list_lock, ibcm_ud_timeout_list_hdr))
3670Sstevel@tonic-gate
3680Sstevel@tonic-gate #ifdef DEBUG
3690Sstevel@tonic-gate int ibcm_test_mode = 0; /* set to 1, if running tests */
3700Sstevel@tonic-gate #endif
3710Sstevel@tonic-gate
3720Sstevel@tonic-gate
3730Sstevel@tonic-gate /* Module Driver Info */
3740Sstevel@tonic-gate static struct modlmisc ibcm_modlmisc = {
3750Sstevel@tonic-gate &mod_miscops,
3767862SRichard.Bean@Sun.COM "IB Communication Manager"
3770Sstevel@tonic-gate };
3780Sstevel@tonic-gate
3790Sstevel@tonic-gate /* Module Linkage */
3800Sstevel@tonic-gate static struct modlinkage ibcm_modlinkage = {
3810Sstevel@tonic-gate MODREV_1,
3820Sstevel@tonic-gate &ibcm_modlmisc,
3830Sstevel@tonic-gate NULL
3840Sstevel@tonic-gate };
3850Sstevel@tonic-gate
3860Sstevel@tonic-gate
3870Sstevel@tonic-gate int
_init(void)3880Sstevel@tonic-gate _init(void)
3890Sstevel@tonic-gate {
3900Sstevel@tonic-gate int rval;
3910Sstevel@tonic-gate ibcm_status_t status;
3920Sstevel@tonic-gate
3930Sstevel@tonic-gate status = ibcm_init();
3940Sstevel@tonic-gate if (status != IBCM_SUCCESS) {
3950Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "_init: ibcm failed %d", status);
3960Sstevel@tonic-gate return (EINVAL);
3970Sstevel@tonic-gate }
3980Sstevel@tonic-gate
3990Sstevel@tonic-gate rval = mod_install(&ibcm_modlinkage);
4000Sstevel@tonic-gate if (rval != 0) {
4010Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "_init: ibcm mod_install failed %d",
4020Sstevel@tonic-gate rval);
4030Sstevel@tonic-gate (void) ibcm_fini();
4040Sstevel@tonic-gate }
4050Sstevel@tonic-gate
4060Sstevel@tonic-gate IBTF_DPRINTF_L5(cmlog, "_init: ibcm successful");
4070Sstevel@tonic-gate return (rval);
4080Sstevel@tonic-gate
4090Sstevel@tonic-gate }
4100Sstevel@tonic-gate
4110Sstevel@tonic-gate
4120Sstevel@tonic-gate int
_info(struct modinfo * modinfop)4130Sstevel@tonic-gate _info(struct modinfo *modinfop)
4140Sstevel@tonic-gate {
4150Sstevel@tonic-gate return (mod_info(&ibcm_modlinkage, modinfop));
4160Sstevel@tonic-gate }
4170Sstevel@tonic-gate
4180Sstevel@tonic-gate
4190Sstevel@tonic-gate int
_fini(void)4200Sstevel@tonic-gate _fini(void)
4210Sstevel@tonic-gate {
4220Sstevel@tonic-gate int status;
4230Sstevel@tonic-gate
4240Sstevel@tonic-gate if (ibcm_fini() != IBCM_SUCCESS)
4250Sstevel@tonic-gate return (EBUSY);
4260Sstevel@tonic-gate
4270Sstevel@tonic-gate if ((status = mod_remove(&ibcm_modlinkage)) != 0) {
4280Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "_fini: ibcm mod_remove failed %d",
4290Sstevel@tonic-gate status);
4300Sstevel@tonic-gate return (status);
4310Sstevel@tonic-gate }
4320Sstevel@tonic-gate
4330Sstevel@tonic-gate IBTF_DPRINTF_L5(cmlog, "_fini: ibcm successful");
4340Sstevel@tonic-gate
4350Sstevel@tonic-gate return (status);
4360Sstevel@tonic-gate }
4370Sstevel@tonic-gate
4380Sstevel@tonic-gate /* Initializes all global mutex and CV in cm module */
4390Sstevel@tonic-gate static void
ibcm_init_locks()4400Sstevel@tonic-gate ibcm_init_locks()
4410Sstevel@tonic-gate {
4420Sstevel@tonic-gate
4430Sstevel@tonic-gate /* Verify CM MAD sizes */
4440Sstevel@tonic-gate #ifdef DEBUG
4450Sstevel@tonic-gate
4460Sstevel@tonic-gate if (ibcm_test_mode > 1) {
4470Sstevel@tonic-gate
4480Sstevel@tonic-gate IBTF_DPRINTF_L1(cmlog, "REQ MAD SIZE %d",
4490Sstevel@tonic-gate sizeof (ibcm_req_msg_t));
4500Sstevel@tonic-gate IBTF_DPRINTF_L1(cmlog, "REP MAD SIZE %d",
4510Sstevel@tonic-gate sizeof (ibcm_rep_msg_t));
4520Sstevel@tonic-gate IBTF_DPRINTF_L1(cmlog, "RTU MAD SIZE %d",
4530Sstevel@tonic-gate sizeof (ibcm_rtu_msg_t));
4540Sstevel@tonic-gate IBTF_DPRINTF_L1(cmlog, "MRA MAD SIZE %d",
4550Sstevel@tonic-gate sizeof (ibcm_mra_msg_t));
4560Sstevel@tonic-gate IBTF_DPRINTF_L1(cmlog, "REJ MAD SIZE %d",
4570Sstevel@tonic-gate sizeof (ibcm_rej_msg_t));
4580Sstevel@tonic-gate IBTF_DPRINTF_L1(cmlog, "LAP MAD SIZE %d",
4590Sstevel@tonic-gate sizeof (ibcm_lap_msg_t));
4600Sstevel@tonic-gate IBTF_DPRINTF_L1(cmlog, "APR MAD SIZE %d",
4610Sstevel@tonic-gate sizeof (ibcm_apr_msg_t));
4620Sstevel@tonic-gate IBTF_DPRINTF_L1(cmlog, "DREQ MAD SIZE %d",
4630Sstevel@tonic-gate sizeof (ibcm_dreq_msg_t));
4640Sstevel@tonic-gate IBTF_DPRINTF_L1(cmlog, "DREP MAD SIZE %d",
4650Sstevel@tonic-gate sizeof (ibcm_drep_msg_t));
4660Sstevel@tonic-gate IBTF_DPRINTF_L1(cmlog, "SIDR REQ MAD SIZE %d",
4670Sstevel@tonic-gate sizeof (ibcm_sidr_req_msg_t));
4680Sstevel@tonic-gate IBTF_DPRINTF_L1(cmlog, "SIDR REP MAD SIZE %d",
4690Sstevel@tonic-gate sizeof (ibcm_sidr_rep_msg_t));
4700Sstevel@tonic-gate }
4710Sstevel@tonic-gate
4720Sstevel@tonic-gate #endif
4730Sstevel@tonic-gate
4740Sstevel@tonic-gate /* Create all global locks within cm module */
4750Sstevel@tonic-gate mutex_init(&ibcm_svc_info_lock, NULL, MUTEX_DEFAULT, NULL);
476*9913SShantkumar.Hiremath@Sun.COM mutex_init(&ibcm_mcglist_lock, NULL, MUTEX_DEFAULT, NULL);
4770Sstevel@tonic-gate mutex_init(&ibcm_timeout_list_lock, NULL, MUTEX_DEFAULT, NULL);
4780Sstevel@tonic-gate mutex_init(&ibcm_global_hca_lock, NULL, MUTEX_DEFAULT, NULL);
4790Sstevel@tonic-gate mutex_init(&ibcm_sa_open_lock, NULL, MUTEX_DEFAULT, NULL);
4800Sstevel@tonic-gate mutex_init(&ibcm_recv_mutex, NULL, MUTEX_DEFAULT, NULL);
4810Sstevel@tonic-gate mutex_init(&ibcm_sm_notice_serialize_lock, NULL, MUTEX_DEFAULT, NULL);
4820Sstevel@tonic-gate mutex_init(&ibcm_qp_list_lock, NULL, MUTEX_DEFAULT, NULL);
4830Sstevel@tonic-gate mutex_init(&ibcm_trace_mutex, NULL, MUTEX_DEFAULT, NULL);
4840Sstevel@tonic-gate mutex_init(&ibcm_trace_print_mutex, NULL, MUTEX_DEFAULT, NULL);
4850Sstevel@tonic-gate cv_init(&ibcm_svc_info_cv, NULL, CV_DRIVER, NULL);
4860Sstevel@tonic-gate cv_init(&ibcm_timeout_list_cv, NULL, CV_DRIVER, NULL);
4870Sstevel@tonic-gate cv_init(&ibcm_timeout_thread_done_cv, NULL, CV_DRIVER, NULL);
4880Sstevel@tonic-gate cv_init(&ibcm_global_hca_cv, NULL, CV_DRIVER, NULL);
4890Sstevel@tonic-gate cv_init(&ibcm_sa_open_cv, NULL, CV_DRIVER, NULL);
4900Sstevel@tonic-gate avl_create(&ibcm_svc_avl_tree, ibcm_svc_compare,
4910Sstevel@tonic-gate sizeof (ibcm_svc_info_t),
4920Sstevel@tonic-gate offsetof(struct ibcm_svc_info_s, svc_link));
4930Sstevel@tonic-gate
4940Sstevel@tonic-gate IBTF_DPRINTF_L5(cmlog, "ibcm_init_locks: done");
4950Sstevel@tonic-gate }
4960Sstevel@tonic-gate
4970Sstevel@tonic-gate /* Destroys all global mutex and CV in cm module */
4980Sstevel@tonic-gate static void
ibcm_fini_locks()4990Sstevel@tonic-gate ibcm_fini_locks()
5000Sstevel@tonic-gate {
5010Sstevel@tonic-gate /* Destroy all global locks within cm module */
5020Sstevel@tonic-gate mutex_destroy(&ibcm_svc_info_lock);
503*9913SShantkumar.Hiremath@Sun.COM mutex_destroy(&ibcm_mcglist_lock);
5040Sstevel@tonic-gate mutex_destroy(&ibcm_timeout_list_lock);
5050Sstevel@tonic-gate mutex_destroy(&ibcm_global_hca_lock);
5060Sstevel@tonic-gate mutex_destroy(&ibcm_sa_open_lock);
5070Sstevel@tonic-gate mutex_destroy(&ibcm_recv_mutex);
5080Sstevel@tonic-gate mutex_destroy(&ibcm_sm_notice_serialize_lock);
5090Sstevel@tonic-gate mutex_destroy(&ibcm_qp_list_lock);
5100Sstevel@tonic-gate mutex_destroy(&ibcm_trace_mutex);
5110Sstevel@tonic-gate mutex_destroy(&ibcm_trace_print_mutex);
5120Sstevel@tonic-gate cv_destroy(&ibcm_svc_info_cv);
5130Sstevel@tonic-gate cv_destroy(&ibcm_timeout_list_cv);
5140Sstevel@tonic-gate cv_destroy(&ibcm_timeout_thread_done_cv);
5150Sstevel@tonic-gate cv_destroy(&ibcm_global_hca_cv);
5160Sstevel@tonic-gate cv_destroy(&ibcm_sa_open_cv);
5170Sstevel@tonic-gate avl_destroy(&ibcm_svc_avl_tree);
5180Sstevel@tonic-gate
5190Sstevel@tonic-gate IBTF_DPRINTF_L5(cmlog, "ibcm_fini_locks: done");
5200Sstevel@tonic-gate }
5210Sstevel@tonic-gate
5220Sstevel@tonic-gate
5230Sstevel@tonic-gate /* Initialize CM's classport info */
5240Sstevel@tonic-gate static void
ibcm_init_classportinfo()5250Sstevel@tonic-gate ibcm_init_classportinfo()
5260Sstevel@tonic-gate {
5270Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(ibcm_clpinfo));
5280Sstevel@tonic-gate
5290Sstevel@tonic-gate ibcm_clpinfo.BaseVersion = IBCM_MAD_BASE_VERSION;
5300Sstevel@tonic-gate ibcm_clpinfo.ClassVersion = IBCM_MAD_CLASS_VERSION;
5310Sstevel@tonic-gate
5320Sstevel@tonic-gate /* For now, CM supports same capabilities at all ports */
5330Sstevel@tonic-gate ibcm_clpinfo.CapabilityMask =
5340Sstevel@tonic-gate h2b16(IBCM_CPINFO_CAP_RC | IBCM_CPINFO_CAP_SIDR);
5350Sstevel@tonic-gate
5360Sstevel@tonic-gate /* Bits 0-7 are all 0 for Communication Mgmt Class */
5370Sstevel@tonic-gate
5380Sstevel@tonic-gate /* For now, CM has the same respvalue at all ports */
5390Sstevel@tonic-gate ibcm_clpinfo.RespTimeValue_plus =
5400Sstevel@tonic-gate h2b32(ibt_usec2ib(ibcm_local_processing_time) & 0x1f);
5410Sstevel@tonic-gate
5420Sstevel@tonic-gate /* For now, redirect fields are set to 0 */
5430Sstevel@tonic-gate /* Trap fields are not applicable to CM, hence set to 0 */
5440Sstevel@tonic-gate
5450Sstevel@tonic-gate _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(ibcm_clpinfo));
5460Sstevel@tonic-gate IBTF_DPRINTF_L5(cmlog, "ibcm_init_classportinfo: done");
5470Sstevel@tonic-gate }
5480Sstevel@tonic-gate
5490Sstevel@tonic-gate /*
5500Sstevel@tonic-gate * ibcm_init():
5510Sstevel@tonic-gate * - call ibt_attach()
5520Sstevel@tonic-gate * - create AVL trees
5530Sstevel@tonic-gate * - Attach HCA handlers that are already present before
5540Sstevel@tonic-gate * CM got loaded.
5550Sstevel@tonic-gate *
5560Sstevel@tonic-gate * Arguments: NONE
5570Sstevel@tonic-gate *
5580Sstevel@tonic-gate * Return values:
5590Sstevel@tonic-gate * IBCM_SUCCESS - success
5600Sstevel@tonic-gate */
5610Sstevel@tonic-gate static ibcm_status_t
ibcm_init(void)5620Sstevel@tonic-gate ibcm_init(void)
5630Sstevel@tonic-gate {
5640Sstevel@tonic-gate ibt_status_t status;
5650Sstevel@tonic-gate kthread_t *t;
5660Sstevel@tonic-gate
5670Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibcm_init:");
5680Sstevel@tonic-gate
5690Sstevel@tonic-gate ibcm_init_classportinfo();
5700Sstevel@tonic-gate
5710Sstevel@tonic-gate if (ibcm_init_ids() != IBCM_SUCCESS) {
5720Sstevel@tonic-gate IBTF_DPRINTF_L1(cmlog, "ibcm_init: "
5730Sstevel@tonic-gate "fatal error: vmem_create() failed");
5740Sstevel@tonic-gate return (IBCM_FAILURE);
5750Sstevel@tonic-gate }
5760Sstevel@tonic-gate ibcm_init_locks();
5770Sstevel@tonic-gate
5780Sstevel@tonic-gate if (ibcm_ar_init() != IBCM_SUCCESS) {
5790Sstevel@tonic-gate IBTF_DPRINTF_L1(cmlog, "ibcm_init: "
5800Sstevel@tonic-gate "fatal error: ibcm_ar_init() failed");
5810Sstevel@tonic-gate ibcm_fini_ids();
5820Sstevel@tonic-gate ibcm_fini_locks();
5830Sstevel@tonic-gate return (IBCM_FAILURE);
5840Sstevel@tonic-gate }
5851495Shiremath ibcm_rc_flow_control_init();
5860Sstevel@tonic-gate
5870Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(ibcm_taskq))
5880Sstevel@tonic-gate ibcm_taskq = system_taskq;
5890Sstevel@tonic-gate _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(ibcm_taskq))
5900Sstevel@tonic-gate
5910Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(ibcm_timeout_list_flags))
5920Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(ibcm_timeout_thread_did))
5930Sstevel@tonic-gate
5940Sstevel@tonic-gate /* Start the timeout list processing thread */
5950Sstevel@tonic-gate ibcm_timeout_list_flags = 0;
5960Sstevel@tonic-gate t = thread_create(NULL, 0, ibcm_process_tlist, 0, 0, &p0, TS_RUN,
5970Sstevel@tonic-gate ibcm_timeout_thread_pri);
5980Sstevel@tonic-gate ibcm_timeout_thread_did = t->t_did;
5990Sstevel@tonic-gate
6000Sstevel@tonic-gate _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(ibcm_timeout_list_flags))
6010Sstevel@tonic-gate _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(ibcm_timeout_thread_did))
6020Sstevel@tonic-gate
6030Sstevel@tonic-gate /*
6040Sstevel@tonic-gate * NOTE : if ibt_attach is done after ibcm_init_hcas, then some
6050Sstevel@tonic-gate * HCA DR events may be lost. CM could call re-init hca list
6060Sstevel@tonic-gate * again, but it is more complicated. Some HCA's DR's lost may
6070Sstevel@tonic-gate * be HCA detach, which makes hca list re-syncing and locking more
6080Sstevel@tonic-gate * complex
6090Sstevel@tonic-gate */
6100Sstevel@tonic-gate status = ibt_attach(&ibcm_ibt_modinfo, NULL, NULL, &ibcm_ibt_handle);
6110Sstevel@tonic-gate if (status != IBT_SUCCESS) {
6120Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_init(): ibt_attach failed %d",
6130Sstevel@tonic-gate status);
6140Sstevel@tonic-gate (void) ibcm_ar_fini();
6151495Shiremath ibcm_stop_timeout_thread();
6160Sstevel@tonic-gate ibcm_fini_ids();
6170Sstevel@tonic-gate ibcm_fini_locks();
6181495Shiremath ibcm_rc_flow_control_fini();
6190Sstevel@tonic-gate return (IBCM_FAILURE);
6200Sstevel@tonic-gate }
6210Sstevel@tonic-gate
6220Sstevel@tonic-gate /* Block all HCA attach/detach asyncs */
6230Sstevel@tonic-gate mutex_enter(&ibcm_global_hca_lock);
6240Sstevel@tonic-gate
6250Sstevel@tonic-gate ibcm_init_hcas();
6260Sstevel@tonic-gate ibcm_finit_state = IBCM_FINIT_IDLE;
6270Sstevel@tonic-gate
628557Shiremath ibcm_path_cache_init();
6299891SRajkumar.Sivaprakasam@Sun.COM /*
6309891SRajkumar.Sivaprakasam@Sun.COM * This callback will be used by IBTL to get the Node record for a
6319891SRajkumar.Sivaprakasam@Sun.COM * given LID via the speccified HCA and port.
6329891SRajkumar.Sivaprakasam@Sun.COM */
6339891SRajkumar.Sivaprakasam@Sun.COM ibtl_cm_set_node_info_cb(ibcm_ibtl_node_info);
634557Shiremath
6350Sstevel@tonic-gate /* Unblock any waiting HCA DR asyncs in CM */
6360Sstevel@tonic-gate mutex_exit(&ibcm_global_hca_lock);
6370Sstevel@tonic-gate
6380Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibcm_init: done");
6390Sstevel@tonic-gate return (IBCM_SUCCESS);
6400Sstevel@tonic-gate }
6410Sstevel@tonic-gate
6420Sstevel@tonic-gate /* Allocates and initializes the "per hca" global data in CM */
6430Sstevel@tonic-gate static void
ibcm_init_hcas()6440Sstevel@tonic-gate ibcm_init_hcas()
6450Sstevel@tonic-gate {
6460Sstevel@tonic-gate uint_t num_hcas = 0;
6470Sstevel@tonic-gate ib_guid_t *guid_array;
6480Sstevel@tonic-gate int i;
6490Sstevel@tonic-gate
6500Sstevel@tonic-gate IBTF_DPRINTF_L5(cmlog, "ibcm_init_hcas:");
6510Sstevel@tonic-gate
6520Sstevel@tonic-gate /* Get the number of HCAs */
6530Sstevel@tonic-gate num_hcas = ibt_get_hca_list(&guid_array);
6540Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibcm_init_hcas: ibt_get_hca_list() "
6550Sstevel@tonic-gate "returned %d hcas", num_hcas);
6560Sstevel@tonic-gate
6570Sstevel@tonic-gate ASSERT(MUTEX_HELD(&ibcm_global_hca_lock));
6580Sstevel@tonic-gate
6590Sstevel@tonic-gate for (i = 0; i < num_hcas; i++)
6600Sstevel@tonic-gate ibcm_hca_attach(guid_array[i]);
6610Sstevel@tonic-gate
6620Sstevel@tonic-gate if (num_hcas)
6630Sstevel@tonic-gate ibt_free_hca_list(guid_array, num_hcas);
6640Sstevel@tonic-gate
6650Sstevel@tonic-gate IBTF_DPRINTF_L5(cmlog, "ibcm_init_hcas: done");
6660Sstevel@tonic-gate }
6670Sstevel@tonic-gate
6680Sstevel@tonic-gate
6690Sstevel@tonic-gate /*
6700Sstevel@tonic-gate * ibcm_fini():
6710Sstevel@tonic-gate * - Deregister w/ ibt
6720Sstevel@tonic-gate * - Cleanup IBCM HCA listp
6730Sstevel@tonic-gate * - Destroy mutexes
6740Sstevel@tonic-gate *
6750Sstevel@tonic-gate * Arguments: NONE
6760Sstevel@tonic-gate *
6770Sstevel@tonic-gate * Return values:
6780Sstevel@tonic-gate * IBCM_SUCCESS - success
6790Sstevel@tonic-gate */
6800Sstevel@tonic-gate static ibcm_status_t
ibcm_fini(void)6810Sstevel@tonic-gate ibcm_fini(void)
6820Sstevel@tonic-gate {
6830Sstevel@tonic-gate ibt_status_t status;
6840Sstevel@tonic-gate
6850Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibcm_fini:");
6860Sstevel@tonic-gate
6870Sstevel@tonic-gate /*
6880Sstevel@tonic-gate * CM assumes that the all general clients got rid of all the
6890Sstevel@tonic-gate * established connections and service registrations, completed all
6900Sstevel@tonic-gate * pending SIDR operations before a call to ibcm_fini()
6910Sstevel@tonic-gate */
6920Sstevel@tonic-gate
6930Sstevel@tonic-gate if (ibcm_ar_fini() != IBCM_SUCCESS) {
6940Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_fini: ibcm_ar_fini failed");
6950Sstevel@tonic-gate return (IBCM_FAILURE);
6960Sstevel@tonic-gate }
6970Sstevel@tonic-gate
6980Sstevel@tonic-gate /* cleanup the svcinfo list */
6990Sstevel@tonic-gate mutex_enter(&ibcm_svc_info_lock);
7000Sstevel@tonic-gate if (avl_first(&ibcm_svc_avl_tree) != NULL) {
7010Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_fini: "
7020Sstevel@tonic-gate "ibcm_svc_avl_tree is not empty");
7030Sstevel@tonic-gate mutex_exit(&ibcm_svc_info_lock);
7040Sstevel@tonic-gate return (IBCM_FAILURE);
7050Sstevel@tonic-gate }
7060Sstevel@tonic-gate mutex_exit(&ibcm_svc_info_lock);
7070Sstevel@tonic-gate
7080Sstevel@tonic-gate /* disables any new hca attach/detaches */
7090Sstevel@tonic-gate mutex_enter(&ibcm_global_hca_lock);
7100Sstevel@tonic-gate
7110Sstevel@tonic-gate ibcm_finit_state = IBCM_FINIT_BUSY;
7120Sstevel@tonic-gate
7130Sstevel@tonic-gate if (ibcm_fini_hcas() != IBCM_SUCCESS) {
7140Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_fini: "
7150Sstevel@tonic-gate "some hca's still have client resources");
7160Sstevel@tonic-gate
7170Sstevel@tonic-gate /* First, re-initialize the hcas */
7180Sstevel@tonic-gate ibcm_init_hcas();
7190Sstevel@tonic-gate /* and then enable the HCA asyncs */
7200Sstevel@tonic-gate ibcm_finit_state = IBCM_FINIT_IDLE;
7210Sstevel@tonic-gate mutex_exit(&ibcm_global_hca_lock);
7220Sstevel@tonic-gate if (ibcm_ar_init() != IBCM_SUCCESS) {
7230Sstevel@tonic-gate IBTF_DPRINTF_L1(cmlog, "ibcm_fini:ibcm_ar_init failed");
7240Sstevel@tonic-gate }
7250Sstevel@tonic-gate return (IBCM_FAILURE);
7260Sstevel@tonic-gate }
7270Sstevel@tonic-gate
7280Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(ibcm_timeout_list_hdr))
7290Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(ibcm_ud_timeout_list_hdr))
7300Sstevel@tonic-gate
7310Sstevel@tonic-gate ASSERT(ibcm_timeout_list_hdr == NULL);
7320Sstevel@tonic-gate ASSERT(ibcm_ud_timeout_list_hdr == NULL);
7330Sstevel@tonic-gate
7340Sstevel@tonic-gate _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(ibcm_timeout_list_hdr))
7350Sstevel@tonic-gate _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(ibcm_ud_timeout_list_hdr))
7360Sstevel@tonic-gate
7370Sstevel@tonic-gate /* Release any pending asyncs on ibcm_global_hca_lock */
7380Sstevel@tonic-gate ibcm_finit_state = IBCM_FINIT_SUCCESS;
7390Sstevel@tonic-gate mutex_exit(&ibcm_global_hca_lock);
7400Sstevel@tonic-gate
7410Sstevel@tonic-gate ibcm_stop_timeout_thread();
7420Sstevel@tonic-gate
7439891SRajkumar.Sivaprakasam@Sun.COM ibtl_cm_set_node_info_cb(NULL);
7440Sstevel@tonic-gate /*
7450Sstevel@tonic-gate * Detach from IBTL. Waits until all pending asyncs are complete.
7460Sstevel@tonic-gate * Above cv_broadcast wakes up any waiting hca attach/detach asyncs
7470Sstevel@tonic-gate */
7480Sstevel@tonic-gate status = ibt_detach(ibcm_ibt_handle);
7490Sstevel@tonic-gate
7500Sstevel@tonic-gate /* if detach fails, CM didn't free up some resources, so assert */
7510Sstevel@tonic-gate if (status != IBT_SUCCESS)
7527862SRichard.Bean@Sun.COM IBTF_DPRINTF_L1(cmlog, "ibcm_fini: ibt_detach failed %d",
7537862SRichard.Bean@Sun.COM status);
7540Sstevel@tonic-gate
755557Shiremath ibcm_rc_flow_control_fini();
756557Shiremath
757557Shiremath ibcm_path_cache_fini();
7580Sstevel@tonic-gate
7590Sstevel@tonic-gate ibcm_fini_ids();
7600Sstevel@tonic-gate ibcm_fini_locks();
7610Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibcm_fini: done");
7620Sstevel@tonic-gate return (IBCM_SUCCESS);
7630Sstevel@tonic-gate }
7640Sstevel@tonic-gate
7650Sstevel@tonic-gate /* This routine exit's the ibcm timeout thread */
7660Sstevel@tonic-gate static void
ibcm_stop_timeout_thread()7670Sstevel@tonic-gate ibcm_stop_timeout_thread()
7680Sstevel@tonic-gate {
7690Sstevel@tonic-gate mutex_enter(&ibcm_timeout_list_lock);
7700Sstevel@tonic-gate
7710Sstevel@tonic-gate /* Stop the timeout list processing thread */
7720Sstevel@tonic-gate ibcm_timeout_list_flags =
7730Sstevel@tonic-gate ibcm_timeout_list_flags | IBCM_TIMEOUT_THREAD_EXIT;
7740Sstevel@tonic-gate
7750Sstevel@tonic-gate /* Wake up, if the timeout thread is on a cv_wait */
7760Sstevel@tonic-gate cv_signal(&ibcm_timeout_list_cv);
7770Sstevel@tonic-gate
7780Sstevel@tonic-gate mutex_exit(&ibcm_timeout_list_lock);
7790Sstevel@tonic-gate thread_join(ibcm_timeout_thread_did);
7800Sstevel@tonic-gate
7810Sstevel@tonic-gate IBTF_DPRINTF_L5(cmlog, "ibcm_stop_timeout_thread: done");
7820Sstevel@tonic-gate }
7830Sstevel@tonic-gate
7840Sstevel@tonic-gate
7850Sstevel@tonic-gate /* Attempts to release all the hca's associated with CM */
7860Sstevel@tonic-gate static ibcm_status_t
ibcm_fini_hcas()7870Sstevel@tonic-gate ibcm_fini_hcas()
7880Sstevel@tonic-gate {
7890Sstevel@tonic-gate ibcm_hca_info_t *hcap, *next;
7900Sstevel@tonic-gate
7910Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibcm_fini_hcas:");
7920Sstevel@tonic-gate
7930Sstevel@tonic-gate ASSERT(MUTEX_HELD(&ibcm_global_hca_lock));
7940Sstevel@tonic-gate
7950Sstevel@tonic-gate hcap = ibcm_hca_listp;
7960Sstevel@tonic-gate while (hcap != NULL) {
7970Sstevel@tonic-gate next = hcap->hca_next;
7980Sstevel@tonic-gate if (ibcm_hca_detach(hcap) != IBCM_SUCCESS) {
7990Sstevel@tonic-gate ibcm_hca_listp = hcap;
8000Sstevel@tonic-gate return (IBCM_FAILURE);
8010Sstevel@tonic-gate }
8020Sstevel@tonic-gate hcap = next;
8030Sstevel@tonic-gate }
8040Sstevel@tonic-gate
8050Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibcm_fini_hcas: SUCCEEDED");
8060Sstevel@tonic-gate return (IBCM_SUCCESS);
8070Sstevel@tonic-gate }
8080Sstevel@tonic-gate
8090Sstevel@tonic-gate
8100Sstevel@tonic-gate /*
8110Sstevel@tonic-gate * ibcm_hca_attach():
8120Sstevel@tonic-gate * Called as an asynchronous event to notify CM of an attach of HCA.
8130Sstevel@tonic-gate * Here ibcm_hca_info_t is initialized and all fields are
8140Sstevel@tonic-gate * filled in along with SA Access handles and IBMA handles.
8150Sstevel@tonic-gate * Also called from ibcm_init to initialize ibcm_hca_info_t's for each
8160Sstevel@tonic-gate * hca's
8170Sstevel@tonic-gate *
8180Sstevel@tonic-gate * Arguments: (WILL CHANGE BASED ON ASYNC EVENT CODE)
8190Sstevel@tonic-gate * hca_guid - HCA's guid
8200Sstevel@tonic-gate *
8210Sstevel@tonic-gate * Return values: NONE
8220Sstevel@tonic-gate */
8230Sstevel@tonic-gate static void
ibcm_hca_attach(ib_guid_t hcaguid)8240Sstevel@tonic-gate ibcm_hca_attach(ib_guid_t hcaguid)
8250Sstevel@tonic-gate {
8260Sstevel@tonic-gate int i;
8270Sstevel@tonic-gate ibt_status_t status;
828*9913SShantkumar.Hiremath@Sun.COM uint8_t nports = 0;
8290Sstevel@tonic-gate ibcm_hca_info_t *hcap;
8300Sstevel@tonic-gate ibt_hca_attr_t hca_attrs;
8310Sstevel@tonic-gate
8320Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibcm_hca_attach: guid = 0x%llX", hcaguid);
8330Sstevel@tonic-gate
8340Sstevel@tonic-gate ASSERT(MUTEX_HELD(&ibcm_global_hca_lock));
8350Sstevel@tonic-gate
8360Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*hcap))
8370Sstevel@tonic-gate
8380Sstevel@tonic-gate status = ibt_query_hca_byguid(hcaguid, &hca_attrs);
8390Sstevel@tonic-gate if (status != IBT_SUCCESS) {
8400Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_hca_attach: "
8410Sstevel@tonic-gate "ibt_query_hca_byguid failed = %d", status);
8420Sstevel@tonic-gate return;
8430Sstevel@tonic-gate }
8440Sstevel@tonic-gate nports = hca_attrs.hca_nports;
8450Sstevel@tonic-gate
8460Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibcm_hca_attach: num ports = %x", nports);
8470Sstevel@tonic-gate
8480Sstevel@tonic-gate if ((hcap = ibcm_add_hca_entry(hcaguid, nports)) == NULL)
8490Sstevel@tonic-gate return;
8500Sstevel@tonic-gate
8510Sstevel@tonic-gate hcap->hca_guid = hcaguid; /* Set GUID */
8520Sstevel@tonic-gate hcap->hca_num_ports = nports; /* Set number of ports */
8530Sstevel@tonic-gate
8540Sstevel@tonic-gate if (ibcm_init_hca_ids(hcap) != IBCM_SUCCESS) {
8550Sstevel@tonic-gate ibcm_delete_hca_entry(hcap);
8560Sstevel@tonic-gate return;
8570Sstevel@tonic-gate }
8580Sstevel@tonic-gate
8590Sstevel@tonic-gate /* Store the static hca attribute data */
8600Sstevel@tonic-gate hcap->hca_caps = hca_attrs.hca_flags;
8613241Shiremath hcap->hca_vendor_id = hca_attrs.hca_vendor_id;
8623241Shiremath hcap->hca_device_id = hca_attrs.hca_device_id;
8630Sstevel@tonic-gate hcap->hca_ack_delay = hca_attrs.hca_local_ack_delay;
8640Sstevel@tonic-gate hcap->hca_max_rdma_in_qp = hca_attrs.hca_max_rdma_in_qp;
8650Sstevel@tonic-gate hcap->hca_max_rdma_out_qp = hca_attrs.hca_max_rdma_out_qp;
8660Sstevel@tonic-gate
8670Sstevel@tonic-gate /* loop thru nports and initialize IBMF handles */
8680Sstevel@tonic-gate for (i = 0; i < hcap->hca_num_ports; i++) {
8690Sstevel@tonic-gate status = ibt_get_port_state_byguid(hcaguid, i + 1, NULL, NULL);
8700Sstevel@tonic-gate if (status != IBT_SUCCESS) {
8710Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_hca_attach: "
8720Sstevel@tonic-gate "port_num %d state DOWN", i + 1);
8730Sstevel@tonic-gate }
8740Sstevel@tonic-gate
8750Sstevel@tonic-gate hcap->hca_port_info[i].port_hcap = hcap;
8760Sstevel@tonic-gate hcap->hca_port_info[i].port_num = i+1;
8770Sstevel@tonic-gate
8780Sstevel@tonic-gate if (ibcm_hca_init_port(hcap, i) != IBT_SUCCESS)
8790Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_hca_attach: "
8800Sstevel@tonic-gate "ibcm_hca_init_port failed %d port_num %d",
8810Sstevel@tonic-gate status, i+1);
8820Sstevel@tonic-gate }
8830Sstevel@tonic-gate
8840Sstevel@tonic-gate /* create the "active" CM AVL tree */
8850Sstevel@tonic-gate avl_create(&hcap->hca_active_tree, ibcm_active_node_compare,
8860Sstevel@tonic-gate sizeof (ibcm_state_data_t),
8870Sstevel@tonic-gate offsetof(struct ibcm_state_data_s, avl_active_link));
8880Sstevel@tonic-gate
8890Sstevel@tonic-gate /* create the "passive" CM AVL tree */
8900Sstevel@tonic-gate avl_create(&hcap->hca_passive_tree, ibcm_passive_node_compare,
8910Sstevel@tonic-gate sizeof (ibcm_state_data_t),
8920Sstevel@tonic-gate offsetof(struct ibcm_state_data_s, avl_passive_link));
8930Sstevel@tonic-gate
8940Sstevel@tonic-gate /* create the "passive comid" CM AVL tree */
8950Sstevel@tonic-gate avl_create(&hcap->hca_passive_comid_tree,
8960Sstevel@tonic-gate ibcm_passive_comid_node_compare,
8970Sstevel@tonic-gate sizeof (ibcm_state_data_t),
8980Sstevel@tonic-gate offsetof(struct ibcm_state_data_s, avl_passive_comid_link));
8990Sstevel@tonic-gate
9000Sstevel@tonic-gate /*
9010Sstevel@tonic-gate * Mark the state of the HCA to "attach" only at the end
9020Sstevel@tonic-gate * Now CM starts accepting incoming MADs and client API calls
9030Sstevel@tonic-gate */
9040Sstevel@tonic-gate hcap->hca_state = IBCM_HCA_ACTIVE;
9050Sstevel@tonic-gate
9060Sstevel@tonic-gate _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*hcap))
9070Sstevel@tonic-gate
9080Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibcm_hca_attach: ATTACH Done");
9090Sstevel@tonic-gate }
9100Sstevel@tonic-gate
9110Sstevel@tonic-gate /*
9120Sstevel@tonic-gate * ibcm_hca_detach():
9130Sstevel@tonic-gate * Called as an asynchronous event to notify CM of a detach of HCA.
9140Sstevel@tonic-gate * Here ibcm_hca_info_t is freed up and all fields that
9150Sstevel@tonic-gate * were initialized earlier are cleaned up
9160Sstevel@tonic-gate *
9170Sstevel@tonic-gate * Arguments: (WILL CHANGE BASED ON ASYNC EVENT CODE)
9180Sstevel@tonic-gate * hca_guid - HCA's guid
9190Sstevel@tonic-gate *
9200Sstevel@tonic-gate * Return values:
9210Sstevel@tonic-gate * IBCM_SUCCESS - able to detach HCA
9220Sstevel@tonic-gate * IBCM_FAILURE - failed to detach HCA
9230Sstevel@tonic-gate */
9240Sstevel@tonic-gate static ibcm_status_t
ibcm_hca_detach(ibcm_hca_info_t * hcap)9250Sstevel@tonic-gate ibcm_hca_detach(ibcm_hca_info_t *hcap)
9260Sstevel@tonic-gate {
9270Sstevel@tonic-gate int port_index, i;
9280Sstevel@tonic-gate ibcm_status_t status = IBCM_SUCCESS;
9290Sstevel@tonic-gate clock_t absolute_time;
9300Sstevel@tonic-gate
9310Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibcm_hca_detach: hcap = 0x%p guid = 0x%llX",
9320Sstevel@tonic-gate hcap, hcap->hca_guid);
9330Sstevel@tonic-gate
9340Sstevel@tonic-gate ASSERT(MUTEX_HELD(&ibcm_global_hca_lock));
9350Sstevel@tonic-gate
9360Sstevel@tonic-gate /*
9370Sstevel@tonic-gate * Declare hca is going away to all CM clients. Wait until the
9380Sstevel@tonic-gate * access count becomes zero.
9390Sstevel@tonic-gate */
9400Sstevel@tonic-gate hcap->hca_state = IBCM_HCA_NOT_ACTIVE;
9410Sstevel@tonic-gate
9428695SRajkumar.Sivaprakasam@Sun.COM /* wait on response CV */
9430Sstevel@tonic-gate absolute_time = ddi_get_lbolt() +
9440Sstevel@tonic-gate drv_usectohz(ibcm_wait_for_acc_cnt_timeout);
9450Sstevel@tonic-gate
9460Sstevel@tonic-gate while (hcap->hca_acc_cnt > 0)
9470Sstevel@tonic-gate if (cv_timedwait(&ibcm_global_hca_cv, &ibcm_global_hca_lock,
9480Sstevel@tonic-gate absolute_time) == -1)
9490Sstevel@tonic-gate break;
9500Sstevel@tonic-gate
9510Sstevel@tonic-gate if (hcap->hca_acc_cnt != 0) {
9520Sstevel@tonic-gate /* We got a timeout */
9538695SRajkumar.Sivaprakasam@Sun.COM IBTF_DPRINTF_L2(cmlog, "ibcm_hca_detach: Aborting due"
9548695SRajkumar.Sivaprakasam@Sun.COM " to timeout on hca_acc_cnt %u, \n Some CM Clients are "
9558695SRajkumar.Sivaprakasam@Sun.COM "still active, looks like we need to wait some more time "
9568695SRajkumar.Sivaprakasam@Sun.COM "(ibcm_wait_for_acc_cnt_timeout).", hcap->hca_acc_cnt);
9570Sstevel@tonic-gate hcap->hca_state = IBCM_HCA_ACTIVE;
9580Sstevel@tonic-gate return (IBCM_FAILURE);
9590Sstevel@tonic-gate }
9600Sstevel@tonic-gate
9610Sstevel@tonic-gate /*
9620Sstevel@tonic-gate * First make sure, there are no active users of ibma handles,
9630Sstevel@tonic-gate * and then de-register handles.
9640Sstevel@tonic-gate */
9650Sstevel@tonic-gate
9660Sstevel@tonic-gate /* make sure that there are no "Service"s registered w/ this HCA. */
9670Sstevel@tonic-gate if (hcap->hca_svc_cnt != 0) {
9680Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_hca_detach: "
9690Sstevel@tonic-gate "Active services still there %d", hcap->hca_svc_cnt);
9700Sstevel@tonic-gate hcap->hca_state = IBCM_HCA_ACTIVE;
9710Sstevel@tonic-gate return (IBCM_FAILURE);
9720Sstevel@tonic-gate }
9730Sstevel@tonic-gate
9740Sstevel@tonic-gate if (ibcm_check_sidr_clean(hcap) != IBCM_SUCCESS) {
9750Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_hca_detach:"
9760Sstevel@tonic-gate "There are active SIDR operations");
9770Sstevel@tonic-gate hcap->hca_state = IBCM_HCA_ACTIVE;
9780Sstevel@tonic-gate return (IBCM_FAILURE);
9790Sstevel@tonic-gate }
9800Sstevel@tonic-gate
9810Sstevel@tonic-gate if (ibcm_check_avl_clean(hcap) != IBCM_SUCCESS) {
9820Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_hca_detach: "
9830Sstevel@tonic-gate "There are active RC connections");
9840Sstevel@tonic-gate hcap->hca_state = IBCM_HCA_ACTIVE;
9850Sstevel@tonic-gate return (IBCM_FAILURE);
9860Sstevel@tonic-gate }
9870Sstevel@tonic-gate
9880Sstevel@tonic-gate /*
9890Sstevel@tonic-gate * Now, wait until all rc and sidr stateps go away
9900Sstevel@tonic-gate * All these stateps must be short lived ones, waiting to be cleaned
9910Sstevel@tonic-gate * up after some timeout value, based on the current state.
9920Sstevel@tonic-gate */
9938695SRajkumar.Sivaprakasam@Sun.COM IBTF_DPRINTF_L3(cmlog, "ibcm_hca_detach:hca_guid = 0x%llX res_cnt = %d",
9940Sstevel@tonic-gate hcap->hca_guid, hcap->hca_res_cnt);
9950Sstevel@tonic-gate
9960Sstevel@tonic-gate while (hcap->hca_res_cnt > 0)
9979879SRamaswamy.Tummala@Sun.COM cv_wait(&ibcm_global_hca_cv, &ibcm_global_hca_lock);
9980Sstevel@tonic-gate
9990Sstevel@tonic-gate /* Re-assert the while loop step above */
10000Sstevel@tonic-gate ASSERT(hcap->hca_sidr_list == NULL);
10010Sstevel@tonic-gate avl_destroy(&hcap->hca_active_tree);
10020Sstevel@tonic-gate avl_destroy(&hcap->hca_passive_tree);
10030Sstevel@tonic-gate avl_destroy(&hcap->hca_passive_comid_tree);
10040Sstevel@tonic-gate
10050Sstevel@tonic-gate /*
10060Sstevel@tonic-gate * Unregister all ports from IBMA
10070Sstevel@tonic-gate * If there is a failure, re-initialize any free'd ibma handles. This
10080Sstevel@tonic-gate * is required to receive the incoming mads
10090Sstevel@tonic-gate */
10100Sstevel@tonic-gate status = IBCM_SUCCESS;
10110Sstevel@tonic-gate for (port_index = 0; port_index < hcap->hca_num_ports; port_index++) {
10120Sstevel@tonic-gate if ((status = ibcm_hca_fini_port(hcap, port_index)) !=
10130Sstevel@tonic-gate IBCM_SUCCESS) {
10140Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_hca_detach: "
10150Sstevel@tonic-gate "Failed to free IBMA Handle for port_num %d",
10160Sstevel@tonic-gate port_index + 1);
10170Sstevel@tonic-gate break;
10180Sstevel@tonic-gate }
10190Sstevel@tonic-gate }
10200Sstevel@tonic-gate
10210Sstevel@tonic-gate /* If detach fails, re-initialize ibma handles for incoming mads */
10220Sstevel@tonic-gate if (status != IBCM_SUCCESS) {
10230Sstevel@tonic-gate for (i = 0; i < port_index; i++) {
10240Sstevel@tonic-gate if (ibcm_hca_init_port(hcap, i) != IBT_SUCCESS)
10250Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_hca_detach: "
10260Sstevel@tonic-gate "Failed to re-allocate IBMA Handles for"
10270Sstevel@tonic-gate " port_num %d", port_index + 1);
10280Sstevel@tonic-gate }
10290Sstevel@tonic-gate hcap->hca_state = IBCM_HCA_ACTIVE;
10300Sstevel@tonic-gate return (IBCM_FAILURE);
10310Sstevel@tonic-gate }
10320Sstevel@tonic-gate
10330Sstevel@tonic-gate ibcm_fini_hca_ids(hcap);
10340Sstevel@tonic-gate ibcm_delete_hca_entry(hcap);
10350Sstevel@tonic-gate
10360Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibcm_hca_detach: DETACH succeeded");
10370Sstevel@tonic-gate return (IBCM_SUCCESS);
10380Sstevel@tonic-gate }
10390Sstevel@tonic-gate
10400Sstevel@tonic-gate /* Checks, if there are any active sidr state entries in the specified hca */
10410Sstevel@tonic-gate static ibcm_status_t
ibcm_check_sidr_clean(ibcm_hca_info_t * hcap)10420Sstevel@tonic-gate ibcm_check_sidr_clean(ibcm_hca_info_t *hcap)
10430Sstevel@tonic-gate {
10440Sstevel@tonic-gate ibcm_ud_state_data_t *usp;
10450Sstevel@tonic-gate uint32_t transient_cnt = 0;
10460Sstevel@tonic-gate
10470Sstevel@tonic-gate IBTF_DPRINTF_L5(cmlog, "ibcm_check_sidr_clean:");
10480Sstevel@tonic-gate
10490Sstevel@tonic-gate rw_enter(&hcap->hca_sidr_list_lock, RW_WRITER);
10500Sstevel@tonic-gate usp = hcap->hca_sidr_list; /* Point to the list */
10510Sstevel@tonic-gate while (usp != NULL) {
10520Sstevel@tonic-gate mutex_enter(&usp->ud_state_mutex);
10530Sstevel@tonic-gate if ((usp->ud_state != IBCM_STATE_SIDR_REP_SENT) &&
10540Sstevel@tonic-gate (usp->ud_state != IBCM_STATE_TIMED_OUT) &&
10550Sstevel@tonic-gate (usp->ud_state != IBCM_STATE_DELETE)) {
10560Sstevel@tonic-gate
10570Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibcm_check_sidr_clean:"
10580Sstevel@tonic-gate "usp = %p not in transient state = %d", usp,
10590Sstevel@tonic-gate usp->ud_state);
10600Sstevel@tonic-gate
10610Sstevel@tonic-gate mutex_exit(&usp->ud_state_mutex);
10620Sstevel@tonic-gate rw_exit(&hcap->hca_sidr_list_lock);
10630Sstevel@tonic-gate return (IBCM_FAILURE);
10640Sstevel@tonic-gate } else {
10650Sstevel@tonic-gate mutex_exit(&usp->ud_state_mutex);
10660Sstevel@tonic-gate ++transient_cnt;
10670Sstevel@tonic-gate }
10680Sstevel@tonic-gate
10690Sstevel@tonic-gate usp = usp->ud_nextp;
10700Sstevel@tonic-gate }
10710Sstevel@tonic-gate rw_exit(&hcap->hca_sidr_list_lock);
10720Sstevel@tonic-gate
10730Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibcm_check_sidr_clean: transient_cnt %d",
10740Sstevel@tonic-gate transient_cnt);
10750Sstevel@tonic-gate
10760Sstevel@tonic-gate return (IBCM_SUCCESS);
10770Sstevel@tonic-gate }
10780Sstevel@tonic-gate
10790Sstevel@tonic-gate /* Checks, if there are any active rc state entries, in the specified hca */
10800Sstevel@tonic-gate static ibcm_status_t
ibcm_check_avl_clean(ibcm_hca_info_t * hcap)10810Sstevel@tonic-gate ibcm_check_avl_clean(ibcm_hca_info_t *hcap)
10820Sstevel@tonic-gate
10830Sstevel@tonic-gate {
10840Sstevel@tonic-gate ibcm_state_data_t *sp;
10850Sstevel@tonic-gate avl_tree_t *avl_tree;
10860Sstevel@tonic-gate uint32_t transient_cnt = 0;
10870Sstevel@tonic-gate
10880Sstevel@tonic-gate IBTF_DPRINTF_L5(cmlog, "ibcm_check_avl_clean:");
10890Sstevel@tonic-gate /*
10900Sstevel@tonic-gate * Both the trees ie., active and passive must reference to all
10910Sstevel@tonic-gate * statep's, so let's use one
10920Sstevel@tonic-gate */
10930Sstevel@tonic-gate avl_tree = &hcap->hca_active_tree;
10940Sstevel@tonic-gate
10950Sstevel@tonic-gate rw_enter(&hcap->hca_state_rwlock, RW_WRITER);
10960Sstevel@tonic-gate
10970Sstevel@tonic-gate for (sp = avl_first(avl_tree); sp != NULL;
10980Sstevel@tonic-gate sp = avl_walk(avl_tree, sp, AVL_AFTER)) {
10990Sstevel@tonic-gate mutex_enter(&sp->state_mutex);
11000Sstevel@tonic-gate if ((sp->state != IBCM_STATE_TIMEWAIT) &&
11010Sstevel@tonic-gate (sp->state != IBCM_STATE_REJ_SENT) &&
11020Sstevel@tonic-gate (sp->state != IBCM_STATE_DELETE)) {
11031093Shiremath IBTF_DPRINTF_L3(cmlog, "ibcm_check_avl_clean: "
11040Sstevel@tonic-gate "sp = %p not in transient state = %d", sp,
11050Sstevel@tonic-gate sp->state);
11060Sstevel@tonic-gate mutex_exit(&sp->state_mutex);
11070Sstevel@tonic-gate rw_exit(&hcap->hca_state_rwlock);
11080Sstevel@tonic-gate return (IBCM_FAILURE);
11090Sstevel@tonic-gate } else {
11100Sstevel@tonic-gate mutex_exit(&sp->state_mutex);
11110Sstevel@tonic-gate ++transient_cnt;
11120Sstevel@tonic-gate }
11130Sstevel@tonic-gate }
11140Sstevel@tonic-gate
11150Sstevel@tonic-gate rw_exit(&hcap->hca_state_rwlock);
11160Sstevel@tonic-gate
11170Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibcm_check_avl_clean: transient_cnt %d",
11180Sstevel@tonic-gate transient_cnt);
11190Sstevel@tonic-gate
11200Sstevel@tonic-gate return (IBCM_SUCCESS);
11210Sstevel@tonic-gate }
11220Sstevel@tonic-gate
11230Sstevel@tonic-gate /* Adds a new entry into CM's global hca list, if hca_guid is not there yet */
11240Sstevel@tonic-gate static ibcm_hca_info_t *
ibcm_add_hca_entry(ib_guid_t hcaguid,uint_t nports)11250Sstevel@tonic-gate ibcm_add_hca_entry(ib_guid_t hcaguid, uint_t nports)
11260Sstevel@tonic-gate {
11270Sstevel@tonic-gate ibcm_hca_info_t *hcap;
11280Sstevel@tonic-gate
11290Sstevel@tonic-gate IBTF_DPRINTF_L5(cmlog, "ibcm_add_hca_entry: guid = 0x%llX",
11300Sstevel@tonic-gate hcaguid);
11310Sstevel@tonic-gate
11320Sstevel@tonic-gate ASSERT(MUTEX_HELD(&ibcm_global_hca_lock));
11330Sstevel@tonic-gate
11340Sstevel@tonic-gate /*
11350Sstevel@tonic-gate * Check if this hca_guid already in the list
11360Sstevel@tonic-gate * If yes, then ignore this and return NULL
11370Sstevel@tonic-gate */
11380Sstevel@tonic-gate
11390Sstevel@tonic-gate hcap = ibcm_hca_listp;
11400Sstevel@tonic-gate
11410Sstevel@tonic-gate /* search for this HCA */
11420Sstevel@tonic-gate while (hcap != NULL) {
11430Sstevel@tonic-gate if (hcap->hca_guid == hcaguid) {
11440Sstevel@tonic-gate /* already exists */
11450Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_add_hca_entry: "
11461093Shiremath "hcap %p guid 0x%llX, entry already exists !!",
11471093Shiremath hcap, hcap->hca_guid);
11480Sstevel@tonic-gate return (NULL);
11490Sstevel@tonic-gate }
11500Sstevel@tonic-gate hcap = hcap->hca_next;
11510Sstevel@tonic-gate }
11520Sstevel@tonic-gate
11530Sstevel@tonic-gate /* Allocate storage for the new HCA entry found */
11540Sstevel@tonic-gate hcap = kmem_zalloc(sizeof (ibcm_hca_info_t) +
11550Sstevel@tonic-gate (nports - 1) * sizeof (ibcm_port_info_t), KM_SLEEP);
11560Sstevel@tonic-gate
11570Sstevel@tonic-gate /* initialize RW lock */
11580Sstevel@tonic-gate rw_init(&hcap->hca_state_rwlock, NULL, RW_DRIVER, NULL);
11590Sstevel@tonic-gate /* initialize SIDR list lock */
11600Sstevel@tonic-gate rw_init(&hcap->hca_sidr_list_lock, NULL, RW_DRIVER, NULL);
11610Sstevel@tonic-gate /* Insert "hcap" into the global HCA list maintained by CM */
11620Sstevel@tonic-gate hcap->hca_next = ibcm_hca_listp;
11630Sstevel@tonic-gate ibcm_hca_listp = hcap;
11640Sstevel@tonic-gate
11650Sstevel@tonic-gate IBTF_DPRINTF_L5(cmlog, "ibcm_add_hca_entry: done hcap = 0x%p", hcap);
11660Sstevel@tonic-gate
11670Sstevel@tonic-gate return (hcap);
11680Sstevel@tonic-gate
11690Sstevel@tonic-gate }
11700Sstevel@tonic-gate
11710Sstevel@tonic-gate /* deletes the given ibcm_hca_info_t from CM's global hca list */
11720Sstevel@tonic-gate void
ibcm_delete_hca_entry(ibcm_hca_info_t * hcap)11730Sstevel@tonic-gate ibcm_delete_hca_entry(ibcm_hca_info_t *hcap)
11740Sstevel@tonic-gate {
11750Sstevel@tonic-gate ibcm_hca_info_t *headp, *prevp = NULL;
11760Sstevel@tonic-gate
11770Sstevel@tonic-gate /* ibcm_hca_global_lock is held */
11780Sstevel@tonic-gate IBTF_DPRINTF_L5(cmlog, "ibcm_delete_hca_entry: guid = 0x%llX "
11790Sstevel@tonic-gate "hcap = 0x%p", hcap->hca_guid, hcap);
11800Sstevel@tonic-gate
11810Sstevel@tonic-gate ASSERT(MUTEX_HELD(&ibcm_global_hca_lock));
11820Sstevel@tonic-gate
11830Sstevel@tonic-gate headp = ibcm_hca_listp;
11840Sstevel@tonic-gate while (headp != NULL) {
11850Sstevel@tonic-gate if (headp == hcap) {
11860Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibcm_delete_hca_entry: "
11870Sstevel@tonic-gate "deleting hcap %p hcaguid %llX", hcap,
11880Sstevel@tonic-gate hcap->hca_guid);
11890Sstevel@tonic-gate if (prevp) {
11900Sstevel@tonic-gate prevp->hca_next = headp->hca_next;
11910Sstevel@tonic-gate } else {
11920Sstevel@tonic-gate prevp = headp->hca_next;
11930Sstevel@tonic-gate ibcm_hca_listp = prevp;
11940Sstevel@tonic-gate }
11950Sstevel@tonic-gate rw_destroy(&hcap->hca_state_rwlock);
11960Sstevel@tonic-gate rw_destroy(&hcap->hca_sidr_list_lock);
11970Sstevel@tonic-gate kmem_free(hcap, sizeof (ibcm_hca_info_t) +
11980Sstevel@tonic-gate (hcap->hca_num_ports - 1) *
11990Sstevel@tonic-gate sizeof (ibcm_port_info_t));
12000Sstevel@tonic-gate return;
12010Sstevel@tonic-gate }
12020Sstevel@tonic-gate
12030Sstevel@tonic-gate prevp = headp;
12040Sstevel@tonic-gate headp = headp->hca_next;
12050Sstevel@tonic-gate }
12060Sstevel@tonic-gate }
12070Sstevel@tonic-gate
12080Sstevel@tonic-gate /*
12090Sstevel@tonic-gate * ibcm_find_hca_entry:
12100Sstevel@tonic-gate * Given a HCA's GUID find out ibcm_hca_info_t entry for that HCA
12110Sstevel@tonic-gate * This entry can be then used to access AVL tree/SIDR list etc.
12120Sstevel@tonic-gate * If entry exists and in HCA ATTACH state, then hca's ref cnt is
12130Sstevel@tonic-gate * incremented and entry returned. Else NULL returned.
12140Sstevel@tonic-gate *
12150Sstevel@tonic-gate * All functions that use ibcm_find_hca_entry and get a non-NULL
12160Sstevel@tonic-gate * return values must call ibcm_dec_hca_acc_cnt to decrement the
12170Sstevel@tonic-gate * respective hca ref cnt. There shouldn't be any usage of
12180Sstevel@tonic-gate * ibcm_hca_info_t * returned from ibcm_find_hca_entry,
12190Sstevel@tonic-gate * after decrementing the hca_acc_cnt
12200Sstevel@tonic-gate *
12210Sstevel@tonic-gate * INPUTS:
12220Sstevel@tonic-gate * hca_guid - HCA's guid
12230Sstevel@tonic-gate *
12240Sstevel@tonic-gate * RETURN VALUE:
12250Sstevel@tonic-gate * hcap - if a match is found, else NULL
12260Sstevel@tonic-gate */
12270Sstevel@tonic-gate ibcm_hca_info_t *
ibcm_find_hca_entry(ib_guid_t hca_guid)12280Sstevel@tonic-gate ibcm_find_hca_entry(ib_guid_t hca_guid)
12290Sstevel@tonic-gate {
12300Sstevel@tonic-gate ibcm_hca_info_t *hcap;
12310Sstevel@tonic-gate
12320Sstevel@tonic-gate IBTF_DPRINTF_L5(cmlog, "ibcm_find_hca_entry: guid = 0x%llX", hca_guid);
12330Sstevel@tonic-gate
12340Sstevel@tonic-gate mutex_enter(&ibcm_global_hca_lock);
12350Sstevel@tonic-gate
12360Sstevel@tonic-gate hcap = ibcm_hca_listp;
12370Sstevel@tonic-gate /* search for this HCA */
12380Sstevel@tonic-gate while (hcap != NULL) {
12390Sstevel@tonic-gate if (hcap->hca_guid == hca_guid)
12400Sstevel@tonic-gate break;
12410Sstevel@tonic-gate hcap = hcap->hca_next;
12420Sstevel@tonic-gate }
12430Sstevel@tonic-gate
12440Sstevel@tonic-gate /* if no hcap for the hca_guid, return NULL */
12450Sstevel@tonic-gate if (hcap == NULL) {
12460Sstevel@tonic-gate mutex_exit(&ibcm_global_hca_lock);
12470Sstevel@tonic-gate return (NULL);
12480Sstevel@tonic-gate }
12490Sstevel@tonic-gate
12500Sstevel@tonic-gate /* return hcap, only if it valid to use */
12510Sstevel@tonic-gate if (hcap->hca_state == IBCM_HCA_ACTIVE) {
12520Sstevel@tonic-gate ++(hcap->hca_acc_cnt);
12530Sstevel@tonic-gate
12540Sstevel@tonic-gate IBTF_DPRINTF_L5(cmlog, "ibcm_find_hca_entry: "
12550Sstevel@tonic-gate "found hcap = 0x%p hca_acc_cnt %u", hcap,
12560Sstevel@tonic-gate hcap->hca_acc_cnt);
12570Sstevel@tonic-gate
12580Sstevel@tonic-gate mutex_exit(&ibcm_global_hca_lock);
12590Sstevel@tonic-gate return (hcap);
12600Sstevel@tonic-gate } else {
12610Sstevel@tonic-gate mutex_exit(&ibcm_global_hca_lock);
12620Sstevel@tonic-gate
12630Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_find_hca_entry: "
12640Sstevel@tonic-gate "found hcap = 0x%p not in active state", hcap);
12650Sstevel@tonic-gate return (NULL);
12660Sstevel@tonic-gate }
12670Sstevel@tonic-gate }
12680Sstevel@tonic-gate
12690Sstevel@tonic-gate /*
12700Sstevel@tonic-gate * Searches for ibcm_hca_info_t entry based on hca_guid, but doesn't increment
12710Sstevel@tonic-gate * the hca's reference count. This function is used, where the calling context
12720Sstevel@tonic-gate * is attempting to delete hcap itself and hence acc_cnt cannot be incremented
12730Sstevel@tonic-gate * OR assumes that valid hcap must be available in ibcm's global hca list.
12740Sstevel@tonic-gate */
12750Sstevel@tonic-gate ibcm_hca_info_t *
ibcm_find_hcap_entry(ib_guid_t hca_guid)12760Sstevel@tonic-gate ibcm_find_hcap_entry(ib_guid_t hca_guid)
12770Sstevel@tonic-gate {
12780Sstevel@tonic-gate ibcm_hca_info_t *hcap;
12790Sstevel@tonic-gate
12800Sstevel@tonic-gate IBTF_DPRINTF_L5(cmlog, "ibcm_find_hcap_entry: guid = 0x%llX", hca_guid);
12810Sstevel@tonic-gate
12820Sstevel@tonic-gate ASSERT(MUTEX_HELD(&ibcm_global_hca_lock));
12830Sstevel@tonic-gate
12840Sstevel@tonic-gate hcap = ibcm_hca_listp;
12850Sstevel@tonic-gate /* search for this HCA */
12860Sstevel@tonic-gate while (hcap != NULL) {
12870Sstevel@tonic-gate if (hcap->hca_guid == hca_guid)
12880Sstevel@tonic-gate break;
12890Sstevel@tonic-gate hcap = hcap->hca_next;
12900Sstevel@tonic-gate }
12910Sstevel@tonic-gate
12920Sstevel@tonic-gate if (hcap == NULL)
12930Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_find_hcap_entry: No hcap found for"
12940Sstevel@tonic-gate " hca_guid 0x%llX", hca_guid);
12950Sstevel@tonic-gate else
12960Sstevel@tonic-gate IBTF_DPRINTF_L5(cmlog, "ibcm_find_hcap_entry: hcap found for"
12970Sstevel@tonic-gate " hca_guid 0x%llX", hca_guid);
12980Sstevel@tonic-gate
12990Sstevel@tonic-gate return (hcap);
13000Sstevel@tonic-gate }
13010Sstevel@tonic-gate
13020Sstevel@tonic-gate /* increment the hca's temporary reference count */
13030Sstevel@tonic-gate ibcm_status_t
ibcm_inc_hca_acc_cnt(ibcm_hca_info_t * hcap)13040Sstevel@tonic-gate ibcm_inc_hca_acc_cnt(ibcm_hca_info_t *hcap)
13050Sstevel@tonic-gate {
13060Sstevel@tonic-gate mutex_enter(&ibcm_global_hca_lock);
13070Sstevel@tonic-gate if (hcap->hca_state == IBCM_HCA_ACTIVE) {
13080Sstevel@tonic-gate ++(hcap->hca_acc_cnt);
13090Sstevel@tonic-gate IBTF_DPRINTF_L5(cmlog, "ibcm_inc_hca_acc_cnt: "
13100Sstevel@tonic-gate "hcap = 0x%p acc_cnt = %d ", hcap, hcap->hca_acc_cnt);
13110Sstevel@tonic-gate mutex_exit(&ibcm_global_hca_lock);
13120Sstevel@tonic-gate return (IBCM_SUCCESS);
13130Sstevel@tonic-gate } else {
13140Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_inc_hca_acc_cnt: "
13150Sstevel@tonic-gate "hcap INACTIVE 0x%p acc_cnt = %d ", hcap,
13160Sstevel@tonic-gate hcap->hca_acc_cnt);
13170Sstevel@tonic-gate mutex_exit(&ibcm_global_hca_lock);
13180Sstevel@tonic-gate return (IBCM_FAILURE);
13190Sstevel@tonic-gate }
13200Sstevel@tonic-gate }
13210Sstevel@tonic-gate
13220Sstevel@tonic-gate /* decrement the hca's ref count, and wake up any waiting threads */
13230Sstevel@tonic-gate void
ibcm_dec_hca_acc_cnt(ibcm_hca_info_t * hcap)13240Sstevel@tonic-gate ibcm_dec_hca_acc_cnt(ibcm_hca_info_t *hcap)
13250Sstevel@tonic-gate {
13260Sstevel@tonic-gate mutex_enter(&ibcm_global_hca_lock);
13270Sstevel@tonic-gate ASSERT(hcap->hca_acc_cnt > 0);
13280Sstevel@tonic-gate --(hcap->hca_acc_cnt);
13291093Shiremath IBTF_DPRINTF_L5(cmlog, "ibcm_dec_hca_acc_cnt: hcap = 0x%p "
13300Sstevel@tonic-gate "acc_cnt = %d", hcap, hcap->hca_acc_cnt);
13310Sstevel@tonic-gate if ((hcap->hca_state == IBCM_HCA_NOT_ACTIVE) &&
13320Sstevel@tonic-gate (hcap->hca_acc_cnt == 0)) {
13330Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibcm_dec_hca_acc_cnt: "
13340Sstevel@tonic-gate "cv_broadcast for hcap = 0x%p", hcap);
13350Sstevel@tonic-gate cv_broadcast(&ibcm_global_hca_cv);
13360Sstevel@tonic-gate }
13370Sstevel@tonic-gate mutex_exit(&ibcm_global_hca_lock);
13380Sstevel@tonic-gate }
13390Sstevel@tonic-gate
13400Sstevel@tonic-gate /* increment the hca's resource count */
13410Sstevel@tonic-gate void
ibcm_inc_hca_res_cnt(ibcm_hca_info_t * hcap)13420Sstevel@tonic-gate ibcm_inc_hca_res_cnt(ibcm_hca_info_t *hcap)
13430Sstevel@tonic-gate
13440Sstevel@tonic-gate {
13450Sstevel@tonic-gate mutex_enter(&ibcm_global_hca_lock);
13460Sstevel@tonic-gate ++(hcap->hca_res_cnt);
13471093Shiremath IBTF_DPRINTF_L5(cmlog, "ibcm_inc_hca_res_cnt: hcap = 0x%p "
13480Sstevel@tonic-gate "ref_cnt = %d", hcap, hcap->hca_res_cnt);
13490Sstevel@tonic-gate mutex_exit(&ibcm_global_hca_lock);
13500Sstevel@tonic-gate }
13510Sstevel@tonic-gate
13520Sstevel@tonic-gate /* decrement the hca's resource count, and wake up any waiting threads */
13530Sstevel@tonic-gate void
ibcm_dec_hca_res_cnt(ibcm_hca_info_t * hcap)13540Sstevel@tonic-gate ibcm_dec_hca_res_cnt(ibcm_hca_info_t *hcap)
13550Sstevel@tonic-gate {
13560Sstevel@tonic-gate mutex_enter(&ibcm_global_hca_lock);
13570Sstevel@tonic-gate ASSERT(hcap->hca_res_cnt > 0);
13580Sstevel@tonic-gate --(hcap->hca_res_cnt);
13591093Shiremath IBTF_DPRINTF_L5(cmlog, "ibcm_dec_hca_res_cnt: hcap = 0x%p "
13600Sstevel@tonic-gate "ref_cnt = %d", hcap, hcap->hca_res_cnt);
13610Sstevel@tonic-gate if ((hcap->hca_state == IBCM_HCA_NOT_ACTIVE) &&
13620Sstevel@tonic-gate (hcap->hca_res_cnt == 0)) {
13630Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibcm_dec_hca_res_cnt: "
13640Sstevel@tonic-gate "cv_broadcast for hcap = 0x%p", hcap);
13650Sstevel@tonic-gate cv_broadcast(&ibcm_global_hca_cv);
13660Sstevel@tonic-gate }
13670Sstevel@tonic-gate mutex_exit(&ibcm_global_hca_lock);
13680Sstevel@tonic-gate }
13690Sstevel@tonic-gate
13700Sstevel@tonic-gate /* increment the hca's service count */
13710Sstevel@tonic-gate void
ibcm_inc_hca_svc_cnt(ibcm_hca_info_t * hcap)13720Sstevel@tonic-gate ibcm_inc_hca_svc_cnt(ibcm_hca_info_t *hcap)
13730Sstevel@tonic-gate
13740Sstevel@tonic-gate {
13750Sstevel@tonic-gate mutex_enter(&ibcm_global_hca_lock);
13760Sstevel@tonic-gate ++(hcap->hca_svc_cnt);
13771093Shiremath IBTF_DPRINTF_L5(cmlog, "ibcm_inc_hca_svc_cnt: hcap = 0x%p "
13780Sstevel@tonic-gate "svc_cnt = %d", hcap, hcap->hca_svc_cnt);
13790Sstevel@tonic-gate mutex_exit(&ibcm_global_hca_lock);
13800Sstevel@tonic-gate }
13810Sstevel@tonic-gate
13820Sstevel@tonic-gate /* decrement the hca's service count */
13830Sstevel@tonic-gate void
ibcm_dec_hca_svc_cnt(ibcm_hca_info_t * hcap)13840Sstevel@tonic-gate ibcm_dec_hca_svc_cnt(ibcm_hca_info_t *hcap)
13850Sstevel@tonic-gate {
13860Sstevel@tonic-gate mutex_enter(&ibcm_global_hca_lock);
13870Sstevel@tonic-gate ASSERT(hcap->hca_svc_cnt > 0);
13880Sstevel@tonic-gate --(hcap->hca_svc_cnt);
13891093Shiremath IBTF_DPRINTF_L5(cmlog, "ibcm_dec_hca_svc_cnt: hcap = 0x%p "
13900Sstevel@tonic-gate "svc_cnt = %d", hcap, hcap->hca_svc_cnt);
13910Sstevel@tonic-gate mutex_exit(&ibcm_global_hca_lock);
13920Sstevel@tonic-gate }
13930Sstevel@tonic-gate
1394557Shiremath /*
13951093Shiremath * The following code manages three classes of requests that CM makes to
13961093Shiremath * the fabric. Those three classes are SA_ACCESS, REQ/REP/RTU, and DREQ/DREP.
13971093Shiremath * The main issue is that the fabric can become very busy, and the CM
13981093Shiremath * protocols rely on responses being made based on a predefined timeout
13991093Shiremath * value. By managing how many simultaneous sessions are allowed, there
14001093Shiremath * is observed extremely high reliability of CM protocol succeeding when
14011093Shiremath * it should.
14021093Shiremath *
14031093Shiremath * SA_ACCESS and DREQ/DREP are managed at the thread level, whereby the
14041093Shiremath * thread blocks until there are less than some number of threads doing
14051093Shiremath * similar requests.
14061093Shiremath *
14071093Shiremath * REQ/REP/RTU requests beyond a given limit are added to a list,
14081093Shiremath * allowing the thread to return immediately to its caller in the
14091093Shiremath * case where the "mode" is IBT_NONBLOCKING. This is the mode used
14101093Shiremath * by uDAPL and seems to be an important feature/behavior.
1411557Shiremath */
1412557Shiremath
14131093Shiremath static int
ibcm_ok_to_start(struct ibcm_open_s * openp)14141093Shiremath ibcm_ok_to_start(struct ibcm_open_s *openp)
14151093Shiremath {
14161093Shiremath return (openp->sends < openp->sends_hiwat &&
14171093Shiremath openp->in_progress < openp->in_progress_max);
14181093Shiremath }
14191093Shiremath
14201093Shiremath void
ibcm_open_done(ibcm_state_data_t * statep)14211093Shiremath ibcm_open_done(ibcm_state_data_t *statep)
14221093Shiremath {
14231093Shiremath int run;
14244045Sbillt ibcm_state_data_t **linkp, *tmp;
14251093Shiremath
14261093Shiremath ASSERT(MUTEX_HELD(&statep->state_mutex));
14271093Shiremath if (statep->open_flow == 1) {
14281093Shiremath statep->open_flow = 0;
14291093Shiremath mutex_enter(&ibcm_open.mutex);
14304045Sbillt if (statep->open_link == NULL) {
14314045Sbillt ibcm_open.in_progress--;
14324045Sbillt run = ibcm_ok_to_start(&ibcm_open);
14334045Sbillt } else {
14344045Sbillt ibcm_open.queued--;
14354045Sbillt linkp = &ibcm_open.head.open_link;
14364045Sbillt while (*linkp != statep)
14374045Sbillt linkp = &((*linkp)->open_link);
14384045Sbillt *linkp = statep->open_link;
14394045Sbillt statep->open_link = NULL;
14404045Sbillt /*
14414045Sbillt * If we remove what tail pointed to, we need
14424045Sbillt * to reassign tail (it is never NULL).
14434045Sbillt * tail points to head for the empty list.
14444045Sbillt */
14454045Sbillt if (ibcm_open.tail == statep) {
14464045Sbillt tmp = &ibcm_open.head;
14474045Sbillt while (tmp->open_link != &ibcm_open.head)
14484045Sbillt tmp = tmp->open_link;
14494045Sbillt ibcm_open.tail = tmp;
14504045Sbillt }
14514045Sbillt run = 0;
14524045Sbillt }
14531093Shiremath mutex_exit(&ibcm_open.mutex);
14541093Shiremath if (run)
14551093Shiremath ibcm_run_tlist_thread();
14561093Shiremath }
14571093Shiremath }
1458557Shiremath
14591093Shiremath /* dtrace */
14601093Shiremath void
ibcm_open_wait(hrtime_t delta)14611093Shiremath ibcm_open_wait(hrtime_t delta)
14621093Shiremath {
14631093Shiremath if (delta > 1000000)
14641093Shiremath IBTF_DPRINTF_L2(cmlog, "ibcm_open_wait: flow more %lld", delta);
14651093Shiremath }
14661093Shiremath
14671093Shiremath void
ibcm_open_start(ibcm_state_data_t * statep)14681093Shiremath ibcm_open_start(ibcm_state_data_t *statep)
14691093Shiremath {
14701093Shiremath ibcm_insert_trace(statep, IBCM_TRACE_OUTGOING_REQ);
14711093Shiremath
14721093Shiremath mutex_enter(&statep->state_mutex);
14731093Shiremath ibcm_open_wait(gethrtime() - statep->post_time);
14741093Shiremath mutex_exit(&statep->state_mutex);
14751093Shiremath
14761093Shiremath ibcm_post_rc_mad(statep, statep->stored_msg, ibcm_post_req_complete,
14771093Shiremath statep);
14781093Shiremath
14791093Shiremath mutex_enter(&statep->state_mutex);
14801093Shiremath IBCM_REF_CNT_DECR(statep);
14811093Shiremath mutex_exit(&statep->state_mutex);
14821093Shiremath }
14831093Shiremath
14841093Shiremath void
ibcm_open_enqueue(ibcm_state_data_t * statep)14851093Shiremath ibcm_open_enqueue(ibcm_state_data_t *statep)
14861093Shiremath {
14871093Shiremath int run;
1488557Shiremath
14891093Shiremath mutex_enter(&statep->state_mutex);
14901093Shiremath statep->post_time = gethrtime();
14911093Shiremath mutex_exit(&statep->state_mutex);
14921093Shiremath mutex_enter(&ibcm_open.mutex);
14931093Shiremath if (ibcm_open.queued == 0 && ibcm_ok_to_start(&ibcm_open)) {
14941093Shiremath ibcm_open.in_progress++;
14951093Shiremath mutex_exit(&ibcm_open.mutex);
14961093Shiremath ibcm_open_start(statep);
14971093Shiremath } else {
14981093Shiremath ibcm_open.queued++;
14994045Sbillt statep->open_link = &ibcm_open.head;
15001093Shiremath ibcm_open.tail->open_link = statep;
15011093Shiremath ibcm_open.tail = statep;
15021093Shiremath run = ibcm_ok_to_start(&ibcm_open);
15031093Shiremath mutex_exit(&ibcm_open.mutex);
15041093Shiremath if (run)
15051093Shiremath ibcm_run_tlist_thread();
15061093Shiremath }
15071093Shiremath }
15081093Shiremath
15091093Shiremath ibcm_state_data_t *
ibcm_open_dequeue(void)15101093Shiremath ibcm_open_dequeue(void)
15111093Shiremath {
15121093Shiremath ibcm_state_data_t *statep;
1513557Shiremath
15141093Shiremath ASSERT(MUTEX_HELD(&ibcm_open.mutex));
15151093Shiremath ibcm_open.queued--;
15161093Shiremath ibcm_open.in_progress++;
15171093Shiremath statep = ibcm_open.head.open_link;
15181093Shiremath ibcm_open.head.open_link = statep->open_link;
15191093Shiremath statep->open_link = NULL;
15204045Sbillt /*
15214045Sbillt * If we remove what tail pointed to, we need
15224045Sbillt * to reassign tail (it is never NULL).
15234045Sbillt * tail points to head for the empty list.
15244045Sbillt */
15251093Shiremath if (ibcm_open.tail == statep)
15261093Shiremath ibcm_open.tail = &ibcm_open.head;
15271093Shiremath return (statep);
15281093Shiremath }
15291093Shiremath
15301093Shiremath void
ibcm_check_for_opens(void)15311093Shiremath ibcm_check_for_opens(void)
15321093Shiremath {
15331093Shiremath ibcm_state_data_t *statep;
15341093Shiremath
15351093Shiremath mutex_enter(&ibcm_open.mutex);
15361093Shiremath
15371093Shiremath while (ibcm_open.queued > 0) {
15381093Shiremath if (ibcm_ok_to_start(&ibcm_open)) {
15391093Shiremath statep = ibcm_open_dequeue();
15401093Shiremath mutex_exit(&ibcm_open.mutex);
15411093Shiremath
15421093Shiremath ibcm_open_start(statep);
15431093Shiremath
15441093Shiremath mutex_enter(&ibcm_open.mutex);
15451093Shiremath } else {
15461093Shiremath break;
15471093Shiremath }
15481093Shiremath }
15491093Shiremath mutex_exit(&ibcm_open.mutex);
15501093Shiremath }
15511093Shiremath
1552557Shiremath
1553557Shiremath static void
ibcm_flow_init(ibcm_flow_t * flow,uint_t simul_max)1554557Shiremath ibcm_flow_init(ibcm_flow_t *flow, uint_t simul_max)
1555557Shiremath {
15561093Shiremath flow->list = NULL;
15571093Shiremath flow->simul = 0;
15581093Shiremath flow->waiters_per_chunk = 4;
15591093Shiremath flow->simul_max = simul_max;
15601093Shiremath flow->lowat = simul_max - flow->waiters_per_chunk;
15611093Shiremath flow->lowat_default = flow->lowat;
1562557Shiremath /* stats */
15631093Shiremath flow->total = 0;
1564557Shiremath }
1565557Shiremath
1566557Shiremath static void
ibcm_rc_flow_control_init(void)1567557Shiremath ibcm_rc_flow_control_init(void)
15680Sstevel@tonic-gate {
15691093Shiremath mutex_init(&ibcm_open.mutex, NULL, MUTEX_DEFAULT, NULL);
15701093Shiremath mutex_enter(&ibcm_open.mutex);
15711093Shiremath ibcm_flow_init(&ibcm_close_flow, ibcm_close_simul_max);
15721093Shiremath ibcm_flow_init(&ibcm_lapr_flow, ibcm_lapr_simul_max);
1573557Shiremath ibcm_flow_init(&ibcm_saa_flow, ibcm_saa_simul_max);
15741093Shiremath
15751093Shiremath ibcm_open.queued = 0;
15761093Shiremath ibcm_open.exit_deferred = 0;
15771093Shiremath ibcm_open.in_progress = 0;
15781093Shiremath ibcm_open.in_progress_max = 16;
15791093Shiremath ibcm_open.sends = 0;
15801093Shiremath ibcm_open.sends_max = 0;
15811093Shiremath ibcm_open.sends_lowat = 8;
15821093Shiremath ibcm_open.sends_hiwat = 16;
15831093Shiremath ibcm_open.tail = &ibcm_open.head;
15841093Shiremath ibcm_open.head.open_link = NULL;
15851093Shiremath mutex_exit(&ibcm_open.mutex);
15863241Shiremath
15873241Shiremath mutex_init(&ibcm_close.mutex, NULL, MUTEX_DEFAULT, NULL);
15883241Shiremath mutex_enter(&ibcm_close.mutex);
15893241Shiremath ibcm_close.tail = &ibcm_close.head;
15903241Shiremath ibcm_close.head.close_link = NULL;
15913241Shiremath mutex_exit(&ibcm_close.mutex);
1592557Shiremath }
1593557Shiremath
1594557Shiremath static void
ibcm_rc_flow_control_fini(void)1595557Shiremath ibcm_rc_flow_control_fini(void)
1596557Shiremath {
15971093Shiremath mutex_destroy(&ibcm_open.mutex);
15983241Shiremath mutex_destroy(&ibcm_close.mutex);
1599557Shiremath }
1600557Shiremath
1601557Shiremath static ibcm_flow1_t *
ibcm_flow_find(ibcm_flow_t * flow)1602557Shiremath ibcm_flow_find(ibcm_flow_t *flow)
1603557Shiremath {
1604557Shiremath ibcm_flow1_t *flow1;
1605557Shiremath ibcm_flow1_t *f;
1606557Shiremath
1607557Shiremath f = flow->list;
1608557Shiremath if (f) { /* most likely code path */
1609557Shiremath while (f->link != NULL)
1610557Shiremath f = f->link;
1611557Shiremath if (f->waiters < flow->waiters_per_chunk)
1612557Shiremath return (f);
1613557Shiremath }
1614557Shiremath
1615557Shiremath /* There was no flow1 list element ready for another waiter */
16161093Shiremath mutex_exit(&ibcm_open.mutex);
1617557Shiremath flow1 = kmem_alloc(sizeof (*flow1), KM_SLEEP);
16181093Shiremath mutex_enter(&ibcm_open.mutex);
1619557Shiremath
1620557Shiremath f = flow->list;
1621557Shiremath if (f) {
1622557Shiremath while (f->link != NULL)
1623557Shiremath f = f->link;
1624557Shiremath if (f->waiters < flow->waiters_per_chunk) {
1625557Shiremath kmem_free(flow1, sizeof (*flow1));
1626557Shiremath return (f);
1627557Shiremath }
1628557Shiremath f->link = flow1;
1629557Shiremath } else {
1630557Shiremath flow->list = flow1;
1631557Shiremath }
1632557Shiremath cv_init(&flow1->cv, NULL, CV_DRIVER, NULL);
1633557Shiremath flow1->waiters = 0;
1634557Shiremath flow1->link = NULL;
1635557Shiremath return (flow1);
1636557Shiremath }
1637557Shiremath
1638557Shiremath static void
ibcm_flow_enter(ibcm_flow_t * flow)1639557Shiremath ibcm_flow_enter(ibcm_flow_t *flow)
1640557Shiremath {
16411093Shiremath mutex_enter(&ibcm_open.mutex);
1642557Shiremath if (flow->list == NULL && flow->simul < flow->simul_max) {
1643557Shiremath flow->simul++;
1644557Shiremath flow->total++;
16451093Shiremath mutex_exit(&ibcm_open.mutex);
1646557Shiremath } else {
1647557Shiremath ibcm_flow1_t *flow1;
1648557Shiremath
1649557Shiremath flow1 = ibcm_flow_find(flow);
1650557Shiremath flow1->waiters++;
16511093Shiremath cv_wait(&flow1->cv, &ibcm_open.mutex);
1652557Shiremath if (--flow1->waiters == 0) {
1653557Shiremath cv_destroy(&flow1->cv);
16541093Shiremath mutex_exit(&ibcm_open.mutex);
1655557Shiremath kmem_free(flow1, sizeof (*flow1));
16561093Shiremath } else
16571093Shiremath mutex_exit(&ibcm_open.mutex);
16580Sstevel@tonic-gate }
1659557Shiremath }
1660557Shiremath
1661557Shiremath static void
ibcm_flow_exit(ibcm_flow_t * flow)1662557Shiremath ibcm_flow_exit(ibcm_flow_t *flow)
1663557Shiremath {
16641093Shiremath mutex_enter(&ibcm_open.mutex);
1665557Shiremath if (--flow->simul < flow->lowat) {
16661093Shiremath if (flow->lowat < flow->lowat_default)
16671093Shiremath flow->lowat++;
1668557Shiremath if (flow->list) {
1669557Shiremath ibcm_flow1_t *flow1;
1670557Shiremath
1671557Shiremath flow1 = flow->list;
1672557Shiremath flow->list = flow1->link; /* unlink */
1673557Shiremath flow1->link = NULL; /* be clean */
1674557Shiremath flow->total += flow1->waiters;
1675557Shiremath flow->simul += flow1->waiters;
1676557Shiremath cv_broadcast(&flow1->cv);
1677557Shiremath }
16780Sstevel@tonic-gate }
16791093Shiremath mutex_exit(&ibcm_open.mutex);
16801093Shiremath }
16811093Shiremath
16821093Shiremath void
ibcm_flow_inc(void)16831093Shiremath ibcm_flow_inc(void)
16841093Shiremath {
16851093Shiremath mutex_enter(&ibcm_open.mutex);
16861093Shiremath if (++ibcm_open.sends > ibcm_open.sends_max) {
16871093Shiremath ibcm_open.sends_max = ibcm_open.sends;
16881093Shiremath IBTF_DPRINTF_L2(cmlog, "ibcm_flow_inc: sends max = %d",
16891093Shiremath ibcm_open.sends_max);
16901093Shiremath }
16911093Shiremath mutex_exit(&ibcm_open.mutex);
1692557Shiremath }
1693557Shiremath
1694557Shiremath static void
ibcm_check_send_cmpltn_time(hrtime_t delta,char * event_msg)16951093Shiremath ibcm_check_send_cmpltn_time(hrtime_t delta, char *event_msg)
1696557Shiremath {
16971093Shiremath if (delta > 4000000LL) {
16981093Shiremath IBTF_DPRINTF_L2(cmlog, "ibcm_check_send_cmpltn_time: "
16991093Shiremath "%s: %lldns", event_msg, delta);
1700557Shiremath }
17010Sstevel@tonic-gate }
17020Sstevel@tonic-gate
17030Sstevel@tonic-gate void
ibcm_flow_dec(hrtime_t time,char * mad_type)17041093Shiremath ibcm_flow_dec(hrtime_t time, char *mad_type)
17050Sstevel@tonic-gate {
17061093Shiremath int flow_exit = 0;
17071093Shiremath int run = 0;
17081093Shiremath
17091093Shiremath if (ibcm_dtrace)
17101093Shiremath ibcm_check_send_cmpltn_time(gethrtime() - time, mad_type);
17111093Shiremath mutex_enter(&ibcm_open.mutex);
17121093Shiremath ibcm_open.sends--;
17131093Shiremath if (ibcm_open.sends < ibcm_open.sends_lowat) {
17141093Shiremath run = ibcm_ok_to_start(&ibcm_open);
17151093Shiremath if (ibcm_open.exit_deferred) {
17161093Shiremath ibcm_open.exit_deferred--;
17171093Shiremath flow_exit = 1;
17181093Shiremath }
17191093Shiremath }
17201093Shiremath mutex_exit(&ibcm_open.mutex);
17211093Shiremath if (flow_exit)
17221093Shiremath ibcm_flow_exit(&ibcm_close_flow);
17231093Shiremath if (run)
17241093Shiremath ibcm_run_tlist_thread();
1725557Shiremath }
1726557Shiremath
1727557Shiremath void
ibcm_close_enqueue(ibcm_state_data_t * statep)17283241Shiremath ibcm_close_enqueue(ibcm_state_data_t *statep)
17293241Shiremath {
17303241Shiremath mutex_enter(&ibcm_close.mutex);
17313241Shiremath statep->close_link = NULL;
17323241Shiremath ibcm_close.tail->close_link = statep;
17333241Shiremath ibcm_close.tail = statep;
17343241Shiremath mutex_exit(&ibcm_close.mutex);
17353241Shiremath ibcm_run_tlist_thread();
17363241Shiremath }
17373241Shiremath
17383241Shiremath void
ibcm_check_for_async_close()17393241Shiremath ibcm_check_for_async_close()
17403241Shiremath {
17413241Shiremath ibcm_state_data_t *statep;
17423241Shiremath
17433241Shiremath mutex_enter(&ibcm_close.mutex);
17443241Shiremath
17453241Shiremath while (ibcm_close.head.close_link) {
17463241Shiremath statep = ibcm_close.head.close_link;
17473241Shiremath ibcm_close.head.close_link = statep->close_link;
17483241Shiremath statep->close_link = NULL;
17493241Shiremath if (ibcm_close.tail == statep)
17503241Shiremath ibcm_close.tail = &ibcm_close.head;
17513241Shiremath mutex_exit(&ibcm_close.mutex);
17523241Shiremath ibcm_close_start(statep);
17533241Shiremath mutex_enter(&ibcm_close.mutex);
17543241Shiremath }
17553241Shiremath mutex_exit(&ibcm_close.mutex);
17563241Shiremath }
17573241Shiremath
17583241Shiremath void
ibcm_close_enter(void)17591093Shiremath ibcm_close_enter(void)
17600Sstevel@tonic-gate {
1761557Shiremath ibcm_flow_enter(&ibcm_close_flow);
17620Sstevel@tonic-gate }
17630Sstevel@tonic-gate
17640Sstevel@tonic-gate void
ibcm_close_exit(void)17651093Shiremath ibcm_close_exit(void)
17660Sstevel@tonic-gate {
17671093Shiremath int flow_exit;
17681093Shiremath
17691093Shiremath mutex_enter(&ibcm_open.mutex);
17701093Shiremath if (ibcm_open.sends < ibcm_open.sends_lowat ||
17711093Shiremath ibcm_open.exit_deferred >= 4)
17721093Shiremath flow_exit = 1;
17731093Shiremath else {
17741093Shiremath flow_exit = 0;
17751093Shiremath ibcm_open.exit_deferred++;
17761093Shiremath }
17771093Shiremath mutex_exit(&ibcm_open.mutex);
17781093Shiremath if (flow_exit)
17791093Shiremath ibcm_flow_exit(&ibcm_close_flow);
17801093Shiremath }
17811093Shiremath
17821093Shiremath /*
17831093Shiremath * This function needs to be called twice to finish our flow
17841093Shiremath * control accounting when closing down a connection. One
17851093Shiremath * call has send_done set to 1, while the other has it set to 0.
17861093Shiremath * Because of retries, this could get called more than once
17871093Shiremath * with either 0 or 1, but additional calls have no effect.
17881093Shiremath */
17891093Shiremath void
ibcm_close_done(ibcm_state_data_t * statep,int send_done)17901093Shiremath ibcm_close_done(ibcm_state_data_t *statep, int send_done)
17911093Shiremath {
17921093Shiremath int flow_exit;
17931093Shiremath
17941093Shiremath ASSERT(MUTEX_HELD(&statep->state_mutex));
17951093Shiremath if (statep->close_flow == 1) {
17961093Shiremath if (send_done)
17971093Shiremath statep->close_flow = 3;
17981093Shiremath else
17991093Shiremath statep->close_flow = 2;
18001093Shiremath } else if ((send_done && statep->close_flow == 2) ||
18011093Shiremath (!send_done && statep->close_flow == 3)) {
18021093Shiremath statep->close_flow = 0;
18031093Shiremath mutex_enter(&ibcm_open.mutex);
18041093Shiremath if (ibcm_open.sends < ibcm_open.sends_lowat ||
18051093Shiremath ibcm_open.exit_deferred >= 4)
18061093Shiremath flow_exit = 1;
18071093Shiremath else {
18081093Shiremath flow_exit = 0;
18091093Shiremath ibcm_open.exit_deferred++;
18101093Shiremath }
18111093Shiremath mutex_exit(&ibcm_open.mutex);
18121093Shiremath if (flow_exit)
18131093Shiremath ibcm_flow_exit(&ibcm_close_flow);
18141093Shiremath }
18150Sstevel@tonic-gate }
18160Sstevel@tonic-gate
18170Sstevel@tonic-gate void
ibcm_lapr_enter(void)18181093Shiremath ibcm_lapr_enter(void)
18190Sstevel@tonic-gate {
18201093Shiremath ibcm_flow_enter(&ibcm_lapr_flow);
18211093Shiremath }
18221093Shiremath
18231093Shiremath void
ibcm_lapr_exit(void)18241093Shiremath ibcm_lapr_exit(void)
18251093Shiremath {
18261093Shiremath ibcm_flow_exit(&ibcm_lapr_flow);
18270Sstevel@tonic-gate }
18280Sstevel@tonic-gate
18290Sstevel@tonic-gate void
ibcm_sa_access_enter()18300Sstevel@tonic-gate ibcm_sa_access_enter()
18310Sstevel@tonic-gate {
1832557Shiremath ibcm_flow_enter(&ibcm_saa_flow);
18330Sstevel@tonic-gate }
18340Sstevel@tonic-gate
18350Sstevel@tonic-gate void
ibcm_sa_access_exit()18360Sstevel@tonic-gate ibcm_sa_access_exit()
18370Sstevel@tonic-gate {
1838557Shiremath ibcm_flow_exit(&ibcm_saa_flow);
18390Sstevel@tonic-gate }
18400Sstevel@tonic-gate
18410Sstevel@tonic-gate static void
ibcm_sm_notice_handler(ibmf_saa_handle_t saa_handle,ibmf_saa_subnet_event_t saa_event_code,ibmf_saa_event_details_t * saa_event_details,void * callback_arg)18420Sstevel@tonic-gate ibcm_sm_notice_handler(ibmf_saa_handle_t saa_handle,
18430Sstevel@tonic-gate ibmf_saa_subnet_event_t saa_event_code,
18440Sstevel@tonic-gate ibmf_saa_event_details_t *saa_event_details,
18450Sstevel@tonic-gate void *callback_arg)
18460Sstevel@tonic-gate {
18470Sstevel@tonic-gate ibcm_port_info_t *portp = (ibcm_port_info_t *)callback_arg;
18480Sstevel@tonic-gate ibt_subnet_event_code_t code;
18490Sstevel@tonic-gate ibt_subnet_event_t event;
18500Sstevel@tonic-gate uint8_t event_status;
18510Sstevel@tonic-gate
18520Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibcm_sm_notice_handler: saa_hdl %p, code = %d",
18530Sstevel@tonic-gate saa_handle, saa_event_code);
18540Sstevel@tonic-gate
18550Sstevel@tonic-gate mutex_enter(&ibcm_sm_notice_serialize_lock);
18560Sstevel@tonic-gate
18570Sstevel@tonic-gate switch (saa_event_code) {
18580Sstevel@tonic-gate case IBMF_SAA_EVENT_MCG_CREATED:
18590Sstevel@tonic-gate code = IBT_SM_EVENT_MCG_CREATED;
18600Sstevel@tonic-gate break;
18610Sstevel@tonic-gate case IBMF_SAA_EVENT_MCG_DELETED:
18620Sstevel@tonic-gate code = IBT_SM_EVENT_MCG_DELETED;
18630Sstevel@tonic-gate break;
18640Sstevel@tonic-gate case IBMF_SAA_EVENT_GID_AVAILABLE:
18650Sstevel@tonic-gate code = IBT_SM_EVENT_GID_AVAIL;
1866557Shiremath ibcm_path_cache_purge();
18670Sstevel@tonic-gate break;
18680Sstevel@tonic-gate case IBMF_SAA_EVENT_GID_UNAVAILABLE:
18690Sstevel@tonic-gate code = IBT_SM_EVENT_GID_UNAVAIL;
1870557Shiremath ibcm_path_cache_purge();
18710Sstevel@tonic-gate break;
18720Sstevel@tonic-gate case IBMF_SAA_EVENT_SUBSCRIBER_STATUS_CHG:
18730Sstevel@tonic-gate event_status =
18740Sstevel@tonic-gate saa_event_details->ie_producer_event_status_mask &
18750Sstevel@tonic-gate IBMF_SAA_EVENT_STATUS_MASK_PRODUCER_SM;
18760Sstevel@tonic-gate if (event_status == (portp->port_event_status &
18770Sstevel@tonic-gate IBMF_SAA_EVENT_STATUS_MASK_PRODUCER_SM)) {
18780Sstevel@tonic-gate mutex_exit(&ibcm_sm_notice_serialize_lock);
18790Sstevel@tonic-gate return; /* no change */
18800Sstevel@tonic-gate }
18810Sstevel@tonic-gate portp->port_event_status = event_status;
18820Sstevel@tonic-gate if (event_status == IBMF_SAA_EVENT_STATUS_MASK_PRODUCER_SM)
18830Sstevel@tonic-gate code = IBT_SM_EVENT_AVAILABLE;
18840Sstevel@tonic-gate else
18850Sstevel@tonic-gate code = IBT_SM_EVENT_UNAVAILABLE;
18860Sstevel@tonic-gate break;
18870Sstevel@tonic-gate default:
18880Sstevel@tonic-gate mutex_exit(&ibcm_sm_notice_serialize_lock);
18890Sstevel@tonic-gate return;
18900Sstevel@tonic-gate }
18910Sstevel@tonic-gate
18920Sstevel@tonic-gate mutex_enter(&ibcm_global_hca_lock);
18930Sstevel@tonic-gate
18940Sstevel@tonic-gate /* don't send the event if we're tearing down */
18950Sstevel@tonic-gate if (!IBCM_ACCESS_HCA_OK(portp->port_hcap)) {
18960Sstevel@tonic-gate mutex_exit(&ibcm_global_hca_lock);
18970Sstevel@tonic-gate mutex_exit(&ibcm_sm_notice_serialize_lock);
18980Sstevel@tonic-gate return;
18990Sstevel@tonic-gate }
19000Sstevel@tonic-gate
19010Sstevel@tonic-gate ++(portp->port_hcap->hca_acc_cnt);
19020Sstevel@tonic-gate mutex_exit(&ibcm_global_hca_lock);
19030Sstevel@tonic-gate
19040Sstevel@tonic-gate event.sm_notice_gid = saa_event_details->ie_gid;
19050Sstevel@tonic-gate ibtl_cm_sm_notice_handler(portp->port_sgid0, code, &event);
19060Sstevel@tonic-gate
19070Sstevel@tonic-gate mutex_exit(&ibcm_sm_notice_serialize_lock);
19080Sstevel@tonic-gate
19090Sstevel@tonic-gate ibcm_dec_hca_acc_cnt(portp->port_hcap);
19100Sstevel@tonic-gate }
19110Sstevel@tonic-gate
19120Sstevel@tonic-gate void
ibt_register_subnet_notices(ibt_clnt_hdl_t ibt_hdl,ibt_sm_notice_handler_t sm_notice_handler,void * private)19130Sstevel@tonic-gate ibt_register_subnet_notices(ibt_clnt_hdl_t ibt_hdl,
19140Sstevel@tonic-gate ibt_sm_notice_handler_t sm_notice_handler, void *private)
19150Sstevel@tonic-gate {
19160Sstevel@tonic-gate ibcm_port_info_t *portp;
19170Sstevel@tonic-gate ibcm_hca_info_t *hcap;
19180Sstevel@tonic-gate uint8_t port;
19190Sstevel@tonic-gate int num_failed_sgids;
19200Sstevel@tonic-gate ibtl_cm_sm_init_fail_t *ifail;
19210Sstevel@tonic-gate ib_gid_t *sgidp;
19220Sstevel@tonic-gate
1923*9913SShantkumar.Hiremath@Sun.COM IBTF_DPRINTF_L3(cmlog, "ibt_register_subnet_notices(%p, %s)",
1924*9913SShantkumar.Hiremath@Sun.COM ibt_hdl, ibtl_cm_get_clnt_name(ibt_hdl));
19250Sstevel@tonic-gate
19260Sstevel@tonic-gate mutex_enter(&ibcm_sm_notice_serialize_lock);
19270Sstevel@tonic-gate
19280Sstevel@tonic-gate ibtl_cm_set_sm_notice_handler(ibt_hdl, sm_notice_handler, private);
19290Sstevel@tonic-gate if (sm_notice_handler == NULL) {
19300Sstevel@tonic-gate mutex_exit(&ibcm_sm_notice_serialize_lock);
19310Sstevel@tonic-gate return;
19320Sstevel@tonic-gate }
19330Sstevel@tonic-gate
19340Sstevel@tonic-gate /* for each port, if service is not available, make a call */
19350Sstevel@tonic-gate mutex_enter(&ibcm_global_hca_lock);
19360Sstevel@tonic-gate num_failed_sgids = 0;
19370Sstevel@tonic-gate hcap = ibcm_hca_listp;
19380Sstevel@tonic-gate while (hcap != NULL) {
19390Sstevel@tonic-gate portp = hcap->hca_port_info;
19400Sstevel@tonic-gate for (port = 0; port < hcap->hca_num_ports; port++) {
19410Sstevel@tonic-gate if (!(portp->port_event_status &
19420Sstevel@tonic-gate IBMF_SAA_EVENT_STATUS_MASK_PRODUCER_SM))
19430Sstevel@tonic-gate num_failed_sgids++;
19440Sstevel@tonic-gate portp++;
19450Sstevel@tonic-gate }
19460Sstevel@tonic-gate hcap = hcap->hca_next;
19470Sstevel@tonic-gate }
19480Sstevel@tonic-gate if (num_failed_sgids != 0) {
19490Sstevel@tonic-gate ifail = kmem_alloc(sizeof (*ifail) +
19500Sstevel@tonic-gate (num_failed_sgids - 1) * sizeof (ib_gid_t), KM_SLEEP);
19510Sstevel@tonic-gate ifail->smf_num_sgids = num_failed_sgids;
19520Sstevel@tonic-gate ifail->smf_ibt_hdl = ibt_hdl;
19530Sstevel@tonic-gate sgidp = &ifail->smf_sgid[0];
19540Sstevel@tonic-gate hcap = ibcm_hca_listp;
19550Sstevel@tonic-gate while (hcap != NULL) {
19560Sstevel@tonic-gate portp = hcap->hca_port_info;
19570Sstevel@tonic-gate for (port = 0; port < hcap->hca_num_ports; port++) {
19580Sstevel@tonic-gate if (!(portp->port_event_status &
19590Sstevel@tonic-gate IBMF_SAA_EVENT_STATUS_MASK_PRODUCER_SM))
19600Sstevel@tonic-gate *sgidp++ = portp->port_sgid0;
19610Sstevel@tonic-gate portp++;
19620Sstevel@tonic-gate }
19630Sstevel@tonic-gate hcap = hcap->hca_next;
19640Sstevel@tonic-gate }
19650Sstevel@tonic-gate }
19660Sstevel@tonic-gate mutex_exit(&ibcm_global_hca_lock);
19670Sstevel@tonic-gate
19680Sstevel@tonic-gate if (num_failed_sgids != 0) {
19690Sstevel@tonic-gate ibtl_cm_sm_notice_init_failure(ifail);
19700Sstevel@tonic-gate kmem_free(ifail, sizeof (*ifail) +
19710Sstevel@tonic-gate (num_failed_sgids - 1) * sizeof (ib_gid_t));
19720Sstevel@tonic-gate }
19730Sstevel@tonic-gate mutex_exit(&ibcm_sm_notice_serialize_lock);
19740Sstevel@tonic-gate }
19750Sstevel@tonic-gate
19760Sstevel@tonic-gate /* The following is run from a taskq because we've seen the stack overflow. */
19770Sstevel@tonic-gate static void
ibcm_init_saa(void * arg)19780Sstevel@tonic-gate ibcm_init_saa(void *arg)
19790Sstevel@tonic-gate {
19800Sstevel@tonic-gate ibcm_port_info_t *portp = (ibcm_port_info_t *)arg;
19810Sstevel@tonic-gate int status;
19820Sstevel@tonic-gate ib_guid_t port_guid;
19830Sstevel@tonic-gate ibmf_saa_subnet_event_args_t event_args;
19840Sstevel@tonic-gate
19850Sstevel@tonic-gate port_guid = portp->port_sgid0.gid_guid;
19860Sstevel@tonic-gate
19870Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibcm_init_saa: port guid %llX", port_guid);
19880Sstevel@tonic-gate
19890Sstevel@tonic-gate event_args.is_event_callback_arg = portp;
19900Sstevel@tonic-gate event_args.is_event_callback = ibcm_sm_notice_handler;
19910Sstevel@tonic-gate
19920Sstevel@tonic-gate if ((status = ibmf_sa_session_open(port_guid, 0, &event_args,
19930Sstevel@tonic-gate IBMF_VERSION, 0, &portp->port_ibmf_saa_hdl)) != IBMF_SUCCESS) {
19941093Shiremath IBTF_DPRINTF_L2(cmlog, "ibcm_init_saa: "
19950Sstevel@tonic-gate "ibmf_sa_session_open failed for port guid %llX "
19960Sstevel@tonic-gate "status = %d", port_guid, status);
19970Sstevel@tonic-gate } else {
19981093Shiremath IBTF_DPRINTF_L2(cmlog, "ibcm_init_saa: "
19990Sstevel@tonic-gate "registered sa_hdl 0x%p for port guid %llX",
20000Sstevel@tonic-gate portp->port_ibmf_saa_hdl, port_guid);
20010Sstevel@tonic-gate }
20020Sstevel@tonic-gate
20030Sstevel@tonic-gate mutex_enter(&ibcm_sa_open_lock);
20040Sstevel@tonic-gate portp->port_saa_open_in_progress = 0;
20050Sstevel@tonic-gate cv_broadcast(&ibcm_sa_open_cv);
20060Sstevel@tonic-gate mutex_exit(&ibcm_sa_open_lock);
20070Sstevel@tonic-gate }
20080Sstevel@tonic-gate
20090Sstevel@tonic-gate void
ibcm_init_saa_handle(ibcm_hca_info_t * hcap,uint8_t port)20100Sstevel@tonic-gate ibcm_init_saa_handle(ibcm_hca_info_t *hcap, uint8_t port)
20110Sstevel@tonic-gate {
20120Sstevel@tonic-gate ibmf_saa_handle_t saa_handle;
20130Sstevel@tonic-gate uint8_t port_index = port - 1;
20140Sstevel@tonic-gate ibcm_port_info_t *portp = &hcap->hca_port_info[port_index];
20150Sstevel@tonic-gate ibt_status_t ibt_status;
20160Sstevel@tonic-gate
20170Sstevel@tonic-gate if (port_index >= hcap->hca_num_ports)
20180Sstevel@tonic-gate return;
20190Sstevel@tonic-gate
20200Sstevel@tonic-gate mutex_enter(&ibcm_sa_open_lock);
20210Sstevel@tonic-gate if (portp->port_saa_open_in_progress) {
20220Sstevel@tonic-gate mutex_exit(&ibcm_sa_open_lock);
20230Sstevel@tonic-gate return;
20240Sstevel@tonic-gate }
20250Sstevel@tonic-gate
20260Sstevel@tonic-gate saa_handle = portp->port_ibmf_saa_hdl;
20270Sstevel@tonic-gate if (saa_handle != NULL) {
20280Sstevel@tonic-gate mutex_exit(&ibcm_sa_open_lock);
20290Sstevel@tonic-gate return;
20300Sstevel@tonic-gate }
20310Sstevel@tonic-gate
20320Sstevel@tonic-gate portp->port_saa_open_in_progress = 1;
20330Sstevel@tonic-gate mutex_exit(&ibcm_sa_open_lock);
20340Sstevel@tonic-gate
20350Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(portp->port_event_status))
20360Sstevel@tonic-gate
20370Sstevel@tonic-gate /* The assumption is that we're getting event notifications */
20380Sstevel@tonic-gate portp->port_event_status = IBMF_SAA_EVENT_STATUS_MASK_PRODUCER_SM;
20390Sstevel@tonic-gate
20400Sstevel@tonic-gate _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(portp->port_event_status))
20410Sstevel@tonic-gate
20420Sstevel@tonic-gate ibt_status = ibt_get_port_state_byguid(portp->port_hcap->hca_guid,
20430Sstevel@tonic-gate portp->port_num, &portp->port_sgid0, NULL);
20440Sstevel@tonic-gate if (ibt_status != IBT_SUCCESS) {
20451093Shiremath IBTF_DPRINTF_L2(cmlog, "ibcm_init_saa_handle: "
20460Sstevel@tonic-gate "ibt_get_port_state_byguid failed for guid %llX "
20470Sstevel@tonic-gate "with status %d", portp->port_hcap->hca_guid, ibt_status);
20480Sstevel@tonic-gate mutex_enter(&ibcm_sa_open_lock);
20490Sstevel@tonic-gate portp->port_saa_open_in_progress = 0;
20500Sstevel@tonic-gate cv_broadcast(&ibcm_sa_open_cv);
20510Sstevel@tonic-gate mutex_exit(&ibcm_sa_open_lock);
20520Sstevel@tonic-gate return;
20530Sstevel@tonic-gate }
20540Sstevel@tonic-gate /* if the port is UP, try sa_session_open */
20550Sstevel@tonic-gate (void) taskq_dispatch(ibcm_taskq, ibcm_init_saa, portp, TQ_SLEEP);
20560Sstevel@tonic-gate }
20570Sstevel@tonic-gate
20580Sstevel@tonic-gate
20590Sstevel@tonic-gate ibmf_saa_handle_t
ibcm_get_saa_handle(ibcm_hca_info_t * hcap,uint8_t port)20600Sstevel@tonic-gate ibcm_get_saa_handle(ibcm_hca_info_t *hcap, uint8_t port)
20610Sstevel@tonic-gate {
20620Sstevel@tonic-gate ibmf_saa_handle_t saa_handle;
20630Sstevel@tonic-gate uint8_t port_index = port - 1;
20640Sstevel@tonic-gate ibcm_port_info_t *portp = &hcap->hca_port_info[port_index];
20650Sstevel@tonic-gate ibt_status_t ibt_status;
20660Sstevel@tonic-gate
20670Sstevel@tonic-gate if (port_index >= hcap->hca_num_ports)
20680Sstevel@tonic-gate return (NULL);
20690Sstevel@tonic-gate
20700Sstevel@tonic-gate mutex_enter(&ibcm_sa_open_lock);
20710Sstevel@tonic-gate while (portp->port_saa_open_in_progress) {
20720Sstevel@tonic-gate cv_wait(&ibcm_sa_open_cv, &ibcm_sa_open_lock);
20730Sstevel@tonic-gate }
20740Sstevel@tonic-gate
20750Sstevel@tonic-gate saa_handle = portp->port_ibmf_saa_hdl;
20760Sstevel@tonic-gate if (saa_handle != NULL) {
20770Sstevel@tonic-gate mutex_exit(&ibcm_sa_open_lock);
20780Sstevel@tonic-gate return (saa_handle);
20790Sstevel@tonic-gate }
20800Sstevel@tonic-gate
20810Sstevel@tonic-gate portp->port_saa_open_in_progress = 1;
20820Sstevel@tonic-gate mutex_exit(&ibcm_sa_open_lock);
20830Sstevel@tonic-gate
20840Sstevel@tonic-gate ibt_status = ibt_get_port_state_byguid(portp->port_hcap->hca_guid,
20850Sstevel@tonic-gate portp->port_num, &portp->port_sgid0, NULL);
20860Sstevel@tonic-gate if (ibt_status != IBT_SUCCESS) {
20871093Shiremath IBTF_DPRINTF_L2(cmlog, "ibcm_get_saa_handle: "
20880Sstevel@tonic-gate "ibt_get_port_state_byguid failed for guid %llX "
20890Sstevel@tonic-gate "with status %d", portp->port_hcap->hca_guid, ibt_status);
20900Sstevel@tonic-gate mutex_enter(&ibcm_sa_open_lock);
20910Sstevel@tonic-gate portp->port_saa_open_in_progress = 0;
20920Sstevel@tonic-gate cv_broadcast(&ibcm_sa_open_cv);
20930Sstevel@tonic-gate mutex_exit(&ibcm_sa_open_lock);
20940Sstevel@tonic-gate return (NULL);
20950Sstevel@tonic-gate }
20960Sstevel@tonic-gate /* if the port is UP, try sa_session_open */
20970Sstevel@tonic-gate (void) taskq_dispatch(ibcm_taskq, ibcm_init_saa, portp, TQ_SLEEP);
20980Sstevel@tonic-gate
20990Sstevel@tonic-gate mutex_enter(&ibcm_sa_open_lock);
21000Sstevel@tonic-gate while (portp->port_saa_open_in_progress) {
21010Sstevel@tonic-gate cv_wait(&ibcm_sa_open_cv, &ibcm_sa_open_lock);
21020Sstevel@tonic-gate }
21030Sstevel@tonic-gate saa_handle = portp->port_ibmf_saa_hdl;
21040Sstevel@tonic-gate mutex_exit(&ibcm_sa_open_lock);
21050Sstevel@tonic-gate return (saa_handle);
21060Sstevel@tonic-gate }
21070Sstevel@tonic-gate
21080Sstevel@tonic-gate
21090Sstevel@tonic-gate /*
21100Sstevel@tonic-gate * ibcm_hca_init_port():
21110Sstevel@tonic-gate * - Register port with IBMA
21120Sstevel@tonic-gate *
21130Sstevel@tonic-gate * Arguments:
21140Sstevel@tonic-gate * hcap - HCA's guid
21150Sstevel@tonic-gate * port_index - port number minus 1
21160Sstevel@tonic-gate *
21170Sstevel@tonic-gate * Return values:
21180Sstevel@tonic-gate * IBCM_SUCCESS - success
21190Sstevel@tonic-gate */
21200Sstevel@tonic-gate ibt_status_t
ibcm_hca_init_port(ibcm_hca_info_t * hcap,uint8_t port_index)21210Sstevel@tonic-gate ibcm_hca_init_port(ibcm_hca_info_t *hcap, uint8_t port_index)
21220Sstevel@tonic-gate {
21230Sstevel@tonic-gate int status;
21240Sstevel@tonic-gate ibmf_register_info_t *ibmf_reg;
21250Sstevel@tonic-gate
21260Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibcm_hca_init_port: hcap = 0x%p port_num %d",
21270Sstevel@tonic-gate hcap, port_index + 1);
21280Sstevel@tonic-gate
21290Sstevel@tonic-gate ASSERT(MUTEX_HELD(&ibcm_global_hca_lock));
21300Sstevel@tonic-gate
21310Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(hcap->hca_port_info))
21320Sstevel@tonic-gate
21330Sstevel@tonic-gate if (hcap->hca_port_info[port_index].port_ibmf_hdl == NULL) {
21340Sstevel@tonic-gate /* Register with IBMF */
21350Sstevel@tonic-gate ibmf_reg = &hcap->hca_port_info[port_index].port_ibmf_reg;
21360Sstevel@tonic-gate ibmf_reg->ir_ci_guid = hcap->hca_guid;
21370Sstevel@tonic-gate ibmf_reg->ir_port_num = port_index + 1;
21380Sstevel@tonic-gate ibmf_reg->ir_client_class = COMM_MGT_MANAGER_AGENT;
21390Sstevel@tonic-gate
21400Sstevel@tonic-gate /*
21410Sstevel@tonic-gate * register with management framework
21420Sstevel@tonic-gate */
21430Sstevel@tonic-gate status = ibmf_register(ibmf_reg, IBMF_VERSION,
21440Sstevel@tonic-gate IBMF_REG_FLAG_NO_OFFLOAD, NULL, NULL,
21450Sstevel@tonic-gate &(hcap->hca_port_info[port_index].port_ibmf_hdl),
21460Sstevel@tonic-gate &(hcap->hca_port_info[port_index].port_ibmf_caps));
21470Sstevel@tonic-gate
21480Sstevel@tonic-gate if (status != IBMF_SUCCESS) {
21490Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_hca_init_port: "
21500Sstevel@tonic-gate "ibmf_register failed for port_num %x, "
21510Sstevel@tonic-gate "status = %x", port_index + 1, status);
21520Sstevel@tonic-gate return (ibcm_ibmf_analyze_error(status));
21530Sstevel@tonic-gate }
21540Sstevel@tonic-gate
21550Sstevel@tonic-gate hcap->hca_port_info[port_index].port_qp1.qp_cm =
21560Sstevel@tonic-gate IBMF_QP_HANDLE_DEFAULT;
21570Sstevel@tonic-gate hcap->hca_port_info[port_index].port_qp1.qp_port =
21580Sstevel@tonic-gate &(hcap->hca_port_info[port_index]);
21590Sstevel@tonic-gate
21600Sstevel@tonic-gate /*
21610Sstevel@tonic-gate * Register the read callback with IBMF.
21620Sstevel@tonic-gate * Since we just did an ibmf_register, handle is
21630Sstevel@tonic-gate * valid and ibcm_recv_cb() is valid so we can
21640Sstevel@tonic-gate * safely assert for success of ibmf_setup_recv_cb()
21650Sstevel@tonic-gate *
21660Sstevel@tonic-gate * Depending on the "state" of the HCA,
21670Sstevel@tonic-gate * CM may drop incoming packets
21680Sstevel@tonic-gate */
21690Sstevel@tonic-gate status = ibmf_setup_async_cb(
21700Sstevel@tonic-gate hcap->hca_port_info[port_index].port_ibmf_hdl,
21710Sstevel@tonic-gate IBMF_QP_HANDLE_DEFAULT, ibcm_recv_cb,
21720Sstevel@tonic-gate &(hcap->hca_port_info[port_index].port_qp1), 0);
21730Sstevel@tonic-gate ASSERT(status == IBMF_SUCCESS);
21740Sstevel@tonic-gate
21750Sstevel@tonic-gate IBTF_DPRINTF_L5(cmlog, "ibcm_hca_init_port: "
21760Sstevel@tonic-gate "IBMF hdl[%x] = 0x%p", port_index,
21770Sstevel@tonic-gate hcap->hca_port_info[port_index].port_ibmf_hdl);
21780Sstevel@tonic-gate
21790Sstevel@tonic-gate /* Attempt to get the saa_handle for this port */
21800Sstevel@tonic-gate ibcm_init_saa_handle(hcap, port_index + 1);
21810Sstevel@tonic-gate }
21820Sstevel@tonic-gate
21830Sstevel@tonic-gate return (IBT_SUCCESS);
21840Sstevel@tonic-gate }
21850Sstevel@tonic-gate
21860Sstevel@tonic-gate /*
21870Sstevel@tonic-gate * useful, to re attempt to initialize port ibma handles from elsewhere in
21880Sstevel@tonic-gate * cm code
21890Sstevel@tonic-gate */
21900Sstevel@tonic-gate ibt_status_t
ibcm_hca_reinit_port(ibcm_hca_info_t * hcap,uint8_t port_index)21910Sstevel@tonic-gate ibcm_hca_reinit_port(ibcm_hca_info_t *hcap, uint8_t port_index)
21920Sstevel@tonic-gate {
21930Sstevel@tonic-gate ibt_status_t status;
21940Sstevel@tonic-gate
21950Sstevel@tonic-gate IBTF_DPRINTF_L5(cmlog, "ibcm_hca_reinit_port: hcap 0x%p port_num %d",
21960Sstevel@tonic-gate hcap, port_index + 1);
21970Sstevel@tonic-gate
21980Sstevel@tonic-gate mutex_enter(&ibcm_global_hca_lock);
21990Sstevel@tonic-gate status = ibcm_hca_init_port(hcap, port_index);
22000Sstevel@tonic-gate mutex_exit(&ibcm_global_hca_lock);
22010Sstevel@tonic-gate return (status);
22020Sstevel@tonic-gate }
22030Sstevel@tonic-gate
22040Sstevel@tonic-gate
22050Sstevel@tonic-gate /*
22060Sstevel@tonic-gate * ibcm_hca_fini_port():
22070Sstevel@tonic-gate * - Deregister port with IBMA
22080Sstevel@tonic-gate *
22090Sstevel@tonic-gate * Arguments:
22100Sstevel@tonic-gate * hcap - HCA's guid
22110Sstevel@tonic-gate * port_index - port number minus 1
22120Sstevel@tonic-gate *
22130Sstevel@tonic-gate * Return values:
22140Sstevel@tonic-gate * IBCM_SUCCESS - success
22150Sstevel@tonic-gate */
22160Sstevel@tonic-gate static ibcm_status_t
ibcm_hca_fini_port(ibcm_hca_info_t * hcap,uint8_t port_index)22170Sstevel@tonic-gate ibcm_hca_fini_port(ibcm_hca_info_t *hcap, uint8_t port_index)
22180Sstevel@tonic-gate {
22190Sstevel@tonic-gate int ibmf_status;
22200Sstevel@tonic-gate ibcm_status_t ibcm_status;
22210Sstevel@tonic-gate
22220Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibcm_hca_fini_port: hcap = 0x%p port_num %d ",
22230Sstevel@tonic-gate hcap, port_index + 1);
22240Sstevel@tonic-gate
22250Sstevel@tonic-gate ASSERT(MUTEX_HELD(&ibcm_global_hca_lock));
22260Sstevel@tonic-gate
22270Sstevel@tonic-gate if (hcap->hca_port_info[port_index].port_ibmf_saa_hdl != NULL) {
22280Sstevel@tonic-gate IBTF_DPRINTF_L5(cmlog, "ibcm_hca_fini_port: "
22290Sstevel@tonic-gate "ibmf_sa_session_close IBMF SAA hdl %p",
22300Sstevel@tonic-gate hcap->hca_port_info[port_index].port_ibmf_saa_hdl);
22310Sstevel@tonic-gate
22320Sstevel@tonic-gate ibmf_status = ibmf_sa_session_close(
22330Sstevel@tonic-gate &hcap->hca_port_info[port_index].port_ibmf_saa_hdl, 0);
22340Sstevel@tonic-gate if (ibmf_status != IBMF_SUCCESS) {
22351093Shiremath IBTF_DPRINTF_L2(cmlog, "ibcm_hca_fini_port: "
22360Sstevel@tonic-gate "ibmf_sa_session_close of port %d returned %x",
22370Sstevel@tonic-gate port_index + 1, ibmf_status);
22380Sstevel@tonic-gate return (IBCM_FAILURE);
22390Sstevel@tonic-gate }
22400Sstevel@tonic-gate }
22410Sstevel@tonic-gate
22420Sstevel@tonic-gate if (hcap->hca_port_info[port_index].port_ibmf_hdl != NULL) {
22430Sstevel@tonic-gate IBTF_DPRINTF_L5(cmlog, "ibcm_hca_fini_port: "
22440Sstevel@tonic-gate "ibmf_unregister IBMF Hdl %p",
22450Sstevel@tonic-gate hcap->hca_port_info[port_index].port_ibmf_hdl);
22460Sstevel@tonic-gate
22470Sstevel@tonic-gate /* clean-up all the ibmf qp's allocated on this port */
22480Sstevel@tonic-gate ibcm_status = ibcm_free_allqps(hcap, port_index + 1);
22490Sstevel@tonic-gate
22500Sstevel@tonic-gate if (ibcm_status != IBCM_SUCCESS) {
22510Sstevel@tonic-gate
22521093Shiremath IBTF_DPRINTF_L2(cmlog, "ibcm_hca_fini_port: "
22530Sstevel@tonic-gate "ibcm_free_allqps failed for port_num %d",
22540Sstevel@tonic-gate port_index + 1);
22550Sstevel@tonic-gate return (IBCM_FAILURE);
22560Sstevel@tonic-gate }
22570Sstevel@tonic-gate
22580Sstevel@tonic-gate /* Tear down the receive callback */
22590Sstevel@tonic-gate ibmf_status = ibmf_tear_down_async_cb(
22600Sstevel@tonic-gate hcap->hca_port_info[port_index].port_ibmf_hdl,
22610Sstevel@tonic-gate IBMF_QP_HANDLE_DEFAULT, 0);
22620Sstevel@tonic-gate
22630Sstevel@tonic-gate if (ibmf_status != IBMF_SUCCESS) {
22641093Shiremath IBTF_DPRINTF_L2(cmlog, "ibcm_hca_fini_port: "
22650Sstevel@tonic-gate "ibmf_tear_down_async_cb failed %d port_num %d",
22660Sstevel@tonic-gate ibmf_status, port_index + 1);
22670Sstevel@tonic-gate return (IBCM_FAILURE);
22680Sstevel@tonic-gate }
22690Sstevel@tonic-gate
22700Sstevel@tonic-gate /* Now, unregister with IBMF */
22710Sstevel@tonic-gate ibmf_status = ibmf_unregister(
22720Sstevel@tonic-gate &hcap->hca_port_info[port_index].port_ibmf_hdl, 0);
22730Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibcm_hca_fini_port: "
22740Sstevel@tonic-gate "ibmf_unregister of port_num %x returned %x",
22750Sstevel@tonic-gate port_index + 1, ibmf_status);
22760Sstevel@tonic-gate
22770Sstevel@tonic-gate if (ibmf_status == IBMF_SUCCESS)
22787862SRichard.Bean@Sun.COM hcap->hca_port_info[port_index].port_ibmf_hdl = NULL;
22790Sstevel@tonic-gate else {
22801093Shiremath IBTF_DPRINTF_L2(cmlog, "ibcm_hca_fini_port: "
22810Sstevel@tonic-gate "ibmf_unregister failed %d port_num %d",
22820Sstevel@tonic-gate ibmf_status, port_index + 1);
22830Sstevel@tonic-gate return (IBCM_FAILURE);
22840Sstevel@tonic-gate }
22850Sstevel@tonic-gate }
22860Sstevel@tonic-gate return (IBCM_SUCCESS);
22870Sstevel@tonic-gate }
22880Sstevel@tonic-gate
22890Sstevel@tonic-gate /*
22900Sstevel@tonic-gate * ibcm_comm_est_handler():
22910Sstevel@tonic-gate * Check if the given channel is in ESTABLISHED state or not
22920Sstevel@tonic-gate *
22930Sstevel@tonic-gate * Arguments:
22940Sstevel@tonic-gate * eventp - A pointer to an ibt_async_event_t struct
22950Sstevel@tonic-gate *
22960Sstevel@tonic-gate * Return values: NONE
22970Sstevel@tonic-gate */
22980Sstevel@tonic-gate static void
ibcm_comm_est_handler(ibt_async_event_t * eventp)22990Sstevel@tonic-gate ibcm_comm_est_handler(ibt_async_event_t *eventp)
23000Sstevel@tonic-gate {
23010Sstevel@tonic-gate ibcm_state_data_t *statep;
23020Sstevel@tonic-gate
23030Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibcm_comm_est_handler:");
23040Sstevel@tonic-gate
23050Sstevel@tonic-gate /* Both QP and EEC handles can't be NULL */
23060Sstevel@tonic-gate if (eventp->ev_chan_hdl == NULL) {
23070Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_comm_est_handler: "
23080Sstevel@tonic-gate "both QP and EEC handles are NULL");
23090Sstevel@tonic-gate return;
23100Sstevel@tonic-gate }
23110Sstevel@tonic-gate
23120Sstevel@tonic-gate /* get the "statep" from qp/eec handles */
23130Sstevel@tonic-gate IBCM_GET_CHAN_PRIVATE(eventp->ev_chan_hdl, statep);
23140Sstevel@tonic-gate if (statep == NULL) {
23150Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_comm_est_handler: statep is NULL");
23160Sstevel@tonic-gate return;
23170Sstevel@tonic-gate }
23180Sstevel@tonic-gate
23190Sstevel@tonic-gate mutex_enter(&statep->state_mutex);
23200Sstevel@tonic-gate
23210Sstevel@tonic-gate IBCM_RELEASE_CHAN_PRIVATE(eventp->ev_chan_hdl);
23220Sstevel@tonic-gate
23230Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibcm_comm_est_handler: statep = %p", statep);
23240Sstevel@tonic-gate
23250Sstevel@tonic-gate IBCM_REF_CNT_INCR(statep);
23260Sstevel@tonic-gate
23270Sstevel@tonic-gate if ((statep->state == IBCM_STATE_REP_SENT) ||
23280Sstevel@tonic-gate (statep->state == IBCM_STATE_MRA_REP_RCVD)) {
23290Sstevel@tonic-gate timeout_id_t timer_val = statep->timerid;
23300Sstevel@tonic-gate
23310Sstevel@tonic-gate statep->state = IBCM_STATE_TRANSIENT_ESTABLISHED;
23320Sstevel@tonic-gate
23330Sstevel@tonic-gate if (timer_val) {
23340Sstevel@tonic-gate statep->timerid = 0;
23350Sstevel@tonic-gate mutex_exit(&statep->state_mutex);
23360Sstevel@tonic-gate (void) untimeout(timer_val);
23370Sstevel@tonic-gate } else
23380Sstevel@tonic-gate mutex_exit(&statep->state_mutex);
23390Sstevel@tonic-gate
23400Sstevel@tonic-gate /* CM doesn't have RTU message here */
23410Sstevel@tonic-gate ibcm_cep_state_rtu(statep, NULL);
23420Sstevel@tonic-gate
23430Sstevel@tonic-gate } else {
2344557Shiremath if (statep->state == IBCM_STATE_ESTABLISHED ||
2345557Shiremath statep->state == IBCM_STATE_TRANSIENT_ESTABLISHED) {
23460Sstevel@tonic-gate IBTF_DPRINTF_L4(cmlog, "ibcm_comm_est_handler: "
23470Sstevel@tonic-gate "Channel already in ESTABLISHED state");
23480Sstevel@tonic-gate } else {
23490Sstevel@tonic-gate /* An unexpected behavior from remote */
23500Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_comm_est_handler: "
23510Sstevel@tonic-gate "Unexpected in state = %d", statep->state);
23520Sstevel@tonic-gate }
23530Sstevel@tonic-gate mutex_exit(&statep->state_mutex);
23540Sstevel@tonic-gate
23550Sstevel@tonic-gate ibcm_insert_trace(statep, IBCM_TRACE_INCOMING_COMEST);
23560Sstevel@tonic-gate }
23570Sstevel@tonic-gate
23580Sstevel@tonic-gate mutex_enter(&statep->state_mutex);
23590Sstevel@tonic-gate IBCM_REF_CNT_DECR(statep);
23600Sstevel@tonic-gate mutex_exit(&statep->state_mutex);
23610Sstevel@tonic-gate }
23620Sstevel@tonic-gate
23630Sstevel@tonic-gate
23640Sstevel@tonic-gate /*
23650Sstevel@tonic-gate * ibcm_async_handler():
23660Sstevel@tonic-gate * CM's Async Handler
23670Sstevel@tonic-gate * (Handles ATTACH, DETACH, COM_EST events)
23680Sstevel@tonic-gate *
23690Sstevel@tonic-gate * Arguments:
23700Sstevel@tonic-gate * eventp - A pointer to an ibt_async_event_t struct
23710Sstevel@tonic-gate *
23720Sstevel@tonic-gate * Return values: None
23730Sstevel@tonic-gate *
23740Sstevel@tonic-gate * NOTE : CM assumes that all HCA DR events are delivered sequentially
23750Sstevel@tonic-gate * i.e., until ibcm_async_handler completes for a given HCA DR, framework
23760Sstevel@tonic-gate * shall not invoke ibcm_async_handler with another DR event for the same
23770Sstevel@tonic-gate * HCA
23780Sstevel@tonic-gate */
23790Sstevel@tonic-gate /* ARGSUSED */
23800Sstevel@tonic-gate void
ibcm_async_handler(void * clnt_hdl,ibt_hca_hdl_t hca_hdl,ibt_async_code_t code,ibt_async_event_t * eventp)23810Sstevel@tonic-gate ibcm_async_handler(void *clnt_hdl, ibt_hca_hdl_t hca_hdl,
23820Sstevel@tonic-gate ibt_async_code_t code, ibt_async_event_t *eventp)
23830Sstevel@tonic-gate {
23840Sstevel@tonic-gate ibcm_hca_info_t *hcap;
23850Sstevel@tonic-gate ibcm_port_up_t *pup;
23860Sstevel@tonic-gate
23870Sstevel@tonic-gate IBTF_DPRINTF_L3(cmlog, "ibcm_async_handler: "
23880Sstevel@tonic-gate "clnt_hdl = %p, code = 0x%x, eventp = 0x%p",
23890Sstevel@tonic-gate clnt_hdl, code, eventp);
23900Sstevel@tonic-gate
23910Sstevel@tonic-gate mutex_enter(&ibcm_global_hca_lock);
23920Sstevel@tonic-gate
23930Sstevel@tonic-gate /* If fini is going to complete successfully, then return */
23940Sstevel@tonic-gate if (ibcm_finit_state != IBCM_FINIT_IDLE) {
23950Sstevel@tonic-gate
23960Sstevel@tonic-gate /*
23970Sstevel@tonic-gate * This finit state implies one of the following:
23980Sstevel@tonic-gate * Init either didn't start or didn't complete OR
23990Sstevel@tonic-gate * Fini is about to return SUCCESS and release the global lock.
24000Sstevel@tonic-gate * In all these cases, it is safe to ignore the async.
24010Sstevel@tonic-gate */
24020Sstevel@tonic-gate
24030Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_async_handler: ignoring event %x, "
24040Sstevel@tonic-gate "as either init didn't complete or fini about to succeed",
24050Sstevel@tonic-gate code);
24060Sstevel@tonic-gate mutex_exit(&ibcm_global_hca_lock);
24070Sstevel@tonic-gate return;
24080Sstevel@tonic-gate }
24090Sstevel@tonic-gate
24100Sstevel@tonic-gate switch (code) {
24119891SRajkumar.Sivaprakasam@Sun.COM case IBT_PORT_CHANGE_EVENT:
24129891SRajkumar.Sivaprakasam@Sun.COM if ((eventp->ev_port_flags & IBT_PORT_CHANGE_SM_LID) == 0)
24139891SRajkumar.Sivaprakasam@Sun.COM break;
24149891SRajkumar.Sivaprakasam@Sun.COM /* FALLTHROUGH */
24159891SRajkumar.Sivaprakasam@Sun.COM case IBT_CLNT_REREG_EVENT:
24160Sstevel@tonic-gate case IBT_EVENT_PORT_UP:
24170Sstevel@tonic-gate mutex_exit(&ibcm_global_hca_lock);
24180Sstevel@tonic-gate pup = kmem_alloc(sizeof (ibcm_port_up_t), KM_SLEEP);
24190Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*pup))
24200Sstevel@tonic-gate pup->pup_hca_guid = eventp->ev_hca_guid;
24210Sstevel@tonic-gate pup->pup_port = eventp->ev_port;
24220Sstevel@tonic-gate _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*pup))
24230Sstevel@tonic-gate (void) taskq_dispatch(ibcm_taskq,
24240Sstevel@tonic-gate ibcm_service_record_rewrite_task, pup, TQ_SLEEP);
2425557Shiremath ibcm_path_cache_purge();
24260Sstevel@tonic-gate return;
24270Sstevel@tonic-gate
24280Sstevel@tonic-gate case IBT_HCA_ATTACH_EVENT:
24290Sstevel@tonic-gate
24300Sstevel@tonic-gate /* eventp->ev_hcaguid is the HCA GUID of interest */
24310Sstevel@tonic-gate ibcm_hca_attach(eventp->ev_hca_guid);
24320Sstevel@tonic-gate break;
24330Sstevel@tonic-gate
24340Sstevel@tonic-gate case IBT_HCA_DETACH_EVENT:
24350Sstevel@tonic-gate
24360Sstevel@tonic-gate /* eventp->ev_hca_guid is the HCA GUID of interest */
24370Sstevel@tonic-gate if ((hcap = ibcm_find_hcap_entry(eventp->ev_hca_guid)) ==
24380Sstevel@tonic-gate NULL) {
24390Sstevel@tonic-gate IBTF_DPRINTF_L2(cmlog, "ibcm_async_handler:"
24400Sstevel@tonic-gate " hca %llX doesn't exist", eventp->ev_hca_guid);
24410Sstevel@tonic-gate break;
24420Sstevel@tonic-gate }
24430Sstevel@tonic-gate
24440Sstevel@tonic-gate (void) ibcm_hca_detach(hcap);
24450Sstevel@tonic-gate break;
24460Sstevel@tonic-gate
24470Sstevel@tonic-gate case IBT_EVENT_COM_EST_QP:
24480Sstevel@tonic-gate /* eventp->ev_qp_hdl is the ibt_qp_hdl_t of interest */
24490Sstevel@tonic-gate case IBT_EVENT_COM_EST_EEC:
24500Sstevel@tonic-gate /* eventp->ev_eec_hdl is the ibt_eec_hdl_t of interest */
24510Sstevel@tonic-gate ibcm_comm_est_handler(eventp);
24520Sstevel@tonic-gate break;
24530Sstevel@tonic-gate default:
24540Sstevel@tonic-gate break;
24550Sstevel@tonic-gate }
24560Sstevel@tonic-gate
24570Sstevel@tonic-gate /* Unblock, any blocked fini/init operations */
24580Sstevel@tonic-gate mutex_exit(&ibcm_global_hca_lock);
24590Sstevel@tonic-gate }
2460