79 ibt_async_code_t, ibt_async_event_t *);
80
81 /* Global variables */
82 char cmlog[] = "ibcm"; /* for debug log messages */
83 ibt_clnt_hdl_t ibcm_ibt_handle; /* IBT handle */
84 kmutex_t ibcm_svc_info_lock; /* list lock */
85 kcondvar_t ibcm_svc_info_cv; /* cv for deregister */
86 kmutex_t ibcm_recv_mutex;
87 avl_tree_t ibcm_svc_avl_tree;
88 taskq_t *ibcm_taskq = NULL;
89 int taskq_dispatch_fail_cnt;
90
91 kmutex_t ibcm_mcglist_lock; /* MCG list lock */
92 kmutex_t ibcm_trace_mutex; /* Trace mutex */
93 kmutex_t ibcm_trace_print_mutex; /* Trace print mutex */
94 int ibcm_conn_max_trcnt = IBCM_MAX_CONN_TRCNT;
95
96 int ibcm_enable_trace = 2; /* Trace level 4 by default */
97 int ibcm_dtrace = 0; /* conditionally enable more dtrace */
98
99 _NOTE(MUTEX_PROTECTS_DATA(ibcm_svc_info_lock, ibcm_svc_info_s::{svc_bind_list
100 svc_ref_cnt svc_to_delete}))
101
102 _NOTE(MUTEX_PROTECTS_DATA(ibcm_svc_info_lock, ibcm_svc_bind_s::{sbind_link}))
103
104 _NOTE(MUTEX_PROTECTS_DATA(ibcm_trace_mutex, ibcm_conn_trace_s))
105
106 _NOTE(DATA_READABLE_WITHOUT_LOCK(ibcm_conn_trace_s))
107
108 _NOTE(MUTEX_PROTECTS_DATA(ibcm_trace_print_mutex, ibcm_debug_buf))
109
110 _NOTE(DATA_READABLE_WITHOUT_LOCK(ibcm_debug_buf))
111
112 /*
113 * Initial state is INIT. All hca dr's return success immediately in this
114 * state, without adding or deleting any hca's to CM.
115 */
116 ibcm_finit_state_t ibcm_finit_state = IBCM_FINIT_INIT;
117
118 /* mutex and cv to manage hca's reference and resource count(s) */
119 kmutex_t ibcm_global_hca_lock;
120 kcondvar_t ibcm_global_hca_cv;
121
122 /* mutex and cv to sa session open */
123 kmutex_t ibcm_sa_open_lock;
124 kcondvar_t ibcm_sa_open_cv;
125 int ibcm_sa_timeout_delay = 1; /* in ticks */
126 _NOTE(MUTEX_PROTECTS_DATA(ibcm_sa_open_lock,
127 ibcm_port_info_s::{port_ibmf_saa_hdl port_saa_open_in_progress}))
128
129 _NOTE(DATA_READABLE_WITHOUT_LOCK(ibcm_port_info_s::{port_ibmf_saa_hdl}))
130
131 /* serialize sm notice callbacks */
132 kmutex_t ibcm_sm_notice_serialize_lock;
133
134 _NOTE(LOCK_ORDER(ibcm_sm_notice_serialize_lock ibcm_global_hca_lock))
135
136 _NOTE(MUTEX_PROTECTS_DATA(ibcm_global_hca_lock, ibcm_hca_info_s::{hca_state
137 hca_svc_cnt hca_acc_cnt hca_res_cnt hca_next}))
138
139 _NOTE(MUTEX_PROTECTS_DATA(ibcm_global_hca_lock,
140 ibcm_port_info_s::{port_ibmf_hdl}))
141
142 _NOTE(MUTEX_PROTECTS_DATA(ibcm_sm_notice_serialize_lock,
143 ibcm_port_info_s::{port_event_status}))
144
145 _NOTE(DATA_READABLE_WITHOUT_LOCK(ibcm_hca_info_s::{hca_state}))
146 _NOTE(DATA_READABLE_WITHOUT_LOCK(
147 ibcm_hca_info_s::{hca_port_info.port_ibmf_hdl}))
148
149 /* mutex for CM's qp list management */
150 kmutex_t ibcm_qp_list_lock;
151
152 _NOTE(MUTEX_PROTECTS_DATA(ibcm_qp_list_lock, ibcm_port_info_s::{port_qplist}))
153 _NOTE(MUTEX_PROTECTS_DATA(ibcm_qp_list_lock, ibcm_qp_list_s))
154 _NOTE(MUTEX_PROTECTS_DATA(ibcm_qp_list_lock, ibcm_qp_list_s))
155
156 kcondvar_t ibcm_timeout_list_cv;
157 kcondvar_t ibcm_timeout_thread_done_cv;
158 kt_did_t ibcm_timeout_thread_did;
159 ibcm_state_data_t *ibcm_timeout_list_hdr, *ibcm_timeout_list_tail;
160 ibcm_ud_state_data_t *ibcm_ud_timeout_list_hdr, *ibcm_ud_timeout_list_tail;
161 kmutex_t ibcm_timeout_list_lock;
162 uint8_t ibcm_timeout_list_flags = 0;
163 pri_t ibcm_timeout_thread_pri = MINCLSYSPRI;
164
165 _NOTE(MUTEX_PROTECTS_DATA(ibcm_timeout_list_lock,
166 ibcm_state_data_s::timeout_next))
167
168 _NOTE(MUTEX_PROTECTS_DATA(ibcm_timeout_list_lock,
169 ibcm_ud_state_data_s::ud_timeout_next))
170
171 /*
172 * Flow control logic for open_rc_channel uses the following.
173 */
174
175 struct ibcm_open_s {
176 kmutex_t mutex;
177 kcondvar_t cv;
178 uint8_t task_running;
179 uint_t queued;
180 uint_t exit_deferred;
181 uint_t in_progress;
182 uint_t in_progress_max;
183 uint_t sends;
184 uint_t sends_max;
185 uint_t sends_lowat;
186 uint_t sends_hiwat;
187 ibcm_state_data_t *tail;
188 ibcm_state_data_t head;
189 } ibcm_open;
190
340 "INIT_RTR_FAIL ",
341 "RTR_RTS ",
342 "RTR_RTS_FAIL ",
343 "RTS_RTS ",
344 "RTS_RTS_FAIL ",
345 "TO_ERROR ",
346 "ERROR_FAIL ",
347 "SET_ALT ",
348 "SET_ALT_FAIL ",
349 "STALE_DETECT ",
350 "OUTGOING_REQ_RETRY ",
351 "OUTGOING_REP_RETRY ",
352 "OUTGOING_LAP_RETRY ",
353 "OUTGOING_MRA_RETRY ",
354 "OUTGOING_DREQ_RETRY ",
355 "NEVER SEE THIS "
356 };
357
358 char ibcm_debug_buf[IBCM_DEBUG_BUF_SIZE];
359
360 _NOTE(SCHEME_PROTECTS_DATA("used in a localized function consistently",
361 ibcm_debug_buf))
362 _NOTE(READ_ONLY_DATA(ibcm_taskq))
363
364 _NOTE(MUTEX_PROTECTS_DATA(ibcm_timeout_list_lock, ibcm_timeout_list_flags))
365 _NOTE(MUTEX_PROTECTS_DATA(ibcm_timeout_list_lock, ibcm_timeout_list_hdr))
366 _NOTE(MUTEX_PROTECTS_DATA(ibcm_timeout_list_lock, ibcm_ud_timeout_list_hdr))
367
368 #ifdef DEBUG
369 int ibcm_test_mode = 0; /* set to 1, if running tests */
370 #endif
371
372
373 /* Module Driver Info */
374 static struct modlmisc ibcm_modlmisc = {
375 &mod_miscops,
376 "IB Communication Manager"
377 };
378
379 /* Module Linkage */
380 static struct modlinkage ibcm_modlinkage = {
381 MODREV_1,
382 &ibcm_modlmisc,
383 NULL
384 };
385
386
387 int
507 mutex_destroy(&ibcm_recv_mutex);
508 mutex_destroy(&ibcm_sm_notice_serialize_lock);
509 mutex_destroy(&ibcm_qp_list_lock);
510 mutex_destroy(&ibcm_trace_mutex);
511 mutex_destroy(&ibcm_trace_print_mutex);
512 cv_destroy(&ibcm_svc_info_cv);
513 cv_destroy(&ibcm_timeout_list_cv);
514 cv_destroy(&ibcm_timeout_thread_done_cv);
515 cv_destroy(&ibcm_global_hca_cv);
516 cv_destroy(&ibcm_sa_open_cv);
517 avl_destroy(&ibcm_svc_avl_tree);
518
519 IBTF_DPRINTF_L5(cmlog, "ibcm_fini_locks: done");
520 }
521
522
523 /* Initialize CM's classport info */
524 static void
525 ibcm_init_classportinfo()
526 {
527 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(ibcm_clpinfo));
528
529 ibcm_clpinfo.BaseVersion = IBCM_MAD_BASE_VERSION;
530 ibcm_clpinfo.ClassVersion = IBCM_MAD_CLASS_VERSION;
531
532 /* For now, CM supports same capabilities at all ports */
533 ibcm_clpinfo.CapabilityMask =
534 h2b16(IBCM_CPINFO_CAP_RC | IBCM_CPINFO_CAP_SIDR);
535
536 /* Bits 0-7 are all 0 for Communication Mgmt Class */
537
538 /* For now, CM has the same respvalue at all ports */
539 ibcm_clpinfo.RespTimeValue_plus =
540 h2b32(ibt_usec2ib(ibcm_local_processing_time) & 0x1f);
541
542 /* For now, redirect fields are set to 0 */
543 /* Trap fields are not applicable to CM, hence set to 0 */
544
545 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(ibcm_clpinfo));
546 IBTF_DPRINTF_L5(cmlog, "ibcm_init_classportinfo: done");
547 }
548
549 /*
550 * ibcm_init():
551 * - call ibt_attach()
552 * - create AVL trees
553 * - Attach HCA handlers that are already present before
554 * CM got loaded.
555 *
556 * Arguments: NONE
557 *
558 * Return values:
559 * IBCM_SUCCESS - success
560 */
561 static ibcm_status_t
562 ibcm_init(void)
563 {
564 ibt_status_t status;
565 kthread_t *t;
567 IBTF_DPRINTF_L3(cmlog, "ibcm_init:");
568
569 ibcm_init_classportinfo();
570
571 if (ibcm_init_ids() != IBCM_SUCCESS) {
572 IBTF_DPRINTF_L1(cmlog, "ibcm_init: "
573 "fatal error: vmem_create() failed");
574 return (IBCM_FAILURE);
575 }
576 ibcm_init_locks();
577
578 if (ibcm_ar_init() != IBCM_SUCCESS) {
579 IBTF_DPRINTF_L1(cmlog, "ibcm_init: "
580 "fatal error: ibcm_ar_init() failed");
581 ibcm_fini_ids();
582 ibcm_fini_locks();
583 return (IBCM_FAILURE);
584 }
585 ibcm_rc_flow_control_init();
586
587 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(ibcm_taskq))
588 ibcm_taskq = system_taskq;
589 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(ibcm_taskq))
590
591 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(ibcm_timeout_list_flags))
592 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(ibcm_timeout_thread_did))
593
594 /* Start the timeout list processing thread */
595 ibcm_timeout_list_flags = 0;
596 t = thread_create(NULL, 0, ibcm_process_tlist, 0, 0, &p0, TS_RUN,
597 ibcm_timeout_thread_pri);
598 ibcm_timeout_thread_did = t->t_did;
599
600 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(ibcm_timeout_list_flags))
601 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(ibcm_timeout_thread_did))
602
603 /*
604 * NOTE : if ibt_attach is done after ibcm_init_hcas, then some
605 * HCA DR events may be lost. CM could call re-init hca list
606 * again, but it is more complicated. Some HCA's DR's lost may
607 * be HCA detach, which makes hca list re-syncing and locking more
608 * complex
609 */
610 status = ibt_attach(&ibcm_ibt_modinfo, NULL, NULL, &ibcm_ibt_handle);
611 if (status != IBT_SUCCESS) {
612 IBTF_DPRINTF_L2(cmlog, "ibcm_init(): ibt_attach failed %d",
613 status);
614 (void) ibcm_ar_fini();
615 ibcm_stop_timeout_thread();
616 ibcm_fini_ids();
617 ibcm_fini_locks();
618 ibcm_rc_flow_control_fini();
619 return (IBCM_FAILURE);
620 }
621
622 /* Block all HCA attach/detach asyncs */
708 /* disables any new hca attach/detaches */
709 mutex_enter(&ibcm_global_hca_lock);
710
711 ibcm_finit_state = IBCM_FINIT_BUSY;
712
713 if (ibcm_fini_hcas() != IBCM_SUCCESS) {
714 IBTF_DPRINTF_L2(cmlog, "ibcm_fini: "
715 "some hca's still have client resources");
716
717 /* First, re-initialize the hcas */
718 ibcm_init_hcas();
719 /* and then enable the HCA asyncs */
720 ibcm_finit_state = IBCM_FINIT_IDLE;
721 mutex_exit(&ibcm_global_hca_lock);
722 if (ibcm_ar_init() != IBCM_SUCCESS) {
723 IBTF_DPRINTF_L1(cmlog, "ibcm_fini:ibcm_ar_init failed");
724 }
725 return (IBCM_FAILURE);
726 }
727
728 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(ibcm_timeout_list_hdr))
729 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(ibcm_ud_timeout_list_hdr))
730
731 ASSERT(ibcm_timeout_list_hdr == NULL);
732 ASSERT(ibcm_ud_timeout_list_hdr == NULL);
733
734 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(ibcm_timeout_list_hdr))
735 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(ibcm_ud_timeout_list_hdr))
736
737 /* Release any pending asyncs on ibcm_global_hca_lock */
738 ibcm_finit_state = IBCM_FINIT_SUCCESS;
739 mutex_exit(&ibcm_global_hca_lock);
740
741 ibcm_stop_timeout_thread();
742
743 ibtl_cm_set_node_info_cb(NULL);
744 /*
745 * Detach from IBTL. Waits until all pending asyncs are complete.
746 * Above cv_broadcast wakes up any waiting hca attach/detach asyncs
747 */
748 status = ibt_detach(ibcm_ibt_handle);
749
750 /* if detach fails, CM didn't free up some resources, so assert */
751 if (status != IBT_SUCCESS)
752 IBTF_DPRINTF_L1(cmlog, "ibcm_fini: ibt_detach failed %d",
753 status);
754
755 ibcm_rc_flow_control_fini();
756
816 * hca's
817 *
818 * Arguments: (WILL CHANGE BASED ON ASYNC EVENT CODE)
819 * hca_guid - HCA's guid
820 *
821 * Return values: NONE
822 */
823 static void
824 ibcm_hca_attach(ib_guid_t hcaguid)
825 {
826 int i;
827 ibt_status_t status;
828 uint8_t nports = 0;
829 ibcm_hca_info_t *hcap;
830 ibt_hca_attr_t hca_attrs;
831
832 IBTF_DPRINTF_L3(cmlog, "ibcm_hca_attach: guid = 0x%llX", hcaguid);
833
834 ASSERT(MUTEX_HELD(&ibcm_global_hca_lock));
835
836 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*hcap))
837
838 status = ibt_query_hca_byguid(hcaguid, &hca_attrs);
839 if (status != IBT_SUCCESS) {
840 IBTF_DPRINTF_L2(cmlog, "ibcm_hca_attach: "
841 "ibt_query_hca_byguid failed = %d", status);
842 return;
843 }
844 nports = hca_attrs.hca_nports;
845
846 IBTF_DPRINTF_L4(cmlog, "ibcm_hca_attach: num ports = %x", nports);
847
848 if ((hcap = ibcm_add_hca_entry(hcaguid, nports)) == NULL)
849 return;
850
851 hcap->hca_guid = hcaguid; /* Set GUID */
852 hcap->hca_num_ports = nports; /* Set number of ports */
853
854 if (ibcm_init_hca_ids(hcap) != IBCM_SUCCESS) {
855 ibcm_delete_hca_entry(hcap);
856 return;
857 }
886 sizeof (ibcm_state_data_t),
887 offsetof(struct ibcm_state_data_s, avl_active_link));
888
889 /* create the "passive" CM AVL tree */
890 avl_create(&hcap->hca_passive_tree, ibcm_passive_node_compare,
891 sizeof (ibcm_state_data_t),
892 offsetof(struct ibcm_state_data_s, avl_passive_link));
893
894 /* create the "passive comid" CM AVL tree */
895 avl_create(&hcap->hca_passive_comid_tree,
896 ibcm_passive_comid_node_compare,
897 sizeof (ibcm_state_data_t),
898 offsetof(struct ibcm_state_data_s, avl_passive_comid_link));
899
900 /*
901 * Mark the state of the HCA to "attach" only at the end
902 * Now CM starts accepting incoming MADs and client API calls
903 */
904 hcap->hca_state = IBCM_HCA_ACTIVE;
905
906 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*hcap))
907
908 IBTF_DPRINTF_L3(cmlog, "ibcm_hca_attach: ATTACH Done");
909 }
910
911 /*
912 * ibcm_hca_detach():
913 * Called as an asynchronous event to notify CM of a detach of HCA.
914 * Here ibcm_hca_info_t is freed up and all fields that
915 * were initialized earlier are cleaned up
916 *
917 * Arguments: (WILL CHANGE BASED ON ASYNC EVENT CODE)
918 * hca_guid - HCA's guid
919 *
920 * Return values:
921 * IBCM_SUCCESS - able to detach HCA
922 * IBCM_FAILURE - failed to detach HCA
923 */
924 static ibcm_status_t
925 ibcm_hca_detach(ibcm_hca_info_t *hcap)
926 {
927 int port_index, i;
2015 ibt_status_t ibt_status;
2016
2017 if (port_index >= hcap->hca_num_ports)
2018 return;
2019
2020 mutex_enter(&ibcm_sa_open_lock);
2021 if (portp->port_saa_open_in_progress) {
2022 mutex_exit(&ibcm_sa_open_lock);
2023 return;
2024 }
2025
2026 saa_handle = portp->port_ibmf_saa_hdl;
2027 if (saa_handle != NULL) {
2028 mutex_exit(&ibcm_sa_open_lock);
2029 return;
2030 }
2031
2032 portp->port_saa_open_in_progress = 1;
2033 mutex_exit(&ibcm_sa_open_lock);
2034
2035 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(portp->port_event_status))
2036
2037 /* The assumption is that we're getting event notifications */
2038 portp->port_event_status = IBMF_SAA_EVENT_STATUS_MASK_PRODUCER_SM;
2039
2040 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(portp->port_event_status))
2041
2042 ibt_status = ibt_get_port_state_byguid(portp->port_hcap->hca_guid,
2043 portp->port_num, &portp->port_sgid0, NULL);
2044 if (ibt_status != IBT_SUCCESS) {
2045 IBTF_DPRINTF_L2(cmlog, "ibcm_init_saa_handle: "
2046 "ibt_get_port_state_byguid failed for guid %llX "
2047 "with status %d", portp->port_hcap->hca_guid, ibt_status);
2048 mutex_enter(&ibcm_sa_open_lock);
2049 portp->port_saa_open_in_progress = 0;
2050 cv_broadcast(&ibcm_sa_open_cv);
2051 mutex_exit(&ibcm_sa_open_lock);
2052 return;
2053 }
2054 /* if the port is UP, try sa_session_open */
2055 (void) taskq_dispatch(ibcm_taskq, ibcm_init_saa, portp, TQ_SLEEP);
2056 }
2057
2058
2059 ibmf_saa_handle_t
2060 ibcm_get_saa_handle(ibcm_hca_info_t *hcap, uint8_t port)
2061 {
2111 * - Register port with IBMA
2112 *
2113 * Arguments:
2114 * hcap - HCA's guid
2115 * port_index - port number minus 1
2116 *
2117 * Return values:
2118 * IBCM_SUCCESS - success
2119 */
2120 ibt_status_t
2121 ibcm_hca_init_port(ibcm_hca_info_t *hcap, uint8_t port_index)
2122 {
2123 int status;
2124 ibmf_register_info_t *ibmf_reg;
2125
2126 IBTF_DPRINTF_L4(cmlog, "ibcm_hca_init_port: hcap = 0x%p port_num %d",
2127 hcap, port_index + 1);
2128
2129 ASSERT(MUTEX_HELD(&ibcm_global_hca_lock));
2130
2131 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(hcap->hca_port_info))
2132
2133 if (hcap->hca_port_info[port_index].port_ibmf_hdl == NULL) {
2134 /* Register with IBMF */
2135 ibmf_reg = &hcap->hca_port_info[port_index].port_ibmf_reg;
2136 ibmf_reg->ir_ci_guid = hcap->hca_guid;
2137 ibmf_reg->ir_port_num = port_index + 1;
2138 ibmf_reg->ir_client_class = COMM_MGT_MANAGER_AGENT;
2139
2140 /*
2141 * register with management framework
2142 */
2143 status = ibmf_register(ibmf_reg, IBMF_VERSION,
2144 IBMF_REG_FLAG_NO_OFFLOAD, NULL, NULL,
2145 &(hcap->hca_port_info[port_index].port_ibmf_hdl),
2146 &(hcap->hca_port_info[port_index].port_ibmf_caps));
2147
2148 if (status != IBMF_SUCCESS) {
2149 IBTF_DPRINTF_L2(cmlog, "ibcm_hca_init_port: "
2150 "ibmf_register failed for port_num %x, "
2151 "status = %x", port_index + 1, status);
2152 return (ibcm_ibmf_analyze_error(status));
2399 * Fini is about to return SUCCESS and release the global lock.
2400 * In all these cases, it is safe to ignore the async.
2401 */
2402
2403 IBTF_DPRINTF_L2(cmlog, "ibcm_async_handler: ignoring event %x, "
2404 "as either init didn't complete or fini about to succeed",
2405 code);
2406 mutex_exit(&ibcm_global_hca_lock);
2407 return;
2408 }
2409
2410 switch (code) {
2411 case IBT_PORT_CHANGE_EVENT:
2412 if ((eventp->ev_port_flags & IBT_PORT_CHANGE_SM_LID) == 0)
2413 break;
2414 /* FALLTHROUGH */
2415 case IBT_CLNT_REREG_EVENT:
2416 case IBT_EVENT_PORT_UP:
2417 mutex_exit(&ibcm_global_hca_lock);
2418 pup = kmem_alloc(sizeof (ibcm_port_up_t), KM_SLEEP);
2419 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*pup))
2420 pup->pup_hca_guid = eventp->ev_hca_guid;
2421 pup->pup_port = eventp->ev_port;
2422 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*pup))
2423 (void) taskq_dispatch(ibcm_taskq,
2424 ibcm_service_record_rewrite_task, pup, TQ_SLEEP);
2425 ibcm_path_cache_purge();
2426 return;
2427
2428 case IBT_HCA_ATTACH_EVENT:
2429
2430 /* eventp->ev_hcaguid is the HCA GUID of interest */
2431 ibcm_hca_attach(eventp->ev_hca_guid);
2432 break;
2433
2434 case IBT_HCA_DETACH_EVENT:
2435
2436 /* eventp->ev_hca_guid is the HCA GUID of interest */
2437 if ((hcap = ibcm_find_hcap_entry(eventp->ev_hca_guid)) ==
2438 NULL) {
2439 IBTF_DPRINTF_L2(cmlog, "ibcm_async_handler:"
2440 " hca %llX doesn't exist", eventp->ev_hca_guid);
2441 break;
2442 }
|
79 ibt_async_code_t, ibt_async_event_t *);
80
81 /* Global variables */
82 char cmlog[] = "ibcm"; /* for debug log messages */
83 ibt_clnt_hdl_t ibcm_ibt_handle; /* IBT handle */
84 kmutex_t ibcm_svc_info_lock; /* list lock */
85 kcondvar_t ibcm_svc_info_cv; /* cv for deregister */
86 kmutex_t ibcm_recv_mutex;
87 avl_tree_t ibcm_svc_avl_tree;
88 taskq_t *ibcm_taskq = NULL;
89 int taskq_dispatch_fail_cnt;
90
91 kmutex_t ibcm_mcglist_lock; /* MCG list lock */
92 kmutex_t ibcm_trace_mutex; /* Trace mutex */
93 kmutex_t ibcm_trace_print_mutex; /* Trace print mutex */
94 int ibcm_conn_max_trcnt = IBCM_MAX_CONN_TRCNT;
95
96 int ibcm_enable_trace = 2; /* Trace level 4 by default */
97 int ibcm_dtrace = 0; /* conditionally enable more dtrace */
98
99 /*
100 * Initial state is INIT. All hca dr's return success immediately in this
101 * state, without adding or deleting any hca's to CM.
102 */
103 ibcm_finit_state_t ibcm_finit_state = IBCM_FINIT_INIT;
104
105 /* mutex and cv to manage hca's reference and resource count(s) */
106 kmutex_t ibcm_global_hca_lock;
107 kcondvar_t ibcm_global_hca_cv;
108
109 /* mutex and cv to sa session open */
110 kmutex_t ibcm_sa_open_lock;
111 kcondvar_t ibcm_sa_open_cv;
112 int ibcm_sa_timeout_delay = 1; /* in ticks */
113
114 /* serialize sm notice callbacks */
115 kmutex_t ibcm_sm_notice_serialize_lock;
116
117 /* mutex for CM's qp list management */
118 kmutex_t ibcm_qp_list_lock;
119
120 kcondvar_t ibcm_timeout_list_cv;
121 kcondvar_t ibcm_timeout_thread_done_cv;
122 kt_did_t ibcm_timeout_thread_did;
123 ibcm_state_data_t *ibcm_timeout_list_hdr, *ibcm_timeout_list_tail;
124 ibcm_ud_state_data_t *ibcm_ud_timeout_list_hdr, *ibcm_ud_timeout_list_tail;
125 kmutex_t ibcm_timeout_list_lock;
126 uint8_t ibcm_timeout_list_flags = 0;
127 pri_t ibcm_timeout_thread_pri = MINCLSYSPRI;
128
129 /*
130 * Flow control logic for open_rc_channel uses the following.
131 */
132
133 struct ibcm_open_s {
134 kmutex_t mutex;
135 kcondvar_t cv;
136 uint8_t task_running;
137 uint_t queued;
138 uint_t exit_deferred;
139 uint_t in_progress;
140 uint_t in_progress_max;
141 uint_t sends;
142 uint_t sends_max;
143 uint_t sends_lowat;
144 uint_t sends_hiwat;
145 ibcm_state_data_t *tail;
146 ibcm_state_data_t head;
147 } ibcm_open;
148
298 "INIT_RTR_FAIL ",
299 "RTR_RTS ",
300 "RTR_RTS_FAIL ",
301 "RTS_RTS ",
302 "RTS_RTS_FAIL ",
303 "TO_ERROR ",
304 "ERROR_FAIL ",
305 "SET_ALT ",
306 "SET_ALT_FAIL ",
307 "STALE_DETECT ",
308 "OUTGOING_REQ_RETRY ",
309 "OUTGOING_REP_RETRY ",
310 "OUTGOING_LAP_RETRY ",
311 "OUTGOING_MRA_RETRY ",
312 "OUTGOING_DREQ_RETRY ",
313 "NEVER SEE THIS "
314 };
315
316 char ibcm_debug_buf[IBCM_DEBUG_BUF_SIZE];
317
318 #ifdef DEBUG
319 int ibcm_test_mode = 0; /* set to 1, if running tests */
320 #endif
321
322
323 /* Module Driver Info */
324 static struct modlmisc ibcm_modlmisc = {
325 &mod_miscops,
326 "IB Communication Manager"
327 };
328
329 /* Module Linkage */
330 static struct modlinkage ibcm_modlinkage = {
331 MODREV_1,
332 &ibcm_modlmisc,
333 NULL
334 };
335
336
337 int
457 mutex_destroy(&ibcm_recv_mutex);
458 mutex_destroy(&ibcm_sm_notice_serialize_lock);
459 mutex_destroy(&ibcm_qp_list_lock);
460 mutex_destroy(&ibcm_trace_mutex);
461 mutex_destroy(&ibcm_trace_print_mutex);
462 cv_destroy(&ibcm_svc_info_cv);
463 cv_destroy(&ibcm_timeout_list_cv);
464 cv_destroy(&ibcm_timeout_thread_done_cv);
465 cv_destroy(&ibcm_global_hca_cv);
466 cv_destroy(&ibcm_sa_open_cv);
467 avl_destroy(&ibcm_svc_avl_tree);
468
469 IBTF_DPRINTF_L5(cmlog, "ibcm_fini_locks: done");
470 }
471
472
473 /* Initialize CM's classport info */
474 static void
475 ibcm_init_classportinfo()
476 {
477 ibcm_clpinfo.BaseVersion = IBCM_MAD_BASE_VERSION;
478 ibcm_clpinfo.ClassVersion = IBCM_MAD_CLASS_VERSION;
479
480 /* For now, CM supports same capabilities at all ports */
481 ibcm_clpinfo.CapabilityMask =
482 h2b16(IBCM_CPINFO_CAP_RC | IBCM_CPINFO_CAP_SIDR);
483
484 /* Bits 0-7 are all 0 for Communication Mgmt Class */
485
486 /* For now, CM has the same respvalue at all ports */
487 ibcm_clpinfo.RespTimeValue_plus =
488 h2b32(ibt_usec2ib(ibcm_local_processing_time) & 0x1f);
489
490 /* For now, redirect fields are set to 0 */
491 /* Trap fields are not applicable to CM, hence set to 0 */
492
493 IBTF_DPRINTF_L5(cmlog, "ibcm_init_classportinfo: done");
494 }
495
496 /*
497 * ibcm_init():
498 * - call ibt_attach()
499 * - create AVL trees
500 * - Attach HCA handlers that are already present before
501 * CM got loaded.
502 *
503 * Arguments: NONE
504 *
505 * Return values:
506 * IBCM_SUCCESS - success
507 */
508 static ibcm_status_t
509 ibcm_init(void)
510 {
511 ibt_status_t status;
512 kthread_t *t;
514 IBTF_DPRINTF_L3(cmlog, "ibcm_init:");
515
516 ibcm_init_classportinfo();
517
518 if (ibcm_init_ids() != IBCM_SUCCESS) {
519 IBTF_DPRINTF_L1(cmlog, "ibcm_init: "
520 "fatal error: vmem_create() failed");
521 return (IBCM_FAILURE);
522 }
523 ibcm_init_locks();
524
525 if (ibcm_ar_init() != IBCM_SUCCESS) {
526 IBTF_DPRINTF_L1(cmlog, "ibcm_init: "
527 "fatal error: ibcm_ar_init() failed");
528 ibcm_fini_ids();
529 ibcm_fini_locks();
530 return (IBCM_FAILURE);
531 }
532 ibcm_rc_flow_control_init();
533
534 ibcm_taskq = system_taskq;
535
536 /* Start the timeout list processing thread */
537 ibcm_timeout_list_flags = 0;
538 t = thread_create(NULL, 0, ibcm_process_tlist, 0, 0, &p0, TS_RUN,
539 ibcm_timeout_thread_pri);
540 ibcm_timeout_thread_did = t->t_did;
541
542 /*
543 * NOTE : if ibt_attach is done after ibcm_init_hcas, then some
544 * HCA DR events may be lost. CM could call re-init hca list
545 * again, but it is more complicated. Some HCA's DR's lost may
546 * be HCA detach, which makes hca list re-syncing and locking more
547 * complex
548 */
549 status = ibt_attach(&ibcm_ibt_modinfo, NULL, NULL, &ibcm_ibt_handle);
550 if (status != IBT_SUCCESS) {
551 IBTF_DPRINTF_L2(cmlog, "ibcm_init(): ibt_attach failed %d",
552 status);
553 (void) ibcm_ar_fini();
554 ibcm_stop_timeout_thread();
555 ibcm_fini_ids();
556 ibcm_fini_locks();
557 ibcm_rc_flow_control_fini();
558 return (IBCM_FAILURE);
559 }
560
561 /* Block all HCA attach/detach asyncs */
647 /* disables any new hca attach/detaches */
648 mutex_enter(&ibcm_global_hca_lock);
649
650 ibcm_finit_state = IBCM_FINIT_BUSY;
651
652 if (ibcm_fini_hcas() != IBCM_SUCCESS) {
653 IBTF_DPRINTF_L2(cmlog, "ibcm_fini: "
654 "some hca's still have client resources");
655
656 /* First, re-initialize the hcas */
657 ibcm_init_hcas();
658 /* and then enable the HCA asyncs */
659 ibcm_finit_state = IBCM_FINIT_IDLE;
660 mutex_exit(&ibcm_global_hca_lock);
661 if (ibcm_ar_init() != IBCM_SUCCESS) {
662 IBTF_DPRINTF_L1(cmlog, "ibcm_fini:ibcm_ar_init failed");
663 }
664 return (IBCM_FAILURE);
665 }
666
667 ASSERT(ibcm_timeout_list_hdr == NULL);
668 ASSERT(ibcm_ud_timeout_list_hdr == NULL);
669
670 /* Release any pending asyncs on ibcm_global_hca_lock */
671 ibcm_finit_state = IBCM_FINIT_SUCCESS;
672 mutex_exit(&ibcm_global_hca_lock);
673
674 ibcm_stop_timeout_thread();
675
676 ibtl_cm_set_node_info_cb(NULL);
677 /*
678 * Detach from IBTL. Waits until all pending asyncs are complete.
679 * Above cv_broadcast wakes up any waiting hca attach/detach asyncs
680 */
681 status = ibt_detach(ibcm_ibt_handle);
682
683 /* if detach fails, CM didn't free up some resources, so assert */
684 if (status != IBT_SUCCESS)
685 IBTF_DPRINTF_L1(cmlog, "ibcm_fini: ibt_detach failed %d",
686 status);
687
688 ibcm_rc_flow_control_fini();
689
749 * hca's
750 *
751 * Arguments: (WILL CHANGE BASED ON ASYNC EVENT CODE)
752 * hca_guid - HCA's guid
753 *
754 * Return values: NONE
755 */
756 static void
757 ibcm_hca_attach(ib_guid_t hcaguid)
758 {
759 int i;
760 ibt_status_t status;
761 uint8_t nports = 0;
762 ibcm_hca_info_t *hcap;
763 ibt_hca_attr_t hca_attrs;
764
765 IBTF_DPRINTF_L3(cmlog, "ibcm_hca_attach: guid = 0x%llX", hcaguid);
766
767 ASSERT(MUTEX_HELD(&ibcm_global_hca_lock));
768
769 status = ibt_query_hca_byguid(hcaguid, &hca_attrs);
770 if (status != IBT_SUCCESS) {
771 IBTF_DPRINTF_L2(cmlog, "ibcm_hca_attach: "
772 "ibt_query_hca_byguid failed = %d", status);
773 return;
774 }
775 nports = hca_attrs.hca_nports;
776
777 IBTF_DPRINTF_L4(cmlog, "ibcm_hca_attach: num ports = %x", nports);
778
779 if ((hcap = ibcm_add_hca_entry(hcaguid, nports)) == NULL)
780 return;
781
782 hcap->hca_guid = hcaguid; /* Set GUID */
783 hcap->hca_num_ports = nports; /* Set number of ports */
784
785 if (ibcm_init_hca_ids(hcap) != IBCM_SUCCESS) {
786 ibcm_delete_hca_entry(hcap);
787 return;
788 }
817 sizeof (ibcm_state_data_t),
818 offsetof(struct ibcm_state_data_s, avl_active_link));
819
820 /* create the "passive" CM AVL tree */
821 avl_create(&hcap->hca_passive_tree, ibcm_passive_node_compare,
822 sizeof (ibcm_state_data_t),
823 offsetof(struct ibcm_state_data_s, avl_passive_link));
824
825 /* create the "passive comid" CM AVL tree */
826 avl_create(&hcap->hca_passive_comid_tree,
827 ibcm_passive_comid_node_compare,
828 sizeof (ibcm_state_data_t),
829 offsetof(struct ibcm_state_data_s, avl_passive_comid_link));
830
831 /*
832 * Mark the state of the HCA to "attach" only at the end
833 * Now CM starts accepting incoming MADs and client API calls
834 */
835 hcap->hca_state = IBCM_HCA_ACTIVE;
836
837 IBTF_DPRINTF_L3(cmlog, "ibcm_hca_attach: ATTACH Done");
838 }
839
840 /*
841 * ibcm_hca_detach():
842 * Called as an asynchronous event to notify CM of a detach of HCA.
843 * Here ibcm_hca_info_t is freed up and all fields that
844 * were initialized earlier are cleaned up
845 *
846 * Arguments: (WILL CHANGE BASED ON ASYNC EVENT CODE)
847 * hca_guid - HCA's guid
848 *
849 * Return values:
850 * IBCM_SUCCESS - able to detach HCA
851 * IBCM_FAILURE - failed to detach HCA
852 */
853 static ibcm_status_t
854 ibcm_hca_detach(ibcm_hca_info_t *hcap)
855 {
856 int port_index, i;
1944 ibt_status_t ibt_status;
1945
1946 if (port_index >= hcap->hca_num_ports)
1947 return;
1948
1949 mutex_enter(&ibcm_sa_open_lock);
1950 if (portp->port_saa_open_in_progress) {
1951 mutex_exit(&ibcm_sa_open_lock);
1952 return;
1953 }
1954
1955 saa_handle = portp->port_ibmf_saa_hdl;
1956 if (saa_handle != NULL) {
1957 mutex_exit(&ibcm_sa_open_lock);
1958 return;
1959 }
1960
1961 portp->port_saa_open_in_progress = 1;
1962 mutex_exit(&ibcm_sa_open_lock);
1963
1964 /* The assumption is that we're getting event notifications */
1965 portp->port_event_status = IBMF_SAA_EVENT_STATUS_MASK_PRODUCER_SM;
1966
1967 ibt_status = ibt_get_port_state_byguid(portp->port_hcap->hca_guid,
1968 portp->port_num, &portp->port_sgid0, NULL);
1969 if (ibt_status != IBT_SUCCESS) {
1970 IBTF_DPRINTF_L2(cmlog, "ibcm_init_saa_handle: "
1971 "ibt_get_port_state_byguid failed for guid %llX "
1972 "with status %d", portp->port_hcap->hca_guid, ibt_status);
1973 mutex_enter(&ibcm_sa_open_lock);
1974 portp->port_saa_open_in_progress = 0;
1975 cv_broadcast(&ibcm_sa_open_cv);
1976 mutex_exit(&ibcm_sa_open_lock);
1977 return;
1978 }
1979 /* if the port is UP, try sa_session_open */
1980 (void) taskq_dispatch(ibcm_taskq, ibcm_init_saa, portp, TQ_SLEEP);
1981 }
1982
1983
1984 ibmf_saa_handle_t
1985 ibcm_get_saa_handle(ibcm_hca_info_t *hcap, uint8_t port)
1986 {
2036 * - Register port with IBMA
2037 *
2038 * Arguments:
2039 * hcap - HCA's guid
2040 * port_index - port number minus 1
2041 *
2042 * Return values:
2043 * IBCM_SUCCESS - success
2044 */
2045 ibt_status_t
2046 ibcm_hca_init_port(ibcm_hca_info_t *hcap, uint8_t port_index)
2047 {
2048 int status;
2049 ibmf_register_info_t *ibmf_reg;
2050
2051 IBTF_DPRINTF_L4(cmlog, "ibcm_hca_init_port: hcap = 0x%p port_num %d",
2052 hcap, port_index + 1);
2053
2054 ASSERT(MUTEX_HELD(&ibcm_global_hca_lock));
2055
2056 if (hcap->hca_port_info[port_index].port_ibmf_hdl == NULL) {
2057 /* Register with IBMF */
2058 ibmf_reg = &hcap->hca_port_info[port_index].port_ibmf_reg;
2059 ibmf_reg->ir_ci_guid = hcap->hca_guid;
2060 ibmf_reg->ir_port_num = port_index + 1;
2061 ibmf_reg->ir_client_class = COMM_MGT_MANAGER_AGENT;
2062
2063 /*
2064 * register with management framework
2065 */
2066 status = ibmf_register(ibmf_reg, IBMF_VERSION,
2067 IBMF_REG_FLAG_NO_OFFLOAD, NULL, NULL,
2068 &(hcap->hca_port_info[port_index].port_ibmf_hdl),
2069 &(hcap->hca_port_info[port_index].port_ibmf_caps));
2070
2071 if (status != IBMF_SUCCESS) {
2072 IBTF_DPRINTF_L2(cmlog, "ibcm_hca_init_port: "
2073 "ibmf_register failed for port_num %x, "
2074 "status = %x", port_index + 1, status);
2075 return (ibcm_ibmf_analyze_error(status));
2322 * Fini is about to return SUCCESS and release the global lock.
2323 * In all these cases, it is safe to ignore the async.
2324 */
2325
2326 IBTF_DPRINTF_L2(cmlog, "ibcm_async_handler: ignoring event %x, "
2327 "as either init didn't complete or fini about to succeed",
2328 code);
2329 mutex_exit(&ibcm_global_hca_lock);
2330 return;
2331 }
2332
2333 switch (code) {
2334 case IBT_PORT_CHANGE_EVENT:
2335 if ((eventp->ev_port_flags & IBT_PORT_CHANGE_SM_LID) == 0)
2336 break;
2337 /* FALLTHROUGH */
2338 case IBT_CLNT_REREG_EVENT:
2339 case IBT_EVENT_PORT_UP:
2340 mutex_exit(&ibcm_global_hca_lock);
2341 pup = kmem_alloc(sizeof (ibcm_port_up_t), KM_SLEEP);
2342 pup->pup_hca_guid = eventp->ev_hca_guid;
2343 pup->pup_port = eventp->ev_port;
2344 (void) taskq_dispatch(ibcm_taskq,
2345 ibcm_service_record_rewrite_task, pup, TQ_SLEEP);
2346 ibcm_path_cache_purge();
2347 return;
2348
2349 case IBT_HCA_ATTACH_EVENT:
2350
2351 /* eventp->ev_hcaguid is the HCA GUID of interest */
2352 ibcm_hca_attach(eventp->ev_hca_guid);
2353 break;
2354
2355 case IBT_HCA_DETACH_EVENT:
2356
2357 /* eventp->ev_hca_guid is the HCA GUID of interest */
2358 if ((hcap = ibcm_find_hcap_entry(eventp->ev_hca_guid)) ==
2359 NULL) {
2360 IBTF_DPRINTF_L2(cmlog, "ibcm_async_handler:"
2361 " hca %llX doesn't exist", eventp->ev_hca_guid);
2362 break;
2363 }
|