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
51689Spramodbg * Common Development and Distribution License (the "License").
61689Spramodbg * 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 /*
2212637SJustin.Frank@Sun.COM * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
230Sstevel@tonic-gate */
240Sstevel@tonic-gate
250Sstevel@tonic-gate /*
260Sstevel@tonic-gate * ibdm.c
270Sstevel@tonic-gate *
280Sstevel@tonic-gate * This file contains the InifiniBand Device Manager (IBDM) support functions.
290Sstevel@tonic-gate * IB nexus driver will only be the client for the IBDM module.
300Sstevel@tonic-gate *
310Sstevel@tonic-gate * IBDM registers with IBTF for HCA arrival/removal notification.
320Sstevel@tonic-gate * IBDM registers with SA access to send DM MADs to discover the IOC's behind
330Sstevel@tonic-gate * the IOU's.
340Sstevel@tonic-gate *
350Sstevel@tonic-gate * IB nexus driver registers with IBDM to find the information about the
360Sstevel@tonic-gate * HCA's and IOC's (behind the IOU) present on the IB fabric.
370Sstevel@tonic-gate */
380Sstevel@tonic-gate
390Sstevel@tonic-gate #include <sys/systm.h>
400Sstevel@tonic-gate #include <sys/taskq.h>
410Sstevel@tonic-gate #include <sys/ib/mgt/ibdm/ibdm_impl.h>
426262Seota #include <sys/ib/mgt/ibmf/ibmf_impl.h>
4310096SSudhakar.Dindukurti@Sun.COM #include <sys/ib/ibtl/impl/ibtl_ibnex.h>
440Sstevel@tonic-gate #include <sys/modctl.h>
450Sstevel@tonic-gate
460Sstevel@tonic-gate /* Function Prototype declarations */
474024Spramodbg static int ibdm_free_iou_info(ibdm_dp_gidinfo_t *, ibdm_iou_info_t **);
480Sstevel@tonic-gate static int ibdm_fini(void);
490Sstevel@tonic-gate static int ibdm_init(void);
500Sstevel@tonic-gate static int ibdm_get_reachable_ports(ibdm_port_attr_t *,
510Sstevel@tonic-gate ibdm_hca_list_t *);
520Sstevel@tonic-gate static ibdm_dp_gidinfo_t *ibdm_check_dgid(ib_guid_t, ib_sn_prefix_t);
530Sstevel@tonic-gate static ibdm_dp_gidinfo_t *ibdm_check_dest_nodeguid(ibdm_dp_gidinfo_t *);
546262Seota static boolean_t ibdm_is_cisco(ib_guid_t);
556262Seota static boolean_t ibdm_is_cisco_switch(ibdm_dp_gidinfo_t *);
566262Seota static void ibdm_wait_cisco_probe_completion(ibdm_dp_gidinfo_t *);
576262Seota static int ibdm_set_classportinfo(ibdm_dp_gidinfo_t *);
580Sstevel@tonic-gate static int ibdm_send_classportinfo(ibdm_dp_gidinfo_t *);
590Sstevel@tonic-gate static int ibdm_send_iounitinfo(ibdm_dp_gidinfo_t *);
600Sstevel@tonic-gate static int ibdm_is_dev_mgt_supported(ibdm_dp_gidinfo_t *);
610Sstevel@tonic-gate static int ibdm_get_node_port_guids(ibmf_saa_handle_t, ib_lid_t,
620Sstevel@tonic-gate ib_guid_t *, ib_guid_t *);
630Sstevel@tonic-gate static int ibdm_retry_command(ibdm_timeout_cb_args_t *);
640Sstevel@tonic-gate static int ibdm_get_diagcode(ibdm_dp_gidinfo_t *, int);
650Sstevel@tonic-gate static int ibdm_verify_mad_status(ib_mad_hdr_t *);
660Sstevel@tonic-gate static int ibdm_handle_redirection(ibmf_msg_t *,
670Sstevel@tonic-gate ibdm_dp_gidinfo_t *, int *);
680Sstevel@tonic-gate static void ibdm_wait_probe_completion(void);
690Sstevel@tonic-gate static void ibdm_sweep_fabric(int);
700Sstevel@tonic-gate static void ibdm_probe_gid_thread(void *);
710Sstevel@tonic-gate static void ibdm_wakeup_probe_gid_cv(void);
720Sstevel@tonic-gate static void ibdm_port_attr_ibmf_init(ibdm_port_attr_t *, ib_pkey_t, int);
730Sstevel@tonic-gate static int ibdm_port_attr_ibmf_fini(ibdm_port_attr_t *, int);
740Sstevel@tonic-gate static void ibdm_update_port_attr(ibdm_port_attr_t *);
750Sstevel@tonic-gate static void ibdm_handle_hca_attach(ib_guid_t);
760Sstevel@tonic-gate static void ibdm_handle_srventry_mad(ibmf_msg_t *,
770Sstevel@tonic-gate ibdm_dp_gidinfo_t *, int *);
780Sstevel@tonic-gate static void ibdm_ibmf_recv_cb(ibmf_handle_t, ibmf_msg_t *, void *);
790Sstevel@tonic-gate static void ibdm_recv_incoming_mad(void *);
800Sstevel@tonic-gate static void ibdm_process_incoming_mad(ibmf_handle_t, ibmf_msg_t *, void *);
810Sstevel@tonic-gate static void ibdm_ibmf_send_cb(ibmf_handle_t, ibmf_msg_t *, void *);
820Sstevel@tonic-gate static void ibdm_pkt_timeout_hdlr(void *arg);
830Sstevel@tonic-gate static void ibdm_initialize_port(ibdm_port_attr_t *);
849891SRajkumar.Sivaprakasam@Sun.COM static void ibdm_update_port_pkeys(ibdm_port_attr_t *port);
850Sstevel@tonic-gate static void ibdm_handle_diagcode(ibmf_msg_t *, ibdm_dp_gidinfo_t *, int *);
860Sstevel@tonic-gate static void ibdm_probe_gid(ibdm_dp_gidinfo_t *);
870Sstevel@tonic-gate static void ibdm_alloc_send_buffers(ibmf_msg_t *);
880Sstevel@tonic-gate static void ibdm_free_send_buffers(ibmf_msg_t *);
890Sstevel@tonic-gate static void ibdm_handle_hca_detach(ib_guid_t);
9010096SSudhakar.Dindukurti@Sun.COM static void ibdm_handle_port_change_event(ibt_async_event_t *);
910Sstevel@tonic-gate static int ibdm_fini_port(ibdm_port_attr_t *);
920Sstevel@tonic-gate static int ibdm_uninit_hca(ibdm_hca_list_t *);
936262Seota static void ibdm_handle_setclassportinfo(ibmf_handle_t, ibmf_msg_t *,
946262Seota ibdm_dp_gidinfo_t *, int *);
950Sstevel@tonic-gate static void ibdm_handle_iounitinfo(ibmf_handle_t,
960Sstevel@tonic-gate ibmf_msg_t *, ibdm_dp_gidinfo_t *, int *);
970Sstevel@tonic-gate static void ibdm_handle_ioc_profile(ibmf_handle_t,
980Sstevel@tonic-gate ibmf_msg_t *, ibdm_dp_gidinfo_t *, int *);
990Sstevel@tonic-gate static void ibdm_event_hdlr(void *, ibt_hca_hdl_t,
1000Sstevel@tonic-gate ibt_async_code_t, ibt_async_event_t *);
1010Sstevel@tonic-gate static void ibdm_handle_classportinfo(ibmf_handle_t,
1020Sstevel@tonic-gate ibmf_msg_t *, ibdm_dp_gidinfo_t *, int *);
1030Sstevel@tonic-gate static void ibdm_update_ioc_port_gidlist(ibdm_ioc_info_t *,
1040Sstevel@tonic-gate ibdm_dp_gidinfo_t *);
1050Sstevel@tonic-gate
1060Sstevel@tonic-gate static ibdm_hca_list_t *ibdm_dup_hca_attr(ibdm_hca_list_t *);
1070Sstevel@tonic-gate static ibdm_ioc_info_t *ibdm_dup_ioc_info(ibdm_ioc_info_t *,
1080Sstevel@tonic-gate ibdm_dp_gidinfo_t *gid_list);
1090Sstevel@tonic-gate static void ibdm_probe_ioc(ib_guid_t, ib_guid_t, int);
1100Sstevel@tonic-gate static ibdm_ioc_info_t *ibdm_is_ioc_present(ib_guid_t,
1110Sstevel@tonic-gate ibdm_dp_gidinfo_t *, int *);
1120Sstevel@tonic-gate static ibdm_port_attr_t *ibdm_get_port_attr(ibt_async_event_t *,
1130Sstevel@tonic-gate ibdm_hca_list_t **);
1140Sstevel@tonic-gate static sa_node_record_t *ibdm_get_node_records(ibmf_saa_handle_t,
1150Sstevel@tonic-gate size_t *, ib_guid_t);
1166262Seota static int ibdm_get_node_record_by_port(ibmf_saa_handle_t,
1176262Seota ib_guid_t, sa_node_record_t **, size_t *);
1180Sstevel@tonic-gate static sa_portinfo_record_t *ibdm_get_portinfo(ibmf_saa_handle_t, size_t *,
1190Sstevel@tonic-gate ib_lid_t);
1200Sstevel@tonic-gate static ibdm_dp_gidinfo_t *ibdm_create_gid_info(ibdm_port_attr_t *,
1210Sstevel@tonic-gate ib_gid_t, ib_gid_t);
1220Sstevel@tonic-gate static ibdm_dp_gidinfo_t *ibdm_find_gid(ib_guid_t, ib_guid_t);
1230Sstevel@tonic-gate static int ibdm_send_ioc_profile(ibdm_dp_gidinfo_t *, uint8_t);
1240Sstevel@tonic-gate static ibdm_ioc_info_t *ibdm_update_ioc_gidlist(ibdm_dp_gidinfo_t *, int);
1250Sstevel@tonic-gate static void ibdm_saa_event_cb(ibmf_saa_handle_t, ibmf_saa_subnet_event_t,
1260Sstevel@tonic-gate ibmf_saa_event_details_t *, void *);
1270Sstevel@tonic-gate static void ibdm_reprobe_update_port_srv(ibdm_ioc_info_t *,
1280Sstevel@tonic-gate ibdm_dp_gidinfo_t *);
1290Sstevel@tonic-gate static ibdm_dp_gidinfo_t *ibdm_handle_gid_rm(ibdm_dp_gidinfo_t *);
1300Sstevel@tonic-gate static void ibdm_rmfrom_glgid_list(ibdm_dp_gidinfo_t *,
1310Sstevel@tonic-gate ibdm_dp_gidinfo_t *);
1320Sstevel@tonic-gate static void ibdm_addto_gidlist(ibdm_gid_t **, ibdm_gid_t *);
1330Sstevel@tonic-gate static void ibdm_free_gid_list(ibdm_gid_t *);
1340Sstevel@tonic-gate static void ibdm_rescan_gidlist(ib_guid_t *ioc_guid);
1350Sstevel@tonic-gate static void ibdm_notify_newgid_iocs(ibdm_dp_gidinfo_t *);
1360Sstevel@tonic-gate static void ibdm_saa_event_taskq(void *);
1370Sstevel@tonic-gate static void ibdm_free_saa_event_arg(ibdm_saa_event_arg_t *);
1380Sstevel@tonic-gate static void ibdm_get_next_port(ibdm_hca_list_t **,
1390Sstevel@tonic-gate ibdm_port_attr_t **, int);
1400Sstevel@tonic-gate static void ibdm_add_to_gl_gid(ibdm_dp_gidinfo_t *,
1410Sstevel@tonic-gate ibdm_dp_gidinfo_t *);
1420Sstevel@tonic-gate static void ibdm_addto_glhcalist(ibdm_dp_gidinfo_t *,
1430Sstevel@tonic-gate ibdm_hca_list_t *);
1440Sstevel@tonic-gate static void ibdm_delete_glhca_list(ibdm_dp_gidinfo_t *);
1450Sstevel@tonic-gate static void ibdm_saa_handle_new_gid(void *);
1460Sstevel@tonic-gate static void ibdm_reset_all_dgids(ibmf_saa_handle_t);
1470Sstevel@tonic-gate static void ibdm_reset_gidinfo(ibdm_dp_gidinfo_t *);
1480Sstevel@tonic-gate static void ibdm_delete_gidinfo(ibdm_dp_gidinfo_t *);
1491093Shiremath static void ibdm_fill_srv_attr_mod(ib_mad_hdr_t *, ibdm_timeout_cb_args_t *);
1501093Shiremath static void ibdm_bump_transactionID(ibdm_dp_gidinfo_t *);
1514024Spramodbg static ibdm_ioc_info_t *ibdm_handle_prev_iou();
1524024Spramodbg static int ibdm_serv_cmp(ibdm_srvents_info_t *, ibdm_srvents_info_t *,
1534024Spramodbg int);
1546699Seota static ibdm_ioc_info_t *ibdm_get_ioc_info_with_gid(ib_guid_t,
1556699Seota ibdm_dp_gidinfo_t **);
1560Sstevel@tonic-gate
1570Sstevel@tonic-gate int ibdm_dft_timeout = IBDM_DFT_TIMEOUT;
1580Sstevel@tonic-gate int ibdm_dft_retry_cnt = IBDM_DFT_NRETRIES;
1590Sstevel@tonic-gate #ifdef DEBUG
1600Sstevel@tonic-gate int ibdm_ignore_saa_event = 0;
1610Sstevel@tonic-gate #endif
162*12723SRamaswamy.Tummala@Sun.COM int ibdm_enumerate_iocs = 0;
1630Sstevel@tonic-gate
1640Sstevel@tonic-gate /* Modload support */
1650Sstevel@tonic-gate static struct modlmisc ibdm_modlmisc = {
1660Sstevel@tonic-gate &mod_miscops,
1678082SRamaswamy.Tummala@Sun.COM "InfiniBand Device Manager"
1680Sstevel@tonic-gate };
1690Sstevel@tonic-gate
1700Sstevel@tonic-gate struct modlinkage ibdm_modlinkage = {
1710Sstevel@tonic-gate MODREV_1,
1720Sstevel@tonic-gate (void *)&ibdm_modlmisc,
1730Sstevel@tonic-gate NULL
1740Sstevel@tonic-gate };
1750Sstevel@tonic-gate
1760Sstevel@tonic-gate static ibt_clnt_modinfo_t ibdm_ibt_modinfo = {
1778580SBill.Taylor@Sun.COM IBTI_V_CURR,
1780Sstevel@tonic-gate IBT_DM,
1790Sstevel@tonic-gate ibdm_event_hdlr,
1800Sstevel@tonic-gate NULL,
1810Sstevel@tonic-gate "ibdm"
1820Sstevel@tonic-gate };
1830Sstevel@tonic-gate
1840Sstevel@tonic-gate /* Global variables */
1850Sstevel@tonic-gate ibdm_t ibdm;
1860Sstevel@tonic-gate int ibdm_taskq_enable = IBDM_ENABLE_TASKQ_HANDLING;
1870Sstevel@tonic-gate char *ibdm_string = "ibdm";
1880Sstevel@tonic-gate
1890Sstevel@tonic-gate _NOTE(SCHEME_PROTECTS_DATA("Serialized access by cv",
1900Sstevel@tonic-gate ibdm.ibdm_dp_gidlist_head))
1910Sstevel@tonic-gate
1920Sstevel@tonic-gate /*
1930Sstevel@tonic-gate * _init
1940Sstevel@tonic-gate * Loadable module init, called before any other module.
1950Sstevel@tonic-gate * Initialize mutex
1960Sstevel@tonic-gate * Register with IBTF
1970Sstevel@tonic-gate */
1980Sstevel@tonic-gate int
_init(void)1990Sstevel@tonic-gate _init(void)
2000Sstevel@tonic-gate {
2010Sstevel@tonic-gate int err;
2020Sstevel@tonic-gate
2030Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\t_init: addr of ibdm %p", &ibdm);
2040Sstevel@tonic-gate
2050Sstevel@tonic-gate if ((err = ibdm_init()) != IBDM_SUCCESS) {
2060Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "_init: ibdm_init failed 0x%x", err);
2070Sstevel@tonic-gate (void) ibdm_fini();
2080Sstevel@tonic-gate return (DDI_FAILURE);
2090Sstevel@tonic-gate }
2100Sstevel@tonic-gate
2110Sstevel@tonic-gate if ((err = mod_install(&ibdm_modlinkage)) != 0) {
2120Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "_init: mod_install failed 0x%x", err);
2130Sstevel@tonic-gate (void) ibdm_fini();
2140Sstevel@tonic-gate }
2150Sstevel@tonic-gate return (err);
2160Sstevel@tonic-gate }
2170Sstevel@tonic-gate
2180Sstevel@tonic-gate
2190Sstevel@tonic-gate int
_fini(void)2200Sstevel@tonic-gate _fini(void)
2210Sstevel@tonic-gate {
2220Sstevel@tonic-gate int err;
2230Sstevel@tonic-gate
2240Sstevel@tonic-gate if ((err = ibdm_fini()) != IBDM_SUCCESS) {
2250Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "_fini: ibdm_fini failed 0x%x", err);
2260Sstevel@tonic-gate (void) ibdm_init();
2270Sstevel@tonic-gate return (EBUSY);
2280Sstevel@tonic-gate }
2290Sstevel@tonic-gate
2300Sstevel@tonic-gate if ((err = mod_remove(&ibdm_modlinkage)) != 0) {
2310Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "_fini: mod_remove failed 0x%x", err);
2320Sstevel@tonic-gate (void) ibdm_init();
2330Sstevel@tonic-gate }
2340Sstevel@tonic-gate return (err);
2350Sstevel@tonic-gate }
2360Sstevel@tonic-gate
2370Sstevel@tonic-gate
2380Sstevel@tonic-gate int
_info(struct modinfo * modinfop)2390Sstevel@tonic-gate _info(struct modinfo *modinfop)
2400Sstevel@tonic-gate {
2410Sstevel@tonic-gate return (mod_info(&ibdm_modlinkage, modinfop));
2420Sstevel@tonic-gate }
2430Sstevel@tonic-gate
2440Sstevel@tonic-gate
2450Sstevel@tonic-gate /*
2460Sstevel@tonic-gate * ibdm_init():
2470Sstevel@tonic-gate * Register with IBTF
2480Sstevel@tonic-gate * Allocate memory for the HCAs
2490Sstevel@tonic-gate * Allocate minor-nodes for the HCAs
2500Sstevel@tonic-gate */
2510Sstevel@tonic-gate static int
ibdm_init(void)2520Sstevel@tonic-gate ibdm_init(void)
2530Sstevel@tonic-gate {
2540Sstevel@tonic-gate int i, hca_count;
2550Sstevel@tonic-gate ib_guid_t *hca_guids;
2560Sstevel@tonic-gate ibt_status_t status;
2570Sstevel@tonic-gate
2580Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tibdm_init:");
2590Sstevel@tonic-gate if (!(ibdm.ibdm_state & IBDM_LOCKS_ALLOCED)) {
2600Sstevel@tonic-gate mutex_init(&ibdm.ibdm_mutex, NULL, MUTEX_DEFAULT, NULL);
2610Sstevel@tonic-gate mutex_init(&ibdm.ibdm_hl_mutex, NULL, MUTEX_DEFAULT, NULL);
2620Sstevel@tonic-gate mutex_init(&ibdm.ibdm_ibnex_mutex, NULL, MUTEX_DEFAULT, NULL);
2638082SRamaswamy.Tummala@Sun.COM cv_init(&ibdm.ibdm_port_settle_cv, NULL, CV_DRIVER, NULL);
2640Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
2650Sstevel@tonic-gate ibdm.ibdm_state |= IBDM_LOCKS_ALLOCED;
2660Sstevel@tonic-gate }
2670Sstevel@tonic-gate
2680Sstevel@tonic-gate if (!(ibdm.ibdm_state & IBDM_IBT_ATTACHED)) {
2690Sstevel@tonic-gate if ((status = ibt_attach(&ibdm_ibt_modinfo, NULL, NULL,
2700Sstevel@tonic-gate (void *)&ibdm.ibdm_ibt_clnt_hdl)) != IBT_SUCCESS) {
2710Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "ibdm_init: ibt_attach "
2720Sstevel@tonic-gate "failed %x", status);
2730Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
2740Sstevel@tonic-gate return (IBDM_FAILURE);
2750Sstevel@tonic-gate }
2760Sstevel@tonic-gate
2770Sstevel@tonic-gate ibdm.ibdm_state |= IBDM_IBT_ATTACHED;
2780Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
2790Sstevel@tonic-gate }
2800Sstevel@tonic-gate
2810Sstevel@tonic-gate
2820Sstevel@tonic-gate if (!(ibdm.ibdm_state & IBDM_HCA_ATTACHED)) {
2830Sstevel@tonic-gate hca_count = ibt_get_hca_list(&hca_guids);
2840Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "ibdm_init: num_hcas = %d", hca_count);
2850Sstevel@tonic-gate for (i = 0; i < hca_count; i++)
2860Sstevel@tonic-gate (void) ibdm_handle_hca_attach(hca_guids[i]);
2870Sstevel@tonic-gate if (hca_count)
2880Sstevel@tonic-gate ibt_free_hca_list(hca_guids, hca_count);
2890Sstevel@tonic-gate
2900Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
2910Sstevel@tonic-gate ibdm.ibdm_state |= IBDM_HCA_ATTACHED;
2920Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
2930Sstevel@tonic-gate }
2940Sstevel@tonic-gate
2950Sstevel@tonic-gate if (!(ibdm.ibdm_state & IBDM_CVS_ALLOCED)) {
2960Sstevel@tonic-gate cv_init(&ibdm.ibdm_probe_cv, NULL, CV_DRIVER, NULL);
2970Sstevel@tonic-gate cv_init(&ibdm.ibdm_busy_cv, NULL, CV_DRIVER, NULL);
2980Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
2990Sstevel@tonic-gate ibdm.ibdm_state |= IBDM_CVS_ALLOCED;
3000Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
3010Sstevel@tonic-gate }
3020Sstevel@tonic-gate return (IBDM_SUCCESS);
3030Sstevel@tonic-gate }
3040Sstevel@tonic-gate
3050Sstevel@tonic-gate
3060Sstevel@tonic-gate static int
ibdm_free_iou_info(ibdm_dp_gidinfo_t * gid_info,ibdm_iou_info_t ** ioup)3074024Spramodbg ibdm_free_iou_info(ibdm_dp_gidinfo_t *gid_info, ibdm_iou_info_t **ioup)
3080Sstevel@tonic-gate {
3090Sstevel@tonic-gate int ii, k, niocs;
3100Sstevel@tonic-gate size_t size;
3110Sstevel@tonic-gate ibdm_gid_t *delete, *head;
3120Sstevel@tonic-gate timeout_id_t timeout_id;
3130Sstevel@tonic-gate ibdm_ioc_info_t *ioc;
3144024Spramodbg ibdm_iou_info_t *gl_iou = *ioup;
3150Sstevel@tonic-gate
3160Sstevel@tonic-gate ASSERT(mutex_owned(&gid_info->gl_mutex));
3174024Spramodbg if (gl_iou == NULL) {
3180Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tibdm_free_iou_info: No IOU");
3190Sstevel@tonic-gate return (0);
3200Sstevel@tonic-gate }
3210Sstevel@tonic-gate
3224024Spramodbg niocs = gl_iou->iou_info.iou_num_ctrl_slots;
3230Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tfree_iou_info: gid_info = %p, niocs %d",
3240Sstevel@tonic-gate gid_info, niocs);
3250Sstevel@tonic-gate
3260Sstevel@tonic-gate for (ii = 0; ii < niocs; ii++) {
3274024Spramodbg ioc = (ibdm_ioc_info_t *)&gl_iou->iou_ioc_info[ii];
3280Sstevel@tonic-gate
3290Sstevel@tonic-gate /* handle the case where an ioc_timeout_id is scheduled */
3300Sstevel@tonic-gate if (ioc->ioc_timeout_id) {
3310Sstevel@tonic-gate timeout_id = ioc->ioc_timeout_id;
3326699Seota ioc->ioc_timeout_id = 0;
3330Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
3340Sstevel@tonic-gate IBTF_DPRINTF_L5("ibdm", "free_iou_info: "
3350Sstevel@tonic-gate "ioc_timeout_id = 0x%x", timeout_id);
3360Sstevel@tonic-gate if (untimeout(timeout_id) == -1) {
3370Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "free_iou_info: "
3380Sstevel@tonic-gate "untimeout ioc_timeout_id failed");
3390Sstevel@tonic-gate mutex_enter(&gid_info->gl_mutex);
3400Sstevel@tonic-gate return (-1);
3410Sstevel@tonic-gate }
3420Sstevel@tonic-gate mutex_enter(&gid_info->gl_mutex);
3430Sstevel@tonic-gate }
3440Sstevel@tonic-gate
3450Sstevel@tonic-gate /* handle the case where an ioc_dc_timeout_id is scheduled */
3460Sstevel@tonic-gate if (ioc->ioc_dc_timeout_id) {
3470Sstevel@tonic-gate timeout_id = ioc->ioc_dc_timeout_id;
3486699Seota ioc->ioc_dc_timeout_id = 0;
3490Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
3500Sstevel@tonic-gate IBTF_DPRINTF_L5("ibdm", "free_iou_info: "
3510Sstevel@tonic-gate "ioc_dc_timeout_id = 0x%x", timeout_id);
3520Sstevel@tonic-gate if (untimeout(timeout_id) == -1) {
3530Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "free_iou_info: "
3540Sstevel@tonic-gate "untimeout ioc_dc_timeout_id failed");
3550Sstevel@tonic-gate mutex_enter(&gid_info->gl_mutex);
3560Sstevel@tonic-gate return (-1);
3570Sstevel@tonic-gate }
3580Sstevel@tonic-gate mutex_enter(&gid_info->gl_mutex);
3590Sstevel@tonic-gate }
3600Sstevel@tonic-gate
3610Sstevel@tonic-gate /* handle the case where serv[k].se_timeout_id is scheduled */
3620Sstevel@tonic-gate for (k = 0; k < ioc->ioc_profile.ioc_service_entries; k++) {
3630Sstevel@tonic-gate if (ioc->ioc_serv[k].se_timeout_id) {
3640Sstevel@tonic-gate timeout_id = ioc->ioc_serv[k].se_timeout_id;
3656699Seota ioc->ioc_serv[k].se_timeout_id = 0;
3660Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
3670Sstevel@tonic-gate IBTF_DPRINTF_L5("ibdm", "free_iou_info: "
3680Sstevel@tonic-gate "ioc->ioc_serv[%d].se_timeout_id = 0x%x",
3690Sstevel@tonic-gate k, timeout_id);
3700Sstevel@tonic-gate if (untimeout(timeout_id) == -1) {
3710Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "free_iou_info:"
3720Sstevel@tonic-gate " untimeout se_timeout_id failed");
3730Sstevel@tonic-gate mutex_enter(&gid_info->gl_mutex);
3740Sstevel@tonic-gate return (-1);
3750Sstevel@tonic-gate }
3760Sstevel@tonic-gate mutex_enter(&gid_info->gl_mutex);
3770Sstevel@tonic-gate }
3780Sstevel@tonic-gate }
3790Sstevel@tonic-gate
3804024Spramodbg /* delete GID list in IOC */
3810Sstevel@tonic-gate head = ioc->ioc_gid_list;
3820Sstevel@tonic-gate while (head) {
3830Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tibdm_free_iou_info: "
3840Sstevel@tonic-gate "Deleting gid_list struct %p", head);
3850Sstevel@tonic-gate delete = head;
3860Sstevel@tonic-gate head = head->gid_next;
3870Sstevel@tonic-gate kmem_free(delete, sizeof (ibdm_gid_t));
3880Sstevel@tonic-gate }
3890Sstevel@tonic-gate ioc->ioc_gid_list = NULL;
3900Sstevel@tonic-gate
3910Sstevel@tonic-gate /* delete ioc_serv */
3920Sstevel@tonic-gate size = ioc->ioc_profile.ioc_service_entries *
3930Sstevel@tonic-gate sizeof (ibdm_srvents_info_t);
3940Sstevel@tonic-gate if (ioc->ioc_serv && size) {
3950Sstevel@tonic-gate kmem_free(ioc->ioc_serv, size);
3960Sstevel@tonic-gate ioc->ioc_serv = NULL;
3970Sstevel@tonic-gate }
3980Sstevel@tonic-gate }
3996262Seota /*
4006262Seota * Clear the IBDM_CISCO_PROBE_DONE flag to get the IO Unit information
4016262Seota * via the switch during the probe process.
4026262Seota */
4036262Seota gid_info->gl_flag &= ~IBDM_CISCO_PROBE_DONE;
4040Sstevel@tonic-gate
4050Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tibdm_free_iou_info: deleting IOU & IOC");
4060Sstevel@tonic-gate size = sizeof (ibdm_iou_info_t) + niocs * sizeof (ibdm_ioc_info_t);
4074024Spramodbg kmem_free(gl_iou, size);
4084024Spramodbg *ioup = NULL;
4090Sstevel@tonic-gate return (0);
4100Sstevel@tonic-gate }
4110Sstevel@tonic-gate
4120Sstevel@tonic-gate
4130Sstevel@tonic-gate /*
4140Sstevel@tonic-gate * ibdm_fini():
4150Sstevel@tonic-gate * Un-register with IBTF
4160Sstevel@tonic-gate * De allocate memory for the GID info
4170Sstevel@tonic-gate */
4180Sstevel@tonic-gate static int
ibdm_fini()4190Sstevel@tonic-gate ibdm_fini()
4200Sstevel@tonic-gate {
4210Sstevel@tonic-gate int ii;
4220Sstevel@tonic-gate ibdm_hca_list_t *hca_list, *temp;
4230Sstevel@tonic-gate ibdm_dp_gidinfo_t *gid_info, *tmp;
4240Sstevel@tonic-gate ibdm_gid_t *head, *delete;
4250Sstevel@tonic-gate
4260Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tibdm_fini");
4270Sstevel@tonic-gate
4280Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_hl_mutex);
4290Sstevel@tonic-gate if (ibdm.ibdm_state & IBDM_IBT_ATTACHED) {
4300Sstevel@tonic-gate if (ibt_detach(ibdm.ibdm_ibt_clnt_hdl) != IBT_SUCCESS) {
4310Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "\t_fini: ibt_detach failed");
4320Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_hl_mutex);
4330Sstevel@tonic-gate return (IBDM_FAILURE);
4340Sstevel@tonic-gate }
4350Sstevel@tonic-gate ibdm.ibdm_state &= ~IBDM_IBT_ATTACHED;
4360Sstevel@tonic-gate ibdm.ibdm_ibt_clnt_hdl = NULL;
4370Sstevel@tonic-gate }
4380Sstevel@tonic-gate
4390Sstevel@tonic-gate hca_list = ibdm.ibdm_hca_list_head;
4400Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tibdm_fini: nhcas %d", ibdm.ibdm_hca_count);
4410Sstevel@tonic-gate for (ii = 0; ii < ibdm.ibdm_hca_count; ii++) {
4420Sstevel@tonic-gate temp = hca_list;
4430Sstevel@tonic-gate hca_list = hca_list->hl_next;
4440Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tibdm_fini: hca %p", temp);
4450Sstevel@tonic-gate if (ibdm_uninit_hca(temp) != IBDM_SUCCESS) {
4460Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "\tibdm_fini: "
4470Sstevel@tonic-gate "uninit_hca %p failed", temp);
4480Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_hl_mutex);
4490Sstevel@tonic-gate return (IBDM_FAILURE);
4500Sstevel@tonic-gate }
4510Sstevel@tonic-gate }
4520Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_hl_mutex);
4530Sstevel@tonic-gate
4540Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
4550Sstevel@tonic-gate if (ibdm.ibdm_state & IBDM_HCA_ATTACHED)
4560Sstevel@tonic-gate ibdm.ibdm_state &= ~IBDM_HCA_ATTACHED;
4570Sstevel@tonic-gate
4580Sstevel@tonic-gate gid_info = ibdm.ibdm_dp_gidlist_head;
4590Sstevel@tonic-gate while (gid_info) {
4600Sstevel@tonic-gate mutex_enter(&gid_info->gl_mutex);
4614024Spramodbg (void) ibdm_free_iou_info(gid_info, &gid_info->gl_iou);
4620Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
4630Sstevel@tonic-gate ibdm_delete_glhca_list(gid_info);
4640Sstevel@tonic-gate
4650Sstevel@tonic-gate tmp = gid_info;
4660Sstevel@tonic-gate gid_info = gid_info->gl_next;
4670Sstevel@tonic-gate mutex_destroy(&tmp->gl_mutex);
4680Sstevel@tonic-gate head = tmp->gl_gid;
4690Sstevel@tonic-gate while (head) {
4700Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm",
4710Sstevel@tonic-gate "\tibdm_fini: Deleting gid structs");
4720Sstevel@tonic-gate delete = head;
4730Sstevel@tonic-gate head = head->gid_next;
4740Sstevel@tonic-gate kmem_free(delete, sizeof (ibdm_gid_t));
4750Sstevel@tonic-gate }
4760Sstevel@tonic-gate kmem_free(tmp, sizeof (ibdm_dp_gidinfo_t));
4770Sstevel@tonic-gate }
4780Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
4790Sstevel@tonic-gate
4800Sstevel@tonic-gate if (ibdm.ibdm_state & IBDM_LOCKS_ALLOCED) {
4810Sstevel@tonic-gate ibdm.ibdm_state &= ~IBDM_LOCKS_ALLOCED;
4820Sstevel@tonic-gate mutex_destroy(&ibdm.ibdm_mutex);
4830Sstevel@tonic-gate mutex_destroy(&ibdm.ibdm_hl_mutex);
4840Sstevel@tonic-gate mutex_destroy(&ibdm.ibdm_ibnex_mutex);
4858082SRamaswamy.Tummala@Sun.COM cv_destroy(&ibdm.ibdm_port_settle_cv);
4860Sstevel@tonic-gate }
4870Sstevel@tonic-gate if (ibdm.ibdm_state & IBDM_CVS_ALLOCED) {
4880Sstevel@tonic-gate ibdm.ibdm_state &= ~IBDM_CVS_ALLOCED;
4890Sstevel@tonic-gate cv_destroy(&ibdm.ibdm_probe_cv);
4900Sstevel@tonic-gate cv_destroy(&ibdm.ibdm_busy_cv);
4910Sstevel@tonic-gate }
4920Sstevel@tonic-gate return (IBDM_SUCCESS);
4930Sstevel@tonic-gate }
4940Sstevel@tonic-gate
4950Sstevel@tonic-gate
4960Sstevel@tonic-gate /*
4970Sstevel@tonic-gate * ibdm_event_hdlr()
4980Sstevel@tonic-gate *
4990Sstevel@tonic-gate * IBDM registers this asynchronous event handler at the time of
5000Sstevel@tonic-gate * ibt_attach. IBDM support the following async events. For other
5010Sstevel@tonic-gate * event, simply returns success.
5020Sstevel@tonic-gate * IBT_HCA_ATTACH_EVENT:
5030Sstevel@tonic-gate * Retrieves the information about all the port that are
5040Sstevel@tonic-gate * present on this HCA, allocates the port attributes
5050Sstevel@tonic-gate * structure and calls IB nexus callback routine with
5060Sstevel@tonic-gate * the port attributes structure as an input argument.
5070Sstevel@tonic-gate * IBT_HCA_DETACH_EVENT:
5080Sstevel@tonic-gate * Retrieves the information about all the ports that are
5090Sstevel@tonic-gate * present on this HCA and calls IB nexus callback with
5100Sstevel@tonic-gate * port guid as an argument
5110Sstevel@tonic-gate * IBT_EVENT_PORT_UP:
5120Sstevel@tonic-gate * Register with IBMF and SA access
5130Sstevel@tonic-gate * Setup IBMF receive callback routine
5140Sstevel@tonic-gate * IBT_EVENT_PORT_DOWN:
5150Sstevel@tonic-gate * Un-Register with IBMF and SA access
5160Sstevel@tonic-gate * Teardown IBMF receive callback routine
5170Sstevel@tonic-gate */
5180Sstevel@tonic-gate /*ARGSUSED*/
5190Sstevel@tonic-gate static void
ibdm_event_hdlr(void * clnt_hdl,ibt_hca_hdl_t hca_hdl,ibt_async_code_t code,ibt_async_event_t * event)5200Sstevel@tonic-gate ibdm_event_hdlr(void *clnt_hdl,
5210Sstevel@tonic-gate ibt_hca_hdl_t hca_hdl, ibt_async_code_t code, ibt_async_event_t *event)
5220Sstevel@tonic-gate {
5230Sstevel@tonic-gate ibdm_hca_list_t *hca_list;
5240Sstevel@tonic-gate ibdm_port_attr_t *port;
5250Sstevel@tonic-gate ibmf_saa_handle_t port_sa_hdl;
5260Sstevel@tonic-gate
5270Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tevent_hdlr: async code 0x%x", code);
5280Sstevel@tonic-gate
5290Sstevel@tonic-gate switch (code) {
5300Sstevel@tonic-gate case IBT_HCA_ATTACH_EVENT: /* New HCA registered with IBTF */
5310Sstevel@tonic-gate ibdm_handle_hca_attach(event->ev_hca_guid);
5320Sstevel@tonic-gate break;
5330Sstevel@tonic-gate
5340Sstevel@tonic-gate case IBT_HCA_DETACH_EVENT: /* HCA unregistered with IBTF */
5350Sstevel@tonic-gate ibdm_handle_hca_detach(event->ev_hca_guid);
5360Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_ibnex_mutex);
5370Sstevel@tonic-gate if (ibdm.ibdm_ibnex_callback != NULL) {
5380Sstevel@tonic-gate (*ibdm.ibdm_ibnex_callback)((void *)
5390Sstevel@tonic-gate &event->ev_hca_guid, IBDM_EVENT_HCA_REMOVED);
5400Sstevel@tonic-gate }
5410Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_ibnex_mutex);
5420Sstevel@tonic-gate break;
5430Sstevel@tonic-gate
5440Sstevel@tonic-gate case IBT_EVENT_PORT_UP:
5450Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tevent_hdlr: PORT_UP");
5460Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_hl_mutex);
5470Sstevel@tonic-gate port = ibdm_get_port_attr(event, &hca_list);
5480Sstevel@tonic-gate if (port == NULL) {
5490Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm",
5506262Seota "\tevent_hdlr: HCA not present");
5510Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_hl_mutex);
5520Sstevel@tonic-gate break;
5530Sstevel@tonic-gate }
5540Sstevel@tonic-gate ibdm_initialize_port(port);
5550Sstevel@tonic-gate hca_list->hl_nports_active++;
5568082SRamaswamy.Tummala@Sun.COM cv_broadcast(&ibdm.ibdm_port_settle_cv);
5570Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_hl_mutex);
55810096SSudhakar.Dindukurti@Sun.COM
55910096SSudhakar.Dindukurti@Sun.COM /* Inform IB nexus driver */
56010096SSudhakar.Dindukurti@Sun.COM mutex_enter(&ibdm.ibdm_ibnex_mutex);
56110096SSudhakar.Dindukurti@Sun.COM if (ibdm.ibdm_ibnex_callback != NULL) {
56210096SSudhakar.Dindukurti@Sun.COM (*ibdm.ibdm_ibnex_callback)((void *)
56310096SSudhakar.Dindukurti@Sun.COM &event->ev_hca_guid, IBDM_EVENT_PORT_UP);
56410096SSudhakar.Dindukurti@Sun.COM }
56510096SSudhakar.Dindukurti@Sun.COM mutex_exit(&ibdm.ibdm_ibnex_mutex);
5660Sstevel@tonic-gate break;
5670Sstevel@tonic-gate
5680Sstevel@tonic-gate case IBT_ERROR_PORT_DOWN:
5690Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tevent_hdlr: PORT_DOWN");
5700Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_hl_mutex);
5710Sstevel@tonic-gate port = ibdm_get_port_attr(event, &hca_list);
5720Sstevel@tonic-gate if (port == NULL) {
5730Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm",
5746262Seota "\tevent_hdlr: HCA not present");
5750Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_hl_mutex);
5760Sstevel@tonic-gate break;
5770Sstevel@tonic-gate }
5780Sstevel@tonic-gate hca_list->hl_nports_active--;
5790Sstevel@tonic-gate port_sa_hdl = port->pa_sa_hdl;
5800Sstevel@tonic-gate (void) ibdm_fini_port(port);
5813826Shiremath port->pa_state = IBT_PORT_DOWN;
5828082SRamaswamy.Tummala@Sun.COM cv_broadcast(&ibdm.ibdm_port_settle_cv);
5830Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_hl_mutex);
5840Sstevel@tonic-gate ibdm_reset_all_dgids(port_sa_hdl);
5850Sstevel@tonic-gate break;
5860Sstevel@tonic-gate
5879891SRajkumar.Sivaprakasam@Sun.COM case IBT_PORT_CHANGE_EVENT:
5889891SRajkumar.Sivaprakasam@Sun.COM IBTF_DPRINTF_L4("ibdm", "\tevent_hdlr: PORT_CHANGE");
58910096SSudhakar.Dindukurti@Sun.COM if (event->ev_port_flags & IBT_PORT_CHANGE_PKEY)
59010096SSudhakar.Dindukurti@Sun.COM ibdm_handle_port_change_event(event);
5919891SRajkumar.Sivaprakasam@Sun.COM break;
5929891SRajkumar.Sivaprakasam@Sun.COM
5930Sstevel@tonic-gate default: /* Ignore all other events/errors */
5940Sstevel@tonic-gate break;
5950Sstevel@tonic-gate }
5960Sstevel@tonic-gate }
5970Sstevel@tonic-gate
59810096SSudhakar.Dindukurti@Sun.COM static void
ibdm_handle_port_change_event(ibt_async_event_t * event)59910096SSudhakar.Dindukurti@Sun.COM ibdm_handle_port_change_event(ibt_async_event_t *event)
60010096SSudhakar.Dindukurti@Sun.COM {
60110096SSudhakar.Dindukurti@Sun.COM ibdm_port_attr_t *port;
60210096SSudhakar.Dindukurti@Sun.COM ibdm_hca_list_t *hca_list;
60310096SSudhakar.Dindukurti@Sun.COM
60410096SSudhakar.Dindukurti@Sun.COM IBTF_DPRINTF_L2("ibdm", "\tibdm_handle_port_change_event:"
60510096SSudhakar.Dindukurti@Sun.COM " HCA guid %llx", event->ev_hca_guid);
60610096SSudhakar.Dindukurti@Sun.COM mutex_enter(&ibdm.ibdm_hl_mutex);
60710096SSudhakar.Dindukurti@Sun.COM port = ibdm_get_port_attr(event, &hca_list);
60810096SSudhakar.Dindukurti@Sun.COM if (port == NULL) {
60910096SSudhakar.Dindukurti@Sun.COM IBTF_DPRINTF_L2("ibdm", "\tevent_hdlr: HCA not present");
61010096SSudhakar.Dindukurti@Sun.COM mutex_exit(&ibdm.ibdm_hl_mutex);
61110096SSudhakar.Dindukurti@Sun.COM return;
61210096SSudhakar.Dindukurti@Sun.COM }
61310096SSudhakar.Dindukurti@Sun.COM ibdm_update_port_pkeys(port);
61410096SSudhakar.Dindukurti@Sun.COM cv_broadcast(&ibdm.ibdm_port_settle_cv);
61510096SSudhakar.Dindukurti@Sun.COM mutex_exit(&ibdm.ibdm_hl_mutex);
61610096SSudhakar.Dindukurti@Sun.COM
61710096SSudhakar.Dindukurti@Sun.COM /* Inform IB nexus driver */
61810096SSudhakar.Dindukurti@Sun.COM mutex_enter(&ibdm.ibdm_ibnex_mutex);
61910096SSudhakar.Dindukurti@Sun.COM if (ibdm.ibdm_ibnex_callback != NULL) {
62010096SSudhakar.Dindukurti@Sun.COM (*ibdm.ibdm_ibnex_callback)((void *)
62110096SSudhakar.Dindukurti@Sun.COM &event->ev_hca_guid, IBDM_EVENT_PORT_PKEY_CHANGE);
62210096SSudhakar.Dindukurti@Sun.COM }
62310096SSudhakar.Dindukurti@Sun.COM mutex_exit(&ibdm.ibdm_ibnex_mutex);
62410096SSudhakar.Dindukurti@Sun.COM }
6250Sstevel@tonic-gate
6260Sstevel@tonic-gate /*
6279891SRajkumar.Sivaprakasam@Sun.COM * ibdm_update_port_pkeys()
6289891SRajkumar.Sivaprakasam@Sun.COM * Update the pkey table
6299891SRajkumar.Sivaprakasam@Sun.COM * Update the port attributes
6309891SRajkumar.Sivaprakasam@Sun.COM */
6319891SRajkumar.Sivaprakasam@Sun.COM static void
ibdm_update_port_pkeys(ibdm_port_attr_t * port)6329891SRajkumar.Sivaprakasam@Sun.COM ibdm_update_port_pkeys(ibdm_port_attr_t *port)
6339891SRajkumar.Sivaprakasam@Sun.COM {
6349891SRajkumar.Sivaprakasam@Sun.COM uint_t nports, size;
6359891SRajkumar.Sivaprakasam@Sun.COM uint_t pkey_idx, opkey_idx;
6369891SRajkumar.Sivaprakasam@Sun.COM uint16_t npkeys;
6379891SRajkumar.Sivaprakasam@Sun.COM ibt_hca_portinfo_t *pinfop;
6389891SRajkumar.Sivaprakasam@Sun.COM ib_pkey_t pkey;
6399891SRajkumar.Sivaprakasam@Sun.COM ibdm_pkey_tbl_t *pkey_tbl;
6409891SRajkumar.Sivaprakasam@Sun.COM ibdm_port_attr_t newport;
6419891SRajkumar.Sivaprakasam@Sun.COM
6429891SRajkumar.Sivaprakasam@Sun.COM IBTF_DPRINTF_L4("ibdm", "\tupdate_port_pkeys:");
6439891SRajkumar.Sivaprakasam@Sun.COM ASSERT(MUTEX_HELD(&ibdm.ibdm_hl_mutex));
6449891SRajkumar.Sivaprakasam@Sun.COM
6459891SRajkumar.Sivaprakasam@Sun.COM /* Check whether the port is active */
6469891SRajkumar.Sivaprakasam@Sun.COM if (ibt_get_port_state(port->pa_hca_hdl, port->pa_port_num, NULL,
6479891SRajkumar.Sivaprakasam@Sun.COM NULL) != IBT_SUCCESS)
6489891SRajkumar.Sivaprakasam@Sun.COM return;
6499891SRajkumar.Sivaprakasam@Sun.COM
6509891SRajkumar.Sivaprakasam@Sun.COM if (ibt_query_hca_ports(port->pa_hca_hdl, port->pa_port_num,
6519891SRajkumar.Sivaprakasam@Sun.COM &pinfop, &nports, &size) != IBT_SUCCESS) {
6529891SRajkumar.Sivaprakasam@Sun.COM /* This should not occur */
6539891SRajkumar.Sivaprakasam@Sun.COM port->pa_npkeys = 0;
6549891SRajkumar.Sivaprakasam@Sun.COM port->pa_pkey_tbl = NULL;
6559891SRajkumar.Sivaprakasam@Sun.COM return;
6569891SRajkumar.Sivaprakasam@Sun.COM }
6579891SRajkumar.Sivaprakasam@Sun.COM
6589891SRajkumar.Sivaprakasam@Sun.COM npkeys = pinfop->p_pkey_tbl_sz;
6599891SRajkumar.Sivaprakasam@Sun.COM pkey_tbl = kmem_zalloc(npkeys * sizeof (ibdm_pkey_tbl_t), KM_SLEEP);
6609891SRajkumar.Sivaprakasam@Sun.COM newport.pa_pkey_tbl = pkey_tbl;
6619891SRajkumar.Sivaprakasam@Sun.COM newport.pa_ibmf_hdl = port->pa_ibmf_hdl;
6629891SRajkumar.Sivaprakasam@Sun.COM
6639891SRajkumar.Sivaprakasam@Sun.COM for (pkey_idx = 0; pkey_idx < npkeys; pkey_idx++) {
6649891SRajkumar.Sivaprakasam@Sun.COM pkey = pkey_tbl[pkey_idx].pt_pkey =
6659891SRajkumar.Sivaprakasam@Sun.COM pinfop->p_pkey_tbl[pkey_idx];
6669891SRajkumar.Sivaprakasam@Sun.COM /*
6679891SRajkumar.Sivaprakasam@Sun.COM * Is this pkey present in the current table ?
6689891SRajkumar.Sivaprakasam@Sun.COM */
6699891SRajkumar.Sivaprakasam@Sun.COM for (opkey_idx = 0; opkey_idx < port->pa_npkeys; opkey_idx++) {
6709891SRajkumar.Sivaprakasam@Sun.COM if (pkey == port->pa_pkey_tbl[opkey_idx].pt_pkey) {
6719891SRajkumar.Sivaprakasam@Sun.COM pkey_tbl[pkey_idx].pt_qp_hdl =
6729891SRajkumar.Sivaprakasam@Sun.COM port->pa_pkey_tbl[opkey_idx].pt_qp_hdl;
6739891SRajkumar.Sivaprakasam@Sun.COM port->pa_pkey_tbl[opkey_idx].pt_qp_hdl = NULL;
6749891SRajkumar.Sivaprakasam@Sun.COM break;
6759891SRajkumar.Sivaprakasam@Sun.COM }
6769891SRajkumar.Sivaprakasam@Sun.COM }
6779891SRajkumar.Sivaprakasam@Sun.COM
6789891SRajkumar.Sivaprakasam@Sun.COM if (opkey_idx == port->pa_npkeys) {
6799891SRajkumar.Sivaprakasam@Sun.COM pkey = pkey_tbl[pkey_idx].pt_pkey;
6809891SRajkumar.Sivaprakasam@Sun.COM if (IBDM_INVALID_PKEY(pkey)) {
6819891SRajkumar.Sivaprakasam@Sun.COM pkey_tbl[pkey_idx].pt_qp_hdl = NULL;
6829891SRajkumar.Sivaprakasam@Sun.COM continue;
6839891SRajkumar.Sivaprakasam@Sun.COM }
6849891SRajkumar.Sivaprakasam@Sun.COM ibdm_port_attr_ibmf_init(&newport, pkey, pkey_idx);
6859891SRajkumar.Sivaprakasam@Sun.COM }
6869891SRajkumar.Sivaprakasam@Sun.COM }
6879891SRajkumar.Sivaprakasam@Sun.COM
6889891SRajkumar.Sivaprakasam@Sun.COM for (opkey_idx = 0; opkey_idx < port->pa_npkeys; opkey_idx++) {
6899891SRajkumar.Sivaprakasam@Sun.COM if (port->pa_pkey_tbl[opkey_idx].pt_qp_hdl != NULL) {
6909891SRajkumar.Sivaprakasam@Sun.COM if (ibdm_port_attr_ibmf_fini(port, opkey_idx) !=
6919891SRajkumar.Sivaprakasam@Sun.COM IBDM_SUCCESS) {
6929891SRajkumar.Sivaprakasam@Sun.COM IBTF_DPRINTF_L2("ibdm", "\tupdate_port_pkeys: "
6939891SRajkumar.Sivaprakasam@Sun.COM "ibdm_port_attr_ibmf_fini failed for "
6949891SRajkumar.Sivaprakasam@Sun.COM "port pkey 0x%x",
6959891SRajkumar.Sivaprakasam@Sun.COM port->pa_pkey_tbl[opkey_idx].pt_pkey);
6969891SRajkumar.Sivaprakasam@Sun.COM }
6979891SRajkumar.Sivaprakasam@Sun.COM }
6989891SRajkumar.Sivaprakasam@Sun.COM }
6999891SRajkumar.Sivaprakasam@Sun.COM
7009891SRajkumar.Sivaprakasam@Sun.COM if (port->pa_pkey_tbl != NULL) {
7019891SRajkumar.Sivaprakasam@Sun.COM kmem_free(port->pa_pkey_tbl,
7029891SRajkumar.Sivaprakasam@Sun.COM port->pa_npkeys * sizeof (ibdm_pkey_tbl_t));
7039891SRajkumar.Sivaprakasam@Sun.COM }
7049891SRajkumar.Sivaprakasam@Sun.COM
7059891SRajkumar.Sivaprakasam@Sun.COM port->pa_npkeys = npkeys;
7069891SRajkumar.Sivaprakasam@Sun.COM port->pa_pkey_tbl = pkey_tbl;
7079891SRajkumar.Sivaprakasam@Sun.COM port->pa_sn_prefix = pinfop->p_sgid_tbl[0].gid_prefix;
7089891SRajkumar.Sivaprakasam@Sun.COM port->pa_state = pinfop->p_linkstate;
7099891SRajkumar.Sivaprakasam@Sun.COM ibt_free_portinfo(pinfop, size);
7109891SRajkumar.Sivaprakasam@Sun.COM }
7119891SRajkumar.Sivaprakasam@Sun.COM
7129891SRajkumar.Sivaprakasam@Sun.COM /*
7130Sstevel@tonic-gate * ibdm_initialize_port()
7140Sstevel@tonic-gate * Register with IBMF
7150Sstevel@tonic-gate * Register with SA access
7160Sstevel@tonic-gate * Register a receive callback routine with IBMF. IBMF invokes
7170Sstevel@tonic-gate * this routine whenever a MAD arrives at this port.
7180Sstevel@tonic-gate * Update the port attributes
7190Sstevel@tonic-gate */
7200Sstevel@tonic-gate static void
ibdm_initialize_port(ibdm_port_attr_t * port)7210Sstevel@tonic-gate ibdm_initialize_port(ibdm_port_attr_t *port)
7220Sstevel@tonic-gate {
7230Sstevel@tonic-gate int ii;
7240Sstevel@tonic-gate uint_t nports, size;
7250Sstevel@tonic-gate uint_t pkey_idx;
7260Sstevel@tonic-gate ib_pkey_t pkey;
7270Sstevel@tonic-gate ibt_hca_portinfo_t *pinfop;
7280Sstevel@tonic-gate ibmf_register_info_t ibmf_reg;
7290Sstevel@tonic-gate ibmf_saa_subnet_event_args_t event_args;
7300Sstevel@tonic-gate
7310Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tinitialize_port:");
7320Sstevel@tonic-gate ASSERT(MUTEX_HELD(&ibdm.ibdm_hl_mutex));
7330Sstevel@tonic-gate
7340Sstevel@tonic-gate /* Check whether the port is active */
7350Sstevel@tonic-gate if (ibt_get_port_state(port->pa_hca_hdl, port->pa_port_num, NULL,
7360Sstevel@tonic-gate NULL) != IBT_SUCCESS)
7370Sstevel@tonic-gate return;
7380Sstevel@tonic-gate
739*12723SRamaswamy.Tummala@Sun.COM if (port->pa_sa_hdl != NULL || port->pa_pkey_tbl != NULL)
7400Sstevel@tonic-gate return;
7410Sstevel@tonic-gate
7420Sstevel@tonic-gate if (ibt_query_hca_ports(port->pa_hca_hdl, port->pa_port_num,
7430Sstevel@tonic-gate &pinfop, &nports, &size) != IBT_SUCCESS) {
7440Sstevel@tonic-gate /* This should not occur */
7450Sstevel@tonic-gate port->pa_npkeys = 0;
7460Sstevel@tonic-gate port->pa_pkey_tbl = NULL;
7470Sstevel@tonic-gate return;
7480Sstevel@tonic-gate }
7490Sstevel@tonic-gate port->pa_sn_prefix = pinfop->p_sgid_tbl[0].gid_prefix;
7500Sstevel@tonic-gate
7510Sstevel@tonic-gate port->pa_state = pinfop->p_linkstate;
7520Sstevel@tonic-gate port->pa_npkeys = pinfop->p_pkey_tbl_sz;
7530Sstevel@tonic-gate port->pa_pkey_tbl = (ibdm_pkey_tbl_t *)kmem_zalloc(
7540Sstevel@tonic-gate port->pa_npkeys * sizeof (ibdm_pkey_tbl_t), KM_SLEEP);
7550Sstevel@tonic-gate
7560Sstevel@tonic-gate for (pkey_idx = 0; pkey_idx < port->pa_npkeys; pkey_idx++)
7570Sstevel@tonic-gate port->pa_pkey_tbl[pkey_idx].pt_pkey =
7580Sstevel@tonic-gate pinfop->p_pkey_tbl[pkey_idx];
7590Sstevel@tonic-gate
7600Sstevel@tonic-gate ibt_free_portinfo(pinfop, size);
7610Sstevel@tonic-gate
762*12723SRamaswamy.Tummala@Sun.COM if (ibdm_enumerate_iocs) {
763*12723SRamaswamy.Tummala@Sun.COM event_args.is_event_callback = ibdm_saa_event_cb;
764*12723SRamaswamy.Tummala@Sun.COM event_args.is_event_callback_arg = port;
765*12723SRamaswamy.Tummala@Sun.COM if (ibmf_sa_session_open(port->pa_port_guid, 0, &event_args,
766*12723SRamaswamy.Tummala@Sun.COM IBMF_VERSION, 0, &port->pa_sa_hdl) != IBMF_SUCCESS) {
767*12723SRamaswamy.Tummala@Sun.COM IBTF_DPRINTF_L2("ibdm", "\tinitialize_port: "
768*12723SRamaswamy.Tummala@Sun.COM "sa access registration failed");
769*12723SRamaswamy.Tummala@Sun.COM (void) ibdm_fini_port(port);
770*12723SRamaswamy.Tummala@Sun.COM return;
771*12723SRamaswamy.Tummala@Sun.COM }
772*12723SRamaswamy.Tummala@Sun.COM
773*12723SRamaswamy.Tummala@Sun.COM ibmf_reg.ir_ci_guid = port->pa_hca_guid;
774*12723SRamaswamy.Tummala@Sun.COM ibmf_reg.ir_port_num = port->pa_port_num;
775*12723SRamaswamy.Tummala@Sun.COM ibmf_reg.ir_client_class = DEV_MGT_MANAGER;
776*12723SRamaswamy.Tummala@Sun.COM
777*12723SRamaswamy.Tummala@Sun.COM if (ibmf_register(&ibmf_reg, IBMF_VERSION, 0, NULL, NULL,
778*12723SRamaswamy.Tummala@Sun.COM &port->pa_ibmf_hdl, &port->pa_ibmf_caps) != IBMF_SUCCESS) {
779*12723SRamaswamy.Tummala@Sun.COM IBTF_DPRINTF_L2("ibdm", "\tinitialize_port: "
780*12723SRamaswamy.Tummala@Sun.COM "IBMF registration failed");
781*12723SRamaswamy.Tummala@Sun.COM (void) ibdm_fini_port(port);
782*12723SRamaswamy.Tummala@Sun.COM return;
783*12723SRamaswamy.Tummala@Sun.COM }
784*12723SRamaswamy.Tummala@Sun.COM
785*12723SRamaswamy.Tummala@Sun.COM if (ibmf_setup_async_cb(port->pa_ibmf_hdl,
786*12723SRamaswamy.Tummala@Sun.COM IBMF_QP_HANDLE_DEFAULT,
787*12723SRamaswamy.Tummala@Sun.COM ibdm_ibmf_recv_cb, 0, 0) != IBMF_SUCCESS) {
788*12723SRamaswamy.Tummala@Sun.COM IBTF_DPRINTF_L2("ibdm", "\tinitialize_port: "
789*12723SRamaswamy.Tummala@Sun.COM "IBMF setup recv cb failed");
790*12723SRamaswamy.Tummala@Sun.COM (void) ibdm_fini_port(port);
791*12723SRamaswamy.Tummala@Sun.COM return;
792*12723SRamaswamy.Tummala@Sun.COM }
793*12723SRamaswamy.Tummala@Sun.COM } else {
794*12723SRamaswamy.Tummala@Sun.COM port->pa_sa_hdl = NULL;
795*12723SRamaswamy.Tummala@Sun.COM port->pa_ibmf_hdl = NULL;
7960Sstevel@tonic-gate }
7970Sstevel@tonic-gate
7980Sstevel@tonic-gate for (ii = 0; ii < port->pa_npkeys; ii++) {
7990Sstevel@tonic-gate pkey = port->pa_pkey_tbl[ii].pt_pkey;
8000Sstevel@tonic-gate if (IBDM_INVALID_PKEY(pkey)) {
8010Sstevel@tonic-gate port->pa_pkey_tbl[ii].pt_qp_hdl = NULL;
8020Sstevel@tonic-gate continue;
8030Sstevel@tonic-gate }
8040Sstevel@tonic-gate ibdm_port_attr_ibmf_init(port, pkey, ii);
8050Sstevel@tonic-gate }
8060Sstevel@tonic-gate }
8070Sstevel@tonic-gate
8080Sstevel@tonic-gate
8090Sstevel@tonic-gate /*
8100Sstevel@tonic-gate * ibdm_port_attr_ibmf_init:
8110Sstevel@tonic-gate * With IBMF - Alloc QP Handle and Setup Async callback
8120Sstevel@tonic-gate */
8130Sstevel@tonic-gate static void
ibdm_port_attr_ibmf_init(ibdm_port_attr_t * port,ib_pkey_t pkey,int ii)8140Sstevel@tonic-gate ibdm_port_attr_ibmf_init(ibdm_port_attr_t *port, ib_pkey_t pkey, int ii)
8150Sstevel@tonic-gate {
8160Sstevel@tonic-gate int ret;
8170Sstevel@tonic-gate
818*12723SRamaswamy.Tummala@Sun.COM if (ibdm_enumerate_iocs == 0) {
819*12723SRamaswamy.Tummala@Sun.COM port->pa_pkey_tbl[ii].pt_qp_hdl = NULL;
820*12723SRamaswamy.Tummala@Sun.COM return;
821*12723SRamaswamy.Tummala@Sun.COM }
822*12723SRamaswamy.Tummala@Sun.COM
8230Sstevel@tonic-gate if ((ret = ibmf_alloc_qp(port->pa_ibmf_hdl, pkey, IB_GSI_QKEY,
8240Sstevel@tonic-gate IBMF_ALT_QP_MAD_NO_RMPP, &port->pa_pkey_tbl[ii].pt_qp_hdl)) !=
8250Sstevel@tonic-gate IBMF_SUCCESS) {
8260Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "\tport_attr_ibmf_init: "
8270Sstevel@tonic-gate "IBMF failed to alloc qp %d", ret);
8280Sstevel@tonic-gate port->pa_pkey_tbl[ii].pt_qp_hdl = NULL;
8290Sstevel@tonic-gate return;
8300Sstevel@tonic-gate }
8310Sstevel@tonic-gate
8320Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tport_attr_ibmf_init: QP handle is %p",
8330Sstevel@tonic-gate port->pa_ibmf_hdl);
8340Sstevel@tonic-gate
8350Sstevel@tonic-gate if ((ret = ibmf_setup_async_cb(port->pa_ibmf_hdl,
8360Sstevel@tonic-gate port->pa_pkey_tbl[ii].pt_qp_hdl, ibdm_ibmf_recv_cb, 0, 0)) !=
8370Sstevel@tonic-gate IBMF_SUCCESS) {
8380Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "\tport_attr_ibmf_init: "
8390Sstevel@tonic-gate "IBMF setup recv cb failed %d", ret);
8400Sstevel@tonic-gate (void) ibmf_free_qp(port->pa_ibmf_hdl,
8410Sstevel@tonic-gate &port->pa_pkey_tbl[ii].pt_qp_hdl, 0);
8420Sstevel@tonic-gate port->pa_pkey_tbl[ii].pt_qp_hdl = NULL;
8430Sstevel@tonic-gate }
8440Sstevel@tonic-gate }
8450Sstevel@tonic-gate
8460Sstevel@tonic-gate
8470Sstevel@tonic-gate /*
8480Sstevel@tonic-gate * ibdm_get_port_attr()
8490Sstevel@tonic-gate * Get port attributes from HCA guid and port number
8500Sstevel@tonic-gate * Return pointer to ibdm_port_attr_t on Success
8510Sstevel@tonic-gate * and NULL on failure
8520Sstevel@tonic-gate */
8530Sstevel@tonic-gate static ibdm_port_attr_t *
ibdm_get_port_attr(ibt_async_event_t * event,ibdm_hca_list_t ** retval)8540Sstevel@tonic-gate ibdm_get_port_attr(ibt_async_event_t *event, ibdm_hca_list_t **retval)
8550Sstevel@tonic-gate {
8560Sstevel@tonic-gate ibdm_hca_list_t *hca_list;
8570Sstevel@tonic-gate ibdm_port_attr_t *port_attr;
8580Sstevel@tonic-gate int ii;
8590Sstevel@tonic-gate
8600Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tget_port_attr: port# %d", event->ev_port);
8610Sstevel@tonic-gate ASSERT(MUTEX_HELD(&ibdm.ibdm_hl_mutex));
8620Sstevel@tonic-gate hca_list = ibdm.ibdm_hca_list_head;
8630Sstevel@tonic-gate while (hca_list) {
8640Sstevel@tonic-gate if (hca_list->hl_hca_guid == event->ev_hca_guid) {
8650Sstevel@tonic-gate for (ii = 0; ii < hca_list->hl_nports; ii++) {
8660Sstevel@tonic-gate port_attr = &hca_list->hl_port_attr[ii];
8670Sstevel@tonic-gate if (port_attr->pa_port_num == event->ev_port) {
8680Sstevel@tonic-gate *retval = hca_list;
8690Sstevel@tonic-gate return (port_attr);
8700Sstevel@tonic-gate }
8710Sstevel@tonic-gate }
8720Sstevel@tonic-gate }
8730Sstevel@tonic-gate hca_list = hca_list->hl_next;
8740Sstevel@tonic-gate }
8750Sstevel@tonic-gate return (NULL);
8760Sstevel@tonic-gate }
8770Sstevel@tonic-gate
8780Sstevel@tonic-gate
8790Sstevel@tonic-gate /*
8800Sstevel@tonic-gate * ibdm_update_port_attr()
8810Sstevel@tonic-gate * Update the port attributes
8820Sstevel@tonic-gate */
8830Sstevel@tonic-gate static void
ibdm_update_port_attr(ibdm_port_attr_t * port)8840Sstevel@tonic-gate ibdm_update_port_attr(ibdm_port_attr_t *port)
8850Sstevel@tonic-gate {
8860Sstevel@tonic-gate uint_t nports, size;
8870Sstevel@tonic-gate uint_t pkey_idx;
8880Sstevel@tonic-gate ibt_hca_portinfo_t *portinfop;
8890Sstevel@tonic-gate
8900Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tupdate_port_attr: Begin");
8910Sstevel@tonic-gate if (ibt_query_hca_ports(port->pa_hca_hdl,
8920Sstevel@tonic-gate port->pa_port_num, &portinfop, &nports, &size) != IBT_SUCCESS) {
8930Sstevel@tonic-gate /* This should not occur */
8940Sstevel@tonic-gate port->pa_npkeys = 0;
8950Sstevel@tonic-gate port->pa_pkey_tbl = NULL;
8960Sstevel@tonic-gate return;
8970Sstevel@tonic-gate }
8980Sstevel@tonic-gate port->pa_sn_prefix = portinfop->p_sgid_tbl[0].gid_prefix;
8990Sstevel@tonic-gate
9000Sstevel@tonic-gate port->pa_state = portinfop->p_linkstate;
9010Sstevel@tonic-gate
9020Sstevel@tonic-gate /*
9030Sstevel@tonic-gate * PKey information in portinfo valid only if port is
9040Sstevel@tonic-gate * ACTIVE. Bail out if not.
9050Sstevel@tonic-gate */
9060Sstevel@tonic-gate if (port->pa_state != IBT_PORT_ACTIVE) {
9070Sstevel@tonic-gate port->pa_npkeys = 0;
9080Sstevel@tonic-gate port->pa_pkey_tbl = NULL;
9090Sstevel@tonic-gate ibt_free_portinfo(portinfop, size);
9100Sstevel@tonic-gate return;
9110Sstevel@tonic-gate }
9120Sstevel@tonic-gate
9130Sstevel@tonic-gate port->pa_npkeys = portinfop->p_pkey_tbl_sz;
9140Sstevel@tonic-gate port->pa_pkey_tbl = (ibdm_pkey_tbl_t *)kmem_zalloc(
9150Sstevel@tonic-gate port->pa_npkeys * sizeof (ibdm_pkey_tbl_t), KM_SLEEP);
9160Sstevel@tonic-gate
9170Sstevel@tonic-gate for (pkey_idx = 0; pkey_idx < port->pa_npkeys; pkey_idx++) {
9180Sstevel@tonic-gate port->pa_pkey_tbl[pkey_idx].pt_pkey =
9190Sstevel@tonic-gate portinfop->p_pkey_tbl[pkey_idx];
9200Sstevel@tonic-gate }
9210Sstevel@tonic-gate ibt_free_portinfo(portinfop, size);
9220Sstevel@tonic-gate }
9230Sstevel@tonic-gate
9240Sstevel@tonic-gate
9250Sstevel@tonic-gate /*
9260Sstevel@tonic-gate * ibdm_handle_hca_attach()
9270Sstevel@tonic-gate */
9280Sstevel@tonic-gate static void
ibdm_handle_hca_attach(ib_guid_t hca_guid)9290Sstevel@tonic-gate ibdm_handle_hca_attach(ib_guid_t hca_guid)
9300Sstevel@tonic-gate {
9310Sstevel@tonic-gate uint_t size;
9320Sstevel@tonic-gate uint_t ii, nports;
9330Sstevel@tonic-gate ibt_status_t status;
9340Sstevel@tonic-gate ibt_hca_hdl_t hca_hdl;
9350Sstevel@tonic-gate ibt_hca_attr_t *hca_attr;
9360Sstevel@tonic-gate ibdm_hca_list_t *hca_list, *temp;
9370Sstevel@tonic-gate ibdm_port_attr_t *port_attr;
9380Sstevel@tonic-gate ibt_hca_portinfo_t *portinfop;
9390Sstevel@tonic-gate
9400Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm",
9410Sstevel@tonic-gate "\thandle_hca_attach: hca_guid = 0x%llX", hca_guid);
9420Sstevel@tonic-gate
9430Sstevel@tonic-gate /* open the HCA first */
9440Sstevel@tonic-gate if ((status = ibt_open_hca(ibdm.ibdm_ibt_clnt_hdl, hca_guid,
9450Sstevel@tonic-gate &hca_hdl)) != IBT_SUCCESS) {
9460Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "\thandle_hca_attach: "
9470Sstevel@tonic-gate "open_hca failed, status 0x%x", status);
9480Sstevel@tonic-gate return;
9490Sstevel@tonic-gate }
9500Sstevel@tonic-gate
9510Sstevel@tonic-gate hca_attr = (ibt_hca_attr_t *)
9520Sstevel@tonic-gate kmem_alloc(sizeof (ibt_hca_attr_t), KM_SLEEP);
9530Sstevel@tonic-gate /* ibt_query_hca always returns IBT_SUCCESS */
9540Sstevel@tonic-gate (void) ibt_query_hca(hca_hdl, hca_attr);
9550Sstevel@tonic-gate
9560Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tvid: 0x%x, pid: 0x%x, ver: 0x%x,"
9570Sstevel@tonic-gate " #ports: %d", hca_attr->hca_vendor_id, hca_attr->hca_device_id,
9580Sstevel@tonic-gate hca_attr->hca_version_id, hca_attr->hca_nports);
9590Sstevel@tonic-gate
9600Sstevel@tonic-gate if ((status = ibt_query_hca_ports(hca_hdl, 0, &portinfop, &nports,
9610Sstevel@tonic-gate &size)) != IBT_SUCCESS) {
9620Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "\thandle_hca_attach: "
9630Sstevel@tonic-gate "ibt_query_hca_ports failed, status 0x%x", status);
9640Sstevel@tonic-gate kmem_free(hca_attr, sizeof (ibt_hca_attr_t));
9650Sstevel@tonic-gate (void) ibt_close_hca(hca_hdl);
9660Sstevel@tonic-gate return;
9670Sstevel@tonic-gate }
9680Sstevel@tonic-gate hca_list = (ibdm_hca_list_t *)
9690Sstevel@tonic-gate kmem_zalloc((sizeof (ibdm_hca_list_t)), KM_SLEEP);
9700Sstevel@tonic-gate hca_list->hl_port_attr = (ibdm_port_attr_t *)kmem_zalloc(
9710Sstevel@tonic-gate (sizeof (ibdm_port_attr_t) * hca_attr->hca_nports), KM_SLEEP);
9720Sstevel@tonic-gate hca_list->hl_hca_guid = hca_attr->hca_node_guid;
9730Sstevel@tonic-gate hca_list->hl_nports = hca_attr->hca_nports;
9740Sstevel@tonic-gate hca_list->hl_attach_time = ddi_get_time();
9750Sstevel@tonic-gate hca_list->hl_hca_hdl = hca_hdl;
9760Sstevel@tonic-gate
9770Sstevel@tonic-gate /*
9780Sstevel@tonic-gate * Init a dummy port attribute for the HCA node
9790Sstevel@tonic-gate * This is for Per-HCA Node. Initialize port_attr :
9800Sstevel@tonic-gate * hca_guid & port_guid -> hca_guid
9810Sstevel@tonic-gate * npkeys, pkey_tbl is NULL
9820Sstevel@tonic-gate * port_num, sn_prefix is 0
9830Sstevel@tonic-gate * vendorid, product_id, dev_version from HCA
9840Sstevel@tonic-gate * pa_state is IBT_PORT_ACTIVE
9850Sstevel@tonic-gate */
9860Sstevel@tonic-gate hca_list->hl_hca_port_attr = (ibdm_port_attr_t *)kmem_zalloc(
9870Sstevel@tonic-gate sizeof (ibdm_port_attr_t), KM_SLEEP);
9880Sstevel@tonic-gate port_attr = hca_list->hl_hca_port_attr;
9890Sstevel@tonic-gate port_attr->pa_vendorid = hca_attr->hca_vendor_id;
9900Sstevel@tonic-gate port_attr->pa_productid = hca_attr->hca_device_id;
9910Sstevel@tonic-gate port_attr->pa_dev_version = hca_attr->hca_version_id;
9920Sstevel@tonic-gate port_attr->pa_hca_guid = hca_attr->hca_node_guid;
9930Sstevel@tonic-gate port_attr->pa_hca_hdl = hca_list->hl_hca_hdl;
9940Sstevel@tonic-gate port_attr->pa_port_guid = hca_attr->hca_node_guid;
9950Sstevel@tonic-gate port_attr->pa_state = IBT_PORT_ACTIVE;
9960Sstevel@tonic-gate
9970Sstevel@tonic-gate
9980Sstevel@tonic-gate for (ii = 0; ii < nports; ii++) {
9990Sstevel@tonic-gate port_attr = &hca_list->hl_port_attr[ii];
10000Sstevel@tonic-gate port_attr->pa_vendorid = hca_attr->hca_vendor_id;
10010Sstevel@tonic-gate port_attr->pa_productid = hca_attr->hca_device_id;
10020Sstevel@tonic-gate port_attr->pa_dev_version = hca_attr->hca_version_id;
10030Sstevel@tonic-gate port_attr->pa_hca_guid = hca_attr->hca_node_guid;
10040Sstevel@tonic-gate port_attr->pa_hca_hdl = hca_list->hl_hca_hdl;
10050Sstevel@tonic-gate port_attr->pa_port_guid = portinfop[ii].p_sgid_tbl->gid_guid;
10060Sstevel@tonic-gate port_attr->pa_sn_prefix = portinfop[ii].p_sgid_tbl->gid_prefix;
10070Sstevel@tonic-gate port_attr->pa_port_num = portinfop[ii].p_port_num;
10080Sstevel@tonic-gate port_attr->pa_state = portinfop[ii].p_linkstate;
10090Sstevel@tonic-gate
10100Sstevel@tonic-gate /*
10110Sstevel@tonic-gate * Register with IBMF, SA access when the port is in
10120Sstevel@tonic-gate * ACTIVE state. Also register a callback routine
10130Sstevel@tonic-gate * with IBMF to receive incoming DM MAD's.
10140Sstevel@tonic-gate * The IBDM event handler takes care of registration of
10150Sstevel@tonic-gate * port which are not active.
10160Sstevel@tonic-gate */
10170Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm",
10180Sstevel@tonic-gate "\thandle_hca_attach: port guid %llx Port state 0x%x",
10190Sstevel@tonic-gate port_attr->pa_port_guid, portinfop[ii].p_linkstate);
10200Sstevel@tonic-gate
10210Sstevel@tonic-gate if (portinfop[ii].p_linkstate == IBT_PORT_ACTIVE) {
10220Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_hl_mutex);
10230Sstevel@tonic-gate hca_list->hl_nports_active++;
10240Sstevel@tonic-gate ibdm_initialize_port(port_attr);
10258082SRamaswamy.Tummala@Sun.COM cv_broadcast(&ibdm.ibdm_port_settle_cv);
10260Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_hl_mutex);
10270Sstevel@tonic-gate }
10280Sstevel@tonic-gate }
10290Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_hl_mutex);
10300Sstevel@tonic-gate for (temp = ibdm.ibdm_hca_list_head; temp; temp = temp->hl_next) {
10310Sstevel@tonic-gate if (temp->hl_hca_guid == hca_guid) {
10320Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "hca_attach: HCA %llX "
10330Sstevel@tonic-gate "already seen by IBDM", hca_guid);
10340Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_hl_mutex);
10350Sstevel@tonic-gate (void) ibdm_uninit_hca(hca_list);
10360Sstevel@tonic-gate return;
10370Sstevel@tonic-gate }
10380Sstevel@tonic-gate }
10390Sstevel@tonic-gate ibdm.ibdm_hca_count++;
10400Sstevel@tonic-gate if (ibdm.ibdm_hca_list_head == NULL) {
10410Sstevel@tonic-gate ibdm.ibdm_hca_list_head = hca_list;
10420Sstevel@tonic-gate ibdm.ibdm_hca_list_tail = hca_list;
10430Sstevel@tonic-gate } else {
10440Sstevel@tonic-gate ibdm.ibdm_hca_list_tail->hl_next = hca_list;
10450Sstevel@tonic-gate ibdm.ibdm_hca_list_tail = hca_list;
10460Sstevel@tonic-gate }
10470Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_hl_mutex);
10480Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_ibnex_mutex);
10490Sstevel@tonic-gate if (ibdm.ibdm_ibnex_callback != NULL) {
10500Sstevel@tonic-gate (*ibdm.ibdm_ibnex_callback)((void *)
10510Sstevel@tonic-gate &hca_guid, IBDM_EVENT_HCA_ADDED);
10520Sstevel@tonic-gate }
10530Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_ibnex_mutex);
10540Sstevel@tonic-gate
10550Sstevel@tonic-gate kmem_free(hca_attr, sizeof (ibt_hca_attr_t));
10560Sstevel@tonic-gate ibt_free_portinfo(portinfop, size);
10570Sstevel@tonic-gate }
10580Sstevel@tonic-gate
10590Sstevel@tonic-gate
10600Sstevel@tonic-gate /*
10610Sstevel@tonic-gate * ibdm_handle_hca_detach()
10620Sstevel@tonic-gate */
10630Sstevel@tonic-gate static void
ibdm_handle_hca_detach(ib_guid_t hca_guid)10640Sstevel@tonic-gate ibdm_handle_hca_detach(ib_guid_t hca_guid)
10650Sstevel@tonic-gate {
10660Sstevel@tonic-gate ibdm_hca_list_t *head, *prev = NULL;
10672927Spramodbg size_t len;
10682259Shiremath ibdm_dp_gidinfo_t *gidinfo;
106912637SJustin.Frank@Sun.COM ibdm_port_attr_t *port_attr;
107012637SJustin.Frank@Sun.COM int i;
10710Sstevel@tonic-gate
10720Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm",
10730Sstevel@tonic-gate "\thandle_hca_detach: hca_guid = 0x%llx", hca_guid);
10740Sstevel@tonic-gate
10750Sstevel@tonic-gate /* Make sure no probes are running */
10760Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
10770Sstevel@tonic-gate while (ibdm.ibdm_busy & IBDM_BUSY)
10780Sstevel@tonic-gate cv_wait(&ibdm.ibdm_busy_cv, &ibdm.ibdm_mutex);
10790Sstevel@tonic-gate ibdm.ibdm_busy |= IBDM_BUSY;
10800Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
10810Sstevel@tonic-gate
10820Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_hl_mutex);
10830Sstevel@tonic-gate head = ibdm.ibdm_hca_list_head;
10840Sstevel@tonic-gate while (head) {
10850Sstevel@tonic-gate if (head->hl_hca_guid == hca_guid) {
10860Sstevel@tonic-gate if (prev == NULL)
10870Sstevel@tonic-gate ibdm.ibdm_hca_list_head = head->hl_next;
10880Sstevel@tonic-gate else
10890Sstevel@tonic-gate prev->hl_next = head->hl_next;
10908082SRamaswamy.Tummala@Sun.COM if (ibdm.ibdm_hca_list_tail == head)
10918082SRamaswamy.Tummala@Sun.COM ibdm.ibdm_hca_list_tail = prev;
10920Sstevel@tonic-gate ibdm.ibdm_hca_count--;
10930Sstevel@tonic-gate break;
10940Sstevel@tonic-gate }
10950Sstevel@tonic-gate prev = head;
10960Sstevel@tonic-gate head = head->hl_next;
10970Sstevel@tonic-gate }
10980Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_hl_mutex);
10990Sstevel@tonic-gate if (ibdm_uninit_hca(head) != IBDM_SUCCESS)
11000Sstevel@tonic-gate (void) ibdm_handle_hca_attach(hca_guid);
11010Sstevel@tonic-gate
1102*12723SRamaswamy.Tummala@Sun.COM #ifdef DEBUG
1103*12723SRamaswamy.Tummala@Sun.COM if (ibdm_enumerate_iocs == 0) {
1104*12723SRamaswamy.Tummala@Sun.COM ASSERT(ibdm.ibdm_dp_gidlist_head == NULL);
1105*12723SRamaswamy.Tummala@Sun.COM }
1106*12723SRamaswamy.Tummala@Sun.COM #endif
1107*12723SRamaswamy.Tummala@Sun.COM
11082259Shiremath /*
11092259Shiremath * Now clean up the HCA lists in the gidlist.
11102259Shiremath */
11112259Shiremath for (gidinfo = ibdm.ibdm_dp_gidlist_head; gidinfo; gidinfo =
11122259Shiremath gidinfo->gl_next) {
11132259Shiremath prev = NULL;
11142259Shiremath head = gidinfo->gl_hca_list;
11152259Shiremath while (head) {
11162259Shiremath if (head->hl_hca_guid == hca_guid) {
11172259Shiremath if (prev == NULL)
11182259Shiremath gidinfo->gl_hca_list =
11192259Shiremath head->hl_next;
11202259Shiremath else
11212259Shiremath prev->hl_next = head->hl_next;
112212637SJustin.Frank@Sun.COM for (i = 0; i < head->hl_nports; i++) {
112312637SJustin.Frank@Sun.COM port_attr = &head->hl_port_attr[i];
112412637SJustin.Frank@Sun.COM if (port_attr->pa_pkey_tbl != NULL)
112512637SJustin.Frank@Sun.COM kmem_free(
112612637SJustin.Frank@Sun.COM port_attr->pa_pkey_tbl,
112712637SJustin.Frank@Sun.COM port_attr->pa_npkeys *
112812637SJustin.Frank@Sun.COM sizeof (ibdm_pkey_tbl_t));
112912637SJustin.Frank@Sun.COM }
11302927Spramodbg len = sizeof (ibdm_hca_list_t) +
11312927Spramodbg (head->hl_nports *
11322927Spramodbg sizeof (ibdm_port_attr_t));
11332927Spramodbg kmem_free(head, len);
11342927Spramodbg
11352259Shiremath break;
11362259Shiremath }
11372259Shiremath prev = head;
11382259Shiremath head = head->hl_next;
11392259Shiremath }
11402259Shiremath }
11412259Shiremath
11420Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
11430Sstevel@tonic-gate ibdm.ibdm_busy &= ~IBDM_BUSY;
11440Sstevel@tonic-gate cv_broadcast(&ibdm.ibdm_busy_cv);
11450Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
11460Sstevel@tonic-gate }
11470Sstevel@tonic-gate
11480Sstevel@tonic-gate
11490Sstevel@tonic-gate static int
ibdm_uninit_hca(ibdm_hca_list_t * head)11500Sstevel@tonic-gate ibdm_uninit_hca(ibdm_hca_list_t *head)
11510Sstevel@tonic-gate {
11520Sstevel@tonic-gate int ii;
11530Sstevel@tonic-gate ibdm_port_attr_t *port_attr;
11540Sstevel@tonic-gate
11550Sstevel@tonic-gate for (ii = 0; ii < head->hl_nports; ii++) {
11560Sstevel@tonic-gate port_attr = &head->hl_port_attr[ii];
11570Sstevel@tonic-gate if (ibdm_fini_port(port_attr) != IBDM_SUCCESS) {
11580Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "uninit_hca: HCA %p port 0x%x "
11590Sstevel@tonic-gate "ibdm_fini_port() failed", head, ii);
11600Sstevel@tonic-gate return (IBDM_FAILURE);
11610Sstevel@tonic-gate }
11620Sstevel@tonic-gate }
11630Sstevel@tonic-gate if (head->hl_hca_hdl)
116410096SSudhakar.Dindukurti@Sun.COM if (ibt_close_hca(head->hl_hca_hdl) != IBT_SUCCESS) {
116510096SSudhakar.Dindukurti@Sun.COM IBTF_DPRINTF_L2("ibdm", "uninit_hca: "
116610096SSudhakar.Dindukurti@Sun.COM "ibt_close_hca() failed");
11670Sstevel@tonic-gate return (IBDM_FAILURE);
116810096SSudhakar.Dindukurti@Sun.COM }
11690Sstevel@tonic-gate kmem_free(head->hl_port_attr,
11700Sstevel@tonic-gate head->hl_nports * sizeof (ibdm_port_attr_t));
11710Sstevel@tonic-gate kmem_free(head->hl_hca_port_attr, sizeof (ibdm_port_attr_t));
11720Sstevel@tonic-gate kmem_free(head, sizeof (ibdm_hca_list_t));
11730Sstevel@tonic-gate return (IBDM_SUCCESS);
11740Sstevel@tonic-gate }
11750Sstevel@tonic-gate
11760Sstevel@tonic-gate
11770Sstevel@tonic-gate /*
11780Sstevel@tonic-gate * For each port on the HCA,
11790Sstevel@tonic-gate * 1) Teardown IBMF receive callback function
11800Sstevel@tonic-gate * 2) Unregister with IBMF
11810Sstevel@tonic-gate * 3) Unregister with SA access
11820Sstevel@tonic-gate */
11830Sstevel@tonic-gate static int
ibdm_fini_port(ibdm_port_attr_t * port_attr)11840Sstevel@tonic-gate ibdm_fini_port(ibdm_port_attr_t *port_attr)
11850Sstevel@tonic-gate {
11860Sstevel@tonic-gate int ii, ibmf_status;
11870Sstevel@tonic-gate
11880Sstevel@tonic-gate for (ii = 0; ii < port_attr->pa_npkeys; ii++) {
11890Sstevel@tonic-gate if (port_attr->pa_pkey_tbl == NULL)
11900Sstevel@tonic-gate break;
11910Sstevel@tonic-gate if (!port_attr->pa_pkey_tbl[ii].pt_qp_hdl)
11920Sstevel@tonic-gate continue;
11930Sstevel@tonic-gate if (ibdm_port_attr_ibmf_fini(port_attr, ii) != IBDM_SUCCESS) {
11940Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tfini_port: "
11950Sstevel@tonic-gate "ibdm_port_attr_ibmf_fini failed for "
11960Sstevel@tonic-gate "port pkey 0x%x", ii);
11970Sstevel@tonic-gate return (IBDM_FAILURE);
11980Sstevel@tonic-gate }
11990Sstevel@tonic-gate }
12000Sstevel@tonic-gate
12010Sstevel@tonic-gate if (port_attr->pa_ibmf_hdl) {
12020Sstevel@tonic-gate ibmf_status = ibmf_tear_down_async_cb(port_attr->pa_ibmf_hdl,
12030Sstevel@tonic-gate IBMF_QP_HANDLE_DEFAULT, 0);
12040Sstevel@tonic-gate if (ibmf_status != IBMF_SUCCESS) {
12050Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tfini_port: "
12060Sstevel@tonic-gate "ibmf_tear_down_async_cb failed %d", ibmf_status);
12070Sstevel@tonic-gate return (IBDM_FAILURE);
12080Sstevel@tonic-gate }
12090Sstevel@tonic-gate
12100Sstevel@tonic-gate ibmf_status = ibmf_unregister(&port_attr->pa_ibmf_hdl, 0);
12110Sstevel@tonic-gate if (ibmf_status != IBMF_SUCCESS) {
121210096SSudhakar.Dindukurti@Sun.COM IBTF_DPRINTF_L2("ibdm", "\tfini_port: "
12130Sstevel@tonic-gate "ibmf_unregister failed %d", ibmf_status);
12140Sstevel@tonic-gate return (IBDM_FAILURE);
12150Sstevel@tonic-gate }
12160Sstevel@tonic-gate
12170Sstevel@tonic-gate port_attr->pa_ibmf_hdl = NULL;
12180Sstevel@tonic-gate }
12190Sstevel@tonic-gate
12200Sstevel@tonic-gate if (port_attr->pa_sa_hdl) {
12210Sstevel@tonic-gate ibmf_status = ibmf_sa_session_close(&port_attr->pa_sa_hdl, 0);
12220Sstevel@tonic-gate if (ibmf_status != IBMF_SUCCESS) {
122310096SSudhakar.Dindukurti@Sun.COM IBTF_DPRINTF_L2("ibdm", "\tfini_port: "
12240Sstevel@tonic-gate "ibmf_sa_session_close failed %d", ibmf_status);
12250Sstevel@tonic-gate return (IBDM_FAILURE);
12260Sstevel@tonic-gate }
12270Sstevel@tonic-gate port_attr->pa_sa_hdl = NULL;
12280Sstevel@tonic-gate }
12290Sstevel@tonic-gate
12300Sstevel@tonic-gate if (port_attr->pa_pkey_tbl != NULL) {
12310Sstevel@tonic-gate kmem_free(port_attr->pa_pkey_tbl,
12320Sstevel@tonic-gate port_attr->pa_npkeys * sizeof (ibdm_pkey_tbl_t));
12330Sstevel@tonic-gate port_attr->pa_pkey_tbl = NULL;
12340Sstevel@tonic-gate port_attr->pa_npkeys = 0;
12350Sstevel@tonic-gate }
12360Sstevel@tonic-gate
12370Sstevel@tonic-gate return (IBDM_SUCCESS);
12380Sstevel@tonic-gate }
12390Sstevel@tonic-gate
12400Sstevel@tonic-gate
12410Sstevel@tonic-gate /*
12420Sstevel@tonic-gate * ibdm_port_attr_ibmf_fini:
12430Sstevel@tonic-gate * With IBMF - Tear down Async callback and free QP Handle
12440Sstevel@tonic-gate */
12450Sstevel@tonic-gate static int
ibdm_port_attr_ibmf_fini(ibdm_port_attr_t * port_attr,int ii)12460Sstevel@tonic-gate ibdm_port_attr_ibmf_fini(ibdm_port_attr_t *port_attr, int ii)
12470Sstevel@tonic-gate {
12480Sstevel@tonic-gate int ibmf_status;
12490Sstevel@tonic-gate
12500Sstevel@tonic-gate IBTF_DPRINTF_L5("ibdm", "\tport_attr_ibmf_fini:");
12510Sstevel@tonic-gate
1252*12723SRamaswamy.Tummala@Sun.COM if (ibdm_enumerate_iocs == 0) {
1253*12723SRamaswamy.Tummala@Sun.COM ASSERT(port_attr->pa_pkey_tbl[ii].pt_qp_hdl == NULL);
1254*12723SRamaswamy.Tummala@Sun.COM return (IBDM_SUCCESS);
1255*12723SRamaswamy.Tummala@Sun.COM }
1256*12723SRamaswamy.Tummala@Sun.COM
12570Sstevel@tonic-gate if (port_attr->pa_pkey_tbl[ii].pt_qp_hdl) {
12580Sstevel@tonic-gate ibmf_status = ibmf_tear_down_async_cb(port_attr->pa_ibmf_hdl,
12590Sstevel@tonic-gate port_attr->pa_pkey_tbl[ii].pt_qp_hdl, 0);
12600Sstevel@tonic-gate if (ibmf_status != IBMF_SUCCESS) {
12610Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tport_attr_ibmf_fini: "
12620Sstevel@tonic-gate "ibmf_tear_down_async_cb failed %d", ibmf_status);
12630Sstevel@tonic-gate return (IBDM_FAILURE);
12640Sstevel@tonic-gate }
12650Sstevel@tonic-gate ibmf_status = ibmf_free_qp(port_attr->pa_ibmf_hdl,
12660Sstevel@tonic-gate &port_attr->pa_pkey_tbl[ii].pt_qp_hdl, 0);
12670Sstevel@tonic-gate if (ibmf_status != IBMF_SUCCESS) {
12680Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tport_attr_ibmf_fini: "
12690Sstevel@tonic-gate "ibmf_free_qp failed %d", ibmf_status);
12700Sstevel@tonic-gate return (IBDM_FAILURE);
12710Sstevel@tonic-gate }
12720Sstevel@tonic-gate port_attr->pa_pkey_tbl[ii].pt_qp_hdl = NULL;
12730Sstevel@tonic-gate }
12740Sstevel@tonic-gate return (IBDM_SUCCESS);
12750Sstevel@tonic-gate }
12760Sstevel@tonic-gate
12770Sstevel@tonic-gate
12780Sstevel@tonic-gate /*
12790Sstevel@tonic-gate * ibdm_gid_decr_pending:
12800Sstevel@tonic-gate * decrement gl_pending_cmds. If zero wakeup sleeping threads
12810Sstevel@tonic-gate */
12820Sstevel@tonic-gate static void
ibdm_gid_decr_pending(ibdm_dp_gidinfo_t * gidinfo)12830Sstevel@tonic-gate ibdm_gid_decr_pending(ibdm_dp_gidinfo_t *gidinfo)
12840Sstevel@tonic-gate {
12850Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
12860Sstevel@tonic-gate mutex_enter(&gidinfo->gl_mutex);
12870Sstevel@tonic-gate if (--gidinfo->gl_pending_cmds == 0) {
12880Sstevel@tonic-gate /*
12890Sstevel@tonic-gate * Handle DGID getting removed.
12900Sstevel@tonic-gate */
12910Sstevel@tonic-gate if (gidinfo->gl_disconnected) {
12920Sstevel@tonic-gate mutex_exit(&gidinfo->gl_mutex);
12930Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
12940Sstevel@tonic-gate
12950Sstevel@tonic-gate IBTF_DPRINTF_L3(ibdm_string, "\tgid_decr_pending: "
12960Sstevel@tonic-gate "gidinfo %p hot removal", gidinfo);
12970Sstevel@tonic-gate ibdm_delete_gidinfo(gidinfo);
12980Sstevel@tonic-gate
12990Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
13000Sstevel@tonic-gate ibdm.ibdm_ngid_probes_in_progress--;
13010Sstevel@tonic-gate ibdm_wait_probe_completion();
13020Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
13030Sstevel@tonic-gate return;
13040Sstevel@tonic-gate }
13050Sstevel@tonic-gate mutex_exit(&gidinfo->gl_mutex);
13060Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
13070Sstevel@tonic-gate ibdm_notify_newgid_iocs(gidinfo);
13080Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
13090Sstevel@tonic-gate mutex_enter(&gidinfo->gl_mutex);
13100Sstevel@tonic-gate
13110Sstevel@tonic-gate ibdm.ibdm_ngid_probes_in_progress--;
13120Sstevel@tonic-gate ibdm_wait_probe_completion();
13130Sstevel@tonic-gate }
13140Sstevel@tonic-gate mutex_exit(&gidinfo->gl_mutex);
13150Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
13160Sstevel@tonic-gate }
13170Sstevel@tonic-gate
13180Sstevel@tonic-gate
13190Sstevel@tonic-gate /*
13200Sstevel@tonic-gate * ibdm_wait_probe_completion:
13210Sstevel@tonic-gate * wait for probing to complete
13220Sstevel@tonic-gate */
13230Sstevel@tonic-gate static void
ibdm_wait_probe_completion(void)13240Sstevel@tonic-gate ibdm_wait_probe_completion(void)
13250Sstevel@tonic-gate {
13260Sstevel@tonic-gate ASSERT(MUTEX_HELD(&ibdm.ibdm_mutex));
13270Sstevel@tonic-gate if (ibdm.ibdm_ngid_probes_in_progress) {
13280Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\twait for probe complete");
13290Sstevel@tonic-gate ibdm.ibdm_busy |= IBDM_PROBE_IN_PROGRESS;
13300Sstevel@tonic-gate while (ibdm.ibdm_busy & IBDM_PROBE_IN_PROGRESS)
13310Sstevel@tonic-gate cv_wait(&ibdm.ibdm_probe_cv, &ibdm.ibdm_mutex);
13320Sstevel@tonic-gate }
13330Sstevel@tonic-gate }
13340Sstevel@tonic-gate
13350Sstevel@tonic-gate
13360Sstevel@tonic-gate /*
13376262Seota * ibdm_wait_cisco_probe_completion:
13386262Seota * wait for the reply from the Cisco FC GW switch after a setclassportinfo
13396262Seota * request is sent. This wait can be achieved on each gid.
13406262Seota */
13416262Seota static void
ibdm_wait_cisco_probe_completion(ibdm_dp_gidinfo_t * gidinfo)13426262Seota ibdm_wait_cisco_probe_completion(ibdm_dp_gidinfo_t *gidinfo)
13436262Seota {
13446262Seota ASSERT(MUTEX_HELD(&gidinfo->gl_mutex));
13456262Seota IBTF_DPRINTF_L4("ibdm", "\twait for cisco probe complete");
13466262Seota gidinfo->gl_flag |= IBDM_CISCO_PROBE;
13476262Seota while (gidinfo->gl_flag & IBDM_CISCO_PROBE)
13486262Seota cv_wait(&gidinfo->gl_probe_cv, &gidinfo->gl_mutex);
13496262Seota }
13506262Seota
13516262Seota
13526262Seota /*
13530Sstevel@tonic-gate * ibdm_wakeup_probe_gid_cv:
13540Sstevel@tonic-gate * wakeup waiting threads (based on ibdm_ngid_probes_in_progress)
13550Sstevel@tonic-gate */
13560Sstevel@tonic-gate static void
ibdm_wakeup_probe_gid_cv(void)13570Sstevel@tonic-gate ibdm_wakeup_probe_gid_cv(void)
13580Sstevel@tonic-gate {
13590Sstevel@tonic-gate ASSERT(MUTEX_HELD(&ibdm.ibdm_mutex));
13600Sstevel@tonic-gate if (!ibdm.ibdm_ngid_probes_in_progress) {
13610Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "wakeup_probe_gid_thread: Wakeup");
13620Sstevel@tonic-gate ibdm.ibdm_busy &= ~IBDM_PROBE_IN_PROGRESS;
13630Sstevel@tonic-gate cv_broadcast(&ibdm.ibdm_probe_cv);
13640Sstevel@tonic-gate }
13650Sstevel@tonic-gate
13660Sstevel@tonic-gate }
13670Sstevel@tonic-gate
13680Sstevel@tonic-gate
13690Sstevel@tonic-gate /*
13700Sstevel@tonic-gate * ibdm_sweep_fabric(reprobe_flag)
13710Sstevel@tonic-gate * Find all possible Managed IOU's and their IOC's that are visible
13720Sstevel@tonic-gate * to the host. The algorithm used is as follows
13730Sstevel@tonic-gate *
13740Sstevel@tonic-gate * Send a "bus walk" request for each port on the host HCA to SA access
13750Sstevel@tonic-gate * SA returns complete set of GID's that are reachable from
13760Sstevel@tonic-gate * source port. This is done in parallel.
13770Sstevel@tonic-gate *
13780Sstevel@tonic-gate * Initialize GID state to IBDM_GID_PROBE_NOT_DONE
13790Sstevel@tonic-gate *
13800Sstevel@tonic-gate * Sort the GID list and eliminate duplicate GID's
13810Sstevel@tonic-gate * 1) Use DGID for sorting
13820Sstevel@tonic-gate * 2) use PortGuid for sorting
13830Sstevel@tonic-gate * Send SA query to retrieve NodeRecord and
13840Sstevel@tonic-gate * extract PortGuid from that.
13850Sstevel@tonic-gate *
13860Sstevel@tonic-gate * Set GID state to IBDM_GID_PROBE_FAILED to all the ports that dont
13870Sstevel@tonic-gate * support DM MAD's
13880Sstevel@tonic-gate * Send a "Portinfo" query to get the port capabilities and
13890Sstevel@tonic-gate * then check for DM MAD's support
13900Sstevel@tonic-gate *
13910Sstevel@tonic-gate * Send "ClassPortInfo" request for all the GID's in parallel,
13920Sstevel@tonic-gate * set the GID state to IBDM_GET_CLASSPORTINFO and wait on the
13930Sstevel@tonic-gate * cv_signal to complete.
13940Sstevel@tonic-gate *
13950Sstevel@tonic-gate * When DM agent on the remote GID sends back the response, IBMF
13960Sstevel@tonic-gate * invokes DM callback routine.
13970Sstevel@tonic-gate *
13980Sstevel@tonic-gate * If the response is proper, send "IOUnitInfo" request and set
13990Sstevel@tonic-gate * GID state to IBDM_GET_IOUNITINFO.
14000Sstevel@tonic-gate *
14010Sstevel@tonic-gate * If the response is proper, send "IocProfileInfo" request to
14020Sstevel@tonic-gate * all the IOC simultaneously and set GID state to IBDM_GET_IOC_DETAILS.
14030Sstevel@tonic-gate *
14040Sstevel@tonic-gate * Send request to get Service entries simultaneously
14050Sstevel@tonic-gate *
14060Sstevel@tonic-gate * Signal the waiting thread when received response for all the commands.
14070Sstevel@tonic-gate *
14080Sstevel@tonic-gate * Set the GID state to IBDM_GID_PROBE_FAILED when received a error
14090Sstevel@tonic-gate * response during the probing period.
14100Sstevel@tonic-gate *
14110Sstevel@tonic-gate * Note:
14120Sstevel@tonic-gate * ibdm.ibdm_ngid_probes_in_progress and ibdm_gid_list_t:gl_pending_cmds
14130Sstevel@tonic-gate * keep track of number commands in progress at any point of time.
14140Sstevel@tonic-gate * MAD transaction ID is used to identify a particular GID
14150Sstevel@tonic-gate * TBD: Consider registering the IBMF receive callback on demand
14160Sstevel@tonic-gate *
14170Sstevel@tonic-gate * Note: This routine must be called with ibdm.ibdm_mutex held
14180Sstevel@tonic-gate * TBD: Re probe the failure GID (for certain failures) when requested
14190Sstevel@tonic-gate * for fabric sweep next time
14200Sstevel@tonic-gate *
14210Sstevel@tonic-gate * Parameters : If reprobe_flag is set, All IOCs will be reprobed.
14220Sstevel@tonic-gate */
14230Sstevel@tonic-gate static void
ibdm_sweep_fabric(int reprobe_flag)14240Sstevel@tonic-gate ibdm_sweep_fabric(int reprobe_flag)
14250Sstevel@tonic-gate {
14260Sstevel@tonic-gate int ii;
14270Sstevel@tonic-gate int new_paths = 0;
14280Sstevel@tonic-gate uint8_t niocs;
14290Sstevel@tonic-gate taskqid_t tid;
14300Sstevel@tonic-gate ibdm_ioc_info_t *ioc;
14310Sstevel@tonic-gate ibdm_hca_list_t *hca_list = NULL;
14320Sstevel@tonic-gate ibdm_port_attr_t *port = NULL;
14330Sstevel@tonic-gate ibdm_dp_gidinfo_t *gid_info;
14340Sstevel@tonic-gate
14350Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tsweep_fabric: Enter");
14360Sstevel@tonic-gate ASSERT(MUTEX_HELD(&ibdm.ibdm_mutex));
14370Sstevel@tonic-gate
14380Sstevel@tonic-gate /*
14390Sstevel@tonic-gate * Check whether a sweep already in progress. If so, just
14400Sstevel@tonic-gate * wait for the fabric sweep to complete
14410Sstevel@tonic-gate */
14420Sstevel@tonic-gate while (ibdm.ibdm_busy & IBDM_BUSY)
14430Sstevel@tonic-gate cv_wait(&ibdm.ibdm_busy_cv, &ibdm.ibdm_mutex);
14440Sstevel@tonic-gate ibdm.ibdm_busy |= IBDM_BUSY;
14450Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
14460Sstevel@tonic-gate
14470Sstevel@tonic-gate ibdm_dump_sweep_fabric_timestamp(0);
14480Sstevel@tonic-gate
14490Sstevel@tonic-gate /* Rescan the GID list for any removed GIDs for reprobe */
14500Sstevel@tonic-gate if (reprobe_flag)
14510Sstevel@tonic-gate ibdm_rescan_gidlist(NULL);
14520Sstevel@tonic-gate
14530Sstevel@tonic-gate /*
14540Sstevel@tonic-gate * Get list of all the ports reachable from the local known HCA
14550Sstevel@tonic-gate * ports which are active
14560Sstevel@tonic-gate */
14570Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_hl_mutex);
14580Sstevel@tonic-gate for (ibdm_get_next_port(&hca_list, &port, 1); port;
14590Sstevel@tonic-gate ibdm_get_next_port(&hca_list, &port, 1)) {
14600Sstevel@tonic-gate /*
14610Sstevel@tonic-gate * Get PATHS to all the reachable ports from
14620Sstevel@tonic-gate * SGID and update the global ibdm structure.
14630Sstevel@tonic-gate */
14640Sstevel@tonic-gate new_paths = ibdm_get_reachable_ports(port, hca_list);
14650Sstevel@tonic-gate ibdm.ibdm_ngids += new_paths;
14660Sstevel@tonic-gate }
14670Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_hl_mutex);
14680Sstevel@tonic-gate
14690Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
14700Sstevel@tonic-gate ibdm.ibdm_ngid_probes_in_progress += ibdm.ibdm_ngids;
14710Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
14720Sstevel@tonic-gate
14730Sstevel@tonic-gate /* Send a request to probe GIDs asynchronously. */
14740Sstevel@tonic-gate for (gid_info = ibdm.ibdm_dp_gidlist_head; gid_info;
14750Sstevel@tonic-gate gid_info = gid_info->gl_next) {
14760Sstevel@tonic-gate mutex_enter(&gid_info->gl_mutex);
14770Sstevel@tonic-gate gid_info->gl_reprobe_flag = reprobe_flag;
14780Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
14790Sstevel@tonic-gate
14800Sstevel@tonic-gate /* process newly encountered GIDs */
14810Sstevel@tonic-gate tid = taskq_dispatch(system_taskq, ibdm_probe_gid_thread,
14820Sstevel@tonic-gate (void *)gid_info, TQ_NOSLEEP);
14830Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tsweep_fabric: gid_info = %p"
14840Sstevel@tonic-gate " taskq_id = %x", gid_info, tid);
14850Sstevel@tonic-gate /* taskq failed to dispatch call it directly */
14860Sstevel@tonic-gate if (tid == NULL)
14870Sstevel@tonic-gate ibdm_probe_gid_thread((void *)gid_info);
14880Sstevel@tonic-gate }
14890Sstevel@tonic-gate
14900Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
14910Sstevel@tonic-gate ibdm_wait_probe_completion();
14920Sstevel@tonic-gate
14930Sstevel@tonic-gate /*
14940Sstevel@tonic-gate * Update the properties, if reprobe_flag is set
14950Sstevel@tonic-gate * Skip if gl_reprobe_flag is set, this will be
14960Sstevel@tonic-gate * a re-inserted / new GID, for which notifications
14970Sstevel@tonic-gate * have already been send.
14980Sstevel@tonic-gate */
14990Sstevel@tonic-gate if (reprobe_flag) {
15000Sstevel@tonic-gate for (gid_info = ibdm.ibdm_dp_gidlist_head; gid_info;
15010Sstevel@tonic-gate gid_info = gid_info->gl_next) {
15020Sstevel@tonic-gate if (gid_info->gl_iou == NULL)
15030Sstevel@tonic-gate continue;
15040Sstevel@tonic-gate if (gid_info->gl_reprobe_flag) {
15050Sstevel@tonic-gate gid_info->gl_reprobe_flag = 0;
15060Sstevel@tonic-gate continue;
15070Sstevel@tonic-gate }
15080Sstevel@tonic-gate
15090Sstevel@tonic-gate niocs = gid_info->gl_iou->iou_info.iou_num_ctrl_slots;
15100Sstevel@tonic-gate for (ii = 0; ii < niocs; ii++) {
15110Sstevel@tonic-gate ioc = IBDM_GIDINFO2IOCINFO(gid_info, ii);
15120Sstevel@tonic-gate if (ioc)
15130Sstevel@tonic-gate ibdm_reprobe_update_port_srv(ioc,
15140Sstevel@tonic-gate gid_info);
15150Sstevel@tonic-gate }
15160Sstevel@tonic-gate }
15174024Spramodbg } else if (ibdm.ibdm_prev_iou) {
15184024Spramodbg ibdm_ioc_info_t *ioc_list;
15194024Spramodbg
15204024Spramodbg /*
15214024Spramodbg * Get the list of IOCs which have changed.
15224024Spramodbg * If any IOCs have changed, Notify IBNexus
15234024Spramodbg */
15244024Spramodbg ibdm.ibdm_prev_iou = 0;
15254024Spramodbg ioc_list = ibdm_handle_prev_iou();
15264024Spramodbg if (ioc_list) {
15274024Spramodbg if (ibdm.ibdm_ibnex_callback != NULL) {
15284024Spramodbg (*ibdm.ibdm_ibnex_callback)(
15294024Spramodbg (void *)ioc_list,
15304024Spramodbg IBDM_EVENT_IOC_PROP_UPDATE);
15314024Spramodbg }
15324024Spramodbg }
15334024Spramodbg }
15344024Spramodbg
15350Sstevel@tonic-gate ibdm_dump_sweep_fabric_timestamp(1);
15360Sstevel@tonic-gate
15370Sstevel@tonic-gate ibdm.ibdm_busy &= ~IBDM_BUSY;
15380Sstevel@tonic-gate cv_broadcast(&ibdm.ibdm_busy_cv);
15390Sstevel@tonic-gate IBTF_DPRINTF_L5("ibdm", "\tsweep_fabric: EXIT");
15400Sstevel@tonic-gate }
15410Sstevel@tonic-gate
15420Sstevel@tonic-gate
15430Sstevel@tonic-gate /*
15446262Seota * ibdm_is_cisco:
15456262Seota * Check if this is a Cisco device or not.
15466262Seota */
15476262Seota static boolean_t
ibdm_is_cisco(ib_guid_t guid)15486262Seota ibdm_is_cisco(ib_guid_t guid)
15496262Seota {
15506262Seota if ((guid >> IBDM_OUI_GUID_SHIFT) == IBDM_CISCO_COMPANY_ID)
15516262Seota return (B_TRUE);
15526262Seota return (B_FALSE);
15536262Seota }
15546262Seota
15556262Seota
15566262Seota /*
15576262Seota * ibdm_is_cisco_switch:
15586262Seota * Check if this switch is a CISCO switch or not.
15596262Seota * Note that if this switch is already activated, ibdm_is_cisco_switch()
15606262Seota * returns B_FALSE not to re-activate it again.
15616262Seota */
15626262Seota static boolean_t
ibdm_is_cisco_switch(ibdm_dp_gidinfo_t * gid_info)15636262Seota ibdm_is_cisco_switch(ibdm_dp_gidinfo_t *gid_info)
15646262Seota {
15656262Seota int company_id, device_id;
15666262Seota ASSERT(gid_info != 0);
15676262Seota ASSERT(MUTEX_HELD(&gid_info->gl_mutex));
15686262Seota
15696262Seota /*
15706262Seota * If this switch is already activated, don't re-activate it.
15716262Seota */
15726262Seota if (gid_info->gl_flag & IBDM_CISCO_PROBE_DONE)
15736262Seota return (B_FALSE);
15746262Seota
15756262Seota /*
15766262Seota * Check if this switch is a Cisco FC GW or not.
15776262Seota * Use the node guid (the OUI part) instead of the vendor id
15786262Seota * since the vendor id is zero in practice.
15796262Seota */
15806262Seota company_id = gid_info->gl_nodeguid >> IBDM_OUI_GUID_SHIFT;
15816262Seota device_id = gid_info->gl_devid;
15826262Seota
15836262Seota if (company_id == IBDM_CISCO_COMPANY_ID &&
15846262Seota device_id == IBDM_CISCO_DEVICE_ID)
15856262Seota return (B_TRUE);
15866262Seota return (B_FALSE);
15876262Seota }
15886262Seota
15896262Seota
15906262Seota /*
15910Sstevel@tonic-gate * ibdm_probe_gid_thread:
15920Sstevel@tonic-gate * thread that does the actual work for sweeping the fabric
15930Sstevel@tonic-gate * for a given GID
15940Sstevel@tonic-gate */
15950Sstevel@tonic-gate static void
ibdm_probe_gid_thread(void * args)15960Sstevel@tonic-gate ibdm_probe_gid_thread(void *args)
15970Sstevel@tonic-gate {
15980Sstevel@tonic-gate int reprobe_flag;
15990Sstevel@tonic-gate ib_guid_t node_guid;
16000Sstevel@tonic-gate ib_guid_t port_guid;
16010Sstevel@tonic-gate ibdm_dp_gidinfo_t *gid_info;
16020Sstevel@tonic-gate
16030Sstevel@tonic-gate gid_info = (ibdm_dp_gidinfo_t *)args;
16040Sstevel@tonic-gate reprobe_flag = gid_info->gl_reprobe_flag;
16050Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tprobe_gid_thread: gid_info = %p, flag = %d",
16060Sstevel@tonic-gate gid_info, reprobe_flag);
16070Sstevel@tonic-gate ASSERT(gid_info != NULL);
16080Sstevel@tonic-gate ASSERT(gid_info->gl_pending_cmds == 0);
16090Sstevel@tonic-gate
16100Sstevel@tonic-gate if (gid_info->gl_state != IBDM_GID_PROBE_NOT_DONE &&
16110Sstevel@tonic-gate reprobe_flag == 0) {
16120Sstevel@tonic-gate /*
16130Sstevel@tonic-gate * This GID may have been already probed. Send
16140Sstevel@tonic-gate * in a CLP to check if IOUnitInfo changed?
16150Sstevel@tonic-gate * Explicitly set gl_reprobe_flag to 0 so that
16160Sstevel@tonic-gate * IBnex is not notified on completion
16170Sstevel@tonic-gate */
16180Sstevel@tonic-gate if (gid_info->gl_state == IBDM_GID_PROBING_COMPLETE) {
16190Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tprobe_gid_thread: "
16200Sstevel@tonic-gate "get new IOCs information");
16210Sstevel@tonic-gate mutex_enter(&gid_info->gl_mutex);
16220Sstevel@tonic-gate gid_info->gl_pending_cmds++;
16230Sstevel@tonic-gate gid_info->gl_state = IBDM_GET_IOUNITINFO;
16240Sstevel@tonic-gate gid_info->gl_reprobe_flag = 0;
16250Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
16260Sstevel@tonic-gate if (ibdm_send_iounitinfo(gid_info) != IBDM_SUCCESS) {
16270Sstevel@tonic-gate mutex_enter(&gid_info->gl_mutex);
16286262Seota --gid_info->gl_pending_cmds;
16290Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
16300Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
16310Sstevel@tonic-gate --ibdm.ibdm_ngid_probes_in_progress;
16320Sstevel@tonic-gate ibdm_wakeup_probe_gid_cv();
16330Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
16340Sstevel@tonic-gate }
16350Sstevel@tonic-gate } else {
16360Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
16370Sstevel@tonic-gate --ibdm.ibdm_ngid_probes_in_progress;
16380Sstevel@tonic-gate ibdm_wakeup_probe_gid_cv();
16390Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
16400Sstevel@tonic-gate }
16410Sstevel@tonic-gate return;
16420Sstevel@tonic-gate } else if (reprobe_flag && gid_info->gl_state ==
16430Sstevel@tonic-gate IBDM_GID_PROBING_COMPLETE) {
16440Sstevel@tonic-gate /*
16450Sstevel@tonic-gate * Reprobe all IOCs for the GID which has completed
16460Sstevel@tonic-gate * probe. Skip other port GIDs to same IOU.
16470Sstevel@tonic-gate * Explicitly set gl_reprobe_flag to 0 so that
16480Sstevel@tonic-gate * IBnex is not notified on completion
16490Sstevel@tonic-gate */
16500Sstevel@tonic-gate ibdm_ioc_info_t *ioc_info;
16510Sstevel@tonic-gate uint8_t niocs, ii;
16520Sstevel@tonic-gate
16531689Spramodbg ASSERT(gid_info->gl_iou);
16540Sstevel@tonic-gate mutex_enter(&gid_info->gl_mutex);
16550Sstevel@tonic-gate niocs = gid_info->gl_iou->iou_info.iou_num_ctrl_slots;
16560Sstevel@tonic-gate gid_info->gl_state = IBDM_GET_IOC_DETAILS;
16570Sstevel@tonic-gate gid_info->gl_pending_cmds += niocs;
16580Sstevel@tonic-gate gid_info->gl_reprobe_flag = 0;
16590Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
16600Sstevel@tonic-gate for (ii = 0; ii < niocs; ii++) {
16610Sstevel@tonic-gate uchar_t slot_info;
16620Sstevel@tonic-gate ib_dm_io_unitinfo_t *giou_info;
16630Sstevel@tonic-gate
16640Sstevel@tonic-gate /*
16650Sstevel@tonic-gate * Check whether IOC is present in the slot
16660Sstevel@tonic-gate * Series of nibbles (in the field
16670Sstevel@tonic-gate * iou_ctrl_list) represents a slot in the
16680Sstevel@tonic-gate * IOU.
16690Sstevel@tonic-gate * Byte format: 76543210
16700Sstevel@tonic-gate * Bits 0-3 of first byte represent Slot 2
16710Sstevel@tonic-gate * bits 4-7 of first byte represent slot 1,
16720Sstevel@tonic-gate * bits 0-3 of second byte represent slot 4
16730Sstevel@tonic-gate * and so on
16740Sstevel@tonic-gate * Each 4-bit nibble has the following meaning
16750Sstevel@tonic-gate * 0x0 : IOC not installed
16760Sstevel@tonic-gate * 0x1 : IOC is present
16770Sstevel@tonic-gate * 0xf : Slot does not exist
16780Sstevel@tonic-gate * and all other values are reserved.
16790Sstevel@tonic-gate */
16800Sstevel@tonic-gate ioc_info = IBDM_GIDINFO2IOCINFO(gid_info, ii);
16810Sstevel@tonic-gate giou_info = &gid_info->gl_iou->iou_info;
16820Sstevel@tonic-gate slot_info = giou_info->iou_ctrl_list[(ii/2)];
16830Sstevel@tonic-gate if ((ii % 2) == 0)
16840Sstevel@tonic-gate slot_info = (slot_info >> 4);
16850Sstevel@tonic-gate
16860Sstevel@tonic-gate if ((slot_info & 0xf) != 1) {
16870Sstevel@tonic-gate ioc_info->ioc_state =
16880Sstevel@tonic-gate IBDM_IOC_STATE_PROBE_FAILED;
16890Sstevel@tonic-gate ibdm_gid_decr_pending(gid_info);
16900Sstevel@tonic-gate continue;
16910Sstevel@tonic-gate }
16920Sstevel@tonic-gate
16930Sstevel@tonic-gate if (ibdm_send_ioc_profile(gid_info, ii) !=
16940Sstevel@tonic-gate IBDM_SUCCESS) {
16950Sstevel@tonic-gate ibdm_gid_decr_pending(gid_info);
16960Sstevel@tonic-gate }
16970Sstevel@tonic-gate }
16980Sstevel@tonic-gate
16990Sstevel@tonic-gate return;
17000Sstevel@tonic-gate } else if (gid_info->gl_state != IBDM_GID_PROBE_NOT_DONE) {
17010Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
17020Sstevel@tonic-gate --ibdm.ibdm_ngid_probes_in_progress;
17030Sstevel@tonic-gate ibdm_wakeup_probe_gid_cv();
17040Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
17050Sstevel@tonic-gate return;
17060Sstevel@tonic-gate }
17070Sstevel@tonic-gate
17080Sstevel@tonic-gate /*
17090Sstevel@tonic-gate * Check whether the destination GID supports DM agents. If
17100Sstevel@tonic-gate * not, stop probing the GID and continue with the next GID
17110Sstevel@tonic-gate * in the list.
17120Sstevel@tonic-gate */
17130Sstevel@tonic-gate if (ibdm_is_dev_mgt_supported(gid_info) != IBDM_SUCCESS) {
17140Sstevel@tonic-gate mutex_enter(&gid_info->gl_mutex);
17150Sstevel@tonic-gate gid_info->gl_state = IBDM_GID_PROBING_FAILED;
171610231SRajkumar.Sivaprakasam@Sun.COM gid_info->gl_is_dm_capable = B_FALSE;
17170Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
17180Sstevel@tonic-gate ibdm_delete_glhca_list(gid_info);
17190Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
17200Sstevel@tonic-gate --ibdm.ibdm_ngid_probes_in_progress;
17210Sstevel@tonic-gate ibdm_wakeup_probe_gid_cv();
17220Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
17230Sstevel@tonic-gate return;
17240Sstevel@tonic-gate }
17250Sstevel@tonic-gate
172610231SRajkumar.Sivaprakasam@Sun.COM /*
172710231SRajkumar.Sivaprakasam@Sun.COM * This GID is Device management capable
172810231SRajkumar.Sivaprakasam@Sun.COM */
172910231SRajkumar.Sivaprakasam@Sun.COM mutex_enter(&gid_info->gl_mutex);
173010231SRajkumar.Sivaprakasam@Sun.COM gid_info->gl_is_dm_capable = B_TRUE;
173110231SRajkumar.Sivaprakasam@Sun.COM mutex_exit(&gid_info->gl_mutex);
173210231SRajkumar.Sivaprakasam@Sun.COM
17330Sstevel@tonic-gate /* Get the nodeguid and portguid of the port */
17340Sstevel@tonic-gate if (ibdm_get_node_port_guids(gid_info->gl_sa_hdl, gid_info->gl_dlid,
17350Sstevel@tonic-gate &node_guid, &port_guid) != IBDM_SUCCESS) {
17360Sstevel@tonic-gate mutex_enter(&gid_info->gl_mutex);
17370Sstevel@tonic-gate gid_info->gl_state = IBDM_GID_PROBING_FAILED;
17380Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
17390Sstevel@tonic-gate ibdm_delete_glhca_list(gid_info);
17400Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
17410Sstevel@tonic-gate --ibdm.ibdm_ngid_probes_in_progress;
17420Sstevel@tonic-gate ibdm_wakeup_probe_gid_cv();
17430Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
17440Sstevel@tonic-gate return;
17450Sstevel@tonic-gate }
17460Sstevel@tonic-gate
17470Sstevel@tonic-gate /*
17480Sstevel@tonic-gate * Check whether we already knew about this NodeGuid
17490Sstevel@tonic-gate * If so, do not probe the GID and continue with the
17500Sstevel@tonic-gate * next GID in the gid list. Set the GID state to
17510Sstevel@tonic-gate * probing done.
17520Sstevel@tonic-gate */
17530Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
17540Sstevel@tonic-gate gid_info->gl_nodeguid = node_guid;
17550Sstevel@tonic-gate gid_info->gl_portguid = port_guid;
17560Sstevel@tonic-gate if (ibdm_check_dest_nodeguid(gid_info) != NULL) {
17570Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
17580Sstevel@tonic-gate mutex_enter(&gid_info->gl_mutex);
17590Sstevel@tonic-gate gid_info->gl_state = IBDM_GID_PROBING_SKIPPED;
17600Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
17610Sstevel@tonic-gate ibdm_delete_glhca_list(gid_info);
17620Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
17630Sstevel@tonic-gate --ibdm.ibdm_ngid_probes_in_progress;
17640Sstevel@tonic-gate ibdm_wakeup_probe_gid_cv();
17650Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
17660Sstevel@tonic-gate return;
17670Sstevel@tonic-gate }
17680Sstevel@tonic-gate ibdm_add_to_gl_gid(gid_info, gid_info);
17690Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
17700Sstevel@tonic-gate
17710Sstevel@tonic-gate /*
17720Sstevel@tonic-gate * New or reinserted GID : Enable notification to IBnex
17730Sstevel@tonic-gate */
17740Sstevel@tonic-gate mutex_enter(&gid_info->gl_mutex);
17750Sstevel@tonic-gate gid_info->gl_reprobe_flag = 1;
17766262Seota
17776262Seota /*
17786262Seota * A Cisco FC GW needs the special handling to get IOUnitInfo.
17796262Seota */
17806262Seota if (ibdm_is_cisco_switch(gid_info)) {
17816262Seota gid_info->gl_pending_cmds++;
17826262Seota gid_info->gl_state = IBDM_SET_CLASSPORTINFO;
17836262Seota mutex_exit(&gid_info->gl_mutex);
17846262Seota
17856262Seota if (ibdm_set_classportinfo(gid_info) != IBDM_SUCCESS) {
17866262Seota mutex_enter(&gid_info->gl_mutex);
17876262Seota gid_info->gl_state = IBDM_GID_PROBING_FAILED;
17886262Seota --gid_info->gl_pending_cmds;
17896262Seota mutex_exit(&gid_info->gl_mutex);
17906262Seota
17916262Seota /* free the hca_list on this gid_info */
17926262Seota ibdm_delete_glhca_list(gid_info);
17936262Seota
17946262Seota mutex_enter(&ibdm.ibdm_mutex);
17956262Seota --ibdm.ibdm_ngid_probes_in_progress;
17966262Seota ibdm_wakeup_probe_gid_cv();
17976262Seota mutex_exit(&ibdm.ibdm_mutex);
17986262Seota
17996262Seota return;
18006262Seota }
18016262Seota
18026262Seota mutex_enter(&gid_info->gl_mutex);
18036262Seota ibdm_wait_cisco_probe_completion(gid_info);
18046262Seota
18056262Seota IBTF_DPRINTF_L4("ibdm", "\tibdm_probe_gid_thread: "
18066262Seota "CISCO Wakeup signal received");
18076262Seota }
18086262Seota
18096262Seota /* move on to the 'GET_CLASSPORTINFO' stage */
18106262Seota gid_info->gl_pending_cmds++;
18116262Seota gid_info->gl_state = IBDM_GET_CLASSPORTINFO;
18120Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
18130Sstevel@tonic-gate
18146262Seota IBTF_DPRINTF_L3(ibdm_string, "\tibdm_probe_gid_thread: "
18156262Seota "%d: gid_info %p gl_state %d pending_cmds %d",
18166262Seota __LINE__, gid_info, gid_info->gl_state,
18176262Seota gid_info->gl_pending_cmds);
18186262Seota
18190Sstevel@tonic-gate /*
18200Sstevel@tonic-gate * Send ClassPortInfo request to the GID asynchronously.
18210Sstevel@tonic-gate */
18220Sstevel@tonic-gate if (ibdm_send_classportinfo(gid_info) != IBDM_SUCCESS) {
18236262Seota
18240Sstevel@tonic-gate mutex_enter(&gid_info->gl_mutex);
18250Sstevel@tonic-gate gid_info->gl_state = IBDM_GID_PROBING_FAILED;
18266262Seota --gid_info->gl_pending_cmds;
18270Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
18286262Seota
18296262Seota /* free the hca_list on this gid_info */
18300Sstevel@tonic-gate ibdm_delete_glhca_list(gid_info);
18316262Seota
18320Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
18330Sstevel@tonic-gate --ibdm.ibdm_ngid_probes_in_progress;
18340Sstevel@tonic-gate ibdm_wakeup_probe_gid_cv();
18350Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
18366262Seota
18370Sstevel@tonic-gate return;
18380Sstevel@tonic-gate }
18390Sstevel@tonic-gate }
18400Sstevel@tonic-gate
18410Sstevel@tonic-gate
18420Sstevel@tonic-gate /*
18430Sstevel@tonic-gate * ibdm_check_dest_nodeguid
18440Sstevel@tonic-gate * Searches for the NodeGuid in the GID list
18450Sstevel@tonic-gate * Returns matching gid_info if found and otherwise NULL
18460Sstevel@tonic-gate *
18470Sstevel@tonic-gate * This function is called to handle new GIDs discovered
18480Sstevel@tonic-gate * during device sweep / probe or for GID_AVAILABLE event.
18490Sstevel@tonic-gate *
18500Sstevel@tonic-gate * Parameter :
18510Sstevel@tonic-gate * gid_info GID to check
18520Sstevel@tonic-gate */
18530Sstevel@tonic-gate static ibdm_dp_gidinfo_t *
ibdm_check_dest_nodeguid(ibdm_dp_gidinfo_t * gid_info)18540Sstevel@tonic-gate ibdm_check_dest_nodeguid(ibdm_dp_gidinfo_t *gid_info)
18550Sstevel@tonic-gate {
18560Sstevel@tonic-gate ibdm_dp_gidinfo_t *gid_list;
18570Sstevel@tonic-gate ibdm_gid_t *tmp;
18580Sstevel@tonic-gate
18590Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tcheck_dest_nodeguid");
18600Sstevel@tonic-gate
18610Sstevel@tonic-gate gid_list = ibdm.ibdm_dp_gidlist_head;
18620Sstevel@tonic-gate while (gid_list) {
18630Sstevel@tonic-gate if ((gid_list != gid_info) &&
18640Sstevel@tonic-gate (gid_info->gl_nodeguid == gid_list->gl_nodeguid)) {
18650Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm",
18660Sstevel@tonic-gate "\tcheck_dest_nodeguid: NodeGuid is present");
18670Sstevel@tonic-gate
18680Sstevel@tonic-gate /* Add to gid_list */
18690Sstevel@tonic-gate tmp = kmem_zalloc(sizeof (ibdm_gid_t),
18700Sstevel@tonic-gate KM_SLEEP);
18710Sstevel@tonic-gate tmp->gid_dgid_hi = gid_info->gl_dgid_hi;
18720Sstevel@tonic-gate tmp->gid_dgid_lo = gid_info->gl_dgid_lo;
18730Sstevel@tonic-gate tmp->gid_next = gid_list->gl_gid;
18740Sstevel@tonic-gate gid_list->gl_gid = tmp;
18750Sstevel@tonic-gate gid_list->gl_ngids++;
18760Sstevel@tonic-gate return (gid_list);
18770Sstevel@tonic-gate }
18780Sstevel@tonic-gate
18790Sstevel@tonic-gate gid_list = gid_list->gl_next;
18800Sstevel@tonic-gate }
18810Sstevel@tonic-gate
18820Sstevel@tonic-gate return (NULL);
18830Sstevel@tonic-gate }
18840Sstevel@tonic-gate
18850Sstevel@tonic-gate
18860Sstevel@tonic-gate /*
18870Sstevel@tonic-gate * ibdm_is_dev_mgt_supported
18880Sstevel@tonic-gate * Get the PortInfo attribute (SA Query)
18890Sstevel@tonic-gate * Check "CompatabilityMask" field in the Portinfo.
18900Sstevel@tonic-gate * Return IBDM_SUCCESS if DM MAD's supported (if bit 19 set)
18910Sstevel@tonic-gate * by the port, otherwise IBDM_FAILURE
18920Sstevel@tonic-gate */
18930Sstevel@tonic-gate static int
ibdm_is_dev_mgt_supported(ibdm_dp_gidinfo_t * gid_info)18940Sstevel@tonic-gate ibdm_is_dev_mgt_supported(ibdm_dp_gidinfo_t *gid_info)
18950Sstevel@tonic-gate {
18960Sstevel@tonic-gate int ret;
18970Sstevel@tonic-gate size_t length = 0;
18980Sstevel@tonic-gate sa_portinfo_record_t req, *resp = NULL;
18990Sstevel@tonic-gate ibmf_saa_access_args_t qargs;
19000Sstevel@tonic-gate
19010Sstevel@tonic-gate bzero(&req, sizeof (sa_portinfo_record_t));
19020Sstevel@tonic-gate req.EndportLID = gid_info->gl_dlid;
19030Sstevel@tonic-gate
19040Sstevel@tonic-gate qargs.sq_attr_id = SA_PORTINFORECORD_ATTRID;
19050Sstevel@tonic-gate qargs.sq_access_type = IBMF_SAA_RETRIEVE;
19060Sstevel@tonic-gate qargs.sq_component_mask = SA_PORTINFO_COMPMASK_PORTLID;
19070Sstevel@tonic-gate qargs.sq_template = &req;
19080Sstevel@tonic-gate qargs.sq_callback = NULL;
19090Sstevel@tonic-gate qargs.sq_callback_arg = NULL;
19100Sstevel@tonic-gate
19110Sstevel@tonic-gate ret = ibmf_sa_access(gid_info->gl_sa_hdl,
19120Sstevel@tonic-gate &qargs, 0, &length, (void **)&resp);
19130Sstevel@tonic-gate
19140Sstevel@tonic-gate if ((ret != IBMF_SUCCESS) || (length == 0) || (resp == NULL)) {
19150Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "\tis_dev_mgt_supported:"
19160Sstevel@tonic-gate "failed to get PORTINFO attribute %d", ret);
19170Sstevel@tonic-gate return (IBDM_FAILURE);
19180Sstevel@tonic-gate }
19190Sstevel@tonic-gate
19200Sstevel@tonic-gate if (resp->PortInfo.CapabilityMask & SM_CAP_MASK_IS_DM_SUPPD) {
19210Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tis_dev_mgt_supported: SUPPD !!");
19220Sstevel@tonic-gate ret = IBDM_SUCCESS;
19230Sstevel@tonic-gate } else {
19240Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tis_dev_mgt_supported: "
19250Sstevel@tonic-gate "Not SUPPD !!, cap 0x%x", resp->PortInfo.CapabilityMask);
19260Sstevel@tonic-gate ret = IBDM_FAILURE;
19270Sstevel@tonic-gate }
19280Sstevel@tonic-gate kmem_free(resp, length);
19290Sstevel@tonic-gate return (ret);
19300Sstevel@tonic-gate }
19310Sstevel@tonic-gate
19320Sstevel@tonic-gate
19330Sstevel@tonic-gate /*
19340Sstevel@tonic-gate * ibdm_get_node_port_guids()
19350Sstevel@tonic-gate * Get the NodeInfoRecord of the port
19360Sstevel@tonic-gate * Save NodeGuid and PortGUID values in the GID list structure.
19370Sstevel@tonic-gate * Return IBDM_SUCCESS/IBDM_FAILURE
19380Sstevel@tonic-gate */
19390Sstevel@tonic-gate static int
ibdm_get_node_port_guids(ibmf_saa_handle_t sa_hdl,ib_lid_t dlid,ib_guid_t * node_guid,ib_guid_t * port_guid)19400Sstevel@tonic-gate ibdm_get_node_port_guids(ibmf_saa_handle_t sa_hdl, ib_lid_t dlid,
19410Sstevel@tonic-gate ib_guid_t *node_guid, ib_guid_t *port_guid)
19420Sstevel@tonic-gate {
19430Sstevel@tonic-gate int ret;
19440Sstevel@tonic-gate size_t length = 0;
19450Sstevel@tonic-gate sa_node_record_t req, *resp = NULL;
19460Sstevel@tonic-gate ibmf_saa_access_args_t qargs;
19470Sstevel@tonic-gate
19480Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tget_node_port_guids");
19490Sstevel@tonic-gate
19500Sstevel@tonic-gate bzero(&req, sizeof (sa_node_record_t));
19510Sstevel@tonic-gate req.LID = dlid;
19520Sstevel@tonic-gate
19530Sstevel@tonic-gate qargs.sq_attr_id = SA_NODERECORD_ATTRID;
19540Sstevel@tonic-gate qargs.sq_access_type = IBMF_SAA_RETRIEVE;
19550Sstevel@tonic-gate qargs.sq_component_mask = SA_NODEINFO_COMPMASK_NODELID;
19560Sstevel@tonic-gate qargs.sq_template = &req;
19570Sstevel@tonic-gate qargs.sq_callback = NULL;
19580Sstevel@tonic-gate qargs.sq_callback_arg = NULL;
19590Sstevel@tonic-gate
19600Sstevel@tonic-gate ret = ibmf_sa_access(sa_hdl, &qargs, 0, &length, (void **)&resp);
19610Sstevel@tonic-gate if ((ret != IBMF_SUCCESS) || (length == 0) || (resp == NULL)) {
19620Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "\tget_node_port_guids:"
19630Sstevel@tonic-gate " SA Retrieve Failed: %d", ret);
19640Sstevel@tonic-gate return (IBDM_FAILURE);
19650Sstevel@tonic-gate }
19660Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tget_node_port_guids: NodeGuid %llx Port"
19670Sstevel@tonic-gate "GUID %llx", resp->NodeInfo.NodeGUID, resp->NodeInfo.NodeGUID);
19680Sstevel@tonic-gate
19690Sstevel@tonic-gate *node_guid = resp->NodeInfo.NodeGUID;
19700Sstevel@tonic-gate *port_guid = resp->NodeInfo.PortGUID;
19710Sstevel@tonic-gate kmem_free(resp, length);
19720Sstevel@tonic-gate return (IBDM_SUCCESS);
19730Sstevel@tonic-gate }
19740Sstevel@tonic-gate
19750Sstevel@tonic-gate
19760Sstevel@tonic-gate /*
19770Sstevel@tonic-gate * ibdm_get_reachable_ports()
19780Sstevel@tonic-gate * Get list of the destination GID (and its path records) by
19790Sstevel@tonic-gate * querying the SA access.
19800Sstevel@tonic-gate *
19810Sstevel@tonic-gate * Returns Number paths
19820Sstevel@tonic-gate */
19830Sstevel@tonic-gate static int
ibdm_get_reachable_ports(ibdm_port_attr_t * portinfo,ibdm_hca_list_t * hca)19840Sstevel@tonic-gate ibdm_get_reachable_ports(ibdm_port_attr_t *portinfo, ibdm_hca_list_t *hca)
19850Sstevel@tonic-gate {
19860Sstevel@tonic-gate uint_t ii, jj, nrecs;
19870Sstevel@tonic-gate uint_t npaths = 0;
19880Sstevel@tonic-gate size_t length;
19890Sstevel@tonic-gate ib_gid_t sgid;
19900Sstevel@tonic-gate ibdm_pkey_tbl_t *pkey_tbl;
19910Sstevel@tonic-gate sa_path_record_t *result;
19920Sstevel@tonic-gate sa_path_record_t *precp;
19930Sstevel@tonic-gate ibdm_dp_gidinfo_t *gid_info;
19940Sstevel@tonic-gate
19950Sstevel@tonic-gate ASSERT(MUTEX_HELD(&ibdm.ibdm_hl_mutex));
19960Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tget_reachable_ports: portinfo %p", portinfo);
19970Sstevel@tonic-gate
19980Sstevel@tonic-gate sgid.gid_prefix = portinfo->pa_sn_prefix;
19990Sstevel@tonic-gate sgid.gid_guid = portinfo->pa_port_guid;
20000Sstevel@tonic-gate
20010Sstevel@tonic-gate /* get reversible paths */
20020Sstevel@tonic-gate if (portinfo->pa_sa_hdl && ibmf_saa_paths_from_gid(portinfo->pa_sa_hdl,
20030Sstevel@tonic-gate sgid, IBMF_SAA_PKEY_WC, B_TRUE, 0, &nrecs, &length, &result)
20040Sstevel@tonic-gate != IBMF_SUCCESS) {
20050Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm",
20060Sstevel@tonic-gate "\tget_reachable_ports: Getting path records failed");
20070Sstevel@tonic-gate return (0);
20080Sstevel@tonic-gate }
20090Sstevel@tonic-gate
20100Sstevel@tonic-gate for (ii = 0; ii < nrecs; ii++) {
20116262Seota sa_node_record_t *nrec;
20126262Seota size_t length;
20136262Seota
20140Sstevel@tonic-gate precp = &result[ii];
20150Sstevel@tonic-gate if ((gid_info = ibdm_check_dgid(precp->DGID.gid_guid,
20160Sstevel@tonic-gate precp->DGID.gid_prefix)) != NULL) {
20173826Shiremath IBTF_DPRINTF_L5("ibdm", "\tget_reachable_ports: "
20180Sstevel@tonic-gate "Already exists nrecs %d, ii %d", nrecs, ii);
20190Sstevel@tonic-gate ibdm_addto_glhcalist(gid_info, hca);
20200Sstevel@tonic-gate continue;
20210Sstevel@tonic-gate }
20220Sstevel@tonic-gate /*
20230Sstevel@tonic-gate * This is a new GID. Allocate a GID structure and
20240Sstevel@tonic-gate * initialize the structure
20250Sstevel@tonic-gate * gl_state is initialized to IBDM_GID_PROBE_NOT_DONE (0)
20260Sstevel@tonic-gate * by kmem_zalloc call
20270Sstevel@tonic-gate */
20280Sstevel@tonic-gate gid_info = kmem_zalloc(sizeof (ibdm_dp_gidinfo_t), KM_SLEEP);
20290Sstevel@tonic-gate mutex_init(&gid_info->gl_mutex, NULL, MUTEX_DEFAULT, NULL);
20306262Seota cv_init(&gid_info->gl_probe_cv, NULL, CV_DRIVER, NULL);
20310Sstevel@tonic-gate gid_info->gl_dgid_hi = precp->DGID.gid_prefix;
20320Sstevel@tonic-gate gid_info->gl_dgid_lo = precp->DGID.gid_guid;
20330Sstevel@tonic-gate gid_info->gl_sgid_hi = precp->SGID.gid_prefix;
20340Sstevel@tonic-gate gid_info->gl_sgid_lo = precp->SGID.gid_guid;
20350Sstevel@tonic-gate gid_info->gl_p_key = precp->P_Key;
20360Sstevel@tonic-gate gid_info->gl_sa_hdl = portinfo->pa_sa_hdl;
20370Sstevel@tonic-gate gid_info->gl_ibmf_hdl = portinfo->pa_ibmf_hdl;
20380Sstevel@tonic-gate gid_info->gl_slid = precp->SLID;
20390Sstevel@tonic-gate gid_info->gl_dlid = precp->DLID;
20401093Shiremath gid_info->gl_transactionID = (++ibdm.ibdm_transactionID)
20411093Shiremath << IBDM_GID_TRANSACTIONID_SHIFT;
20421093Shiremath gid_info->gl_min_transactionID = gid_info->gl_transactionID;
20431093Shiremath gid_info->gl_max_transactionID = (ibdm.ibdm_transactionID +1)
20441093Shiremath << IBDM_GID_TRANSACTIONID_SHIFT;
20456699Seota gid_info->gl_SL = precp->SL;
20466262Seota
20476262Seota /*
20486262Seota * get the node record with this guid if the destination
20496262Seota * device is a Cisco one.
20506262Seota */
20516262Seota if (ibdm_is_cisco(precp->DGID.gid_guid) &&
20526262Seota (gid_info->gl_nodeguid == 0 || gid_info->gl_devid == 0) &&
20536262Seota ibdm_get_node_record_by_port(portinfo->pa_sa_hdl,
20546262Seota precp->DGID.gid_guid, &nrec, &length) == IBDM_SUCCESS) {
20556262Seota gid_info->gl_nodeguid = nrec->NodeInfo.NodeGUID;
20566262Seota gid_info->gl_devid = nrec->NodeInfo.DeviceID;
20576262Seota kmem_free(nrec, length);
20586262Seota }
20596262Seota
20600Sstevel@tonic-gate ibdm_addto_glhcalist(gid_info, hca);
20610Sstevel@tonic-gate
20620Sstevel@tonic-gate ibdm_dump_path_info(precp);
20630Sstevel@tonic-gate
20640Sstevel@tonic-gate gid_info->gl_qp_hdl = NULL;
20651093Shiremath ASSERT(portinfo->pa_pkey_tbl != NULL &&
20661093Shiremath portinfo->pa_npkeys != 0);
20670Sstevel@tonic-gate
20680Sstevel@tonic-gate for (jj = 0; jj < portinfo->pa_npkeys; jj++) {
20690Sstevel@tonic-gate pkey_tbl = &portinfo->pa_pkey_tbl[jj];
20700Sstevel@tonic-gate if ((gid_info->gl_p_key == pkey_tbl->pt_pkey) &&
20710Sstevel@tonic-gate (pkey_tbl->pt_qp_hdl != NULL)) {
20720Sstevel@tonic-gate gid_info->gl_qp_hdl = pkey_tbl->pt_qp_hdl;
20730Sstevel@tonic-gate break;
20740Sstevel@tonic-gate }
20750Sstevel@tonic-gate }
20760Sstevel@tonic-gate
20771093Shiremath /*
20781093Shiremath * QP handle for GID not initialized. No matching Pkey
20791093Shiremath * was found!! ibdm should *not* hit this case. Flag an
20801093Shiremath * error and drop the GID if ibdm does encounter this.
20811093Shiremath */
20820Sstevel@tonic-gate if (gid_info->gl_qp_hdl == NULL) {
20831093Shiremath IBTF_DPRINTF_L2(ibdm_string,
20841093Shiremath "\tget_reachable_ports: No matching Pkey");
20851093Shiremath ibdm_delete_gidinfo(gid_info);
20860Sstevel@tonic-gate continue;
20870Sstevel@tonic-gate }
20880Sstevel@tonic-gate if (ibdm.ibdm_dp_gidlist_head == NULL) {
20890Sstevel@tonic-gate ibdm.ibdm_dp_gidlist_head = gid_info;
20900Sstevel@tonic-gate ibdm.ibdm_dp_gidlist_tail = gid_info;
20910Sstevel@tonic-gate } else {
20920Sstevel@tonic-gate ibdm.ibdm_dp_gidlist_tail->gl_next = gid_info;
20930Sstevel@tonic-gate gid_info->gl_prev = ibdm.ibdm_dp_gidlist_tail;
20940Sstevel@tonic-gate ibdm.ibdm_dp_gidlist_tail = gid_info;
20950Sstevel@tonic-gate }
20960Sstevel@tonic-gate npaths++;
20970Sstevel@tonic-gate }
20980Sstevel@tonic-gate kmem_free(result, length);
20990Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tget_reachable_ports: npaths = %d", npaths);
21000Sstevel@tonic-gate return (npaths);
21010Sstevel@tonic-gate }
21020Sstevel@tonic-gate
21030Sstevel@tonic-gate
21040Sstevel@tonic-gate /*
21050Sstevel@tonic-gate * ibdm_check_dgid()
21060Sstevel@tonic-gate * Look in the global list to check whether we know this DGID already
21070Sstevel@tonic-gate * Return IBDM_GID_PRESENT/IBDM_GID_NOT_PRESENT
21080Sstevel@tonic-gate */
21090Sstevel@tonic-gate static ibdm_dp_gidinfo_t *
ibdm_check_dgid(ib_guid_t guid,ib_sn_prefix_t prefix)21100Sstevel@tonic-gate ibdm_check_dgid(ib_guid_t guid, ib_sn_prefix_t prefix)
21110Sstevel@tonic-gate {
21120Sstevel@tonic-gate ibdm_dp_gidinfo_t *gid_list;
21130Sstevel@tonic-gate
21140Sstevel@tonic-gate for (gid_list = ibdm.ibdm_dp_gidlist_head; gid_list;
21150Sstevel@tonic-gate gid_list = gid_list->gl_next) {
21160Sstevel@tonic-gate if ((guid == gid_list->gl_dgid_lo) &&
21170Sstevel@tonic-gate (prefix == gid_list->gl_dgid_hi)) {
21180Sstevel@tonic-gate break;
21190Sstevel@tonic-gate }
21200Sstevel@tonic-gate }
21210Sstevel@tonic-gate return (gid_list);
21220Sstevel@tonic-gate }
21230Sstevel@tonic-gate
21240Sstevel@tonic-gate
21250Sstevel@tonic-gate /*
21260Sstevel@tonic-gate * ibdm_find_gid()
21270Sstevel@tonic-gate * Look in the global list to find a GID entry with matching
21280Sstevel@tonic-gate * port & node GUID.
21290Sstevel@tonic-gate * Return pointer to gidinfo if found, else return NULL
21300Sstevel@tonic-gate */
21310Sstevel@tonic-gate static ibdm_dp_gidinfo_t *
ibdm_find_gid(ib_guid_t nodeguid,ib_guid_t portguid)21320Sstevel@tonic-gate ibdm_find_gid(ib_guid_t nodeguid, ib_guid_t portguid)
21330Sstevel@tonic-gate {
21340Sstevel@tonic-gate ibdm_dp_gidinfo_t *gid_list;
21350Sstevel@tonic-gate
21360Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "ibdm_find_gid(%llx, %llx)\n",
21370Sstevel@tonic-gate nodeguid, portguid);
21380Sstevel@tonic-gate
21390Sstevel@tonic-gate for (gid_list = ibdm.ibdm_dp_gidlist_head; gid_list;
21400Sstevel@tonic-gate gid_list = gid_list->gl_next) {
21410Sstevel@tonic-gate if ((portguid == gid_list->gl_portguid) &&
21420Sstevel@tonic-gate (nodeguid == gid_list->gl_nodeguid)) {
21430Sstevel@tonic-gate break;
21440Sstevel@tonic-gate }
21450Sstevel@tonic-gate }
21460Sstevel@tonic-gate
21470Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "ibdm_find_gid : returned %p\n",
21480Sstevel@tonic-gate gid_list);
21490Sstevel@tonic-gate return (gid_list);
21500Sstevel@tonic-gate }
21510Sstevel@tonic-gate
21520Sstevel@tonic-gate
21530Sstevel@tonic-gate /*
21546262Seota * ibdm_set_classportinfo()
21556262Seota * ibdm_set_classportinfo() is a function to activate a Cisco FC GW
21566262Seota * by sending the setClassPortInfo request with the trapLID, trapGID
21576262Seota * and etc. to the gateway since the gateway doesn't provide the IO
21586262Seota * Unit Information othewise. This behavior is the Cisco specific one,
21596262Seota * and this function is called to a Cisco FC GW only.
21606262Seota * Returns IBDM_SUCCESS/IBDM_FAILURE
21616262Seota */
21626262Seota static int
ibdm_set_classportinfo(ibdm_dp_gidinfo_t * gid_info)21636262Seota ibdm_set_classportinfo(ibdm_dp_gidinfo_t *gid_info)
21646262Seota {
21656262Seota ibmf_msg_t *msg;
21666262Seota ib_mad_hdr_t *hdr;
21676262Seota ibdm_timeout_cb_args_t *cb_args;
21686262Seota void *data;
21696262Seota ib_mad_classportinfo_t *cpi;
21706262Seota
21716262Seota IBTF_DPRINTF_L4("ibdm",
21726262Seota "\tset_classportinfo: gid info 0x%p", gid_info);
21736262Seota
21746262Seota /*
21756262Seota * Send command to set classportinfo attribute. Allocate a IBMF
21766262Seota * packet and initialize the packet.
21776262Seota */
21786262Seota if (ibmf_alloc_msg(gid_info->gl_ibmf_hdl, IBMF_ALLOC_SLEEP,
21796262Seota &msg) != IBMF_SUCCESS) {
21806262Seota IBTF_DPRINTF_L4("ibdm", "\tset_classportinfo: pkt alloc fail");
21816262Seota return (IBDM_FAILURE);
21826262Seota }
21836262Seota
21846699Seota _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*msg))
21856262Seota ibdm_alloc_send_buffers(msg);
21866699Seota _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*msg))
21876262Seota
21886262Seota msg->im_local_addr.ia_local_lid = gid_info->gl_slid;
21896262Seota msg->im_local_addr.ia_remote_lid = gid_info->gl_dlid;
21906262Seota msg->im_local_addr.ia_remote_qno = 1;
21916262Seota msg->im_local_addr.ia_p_key = gid_info->gl_p_key;
21926262Seota msg->im_local_addr.ia_q_key = IB_GSI_QKEY;
21936699Seota msg->im_local_addr.ia_service_level = gid_info->gl_SL;
21946262Seota
21956262Seota hdr = IBDM_OUT_IBMFMSG_MADHDR(msg);
21966262Seota hdr->BaseVersion = MAD_CLASS_BASE_VERS_1;
21976262Seota hdr->MgmtClass = MAD_MGMT_CLASS_DEV_MGT;
21986262Seota hdr->ClassVersion = IB_DM_CLASS_VERSION_1;
21996262Seota hdr->R_Method = IB_DM_DEVMGT_METHOD_SET;
22006262Seota hdr->Status = 0;
22016262Seota hdr->TransactionID = h2b64(gid_info->gl_transactionID);
22026262Seota hdr->AttributeID = h2b16(IB_DM_ATTR_CLASSPORTINFO);
22036262Seota hdr->AttributeModifier = 0;
22046262Seota
22056262Seota data = msg->im_msgbufs_send.im_bufs_cl_data;
22066262Seota cpi = (ib_mad_classportinfo_t *)data;
22076262Seota
22086262Seota /*
22096262Seota * Set the classportinfo values to activate this Cisco FC GW.
22106262Seota */
22116262Seota cpi->TrapGID_hi = h2b64(gid_info->gl_sgid_hi);
22126262Seota cpi->TrapGID_lo = h2b64(gid_info->gl_sgid_lo);
22136262Seota cpi->TrapLID = h2b16(gid_info->gl_slid);
22146699Seota cpi->TrapSL = gid_info->gl_SL;
22156262Seota cpi->TrapP_Key = h2b16(gid_info->gl_p_key);
22166262Seota cpi->TrapQP = h2b32((((ibmf_alt_qp_t *)gid_info->gl_qp_hdl)->isq_qpn));
22176262Seota cpi->TrapQ_Key = h2b32((((ibmf_alt_qp_t *)
22186262Seota gid_info->gl_qp_hdl)->isq_qkey));
22196262Seota
22206262Seota cb_args = &gid_info->gl_cpi_cb_args;
22216262Seota cb_args->cb_gid_info = gid_info;
22226262Seota cb_args->cb_retry_count = ibdm_dft_retry_cnt;
22236262Seota cb_args->cb_req_type = IBDM_REQ_TYPE_CLASSPORTINFO;
22246262Seota
22256699Seota mutex_enter(&gid_info->gl_mutex);
22266262Seota gid_info->gl_timeout_id = timeout(ibdm_pkt_timeout_hdlr,
22276262Seota cb_args, IBDM_TIMEOUT_VALUE(ibdm_dft_timeout));
22286699Seota mutex_exit(&gid_info->gl_mutex);
22296262Seota
22306262Seota IBTF_DPRINTF_L5("ibdm", "\tset_classportinfo: "
22316262Seota "timeout id %x", gid_info->gl_timeout_id);
22326262Seota
22336262Seota if (ibmf_msg_transport(gid_info->gl_ibmf_hdl, gid_info->gl_qp_hdl,
22346262Seota msg, NULL, ibdm_ibmf_send_cb, cb_args, 0) != IBMF_SUCCESS) {
22356262Seota IBTF_DPRINTF_L2("ibdm",
22366262Seota "\tset_classportinfo: ibmf send failed");
22376262Seota ibdm_ibmf_send_cb(gid_info->gl_ibmf_hdl, msg, cb_args);
22386262Seota }
22396262Seota
22406262Seota return (IBDM_SUCCESS);
22416262Seota }
22426262Seota
22436262Seota
22446262Seota /*
22450Sstevel@tonic-gate * ibdm_send_classportinfo()
22460Sstevel@tonic-gate * Send classportinfo request. When the request is completed
22470Sstevel@tonic-gate * IBMF calls ibdm_classportinfo_cb routine to inform about
22480Sstevel@tonic-gate * the completion.
22490Sstevel@tonic-gate * Returns IBDM_SUCCESS/IBDM_FAILURE
22500Sstevel@tonic-gate */
22510Sstevel@tonic-gate static int
ibdm_send_classportinfo(ibdm_dp_gidinfo_t * gid_info)22520Sstevel@tonic-gate ibdm_send_classportinfo(ibdm_dp_gidinfo_t *gid_info)
22530Sstevel@tonic-gate {
22540Sstevel@tonic-gate ibmf_msg_t *msg;
22550Sstevel@tonic-gate ib_mad_hdr_t *hdr;
22560Sstevel@tonic-gate ibdm_timeout_cb_args_t *cb_args;
22570Sstevel@tonic-gate
22580Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm",
22590Sstevel@tonic-gate "\tsend_classportinfo: gid info 0x%p", gid_info);
22600Sstevel@tonic-gate
22610Sstevel@tonic-gate /*
22620Sstevel@tonic-gate * Send command to get classportinfo attribute. Allocate a IBMF
22630Sstevel@tonic-gate * packet and initialize the packet.
22640Sstevel@tonic-gate */
22650Sstevel@tonic-gate if (ibmf_alloc_msg(gid_info->gl_ibmf_hdl, IBMF_ALLOC_SLEEP,
22660Sstevel@tonic-gate &msg) != IBMF_SUCCESS) {
22670Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tsend_classportinfo: pkt alloc fail");
22680Sstevel@tonic-gate return (IBDM_FAILURE);
22690Sstevel@tonic-gate }
22700Sstevel@tonic-gate
22716699Seota _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*msg))
22720Sstevel@tonic-gate ibdm_alloc_send_buffers(msg);
22736699Seota _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*msg))
22740Sstevel@tonic-gate
22750Sstevel@tonic-gate msg->im_local_addr.ia_local_lid = gid_info->gl_slid;
22760Sstevel@tonic-gate msg->im_local_addr.ia_remote_lid = gid_info->gl_dlid;
22770Sstevel@tonic-gate msg->im_local_addr.ia_remote_qno = 1;
22780Sstevel@tonic-gate msg->im_local_addr.ia_p_key = gid_info->gl_p_key;
22790Sstevel@tonic-gate msg->im_local_addr.ia_q_key = IB_GSI_QKEY;
22806699Seota msg->im_local_addr.ia_service_level = gid_info->gl_SL;
22810Sstevel@tonic-gate
22820Sstevel@tonic-gate hdr = IBDM_OUT_IBMFMSG_MADHDR(msg);
22830Sstevel@tonic-gate hdr->BaseVersion = MAD_CLASS_BASE_VERS_1;
22840Sstevel@tonic-gate hdr->MgmtClass = MAD_MGMT_CLASS_DEV_MGT;
22850Sstevel@tonic-gate hdr->ClassVersion = IB_DM_CLASS_VERSION_1;
22860Sstevel@tonic-gate hdr->R_Method = IB_DM_DEVMGT_METHOD_GET;
22870Sstevel@tonic-gate hdr->Status = 0;
22880Sstevel@tonic-gate hdr->TransactionID = h2b64(gid_info->gl_transactionID);
22890Sstevel@tonic-gate hdr->AttributeID = h2b16(IB_DM_ATTR_CLASSPORTINFO);
22900Sstevel@tonic-gate hdr->AttributeModifier = 0;
22910Sstevel@tonic-gate
22920Sstevel@tonic-gate cb_args = &gid_info->gl_cpi_cb_args;
22930Sstevel@tonic-gate cb_args->cb_gid_info = gid_info;
22940Sstevel@tonic-gate cb_args->cb_retry_count = ibdm_dft_retry_cnt;
22950Sstevel@tonic-gate cb_args->cb_req_type = IBDM_REQ_TYPE_CLASSPORTINFO;
22960Sstevel@tonic-gate
22976699Seota mutex_enter(&gid_info->gl_mutex);
22980Sstevel@tonic-gate gid_info->gl_timeout_id = timeout(ibdm_pkt_timeout_hdlr,
22990Sstevel@tonic-gate cb_args, IBDM_TIMEOUT_VALUE(ibdm_dft_timeout));
23006699Seota mutex_exit(&gid_info->gl_mutex);
23010Sstevel@tonic-gate
23020Sstevel@tonic-gate IBTF_DPRINTF_L5("ibdm", "\tsend_classportinfo: "
23030Sstevel@tonic-gate "timeout id %x", gid_info->gl_timeout_id);
23040Sstevel@tonic-gate
23050Sstevel@tonic-gate if (ibmf_msg_transport(gid_info->gl_ibmf_hdl, gid_info->gl_qp_hdl,
23060Sstevel@tonic-gate msg, NULL, ibdm_ibmf_send_cb, cb_args, 0) != IBMF_SUCCESS) {
23070Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm",
23080Sstevel@tonic-gate "\tsend_classportinfo: ibmf send failed");
23090Sstevel@tonic-gate ibdm_ibmf_send_cb(gid_info->gl_ibmf_hdl, msg, cb_args);
23100Sstevel@tonic-gate }
23110Sstevel@tonic-gate
23120Sstevel@tonic-gate return (IBDM_SUCCESS);
23130Sstevel@tonic-gate }
23140Sstevel@tonic-gate
23150Sstevel@tonic-gate
23160Sstevel@tonic-gate /*
23176262Seota * ibdm_handle_setclassportinfo()
23186262Seota * Invoked by the IBMF when setClassPortInfo request is completed.
23196262Seota */
23206262Seota static void
ibdm_handle_setclassportinfo(ibmf_handle_t ibmf_hdl,ibmf_msg_t * msg,ibdm_dp_gidinfo_t * gid_info,int * flag)23216262Seota ibdm_handle_setclassportinfo(ibmf_handle_t ibmf_hdl,
23226262Seota ibmf_msg_t *msg, ibdm_dp_gidinfo_t *gid_info, int *flag)
23236262Seota {
23246262Seota void *data;
23256262Seota timeout_id_t timeout_id;
23266262Seota ib_mad_classportinfo_t *cpi;
23276262Seota
23286262Seota IBTF_DPRINTF_L4("ibdm", "\thandle_setclassportinfo:ibmf hdl "
23296262Seota "%p msg %p gid info %p", ibmf_hdl, msg, gid_info);
23306262Seota
23316262Seota if (IBDM_IN_IBMFMSG_ATTR(msg) != IB_DM_ATTR_CLASSPORTINFO) {
23326262Seota IBTF_DPRINTF_L4("ibdm", "\thandle_setclassportinfo: "
23336262Seota "Not a ClassPortInfo resp");
23346262Seota *flag |= IBDM_IBMF_PKT_UNEXP_RESP;
23356262Seota return;
23366262Seota }
23376262Seota
23386262Seota /*
23396262Seota * Verify whether timeout handler is created/active.
23406262Seota * If created/ active, cancel the timeout handler
23416262Seota */
23426262Seota mutex_enter(&gid_info->gl_mutex);
23436262Seota if (gid_info->gl_state != IBDM_SET_CLASSPORTINFO) {
23446262Seota IBTF_DPRINTF_L2("ibdm", "\thandle_setclassportinfo:DUP resp");
23456262Seota *flag |= IBDM_IBMF_PKT_DUP_RESP;
23466262Seota mutex_exit(&gid_info->gl_mutex);
23476262Seota return;
23486262Seota }
23496262Seota ibdm_bump_transactionID(gid_info);
23506262Seota
23516262Seota gid_info->gl_iou_cb_args.cb_req_type = 0;
23526262Seota if (gid_info->gl_timeout_id) {
23536262Seota timeout_id = gid_info->gl_timeout_id;
23546262Seota mutex_exit(&gid_info->gl_mutex);
23556262Seota IBTF_DPRINTF_L5("ibdm", "handle_setlassportinfo: "
23566262Seota "gl_timeout_id = 0x%x", timeout_id);
23576262Seota if (untimeout(timeout_id) == -1) {
23586262Seota IBTF_DPRINTF_L2("ibdm", "handle_setclassportinfo: "
23596262Seota "untimeout gl_timeout_id failed");
23606262Seota }
23616262Seota mutex_enter(&gid_info->gl_mutex);
23626262Seota gid_info->gl_timeout_id = 0;
23636262Seota }
23646262Seota mutex_exit(&gid_info->gl_mutex);
23656262Seota
23666262Seota data = msg->im_msgbufs_recv.im_bufs_cl_data;
23676262Seota cpi = (ib_mad_classportinfo_t *)data;
23686262Seota
23696262Seota ibdm_dump_classportinfo(cpi);
23706262Seota }
23716262Seota
23726262Seota
23736262Seota /*
23740Sstevel@tonic-gate * ibdm_handle_classportinfo()
23750Sstevel@tonic-gate * Invoked by the IBMF when the classportinfo request is completed.
23760Sstevel@tonic-gate */
23770Sstevel@tonic-gate static void
ibdm_handle_classportinfo(ibmf_handle_t ibmf_hdl,ibmf_msg_t * msg,ibdm_dp_gidinfo_t * gid_info,int * flag)23780Sstevel@tonic-gate ibdm_handle_classportinfo(ibmf_handle_t ibmf_hdl,
23790Sstevel@tonic-gate ibmf_msg_t *msg, ibdm_dp_gidinfo_t *gid_info, int *flag)
23800Sstevel@tonic-gate {
23810Sstevel@tonic-gate void *data;
23820Sstevel@tonic-gate timeout_id_t timeout_id;
23830Sstevel@tonic-gate ib_mad_hdr_t *hdr;
23846262Seota ib_mad_classportinfo_t *cpi;
23850Sstevel@tonic-gate
23860Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\thandle_classportinfo:ibmf hdl "
23870Sstevel@tonic-gate "%p msg %p gid info %p", ibmf_hdl, msg, gid_info);
23880Sstevel@tonic-gate
23890Sstevel@tonic-gate if (IBDM_IN_IBMFMSG_ATTR(msg) != IB_DM_ATTR_CLASSPORTINFO) {
23900Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\thandle_classportinfo: "
23910Sstevel@tonic-gate "Not a ClassPortInfo resp");
23920Sstevel@tonic-gate *flag |= IBDM_IBMF_PKT_UNEXP_RESP;
23930Sstevel@tonic-gate return;
23940Sstevel@tonic-gate }
23950Sstevel@tonic-gate
23960Sstevel@tonic-gate /*
23970Sstevel@tonic-gate * Verify whether timeout handler is created/active.
23980Sstevel@tonic-gate * If created/ active, cancel the timeout handler
23990Sstevel@tonic-gate */
24000Sstevel@tonic-gate mutex_enter(&gid_info->gl_mutex);
24011093Shiremath ibdm_bump_transactionID(gid_info);
24020Sstevel@tonic-gate if (gid_info->gl_state != IBDM_GET_CLASSPORTINFO) {
24030Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "\thandle_classportinfo:DUP resp");
24040Sstevel@tonic-gate *flag |= IBDM_IBMF_PKT_DUP_RESP;
24050Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
24060Sstevel@tonic-gate return;
24070Sstevel@tonic-gate }
24080Sstevel@tonic-gate gid_info->gl_iou_cb_args.cb_req_type = 0;
24090Sstevel@tonic-gate if (gid_info->gl_timeout_id) {
24100Sstevel@tonic-gate timeout_id = gid_info->gl_timeout_id;
24110Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
24120Sstevel@tonic-gate IBTF_DPRINTF_L5("ibdm", "handle_ioclassportinfo: "
24130Sstevel@tonic-gate "gl_timeout_id = 0x%x", timeout_id);
24140Sstevel@tonic-gate if (untimeout(timeout_id) == -1) {
24150Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "handle_classportinfo: "
24160Sstevel@tonic-gate "untimeout gl_timeout_id failed");
24170Sstevel@tonic-gate }
24180Sstevel@tonic-gate mutex_enter(&gid_info->gl_mutex);
24190Sstevel@tonic-gate gid_info->gl_timeout_id = 0;
24200Sstevel@tonic-gate }
24210Sstevel@tonic-gate gid_info->gl_state = IBDM_GET_IOUNITINFO;
24220Sstevel@tonic-gate gid_info->gl_pending_cmds++;
24230Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
24240Sstevel@tonic-gate
24250Sstevel@tonic-gate data = msg->im_msgbufs_recv.im_bufs_cl_data;
24266262Seota cpi = (ib_mad_classportinfo_t *)data;
24270Sstevel@tonic-gate
24280Sstevel@tonic-gate /*
24290Sstevel@tonic-gate * Cache the "RespTimeValue" and redirection information in the
24300Sstevel@tonic-gate * global gid list data structure. This cached information will
24310Sstevel@tonic-gate * be used to send any further requests to the GID.
24320Sstevel@tonic-gate */
24330Sstevel@tonic-gate gid_info->gl_resp_timeout =
24346262Seota (b2h32(cpi->RespTimeValue) & 0x1F);
24350Sstevel@tonic-gate
24360Sstevel@tonic-gate gid_info->gl_redirected = ((IBDM_IN_IBMFMSG_STATUS(msg) &
24370Sstevel@tonic-gate MAD_STATUS_REDIRECT_REQUIRED) ? B_TRUE: B_FALSE);
24380Sstevel@tonic-gate gid_info->gl_redirect_dlid = b2h16(cpi->RedirectLID);
24390Sstevel@tonic-gate gid_info->gl_redirect_QP = (b2h32(cpi->RedirectQP) & 0xffffff);
24400Sstevel@tonic-gate gid_info->gl_redirect_pkey = b2h16(cpi->RedirectP_Key);
24410Sstevel@tonic-gate gid_info->gl_redirect_qkey = b2h32(cpi->RedirectQ_Key);
24420Sstevel@tonic-gate gid_info->gl_redirectGID_hi = b2h64(cpi->RedirectGID_hi);
24430Sstevel@tonic-gate gid_info->gl_redirectGID_lo = b2h64(cpi->RedirectGID_lo);
24446699Seota gid_info->gl_redirectSL = cpi->RedirectSL;
24450Sstevel@tonic-gate
24460Sstevel@tonic-gate ibdm_dump_classportinfo(cpi);
24470Sstevel@tonic-gate
24480Sstevel@tonic-gate /*
24490Sstevel@tonic-gate * Send IOUnitInfo request
24500Sstevel@tonic-gate * Reuse previously allocated IBMF packet for sending ClassPortInfo
24510Sstevel@tonic-gate * Check whether DM agent on the remote node requested redirection
24520Sstevel@tonic-gate * If so, send the request to the redirect DGID/DLID/PKEY/QP.
24530Sstevel@tonic-gate */
24546699Seota _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*msg))
24550Sstevel@tonic-gate ibdm_alloc_send_buffers(msg);
24566699Seota _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*msg))
24570Sstevel@tonic-gate msg->im_local_addr.ia_local_lid = gid_info->gl_slid;
24580Sstevel@tonic-gate msg->im_local_addr.ia_remote_lid = gid_info->gl_dlid;
24590Sstevel@tonic-gate
24600Sstevel@tonic-gate if (gid_info->gl_redirected == B_TRUE) {
24610Sstevel@tonic-gate if (gid_info->gl_redirect_dlid != 0) {
24620Sstevel@tonic-gate msg->im_local_addr.ia_remote_lid =
24636262Seota gid_info->gl_redirect_dlid;
24640Sstevel@tonic-gate }
24650Sstevel@tonic-gate msg->im_local_addr.ia_remote_qno = gid_info->gl_redirect_QP;
24660Sstevel@tonic-gate msg->im_local_addr.ia_p_key = gid_info->gl_redirect_pkey;
24670Sstevel@tonic-gate msg->im_local_addr.ia_q_key = gid_info->gl_redirect_qkey;
24686699Seota msg->im_local_addr.ia_service_level = gid_info->gl_redirectSL;
24690Sstevel@tonic-gate } else {
24700Sstevel@tonic-gate msg->im_local_addr.ia_remote_qno = 1;
24710Sstevel@tonic-gate msg->im_local_addr.ia_p_key = gid_info->gl_p_key;
24720Sstevel@tonic-gate msg->im_local_addr.ia_q_key = IB_GSI_QKEY;
24736699Seota msg->im_local_addr.ia_service_level = gid_info->gl_SL;
24740Sstevel@tonic-gate }
24750Sstevel@tonic-gate
24760Sstevel@tonic-gate hdr = IBDM_OUT_IBMFMSG_MADHDR(msg);
24770Sstevel@tonic-gate hdr->BaseVersion = MAD_CLASS_BASE_VERS_1;
24780Sstevel@tonic-gate hdr->MgmtClass = MAD_MGMT_CLASS_DEV_MGT;
24790Sstevel@tonic-gate hdr->ClassVersion = IB_DM_CLASS_VERSION_1;
24800Sstevel@tonic-gate hdr->R_Method = IB_DM_DEVMGT_METHOD_GET;
24810Sstevel@tonic-gate hdr->Status = 0;
24820Sstevel@tonic-gate hdr->TransactionID = h2b64(gid_info->gl_transactionID);
24830Sstevel@tonic-gate hdr->AttributeID = h2b16(IB_DM_ATTR_IO_UNITINFO);
24840Sstevel@tonic-gate hdr->AttributeModifier = 0;
24850Sstevel@tonic-gate
24860Sstevel@tonic-gate gid_info->gl_iou_cb_args.cb_req_type = IBDM_REQ_TYPE_IOUINFO;
24870Sstevel@tonic-gate gid_info->gl_iou_cb_args.cb_gid_info = gid_info;
24880Sstevel@tonic-gate gid_info->gl_iou_cb_args.cb_retry_count = ibdm_dft_retry_cnt;
24890Sstevel@tonic-gate
24906699Seota mutex_enter(&gid_info->gl_mutex);
24910Sstevel@tonic-gate gid_info->gl_timeout_id = timeout(ibdm_pkt_timeout_hdlr,
24920Sstevel@tonic-gate &gid_info->gl_iou_cb_args, IBDM_TIMEOUT_VALUE(ibdm_dft_timeout));
24936699Seota mutex_exit(&gid_info->gl_mutex);
24940Sstevel@tonic-gate
24950Sstevel@tonic-gate IBTF_DPRINTF_L5("ibdm", "handle_classportinfo:"
24960Sstevel@tonic-gate "timeout %x", gid_info->gl_timeout_id);
24970Sstevel@tonic-gate
24980Sstevel@tonic-gate if (ibmf_msg_transport(ibmf_hdl, gid_info->gl_qp_hdl, msg, NULL,
24990Sstevel@tonic-gate ibdm_ibmf_send_cb, &gid_info->gl_iou_cb_args, 0) != IBMF_SUCCESS) {
25000Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm",
25010Sstevel@tonic-gate "\thandle_classportinfo: msg transport failed");
25020Sstevel@tonic-gate ibdm_ibmf_send_cb(ibmf_hdl, msg, &gid_info->gl_iou_cb_args);
25030Sstevel@tonic-gate }
25040Sstevel@tonic-gate (*flag) |= IBDM_IBMF_PKT_REUSED;
25050Sstevel@tonic-gate }
25060Sstevel@tonic-gate
25070Sstevel@tonic-gate
25080Sstevel@tonic-gate /*
25090Sstevel@tonic-gate * ibdm_send_iounitinfo:
25100Sstevel@tonic-gate * Sends a DM request to get IOU unitinfo.
25110Sstevel@tonic-gate */
25120Sstevel@tonic-gate static int
ibdm_send_iounitinfo(ibdm_dp_gidinfo_t * gid_info)25130Sstevel@tonic-gate ibdm_send_iounitinfo(ibdm_dp_gidinfo_t *gid_info)
25140Sstevel@tonic-gate {
25150Sstevel@tonic-gate ibmf_msg_t *msg;
25160Sstevel@tonic-gate ib_mad_hdr_t *hdr;
25170Sstevel@tonic-gate
25180Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tsend_iounitinfo: gid info 0x%p", gid_info);
25190Sstevel@tonic-gate
25200Sstevel@tonic-gate /*
25210Sstevel@tonic-gate * Send command to get iounitinfo attribute. Allocate a IBMF
25220Sstevel@tonic-gate * packet and initialize the packet.
25230Sstevel@tonic-gate */
25240Sstevel@tonic-gate if (ibmf_alloc_msg(gid_info->gl_ibmf_hdl, IBMF_ALLOC_SLEEP, &msg) !=
25250Sstevel@tonic-gate IBMF_SUCCESS) {
25260Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tsend_iounitinfo: pkt alloc fail");
25270Sstevel@tonic-gate return (IBDM_FAILURE);
25280Sstevel@tonic-gate }
25290Sstevel@tonic-gate
25301093Shiremath mutex_enter(&gid_info->gl_mutex);
25311093Shiremath ibdm_bump_transactionID(gid_info);
25321093Shiremath mutex_exit(&gid_info->gl_mutex);
25331093Shiremath
25341093Shiremath
25356699Seota _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*msg))
25360Sstevel@tonic-gate ibdm_alloc_send_buffers(msg);
25376699Seota _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*msg))
25380Sstevel@tonic-gate msg->im_local_addr.ia_local_lid = gid_info->gl_slid;
25390Sstevel@tonic-gate msg->im_local_addr.ia_remote_lid = gid_info->gl_dlid;
25400Sstevel@tonic-gate msg->im_local_addr.ia_remote_qno = 1;
25410Sstevel@tonic-gate msg->im_local_addr.ia_p_key = gid_info->gl_p_key;
25420Sstevel@tonic-gate msg->im_local_addr.ia_q_key = IB_GSI_QKEY;
25436699Seota msg->im_local_addr.ia_service_level = gid_info->gl_SL;
25440Sstevel@tonic-gate
25450Sstevel@tonic-gate hdr = IBDM_OUT_IBMFMSG_MADHDR(msg);
25460Sstevel@tonic-gate hdr->BaseVersion = MAD_CLASS_BASE_VERS_1;
25470Sstevel@tonic-gate hdr->MgmtClass = MAD_MGMT_CLASS_DEV_MGT;
25480Sstevel@tonic-gate hdr->ClassVersion = IB_DM_CLASS_VERSION_1;
25490Sstevel@tonic-gate hdr->R_Method = IB_DM_DEVMGT_METHOD_GET;
25500Sstevel@tonic-gate hdr->Status = 0;
25510Sstevel@tonic-gate hdr->TransactionID = h2b64(gid_info->gl_transactionID);
25520Sstevel@tonic-gate hdr->AttributeID = h2b16(IB_DM_ATTR_IO_UNITINFO);
25530Sstevel@tonic-gate hdr->AttributeModifier = 0;
25540Sstevel@tonic-gate
25550Sstevel@tonic-gate gid_info->gl_iou_cb_args.cb_gid_info = gid_info;
25560Sstevel@tonic-gate gid_info->gl_iou_cb_args.cb_retry_count = ibdm_dft_retry_cnt;
25570Sstevel@tonic-gate gid_info->gl_iou_cb_args.cb_req_type = IBDM_REQ_TYPE_IOUINFO;
25580Sstevel@tonic-gate
25596699Seota mutex_enter(&gid_info->gl_mutex);
25600Sstevel@tonic-gate gid_info->gl_timeout_id = timeout(ibdm_pkt_timeout_hdlr,
25610Sstevel@tonic-gate &gid_info->gl_iou_cb_args, IBDM_TIMEOUT_VALUE(ibdm_dft_timeout));
25626699Seota mutex_exit(&gid_info->gl_mutex);
25630Sstevel@tonic-gate
25640Sstevel@tonic-gate IBTF_DPRINTF_L5("ibdm", "send_iouunitinfo:"
25650Sstevel@tonic-gate "timeout %x", gid_info->gl_timeout_id);
25660Sstevel@tonic-gate
25670Sstevel@tonic-gate if (ibmf_msg_transport(gid_info->gl_ibmf_hdl, gid_info->gl_qp_hdl, msg,
25680Sstevel@tonic-gate NULL, ibdm_ibmf_send_cb, &gid_info->gl_iou_cb_args, 0) !=
25690Sstevel@tonic-gate IBMF_SUCCESS) {
25700Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "\tsend_iounitinfo: ibmf send failed");
25710Sstevel@tonic-gate ibdm_ibmf_send_cb(gid_info->gl_ibmf_hdl,
25720Sstevel@tonic-gate msg, &gid_info->gl_iou_cb_args);
25730Sstevel@tonic-gate }
25740Sstevel@tonic-gate return (IBDM_SUCCESS);
25750Sstevel@tonic-gate }
25760Sstevel@tonic-gate
25770Sstevel@tonic-gate /*
25780Sstevel@tonic-gate * ibdm_handle_iounitinfo()
25790Sstevel@tonic-gate * Invoked by the IBMF when IO Unitinfo request is completed.
25800Sstevel@tonic-gate */
25810Sstevel@tonic-gate static void
ibdm_handle_iounitinfo(ibmf_handle_t ibmf_hdl,ibmf_msg_t * msg,ibdm_dp_gidinfo_t * gid_info,int * flag)25820Sstevel@tonic-gate ibdm_handle_iounitinfo(ibmf_handle_t ibmf_hdl,
25830Sstevel@tonic-gate ibmf_msg_t *msg, ibdm_dp_gidinfo_t *gid_info, int *flag)
25840Sstevel@tonic-gate {
25850Sstevel@tonic-gate int ii, first = B_TRUE;
25860Sstevel@tonic-gate int num_iocs;
25870Sstevel@tonic-gate size_t size;
25880Sstevel@tonic-gate uchar_t slot_info;
25890Sstevel@tonic-gate timeout_id_t timeout_id;
25900Sstevel@tonic-gate ib_mad_hdr_t *hdr;
25910Sstevel@tonic-gate ibdm_ioc_info_t *ioc_info;
25920Sstevel@tonic-gate ib_dm_io_unitinfo_t *iou_info;
25930Sstevel@tonic-gate ib_dm_io_unitinfo_t *giou_info;
25940Sstevel@tonic-gate ibdm_timeout_cb_args_t *cb_args;
25950Sstevel@tonic-gate
25960Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\thandle_iouintinfo:"
25970Sstevel@tonic-gate " ibmf hdl %p pkt %p gid info %p", ibmf_hdl, msg, gid_info);
25980Sstevel@tonic-gate
25990Sstevel@tonic-gate if (IBDM_IN_IBMFMSG_ATTR(msg) != IB_DM_ATTR_IO_UNITINFO) {
26000Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\thandle_iounitinfo: "
26010Sstevel@tonic-gate "Unexpected response");
26020Sstevel@tonic-gate (*flag) |= IBDM_IBMF_PKT_UNEXP_RESP;
26030Sstevel@tonic-gate return;
26040Sstevel@tonic-gate }
26050Sstevel@tonic-gate
26060Sstevel@tonic-gate mutex_enter(&gid_info->gl_mutex);
26070Sstevel@tonic-gate if (gid_info->gl_state != IBDM_GET_IOUNITINFO) {
26080Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm",
26090Sstevel@tonic-gate "\thandle_iounitinfo: DUP resp");
26100Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
26110Sstevel@tonic-gate (*flag) = IBDM_IBMF_PKT_DUP_RESP;
26120Sstevel@tonic-gate return;
26130Sstevel@tonic-gate }
26140Sstevel@tonic-gate gid_info->gl_iou_cb_args.cb_req_type = 0;
26150Sstevel@tonic-gate if (gid_info->gl_timeout_id) {
26160Sstevel@tonic-gate timeout_id = gid_info->gl_timeout_id;
26170Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
26180Sstevel@tonic-gate IBTF_DPRINTF_L5("ibdm", "handle_iounitinfo: "
26190Sstevel@tonic-gate "gl_timeout_id = 0x%x", timeout_id);
26200Sstevel@tonic-gate if (untimeout(timeout_id) == -1) {
26210Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "handle_iounitinfo: "
26220Sstevel@tonic-gate "untimeout gl_timeout_id failed");
26230Sstevel@tonic-gate }
26240Sstevel@tonic-gate mutex_enter(&gid_info->gl_mutex);
26250Sstevel@tonic-gate gid_info->gl_timeout_id = 0;
26260Sstevel@tonic-gate }
26270Sstevel@tonic-gate gid_info->gl_state = IBDM_GET_IOC_DETAILS;
26280Sstevel@tonic-gate
26290Sstevel@tonic-gate iou_info = IBDM_IN_IBMFMSG2IOU(msg);
26300Sstevel@tonic-gate ibdm_dump_iounitinfo(iou_info);
26310Sstevel@tonic-gate num_iocs = iou_info->iou_num_ctrl_slots;
26320Sstevel@tonic-gate /*
26330Sstevel@tonic-gate * check if number of IOCs reported is zero? if yes, return.
26340Sstevel@tonic-gate * when num_iocs are reported zero internal IOC database needs
26350Sstevel@tonic-gate * to be updated. To ensure that save the number of IOCs in
26360Sstevel@tonic-gate * the new field "gl_num_iocs". Use a new field instead of
26370Sstevel@tonic-gate * "giou_info->iou_num_ctrl_slots" as that would prevent
26380Sstevel@tonic-gate * an unnecessary kmem_alloc/kmem_free when num_iocs is 0.
26390Sstevel@tonic-gate */
26400Sstevel@tonic-gate if (num_iocs == 0 && gid_info->gl_num_iocs == 0) {
26410Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\thandle_iounitinfo: no IOC's");
26420Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
26430Sstevel@tonic-gate return;
26440Sstevel@tonic-gate }
26450Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\thandle_iounitinfo: num_iocs = %d", num_iocs);
26460Sstevel@tonic-gate
26470Sstevel@tonic-gate /*
26480Sstevel@tonic-gate * if there is an existing gl_iou (IOU has been probed before)
26490Sstevel@tonic-gate * check if the "iou_changeid" is same as saved entry in
26500Sstevel@tonic-gate * "giou_info->iou_changeid".
26510Sstevel@tonic-gate * (note: this logic can prevent IOC enumeration if a given
26520Sstevel@tonic-gate * vendor doesn't support setting iou_changeid field for its IOU)
26530Sstevel@tonic-gate *
26540Sstevel@tonic-gate * if there is an existing gl_iou and iou_changeid has changed :
26550Sstevel@tonic-gate * free up existing gl_iou info and its related structures.
26560Sstevel@tonic-gate * reallocate gl_iou info all over again.
26570Sstevel@tonic-gate * if we donot free this up; then this leads to memory leaks
26580Sstevel@tonic-gate */
26590Sstevel@tonic-gate if (gid_info->gl_iou) {
26600Sstevel@tonic-gate giou_info = &gid_info->gl_iou->iou_info;
26614024Spramodbg if (b2h16(iou_info->iou_changeid) ==
26624024Spramodbg giou_info->iou_changeid) {
26630Sstevel@tonic-gate IBTF_DPRINTF_L3("ibdm",
26640Sstevel@tonic-gate "\thandle_iounitinfo: no IOCs changed");
26650Sstevel@tonic-gate gid_info->gl_state = IBDM_GID_PROBING_COMPLETE;
26660Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
26670Sstevel@tonic-gate return;
26680Sstevel@tonic-gate }
26694024Spramodbg
26704024Spramodbg /*
26714024Spramodbg * Store the iou info as prev_iou to be used after
26724024Spramodbg * sweep is done.
26734024Spramodbg */
26744024Spramodbg ASSERT(gid_info->gl_prev_iou == NULL);
26754024Spramodbg IBTF_DPRINTF_L4(ibdm_string,
26764024Spramodbg "\thandle_iounitinfo: setting gl_prev_iou %p",
26774024Spramodbg gid_info->gl_prev_iou);
26784024Spramodbg gid_info->gl_prev_iou = gid_info->gl_iou;
26794024Spramodbg ibdm.ibdm_prev_iou = 1;
26804024Spramodbg gid_info->gl_iou = NULL;
26810Sstevel@tonic-gate }
26820Sstevel@tonic-gate
26830Sstevel@tonic-gate size = sizeof (ibdm_iou_info_t) + num_iocs * sizeof (ibdm_ioc_info_t);
26840Sstevel@tonic-gate gid_info->gl_iou = (ibdm_iou_info_t *)kmem_zalloc(size, KM_SLEEP);
26850Sstevel@tonic-gate giou_info = &gid_info->gl_iou->iou_info;
26860Sstevel@tonic-gate gid_info->gl_iou->iou_ioc_info = (ibdm_ioc_info_t *)
26876262Seota ((char *)gid_info->gl_iou + sizeof (ibdm_iou_info_t));
26880Sstevel@tonic-gate
26890Sstevel@tonic-gate giou_info->iou_num_ctrl_slots = gid_info->gl_num_iocs = num_iocs;
26900Sstevel@tonic-gate giou_info->iou_flag = iou_info->iou_flag;
26910Sstevel@tonic-gate bcopy(iou_info->iou_ctrl_list, giou_info->iou_ctrl_list, 128);
26920Sstevel@tonic-gate giou_info->iou_changeid = b2h16(iou_info->iou_changeid);
26936262Seota gid_info->gl_pending_cmds++; /* for diag code */
26940Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
26950Sstevel@tonic-gate
26960Sstevel@tonic-gate if (ibdm_get_diagcode(gid_info, 0) != IBDM_SUCCESS) {
26970Sstevel@tonic-gate mutex_enter(&gid_info->gl_mutex);
26980Sstevel@tonic-gate gid_info->gl_pending_cmds--;
26990Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
27000Sstevel@tonic-gate }
27010Sstevel@tonic-gate /*
27020Sstevel@tonic-gate * Parallelize getting IOC controller profiles from here.
27030Sstevel@tonic-gate * Allocate IBMF packets and send commands to get IOC profile for
27040Sstevel@tonic-gate * each IOC present on the IOU.
27050Sstevel@tonic-gate */
27060Sstevel@tonic-gate for (ii = 0; ii < num_iocs; ii++) {
27070Sstevel@tonic-gate /*
27080Sstevel@tonic-gate * Check whether IOC is present in the slot
27090Sstevel@tonic-gate * Series of nibbles (in the field iou_ctrl_list) represents
27100Sstevel@tonic-gate * a slot in the IOU.
27110Sstevel@tonic-gate * Byte format: 76543210
27120Sstevel@tonic-gate * Bits 0-3 of first byte represent Slot 2
27130Sstevel@tonic-gate * bits 4-7 of first byte represent slot 1,
27140Sstevel@tonic-gate * bits 0-3 of second byte represent slot 4 and so on
27150Sstevel@tonic-gate * Each 4-bit nibble has the following meaning
27160Sstevel@tonic-gate * 0x0 : IOC not installed
27170Sstevel@tonic-gate * 0x1 : IOC is present
27180Sstevel@tonic-gate * 0xf : Slot does not exist
27190Sstevel@tonic-gate * and all other values are reserved.
27200Sstevel@tonic-gate */
27210Sstevel@tonic-gate ioc_info = IBDM_GIDINFO2IOCINFO(gid_info, ii);
27220Sstevel@tonic-gate slot_info = giou_info->iou_ctrl_list[(ii/2)];
27230Sstevel@tonic-gate if ((ii % 2) == 0)
27240Sstevel@tonic-gate slot_info = (slot_info >> 4);
27250Sstevel@tonic-gate
27260Sstevel@tonic-gate if ((slot_info & 0xf) != 1) {
27270Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\thandle_iouintinfo: "
27280Sstevel@tonic-gate "No IOC is present in the slot = %d", ii);
27290Sstevel@tonic-gate ioc_info->ioc_state = IBDM_IOC_STATE_PROBE_FAILED;
27300Sstevel@tonic-gate continue;
27310Sstevel@tonic-gate }
27320Sstevel@tonic-gate
27331093Shiremath mutex_enter(&gid_info->gl_mutex);
27341093Shiremath ibdm_bump_transactionID(gid_info);
27351093Shiremath mutex_exit(&gid_info->gl_mutex);
27361093Shiremath
27370Sstevel@tonic-gate /*
27380Sstevel@tonic-gate * Re use the already allocated packet (for IOUnitinfo) to
27390Sstevel@tonic-gate * send the first IOC controller attribute. Allocate new
27400Sstevel@tonic-gate * IBMF packets for the rest of the IOC's
27410Sstevel@tonic-gate */
27420Sstevel@tonic-gate if (first != B_TRUE) {
27430Sstevel@tonic-gate msg = NULL;
27440Sstevel@tonic-gate if (ibmf_alloc_msg(ibmf_hdl, IBMF_ALLOC_SLEEP,
27450Sstevel@tonic-gate &msg) != IBMF_SUCCESS) {
27460Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\thandle_iouintinfo: "
27470Sstevel@tonic-gate "IBMF packet allocation failed");
27480Sstevel@tonic-gate continue;
27490Sstevel@tonic-gate }
27500Sstevel@tonic-gate
27510Sstevel@tonic-gate }
27520Sstevel@tonic-gate
27530Sstevel@tonic-gate /* allocate send buffers for all messages */
27546699Seota _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*msg))
27550Sstevel@tonic-gate ibdm_alloc_send_buffers(msg);
27566699Seota _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*msg))
27570Sstevel@tonic-gate
27580Sstevel@tonic-gate msg->im_local_addr.ia_local_lid = gid_info->gl_slid;
27590Sstevel@tonic-gate msg->im_local_addr.ia_remote_lid = gid_info->gl_dlid;
27600Sstevel@tonic-gate if (gid_info->gl_redirected == B_TRUE) {
27610Sstevel@tonic-gate if (gid_info->gl_redirect_dlid != 0) {
27620Sstevel@tonic-gate msg->im_local_addr.ia_remote_lid =
27636262Seota gid_info->gl_redirect_dlid;
27640Sstevel@tonic-gate }
27650Sstevel@tonic-gate msg->im_local_addr.ia_remote_qno =
27666262Seota gid_info->gl_redirect_QP;
27670Sstevel@tonic-gate msg->im_local_addr.ia_p_key =
27686262Seota gid_info->gl_redirect_pkey;
27690Sstevel@tonic-gate msg->im_local_addr.ia_q_key =
27706262Seota gid_info->gl_redirect_qkey;
27716699Seota msg->im_local_addr.ia_service_level =
27726699Seota gid_info->gl_redirectSL;
27730Sstevel@tonic-gate } else {
27740Sstevel@tonic-gate msg->im_local_addr.ia_remote_qno = 1;
27750Sstevel@tonic-gate msg->im_local_addr.ia_p_key = gid_info->gl_p_key;
27760Sstevel@tonic-gate msg->im_local_addr.ia_q_key = IB_GSI_QKEY;
27776699Seota msg->im_local_addr.ia_service_level = gid_info->gl_SL;
27780Sstevel@tonic-gate }
27790Sstevel@tonic-gate
27800Sstevel@tonic-gate hdr = IBDM_OUT_IBMFMSG_MADHDR(msg);
27810Sstevel@tonic-gate hdr->BaseVersion = MAD_CLASS_BASE_VERS_1;
27820Sstevel@tonic-gate hdr->MgmtClass = MAD_MGMT_CLASS_DEV_MGT;
27830Sstevel@tonic-gate hdr->ClassVersion = IB_DM_CLASS_VERSION_1;
27840Sstevel@tonic-gate hdr->R_Method = IB_DM_DEVMGT_METHOD_GET;
27850Sstevel@tonic-gate hdr->Status = 0;
27860Sstevel@tonic-gate hdr->TransactionID = h2b64(gid_info->gl_transactionID);
27870Sstevel@tonic-gate hdr->AttributeID = h2b16(IB_DM_ATTR_IOC_CTRL_PROFILE);
27880Sstevel@tonic-gate hdr->AttributeModifier = h2b32(ii + 1);
27890Sstevel@tonic-gate
27900Sstevel@tonic-gate ioc_info->ioc_state = IBDM_IOC_STATE_PROBE_INVALID;
27910Sstevel@tonic-gate cb_args = &ioc_info->ioc_cb_args;
27920Sstevel@tonic-gate cb_args->cb_gid_info = gid_info;
27930Sstevel@tonic-gate cb_args->cb_retry_count = ibdm_dft_retry_cnt;
27940Sstevel@tonic-gate cb_args->cb_req_type = IBDM_REQ_TYPE_IOCINFO;
27950Sstevel@tonic-gate cb_args->cb_ioc_num = ii;
27960Sstevel@tonic-gate
27976262Seota mutex_enter(&gid_info->gl_mutex);
27986262Seota gid_info->gl_pending_cmds++; /* for diag code */
27996262Seota
28000Sstevel@tonic-gate ioc_info->ioc_timeout_id = timeout(ibdm_pkt_timeout_hdlr,
28010Sstevel@tonic-gate cb_args, IBDM_TIMEOUT_VALUE(ibdm_dft_timeout));
28026699Seota mutex_exit(&gid_info->gl_mutex);
28030Sstevel@tonic-gate
28040Sstevel@tonic-gate IBTF_DPRINTF_L5("ibdm", "\thandle_iounitinfo:"
28050Sstevel@tonic-gate "timeout 0x%x, ioc_num %d", ioc_info->ioc_timeout_id, ii);
28060Sstevel@tonic-gate
28070Sstevel@tonic-gate if (ibmf_msg_transport(ibmf_hdl, gid_info->gl_qp_hdl, msg,
28080Sstevel@tonic-gate NULL, ibdm_ibmf_send_cb, cb_args, 0) != IBMF_SUCCESS) {
28090Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm",
28100Sstevel@tonic-gate "\thandle_iounitinfo: msg transport failed");
28110Sstevel@tonic-gate ibdm_ibmf_send_cb(ibmf_hdl, msg, cb_args);
28120Sstevel@tonic-gate }
28130Sstevel@tonic-gate (*flag) |= IBDM_IBMF_PKT_REUSED;
28140Sstevel@tonic-gate first = B_FALSE;
28150Sstevel@tonic-gate gid_info->gl_iou->iou_niocs_probe_in_progress++;
28160Sstevel@tonic-gate }
28170Sstevel@tonic-gate }
28180Sstevel@tonic-gate
28190Sstevel@tonic-gate
28200Sstevel@tonic-gate /*
28210Sstevel@tonic-gate * ibdm_handle_ioc_profile()
28220Sstevel@tonic-gate * Invoked by the IBMF when the IOCControllerProfile request
28230Sstevel@tonic-gate * gets completed
28240Sstevel@tonic-gate */
28250Sstevel@tonic-gate static void
ibdm_handle_ioc_profile(ibmf_handle_t ibmf_hdl,ibmf_msg_t * msg,ibdm_dp_gidinfo_t * gid_info,int * flag)28260Sstevel@tonic-gate ibdm_handle_ioc_profile(ibmf_handle_t ibmf_hdl,
28270Sstevel@tonic-gate ibmf_msg_t *msg, ibdm_dp_gidinfo_t *gid_info, int *flag)
28280Sstevel@tonic-gate {
28290Sstevel@tonic-gate int first = B_TRUE, reprobe = 0;
28300Sstevel@tonic-gate uint_t ii, ioc_no, srv_start;
28310Sstevel@tonic-gate uint_t nserv_entries;
28320Sstevel@tonic-gate timeout_id_t timeout_id;
28330Sstevel@tonic-gate ib_mad_hdr_t *hdr;
28340Sstevel@tonic-gate ibdm_ioc_info_t *ioc_info;
28350Sstevel@tonic-gate ibdm_timeout_cb_args_t *cb_args;
28360Sstevel@tonic-gate ib_dm_ioc_ctrl_profile_t *ioc, *gioc;
28370Sstevel@tonic-gate
28380Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\thandle_ioc_profile:"
28390Sstevel@tonic-gate " ibmf hdl %p msg %p gid info %p", ibmf_hdl, msg, gid_info);
28400Sstevel@tonic-gate
28410Sstevel@tonic-gate ioc = IBDM_IN_IBMFMSG2IOC(msg);
28420Sstevel@tonic-gate /*
28430Sstevel@tonic-gate * Check whether we know this IOC already
28440Sstevel@tonic-gate * This will return NULL if reprobe is in progress
28450Sstevel@tonic-gate * IBDM_IOC_STATE_REPROBE_PROGRESS will be set.
28460Sstevel@tonic-gate * Do not hold mutexes here.
28470Sstevel@tonic-gate */
28480Sstevel@tonic-gate if (ibdm_is_ioc_present(ioc->ioc_guid, gid_info, flag) != NULL) {
28490Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\thandle_ioc_profile:"
28506262Seota "IOC guid %llx is present", ioc->ioc_guid);
28510Sstevel@tonic-gate return;
28520Sstevel@tonic-gate }
28530Sstevel@tonic-gate ioc_no = IBDM_IN_IBMFMSG_ATTRMOD(msg);
28540Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\thandle_ioc_profile: ioc_no = %d", ioc_no-1);
28550Sstevel@tonic-gate
28560Sstevel@tonic-gate /* Make sure that IOC index is with the valid range */
28570Sstevel@tonic-gate if (IBDM_IS_IOC_NUM_INVALID(ioc_no, gid_info)) {
28580Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "\thandle_ioc_profile: "
28590Sstevel@tonic-gate "IOC index Out of range, index %d", ioc);
28600Sstevel@tonic-gate (*flag) |= IBDM_IBMF_PKT_UNEXP_RESP;
28610Sstevel@tonic-gate return;
28620Sstevel@tonic-gate }
28630Sstevel@tonic-gate ioc_info = &gid_info->gl_iou->iou_ioc_info[ioc_no - 1];
28640Sstevel@tonic-gate ioc_info->ioc_iou_info = gid_info->gl_iou;
28650Sstevel@tonic-gate
28660Sstevel@tonic-gate mutex_enter(&gid_info->gl_mutex);
28670Sstevel@tonic-gate if (ioc_info->ioc_state == IBDM_IOC_STATE_REPROBE_PROGRESS) {
28680Sstevel@tonic-gate reprobe = 1;
28690Sstevel@tonic-gate ioc_info->ioc_prev_serv = ioc_info->ioc_serv;
28700Sstevel@tonic-gate ioc_info->ioc_serv = NULL;
28710Sstevel@tonic-gate ioc_info->ioc_prev_serv_cnt =
28720Sstevel@tonic-gate ioc_info->ioc_profile.ioc_service_entries;
28730Sstevel@tonic-gate } else if (ioc_info->ioc_state != IBDM_IOC_STATE_PROBE_INVALID) {
28740Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "\thandle_ioc_profile: DUP response"
28750Sstevel@tonic-gate "ioc %d, ioc_state %x", ioc_no - 1, ioc_info->ioc_state);
28760Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
28770Sstevel@tonic-gate (*flag) |= IBDM_IBMF_PKT_DUP_RESP;
28780Sstevel@tonic-gate return;
28790Sstevel@tonic-gate }
28800Sstevel@tonic-gate ioc_info->ioc_cb_args.cb_req_type = 0;
28810Sstevel@tonic-gate if (ioc_info->ioc_timeout_id) {
28820Sstevel@tonic-gate timeout_id = ioc_info->ioc_timeout_id;
28836699Seota ioc_info->ioc_timeout_id = 0;
28840Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
28850Sstevel@tonic-gate IBTF_DPRINTF_L5("ibdm", "handle_ioc_profile: "
28860Sstevel@tonic-gate "ioc_timeout_id = 0x%x", timeout_id);
28870Sstevel@tonic-gate if (untimeout(timeout_id) == -1) {
28880Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "handle_ioc_profile: "
28890Sstevel@tonic-gate "untimeout ioc_timeout_id failed");
28900Sstevel@tonic-gate }
28910Sstevel@tonic-gate mutex_enter(&gid_info->gl_mutex);
28920Sstevel@tonic-gate }
28930Sstevel@tonic-gate
28940Sstevel@tonic-gate ioc_info->ioc_state = IBDM_IOC_STATE_PROBE_SUCCESS;
28950Sstevel@tonic-gate if (reprobe == 0) {
28960Sstevel@tonic-gate ioc_info->ioc_iou_guid = gid_info->gl_nodeguid;
28970Sstevel@tonic-gate ioc_info->ioc_nodeguid = gid_info->gl_nodeguid;
28980Sstevel@tonic-gate }
28990Sstevel@tonic-gate
29000Sstevel@tonic-gate /*
29010Sstevel@tonic-gate * Save all the IOC information in the global structures.
29020Sstevel@tonic-gate * Note the wire format is Big Endian and the Sparc process also
29030Sstevel@tonic-gate * big endian. So, there is no need to convert the data fields
29040Sstevel@tonic-gate * The conversion routines used below are ineffective on Sparc
29050Sstevel@tonic-gate * machines where as they will be effective on little endian
29060Sstevel@tonic-gate * machines such as Intel processors.
29070Sstevel@tonic-gate */
29080Sstevel@tonic-gate gioc = (ib_dm_ioc_ctrl_profile_t *)&ioc_info->ioc_profile;
29090Sstevel@tonic-gate
29100Sstevel@tonic-gate /*
29110Sstevel@tonic-gate * Restrict updates to onlyport GIDs and service entries during reprobe
29120Sstevel@tonic-gate */
29130Sstevel@tonic-gate if (reprobe == 0) {
29140Sstevel@tonic-gate gioc->ioc_guid = b2h64(ioc->ioc_guid);
29150Sstevel@tonic-gate gioc->ioc_vendorid =
29161093Shiremath ((b2h32(ioc->ioc_vendorid) & IB_DM_VENDORID_MASK)
29171093Shiremath >> IB_DM_VENDORID_SHIFT);
29180Sstevel@tonic-gate gioc->ioc_deviceid = b2h32(ioc->ioc_deviceid);
29190Sstevel@tonic-gate gioc->ioc_device_ver = b2h16(ioc->ioc_device_ver);
29200Sstevel@tonic-gate gioc->ioc_subsys_vendorid =
29211093Shiremath ((b2h32(ioc->ioc_subsys_vendorid) & IB_DM_VENDORID_MASK)
29221093Shiremath >> IB_DM_VENDORID_SHIFT);
29230Sstevel@tonic-gate gioc->ioc_subsys_id = b2h32(ioc->ioc_subsys_id);
29240Sstevel@tonic-gate gioc->ioc_io_class = b2h16(ioc->ioc_io_class);
29250Sstevel@tonic-gate gioc->ioc_io_subclass = b2h16(ioc->ioc_io_subclass);
29260Sstevel@tonic-gate gioc->ioc_protocol = b2h16(ioc->ioc_protocol);
29270Sstevel@tonic-gate gioc->ioc_protocol_ver = b2h16(ioc->ioc_protocol_ver);
29280Sstevel@tonic-gate gioc->ioc_send_msg_qdepth =
29290Sstevel@tonic-gate b2h16(ioc->ioc_send_msg_qdepth);
29300Sstevel@tonic-gate gioc->ioc_rdma_read_qdepth =
29310Sstevel@tonic-gate b2h16(ioc->ioc_rdma_read_qdepth);
29320Sstevel@tonic-gate gioc->ioc_send_msg_sz = b2h32(ioc->ioc_send_msg_sz);
29330Sstevel@tonic-gate gioc->ioc_rdma_xfer_sz = b2h32(ioc->ioc_rdma_xfer_sz);
29340Sstevel@tonic-gate gioc->ioc_ctrl_opcap_mask = ioc->ioc_ctrl_opcap_mask;
29350Sstevel@tonic-gate bcopy(ioc->ioc_id_string, gioc->ioc_id_string,
29360Sstevel@tonic-gate IB_DM_IOC_ID_STRING_LEN);
29370Sstevel@tonic-gate
29380Sstevel@tonic-gate ioc_info->ioc_iou_diagcode = gid_info->gl_iou->iou_diagcode;
29390Sstevel@tonic-gate ioc_info->ioc_iou_dc_valid = gid_info->gl_iou->iou_dc_valid;
29400Sstevel@tonic-gate ioc_info->ioc_diagdeviceid = (IB_DM_IOU_DEVICEID_MASK &
29410Sstevel@tonic-gate gid_info->gl_iou->iou_info.iou_flag) ? B_TRUE : B_FALSE;
29420Sstevel@tonic-gate
29436262Seota if (ioc_info->ioc_diagdeviceid == B_TRUE) {
29440Sstevel@tonic-gate gid_info->gl_pending_cmds++;
29456262Seota IBTF_DPRINTF_L3(ibdm_string,
29466262Seota "\tibdm_handle_ioc_profile: "
29476262Seota "%d: gid_info %p gl_state %d pending_cmds %d",
29486262Seota __LINE__, gid_info, gid_info->gl_state,
29496262Seota gid_info->gl_pending_cmds);
29506262Seota }
29510Sstevel@tonic-gate }
29520Sstevel@tonic-gate gioc->ioc_service_entries = ioc->ioc_service_entries;
29530Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
29540Sstevel@tonic-gate
29550Sstevel@tonic-gate ibdm_dump_ioc_profile(gioc);
29560Sstevel@tonic-gate
29570Sstevel@tonic-gate if ((ioc_info->ioc_diagdeviceid == B_TRUE) && (reprobe == 0)) {
29580Sstevel@tonic-gate if (ibdm_get_diagcode(gid_info, ioc_no) != IBDM_SUCCESS) {
29590Sstevel@tonic-gate mutex_enter(&gid_info->gl_mutex);
29600Sstevel@tonic-gate gid_info->gl_pending_cmds--;
29610Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
29620Sstevel@tonic-gate }
29630Sstevel@tonic-gate }
29640Sstevel@tonic-gate ioc_info->ioc_serv = (ibdm_srvents_info_t *)kmem_zalloc(
29650Sstevel@tonic-gate (gioc->ioc_service_entries * sizeof (ibdm_srvents_info_t)),
29660Sstevel@tonic-gate KM_SLEEP);
29670Sstevel@tonic-gate
29680Sstevel@tonic-gate /*
29690Sstevel@tonic-gate * In one single request, maximum number of requests that can be
29700Sstevel@tonic-gate * obtained is 4. If number of service entries are more than four,
29710Sstevel@tonic-gate * calculate number requests needed and send them parallelly.
29720Sstevel@tonic-gate */
29730Sstevel@tonic-gate nserv_entries = ioc->ioc_service_entries;
29740Sstevel@tonic-gate ii = 0;
29750Sstevel@tonic-gate while (nserv_entries) {
29761093Shiremath mutex_enter(&gid_info->gl_mutex);
29776262Seota gid_info->gl_pending_cmds++;
29781093Shiremath ibdm_bump_transactionID(gid_info);
29791093Shiremath mutex_exit(&gid_info->gl_mutex);
29801093Shiremath
29810Sstevel@tonic-gate if (first != B_TRUE) {
29820Sstevel@tonic-gate if (ibmf_alloc_msg(ibmf_hdl, IBMF_ALLOC_SLEEP,
29830Sstevel@tonic-gate &msg) != IBMF_SUCCESS) {
29840Sstevel@tonic-gate continue;
29850Sstevel@tonic-gate }
29860Sstevel@tonic-gate
29870Sstevel@tonic-gate }
29886699Seota _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*msg))
29890Sstevel@tonic-gate ibdm_alloc_send_buffers(msg);
29906699Seota _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*msg))
29910Sstevel@tonic-gate msg->im_local_addr.ia_local_lid = gid_info->gl_slid;
29920Sstevel@tonic-gate msg->im_local_addr.ia_remote_lid = gid_info->gl_dlid;
29930Sstevel@tonic-gate if (gid_info->gl_redirected == B_TRUE) {
29940Sstevel@tonic-gate if (gid_info->gl_redirect_dlid != 0) {
29950Sstevel@tonic-gate msg->im_local_addr.ia_remote_lid =
29960Sstevel@tonic-gate gid_info->gl_redirect_dlid;
29970Sstevel@tonic-gate }
29980Sstevel@tonic-gate msg->im_local_addr.ia_remote_qno =
29990Sstevel@tonic-gate gid_info->gl_redirect_QP;
30000Sstevel@tonic-gate msg->im_local_addr.ia_p_key =
30010Sstevel@tonic-gate gid_info->gl_redirect_pkey;
30020Sstevel@tonic-gate msg->im_local_addr.ia_q_key =
30030Sstevel@tonic-gate gid_info->gl_redirect_qkey;
30046699Seota msg->im_local_addr.ia_service_level =
30056699Seota gid_info->gl_redirectSL;
30060Sstevel@tonic-gate } else {
30070Sstevel@tonic-gate msg->im_local_addr.ia_remote_qno = 1;
30080Sstevel@tonic-gate msg->im_local_addr.ia_p_key = gid_info->gl_p_key;
30090Sstevel@tonic-gate msg->im_local_addr.ia_q_key = IB_GSI_QKEY;
30106699Seota msg->im_local_addr.ia_service_level = gid_info->gl_SL;
30110Sstevel@tonic-gate }
30120Sstevel@tonic-gate
30130Sstevel@tonic-gate hdr = IBDM_OUT_IBMFMSG_MADHDR(msg);
30140Sstevel@tonic-gate hdr->BaseVersion = MAD_CLASS_BASE_VERS_1;
30150Sstevel@tonic-gate hdr->MgmtClass = MAD_MGMT_CLASS_DEV_MGT;
30160Sstevel@tonic-gate hdr->ClassVersion = IB_DM_CLASS_VERSION_1;
30170Sstevel@tonic-gate hdr->R_Method = IB_DM_DEVMGT_METHOD_GET;
30180Sstevel@tonic-gate hdr->Status = 0;
30190Sstevel@tonic-gate hdr->TransactionID = h2b64(gid_info->gl_transactionID);
30200Sstevel@tonic-gate hdr->AttributeID = h2b16(IB_DM_ATTR_SERVICE_ENTRIES);
30210Sstevel@tonic-gate
30220Sstevel@tonic-gate srv_start = ii * 4;
30230Sstevel@tonic-gate cb_args = &ioc_info->ioc_serv[srv_start].se_cb_args;
30240Sstevel@tonic-gate cb_args->cb_gid_info = gid_info;
30250Sstevel@tonic-gate cb_args->cb_retry_count = ibdm_dft_retry_cnt;
30260Sstevel@tonic-gate cb_args->cb_req_type = IBDM_REQ_TYPE_SRVENTS;
30270Sstevel@tonic-gate cb_args->cb_srvents_start = srv_start;
30280Sstevel@tonic-gate cb_args->cb_ioc_num = ioc_no - 1;
30290Sstevel@tonic-gate
30300Sstevel@tonic-gate if (nserv_entries >= IBDM_MAX_SERV_ENTRIES_PER_REQ) {
30310Sstevel@tonic-gate nserv_entries -= IBDM_MAX_SERV_ENTRIES_PER_REQ;
30320Sstevel@tonic-gate cb_args->cb_srvents_end = (cb_args->cb_srvents_start +
30330Sstevel@tonic-gate IBDM_MAX_SERV_ENTRIES_PER_REQ - 1);
30340Sstevel@tonic-gate } else {
30350Sstevel@tonic-gate cb_args->cb_srvents_end =
30360Sstevel@tonic-gate (cb_args->cb_srvents_start + nserv_entries - 1);
30370Sstevel@tonic-gate nserv_entries = 0;
30380Sstevel@tonic-gate }
30396699Seota _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*hdr))
30401093Shiremath ibdm_fill_srv_attr_mod(hdr, cb_args);
30416699Seota _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*hdr))
30426699Seota
30436699Seota mutex_enter(&gid_info->gl_mutex);
30440Sstevel@tonic-gate ioc_info->ioc_serv[srv_start].se_timeout_id = timeout(
30450Sstevel@tonic-gate ibdm_pkt_timeout_hdlr, cb_args,
30460Sstevel@tonic-gate IBDM_TIMEOUT_VALUE(ibdm_dft_timeout));
30476699Seota mutex_exit(&gid_info->gl_mutex);
30480Sstevel@tonic-gate
30490Sstevel@tonic-gate IBTF_DPRINTF_L5("ibdm", "\thandle_ioc_profile:"
30500Sstevel@tonic-gate "timeout %x, ioc %d srv %d",
30510Sstevel@tonic-gate ioc_info->ioc_serv[srv_start].se_timeout_id,
30520Sstevel@tonic-gate ioc_no - 1, srv_start);
30530Sstevel@tonic-gate
30540Sstevel@tonic-gate if (ibmf_msg_transport(ibmf_hdl, gid_info->gl_qp_hdl, msg,
30550Sstevel@tonic-gate NULL, ibdm_ibmf_send_cb, cb_args, 0) != IBMF_SUCCESS) {
30560Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm",
30570Sstevel@tonic-gate "\thandle_ioc_profile: msg send failed");
30580Sstevel@tonic-gate ibdm_ibmf_send_cb(ibmf_hdl, msg, cb_args);
30590Sstevel@tonic-gate }
30600Sstevel@tonic-gate (*flag) |= IBDM_IBMF_PKT_REUSED;
30610Sstevel@tonic-gate first = B_FALSE;
30620Sstevel@tonic-gate ii++;
30630Sstevel@tonic-gate }
30640Sstevel@tonic-gate }
30650Sstevel@tonic-gate
30660Sstevel@tonic-gate
30670Sstevel@tonic-gate /*
30680Sstevel@tonic-gate * ibdm_handle_srventry_mad()
30690Sstevel@tonic-gate */
30700Sstevel@tonic-gate static void
ibdm_handle_srventry_mad(ibmf_msg_t * msg,ibdm_dp_gidinfo_t * gid_info,int * flag)30710Sstevel@tonic-gate ibdm_handle_srventry_mad(ibmf_msg_t *msg,
30720Sstevel@tonic-gate ibdm_dp_gidinfo_t *gid_info, int *flag)
30730Sstevel@tonic-gate {
30740Sstevel@tonic-gate uint_t ii, ioc_no, attrmod;
30750Sstevel@tonic-gate uint_t nentries, start, end;
30760Sstevel@tonic-gate timeout_id_t timeout_id;
30770Sstevel@tonic-gate ib_dm_srv_t *srv_ents;
30780Sstevel@tonic-gate ibdm_ioc_info_t *ioc_info;
30790Sstevel@tonic-gate ibdm_srvents_info_t *gsrv_ents;
30800Sstevel@tonic-gate
30810Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\thandle_srventry_mad:"
30820Sstevel@tonic-gate " IBMF msg %p gid info %p", msg, gid_info);
30830Sstevel@tonic-gate
30840Sstevel@tonic-gate srv_ents = IBDM_IN_IBMFMSG2SRVENT(msg);
30850Sstevel@tonic-gate /*
30860Sstevel@tonic-gate * Get the start and end index of the service entries
30870Sstevel@tonic-gate * Upper 16 bits identify the IOC
30880Sstevel@tonic-gate * Lower 16 bits specify the range of service entries
30890Sstevel@tonic-gate * LSB specifies (Big endian) end of the range
30900Sstevel@tonic-gate * MSB specifies (Big endian) start of the range
30910Sstevel@tonic-gate */
30920Sstevel@tonic-gate attrmod = IBDM_IN_IBMFMSG_ATTRMOD(msg);
30930Sstevel@tonic-gate ioc_no = ((attrmod >> 16) & IBDM_16_BIT_MASK);
30941093Shiremath end = ((attrmod >> 8) & IBDM_8_BIT_MASK);
30951093Shiremath start = (attrmod & IBDM_8_BIT_MASK);
30960Sstevel@tonic-gate
30970Sstevel@tonic-gate /* Make sure that IOC index is with the valid range */
30980Sstevel@tonic-gate if ((ioc_no < 1) |
30990Sstevel@tonic-gate (ioc_no > gid_info->gl_iou->iou_info.iou_num_ctrl_slots)) {
31000Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "\thandle_srventry_mad: "
31010Sstevel@tonic-gate "IOC index Out of range, index %d", ioc_no);
31020Sstevel@tonic-gate (*flag) |= IBDM_IBMF_PKT_UNEXP_RESP;
31030Sstevel@tonic-gate return;
31040Sstevel@tonic-gate }
31050Sstevel@tonic-gate ioc_info = IBDM_GIDINFO2IOCINFO(gid_info, (ioc_no -1));
31060Sstevel@tonic-gate
31070Sstevel@tonic-gate /*
31080Sstevel@tonic-gate * Make sure that the "start" and "end" service indexes are
31090Sstevel@tonic-gate * with in the valid range
31100Sstevel@tonic-gate */
31110Sstevel@tonic-gate nentries = ioc_info->ioc_profile.ioc_service_entries;
31120Sstevel@tonic-gate if ((start > end) | (start >= nentries) | (end >= nentries)) {
31130Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "\thandle_srventry_mad: "
31140Sstevel@tonic-gate "Attr modifier 0x%x, #Serv entries %d", attrmod, nentries);
31150Sstevel@tonic-gate (*flag) |= IBDM_IBMF_PKT_UNEXP_RESP;
31160Sstevel@tonic-gate return;
31170Sstevel@tonic-gate }
31180Sstevel@tonic-gate gsrv_ents = &ioc_info->ioc_serv[start];
31190Sstevel@tonic-gate mutex_enter(&gid_info->gl_mutex);
31200Sstevel@tonic-gate if (gsrv_ents->se_state != IBDM_SE_INVALID) {
31210Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "\thandle_srventry_mad: "
31226262Seota "already known, ioc %d, srv %d, se_state %x",
31230Sstevel@tonic-gate ioc_no - 1, start, gsrv_ents->se_state);
31240Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
31250Sstevel@tonic-gate (*flag) |= IBDM_IBMF_PKT_DUP_RESP;
31260Sstevel@tonic-gate return;
31270Sstevel@tonic-gate }
31280Sstevel@tonic-gate ioc_info->ioc_serv[start].se_cb_args.cb_req_type = 0;
31290Sstevel@tonic-gate if (ioc_info->ioc_serv[start].se_timeout_id) {
31300Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm",
31310Sstevel@tonic-gate "\thandle_srventry_mad: ioc %d start %d", ioc_no, start);
31320Sstevel@tonic-gate timeout_id = ioc_info->ioc_serv[start].se_timeout_id;
31336699Seota ioc_info->ioc_serv[start].se_timeout_id = 0;
31340Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
31350Sstevel@tonic-gate IBTF_DPRINTF_L5("ibdm", "handle_srverntry_mad: "
31360Sstevel@tonic-gate "se_timeout_id = 0x%x", timeout_id);
31370Sstevel@tonic-gate if (untimeout(timeout_id) == -1) {
31380Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "handle_srventry_mad: "
31390Sstevel@tonic-gate "untimeout se_timeout_id failed");
31400Sstevel@tonic-gate }
31410Sstevel@tonic-gate mutex_enter(&gid_info->gl_mutex);
31420Sstevel@tonic-gate }
31430Sstevel@tonic-gate
31440Sstevel@tonic-gate gsrv_ents->se_state = IBDM_SE_VALID;
31450Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
31460Sstevel@tonic-gate for (ii = start; ii <= end; ii++, srv_ents++, gsrv_ents++) {
31471093Shiremath gsrv_ents->se_attr.srv_id = b2h64(srv_ents->srv_id);
31480Sstevel@tonic-gate bcopy(srv_ents->srv_name,
31490Sstevel@tonic-gate gsrv_ents->se_attr.srv_name, IB_DM_MAX_SVC_NAME_LEN);
31500Sstevel@tonic-gate ibdm_dump_service_entries(&gsrv_ents->se_attr);
31510Sstevel@tonic-gate }
31520Sstevel@tonic-gate }
31530Sstevel@tonic-gate
31540Sstevel@tonic-gate
31550Sstevel@tonic-gate /*
31560Sstevel@tonic-gate * ibdm_get_diagcode:
31570Sstevel@tonic-gate * Send request to get IOU/IOC diag code
31580Sstevel@tonic-gate * Returns IBDM_SUCCESS/IBDM_FAILURE
31590Sstevel@tonic-gate */
31600Sstevel@tonic-gate static int
ibdm_get_diagcode(ibdm_dp_gidinfo_t * gid_info,int attr)31610Sstevel@tonic-gate ibdm_get_diagcode(ibdm_dp_gidinfo_t *gid_info, int attr)
31620Sstevel@tonic-gate {
31630Sstevel@tonic-gate ibmf_msg_t *msg;
31640Sstevel@tonic-gate ib_mad_hdr_t *hdr;
31650Sstevel@tonic-gate ibdm_ioc_info_t *ioc;
31660Sstevel@tonic-gate ibdm_timeout_cb_args_t *cb_args;
31670Sstevel@tonic-gate timeout_id_t *timeout_id;
31680Sstevel@tonic-gate
31690Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tget_diagcode: gid info %p, attr = %d",
31700Sstevel@tonic-gate gid_info, attr);
31710Sstevel@tonic-gate
31720Sstevel@tonic-gate if (ibmf_alloc_msg(gid_info->gl_ibmf_hdl, IBMF_ALLOC_SLEEP,
31730Sstevel@tonic-gate &msg) != IBMF_SUCCESS) {
31740Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tget_diagcode: pkt alloc fail");
31750Sstevel@tonic-gate return (IBDM_FAILURE);
31760Sstevel@tonic-gate }
31770Sstevel@tonic-gate
31786699Seota _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*msg))
31790Sstevel@tonic-gate ibdm_alloc_send_buffers(msg);
31806699Seota _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*msg))
31810Sstevel@tonic-gate
31821093Shiremath mutex_enter(&gid_info->gl_mutex);
31831093Shiremath ibdm_bump_transactionID(gid_info);
31841093Shiremath mutex_exit(&gid_info->gl_mutex);
31851093Shiremath
31860Sstevel@tonic-gate msg->im_local_addr.ia_local_lid = gid_info->gl_slid;
31870Sstevel@tonic-gate msg->im_local_addr.ia_remote_lid = gid_info->gl_dlid;
31880Sstevel@tonic-gate if (gid_info->gl_redirected == B_TRUE) {
31890Sstevel@tonic-gate if (gid_info->gl_redirect_dlid != 0) {
31900Sstevel@tonic-gate msg->im_local_addr.ia_remote_lid =
31910Sstevel@tonic-gate gid_info->gl_redirect_dlid;
31920Sstevel@tonic-gate }
31930Sstevel@tonic-gate
31940Sstevel@tonic-gate msg->im_local_addr.ia_remote_qno = gid_info->gl_redirect_QP;
31950Sstevel@tonic-gate msg->im_local_addr.ia_p_key = gid_info->gl_redirect_pkey;
31960Sstevel@tonic-gate msg->im_local_addr.ia_q_key = gid_info->gl_redirect_qkey;
31976699Seota msg->im_local_addr.ia_service_level = gid_info->gl_redirectSL;
31980Sstevel@tonic-gate } else {
31990Sstevel@tonic-gate msg->im_local_addr.ia_remote_qno = 1;
32000Sstevel@tonic-gate msg->im_local_addr.ia_p_key = gid_info->gl_p_key;
32010Sstevel@tonic-gate msg->im_local_addr.ia_q_key = IB_GSI_QKEY;
32026699Seota msg->im_local_addr.ia_service_level = gid_info->gl_SL;
32030Sstevel@tonic-gate }
32040Sstevel@tonic-gate
32050Sstevel@tonic-gate hdr = IBDM_OUT_IBMFMSG_MADHDR(msg);
32060Sstevel@tonic-gate hdr->BaseVersion = MAD_CLASS_BASE_VERS_1;
32070Sstevel@tonic-gate hdr->MgmtClass = MAD_MGMT_CLASS_DEV_MGT;
32080Sstevel@tonic-gate hdr->ClassVersion = IB_DM_CLASS_VERSION_1;
32090Sstevel@tonic-gate hdr->R_Method = IB_DM_DEVMGT_METHOD_GET;
32100Sstevel@tonic-gate hdr->Status = 0;
32110Sstevel@tonic-gate hdr->TransactionID = h2b64(gid_info->gl_transactionID);
32120Sstevel@tonic-gate
32130Sstevel@tonic-gate hdr->AttributeID = h2b16(IB_DM_ATTR_DIAG_CODE);
32140Sstevel@tonic-gate hdr->AttributeModifier = h2b32(attr);
32150Sstevel@tonic-gate
32160Sstevel@tonic-gate if (attr == 0) {
32170Sstevel@tonic-gate cb_args = &gid_info->gl_iou_cb_args;
32180Sstevel@tonic-gate gid_info->gl_iou->iou_dc_valid = B_FALSE;
32190Sstevel@tonic-gate cb_args->cb_ioc_num = 0;
32200Sstevel@tonic-gate cb_args->cb_req_type = IBDM_REQ_TYPE_IOU_DIAGCODE;
32210Sstevel@tonic-gate timeout_id = &gid_info->gl_timeout_id;
32220Sstevel@tonic-gate } else {
32230Sstevel@tonic-gate ioc = IBDM_GIDINFO2IOCINFO(gid_info, (attr - 1));
32240Sstevel@tonic-gate ioc->ioc_dc_valid = B_FALSE;
32250Sstevel@tonic-gate cb_args = &ioc->ioc_dc_cb_args;
32260Sstevel@tonic-gate cb_args->cb_ioc_num = attr - 1;
32270Sstevel@tonic-gate cb_args->cb_req_type = IBDM_REQ_TYPE_IOC_DIAGCODE;
32280Sstevel@tonic-gate timeout_id = &ioc->ioc_dc_timeout_id;
32290Sstevel@tonic-gate }
32300Sstevel@tonic-gate cb_args->cb_gid_info = gid_info;
32310Sstevel@tonic-gate cb_args->cb_retry_count = ibdm_dft_retry_cnt;
32320Sstevel@tonic-gate cb_args->cb_srvents_start = 0;
32330Sstevel@tonic-gate
32346699Seota mutex_enter(&gid_info->gl_mutex);
32350Sstevel@tonic-gate *timeout_id = timeout(ibdm_pkt_timeout_hdlr,
32360Sstevel@tonic-gate cb_args, IBDM_TIMEOUT_VALUE(ibdm_dft_timeout));
32376699Seota mutex_exit(&gid_info->gl_mutex);
32380Sstevel@tonic-gate
32390Sstevel@tonic-gate IBTF_DPRINTF_L5("ibdm", "\tget_diagcode:"
32400Sstevel@tonic-gate "timeout %x, ioc %d", *timeout_id, cb_args->cb_ioc_num);
32410Sstevel@tonic-gate
32420Sstevel@tonic-gate if (ibmf_msg_transport(gid_info->gl_ibmf_hdl, gid_info->gl_qp_hdl,
32430Sstevel@tonic-gate msg, NULL, ibdm_ibmf_send_cb, cb_args, 0) != IBMF_SUCCESS) {
32440Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "\tget_diagcode: ibmf send failed");
32450Sstevel@tonic-gate ibdm_ibmf_send_cb(gid_info->gl_ibmf_hdl, msg, cb_args);
32460Sstevel@tonic-gate }
32470Sstevel@tonic-gate return (IBDM_SUCCESS);
32480Sstevel@tonic-gate }
32490Sstevel@tonic-gate
32500Sstevel@tonic-gate /*
32510Sstevel@tonic-gate * ibdm_handle_diagcode:
32520Sstevel@tonic-gate * Process the DiagCode MAD response and update local DM
32530Sstevel@tonic-gate * data structure.
32540Sstevel@tonic-gate */
32550Sstevel@tonic-gate static void
ibdm_handle_diagcode(ibmf_msg_t * ibmf_msg,ibdm_dp_gidinfo_t * gid_info,int * flag)32560Sstevel@tonic-gate ibdm_handle_diagcode(ibmf_msg_t *ibmf_msg,
32570Sstevel@tonic-gate ibdm_dp_gidinfo_t *gid_info, int *flag)
32580Sstevel@tonic-gate {
32590Sstevel@tonic-gate uint16_t attrmod, *diagcode;
32600Sstevel@tonic-gate ibdm_iou_info_t *iou;
32610Sstevel@tonic-gate ibdm_ioc_info_t *ioc;
32620Sstevel@tonic-gate timeout_id_t timeout_id;
32630Sstevel@tonic-gate ibdm_timeout_cb_args_t *cb_args;
32640Sstevel@tonic-gate
32650Sstevel@tonic-gate diagcode = (uint16_t *)ibmf_msg->im_msgbufs_recv.im_bufs_cl_data;
32660Sstevel@tonic-gate
32670Sstevel@tonic-gate mutex_enter(&gid_info->gl_mutex);
32680Sstevel@tonic-gate attrmod = IBDM_IN_IBMFMSG_ATTRMOD(ibmf_msg);
32690Sstevel@tonic-gate iou = gid_info->gl_iou;
32700Sstevel@tonic-gate if (attrmod == 0) {
32710Sstevel@tonic-gate if (iou->iou_dc_valid != B_FALSE) {
32720Sstevel@tonic-gate (*flag) |= IBDM_IBMF_PKT_DUP_RESP;
32730Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm",
32740Sstevel@tonic-gate "\thandle_diagcode: Duplicate IOU DiagCode");
32750Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
32760Sstevel@tonic-gate return;
32770Sstevel@tonic-gate }
32780Sstevel@tonic-gate cb_args = &gid_info->gl_iou_cb_args;
32790Sstevel@tonic-gate cb_args->cb_req_type = 0;
32800Sstevel@tonic-gate iou->iou_diagcode = b2h16(*diagcode);
32810Sstevel@tonic-gate iou->iou_dc_valid = B_TRUE;
32820Sstevel@tonic-gate if (gid_info->gl_timeout_id) {
32830Sstevel@tonic-gate timeout_id = gid_info->gl_timeout_id;
32840Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
32850Sstevel@tonic-gate IBTF_DPRINTF_L5("ibdm", "\thandle_diagcode: "
32860Sstevel@tonic-gate "gl_timeout_id = 0x%x", timeout_id);
32870Sstevel@tonic-gate if (untimeout(timeout_id) == -1) {
32880Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "handle_diagcode: "
32890Sstevel@tonic-gate "untimeout gl_timeout_id failed");
32900Sstevel@tonic-gate }
32910Sstevel@tonic-gate mutex_enter(&gid_info->gl_mutex);
32920Sstevel@tonic-gate gid_info->gl_timeout_id = 0;
32930Sstevel@tonic-gate }
32940Sstevel@tonic-gate } else {
32950Sstevel@tonic-gate ioc = IBDM_GIDINFO2IOCINFO(gid_info, (attrmod - 1));
32960Sstevel@tonic-gate if (ioc->ioc_dc_valid != B_FALSE) {
32970Sstevel@tonic-gate (*flag) |= IBDM_IBMF_PKT_DUP_RESP;
32980Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm",
32990Sstevel@tonic-gate "\thandle_diagcode: Duplicate IOC DiagCode");
33000Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
33010Sstevel@tonic-gate return;
33020Sstevel@tonic-gate }
33030Sstevel@tonic-gate cb_args = &ioc->ioc_dc_cb_args;
33040Sstevel@tonic-gate cb_args->cb_req_type = 0;
33050Sstevel@tonic-gate ioc->ioc_diagcode = b2h16(*diagcode);
33060Sstevel@tonic-gate ioc->ioc_dc_valid = B_TRUE;
33070Sstevel@tonic-gate timeout_id = iou->iou_ioc_info[attrmod - 1].ioc_dc_timeout_id;
33080Sstevel@tonic-gate if (timeout_id) {
33096699Seota iou->iou_ioc_info[attrmod - 1].ioc_dc_timeout_id = 0;
33100Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
33110Sstevel@tonic-gate IBTF_DPRINTF_L5("ibdm", "handle_diagcode: "
33120Sstevel@tonic-gate "timeout_id = 0x%x", timeout_id);
33130Sstevel@tonic-gate if (untimeout(timeout_id) == -1) {
33140Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "\thandle_diagcode: "
33150Sstevel@tonic-gate "untimeout ioc_dc_timeout_id failed");
33160Sstevel@tonic-gate }
33170Sstevel@tonic-gate mutex_enter(&gid_info->gl_mutex);
33180Sstevel@tonic-gate }
33190Sstevel@tonic-gate }
33200Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
33210Sstevel@tonic-gate
33220Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\thandle_diagcode: DiagCode : 0x%x"
33230Sstevel@tonic-gate "attrmod : 0x%x", b2h16(*diagcode), attrmod);
33240Sstevel@tonic-gate }
33250Sstevel@tonic-gate
33260Sstevel@tonic-gate
33270Sstevel@tonic-gate /*
33280Sstevel@tonic-gate * ibdm_is_ioc_present()
33290Sstevel@tonic-gate * Return ibdm_ioc_info_t if IOC guid is found in the global gid list
33300Sstevel@tonic-gate */
33310Sstevel@tonic-gate static ibdm_ioc_info_t *
ibdm_is_ioc_present(ib_guid_t ioc_guid,ibdm_dp_gidinfo_t * gid_info,int * flag)33320Sstevel@tonic-gate ibdm_is_ioc_present(ib_guid_t ioc_guid,
33330Sstevel@tonic-gate ibdm_dp_gidinfo_t *gid_info, int *flag)
33340Sstevel@tonic-gate {
33350Sstevel@tonic-gate int ii;
33360Sstevel@tonic-gate ibdm_ioc_info_t *ioc;
33370Sstevel@tonic-gate ibdm_dp_gidinfo_t *head;
33380Sstevel@tonic-gate ib_dm_io_unitinfo_t *iou;
33390Sstevel@tonic-gate
33400Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
33410Sstevel@tonic-gate head = ibdm.ibdm_dp_gidlist_head;
33420Sstevel@tonic-gate while (head) {
33430Sstevel@tonic-gate mutex_enter(&head->gl_mutex);
33440Sstevel@tonic-gate if (head->gl_iou == NULL) {
33450Sstevel@tonic-gate mutex_exit(&head->gl_mutex);
33460Sstevel@tonic-gate head = head->gl_next;
33470Sstevel@tonic-gate continue;
33480Sstevel@tonic-gate }
33490Sstevel@tonic-gate iou = &head->gl_iou->iou_info;
33500Sstevel@tonic-gate for (ii = 0; ii < iou->iou_num_ctrl_slots; ii++) {
33510Sstevel@tonic-gate ioc = IBDM_GIDINFO2IOCINFO(head, ii);
33520Sstevel@tonic-gate if ((ioc->ioc_state == IBDM_IOC_STATE_PROBE_SUCCESS) &&
33530Sstevel@tonic-gate (ioc->ioc_profile.ioc_guid == ioc_guid)) {
33540Sstevel@tonic-gate if (gid_info == head) {
33550Sstevel@tonic-gate *flag |= IBDM_IBMF_PKT_DUP_RESP;
33560Sstevel@tonic-gate } else if (ibdm_check_dgid(head->gl_dgid_lo,
33570Sstevel@tonic-gate head->gl_dgid_hi) != NULL) {
33580Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tis_ioc_"
33590Sstevel@tonic-gate "present: gid not present");
33600Sstevel@tonic-gate ibdm_add_to_gl_gid(gid_info, head);
33610Sstevel@tonic-gate }
33620Sstevel@tonic-gate mutex_exit(&head->gl_mutex);
33630Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
33640Sstevel@tonic-gate return (ioc);
33650Sstevel@tonic-gate }
33660Sstevel@tonic-gate }
33670Sstevel@tonic-gate mutex_exit(&head->gl_mutex);
33680Sstevel@tonic-gate head = head->gl_next;
33690Sstevel@tonic-gate }
33700Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
33710Sstevel@tonic-gate return (NULL);
33720Sstevel@tonic-gate }
33730Sstevel@tonic-gate
33740Sstevel@tonic-gate
33750Sstevel@tonic-gate /*
33760Sstevel@tonic-gate * ibdm_ibmf_send_cb()
33770Sstevel@tonic-gate * IBMF invokes this callback routine after posting the DM MAD to
33780Sstevel@tonic-gate * the HCA.
33790Sstevel@tonic-gate */
33800Sstevel@tonic-gate /*ARGSUSED*/
33810Sstevel@tonic-gate static void
ibdm_ibmf_send_cb(ibmf_handle_t ibmf_hdl,ibmf_msg_t * ibmf_msg,void * arg)33820Sstevel@tonic-gate ibdm_ibmf_send_cb(ibmf_handle_t ibmf_hdl, ibmf_msg_t *ibmf_msg, void *arg)
33830Sstevel@tonic-gate {
33840Sstevel@tonic-gate ibdm_dump_ibmf_msg(ibmf_msg, 1);
33850Sstevel@tonic-gate ibdm_free_send_buffers(ibmf_msg);
33860Sstevel@tonic-gate if (ibmf_free_msg(ibmf_hdl, &ibmf_msg) != IBMF_SUCCESS) {
33870Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm",
33880Sstevel@tonic-gate "\tibmf_send_cb: IBMF free msg failed");
33890Sstevel@tonic-gate }
33900Sstevel@tonic-gate }
33910Sstevel@tonic-gate
33920Sstevel@tonic-gate
33930Sstevel@tonic-gate /*
33940Sstevel@tonic-gate * ibdm_ibmf_recv_cb()
33950Sstevel@tonic-gate * Invoked by the IBMF when a response to the one of the DM requests
33960Sstevel@tonic-gate * is received.
33970Sstevel@tonic-gate */
33980Sstevel@tonic-gate /*ARGSUSED*/
33990Sstevel@tonic-gate static void
ibdm_ibmf_recv_cb(ibmf_handle_t ibmf_hdl,ibmf_msg_t * msg,void * arg)34000Sstevel@tonic-gate ibdm_ibmf_recv_cb(ibmf_handle_t ibmf_hdl, ibmf_msg_t *msg, void *arg)
34010Sstevel@tonic-gate {
34020Sstevel@tonic-gate ibdm_taskq_args_t *taskq_args;
34030Sstevel@tonic-gate
34040Sstevel@tonic-gate /*
34050Sstevel@tonic-gate * If the taskq enable is set then dispatch a taskq to process
34060Sstevel@tonic-gate * the MAD, otherwise just process it on this thread
34070Sstevel@tonic-gate */
34080Sstevel@tonic-gate if (ibdm_taskq_enable != IBDM_ENABLE_TASKQ_HANDLING) {
34090Sstevel@tonic-gate ibdm_process_incoming_mad(ibmf_hdl, msg, arg);
34100Sstevel@tonic-gate return;
34110Sstevel@tonic-gate }
34120Sstevel@tonic-gate
34130Sstevel@tonic-gate /*
34140Sstevel@tonic-gate * create a taskq and dispatch it to process the incoming MAD
34150Sstevel@tonic-gate */
34160Sstevel@tonic-gate taskq_args = kmem_alloc(sizeof (ibdm_taskq_args_t), KM_NOSLEEP);
34170Sstevel@tonic-gate if (taskq_args == NULL) {
34180Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "ibmf_recv_cb: kmem_alloc failed for"
34190Sstevel@tonic-gate "taskq_args");
34200Sstevel@tonic-gate if (ibmf_free_msg(ibmf_hdl, &msg) != IBMF_SUCCESS) {
34210Sstevel@tonic-gate IBTF_DPRINTF_L4("ibmf_recv_cb",
34220Sstevel@tonic-gate "\tibmf_recv_cb: IBMF free msg failed");
34230Sstevel@tonic-gate }
34240Sstevel@tonic-gate return;
34250Sstevel@tonic-gate }
34260Sstevel@tonic-gate taskq_args->tq_ibmf_handle = ibmf_hdl;
34270Sstevel@tonic-gate taskq_args->tq_ibmf_msg = msg;
34280Sstevel@tonic-gate taskq_args->tq_args = arg;
34290Sstevel@tonic-gate
34300Sstevel@tonic-gate if (taskq_dispatch(system_taskq, ibdm_recv_incoming_mad, taskq_args,
34310Sstevel@tonic-gate TQ_NOSLEEP) == 0) {
34320Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "ibmf_recv_cb: taskq_dispatch failed");
34330Sstevel@tonic-gate if (ibmf_free_msg(ibmf_hdl, &msg) != IBMF_SUCCESS) {
34340Sstevel@tonic-gate IBTF_DPRINTF_L4("ibmf_recv_cb",
34350Sstevel@tonic-gate "\tibmf_recv_cb: IBMF free msg failed");
34360Sstevel@tonic-gate }
34370Sstevel@tonic-gate kmem_free(taskq_args, sizeof (ibdm_taskq_args_t));
34380Sstevel@tonic-gate return;
34390Sstevel@tonic-gate }
34400Sstevel@tonic-gate
34410Sstevel@tonic-gate /* taskq_args are deleted in ibdm_recv_incoming_mad() */
34420Sstevel@tonic-gate }
34430Sstevel@tonic-gate
34440Sstevel@tonic-gate
34450Sstevel@tonic-gate void
ibdm_recv_incoming_mad(void * args)34460Sstevel@tonic-gate ibdm_recv_incoming_mad(void *args)
34470Sstevel@tonic-gate {
34480Sstevel@tonic-gate ibdm_taskq_args_t *taskq_args;
34490Sstevel@tonic-gate
34500Sstevel@tonic-gate taskq_args = (ibdm_taskq_args_t *)args;
34510Sstevel@tonic-gate
34520Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tibdm_recv_incoming_mad: "
34530Sstevel@tonic-gate "Processing incoming MAD via taskq");
34540Sstevel@tonic-gate
34550Sstevel@tonic-gate ibdm_process_incoming_mad(taskq_args->tq_ibmf_handle,
34560Sstevel@tonic-gate taskq_args->tq_ibmf_msg, taskq_args->tq_args);
34570Sstevel@tonic-gate
34580Sstevel@tonic-gate kmem_free(taskq_args, sizeof (ibdm_taskq_args_t));
34590Sstevel@tonic-gate }
34600Sstevel@tonic-gate
34610Sstevel@tonic-gate
34620Sstevel@tonic-gate /*
34630Sstevel@tonic-gate * Calls ibdm_process_incoming_mad with all function arguments extracted
34640Sstevel@tonic-gate * from args
34650Sstevel@tonic-gate */
34660Sstevel@tonic-gate /*ARGSUSED*/
34670Sstevel@tonic-gate static void
ibdm_process_incoming_mad(ibmf_handle_t ibmf_hdl,ibmf_msg_t * msg,void * arg)34680Sstevel@tonic-gate ibdm_process_incoming_mad(ibmf_handle_t ibmf_hdl, ibmf_msg_t *msg, void *arg)
34690Sstevel@tonic-gate {
34700Sstevel@tonic-gate int flag = 0;
34710Sstevel@tonic-gate int ret;
34720Sstevel@tonic-gate uint64_t transaction_id;
34730Sstevel@tonic-gate ib_mad_hdr_t *hdr;
34740Sstevel@tonic-gate ibdm_dp_gidinfo_t *gid_info = NULL;
34750Sstevel@tonic-gate
34760Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm",
34770Sstevel@tonic-gate "\tprocess_incoming_mad: ibmf hdl %p pkt %p", ibmf_hdl, msg);
34780Sstevel@tonic-gate ibdm_dump_ibmf_msg(msg, 0);
34790Sstevel@tonic-gate
34800Sstevel@tonic-gate /*
34810Sstevel@tonic-gate * IBMF calls this routine for every DM MAD that arrives at this port.
34820Sstevel@tonic-gate * But we handle only the responses for requests we sent. We drop all
34830Sstevel@tonic-gate * the DM packets that does not have response bit set in the MAD
34840Sstevel@tonic-gate * header(this eliminates all the requests sent to this port).
34850Sstevel@tonic-gate * We handle only DM class version 1 MAD's
34860Sstevel@tonic-gate */
34870Sstevel@tonic-gate hdr = IBDM_IN_IBMFMSG_MADHDR(msg);
34880Sstevel@tonic-gate if (ibdm_verify_mad_status(hdr) != IBDM_SUCCESS) {
34890Sstevel@tonic-gate if (ibmf_free_msg(ibmf_hdl, &msg) != IBMF_SUCCESS) {
34900Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "\tprocess_incoming_mad: "
34910Sstevel@tonic-gate "IBMF free msg failed DM request drop it");
34920Sstevel@tonic-gate }
34930Sstevel@tonic-gate return;
34940Sstevel@tonic-gate }
34950Sstevel@tonic-gate
34960Sstevel@tonic-gate transaction_id = b2h64(hdr->TransactionID);
34970Sstevel@tonic-gate
34980Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
34990Sstevel@tonic-gate gid_info = ibdm.ibdm_dp_gidlist_head;
35000Sstevel@tonic-gate while (gid_info) {
35011093Shiremath if ((gid_info->gl_transactionID &
35021093Shiremath IBDM_GID_TRANSACTIONID_MASK) ==
35031093Shiremath (transaction_id & IBDM_GID_TRANSACTIONID_MASK))
35040Sstevel@tonic-gate break;
35050Sstevel@tonic-gate gid_info = gid_info->gl_next;
35060Sstevel@tonic-gate }
35070Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
35080Sstevel@tonic-gate
35090Sstevel@tonic-gate if (gid_info == NULL) {
35100Sstevel@tonic-gate /* Drop the packet */
35110Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "process_incoming_mad: transaction ID"
35120Sstevel@tonic-gate " does not match: 0x%llx", transaction_id);
35130Sstevel@tonic-gate if (ibmf_free_msg(ibmf_hdl, &msg) != IBMF_SUCCESS) {
35140Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "process_incoming_mad: "
35150Sstevel@tonic-gate "IBMF free msg failed DM request drop it");
35160Sstevel@tonic-gate }
35170Sstevel@tonic-gate return;
35180Sstevel@tonic-gate }
35190Sstevel@tonic-gate
35200Sstevel@tonic-gate /* Handle redirection for all the MAD's, except ClassPortInfo */
35210Sstevel@tonic-gate if (((IBDM_IN_IBMFMSG_STATUS(msg) & MAD_STATUS_REDIRECT_REQUIRED)) &&
35226262Seota (IBDM_IN_IBMFMSG_ATTR(msg) != IB_DM_ATTR_CLASSPORTINFO)) {
35230Sstevel@tonic-gate ret = ibdm_handle_redirection(msg, gid_info, &flag);
35240Sstevel@tonic-gate if (ret == IBDM_SUCCESS) {
35250Sstevel@tonic-gate return;
35260Sstevel@tonic-gate }
35270Sstevel@tonic-gate } else {
35280Sstevel@tonic-gate uint_t gl_state;
35290Sstevel@tonic-gate
35300Sstevel@tonic-gate mutex_enter(&gid_info->gl_mutex);
35310Sstevel@tonic-gate gl_state = gid_info->gl_state;
35320Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
35330Sstevel@tonic-gate
35340Sstevel@tonic-gate switch (gl_state) {
35356262Seota
35366262Seota case IBDM_SET_CLASSPORTINFO:
35376262Seota ibdm_handle_setclassportinfo(
35386262Seota ibmf_hdl, msg, gid_info, &flag);
35396262Seota break;
35406262Seota
35410Sstevel@tonic-gate case IBDM_GET_CLASSPORTINFO:
35420Sstevel@tonic-gate ibdm_handle_classportinfo(
35430Sstevel@tonic-gate ibmf_hdl, msg, gid_info, &flag);
35440Sstevel@tonic-gate break;
35450Sstevel@tonic-gate
35460Sstevel@tonic-gate case IBDM_GET_IOUNITINFO:
35470Sstevel@tonic-gate ibdm_handle_iounitinfo(ibmf_hdl, msg, gid_info, &flag);
35480Sstevel@tonic-gate break;
35490Sstevel@tonic-gate
35500Sstevel@tonic-gate case IBDM_GET_IOC_DETAILS:
35510Sstevel@tonic-gate switch (IBDM_IN_IBMFMSG_ATTR(msg)) {
35520Sstevel@tonic-gate
35530Sstevel@tonic-gate case IB_DM_ATTR_SERVICE_ENTRIES:
35540Sstevel@tonic-gate ibdm_handle_srventry_mad(msg, gid_info, &flag);
35550Sstevel@tonic-gate break;
35560Sstevel@tonic-gate
35570Sstevel@tonic-gate case IB_DM_ATTR_IOC_CTRL_PROFILE:
35580Sstevel@tonic-gate ibdm_handle_ioc_profile(
35590Sstevel@tonic-gate ibmf_hdl, msg, gid_info, &flag);
35600Sstevel@tonic-gate break;
35610Sstevel@tonic-gate
35620Sstevel@tonic-gate case IB_DM_ATTR_DIAG_CODE:
35630Sstevel@tonic-gate ibdm_handle_diagcode(msg, gid_info, &flag);
35640Sstevel@tonic-gate break;
35650Sstevel@tonic-gate
35660Sstevel@tonic-gate default:
35670Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "process_incoming_mad: "
35680Sstevel@tonic-gate "Error state, wrong attribute :-(");
35690Sstevel@tonic-gate (void) ibmf_free_msg(ibmf_hdl, &msg);
35700Sstevel@tonic-gate return;
35710Sstevel@tonic-gate }
35720Sstevel@tonic-gate break;
35730Sstevel@tonic-gate default:
35740Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm",
35750Sstevel@tonic-gate "process_incoming_mad: Dropping the packet"
35760Sstevel@tonic-gate " gl_state %x", gl_state);
35770Sstevel@tonic-gate if (ibmf_free_msg(ibmf_hdl, &msg) != IBMF_SUCCESS) {
35780Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "process_incoming_mad: "
35790Sstevel@tonic-gate "IBMF free msg failed DM request drop it");
35800Sstevel@tonic-gate }
35810Sstevel@tonic-gate return;
35820Sstevel@tonic-gate }
35830Sstevel@tonic-gate }
35840Sstevel@tonic-gate
35850Sstevel@tonic-gate if ((flag & IBDM_IBMF_PKT_DUP_RESP) ||
35860Sstevel@tonic-gate (flag & IBDM_IBMF_PKT_UNEXP_RESP)) {
35870Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm",
35880Sstevel@tonic-gate "\tprocess_incoming_mad:Dup/unexp resp : 0x%x", flag);
35890Sstevel@tonic-gate if (ibmf_free_msg(ibmf_hdl, &msg) != IBMF_SUCCESS) {
35900Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "process_incoming_mad: "
35910Sstevel@tonic-gate "IBMF free msg failed DM request drop it");
35920Sstevel@tonic-gate }
35930Sstevel@tonic-gate return;
35940Sstevel@tonic-gate }
35950Sstevel@tonic-gate
35960Sstevel@tonic-gate mutex_enter(&gid_info->gl_mutex);
35970Sstevel@tonic-gate if (gid_info->gl_pending_cmds < 1) {
35980Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm",
35990Sstevel@tonic-gate "\tprocess_incoming_mad: pending commands negative");
36000Sstevel@tonic-gate }
36010Sstevel@tonic-gate if (--gid_info->gl_pending_cmds) {
36020Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tprocess_incoming_mad: "
36030Sstevel@tonic-gate "gid_info %p pending cmds %d",
36040Sstevel@tonic-gate gid_info, gid_info->gl_pending_cmds);
36050Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
36060Sstevel@tonic-gate } else {
36076262Seota uint_t prev_state;
36080Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tprocess_incoming_mad: Probing DONE");
36096262Seota prev_state = gid_info->gl_state;
36100Sstevel@tonic-gate gid_info->gl_state = IBDM_GID_PROBING_COMPLETE;
36116262Seota if (prev_state == IBDM_SET_CLASSPORTINFO) {
36120Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm",
36136262Seota "\tprocess_incoming_mad: "
36146262Seota "Setclassportinfo for Cisco FC GW is done.");
36156262Seota gid_info->gl_flag &= ~IBDM_CISCO_PROBE;
36166262Seota gid_info->gl_flag |= IBDM_CISCO_PROBE_DONE;
36176262Seota mutex_exit(&gid_info->gl_mutex);
36186262Seota cv_broadcast(&gid_info->gl_probe_cv);
36196262Seota } else {
36206262Seota mutex_exit(&gid_info->gl_mutex);
36216262Seota ibdm_notify_newgid_iocs(gid_info);
36226262Seota mutex_enter(&ibdm.ibdm_mutex);
36236262Seota if (--ibdm.ibdm_ngid_probes_in_progress == 0) {
36246262Seota IBTF_DPRINTF_L4("ibdm",
36256262Seota "\tprocess_incoming_mad: Wakeup");
36266262Seota ibdm.ibdm_busy &= ~IBDM_PROBE_IN_PROGRESS;
36276262Seota cv_broadcast(&ibdm.ibdm_probe_cv);
36286262Seota }
36296262Seota mutex_exit(&ibdm.ibdm_mutex);
36300Sstevel@tonic-gate }
36310Sstevel@tonic-gate }
36320Sstevel@tonic-gate
36330Sstevel@tonic-gate /*
36340Sstevel@tonic-gate * Do not deallocate the IBMF packet if atleast one request
36350Sstevel@tonic-gate * is posted. IBMF packet is reused.
36360Sstevel@tonic-gate */
36370Sstevel@tonic-gate if (!(flag & IBDM_IBMF_PKT_REUSED)) {
36380Sstevel@tonic-gate if (ibmf_free_msg(ibmf_hdl, &msg) != IBMF_SUCCESS) {
36390Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "\tprocess_incoming_mad: "
36400Sstevel@tonic-gate "IBMF free msg failed DM request drop it");
36410Sstevel@tonic-gate }
36420Sstevel@tonic-gate }
36430Sstevel@tonic-gate }
36440Sstevel@tonic-gate
36450Sstevel@tonic-gate
36460Sstevel@tonic-gate /*
36470Sstevel@tonic-gate * ibdm_verify_mad_status()
36480Sstevel@tonic-gate * Verifies the MAD status
36490Sstevel@tonic-gate * Returns IBDM_SUCCESS if status is correct
36500Sstevel@tonic-gate * Returns IBDM_FAILURE for bogus MAD status
36510Sstevel@tonic-gate */
36520Sstevel@tonic-gate static int
ibdm_verify_mad_status(ib_mad_hdr_t * hdr)36530Sstevel@tonic-gate ibdm_verify_mad_status(ib_mad_hdr_t *hdr)
36540Sstevel@tonic-gate {
36550Sstevel@tonic-gate int ret = 0;
36560Sstevel@tonic-gate
36570Sstevel@tonic-gate if ((hdr->R_Method != IB_DM_DEVMGT_METHOD_GET_RESP) ||
36580Sstevel@tonic-gate (hdr->ClassVersion != IB_DM_CLASS_VERSION_1)) {
36590Sstevel@tonic-gate return (IBDM_FAILURE);
36600Sstevel@tonic-gate }
36610Sstevel@tonic-gate
36620Sstevel@tonic-gate if (b2h16(hdr->Status) == 0)
36630Sstevel@tonic-gate ret = IBDM_SUCCESS;
36640Sstevel@tonic-gate else if ((b2h16(hdr->Status) & 0x1f) == MAD_STATUS_REDIRECT_REQUIRED)
36650Sstevel@tonic-gate ret = IBDM_SUCCESS;
36660Sstevel@tonic-gate else {
36673826Shiremath IBTF_DPRINTF_L2("ibdm",
36683826Shiremath "\tverify_mad_status: Status : 0x%x", b2h16(hdr->Status));
36690Sstevel@tonic-gate ret = IBDM_FAILURE;
36700Sstevel@tonic-gate }
36710Sstevel@tonic-gate return (ret);
36720Sstevel@tonic-gate }
36730Sstevel@tonic-gate
36740Sstevel@tonic-gate
36750Sstevel@tonic-gate
36760Sstevel@tonic-gate /*
36770Sstevel@tonic-gate * ibdm_handle_redirection()
36780Sstevel@tonic-gate * Returns IBDM_SUCCESS/IBDM_FAILURE
36790Sstevel@tonic-gate */
36800Sstevel@tonic-gate static int
ibdm_handle_redirection(ibmf_msg_t * msg,ibdm_dp_gidinfo_t * gid_info,int * flag)36810Sstevel@tonic-gate ibdm_handle_redirection(ibmf_msg_t *msg,
36820Sstevel@tonic-gate ibdm_dp_gidinfo_t *gid_info, int *flag)
36830Sstevel@tonic-gate {
36840Sstevel@tonic-gate int attrmod, ioc_no, start;
36850Sstevel@tonic-gate void *data;
36860Sstevel@tonic-gate timeout_id_t *timeout_id;
36870Sstevel@tonic-gate ib_mad_hdr_t *hdr;
36880Sstevel@tonic-gate ibdm_ioc_info_t *ioc = NULL;
36890Sstevel@tonic-gate ibdm_timeout_cb_args_t *cb_args;
36906262Seota ib_mad_classportinfo_t *cpi;
36910Sstevel@tonic-gate
36920Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\thandle_redirection: Enter");
36930Sstevel@tonic-gate mutex_enter(&gid_info->gl_mutex);
36940Sstevel@tonic-gate switch (gid_info->gl_state) {
36950Sstevel@tonic-gate case IBDM_GET_IOUNITINFO:
36960Sstevel@tonic-gate cb_args = &gid_info->gl_iou_cb_args;
36970Sstevel@tonic-gate timeout_id = &gid_info->gl_timeout_id;
36980Sstevel@tonic-gate break;
36990Sstevel@tonic-gate
37000Sstevel@tonic-gate case IBDM_GET_IOC_DETAILS:
37010Sstevel@tonic-gate attrmod = IBDM_IN_IBMFMSG_ATTRMOD(msg);
37020Sstevel@tonic-gate switch (IBDM_IN_IBMFMSG_ATTR(msg)) {
37030Sstevel@tonic-gate
37040Sstevel@tonic-gate case IB_DM_ATTR_DIAG_CODE:
37050Sstevel@tonic-gate if (attrmod == 0) {
37060Sstevel@tonic-gate cb_args = &gid_info->gl_iou_cb_args;
37070Sstevel@tonic-gate timeout_id = &gid_info->gl_timeout_id;
37080Sstevel@tonic-gate break;
37090Sstevel@tonic-gate }
37100Sstevel@tonic-gate if (IBDM_IS_IOC_NUM_INVALID(attrmod, gid_info)) {
37110Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "\thandle_redirction:"
37120Sstevel@tonic-gate "IOC# Out of range %d", attrmod);
37130Sstevel@tonic-gate (*flag) |= IBDM_IBMF_PKT_UNEXP_RESP;
37140Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
37150Sstevel@tonic-gate return (IBDM_FAILURE);
37160Sstevel@tonic-gate }
37170Sstevel@tonic-gate ioc = IBDM_GIDINFO2IOCINFO(gid_info, (attrmod -1));
37180Sstevel@tonic-gate cb_args = &ioc->ioc_dc_cb_args;
37190Sstevel@tonic-gate timeout_id = &ioc->ioc_dc_timeout_id;
37200Sstevel@tonic-gate break;
37210Sstevel@tonic-gate
37220Sstevel@tonic-gate case IB_DM_ATTR_IOC_CTRL_PROFILE:
37230Sstevel@tonic-gate if (IBDM_IS_IOC_NUM_INVALID(attrmod, gid_info)) {
37240Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "\thandle_redirction:"
37250Sstevel@tonic-gate "IOC# Out of range %d", attrmod);
37260Sstevel@tonic-gate (*flag) |= IBDM_IBMF_PKT_UNEXP_RESP;
37270Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
37280Sstevel@tonic-gate return (IBDM_FAILURE);
37290Sstevel@tonic-gate }
37300Sstevel@tonic-gate ioc = IBDM_GIDINFO2IOCINFO(gid_info, (attrmod -1));
37310Sstevel@tonic-gate cb_args = &ioc->ioc_cb_args;
37320Sstevel@tonic-gate timeout_id = &ioc->ioc_timeout_id;
37330Sstevel@tonic-gate break;
37340Sstevel@tonic-gate
37350Sstevel@tonic-gate case IB_DM_ATTR_SERVICE_ENTRIES:
37360Sstevel@tonic-gate ioc_no = ((attrmod >> 16) & IBDM_16_BIT_MASK);
37370Sstevel@tonic-gate if (IBDM_IS_IOC_NUM_INVALID(ioc_no, gid_info)) {
37380Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "\thandle_redirction:"
37390Sstevel@tonic-gate "IOC# Out of range %d", ioc_no);
37400Sstevel@tonic-gate (*flag) |= IBDM_IBMF_PKT_UNEXP_RESP;
37410Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
37420Sstevel@tonic-gate return (IBDM_FAILURE);
37430Sstevel@tonic-gate }
37441093Shiremath start = (attrmod & IBDM_8_BIT_MASK);
37450Sstevel@tonic-gate ioc = IBDM_GIDINFO2IOCINFO(gid_info, (ioc_no -1));
37460Sstevel@tonic-gate if (start > ioc->ioc_profile.ioc_service_entries) {
37470Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "\thandle_redirction:"
37480Sstevel@tonic-gate " SE index Out of range %d", start);
37490Sstevel@tonic-gate (*flag) |= IBDM_IBMF_PKT_UNEXP_RESP;
37500Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
37510Sstevel@tonic-gate return (IBDM_FAILURE);
37520Sstevel@tonic-gate }
37530Sstevel@tonic-gate cb_args = &ioc->ioc_serv[start].se_cb_args;
37540Sstevel@tonic-gate timeout_id = &ioc->ioc_serv[start].se_timeout_id;
37550Sstevel@tonic-gate break;
37560Sstevel@tonic-gate
37570Sstevel@tonic-gate default:
37580Sstevel@tonic-gate /* ERROR State */
37590Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm",
37600Sstevel@tonic-gate "\thandle_redirection: wrong attribute :-(");
37610Sstevel@tonic-gate (*flag) |= IBDM_IBMF_PKT_UNEXP_RESP;
37620Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
37630Sstevel@tonic-gate return (IBDM_FAILURE);
37640Sstevel@tonic-gate }
37650Sstevel@tonic-gate break;
37660Sstevel@tonic-gate default:
37670Sstevel@tonic-gate /* ERROR State */
37680Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm",
37690Sstevel@tonic-gate "\thandle_redirection: Error state :-(");
37700Sstevel@tonic-gate (*flag) |= IBDM_IBMF_PKT_UNEXP_RESP;
37710Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
37720Sstevel@tonic-gate return (IBDM_FAILURE);
37730Sstevel@tonic-gate }
37740Sstevel@tonic-gate if ((*timeout_id) != 0) {
37750Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
37760Sstevel@tonic-gate if (untimeout(*timeout_id) == -1) {
37770Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "\thandle_redirection: "
37780Sstevel@tonic-gate "untimeout failed %x", *timeout_id);
37790Sstevel@tonic-gate } else {
37800Sstevel@tonic-gate IBTF_DPRINTF_L5("ibdm",
37810Sstevel@tonic-gate "\thandle_redirection: timeout %x", *timeout_id);
37820Sstevel@tonic-gate }
37830Sstevel@tonic-gate mutex_enter(&gid_info->gl_mutex);
37840Sstevel@tonic-gate *timeout_id = 0;
37850Sstevel@tonic-gate }
37860Sstevel@tonic-gate
37870Sstevel@tonic-gate data = msg->im_msgbufs_recv.im_bufs_cl_data;
37886262Seota cpi = (ib_mad_classportinfo_t *)data;
37890Sstevel@tonic-gate
37900Sstevel@tonic-gate gid_info->gl_resp_timeout =
37916262Seota (b2h32(cpi->RespTimeValue) & 0x1F);
37920Sstevel@tonic-gate
37930Sstevel@tonic-gate gid_info->gl_redirected = B_TRUE;
37940Sstevel@tonic-gate gid_info->gl_redirect_dlid = b2h16(cpi->RedirectLID);
37950Sstevel@tonic-gate gid_info->gl_redirect_QP = (b2h32(cpi->RedirectQP) & 0xffffff);
37960Sstevel@tonic-gate gid_info->gl_redirect_pkey = b2h16(cpi->RedirectP_Key);
37970Sstevel@tonic-gate gid_info->gl_redirect_qkey = b2h32(cpi->RedirectQ_Key);
37980Sstevel@tonic-gate gid_info->gl_redirectGID_hi = b2h64(cpi->RedirectGID_hi);
37990Sstevel@tonic-gate gid_info->gl_redirectGID_lo = b2h64(cpi->RedirectGID_lo);
38006699Seota gid_info->gl_redirectSL = cpi->RedirectSL;
38010Sstevel@tonic-gate
38020Sstevel@tonic-gate if (gid_info->gl_redirect_dlid != 0) {
38030Sstevel@tonic-gate msg->im_local_addr.ia_remote_lid =
38046262Seota gid_info->gl_redirect_dlid;
38050Sstevel@tonic-gate }
38061093Shiremath ibdm_bump_transactionID(gid_info);
38070Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
38080Sstevel@tonic-gate
38096699Seota _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*msg, *hdr))
38100Sstevel@tonic-gate ibdm_alloc_send_buffers(msg);
38110Sstevel@tonic-gate
38120Sstevel@tonic-gate hdr = IBDM_OUT_IBMFMSG_MADHDR(msg);
38130Sstevel@tonic-gate hdr->BaseVersion = MAD_CLASS_BASE_VERS_1;
38140Sstevel@tonic-gate hdr->MgmtClass = MAD_MGMT_CLASS_DEV_MGT;
38150Sstevel@tonic-gate hdr->ClassVersion = IB_DM_CLASS_VERSION_1;
38160Sstevel@tonic-gate hdr->R_Method = IB_DM_DEVMGT_METHOD_GET;
38170Sstevel@tonic-gate hdr->Status = 0;
38180Sstevel@tonic-gate hdr->TransactionID = h2b64(gid_info->gl_transactionID);
38190Sstevel@tonic-gate hdr->AttributeID =
38206262Seota msg->im_msgbufs_recv.im_bufs_mad_hdr->AttributeID;
38210Sstevel@tonic-gate hdr->AttributeModifier =
38226262Seota msg->im_msgbufs_recv.im_bufs_mad_hdr->AttributeModifier;
38236699Seota _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*msg, *hdr))
38240Sstevel@tonic-gate
38250Sstevel@tonic-gate msg->im_local_addr.ia_remote_qno = gid_info->gl_redirect_QP;
38260Sstevel@tonic-gate msg->im_local_addr.ia_p_key = gid_info->gl_redirect_pkey;
38270Sstevel@tonic-gate msg->im_local_addr.ia_q_key = gid_info->gl_redirect_qkey;
38286699Seota msg->im_local_addr.ia_service_level = gid_info->gl_redirectSL;
38296699Seota
38306699Seota mutex_enter(&gid_info->gl_mutex);
38310Sstevel@tonic-gate *timeout_id = timeout(ibdm_pkt_timeout_hdlr,
38320Sstevel@tonic-gate cb_args, IBDM_TIMEOUT_VALUE(ibdm_dft_timeout));
38336699Seota mutex_exit(&gid_info->gl_mutex);
38340Sstevel@tonic-gate
38350Sstevel@tonic-gate IBTF_DPRINTF_L5("ibdm", "\thandle_redirect:"
38360Sstevel@tonic-gate "timeout %x", *timeout_id);
38370Sstevel@tonic-gate
38380Sstevel@tonic-gate if (ibmf_msg_transport(gid_info->gl_ibmf_hdl, gid_info->gl_qp_hdl,
38390Sstevel@tonic-gate msg, NULL, ibdm_ibmf_send_cb, cb_args, 0) != IBMF_SUCCESS) {
38400Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\thandle_redirection:"
38410Sstevel@tonic-gate "message transport failed");
38420Sstevel@tonic-gate ibdm_ibmf_send_cb(gid_info->gl_ibmf_hdl, msg, cb_args);
38430Sstevel@tonic-gate }
38440Sstevel@tonic-gate (*flag) |= IBDM_IBMF_PKT_REUSED;
38450Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\thandle_redirection: Exit");
38460Sstevel@tonic-gate return (IBDM_SUCCESS);
38470Sstevel@tonic-gate }
38480Sstevel@tonic-gate
38490Sstevel@tonic-gate
38500Sstevel@tonic-gate /*
38510Sstevel@tonic-gate * ibdm_pkt_timeout_hdlr
38520Sstevel@tonic-gate * This timeout handler is registed for every IBMF packet that is
38530Sstevel@tonic-gate * sent through the IBMF. It gets called when no response is received
38540Sstevel@tonic-gate * within the specified time for the packet. No retries for the failed
38550Sstevel@tonic-gate * commands currently. Drops the failed IBMF packet and update the
38560Sstevel@tonic-gate * pending list commands.
38570Sstevel@tonic-gate */
38580Sstevel@tonic-gate static void
ibdm_pkt_timeout_hdlr(void * arg)38590Sstevel@tonic-gate ibdm_pkt_timeout_hdlr(void *arg)
38600Sstevel@tonic-gate {
38610Sstevel@tonic-gate ibdm_iou_info_t *iou;
38620Sstevel@tonic-gate ibdm_ioc_info_t *ioc;
38630Sstevel@tonic-gate ibdm_timeout_cb_args_t *cb_args = arg;
38640Sstevel@tonic-gate ibdm_dp_gidinfo_t *gid_info;
38650Sstevel@tonic-gate int srv_ent;
38661689Spramodbg uint_t new_gl_state;
38670Sstevel@tonic-gate
38680Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "\tpkt_timeout_hdlr: gid_info: %p "
38690Sstevel@tonic-gate "rtype 0x%x iocidx 0x%x srvidx %d", cb_args->cb_gid_info,
38700Sstevel@tonic-gate cb_args->cb_req_type, cb_args->cb_ioc_num,
38710Sstevel@tonic-gate cb_args->cb_srvents_start);
38720Sstevel@tonic-gate
38730Sstevel@tonic-gate gid_info = cb_args->cb_gid_info;
38740Sstevel@tonic-gate mutex_enter(&gid_info->gl_mutex);
38750Sstevel@tonic-gate
38760Sstevel@tonic-gate if ((gid_info->gl_state == IBDM_GID_PROBING_COMPLETE) ||
38770Sstevel@tonic-gate (cb_args->cb_req_type == 0)) {
38780Sstevel@tonic-gate
38790Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "\tpkt_timeout_hdlr: req completed"
38800Sstevel@tonic-gate "rtype 0x%x iocidx 0x%x srvidx %d", cb_args->cb_req_type,
38810Sstevel@tonic-gate cb_args->cb_ioc_num, cb_args->cb_srvents_start);
38820Sstevel@tonic-gate
38830Sstevel@tonic-gate if (gid_info->gl_timeout_id)
38840Sstevel@tonic-gate gid_info->gl_timeout_id = 0;
38850Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
38860Sstevel@tonic-gate return;
38870Sstevel@tonic-gate }
38880Sstevel@tonic-gate if (cb_args->cb_retry_count) {
38890Sstevel@tonic-gate cb_args->cb_retry_count--;
38906699Seota /*
38916699Seota * A new timeout_id is set inside ibdm_retry_command().
38926699Seota * When the function returns an error, the timeout_id
38936699Seota * is reset (to zero) in the switch statement below.
38946699Seota */
38950Sstevel@tonic-gate if (ibdm_retry_command(cb_args) == IBDM_SUCCESS) {
38960Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
38970Sstevel@tonic-gate return;
38980Sstevel@tonic-gate }
38990Sstevel@tonic-gate cb_args->cb_retry_count = 0;
39000Sstevel@tonic-gate }
39010Sstevel@tonic-gate
39020Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "\tpkt_timeout_hdlr: command failed: gid %p"
39030Sstevel@tonic-gate " rtype 0x%x iocidx 0x%x srvidx %d", cb_args->cb_gid_info,
39040Sstevel@tonic-gate cb_args->cb_req_type, cb_args->cb_ioc_num,
39050Sstevel@tonic-gate cb_args->cb_srvents_start);
39060Sstevel@tonic-gate
39070Sstevel@tonic-gate switch (cb_args->cb_req_type) {
39080Sstevel@tonic-gate
39090Sstevel@tonic-gate case IBDM_REQ_TYPE_CLASSPORTINFO:
39100Sstevel@tonic-gate case IBDM_REQ_TYPE_IOUINFO:
39111689Spramodbg new_gl_state = IBDM_GID_PROBING_FAILED;
39120Sstevel@tonic-gate if (gid_info->gl_timeout_id)
39130Sstevel@tonic-gate gid_info->gl_timeout_id = 0;
39140Sstevel@tonic-gate break;
39156699Seota
39160Sstevel@tonic-gate case IBDM_REQ_TYPE_IOCINFO:
39176699Seota new_gl_state = IBDM_GID_PROBING_COMPLETE;
39180Sstevel@tonic-gate iou = gid_info->gl_iou;
39190Sstevel@tonic-gate ioc = &iou->iou_ioc_info[cb_args->cb_ioc_num];
39200Sstevel@tonic-gate ioc->ioc_state = IBDM_IOC_STATE_PROBE_FAILED;
39210Sstevel@tonic-gate if (ioc->ioc_timeout_id)
39220Sstevel@tonic-gate ioc->ioc_timeout_id = 0;
39230Sstevel@tonic-gate break;
39246699Seota
39250Sstevel@tonic-gate case IBDM_REQ_TYPE_SRVENTS:
39266699Seota new_gl_state = IBDM_GID_PROBING_COMPLETE;
39270Sstevel@tonic-gate iou = gid_info->gl_iou;
39280Sstevel@tonic-gate ioc = &iou->iou_ioc_info[cb_args->cb_ioc_num];
39290Sstevel@tonic-gate ioc->ioc_state = IBDM_IOC_STATE_PROBE_FAILED;
39300Sstevel@tonic-gate srv_ent = cb_args->cb_srvents_start;
39310Sstevel@tonic-gate if (ioc->ioc_serv[srv_ent].se_timeout_id)
39320Sstevel@tonic-gate ioc->ioc_serv[srv_ent].se_timeout_id = 0;
39330Sstevel@tonic-gate break;
39346699Seota
39350Sstevel@tonic-gate case IBDM_REQ_TYPE_IOU_DIAGCODE:
39366699Seota new_gl_state = IBDM_GID_PROBING_COMPLETE;
39370Sstevel@tonic-gate iou = gid_info->gl_iou;
39380Sstevel@tonic-gate iou->iou_dc_valid = B_FALSE;
39390Sstevel@tonic-gate if (gid_info->gl_timeout_id)
39400Sstevel@tonic-gate gid_info->gl_timeout_id = 0;
39410Sstevel@tonic-gate break;
39426699Seota
39430Sstevel@tonic-gate case IBDM_REQ_TYPE_IOC_DIAGCODE:
39446699Seota new_gl_state = IBDM_GID_PROBING_COMPLETE;
39450Sstevel@tonic-gate iou = gid_info->gl_iou;
39460Sstevel@tonic-gate ioc = &iou->iou_ioc_info[cb_args->cb_ioc_num];
39470Sstevel@tonic-gate ioc->ioc_dc_valid = B_FALSE;
39480Sstevel@tonic-gate if (ioc->ioc_dc_timeout_id)
39490Sstevel@tonic-gate ioc->ioc_dc_timeout_id = 0;
39500Sstevel@tonic-gate break;
39516699Seota
39526262Seota default: /* ERROR State */
39536262Seota new_gl_state = IBDM_GID_PROBING_FAILED;
39546262Seota if (gid_info->gl_timeout_id)
39556262Seota gid_info->gl_timeout_id = 0;
39566699Seota IBTF_DPRINTF_L2("ibdm",
39576699Seota "\tpkt_timeout_hdlr: wrong request type.");
39586262Seota break;
39590Sstevel@tonic-gate }
39606699Seota
39616699Seota --gid_info->gl_pending_cmds; /* decrease the counter */
39626699Seota
39636699Seota if (gid_info->gl_pending_cmds == 0) {
39641689Spramodbg gid_info->gl_state = new_gl_state;
39650Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
39666699Seota /*
39676699Seota * Delete this gid_info if the gid probe fails.
39686699Seota */
39696699Seota if (new_gl_state == IBDM_GID_PROBING_FAILED) {
39706699Seota ibdm_delete_glhca_list(gid_info);
39716699Seota }
39720Sstevel@tonic-gate ibdm_notify_newgid_iocs(gid_info);
39730Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
39740Sstevel@tonic-gate if (--ibdm.ibdm_ngid_probes_in_progress == 0) {
39750Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tpkt_timeout_hdlr: Wakeup");
39760Sstevel@tonic-gate ibdm.ibdm_busy &= ~IBDM_PROBE_IN_PROGRESS;
39770Sstevel@tonic-gate cv_broadcast(&ibdm.ibdm_probe_cv);
39780Sstevel@tonic-gate }
39790Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
39806699Seota } else {
39816699Seota /*
39826699Seota * Reset gl_pending_cmd if the extra timeout happens since
39836699Seota * gl_pending_cmd becomes negative as a result.
39846699Seota */
39856699Seota if (gid_info->gl_pending_cmds < 0) {
39866699Seota gid_info->gl_pending_cmds = 0;
39876699Seota IBTF_DPRINTF_L2("ibdm",
39886699Seota "\tpkt_timeout_hdlr: extra timeout request."
39896699Seota " reset gl_pending_cmds");
39906699Seota }
39910Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
39926699Seota /*
39936699Seota * Delete this gid_info if the gid probe fails.
39946699Seota */
39956699Seota if (new_gl_state == IBDM_GID_PROBING_FAILED) {
39966699Seota ibdm_delete_glhca_list(gid_info);
39976699Seota }
39986699Seota }
39990Sstevel@tonic-gate }
40000Sstevel@tonic-gate
40010Sstevel@tonic-gate
40020Sstevel@tonic-gate /*
40030Sstevel@tonic-gate * ibdm_retry_command()
40040Sstevel@tonic-gate * Retries the failed command.
40050Sstevel@tonic-gate * Returns IBDM_FAILURE/IBDM_SUCCESS
40060Sstevel@tonic-gate */
40070Sstevel@tonic-gate static int
ibdm_retry_command(ibdm_timeout_cb_args_t * cb_args)40080Sstevel@tonic-gate ibdm_retry_command(ibdm_timeout_cb_args_t *cb_args)
40090Sstevel@tonic-gate {
40103826Shiremath int ret;
40110Sstevel@tonic-gate ibmf_msg_t *msg;
40120Sstevel@tonic-gate ib_mad_hdr_t *hdr;
40130Sstevel@tonic-gate ibdm_dp_gidinfo_t *gid_info = cb_args->cb_gid_info;
40140Sstevel@tonic-gate timeout_id_t *timeout_id;
40150Sstevel@tonic-gate ibdm_ioc_info_t *ioc;
40160Sstevel@tonic-gate int ioc_no;
40176699Seota ASSERT(MUTEX_HELD(&gid_info->gl_mutex));
40180Sstevel@tonic-gate
40190Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "\tretry_command: gid_info: %p "
40200Sstevel@tonic-gate "rtype 0x%x iocidx 0x%x srvidx %d", cb_args->cb_gid_info,
40210Sstevel@tonic-gate cb_args->cb_req_type, cb_args->cb_ioc_num,
40220Sstevel@tonic-gate cb_args->cb_srvents_start);
40230Sstevel@tonic-gate
40240Sstevel@tonic-gate ret = ibmf_alloc_msg(gid_info->gl_ibmf_hdl, IBMF_ALLOC_NOSLEEP, &msg);
40250Sstevel@tonic-gate
40260Sstevel@tonic-gate
40270Sstevel@tonic-gate /*
40280Sstevel@tonic-gate * Reset the gid if alloc_msg failed with BAD_HANDLE
40290Sstevel@tonic-gate * ibdm_reset_gidinfo reinits the gid_info
40300Sstevel@tonic-gate */
40310Sstevel@tonic-gate if (ret == IBMF_BAD_HANDLE) {
40320Sstevel@tonic-gate IBTF_DPRINTF_L3(ibdm_string, "\tretry_command: gid %p hdl bad",
40330Sstevel@tonic-gate gid_info);
40340Sstevel@tonic-gate
40350Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
40360Sstevel@tonic-gate ibdm_reset_gidinfo(gid_info);
40370Sstevel@tonic-gate mutex_enter(&gid_info->gl_mutex);
40380Sstevel@tonic-gate
40390Sstevel@tonic-gate /* Retry alloc */
40400Sstevel@tonic-gate ret = ibmf_alloc_msg(gid_info->gl_ibmf_hdl, IBMF_ALLOC_NOSLEEP,
40410Sstevel@tonic-gate &msg);
40420Sstevel@tonic-gate }
40430Sstevel@tonic-gate
40440Sstevel@tonic-gate if (ret != IBDM_SUCCESS) {
40450Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "\tretry_command: alloc failed: %p "
40460Sstevel@tonic-gate "rtype 0x%x iocidx 0x%x srvidx %d", cb_args->cb_gid_info,
40470Sstevel@tonic-gate cb_args->cb_req_type, cb_args->cb_ioc_num,
40480Sstevel@tonic-gate cb_args->cb_srvents_start);
40490Sstevel@tonic-gate return (IBDM_FAILURE);
40500Sstevel@tonic-gate }
40510Sstevel@tonic-gate
40526699Seota _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*msg))
40530Sstevel@tonic-gate ibdm_alloc_send_buffers(msg);
40546699Seota _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*msg))
40550Sstevel@tonic-gate
40561093Shiremath ibdm_bump_transactionID(gid_info);
40571093Shiremath
40580Sstevel@tonic-gate msg->im_local_addr.ia_local_lid = gid_info->gl_slid;
40590Sstevel@tonic-gate msg->im_local_addr.ia_remote_lid = gid_info->gl_dlid;
40600Sstevel@tonic-gate if (gid_info->gl_redirected == B_TRUE) {
40610Sstevel@tonic-gate if (gid_info->gl_redirect_dlid != 0) {
40620Sstevel@tonic-gate msg->im_local_addr.ia_remote_lid =
40636262Seota gid_info->gl_redirect_dlid;
40640Sstevel@tonic-gate }
40650Sstevel@tonic-gate msg->im_local_addr.ia_remote_qno = gid_info->gl_redirect_QP;
40660Sstevel@tonic-gate msg->im_local_addr.ia_p_key = gid_info->gl_redirect_pkey;
40670Sstevel@tonic-gate msg->im_local_addr.ia_q_key = gid_info->gl_redirect_qkey;
40686699Seota msg->im_local_addr.ia_service_level = gid_info->gl_redirectSL;
40690Sstevel@tonic-gate } else {
40700Sstevel@tonic-gate msg->im_local_addr.ia_remote_qno = 1;
40710Sstevel@tonic-gate msg->im_local_addr.ia_p_key = gid_info->gl_p_key;
40720Sstevel@tonic-gate msg->im_local_addr.ia_q_key = IB_GSI_QKEY;
40736699Seota msg->im_local_addr.ia_service_level = gid_info->gl_SL;
40740Sstevel@tonic-gate }
40750Sstevel@tonic-gate hdr = IBDM_OUT_IBMFMSG_MADHDR(msg);
40766699Seota _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*hdr))
40770Sstevel@tonic-gate hdr->BaseVersion = MAD_CLASS_BASE_VERS_1;
40780Sstevel@tonic-gate hdr->MgmtClass = MAD_MGMT_CLASS_DEV_MGT;
40790Sstevel@tonic-gate hdr->ClassVersion = IB_DM_CLASS_VERSION_1;
40800Sstevel@tonic-gate hdr->R_Method = IB_DM_DEVMGT_METHOD_GET;
40810Sstevel@tonic-gate hdr->Status = 0;
40820Sstevel@tonic-gate hdr->TransactionID = h2b64(gid_info->gl_transactionID);
40830Sstevel@tonic-gate
40840Sstevel@tonic-gate switch (cb_args->cb_req_type) {
40850Sstevel@tonic-gate case IBDM_REQ_TYPE_CLASSPORTINFO:
40860Sstevel@tonic-gate hdr->AttributeID = h2b16(IB_DM_ATTR_CLASSPORTINFO);
40870Sstevel@tonic-gate hdr->AttributeModifier = 0;
40880Sstevel@tonic-gate timeout_id = &gid_info->gl_timeout_id;
40890Sstevel@tonic-gate break;
40900Sstevel@tonic-gate case IBDM_REQ_TYPE_IOUINFO:
40910Sstevel@tonic-gate hdr->AttributeID = h2b16(IB_DM_ATTR_IO_UNITINFO);
40920Sstevel@tonic-gate hdr->AttributeModifier = 0;
40930Sstevel@tonic-gate timeout_id = &gid_info->gl_timeout_id;
40940Sstevel@tonic-gate break;
40950Sstevel@tonic-gate case IBDM_REQ_TYPE_IOCINFO:
40960Sstevel@tonic-gate hdr->AttributeID = h2b16(IB_DM_ATTR_IOC_CTRL_PROFILE);
40970Sstevel@tonic-gate hdr->AttributeModifier = h2b32(cb_args->cb_ioc_num + 1);
40980Sstevel@tonic-gate ioc = IBDM_GIDINFO2IOCINFO(gid_info, cb_args->cb_ioc_num);
40990Sstevel@tonic-gate timeout_id = &ioc->ioc_timeout_id;
41000Sstevel@tonic-gate break;
41010Sstevel@tonic-gate case IBDM_REQ_TYPE_SRVENTS:
41020Sstevel@tonic-gate hdr->AttributeID = h2b16(IB_DM_ATTR_SERVICE_ENTRIES);
41031093Shiremath ibdm_fill_srv_attr_mod(hdr, cb_args);
41040Sstevel@tonic-gate ioc = IBDM_GIDINFO2IOCINFO(gid_info, cb_args->cb_ioc_num);
41050Sstevel@tonic-gate timeout_id =
41060Sstevel@tonic-gate &ioc->ioc_serv[cb_args->cb_srvents_start].se_timeout_id;
41070Sstevel@tonic-gate break;
41080Sstevel@tonic-gate case IBDM_REQ_TYPE_IOU_DIAGCODE:
41090Sstevel@tonic-gate hdr->AttributeID = h2b16(IB_DM_ATTR_DIAG_CODE);
41100Sstevel@tonic-gate hdr->AttributeModifier = 0;
41110Sstevel@tonic-gate timeout_id = &gid_info->gl_timeout_id;
41120Sstevel@tonic-gate break;
41130Sstevel@tonic-gate case IBDM_REQ_TYPE_IOC_DIAGCODE:
41140Sstevel@tonic-gate hdr->AttributeID = h2b16(IB_DM_ATTR_DIAG_CODE);
41150Sstevel@tonic-gate hdr->AttributeModifier = h2b32(cb_args->cb_ioc_num + 1);
41160Sstevel@tonic-gate ioc_no = cb_args->cb_ioc_num;
41170Sstevel@tonic-gate ioc = &gid_info->gl_iou->iou_ioc_info[ioc_no];
41180Sstevel@tonic-gate timeout_id = &ioc->ioc_dc_timeout_id;
41190Sstevel@tonic-gate break;
41200Sstevel@tonic-gate }
41216699Seota _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*hdr))
41220Sstevel@tonic-gate
41230Sstevel@tonic-gate *timeout_id = timeout(ibdm_pkt_timeout_hdlr,
41240Sstevel@tonic-gate cb_args, IBDM_TIMEOUT_VALUE(ibdm_dft_timeout));
41250Sstevel@tonic-gate
41266699Seota mutex_exit(&gid_info->gl_mutex);
41276699Seota
41280Sstevel@tonic-gate IBTF_DPRINTF_L5("ibdm", "\tretry_command: %p,%x,%d,%d:"
41290Sstevel@tonic-gate "timeout %x", cb_args->cb_req_type, cb_args->cb_ioc_num,
41300Sstevel@tonic-gate cb_args->cb_srvents_start, *timeout_id);
41310Sstevel@tonic-gate
41323826Shiremath if (ibmf_msg_transport(gid_info->gl_ibmf_hdl,
41330Sstevel@tonic-gate gid_info->gl_qp_hdl, msg, NULL, ibdm_ibmf_send_cb,
41343826Shiremath cb_args, 0) != IBMF_SUCCESS) {
41350Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "\tretry_command: send failed: %p "
41360Sstevel@tonic-gate "rtype 0x%x iocidx 0x%x srvidx %d", cb_args->cb_gid_info,
41370Sstevel@tonic-gate cb_args->cb_req_type, cb_args->cb_ioc_num,
41380Sstevel@tonic-gate cb_args->cb_srvents_start);
41390Sstevel@tonic-gate ibdm_ibmf_send_cb(gid_info->gl_ibmf_hdl, msg, cb_args);
41400Sstevel@tonic-gate }
41410Sstevel@tonic-gate mutex_enter(&gid_info->gl_mutex);
41423826Shiremath return (IBDM_SUCCESS);
41430Sstevel@tonic-gate }
41440Sstevel@tonic-gate
41450Sstevel@tonic-gate
41460Sstevel@tonic-gate /*
41470Sstevel@tonic-gate * ibdm_update_ioc_port_gidlist()
41480Sstevel@tonic-gate */
41490Sstevel@tonic-gate static void
ibdm_update_ioc_port_gidlist(ibdm_ioc_info_t * dest,ibdm_dp_gidinfo_t * gid_info)41500Sstevel@tonic-gate ibdm_update_ioc_port_gidlist(ibdm_ioc_info_t *dest,
41510Sstevel@tonic-gate ibdm_dp_gidinfo_t *gid_info)
41520Sstevel@tonic-gate {
41530Sstevel@tonic-gate int ii, ngid_ents;
41540Sstevel@tonic-gate ibdm_gid_t *tmp;
41550Sstevel@tonic-gate ibdm_hca_list_t *gid_hca_head, *temp;
41560Sstevel@tonic-gate ibdm_hca_list_t *ioc_head = NULL;
41576262Seota ASSERT(MUTEX_HELD(&gid_info->gl_mutex));
41580Sstevel@tonic-gate
41590Sstevel@tonic-gate IBTF_DPRINTF_L5("ibdm", "\tupdate_ioc_port_gidlist: Enter");
41600Sstevel@tonic-gate
41610Sstevel@tonic-gate ngid_ents = gid_info->gl_ngids;
41620Sstevel@tonic-gate dest->ioc_nportgids = ngid_ents;
41630Sstevel@tonic-gate dest->ioc_gid_list = kmem_zalloc(sizeof (ibdm_gid_t) *
41640Sstevel@tonic-gate ngid_ents, KM_SLEEP);
41650Sstevel@tonic-gate tmp = gid_info->gl_gid;
41660Sstevel@tonic-gate for (ii = 0; (ii < ngid_ents) && (tmp); ii++) {
41670Sstevel@tonic-gate dest->ioc_gid_list[ii].gid_dgid_hi = tmp->gid_dgid_hi;
41680Sstevel@tonic-gate dest->ioc_gid_list[ii].gid_dgid_lo = tmp->gid_dgid_lo;
41690Sstevel@tonic-gate tmp = tmp->gid_next;
41700Sstevel@tonic-gate }
41710Sstevel@tonic-gate
41720Sstevel@tonic-gate gid_hca_head = gid_info->gl_hca_list;
41730Sstevel@tonic-gate while (gid_hca_head) {
41740Sstevel@tonic-gate temp = ibdm_dup_hca_attr(gid_hca_head);
41750Sstevel@tonic-gate temp->hl_next = ioc_head;
41760Sstevel@tonic-gate ioc_head = temp;
41770Sstevel@tonic-gate gid_hca_head = gid_hca_head->hl_next;
41780Sstevel@tonic-gate }
41790Sstevel@tonic-gate dest->ioc_hca_list = ioc_head;
41800Sstevel@tonic-gate }
41810Sstevel@tonic-gate
41820Sstevel@tonic-gate
41830Sstevel@tonic-gate /*
41840Sstevel@tonic-gate * ibdm_alloc_send_buffers()
41856262Seota * Allocates memory for the IBMF send buffer to send and/or receive
41866262Seota * the Device Management MAD packet.
41870Sstevel@tonic-gate */
41880Sstevel@tonic-gate static void
ibdm_alloc_send_buffers(ibmf_msg_t * msgp)41890Sstevel@tonic-gate ibdm_alloc_send_buffers(ibmf_msg_t *msgp)
41900Sstevel@tonic-gate {
41910Sstevel@tonic-gate msgp->im_msgbufs_send.im_bufs_mad_hdr =
41920Sstevel@tonic-gate kmem_zalloc(IBDM_MAD_SIZE, KM_SLEEP);
41936262Seota
41946262Seota msgp->im_msgbufs_send.im_bufs_cl_hdr = (uchar_t *)
41950Sstevel@tonic-gate msgp->im_msgbufs_send.im_bufs_mad_hdr + sizeof (ib_mad_hdr_t);
41966262Seota msgp->im_msgbufs_send.im_bufs_cl_hdr_len = IBDM_DM_MAD_HDR_SZ;
41976262Seota
41986262Seota msgp->im_msgbufs_send.im_bufs_cl_data =
41996262Seota ((char *)msgp->im_msgbufs_send.im_bufs_cl_hdr + IBDM_DM_MAD_HDR_SZ);
42000Sstevel@tonic-gate msgp->im_msgbufs_send.im_bufs_cl_data_len =
42016262Seota IBDM_MAD_SIZE - sizeof (ib_mad_hdr_t) - IBDM_DM_MAD_HDR_SZ;
42020Sstevel@tonic-gate }
42030Sstevel@tonic-gate
42040Sstevel@tonic-gate
42050Sstevel@tonic-gate /*
42060Sstevel@tonic-gate * ibdm_alloc_send_buffers()
42070Sstevel@tonic-gate * De-allocates memory for the IBMF send buffer
42080Sstevel@tonic-gate */
42090Sstevel@tonic-gate static void
ibdm_free_send_buffers(ibmf_msg_t * msgp)42100Sstevel@tonic-gate ibdm_free_send_buffers(ibmf_msg_t *msgp)
42110Sstevel@tonic-gate {
42120Sstevel@tonic-gate if (msgp->im_msgbufs_send.im_bufs_mad_hdr != NULL)
42130Sstevel@tonic-gate kmem_free(msgp->im_msgbufs_send.im_bufs_mad_hdr, IBDM_MAD_SIZE);
42140Sstevel@tonic-gate }
42150Sstevel@tonic-gate
42160Sstevel@tonic-gate /*
42170Sstevel@tonic-gate * ibdm_probe_ioc()
42180Sstevel@tonic-gate * 1. Gets the node records for the port GUID. This detects all the port
42190Sstevel@tonic-gate * to the IOU.
42200Sstevel@tonic-gate * 2. Selectively probes all the IOC, given it's node GUID
42210Sstevel@tonic-gate * 3. In case of reprobe, only the IOC to be reprobed is send the IOC
42220Sstevel@tonic-gate * Controller Profile asynchronously
42230Sstevel@tonic-gate */
42240Sstevel@tonic-gate /*ARGSUSED*/
42250Sstevel@tonic-gate static void
ibdm_probe_ioc(ib_guid_t nodeguid,ib_guid_t ioc_guid,int reprobe_flag)42260Sstevel@tonic-gate ibdm_probe_ioc(ib_guid_t nodeguid, ib_guid_t ioc_guid, int reprobe_flag)
42270Sstevel@tonic-gate {
42280Sstevel@tonic-gate int ii, nrecords;
42290Sstevel@tonic-gate size_t nr_len = 0, pi_len = 0;
42300Sstevel@tonic-gate ib_gid_t sgid, dgid;
42310Sstevel@tonic-gate ibdm_hca_list_t *hca_list = NULL;
42320Sstevel@tonic-gate sa_node_record_t *nr, *tmp;
42330Sstevel@tonic-gate ibdm_port_attr_t *port = NULL;
42340Sstevel@tonic-gate ibdm_dp_gidinfo_t *reprobe_gid, *new_gid, *node_gid;
42350Sstevel@tonic-gate ibdm_dp_gidinfo_t *temp_gidinfo;
42360Sstevel@tonic-gate ibdm_gid_t *temp_gid;
42370Sstevel@tonic-gate sa_portinfo_record_t *pi;
42380Sstevel@tonic-gate
42393826Shiremath IBTF_DPRINTF_L4("ibdm", "\tprobe_ioc(%llx, %llx, %x): Begin",
42400Sstevel@tonic-gate nodeguid, ioc_guid, reprobe_flag);
42410Sstevel@tonic-gate
42420Sstevel@tonic-gate /* Rescan the GID list for any removed GIDs for reprobe */
42430Sstevel@tonic-gate if (reprobe_flag)
42440Sstevel@tonic-gate ibdm_rescan_gidlist(&ioc_guid);
42450Sstevel@tonic-gate
42460Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_hl_mutex);
42470Sstevel@tonic-gate for (ibdm_get_next_port(&hca_list, &port, 1); port;
42480Sstevel@tonic-gate ibdm_get_next_port(&hca_list, &port, 1)) {
42490Sstevel@tonic-gate reprobe_gid = new_gid = node_gid = NULL;
42500Sstevel@tonic-gate
42510Sstevel@tonic-gate nr = ibdm_get_node_records(port->pa_sa_hdl, &nr_len, nodeguid);
42520Sstevel@tonic-gate if (nr == NULL) {
42530Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tprobe_ioc: no records");
42540Sstevel@tonic-gate continue;
42550Sstevel@tonic-gate }
42560Sstevel@tonic-gate nrecords = (nr_len / sizeof (sa_node_record_t));
42570Sstevel@tonic-gate for (tmp = nr, ii = 0; (ii < nrecords); ii++, tmp++) {
42586262Seota if ((pi = ibdm_get_portinfo(
42596262Seota port->pa_sa_hdl, &pi_len, tmp->LID)) == NULL) {
42606262Seota IBTF_DPRINTF_L4("ibdm",
42616262Seota "\tibdm_get_portinfo: no portinfo recs");
42626262Seota continue;
42636262Seota }
42646262Seota
42656262Seota /*
42666262Seota * If Device Management is not supported on
42676262Seota * this port, skip the rest.
42686262Seota */
42696262Seota if (!(pi->PortInfo.CapabilityMask &
42700Sstevel@tonic-gate SM_CAP_MASK_IS_DM_SUPPD)) {
42716262Seota kmem_free(pi, pi_len);
42726262Seota continue;
42736262Seota }
42746262Seota
42756262Seota /*
42766262Seota * For reprobes: Check if GID, already in
42776262Seota * the list. If so, set the state to SKIPPED
42786262Seota */
42796262Seota if (((temp_gidinfo = ibdm_find_gid(nodeguid,
42806262Seota tmp->NodeInfo.PortGUID)) != NULL) &&
42816262Seota temp_gidinfo->gl_state ==
42826262Seota IBDM_GID_PROBING_COMPLETE) {
42836262Seota ASSERT(reprobe_gid == NULL);
42846262Seota ibdm_addto_glhcalist(temp_gidinfo,
42856262Seota hca_list);
42866262Seota reprobe_gid = temp_gidinfo;
42876262Seota kmem_free(pi, pi_len);
42886262Seota continue;
42896262Seota } else if (temp_gidinfo != NULL) {
42900Sstevel@tonic-gate kmem_free(pi, pi_len);
42916262Seota ibdm_addto_glhcalist(temp_gidinfo,
42926262Seota hca_list);
42936262Seota continue;
42940Sstevel@tonic-gate }
42956262Seota
42966262Seota IBTF_DPRINTF_L4("ibdm", "\tprobe_ioc : "
42976262Seota "create_gid : prefix %llx, guid %llx\n",
42986262Seota pi->PortInfo.GidPrefix,
42996262Seota tmp->NodeInfo.PortGUID);
43006262Seota
43016262Seota sgid.gid_prefix = port->pa_sn_prefix;
43026262Seota sgid.gid_guid = port->pa_port_guid;
43036262Seota dgid.gid_prefix = pi->PortInfo.GidPrefix;
43046262Seota dgid.gid_guid = tmp->NodeInfo.PortGUID;
43056262Seota new_gid = ibdm_create_gid_info(port, sgid,
43066262Seota dgid);
43076262Seota if (new_gid == NULL) {
43086262Seota IBTF_DPRINTF_L2("ibdm", "\tprobe_ioc: "
43096262Seota "create_gid_info failed\n");
43106262Seota kmem_free(pi, pi_len);
43116262Seota continue;
43126262Seota }
43136262Seota if (node_gid == NULL) {
43146262Seota node_gid = new_gid;
43156262Seota ibdm_add_to_gl_gid(node_gid, node_gid);
43166262Seota } else {
43176262Seota IBTF_DPRINTF_L4("ibdm",
43186262Seota "\tprobe_ioc: new gid");
43196262Seota temp_gid = kmem_zalloc(
43206262Seota sizeof (ibdm_gid_t), KM_SLEEP);
43216262Seota temp_gid->gid_dgid_hi =
43226262Seota new_gid->gl_dgid_hi;
43236262Seota temp_gid->gid_dgid_lo =
43246262Seota new_gid->gl_dgid_lo;
43256262Seota temp_gid->gid_next = node_gid->gl_gid;
43266262Seota node_gid->gl_gid = temp_gid;
43276262Seota node_gid->gl_ngids++;
43286262Seota }
432910231SRajkumar.Sivaprakasam@Sun.COM new_gid->gl_is_dm_capable = B_TRUE;
43306262Seota new_gid->gl_nodeguid = nodeguid;
43316262Seota new_gid->gl_portguid = dgid.gid_guid;
43326262Seota ibdm_addto_glhcalist(new_gid, hca_list);
43336262Seota
43346262Seota /*
43356262Seota * Set the state to skipped as all these
43366262Seota * gids point to the same node.
43376262Seota * We (re)probe only one GID below and reset
43386262Seota * state appropriately
43396262Seota */
43406262Seota new_gid->gl_state = IBDM_GID_PROBING_SKIPPED;
43416262Seota new_gid->gl_devid = (*tmp).NodeInfo.DeviceID;
43426262Seota kmem_free(pi, pi_len);
43430Sstevel@tonic-gate }
43440Sstevel@tonic-gate kmem_free(nr, nr_len);
43450Sstevel@tonic-gate
43460Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tprobe_ioc : reprobe_flag %d "
43470Sstevel@tonic-gate "reprobe_gid %p new_gid %p node_gid %p",
43480Sstevel@tonic-gate reprobe_flag, reprobe_gid, new_gid, node_gid);
43490Sstevel@tonic-gate
43500Sstevel@tonic-gate if (reprobe_flag != 0 && reprobe_gid != NULL) {
43510Sstevel@tonic-gate int niocs, jj;
43520Sstevel@tonic-gate ibdm_ioc_info_t *tmp_ioc;
43530Sstevel@tonic-gate int ioc_matched = 0;
43540Sstevel@tonic-gate
43550Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_hl_mutex);
43560Sstevel@tonic-gate mutex_enter(&reprobe_gid->gl_mutex);
43570Sstevel@tonic-gate reprobe_gid->gl_state = IBDM_GET_IOC_DETAILS;
43580Sstevel@tonic-gate niocs =
43590Sstevel@tonic-gate reprobe_gid->gl_iou->iou_info.iou_num_ctrl_slots;
43600Sstevel@tonic-gate reprobe_gid->gl_pending_cmds++;
43610Sstevel@tonic-gate mutex_exit(&reprobe_gid->gl_mutex);
43620Sstevel@tonic-gate
43630Sstevel@tonic-gate for (jj = 0; jj < niocs; jj++) {
43640Sstevel@tonic-gate tmp_ioc =
43650Sstevel@tonic-gate IBDM_GIDINFO2IOCINFO(reprobe_gid, jj);
43660Sstevel@tonic-gate if (tmp_ioc->ioc_profile.ioc_guid != ioc_guid)
43670Sstevel@tonic-gate continue;
43680Sstevel@tonic-gate
43690Sstevel@tonic-gate ioc_matched = 1;
43700Sstevel@tonic-gate
43710Sstevel@tonic-gate /*
43720Sstevel@tonic-gate * Explicitly set gl_reprobe_flag to 0 so that
43730Sstevel@tonic-gate * IBnex is not notified on completion
43740Sstevel@tonic-gate */
43750Sstevel@tonic-gate mutex_enter(&reprobe_gid->gl_mutex);
43760Sstevel@tonic-gate reprobe_gid->gl_reprobe_flag = 0;
43770Sstevel@tonic-gate mutex_exit(&reprobe_gid->gl_mutex);
43780Sstevel@tonic-gate
43790Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
43800Sstevel@tonic-gate ibdm.ibdm_ngid_probes_in_progress++;
43810Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
43820Sstevel@tonic-gate if (ibdm_send_ioc_profile(reprobe_gid, jj) !=
43830Sstevel@tonic-gate IBDM_SUCCESS) {
43840Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm",
43850Sstevel@tonic-gate "\tprobe_ioc: "
43860Sstevel@tonic-gate "send_ioc_profile failed "
43870Sstevel@tonic-gate "for ioc %d", jj);
43880Sstevel@tonic-gate ibdm_gid_decr_pending(reprobe_gid);
43890Sstevel@tonic-gate break;
43900Sstevel@tonic-gate }
43910Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
43920Sstevel@tonic-gate ibdm_wait_probe_completion();
43930Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
43940Sstevel@tonic-gate break;
43950Sstevel@tonic-gate }
43960Sstevel@tonic-gate if (ioc_matched == 0)
43970Sstevel@tonic-gate ibdm_gid_decr_pending(reprobe_gid);
43980Sstevel@tonic-gate else {
43990Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_hl_mutex);
44000Sstevel@tonic-gate break;
44010Sstevel@tonic-gate }
44020Sstevel@tonic-gate } else if (new_gid != NULL) {
44030Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_hl_mutex);
44040Sstevel@tonic-gate node_gid = node_gid ? node_gid : new_gid;
44050Sstevel@tonic-gate
44060Sstevel@tonic-gate /*
44070Sstevel@tonic-gate * New or reinserted GID : Enable notification
44080Sstevel@tonic-gate * to IBnex
44090Sstevel@tonic-gate */
44100Sstevel@tonic-gate mutex_enter(&node_gid->gl_mutex);
44110Sstevel@tonic-gate node_gid->gl_reprobe_flag = 1;
44120Sstevel@tonic-gate mutex_exit(&node_gid->gl_mutex);
44130Sstevel@tonic-gate
44140Sstevel@tonic-gate ibdm_probe_gid(node_gid);
44150Sstevel@tonic-gate
44160Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_hl_mutex);
44170Sstevel@tonic-gate }
44180Sstevel@tonic-gate }
44190Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_hl_mutex);
44200Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tprobe_ioc : End\n");
44210Sstevel@tonic-gate }
44220Sstevel@tonic-gate
44230Sstevel@tonic-gate
44240Sstevel@tonic-gate /*
44250Sstevel@tonic-gate * ibdm_probe_gid()
44260Sstevel@tonic-gate * Selectively probes the GID
44270Sstevel@tonic-gate */
44280Sstevel@tonic-gate static void
ibdm_probe_gid(ibdm_dp_gidinfo_t * gid_info)44290Sstevel@tonic-gate ibdm_probe_gid(ibdm_dp_gidinfo_t *gid_info)
44300Sstevel@tonic-gate {
44310Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tprobe_gid:");
44326262Seota
44336262Seota /*
44346262Seota * A Cisco FC GW needs the special handling to get IOUnitInfo.
44356262Seota */
44360Sstevel@tonic-gate mutex_enter(&gid_info->gl_mutex);
44376262Seota if (ibdm_is_cisco_switch(gid_info)) {
44386262Seota gid_info->gl_pending_cmds++;
44396262Seota gid_info->gl_state = IBDM_SET_CLASSPORTINFO;
44406262Seota mutex_exit(&gid_info->gl_mutex);
44416262Seota
44426262Seota if (ibdm_set_classportinfo(gid_info) != IBDM_SUCCESS) {
44436262Seota
44446262Seota mutex_enter(&gid_info->gl_mutex);
44456262Seota gid_info->gl_state = IBDM_GID_PROBING_FAILED;
44466262Seota --gid_info->gl_pending_cmds;
44476262Seota mutex_exit(&gid_info->gl_mutex);
44486262Seota
44496262Seota /* free the hca_list on this gid_info */
44506262Seota ibdm_delete_glhca_list(gid_info);
44516262Seota gid_info = gid_info->gl_next;
44526262Seota return;
44536262Seota }
44546262Seota
44556262Seota mutex_enter(&gid_info->gl_mutex);
44566262Seota ibdm_wait_cisco_probe_completion(gid_info);
44576262Seota
44586262Seota IBTF_DPRINTF_L4("ibdm",
44596262Seota "\tprobe_gid: CISCO Wakeup signal received");
44606262Seota }
44616262Seota
44626262Seota /* move on to the 'GET_CLASSPORTINFO' stage */
44630Sstevel@tonic-gate gid_info->gl_pending_cmds++;
44640Sstevel@tonic-gate gid_info->gl_state = IBDM_GET_CLASSPORTINFO;
44650Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
44666262Seota
44670Sstevel@tonic-gate if (ibdm_send_classportinfo(gid_info) != IBDM_SUCCESS) {
44686262Seota
44690Sstevel@tonic-gate mutex_enter(&gid_info->gl_mutex);
44700Sstevel@tonic-gate gid_info->gl_state = IBDM_GID_PROBING_FAILED;
44710Sstevel@tonic-gate --gid_info->gl_pending_cmds;
44720Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
44736262Seota
44746262Seota /* free the hca_list on this gid_info */
44750Sstevel@tonic-gate ibdm_delete_glhca_list(gid_info);
44760Sstevel@tonic-gate gid_info = gid_info->gl_next;
44770Sstevel@tonic-gate return;
44780Sstevel@tonic-gate }
44796262Seota
44800Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
44810Sstevel@tonic-gate ibdm.ibdm_ngid_probes_in_progress++;
44820Sstevel@tonic-gate gid_info = gid_info->gl_next;
44830Sstevel@tonic-gate ibdm_wait_probe_completion();
44840Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
44856262Seota
44860Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tprobe_gid: Wakeup signal received");
44870Sstevel@tonic-gate }
44880Sstevel@tonic-gate
44890Sstevel@tonic-gate
44900Sstevel@tonic-gate /*
44910Sstevel@tonic-gate * ibdm_create_gid_info()
44920Sstevel@tonic-gate * Allocates a gid_info structure and initializes
44930Sstevel@tonic-gate * Returns pointer to the structure on success
44940Sstevel@tonic-gate * and NULL on failure
44950Sstevel@tonic-gate */
44960Sstevel@tonic-gate static ibdm_dp_gidinfo_t *
ibdm_create_gid_info(ibdm_port_attr_t * port,ib_gid_t sgid,ib_gid_t dgid)44970Sstevel@tonic-gate ibdm_create_gid_info(ibdm_port_attr_t *port, ib_gid_t sgid, ib_gid_t dgid)
44980Sstevel@tonic-gate {
44990Sstevel@tonic-gate uint8_t ii, npaths;
45000Sstevel@tonic-gate sa_path_record_t *path;
45010Sstevel@tonic-gate size_t len;
45020Sstevel@tonic-gate ibdm_pkey_tbl_t *pkey_tbl;
45030Sstevel@tonic-gate ibdm_dp_gidinfo_t *gid_info = NULL;
45040Sstevel@tonic-gate int ret;
45050Sstevel@tonic-gate
45060Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tcreate_gid_info: Begin");
45070Sstevel@tonic-gate npaths = 1;
45080Sstevel@tonic-gate
45090Sstevel@tonic-gate /* query for reversible paths */
45100Sstevel@tonic-gate if (port->pa_sa_hdl)
45110Sstevel@tonic-gate ret = ibmf_saa_gid_to_pathrecords(port->pa_sa_hdl,
45120Sstevel@tonic-gate sgid, dgid, IBMF_SAA_PKEY_WC, 0, B_TRUE, &npaths, 0,
45130Sstevel@tonic-gate &len, &path);
45140Sstevel@tonic-gate else
45150Sstevel@tonic-gate return (NULL);
45160Sstevel@tonic-gate
45170Sstevel@tonic-gate if (ret == IBMF_SUCCESS && path) {
45180Sstevel@tonic-gate ibdm_dump_path_info(path);
45190Sstevel@tonic-gate
45200Sstevel@tonic-gate gid_info = kmem_zalloc(
45210Sstevel@tonic-gate sizeof (ibdm_dp_gidinfo_t), KM_SLEEP);
45220Sstevel@tonic-gate mutex_init(&gid_info->gl_mutex, NULL, MUTEX_DEFAULT, NULL);
45236262Seota cv_init(&gid_info->gl_probe_cv, NULL, CV_DRIVER, NULL);
45240Sstevel@tonic-gate gid_info->gl_dgid_hi = path->DGID.gid_prefix;
45250Sstevel@tonic-gate gid_info->gl_dgid_lo = path->DGID.gid_guid;
45260Sstevel@tonic-gate gid_info->gl_sgid_hi = path->SGID.gid_prefix;
45270Sstevel@tonic-gate gid_info->gl_sgid_lo = path->SGID.gid_guid;
45280Sstevel@tonic-gate gid_info->gl_p_key = path->P_Key;
45290Sstevel@tonic-gate gid_info->gl_sa_hdl = port->pa_sa_hdl;
45300Sstevel@tonic-gate gid_info->gl_ibmf_hdl = port->pa_ibmf_hdl;
45310Sstevel@tonic-gate gid_info->gl_slid = path->SLID;
45320Sstevel@tonic-gate gid_info->gl_dlid = path->DLID;
45331093Shiremath gid_info->gl_transactionID = (++ibdm.ibdm_transactionID)
45341093Shiremath << IBDM_GID_TRANSACTIONID_SHIFT;
45351093Shiremath gid_info->gl_min_transactionID = gid_info->gl_transactionID;
45361093Shiremath gid_info->gl_max_transactionID = (ibdm.ibdm_transactionID +1)
45371093Shiremath << IBDM_GID_TRANSACTIONID_SHIFT;
45386699Seota gid_info->gl_SL = path->SL;
45390Sstevel@tonic-gate
45400Sstevel@tonic-gate gid_info->gl_qp_hdl = IBMF_QP_HANDLE_DEFAULT;
45410Sstevel@tonic-gate for (ii = 0; ii < port->pa_npkeys; ii++) {
45420Sstevel@tonic-gate if (port->pa_pkey_tbl == NULL)
45430Sstevel@tonic-gate break;
45440Sstevel@tonic-gate
45450Sstevel@tonic-gate pkey_tbl = &port->pa_pkey_tbl[ii];
45460Sstevel@tonic-gate if ((gid_info->gl_p_key == pkey_tbl->pt_pkey) &&
45470Sstevel@tonic-gate (pkey_tbl->pt_qp_hdl != NULL)) {
45480Sstevel@tonic-gate gid_info->gl_qp_hdl = pkey_tbl->pt_qp_hdl;
45490Sstevel@tonic-gate break;
45500Sstevel@tonic-gate }
45510Sstevel@tonic-gate }
45520Sstevel@tonic-gate kmem_free(path, len);
45531093Shiremath
45541093Shiremath /*
45551093Shiremath * QP handle for GID not initialized. No matching Pkey
45561093Shiremath * was found!! ibdm should *not* hit this case. Flag an
45571093Shiremath * error and drop the GID if ibdm does encounter this.
45581093Shiremath */
45591093Shiremath if (gid_info->gl_qp_hdl == NULL) {
45601093Shiremath IBTF_DPRINTF_L2(ibdm_string,
45611093Shiremath "\tcreate_gid_info: No matching Pkey");
45621093Shiremath ibdm_delete_gidinfo(gid_info);
45631093Shiremath return (NULL);
45641093Shiremath }
45651093Shiremath
45660Sstevel@tonic-gate ibdm.ibdm_ngids++;
45670Sstevel@tonic-gate if (ibdm.ibdm_dp_gidlist_head == NULL) {
45680Sstevel@tonic-gate ibdm.ibdm_dp_gidlist_head = gid_info;
45690Sstevel@tonic-gate ibdm.ibdm_dp_gidlist_tail = gid_info;
45700Sstevel@tonic-gate } else {
45710Sstevel@tonic-gate ibdm.ibdm_dp_gidlist_tail->gl_next = gid_info;
45720Sstevel@tonic-gate gid_info->gl_prev = ibdm.ibdm_dp_gidlist_tail;
45730Sstevel@tonic-gate ibdm.ibdm_dp_gidlist_tail = gid_info;
45740Sstevel@tonic-gate }
45750Sstevel@tonic-gate }
45760Sstevel@tonic-gate
45770Sstevel@tonic-gate return (gid_info);
45780Sstevel@tonic-gate }
45790Sstevel@tonic-gate
45800Sstevel@tonic-gate
45810Sstevel@tonic-gate /*
45820Sstevel@tonic-gate * ibdm_get_node_records
45830Sstevel@tonic-gate * Sends a SA query to get the NODE record
45840Sstevel@tonic-gate * Returns pointer to the sa_node_record_t on success
45850Sstevel@tonic-gate * and NULL on failure
45860Sstevel@tonic-gate */
45870Sstevel@tonic-gate static sa_node_record_t *
ibdm_get_node_records(ibmf_saa_handle_t sa_hdl,size_t * length,ib_guid_t guid)45880Sstevel@tonic-gate ibdm_get_node_records(ibmf_saa_handle_t sa_hdl, size_t *length, ib_guid_t guid)
45890Sstevel@tonic-gate {
45900Sstevel@tonic-gate sa_node_record_t req, *resp = NULL;
45910Sstevel@tonic-gate ibmf_saa_access_args_t args;
45920Sstevel@tonic-gate int ret;
45930Sstevel@tonic-gate
45940Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tget_node_records: Begin");
45950Sstevel@tonic-gate
45960Sstevel@tonic-gate bzero(&req, sizeof (sa_node_record_t));
45970Sstevel@tonic-gate req.NodeInfo.NodeGUID = guid;
45980Sstevel@tonic-gate
45990Sstevel@tonic-gate args.sq_attr_id = SA_NODERECORD_ATTRID;
46000Sstevel@tonic-gate args.sq_access_type = IBMF_SAA_RETRIEVE;
46010Sstevel@tonic-gate args.sq_component_mask = SA_NODEINFO_COMPMASK_NODEGUID;
46020Sstevel@tonic-gate args.sq_template = &req;
46030Sstevel@tonic-gate args.sq_callback = NULL;
46040Sstevel@tonic-gate args.sq_callback_arg = NULL;
46050Sstevel@tonic-gate
46060Sstevel@tonic-gate ret = ibmf_sa_access(sa_hdl, &args, 0, length, (void **) &resp);
46070Sstevel@tonic-gate if (ret != IBMF_SUCCESS) {
46080Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "\tget_node_records:"
46090Sstevel@tonic-gate " SA Retrieve Failed: %d", ret);
46100Sstevel@tonic-gate return (NULL);
46110Sstevel@tonic-gate }
46120Sstevel@tonic-gate if ((resp == NULL) || (*length == 0)) {
46130Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "\tget_node_records: No records");
46140Sstevel@tonic-gate return (NULL);
46150Sstevel@tonic-gate }
46160Sstevel@tonic-gate
46170Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tget_node_records: NodeGuid %llx "
46180Sstevel@tonic-gate "PortGUID %llx", resp->NodeInfo.NodeGUID, resp->NodeInfo.PortGUID);
46190Sstevel@tonic-gate
46200Sstevel@tonic-gate return (resp);
46210Sstevel@tonic-gate }
46220Sstevel@tonic-gate
46230Sstevel@tonic-gate
46240Sstevel@tonic-gate /*
46250Sstevel@tonic-gate * ibdm_get_portinfo()
46260Sstevel@tonic-gate * Sends a SA query to get the PortInfo record
46270Sstevel@tonic-gate * Returns pointer to the sa_portinfo_record_t on success
46280Sstevel@tonic-gate * and NULL on failure
46290Sstevel@tonic-gate */
46300Sstevel@tonic-gate static sa_portinfo_record_t *
ibdm_get_portinfo(ibmf_saa_handle_t sa_hdl,size_t * length,ib_lid_t lid)46310Sstevel@tonic-gate ibdm_get_portinfo(ibmf_saa_handle_t sa_hdl, size_t *length, ib_lid_t lid)
46320Sstevel@tonic-gate {
46330Sstevel@tonic-gate sa_portinfo_record_t req, *resp = NULL;
46340Sstevel@tonic-gate ibmf_saa_access_args_t args;
46350Sstevel@tonic-gate int ret;
46360Sstevel@tonic-gate
46370Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tget_portinfo: Begin");
46380Sstevel@tonic-gate
46390Sstevel@tonic-gate bzero(&req, sizeof (sa_portinfo_record_t));
46400Sstevel@tonic-gate req.EndportLID = lid;
46410Sstevel@tonic-gate
46420Sstevel@tonic-gate args.sq_attr_id = SA_PORTINFORECORD_ATTRID;
46430Sstevel@tonic-gate args.sq_access_type = IBMF_SAA_RETRIEVE;
46440Sstevel@tonic-gate args.sq_component_mask = SA_PORTINFO_COMPMASK_PORTLID;
46450Sstevel@tonic-gate args.sq_template = &req;
46460Sstevel@tonic-gate args.sq_callback = NULL;
46470Sstevel@tonic-gate args.sq_callback_arg = NULL;
46480Sstevel@tonic-gate
46490Sstevel@tonic-gate ret = ibmf_sa_access(sa_hdl, &args, 0, length, (void **) &resp);
46500Sstevel@tonic-gate if (ret != IBMF_SUCCESS) {
46510Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "\tget_portinfo:"
46520Sstevel@tonic-gate " SA Retrieve Failed: 0x%X", ret);
46530Sstevel@tonic-gate return (NULL);
46540Sstevel@tonic-gate }
46550Sstevel@tonic-gate if ((*length == 0) || (resp == NULL))
46560Sstevel@tonic-gate return (NULL);
46570Sstevel@tonic-gate
46580Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tget_portinfo: GidPrefix %llx Cap 0x%x",
46590Sstevel@tonic-gate resp->PortInfo.GidPrefix, resp->PortInfo.CapabilityMask);
46600Sstevel@tonic-gate return (resp);
46610Sstevel@tonic-gate }
46620Sstevel@tonic-gate
46630Sstevel@tonic-gate
46640Sstevel@tonic-gate /*
46650Sstevel@tonic-gate * ibdm_ibnex_register_callback
46660Sstevel@tonic-gate * IB nexus callback routine for HCA attach and detach notification
46670Sstevel@tonic-gate */
46680Sstevel@tonic-gate void
ibdm_ibnex_register_callback(ibdm_callback_t ibnex_dm_callback)46690Sstevel@tonic-gate ibdm_ibnex_register_callback(ibdm_callback_t ibnex_dm_callback)
46700Sstevel@tonic-gate {
46710Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tibnex_register_callbacks");
46720Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_ibnex_mutex);
46730Sstevel@tonic-gate ibdm.ibdm_ibnex_callback = ibnex_dm_callback;
46740Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_ibnex_mutex);
46750Sstevel@tonic-gate }
46760Sstevel@tonic-gate
46770Sstevel@tonic-gate
46780Sstevel@tonic-gate /*
46790Sstevel@tonic-gate * ibdm_ibnex_unregister_callbacks
46800Sstevel@tonic-gate */
46810Sstevel@tonic-gate void
ibdm_ibnex_unregister_callback()46820Sstevel@tonic-gate ibdm_ibnex_unregister_callback()
46830Sstevel@tonic-gate {
46840Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tibnex_unregister_callbacks");
46850Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_ibnex_mutex);
46860Sstevel@tonic-gate ibdm.ibdm_ibnex_callback = NULL;
46870Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_ibnex_mutex);
46880Sstevel@tonic-gate }
46890Sstevel@tonic-gate
46900Sstevel@tonic-gate /*
46918082SRamaswamy.Tummala@Sun.COM * ibdm_get_waittime()
46920Sstevel@tonic-gate * Calculates the wait time based on the last HCA attach time
46930Sstevel@tonic-gate */
46948082SRamaswamy.Tummala@Sun.COM static time_t
ibdm_get_waittime(ib_guid_t hca_guid,int dft_wait)46958082SRamaswamy.Tummala@Sun.COM ibdm_get_waittime(ib_guid_t hca_guid, int dft_wait)
46960Sstevel@tonic-gate {
46970Sstevel@tonic-gate int ii;
46980Sstevel@tonic-gate time_t temp, wait_time = 0;
46990Sstevel@tonic-gate ibdm_hca_list_t *hca;
47000Sstevel@tonic-gate
47018082SRamaswamy.Tummala@Sun.COM IBTF_DPRINTF_L4("ibdm", "\tget_waittime hcaguid:%llx"
47028082SRamaswamy.Tummala@Sun.COM "\tport settling time %d", hca_guid, dft_wait);
47038082SRamaswamy.Tummala@Sun.COM
47048082SRamaswamy.Tummala@Sun.COM ASSERT(mutex_owned(&ibdm.ibdm_hl_mutex));
47058082SRamaswamy.Tummala@Sun.COM
47060Sstevel@tonic-gate hca = ibdm.ibdm_hca_list_head;
47070Sstevel@tonic-gate
47080Sstevel@tonic-gate if (hca_guid) {
47090Sstevel@tonic-gate for (ii = 0; ii < ibdm.ibdm_hca_count; ii++) {
47100Sstevel@tonic-gate if ((hca_guid == hca->hl_hca_guid) &&
47110Sstevel@tonic-gate (hca->hl_nports != hca->hl_nports_active)) {
47120Sstevel@tonic-gate wait_time =
47136262Seota ddi_get_time() - hca->hl_attach_time;
47148082SRamaswamy.Tummala@Sun.COM wait_time = ((wait_time >= dft_wait) ?
47158082SRamaswamy.Tummala@Sun.COM 0 : (dft_wait - wait_time));
47160Sstevel@tonic-gate break;
47170Sstevel@tonic-gate }
47180Sstevel@tonic-gate hca = hca->hl_next;
47190Sstevel@tonic-gate }
4720*12723SRamaswamy.Tummala@Sun.COM IBTF_DPRINTF_L2("ibdm", "\tget_waittime: wait_time = %ld secs",
4721*12723SRamaswamy.Tummala@Sun.COM (long)wait_time);
47220Sstevel@tonic-gate return (wait_time);
47230Sstevel@tonic-gate }
47240Sstevel@tonic-gate
47250Sstevel@tonic-gate for (ii = 0; ii < ibdm.ibdm_hca_count; ii++) {
47260Sstevel@tonic-gate if (hca->hl_nports != hca->hl_nports_active) {
47270Sstevel@tonic-gate temp = ddi_get_time() - hca->hl_attach_time;
47288082SRamaswamy.Tummala@Sun.COM temp = ((temp >= dft_wait) ? 0 : (dft_wait - temp));
47290Sstevel@tonic-gate wait_time = (temp > wait_time) ? temp : wait_time;
47300Sstevel@tonic-gate }
4731*12723SRamaswamy.Tummala@Sun.COM hca = hca->hl_next;
4732*12723SRamaswamy.Tummala@Sun.COM }
4733*12723SRamaswamy.Tummala@Sun.COM IBTF_DPRINTF_L2("ibdm", "\tget_waittime: wait_time = %ld secs",
4734*12723SRamaswamy.Tummala@Sun.COM (long)wait_time);
47358082SRamaswamy.Tummala@Sun.COM return (wait_time);
47368082SRamaswamy.Tummala@Sun.COM }
47378082SRamaswamy.Tummala@Sun.COM
47388082SRamaswamy.Tummala@Sun.COM void
ibdm_ibnex_port_settle_wait(ib_guid_t hca_guid,int dft_wait)47398082SRamaswamy.Tummala@Sun.COM ibdm_ibnex_port_settle_wait(ib_guid_t hca_guid, int dft_wait)
47408082SRamaswamy.Tummala@Sun.COM {
47418082SRamaswamy.Tummala@Sun.COM time_t wait_time;
474211066Srafael.vanoni@sun.com clock_t delta;
47438082SRamaswamy.Tummala@Sun.COM
47448082SRamaswamy.Tummala@Sun.COM mutex_enter(&ibdm.ibdm_hl_mutex);
47458082SRamaswamy.Tummala@Sun.COM
47468082SRamaswamy.Tummala@Sun.COM while ((wait_time = ibdm_get_waittime(hca_guid, dft_wait)) > 0) {
4747*12723SRamaswamy.Tummala@Sun.COM if (wait_time > dft_wait) {
4748*12723SRamaswamy.Tummala@Sun.COM IBTF_DPRINTF_L1("ibdm",
4749*12723SRamaswamy.Tummala@Sun.COM "\tibnex_port_settle_wait: wait_time = %ld secs; "
4750*12723SRamaswamy.Tummala@Sun.COM "Resetting to %d secs",
4751*12723SRamaswamy.Tummala@Sun.COM (long)wait_time, dft_wait);
4752*12723SRamaswamy.Tummala@Sun.COM wait_time = dft_wait;
4753*12723SRamaswamy.Tummala@Sun.COM }
475411184Srafael.vanoni@sun.com delta = drv_usectohz(wait_time * 1000000);
475511066Srafael.vanoni@sun.com (void) cv_reltimedwait(&ibdm.ibdm_port_settle_cv,
475611066Srafael.vanoni@sun.com &ibdm.ibdm_hl_mutex, delta, TR_CLOCK_TICK);
47578082SRamaswamy.Tummala@Sun.COM }
47588082SRamaswamy.Tummala@Sun.COM
47590Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_hl_mutex);
47600Sstevel@tonic-gate }
47610Sstevel@tonic-gate
47620Sstevel@tonic-gate
47630Sstevel@tonic-gate /*
47640Sstevel@tonic-gate * ibdm_ibnex_probe_hcaport
47650Sstevel@tonic-gate * Probes the presence of HCA port (with HCA dip and port number)
47660Sstevel@tonic-gate * Returns port attributes structure on SUCCESS
47670Sstevel@tonic-gate */
47680Sstevel@tonic-gate ibdm_port_attr_t *
ibdm_ibnex_probe_hcaport(ib_guid_t hca_guid,uint8_t port_num)47690Sstevel@tonic-gate ibdm_ibnex_probe_hcaport(ib_guid_t hca_guid, uint8_t port_num)
47700Sstevel@tonic-gate {
47710Sstevel@tonic-gate int ii, jj;
47720Sstevel@tonic-gate ibdm_hca_list_t *hca_list;
47730Sstevel@tonic-gate ibdm_port_attr_t *port_attr;
47740Sstevel@tonic-gate
47750Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tibnex_probe_hcaport:");
47760Sstevel@tonic-gate
47770Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_hl_mutex);
47780Sstevel@tonic-gate hca_list = ibdm.ibdm_hca_list_head;
47790Sstevel@tonic-gate for (ii = 0; ii < ibdm.ibdm_hca_count; ii++) {
47800Sstevel@tonic-gate if (hca_list->hl_hca_guid == hca_guid) {
47810Sstevel@tonic-gate for (jj = 0; jj < hca_list->hl_nports; jj++) {
47820Sstevel@tonic-gate if (hca_list->hl_port_attr[jj].pa_port_num ==
47830Sstevel@tonic-gate port_num) {
47840Sstevel@tonic-gate break;
47850Sstevel@tonic-gate }
47860Sstevel@tonic-gate }
47870Sstevel@tonic-gate if (jj != hca_list->hl_nports)
47880Sstevel@tonic-gate break;
47890Sstevel@tonic-gate }
47900Sstevel@tonic-gate hca_list = hca_list->hl_next;
47910Sstevel@tonic-gate }
47920Sstevel@tonic-gate if (ii == ibdm.ibdm_hca_count) {
47930Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "\tibnex_probe_hcaport: not found");
47940Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_hl_mutex);
47950Sstevel@tonic-gate return (NULL);
47960Sstevel@tonic-gate }
47970Sstevel@tonic-gate port_attr = (ibdm_port_attr_t *)kmem_zalloc(
47980Sstevel@tonic-gate sizeof (ibdm_port_attr_t), KM_SLEEP);
47990Sstevel@tonic-gate bcopy((char *)&hca_list->hl_port_attr[jj],
48000Sstevel@tonic-gate port_attr, sizeof (ibdm_port_attr_t));
48010Sstevel@tonic-gate ibdm_update_port_attr(port_attr);
48020Sstevel@tonic-gate
48030Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_hl_mutex);
48040Sstevel@tonic-gate return (port_attr);
48050Sstevel@tonic-gate }
48060Sstevel@tonic-gate
48070Sstevel@tonic-gate
48080Sstevel@tonic-gate /*
48090Sstevel@tonic-gate * ibdm_ibnex_get_port_attrs
48100Sstevel@tonic-gate * Scan all HCAs for a matching port_guid.
48110Sstevel@tonic-gate * Returns "port attributes" structure on success.
48120Sstevel@tonic-gate */
48130Sstevel@tonic-gate ibdm_port_attr_t *
ibdm_ibnex_get_port_attrs(ib_guid_t port_guid)48140Sstevel@tonic-gate ibdm_ibnex_get_port_attrs(ib_guid_t port_guid)
48150Sstevel@tonic-gate {
48160Sstevel@tonic-gate int ii, jj;
48170Sstevel@tonic-gate ibdm_hca_list_t *hca_list;
48180Sstevel@tonic-gate ibdm_port_attr_t *port_attr;
48190Sstevel@tonic-gate
48200Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tibnex_get_port_attrs:");
48210Sstevel@tonic-gate
48220Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_hl_mutex);
48230Sstevel@tonic-gate hca_list = ibdm.ibdm_hca_list_head;
48240Sstevel@tonic-gate
48250Sstevel@tonic-gate for (ii = 0; ii < ibdm.ibdm_hca_count; ii++) {
48260Sstevel@tonic-gate for (jj = 0; jj < hca_list->hl_nports; jj++) {
48270Sstevel@tonic-gate if (hca_list->hl_port_attr[jj].pa_port_guid ==
48286262Seota port_guid) {
48290Sstevel@tonic-gate break;
48300Sstevel@tonic-gate }
48310Sstevel@tonic-gate }
48320Sstevel@tonic-gate if (jj != hca_list->hl_nports)
48330Sstevel@tonic-gate break;
48340Sstevel@tonic-gate hca_list = hca_list->hl_next;
48350Sstevel@tonic-gate }
48360Sstevel@tonic-gate
48370Sstevel@tonic-gate if (ii == ibdm.ibdm_hca_count) {
48380Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "\tibnex_get_port_attrs: not found");
48390Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_hl_mutex);
48400Sstevel@tonic-gate return (NULL);
48410Sstevel@tonic-gate }
48420Sstevel@tonic-gate
48430Sstevel@tonic-gate port_attr = (ibdm_port_attr_t *)kmem_alloc(sizeof (ibdm_port_attr_t),
48440Sstevel@tonic-gate KM_SLEEP);
48450Sstevel@tonic-gate bcopy((char *)&hca_list->hl_port_attr[jj], port_attr,
48460Sstevel@tonic-gate sizeof (ibdm_port_attr_t));
48470Sstevel@tonic-gate ibdm_update_port_attr(port_attr);
48480Sstevel@tonic-gate
48490Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_hl_mutex);
48500Sstevel@tonic-gate return (port_attr);
48510Sstevel@tonic-gate }
48520Sstevel@tonic-gate
48530Sstevel@tonic-gate
48540Sstevel@tonic-gate /*
48550Sstevel@tonic-gate * ibdm_ibnex_free_port_attr()
48560Sstevel@tonic-gate */
48570Sstevel@tonic-gate void
ibdm_ibnex_free_port_attr(ibdm_port_attr_t * port_attr)48580Sstevel@tonic-gate ibdm_ibnex_free_port_attr(ibdm_port_attr_t *port_attr)
48590Sstevel@tonic-gate {
48600Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tibnex_free_port_attr:");
48610Sstevel@tonic-gate if (port_attr) {
48620Sstevel@tonic-gate if (port_attr->pa_pkey_tbl != NULL) {
48630Sstevel@tonic-gate kmem_free(port_attr->pa_pkey_tbl,
48640Sstevel@tonic-gate (port_attr->pa_npkeys * sizeof (ibdm_pkey_tbl_t)));
48650Sstevel@tonic-gate }
48660Sstevel@tonic-gate kmem_free(port_attr, sizeof (ibdm_port_attr_t));
48670Sstevel@tonic-gate }
48680Sstevel@tonic-gate }
48690Sstevel@tonic-gate
48700Sstevel@tonic-gate
48710Sstevel@tonic-gate /*
48720Sstevel@tonic-gate * ibdm_ibnex_get_hca_list()
48730Sstevel@tonic-gate * Returns portinfo for all the port for all the HCA's
48740Sstevel@tonic-gate */
48750Sstevel@tonic-gate void
ibdm_ibnex_get_hca_list(ibdm_hca_list_t ** hca,int * count)48760Sstevel@tonic-gate ibdm_ibnex_get_hca_list(ibdm_hca_list_t **hca, int *count)
48770Sstevel@tonic-gate {
48780Sstevel@tonic-gate ibdm_hca_list_t *head = NULL, *temp, *temp1;
48790Sstevel@tonic-gate int ii;
48800Sstevel@tonic-gate
48810Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tibnex_get_hca_list:");
48820Sstevel@tonic-gate
48830Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_hl_mutex);
48840Sstevel@tonic-gate temp = ibdm.ibdm_hca_list_head;
48850Sstevel@tonic-gate for (ii = 0; ii < ibdm.ibdm_hca_count; ii++) {
48860Sstevel@tonic-gate temp1 = ibdm_dup_hca_attr(temp);
48870Sstevel@tonic-gate temp1->hl_next = head;
48880Sstevel@tonic-gate head = temp1;
48890Sstevel@tonic-gate temp = temp->hl_next;
48900Sstevel@tonic-gate }
48910Sstevel@tonic-gate *count = ibdm.ibdm_hca_count;
48920Sstevel@tonic-gate *hca = head;
48930Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_hl_mutex);
48940Sstevel@tonic-gate }
48950Sstevel@tonic-gate
48960Sstevel@tonic-gate
48970Sstevel@tonic-gate /*
48980Sstevel@tonic-gate * ibdm_ibnex_get_hca_info_by_guid()
48990Sstevel@tonic-gate */
49000Sstevel@tonic-gate ibdm_hca_list_t *
ibdm_ibnex_get_hca_info_by_guid(ib_guid_t hca_guid)49010Sstevel@tonic-gate ibdm_ibnex_get_hca_info_by_guid(ib_guid_t hca_guid)
49020Sstevel@tonic-gate {
49030Sstevel@tonic-gate ibdm_hca_list_t *head = NULL, *hca = NULL;
49040Sstevel@tonic-gate
49050Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tibnex_get_hca_info_by_dip");
49060Sstevel@tonic-gate
49070Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_hl_mutex);
49080Sstevel@tonic-gate head = ibdm.ibdm_hca_list_head;
49090Sstevel@tonic-gate while (head) {
49100Sstevel@tonic-gate if (head->hl_hca_guid == hca_guid) {
49110Sstevel@tonic-gate hca = ibdm_dup_hca_attr(head);
49120Sstevel@tonic-gate hca->hl_next = NULL;
49130Sstevel@tonic-gate break;
49140Sstevel@tonic-gate }
49150Sstevel@tonic-gate head = head->hl_next;
49160Sstevel@tonic-gate }
49170Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_hl_mutex);
49180Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tibnex_get_hca_info_by_dip %p", hca);
49190Sstevel@tonic-gate return (hca);
49200Sstevel@tonic-gate }
49210Sstevel@tonic-gate
49220Sstevel@tonic-gate
49230Sstevel@tonic-gate /*
49240Sstevel@tonic-gate * ibdm_dup_hca_attr()
49250Sstevel@tonic-gate * Allocate a new HCA attribute strucuture and initialize
49260Sstevel@tonic-gate * hca attribute structure with the incoming HCA attributes
49270Sstevel@tonic-gate * returned the allocated hca attributes.
49280Sstevel@tonic-gate */
49290Sstevel@tonic-gate static ibdm_hca_list_t *
ibdm_dup_hca_attr(ibdm_hca_list_t * in_hca)49300Sstevel@tonic-gate ibdm_dup_hca_attr(ibdm_hca_list_t *in_hca)
49310Sstevel@tonic-gate {
49320Sstevel@tonic-gate int len;
49330Sstevel@tonic-gate ibdm_hca_list_t *out_hca;
49340Sstevel@tonic-gate
49350Sstevel@tonic-gate len = sizeof (ibdm_hca_list_t) +
49360Sstevel@tonic-gate (in_hca->hl_nports * sizeof (ibdm_port_attr_t));
49370Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tdup_hca_attr len %d", len);
49380Sstevel@tonic-gate out_hca = (ibdm_hca_list_t *)kmem_alloc(len, KM_SLEEP);
49390Sstevel@tonic-gate bcopy((char *)in_hca,
49406262Seota (char *)out_hca, sizeof (ibdm_hca_list_t));
49410Sstevel@tonic-gate if (in_hca->hl_nports) {
49420Sstevel@tonic-gate out_hca->hl_port_attr = (ibdm_port_attr_t *)
49436262Seota ((char *)out_hca + sizeof (ibdm_hca_list_t));
49440Sstevel@tonic-gate bcopy((char *)in_hca->hl_port_attr,
49456262Seota (char *)out_hca->hl_port_attr,
49466262Seota (in_hca->hl_nports * sizeof (ibdm_port_attr_t)));
49470Sstevel@tonic-gate for (len = 0; len < out_hca->hl_nports; len++)
49480Sstevel@tonic-gate ibdm_update_port_attr(&out_hca->hl_port_attr[len]);
49490Sstevel@tonic-gate }
49500Sstevel@tonic-gate return (out_hca);
49510Sstevel@tonic-gate }
49520Sstevel@tonic-gate
49530Sstevel@tonic-gate
49540Sstevel@tonic-gate /*
49550Sstevel@tonic-gate * ibdm_ibnex_free_hca_list()
49560Sstevel@tonic-gate * Free one/more HCA lists
49570Sstevel@tonic-gate */
49580Sstevel@tonic-gate void
ibdm_ibnex_free_hca_list(ibdm_hca_list_t * hca_list)49590Sstevel@tonic-gate ibdm_ibnex_free_hca_list(ibdm_hca_list_t *hca_list)
49600Sstevel@tonic-gate {
49612927Spramodbg int ii;
49622927Spramodbg size_t len;
49630Sstevel@tonic-gate ibdm_hca_list_t *temp;
49640Sstevel@tonic-gate ibdm_port_attr_t *port;
49650Sstevel@tonic-gate
49660Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tibnex_free_hca_list:");
49670Sstevel@tonic-gate ASSERT(hca_list);
49680Sstevel@tonic-gate while (hca_list) {
49690Sstevel@tonic-gate temp = hca_list;
49700Sstevel@tonic-gate hca_list = hca_list->hl_next;
49710Sstevel@tonic-gate for (ii = 0; ii < temp->hl_nports; ii++) {
49720Sstevel@tonic-gate port = &temp->hl_port_attr[ii];
49730Sstevel@tonic-gate len = (port->pa_npkeys * sizeof (ibdm_pkey_tbl_t));
49740Sstevel@tonic-gate if (len != 0)
49750Sstevel@tonic-gate kmem_free(port->pa_pkey_tbl, len);
49760Sstevel@tonic-gate }
49770Sstevel@tonic-gate len = sizeof (ibdm_hca_list_t) + (temp->hl_nports *
49786262Seota sizeof (ibdm_port_attr_t));
49790Sstevel@tonic-gate kmem_free(temp, len);
49800Sstevel@tonic-gate }
49810Sstevel@tonic-gate }
49820Sstevel@tonic-gate
49830Sstevel@tonic-gate
49840Sstevel@tonic-gate /*
49850Sstevel@tonic-gate * ibdm_ibnex_probe_iocguid()
49860Sstevel@tonic-gate * Probes the IOC on the fabric and returns the IOC information
49870Sstevel@tonic-gate * if present. Otherwise, NULL is returned
49880Sstevel@tonic-gate */
49890Sstevel@tonic-gate /* ARGSUSED */
49900Sstevel@tonic-gate ibdm_ioc_info_t *
ibdm_ibnex_probe_ioc(ib_guid_t iou,ib_guid_t ioc_guid,int reprobe_flag)49910Sstevel@tonic-gate ibdm_ibnex_probe_ioc(ib_guid_t iou, ib_guid_t ioc_guid, int reprobe_flag)
49920Sstevel@tonic-gate {
49930Sstevel@tonic-gate int k;
49940Sstevel@tonic-gate ibdm_ioc_info_t *ioc_info;
49956699Seota ibdm_dp_gidinfo_t *gid_info; /* used as index and arg */
49966699Seota timeout_id_t *timeout_id;
49970Sstevel@tonic-gate
49980Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tibnex_probe_ioc: (%llX, %llX, %d) Begin",
49990Sstevel@tonic-gate iou, ioc_guid, reprobe_flag);
5000*12723SRamaswamy.Tummala@Sun.COM
5001*12723SRamaswamy.Tummala@Sun.COM if (ibdm_enumerate_iocs == 0)
5002*12723SRamaswamy.Tummala@Sun.COM return (NULL);
5003*12723SRamaswamy.Tummala@Sun.COM
50040Sstevel@tonic-gate /* Check whether we know this already */
50056699Seota ioc_info = ibdm_get_ioc_info_with_gid(ioc_guid, &gid_info);
50060Sstevel@tonic-gate if (ioc_info == NULL) {
50070Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
50080Sstevel@tonic-gate while (ibdm.ibdm_busy & IBDM_BUSY)
50090Sstevel@tonic-gate cv_wait(&ibdm.ibdm_busy_cv, &ibdm.ibdm_mutex);
50100Sstevel@tonic-gate ibdm.ibdm_busy |= IBDM_BUSY;
50110Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
50120Sstevel@tonic-gate ibdm_probe_ioc(iou, ioc_guid, 0);
50130Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
50140Sstevel@tonic-gate ibdm.ibdm_busy &= ~IBDM_BUSY;
50150Sstevel@tonic-gate cv_broadcast(&ibdm.ibdm_busy_cv);
50160Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
50176699Seota ioc_info = ibdm_get_ioc_info_with_gid(ioc_guid, &gid_info);
50180Sstevel@tonic-gate } else if (reprobe_flag) { /* Handle Reprobe for the IOC */
50196699Seota ASSERT(gid_info != NULL);
50200Sstevel@tonic-gate /* Free the ioc_list before reprobe; and cancel any timers */
50210Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
50226699Seota mutex_enter(&gid_info->gl_mutex);
50230Sstevel@tonic-gate if (ioc_info->ioc_timeout_id) {
50246699Seota timeout_id = ioc_info->ioc_timeout_id;
50256699Seota ioc_info->ioc_timeout_id = 0;
50266699Seota mutex_exit(&gid_info->gl_mutex);
50270Sstevel@tonic-gate IBTF_DPRINTF_L5("ibdm", "\tprobe_ioc: "
50286699Seota "ioc_timeout_id = 0x%x", timeout_id);
50296699Seota if (untimeout(timeout_id) == -1) {
50300Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "\tprobe_ioc: "
50310Sstevel@tonic-gate "untimeout ioc_timeout_id failed");
50320Sstevel@tonic-gate }
50336699Seota mutex_enter(&gid_info->gl_mutex);
50340Sstevel@tonic-gate }
50350Sstevel@tonic-gate if (ioc_info->ioc_dc_timeout_id) {
50366699Seota timeout_id = ioc_info->ioc_dc_timeout_id;
50376699Seota ioc_info->ioc_dc_timeout_id = 0;
50386699Seota mutex_exit(&gid_info->gl_mutex);
50390Sstevel@tonic-gate IBTF_DPRINTF_L5("ibdm", "\tprobe_ioc: "
50406699Seota "ioc_dc_timeout_id = 0x%x", timeout_id);
50416699Seota if (untimeout(timeout_id) == -1) {
50420Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "\tprobe_ioc: "
50430Sstevel@tonic-gate "untimeout ioc_dc_timeout_id failed");
50440Sstevel@tonic-gate }
50456699Seota mutex_enter(&gid_info->gl_mutex);
50460Sstevel@tonic-gate }
50470Sstevel@tonic-gate for (k = 0; k < ioc_info->ioc_profile.ioc_service_entries; k++)
50480Sstevel@tonic-gate if (ioc_info->ioc_serv[k].se_timeout_id) {
50496699Seota timeout_id = ioc_info->ioc_serv[k].
50506699Seota se_timeout_id;
50516699Seota ioc_info->ioc_serv[k].se_timeout_id = 0;
50526699Seota mutex_exit(&gid_info->gl_mutex);
50530Sstevel@tonic-gate IBTF_DPRINTF_L5("ibdm", "\tprobe_ioc: "
50540Sstevel@tonic-gate "ioc_info->ioc_serv[k].se_timeout_id = %x",
50556699Seota k, timeout_id);
50566699Seota if (untimeout(timeout_id) == -1) {
50570Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "\tprobe_ioc: "
50580Sstevel@tonic-gate "untimeout se_timeout_id %d "
50590Sstevel@tonic-gate "failed", k);
50600Sstevel@tonic-gate }
50616699Seota mutex_enter(&gid_info->gl_mutex);
50620Sstevel@tonic-gate }
50636699Seota mutex_exit(&gid_info->gl_mutex);
50640Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
50650Sstevel@tonic-gate ibdm_ibnex_free_ioc_list(ioc_info);
50660Sstevel@tonic-gate
50670Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
50680Sstevel@tonic-gate while (ibdm.ibdm_busy & IBDM_BUSY)
50690Sstevel@tonic-gate cv_wait(&ibdm.ibdm_busy_cv, &ibdm.ibdm_mutex);
50700Sstevel@tonic-gate ibdm.ibdm_busy |= IBDM_BUSY;
50710Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
50720Sstevel@tonic-gate
50730Sstevel@tonic-gate ibdm_probe_ioc(iou, ioc_guid, 1);
50740Sstevel@tonic-gate
50750Sstevel@tonic-gate /*
50760Sstevel@tonic-gate * Skip if gl_reprobe_flag is set, this will be
50770Sstevel@tonic-gate * a re-inserted / new GID, for which notifications
50780Sstevel@tonic-gate * have already been send.
50790Sstevel@tonic-gate */
50800Sstevel@tonic-gate for (gid_info = ibdm.ibdm_dp_gidlist_head; gid_info;
50810Sstevel@tonic-gate gid_info = gid_info->gl_next) {
50820Sstevel@tonic-gate uint8_t ii, niocs;
50830Sstevel@tonic-gate ibdm_ioc_info_t *ioc;
50840Sstevel@tonic-gate
50850Sstevel@tonic-gate if (gid_info->gl_iou == NULL)
50860Sstevel@tonic-gate continue;
50870Sstevel@tonic-gate
50880Sstevel@tonic-gate if (gid_info->gl_reprobe_flag) {
50890Sstevel@tonic-gate gid_info->gl_reprobe_flag = 0;
50900Sstevel@tonic-gate continue;
50910Sstevel@tonic-gate }
50920Sstevel@tonic-gate
50930Sstevel@tonic-gate niocs = gid_info->gl_iou->iou_info.iou_num_ctrl_slots;
50940Sstevel@tonic-gate for (ii = 0; ii < niocs; ii++) {
50950Sstevel@tonic-gate ioc = IBDM_GIDINFO2IOCINFO(gid_info, ii);
50960Sstevel@tonic-gate if (ioc->ioc_profile.ioc_guid == ioc_guid) {
50970Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
50980Sstevel@tonic-gate ibdm_reprobe_update_port_srv(ioc,
50990Sstevel@tonic-gate gid_info);
51000Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
51010Sstevel@tonic-gate }
51020Sstevel@tonic-gate }
51030Sstevel@tonic-gate }
51040Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
51050Sstevel@tonic-gate ibdm.ibdm_busy &= ~IBDM_BUSY;
51060Sstevel@tonic-gate cv_broadcast(&ibdm.ibdm_busy_cv);
51070Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
51080Sstevel@tonic-gate
51096699Seota ioc_info = ibdm_get_ioc_info_with_gid(ioc_guid, &gid_info);
51100Sstevel@tonic-gate }
51110Sstevel@tonic-gate return (ioc_info);
51120Sstevel@tonic-gate }
51130Sstevel@tonic-gate
51140Sstevel@tonic-gate
51150Sstevel@tonic-gate /*
51166699Seota * ibdm_get_ioc_info_with_gid()
51170Sstevel@tonic-gate * Returns pointer to ibdm_ioc_info_t if it finds
51186699Seota * matching record for the ioc_guid. Otherwise NULL is returned.
51196699Seota * The pointer to gid_info is set to the second argument in case that
51206699Seota * the non-NULL value returns (and the second argument is not NULL).
51216699Seota *
51226699Seota * Note. use the same strings as "ibnex_get_ioc_info" in
51236699Seota * IBTF_DPRINTF() to keep compatibility.
51240Sstevel@tonic-gate */
51256699Seota static ibdm_ioc_info_t *
ibdm_get_ioc_info_with_gid(ib_guid_t ioc_guid,ibdm_dp_gidinfo_t ** gid_info)51266699Seota ibdm_get_ioc_info_with_gid(ib_guid_t ioc_guid,
51276699Seota ibdm_dp_gidinfo_t **gid_info)
51280Sstevel@tonic-gate {
51290Sstevel@tonic-gate int ii;
51300Sstevel@tonic-gate ibdm_ioc_info_t *ioc = NULL, *tmp = NULL;
51310Sstevel@tonic-gate ibdm_dp_gidinfo_t *gid_list;
51320Sstevel@tonic-gate ib_dm_io_unitinfo_t *iou;
51330Sstevel@tonic-gate
51340Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tibnex_get_ioc_info: GUID %llx", ioc_guid);
51350Sstevel@tonic-gate
51360Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
51370Sstevel@tonic-gate while (ibdm.ibdm_busy & IBDM_BUSY)
51380Sstevel@tonic-gate cv_wait(&ibdm.ibdm_busy_cv, &ibdm.ibdm_mutex);
51390Sstevel@tonic-gate ibdm.ibdm_busy |= IBDM_BUSY;
51400Sstevel@tonic-gate
51416699Seota if (gid_info)
51426699Seota *gid_info = NULL; /* clear the value of gid_info */
51436699Seota
51440Sstevel@tonic-gate gid_list = ibdm.ibdm_dp_gidlist_head;
51450Sstevel@tonic-gate while (gid_list) {
51460Sstevel@tonic-gate mutex_enter(&gid_list->gl_mutex);
51470Sstevel@tonic-gate if (gid_list->gl_state != IBDM_GID_PROBING_COMPLETE) {
51480Sstevel@tonic-gate mutex_exit(&gid_list->gl_mutex);
51490Sstevel@tonic-gate gid_list = gid_list->gl_next;
51500Sstevel@tonic-gate continue;
51510Sstevel@tonic-gate }
51520Sstevel@tonic-gate if (gid_list->gl_iou == NULL) {
51530Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm",
51540Sstevel@tonic-gate "\tget_ioc_info: No IOU info");
51550Sstevel@tonic-gate mutex_exit(&gid_list->gl_mutex);
51560Sstevel@tonic-gate gid_list = gid_list->gl_next;
51570Sstevel@tonic-gate continue;
51580Sstevel@tonic-gate }
51590Sstevel@tonic-gate iou = &gid_list->gl_iou->iou_info;
51600Sstevel@tonic-gate for (ii = 0; ii < iou->iou_num_ctrl_slots; ii++) {
51610Sstevel@tonic-gate tmp = IBDM_GIDINFO2IOCINFO(gid_list, ii);
51620Sstevel@tonic-gate if ((tmp->ioc_profile.ioc_guid == ioc_guid) &&
51630Sstevel@tonic-gate (tmp->ioc_state == IBDM_IOC_STATE_PROBE_SUCCESS)) {
51640Sstevel@tonic-gate ioc = ibdm_dup_ioc_info(tmp, gid_list);
51656699Seota if (gid_info)
51666699Seota *gid_info = gid_list; /* set this ptr */
51670Sstevel@tonic-gate mutex_exit(&gid_list->gl_mutex);
51680Sstevel@tonic-gate ibdm.ibdm_busy &= ~IBDM_BUSY;
51690Sstevel@tonic-gate cv_broadcast(&ibdm.ibdm_busy_cv);
51700Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
51710Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tget_ioc_info: End");
51720Sstevel@tonic-gate return (ioc);
51730Sstevel@tonic-gate }
51740Sstevel@tonic-gate }
51750Sstevel@tonic-gate if (ii == iou->iou_num_ctrl_slots)
51760Sstevel@tonic-gate ioc = NULL;
51770Sstevel@tonic-gate
51780Sstevel@tonic-gate mutex_exit(&gid_list->gl_mutex);
51790Sstevel@tonic-gate gid_list = gid_list->gl_next;
51800Sstevel@tonic-gate }
51810Sstevel@tonic-gate
51820Sstevel@tonic-gate ibdm.ibdm_busy &= ~IBDM_BUSY;
51830Sstevel@tonic-gate cv_broadcast(&ibdm.ibdm_busy_cv);
51840Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
51850Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tget_ioc_info: failure End");
51860Sstevel@tonic-gate return (ioc);
51870Sstevel@tonic-gate }
51880Sstevel@tonic-gate
51896699Seota /*
51906699Seota * ibdm_ibnex_get_ioc_info()
51916699Seota * Returns pointer to ibdm_ioc_info_t if it finds
51926699Seota * matching record for the ioc_guid, otherwise NULL
51936699Seota * is returned
51946699Seota *
51956699Seota * Note. this is a wrapper function to ibdm_get_ioc_info_with_gid() now.
51966699Seota */
51976699Seota ibdm_ioc_info_t *
ibdm_ibnex_get_ioc_info(ib_guid_t ioc_guid)51986699Seota ibdm_ibnex_get_ioc_info(ib_guid_t ioc_guid)
51996699Seota {
5200*12723SRamaswamy.Tummala@Sun.COM if (ibdm_enumerate_iocs == 0)
5201*12723SRamaswamy.Tummala@Sun.COM return (NULL);
5202*12723SRamaswamy.Tummala@Sun.COM
52036699Seota /* will not use the gid_info pointer, so the second arg is NULL */
52046699Seota return (ibdm_get_ioc_info_with_gid(ioc_guid, NULL));
52056699Seota }
52060Sstevel@tonic-gate
52070Sstevel@tonic-gate /*
52080Sstevel@tonic-gate * ibdm_ibnex_get_ioc_count()
52090Sstevel@tonic-gate * Returns number of ibdm_ioc_info_t it finds
52100Sstevel@tonic-gate */
52110Sstevel@tonic-gate int
ibdm_ibnex_get_ioc_count(void)52120Sstevel@tonic-gate ibdm_ibnex_get_ioc_count(void)
52130Sstevel@tonic-gate {
52140Sstevel@tonic-gate int count = 0, k;
52150Sstevel@tonic-gate ibdm_ioc_info_t *ioc;
52160Sstevel@tonic-gate ibdm_dp_gidinfo_t *gid_list;
52170Sstevel@tonic-gate
5218*12723SRamaswamy.Tummala@Sun.COM if (ibdm_enumerate_iocs == 0)
5219*12723SRamaswamy.Tummala@Sun.COM return (0);
5220*12723SRamaswamy.Tummala@Sun.COM
52210Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
52220Sstevel@tonic-gate ibdm_sweep_fabric(0);
52230Sstevel@tonic-gate
52240Sstevel@tonic-gate while (ibdm.ibdm_busy & IBDM_BUSY)
52250Sstevel@tonic-gate cv_wait(&ibdm.ibdm_busy_cv, &ibdm.ibdm_mutex);
52260Sstevel@tonic-gate ibdm.ibdm_busy |= IBDM_BUSY;
52270Sstevel@tonic-gate
52280Sstevel@tonic-gate for (gid_list = ibdm.ibdm_dp_gidlist_head; gid_list;
52290Sstevel@tonic-gate gid_list = gid_list->gl_next) {
52300Sstevel@tonic-gate mutex_enter(&gid_list->gl_mutex);
52310Sstevel@tonic-gate if ((gid_list->gl_state != IBDM_GID_PROBING_COMPLETE) ||
52320Sstevel@tonic-gate (gid_list->gl_iou == NULL)) {
52330Sstevel@tonic-gate mutex_exit(&gid_list->gl_mutex);
52340Sstevel@tonic-gate continue;
52350Sstevel@tonic-gate }
52360Sstevel@tonic-gate for (k = 0; k < gid_list->gl_iou->iou_info.iou_num_ctrl_slots;
52370Sstevel@tonic-gate k++) {
52380Sstevel@tonic-gate ioc = IBDM_GIDINFO2IOCINFO(gid_list, k);
52390Sstevel@tonic-gate if (ioc->ioc_state == IBDM_IOC_STATE_PROBE_SUCCESS)
52400Sstevel@tonic-gate ++count;
52410Sstevel@tonic-gate }
52420Sstevel@tonic-gate mutex_exit(&gid_list->gl_mutex);
52430Sstevel@tonic-gate }
52440Sstevel@tonic-gate ibdm.ibdm_busy &= ~IBDM_BUSY;
52450Sstevel@tonic-gate cv_broadcast(&ibdm.ibdm_busy_cv);
52460Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
52470Sstevel@tonic-gate
52480Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tget_ioc_count: count = %d", count);
52490Sstevel@tonic-gate return (count);
52500Sstevel@tonic-gate }
52510Sstevel@tonic-gate
52520Sstevel@tonic-gate
52530Sstevel@tonic-gate /*
52540Sstevel@tonic-gate * ibdm_ibnex_get_ioc_list()
52550Sstevel@tonic-gate * Returns information about all the IOCs present on the fabric.
52560Sstevel@tonic-gate * Reprobes the IOCs and the GID list if list_flag is set to REPROBE_ALL.
52570Sstevel@tonic-gate * Does not sweep fabric if DONOT_PROBE is set
52580Sstevel@tonic-gate */
52590Sstevel@tonic-gate ibdm_ioc_info_t *
ibdm_ibnex_get_ioc_list(ibdm_ibnex_get_ioclist_mtd_t list_flag)52600Sstevel@tonic-gate ibdm_ibnex_get_ioc_list(ibdm_ibnex_get_ioclist_mtd_t list_flag)
52610Sstevel@tonic-gate {
52620Sstevel@tonic-gate int ii;
52630Sstevel@tonic-gate ibdm_ioc_info_t *ioc_list = NULL, *tmp, *ioc;
52640Sstevel@tonic-gate ibdm_dp_gidinfo_t *gid_list;
52650Sstevel@tonic-gate ib_dm_io_unitinfo_t *iou;
52660Sstevel@tonic-gate
52670Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tget_ioc_list: Enter");
52680Sstevel@tonic-gate
5269*12723SRamaswamy.Tummala@Sun.COM if (ibdm_enumerate_iocs == 0)
5270*12723SRamaswamy.Tummala@Sun.COM return (NULL);
5271*12723SRamaswamy.Tummala@Sun.COM
52720Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
52730Sstevel@tonic-gate if (list_flag != IBDM_IBNEX_DONOT_PROBE)
52740Sstevel@tonic-gate ibdm_sweep_fabric(list_flag == IBDM_IBNEX_REPROBE_ALL);
52750Sstevel@tonic-gate
52760Sstevel@tonic-gate while (ibdm.ibdm_busy & IBDM_BUSY)
52770Sstevel@tonic-gate cv_wait(&ibdm.ibdm_busy_cv, &ibdm.ibdm_mutex);
52780Sstevel@tonic-gate ibdm.ibdm_busy |= IBDM_BUSY;
52790Sstevel@tonic-gate
52800Sstevel@tonic-gate gid_list = ibdm.ibdm_dp_gidlist_head;
52810Sstevel@tonic-gate while (gid_list) {
52820Sstevel@tonic-gate mutex_enter(&gid_list->gl_mutex);
52830Sstevel@tonic-gate if (gid_list->gl_state != IBDM_GID_PROBING_COMPLETE) {
52840Sstevel@tonic-gate mutex_exit(&gid_list->gl_mutex);
52850Sstevel@tonic-gate gid_list = gid_list->gl_next;
52860Sstevel@tonic-gate continue;
52870Sstevel@tonic-gate }
52880Sstevel@tonic-gate if (gid_list->gl_iou == NULL) {
52890Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm",
52900Sstevel@tonic-gate "\tget_ioc_list: No IOU info");
52910Sstevel@tonic-gate mutex_exit(&gid_list->gl_mutex);
52920Sstevel@tonic-gate gid_list = gid_list->gl_next;
52930Sstevel@tonic-gate continue;
52940Sstevel@tonic-gate }
52950Sstevel@tonic-gate iou = &gid_list->gl_iou->iou_info;
52960Sstevel@tonic-gate for (ii = 0; ii < iou->iou_num_ctrl_slots; ii++) {
52970Sstevel@tonic-gate ioc = IBDM_GIDINFO2IOCINFO(gid_list, ii);
52980Sstevel@tonic-gate if (ioc->ioc_state == IBDM_IOC_STATE_PROBE_SUCCESS) {
52990Sstevel@tonic-gate tmp = ibdm_dup_ioc_info(ioc, gid_list);
53000Sstevel@tonic-gate tmp->ioc_next = ioc_list;
53010Sstevel@tonic-gate ioc_list = tmp;
53020Sstevel@tonic-gate }
53030Sstevel@tonic-gate }
53040Sstevel@tonic-gate mutex_exit(&gid_list->gl_mutex);
53050Sstevel@tonic-gate gid_list = gid_list->gl_next;
53060Sstevel@tonic-gate }
53070Sstevel@tonic-gate ibdm.ibdm_busy &= ~IBDM_BUSY;
53080Sstevel@tonic-gate cv_broadcast(&ibdm.ibdm_busy_cv);
53090Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
53100Sstevel@tonic-gate
53110Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tget_ioc_list: End");
53120Sstevel@tonic-gate return (ioc_list);
53130Sstevel@tonic-gate }
53140Sstevel@tonic-gate
53150Sstevel@tonic-gate /*
53160Sstevel@tonic-gate * ibdm_dup_ioc_info()
53170Sstevel@tonic-gate * Duplicate the IOC information and return the IOC
53180Sstevel@tonic-gate * information.
53190Sstevel@tonic-gate */
53200Sstevel@tonic-gate static ibdm_ioc_info_t *
ibdm_dup_ioc_info(ibdm_ioc_info_t * in_ioc,ibdm_dp_gidinfo_t * gid_list)53210Sstevel@tonic-gate ibdm_dup_ioc_info(ibdm_ioc_info_t *in_ioc, ibdm_dp_gidinfo_t *gid_list)
53220Sstevel@tonic-gate {
53230Sstevel@tonic-gate ibdm_ioc_info_t *out_ioc;
53240Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*out_ioc));
53256262Seota ASSERT(MUTEX_HELD(&gid_list->gl_mutex));
53260Sstevel@tonic-gate
53270Sstevel@tonic-gate out_ioc = kmem_alloc(sizeof (ibdm_ioc_info_t), KM_SLEEP);
53280Sstevel@tonic-gate bcopy(in_ioc, out_ioc, sizeof (ibdm_ioc_info_t));
53290Sstevel@tonic-gate ibdm_update_ioc_port_gidlist(out_ioc, gid_list);
53300Sstevel@tonic-gate out_ioc->ioc_iou_dc_valid = gid_list->gl_iou->iou_dc_valid;
53310Sstevel@tonic-gate out_ioc->ioc_iou_diagcode = gid_list->gl_iou->iou_diagcode;
53320Sstevel@tonic-gate
53330Sstevel@tonic-gate return (out_ioc);
53340Sstevel@tonic-gate }
53350Sstevel@tonic-gate
53360Sstevel@tonic-gate
53370Sstevel@tonic-gate /*
53380Sstevel@tonic-gate * ibdm_free_ioc_list()
53390Sstevel@tonic-gate * Deallocate memory for IOC list structure
53400Sstevel@tonic-gate */
53410Sstevel@tonic-gate void
ibdm_ibnex_free_ioc_list(ibdm_ioc_info_t * ioc)53420Sstevel@tonic-gate ibdm_ibnex_free_ioc_list(ibdm_ioc_info_t *ioc)
53430Sstevel@tonic-gate {
53440Sstevel@tonic-gate ibdm_ioc_info_t *temp;
53450Sstevel@tonic-gate
53460Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tibnex_free_ioc_list:");
53470Sstevel@tonic-gate while (ioc) {
53480Sstevel@tonic-gate temp = ioc;
53490Sstevel@tonic-gate ioc = ioc->ioc_next;
53500Sstevel@tonic-gate kmem_free(temp->ioc_gid_list,
53510Sstevel@tonic-gate (sizeof (ibdm_gid_t) * temp->ioc_nportgids));
53520Sstevel@tonic-gate if (temp->ioc_hca_list)
53530Sstevel@tonic-gate ibdm_ibnex_free_hca_list(temp->ioc_hca_list);
53540Sstevel@tonic-gate kmem_free(temp, sizeof (ibdm_ioc_info_t));
53550Sstevel@tonic-gate }
53560Sstevel@tonic-gate }
53570Sstevel@tonic-gate
53580Sstevel@tonic-gate
53590Sstevel@tonic-gate /*
53600Sstevel@tonic-gate * ibdm_ibnex_update_pkey_tbls
53610Sstevel@tonic-gate * Updates the DM P_Key database.
53620Sstevel@tonic-gate * NOTE: Two cases are handled here: P_Key being added or removed.
53630Sstevel@tonic-gate *
53640Sstevel@tonic-gate * Arguments : NONE
53650Sstevel@tonic-gate * Return Values : NONE
53660Sstevel@tonic-gate */
53670Sstevel@tonic-gate void
ibdm_ibnex_update_pkey_tbls(void)53680Sstevel@tonic-gate ibdm_ibnex_update_pkey_tbls(void)
53690Sstevel@tonic-gate {
53700Sstevel@tonic-gate int h, pp, pidx;
53710Sstevel@tonic-gate uint_t nports;
53720Sstevel@tonic-gate uint_t size;
53730Sstevel@tonic-gate ib_pkey_t new_pkey;
53740Sstevel@tonic-gate ib_pkey_t *orig_pkey;
53750Sstevel@tonic-gate ibdm_hca_list_t *hca_list;
53760Sstevel@tonic-gate ibdm_port_attr_t *port;
53770Sstevel@tonic-gate ibt_hca_portinfo_t *pinfop;
53780Sstevel@tonic-gate
53790Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tibnex_update_pkey_tbls:");
53800Sstevel@tonic-gate
53810Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_hl_mutex);
53820Sstevel@tonic-gate hca_list = ibdm.ibdm_hca_list_head;
53830Sstevel@tonic-gate
53840Sstevel@tonic-gate for (h = 0; h < ibdm.ibdm_hca_count; h++) {
53850Sstevel@tonic-gate
53860Sstevel@tonic-gate /* This updates P_Key Tables for all ports of this HCA */
53870Sstevel@tonic-gate (void) ibt_query_hca_ports(hca_list->hl_hca_hdl, 0, &pinfop,
53880Sstevel@tonic-gate &nports, &size);
53890Sstevel@tonic-gate
53900Sstevel@tonic-gate /* number of ports shouldn't have changed */
53910Sstevel@tonic-gate ASSERT(nports == hca_list->hl_nports);
53920Sstevel@tonic-gate
53930Sstevel@tonic-gate for (pp = 0; pp < hca_list->hl_nports; pp++) {
53940Sstevel@tonic-gate port = &hca_list->hl_port_attr[pp];
53950Sstevel@tonic-gate
53960Sstevel@tonic-gate /*
53970Sstevel@tonic-gate * First figure out the P_Keys from IBTL.
53980Sstevel@tonic-gate * Three things could have happened:
53990Sstevel@tonic-gate * New P_Keys added
54000Sstevel@tonic-gate * Existing P_Keys removed
54010Sstevel@tonic-gate * Both of the above two
54020Sstevel@tonic-gate *
54030Sstevel@tonic-gate * Loop through the P_Key Indices and check if a
54040Sstevel@tonic-gate * give P_Key_Ix matches that of the one seen by
54050Sstevel@tonic-gate * IBDM. If they match no action is needed.
54060Sstevel@tonic-gate *
54070Sstevel@tonic-gate * If they don't match:
54080Sstevel@tonic-gate * 1. if orig_pkey is invalid and new_pkey is valid
54090Sstevel@tonic-gate * ---> add new_pkey to DM database
54100Sstevel@tonic-gate * 2. if orig_pkey is valid and new_pkey is invalid
54110Sstevel@tonic-gate * ---> remove orig_pkey from DM database
54120Sstevel@tonic-gate * 3. if orig_pkey and new_pkey are both valid:
54130Sstevel@tonic-gate * ---> remov orig_pkey from DM database
54140Sstevel@tonic-gate * ---> add new_pkey to DM database
54150Sstevel@tonic-gate * 4. if orig_pkey and new_pkey are both invalid:
54160Sstevel@tonic-gate * ---> do nothing. Updated DM database.
54170Sstevel@tonic-gate */
54180Sstevel@tonic-gate
54190Sstevel@tonic-gate for (pidx = 0; pidx < port->pa_npkeys; pidx++) {
54200Sstevel@tonic-gate new_pkey = pinfop[pp].p_pkey_tbl[pidx];
54210Sstevel@tonic-gate orig_pkey = &port->pa_pkey_tbl[pidx].pt_pkey;
54220Sstevel@tonic-gate
54230Sstevel@tonic-gate /* keys match - do nothing */
54240Sstevel@tonic-gate if (*orig_pkey == new_pkey)
54250Sstevel@tonic-gate continue;
54260Sstevel@tonic-gate
54270Sstevel@tonic-gate if (IBDM_INVALID_PKEY(*orig_pkey) &&
54280Sstevel@tonic-gate !IBDM_INVALID_PKEY(new_pkey)) {
54290Sstevel@tonic-gate /* P_Key was added */
54300Sstevel@tonic-gate IBTF_DPRINTF_L5("ibdm",
54310Sstevel@tonic-gate "\tibnex_update_pkey_tbls: new "
54320Sstevel@tonic-gate "P_Key added = 0x%x", new_pkey);
54330Sstevel@tonic-gate *orig_pkey = new_pkey;
54340Sstevel@tonic-gate ibdm_port_attr_ibmf_init(port,
54350Sstevel@tonic-gate new_pkey, pp);
54360Sstevel@tonic-gate } else if (!IBDM_INVALID_PKEY(*orig_pkey) &&
54370Sstevel@tonic-gate IBDM_INVALID_PKEY(new_pkey)) {
54380Sstevel@tonic-gate /* P_Key was removed */
54390Sstevel@tonic-gate IBTF_DPRINTF_L5("ibdm",
54400Sstevel@tonic-gate "\tibnex_update_pkey_tbls: P_Key "
54410Sstevel@tonic-gate "removed = 0x%x", *orig_pkey);
54420Sstevel@tonic-gate *orig_pkey = new_pkey;
54430Sstevel@tonic-gate (void) ibdm_port_attr_ibmf_fini(port,
54440Sstevel@tonic-gate pidx);
54450Sstevel@tonic-gate } else if (!IBDM_INVALID_PKEY(*orig_pkey) &&
54460Sstevel@tonic-gate !IBDM_INVALID_PKEY(new_pkey)) {
54470Sstevel@tonic-gate /* P_Key were replaced */
54480Sstevel@tonic-gate IBTF_DPRINTF_L5("ibdm",
54490Sstevel@tonic-gate "\tibnex_update_pkey_tbls: P_Key "
54500Sstevel@tonic-gate "replaced 0x%x with 0x%x",
54510Sstevel@tonic-gate *orig_pkey, new_pkey);
54520Sstevel@tonic-gate (void) ibdm_port_attr_ibmf_fini(port,
54530Sstevel@tonic-gate pidx);
54540Sstevel@tonic-gate *orig_pkey = new_pkey;
54550Sstevel@tonic-gate ibdm_port_attr_ibmf_init(port,
54560Sstevel@tonic-gate new_pkey, pp);
54570Sstevel@tonic-gate } else {
54580Sstevel@tonic-gate /*
54590Sstevel@tonic-gate * P_Keys are invalid
54600Sstevel@tonic-gate * set anyway to reflect if
54610Sstevel@tonic-gate * INVALID_FULL was changed to
54620Sstevel@tonic-gate * INVALID_LIMITED or vice-versa.
54630Sstevel@tonic-gate */
54640Sstevel@tonic-gate *orig_pkey = new_pkey;
54650Sstevel@tonic-gate } /* end of else */
54660Sstevel@tonic-gate
54670Sstevel@tonic-gate } /* loop of p_key index */
54680Sstevel@tonic-gate
54690Sstevel@tonic-gate } /* loop of #ports of HCA */
54700Sstevel@tonic-gate
54710Sstevel@tonic-gate ibt_free_portinfo(pinfop, size);
54720Sstevel@tonic-gate hca_list = hca_list->hl_next;
54730Sstevel@tonic-gate
54740Sstevel@tonic-gate } /* loop for all HCAs in the system */
54750Sstevel@tonic-gate
54760Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_hl_mutex);
54770Sstevel@tonic-gate }
54780Sstevel@tonic-gate
54790Sstevel@tonic-gate
54800Sstevel@tonic-gate /*
54810Sstevel@tonic-gate * ibdm_send_ioc_profile()
54820Sstevel@tonic-gate * Send IOC Controller Profile request. When the request is completed
54830Sstevel@tonic-gate * IBMF calls ibdm_process_incoming_mad routine to inform about
54840Sstevel@tonic-gate * the completion.
54850Sstevel@tonic-gate */
54860Sstevel@tonic-gate static int
ibdm_send_ioc_profile(ibdm_dp_gidinfo_t * gid_info,uint8_t ioc_no)54870Sstevel@tonic-gate ibdm_send_ioc_profile(ibdm_dp_gidinfo_t *gid_info, uint8_t ioc_no)
54880Sstevel@tonic-gate {
54890Sstevel@tonic-gate ibmf_msg_t *msg;
54900Sstevel@tonic-gate ib_mad_hdr_t *hdr;
54910Sstevel@tonic-gate ibdm_ioc_info_t *ioc_info = &(gid_info->gl_iou->iou_ioc_info[ioc_no]);
54920Sstevel@tonic-gate ibdm_timeout_cb_args_t *cb_args;
54930Sstevel@tonic-gate
54940Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tsend_ioc_profile: "
54950Sstevel@tonic-gate "gid info 0x%p, ioc_no = %d", gid_info, ioc_no);
54960Sstevel@tonic-gate
54970Sstevel@tonic-gate /*
54980Sstevel@tonic-gate * Send command to get IOC profile.
54990Sstevel@tonic-gate * Allocate a IBMF packet and initialize the packet.
55000Sstevel@tonic-gate */
55010Sstevel@tonic-gate if (ibmf_alloc_msg(gid_info->gl_ibmf_hdl, IBMF_ALLOC_SLEEP,
55020Sstevel@tonic-gate &msg) != IBMF_SUCCESS) {
550310096SSudhakar.Dindukurti@Sun.COM IBTF_DPRINTF_L2("ibdm", "\tsend_ioc_profile: pkt alloc fail");
55040Sstevel@tonic-gate return (IBDM_FAILURE);
55050Sstevel@tonic-gate }
55060Sstevel@tonic-gate
55076699Seota _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*msg))
55080Sstevel@tonic-gate ibdm_alloc_send_buffers(msg);
55096699Seota _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*msg))
55100Sstevel@tonic-gate
55111093Shiremath mutex_enter(&gid_info->gl_mutex);
55121093Shiremath ibdm_bump_transactionID(gid_info);
55131093Shiremath mutex_exit(&gid_info->gl_mutex);
55141093Shiremath
55150Sstevel@tonic-gate msg->im_local_addr.ia_local_lid = gid_info->gl_slid;
55160Sstevel@tonic-gate msg->im_local_addr.ia_remote_lid = gid_info->gl_dlid;
55170Sstevel@tonic-gate if (gid_info->gl_redirected == B_TRUE) {
55180Sstevel@tonic-gate if (gid_info->gl_redirect_dlid != 0) {
55190Sstevel@tonic-gate msg->im_local_addr.ia_remote_lid =
55200Sstevel@tonic-gate gid_info->gl_redirect_dlid;
55210Sstevel@tonic-gate }
55220Sstevel@tonic-gate msg->im_local_addr.ia_remote_qno = gid_info->gl_redirect_QP;
55230Sstevel@tonic-gate msg->im_local_addr.ia_p_key = gid_info->gl_redirect_pkey;
55240Sstevel@tonic-gate msg->im_local_addr.ia_q_key = gid_info->gl_redirect_qkey;
55256699Seota msg->im_local_addr.ia_service_level = gid_info->gl_redirectSL;
55260Sstevel@tonic-gate } else {
55270Sstevel@tonic-gate msg->im_local_addr.ia_remote_qno = 1;
55280Sstevel@tonic-gate msg->im_local_addr.ia_p_key = gid_info->gl_p_key;
55290Sstevel@tonic-gate msg->im_local_addr.ia_q_key = IB_GSI_QKEY;
55306699Seota msg->im_local_addr.ia_service_level = gid_info->gl_SL;
55310Sstevel@tonic-gate }
55320Sstevel@tonic-gate
55330Sstevel@tonic-gate hdr = IBDM_OUT_IBMFMSG_MADHDR(msg);
55340Sstevel@tonic-gate hdr->BaseVersion = MAD_CLASS_BASE_VERS_1;
55350Sstevel@tonic-gate hdr->MgmtClass = MAD_MGMT_CLASS_DEV_MGT;
55360Sstevel@tonic-gate hdr->ClassVersion = IB_DM_CLASS_VERSION_1;
55370Sstevel@tonic-gate hdr->R_Method = IB_DM_DEVMGT_METHOD_GET;
55380Sstevel@tonic-gate hdr->Status = 0;
55390Sstevel@tonic-gate hdr->TransactionID = h2b64(gid_info->gl_transactionID);
55400Sstevel@tonic-gate hdr->AttributeID = h2b16(IB_DM_ATTR_IOC_CTRL_PROFILE);
55410Sstevel@tonic-gate hdr->AttributeModifier = h2b32(ioc_no + 1);
55420Sstevel@tonic-gate
55430Sstevel@tonic-gate ioc_info->ioc_state = IBDM_IOC_STATE_REPROBE_PROGRESS;
55440Sstevel@tonic-gate cb_args = &ioc_info->ioc_cb_args;
55450Sstevel@tonic-gate cb_args->cb_gid_info = gid_info;
55460Sstevel@tonic-gate cb_args->cb_retry_count = ibdm_dft_retry_cnt;
55470Sstevel@tonic-gate cb_args->cb_req_type = IBDM_REQ_TYPE_IOCINFO;
55480Sstevel@tonic-gate cb_args->cb_ioc_num = ioc_no;
55490Sstevel@tonic-gate
55506699Seota mutex_enter(&gid_info->gl_mutex);
55510Sstevel@tonic-gate ioc_info->ioc_timeout_id = timeout(ibdm_pkt_timeout_hdlr,
55520Sstevel@tonic-gate cb_args, IBDM_TIMEOUT_VALUE(ibdm_dft_timeout));
55536699Seota mutex_exit(&gid_info->gl_mutex);
55540Sstevel@tonic-gate
55550Sstevel@tonic-gate IBTF_DPRINTF_L5("ibdm", "\tsend_ioc_profile:"
55560Sstevel@tonic-gate "timeout %x", ioc_info->ioc_timeout_id);
55570Sstevel@tonic-gate
55580Sstevel@tonic-gate if (ibmf_msg_transport(gid_info->gl_ibmf_hdl, gid_info->gl_qp_hdl, msg,
55590Sstevel@tonic-gate NULL, ibdm_ibmf_send_cb, cb_args, 0) != IBMF_SUCCESS) {
55600Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm",
55610Sstevel@tonic-gate "\tsend_ioc_profile: msg transport failed");
55620Sstevel@tonic-gate ibdm_ibmf_send_cb(gid_info->gl_ibmf_hdl, msg, cb_args);
55630Sstevel@tonic-gate }
55640Sstevel@tonic-gate ioc_info->ioc_state = IBDM_IOC_STATE_REPROBE_PROGRESS;
55650Sstevel@tonic-gate return (IBDM_SUCCESS);
55660Sstevel@tonic-gate }
55670Sstevel@tonic-gate
55680Sstevel@tonic-gate
55690Sstevel@tonic-gate /*
55700Sstevel@tonic-gate * ibdm_port_reachable
55716262Seota * Returns B_TRUE if the port GID is reachable by sending
55726262Seota * a SA query to get the NODE record for this port GUID.
55736262Seota */
55746262Seota static boolean_t
ibdm_port_reachable(ibmf_saa_handle_t sa_hdl,ib_guid_t guid)55756262Seota ibdm_port_reachable(ibmf_saa_handle_t sa_hdl, ib_guid_t guid)
55766262Seota {
55776262Seota sa_node_record_t *resp;
55786262Seota size_t length;
55796262Seota
55806262Seota /*
55816262Seota * Verify if it's reachable by getting the node record.
55826262Seota */
55836262Seota if (ibdm_get_node_record_by_port(sa_hdl, guid, &resp, &length) ==
55846262Seota IBDM_SUCCESS) {
55856262Seota kmem_free(resp, length);
55866262Seota return (B_TRUE);
55876262Seota }
55886262Seota return (B_FALSE);
55896262Seota }
55906262Seota
55916262Seota /*
55926262Seota * ibdm_get_node_record_by_port
55930Sstevel@tonic-gate * Sends a SA query to get the NODE record for port GUID
55946262Seota * Returns IBDM_SUCCESS if the port GID is reachable.
55956262Seota *
55966262Seota * Note: the caller must be responsible for freeing the resource
55976262Seota * by calling kmem_free(resp, length) later.
55980Sstevel@tonic-gate */
55990Sstevel@tonic-gate static int
ibdm_get_node_record_by_port(ibmf_saa_handle_t sa_hdl,ib_guid_t guid,sa_node_record_t ** resp,size_t * length)56006262Seota ibdm_get_node_record_by_port(ibmf_saa_handle_t sa_hdl, ib_guid_t guid,
56016262Seota sa_node_record_t **resp, size_t *length)
56020Sstevel@tonic-gate {
56036262Seota sa_node_record_t req;
56040Sstevel@tonic-gate ibmf_saa_access_args_t args;
56050Sstevel@tonic-gate int ret;
56066262Seota ASSERT(resp != NULL && length != NULL);
56070Sstevel@tonic-gate
56080Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tport_reachable: port_guid %llx",
56090Sstevel@tonic-gate guid);
56100Sstevel@tonic-gate
56110Sstevel@tonic-gate bzero(&req, sizeof (sa_node_record_t));
56120Sstevel@tonic-gate req.NodeInfo.PortGUID = guid;
56130Sstevel@tonic-gate
56140Sstevel@tonic-gate args.sq_attr_id = SA_NODERECORD_ATTRID;
56150Sstevel@tonic-gate args.sq_access_type = IBMF_SAA_RETRIEVE;
56160Sstevel@tonic-gate args.sq_component_mask = SA_NODEINFO_COMPMASK_PORTGUID;
56170Sstevel@tonic-gate args.sq_template = &req;
56180Sstevel@tonic-gate args.sq_callback = NULL;
56190Sstevel@tonic-gate args.sq_callback_arg = NULL;
56200Sstevel@tonic-gate
56216262Seota ret = ibmf_sa_access(sa_hdl, &args, 0, length, (void **) resp);
56220Sstevel@tonic-gate if (ret != IBMF_SUCCESS) {
56230Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "\tport_reachable:"
56240Sstevel@tonic-gate " SA Retrieve Failed: %d", ret);
56250Sstevel@tonic-gate return (IBDM_FAILURE);
56260Sstevel@tonic-gate }
56276601Seota if (*resp == NULL || *length == 0) {
56286601Seota IBTF_DPRINTF_L2("ibdm", "\tport_reachable: No records");
56296601Seota return (IBDM_FAILURE);
56306601Seota }
56316262Seota /*
56326262Seota * There is one NodeRecord on each endport on a subnet.
56336262Seota */
56346262Seota ASSERT(*length == sizeof (sa_node_record_t));
56356262Seota
56360Sstevel@tonic-gate return (IBDM_SUCCESS);
56370Sstevel@tonic-gate }
56380Sstevel@tonic-gate
56396262Seota
56400Sstevel@tonic-gate /*
56410Sstevel@tonic-gate * Update the gidlist for all affected IOCs when GID becomes
56420Sstevel@tonic-gate * available/unavailable.
56430Sstevel@tonic-gate *
56440Sstevel@tonic-gate * Parameters :
56450Sstevel@tonic-gate * gidinfo - Incoming / Outgoing GID.
56460Sstevel@tonic-gate * add_flag - 1 for GID added, 0 for GID removed.
56470Sstevel@tonic-gate * - (-1) : IOC gid list updated, ioc_list required.
56480Sstevel@tonic-gate *
56490Sstevel@tonic-gate * This function gets the GID for the node GUID corresponding to the
56500Sstevel@tonic-gate * port GID. Gets the IOU info
56510Sstevel@tonic-gate */
56520Sstevel@tonic-gate static ibdm_ioc_info_t *
ibdm_update_ioc_gidlist(ibdm_dp_gidinfo_t * gid_info,int avail_flag)56530Sstevel@tonic-gate ibdm_update_ioc_gidlist(ibdm_dp_gidinfo_t *gid_info, int avail_flag)
56540Sstevel@tonic-gate {
56550Sstevel@tonic-gate ibdm_dp_gidinfo_t *node_gid = NULL;
56560Sstevel@tonic-gate uint8_t niocs, ii;
56570Sstevel@tonic-gate ibdm_ioc_info_t *ioc, *ioc_list = NULL, *tmp;
56580Sstevel@tonic-gate
56590Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tupdate_ioc_gidlist");
56600Sstevel@tonic-gate
56610Sstevel@tonic-gate switch (avail_flag) {
56620Sstevel@tonic-gate case 1 :
56630Sstevel@tonic-gate node_gid = ibdm_check_dest_nodeguid(gid_info);
56640Sstevel@tonic-gate break;
56650Sstevel@tonic-gate case 0 :
56660Sstevel@tonic-gate node_gid = ibdm_handle_gid_rm(gid_info);
56670Sstevel@tonic-gate break;
56680Sstevel@tonic-gate case -1 :
56690Sstevel@tonic-gate node_gid = gid_info;
56700Sstevel@tonic-gate break;
56710Sstevel@tonic-gate default :
56720Sstevel@tonic-gate break;
56730Sstevel@tonic-gate }
56740Sstevel@tonic-gate
56750Sstevel@tonic-gate if (node_gid == NULL) {
56760Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tupdate_ioc_gidlist: "
56770Sstevel@tonic-gate "No node GID found, port gid 0x%p, avail_flag %d",
56780Sstevel@tonic-gate gid_info, avail_flag);
56790Sstevel@tonic-gate return (NULL);
56800Sstevel@tonic-gate }
56810Sstevel@tonic-gate
56820Sstevel@tonic-gate mutex_enter(&node_gid->gl_mutex);
56830Sstevel@tonic-gate if ((node_gid->gl_state != IBDM_GID_PROBING_COMPLETE &&
56840Sstevel@tonic-gate node_gid->gl_state != IBDM_GID_PROBING_SKIPPED) ||
56850Sstevel@tonic-gate node_gid->gl_iou == NULL) {
56860Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tupdate_ioc_gidlist "
56870Sstevel@tonic-gate "gl_state %x, gl_iou %p", node_gid->gl_state,
56880Sstevel@tonic-gate node_gid->gl_iou);
56890Sstevel@tonic-gate mutex_exit(&node_gid->gl_mutex);
56900Sstevel@tonic-gate return (NULL);
56910Sstevel@tonic-gate }
56920Sstevel@tonic-gate
56930Sstevel@tonic-gate niocs = node_gid->gl_iou->iou_info.iou_num_ctrl_slots;
56940Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tupdate_ioc_gidlist : niocs %x",
56950Sstevel@tonic-gate niocs);
56960Sstevel@tonic-gate for (ii = 0; ii < niocs; ii++) {
56970Sstevel@tonic-gate ioc = IBDM_GIDINFO2IOCINFO(node_gid, ii);
56980Sstevel@tonic-gate /*
56990Sstevel@tonic-gate * Skip IOCs for which probe is not complete or
57000Sstevel@tonic-gate * reprobe is progress
57010Sstevel@tonic-gate */
57020Sstevel@tonic-gate if (ioc->ioc_state == IBDM_IOC_STATE_PROBE_SUCCESS) {
57030Sstevel@tonic-gate tmp = ibdm_dup_ioc_info(ioc, node_gid);
57040Sstevel@tonic-gate tmp->ioc_info_updated.ib_gid_prop_updated = 1;
57050Sstevel@tonic-gate tmp->ioc_next = ioc_list;
57060Sstevel@tonic-gate ioc_list = tmp;
57070Sstevel@tonic-gate }
57080Sstevel@tonic-gate }
57090Sstevel@tonic-gate mutex_exit(&node_gid->gl_mutex);
57100Sstevel@tonic-gate
57110Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tupdate_ioc_gidlist : return %p",
57120Sstevel@tonic-gate ioc_list);
57130Sstevel@tonic-gate return (ioc_list);
57140Sstevel@tonic-gate }
57150Sstevel@tonic-gate
57160Sstevel@tonic-gate /*
57170Sstevel@tonic-gate * ibdm_saa_event_cb :
57180Sstevel@tonic-gate * Event handling which does *not* require ibdm_hl_mutex to be
57190Sstevel@tonic-gate * held are executed in the same thread. This is to prevent
57200Sstevel@tonic-gate * deadlocks with HCA port down notifications which hold the
57210Sstevel@tonic-gate * ibdm_hl_mutex.
57220Sstevel@tonic-gate *
57230Sstevel@tonic-gate * GID_AVAILABLE event is handled here. A taskq is spawned to
57240Sstevel@tonic-gate * handle GID_UNAVAILABLE.
57250Sstevel@tonic-gate *
57260Sstevel@tonic-gate * A new mutex ibdm_ibnex_mutex has been introduced to protect
57270Sstevel@tonic-gate * ibnex_callback. This has been done to prevent any possible
57280Sstevel@tonic-gate * deadlock (described above) while handling GID_AVAILABLE.
57290Sstevel@tonic-gate *
57300Sstevel@tonic-gate * IBMF calls the event callback for a HCA port. The SA handle
57310Sstevel@tonic-gate * for this port would be valid, till the callback returns.
57320Sstevel@tonic-gate * IBDM calling IBDM using the above SA handle should be valid.
57330Sstevel@tonic-gate *
57340Sstevel@tonic-gate * IBDM will additionally check (SA handle != NULL), before
57350Sstevel@tonic-gate * calling IBMF.
57360Sstevel@tonic-gate */
57370Sstevel@tonic-gate /*ARGSUSED*/
57380Sstevel@tonic-gate static void
ibdm_saa_event_cb(ibmf_saa_handle_t ibmf_saa_handle,ibmf_saa_subnet_event_t ibmf_saa_event,ibmf_saa_event_details_t * event_details,void * callback_arg)57390Sstevel@tonic-gate ibdm_saa_event_cb(ibmf_saa_handle_t ibmf_saa_handle,
57400Sstevel@tonic-gate ibmf_saa_subnet_event_t ibmf_saa_event,
57410Sstevel@tonic-gate ibmf_saa_event_details_t *event_details, void *callback_arg)
57420Sstevel@tonic-gate {
57430Sstevel@tonic-gate ibdm_saa_event_arg_t *event_arg;
57440Sstevel@tonic-gate ib_gid_t sgid, dgid;
57450Sstevel@tonic-gate ibdm_port_attr_t *hca_port;
57460Sstevel@tonic-gate ibdm_dp_gidinfo_t *gid_info, *node_gid_info = NULL;
57476262Seota sa_node_record_t *nrec;
57486262Seota size_t length;
57490Sstevel@tonic-gate
57500Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*event_arg));
57510Sstevel@tonic-gate
57520Sstevel@tonic-gate hca_port = (ibdm_port_attr_t *)callback_arg;
57530Sstevel@tonic-gate
57540Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tsaa_event_cb(%x, %x, %x, %x)\n",
57550Sstevel@tonic-gate ibmf_saa_handle, ibmf_saa_event, event_details,
57560Sstevel@tonic-gate callback_arg);
5757*12723SRamaswamy.Tummala@Sun.COM
57580Sstevel@tonic-gate #ifdef DEBUG
57590Sstevel@tonic-gate if (ibdm_ignore_saa_event)
57600Sstevel@tonic-gate return;
57610Sstevel@tonic-gate #endif
57620Sstevel@tonic-gate
57630Sstevel@tonic-gate if (ibmf_saa_event == IBMF_SAA_EVENT_GID_AVAILABLE) {
57640Sstevel@tonic-gate /*
57650Sstevel@tonic-gate * Ensure no other probe / sweep fabric is in
57660Sstevel@tonic-gate * progress.
57670Sstevel@tonic-gate */
57680Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
57690Sstevel@tonic-gate while (ibdm.ibdm_busy & IBDM_BUSY)
57700Sstevel@tonic-gate cv_wait(&ibdm.ibdm_busy_cv, &ibdm.ibdm_mutex);
57710Sstevel@tonic-gate ibdm.ibdm_busy |= IBDM_BUSY;
57720Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
57730Sstevel@tonic-gate
57740Sstevel@tonic-gate /*
57750Sstevel@tonic-gate * If we already know about this GID, return.
57760Sstevel@tonic-gate * GID_AVAILABLE may be reported for multiple HCA
57770Sstevel@tonic-gate * ports.
57780Sstevel@tonic-gate */
57790Sstevel@tonic-gate if ((ibdm_check_dgid(event_details->ie_gid.gid_guid,
57800Sstevel@tonic-gate event_details->ie_gid.gid_prefix)) != NULL) {
57810Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
57820Sstevel@tonic-gate ibdm.ibdm_busy &= ~IBDM_BUSY;
57830Sstevel@tonic-gate cv_broadcast(&ibdm.ibdm_busy_cv);
57840Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
57850Sstevel@tonic-gate return;
57860Sstevel@tonic-gate }
57870Sstevel@tonic-gate
57880Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tGID (prefix %x, guid %llx) "
57890Sstevel@tonic-gate "Insertion notified",
57900Sstevel@tonic-gate event_details->ie_gid.gid_prefix,
57910Sstevel@tonic-gate event_details->ie_gid.gid_guid);
57920Sstevel@tonic-gate
57930Sstevel@tonic-gate /* This is a new gid, insert it to GID list */
57940Sstevel@tonic-gate sgid.gid_prefix = hca_port->pa_sn_prefix;
57950Sstevel@tonic-gate sgid.gid_guid = hca_port->pa_port_guid;
57960Sstevel@tonic-gate dgid.gid_prefix = event_details->ie_gid.gid_prefix;
57970Sstevel@tonic-gate dgid.gid_guid = event_details->ie_gid.gid_guid;
57980Sstevel@tonic-gate gid_info = ibdm_create_gid_info(hca_port, sgid, dgid);
57990Sstevel@tonic-gate if (gid_info == NULL) {
58000Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tGID_AVAILABLE: "
58010Sstevel@tonic-gate "create_gid_info returned NULL");
58020Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
58030Sstevel@tonic-gate ibdm.ibdm_busy &= ~IBDM_BUSY;
58040Sstevel@tonic-gate cv_broadcast(&ibdm.ibdm_busy_cv);
58050Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
58060Sstevel@tonic-gate return;
58070Sstevel@tonic-gate }
58080Sstevel@tonic-gate mutex_enter(&gid_info->gl_mutex);
58090Sstevel@tonic-gate gid_info->gl_state = IBDM_GID_PROBING_SKIPPED;
58100Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
58110Sstevel@tonic-gate
58120Sstevel@tonic-gate /* Get the node GUID */
58136262Seota if (ibdm_get_node_record_by_port(ibmf_saa_handle, dgid.gid_guid,
58146262Seota &nrec, &length) != IBDM_SUCCESS) {
58150Sstevel@tonic-gate /*
58160Sstevel@tonic-gate * Set the state to PROBE_NOT_DONE for the
58170Sstevel@tonic-gate * next sweep to probe it
58180Sstevel@tonic-gate */
58190Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "\tsaa_event_taskq: "
58200Sstevel@tonic-gate "Skipping GID : port GUID not found");
58210Sstevel@tonic-gate mutex_enter(&gid_info->gl_mutex);
58220Sstevel@tonic-gate gid_info->gl_state = IBDM_GID_PROBE_NOT_DONE;
58230Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
58240Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
58250Sstevel@tonic-gate ibdm.ibdm_busy &= ~IBDM_BUSY;
58260Sstevel@tonic-gate cv_broadcast(&ibdm.ibdm_busy_cv);
58270Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
58280Sstevel@tonic-gate return;
58290Sstevel@tonic-gate }
58306262Seota gid_info->gl_nodeguid = nrec->NodeInfo.NodeGUID;
58316262Seota gid_info->gl_devid = nrec->NodeInfo.DeviceID;
58326262Seota kmem_free(nrec, length);
58330Sstevel@tonic-gate gid_info->gl_portguid = dgid.gid_guid;
58340Sstevel@tonic-gate
58350Sstevel@tonic-gate /*
58360Sstevel@tonic-gate * Get the gid info with the same node GUID.
58370Sstevel@tonic-gate */
58380Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
58390Sstevel@tonic-gate node_gid_info = ibdm.ibdm_dp_gidlist_head;
58400Sstevel@tonic-gate while (node_gid_info) {
58410Sstevel@tonic-gate if (node_gid_info->gl_nodeguid ==
58420Sstevel@tonic-gate gid_info->gl_nodeguid &&
58430Sstevel@tonic-gate node_gid_info->gl_iou != NULL) {
58440Sstevel@tonic-gate break;
58450Sstevel@tonic-gate }
58460Sstevel@tonic-gate node_gid_info = node_gid_info->gl_next;
58470Sstevel@tonic-gate }
58480Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
58490Sstevel@tonic-gate
58500Sstevel@tonic-gate /*
58510Sstevel@tonic-gate * Handling a new GID requires filling of gl_hca_list.
58520Sstevel@tonic-gate * This require ibdm hca_list to be parsed and hence
58530Sstevel@tonic-gate * holding the ibdm_hl_mutex. Spawning a new thread to
58540Sstevel@tonic-gate * handle this.
58550Sstevel@tonic-gate */
58560Sstevel@tonic-gate if (node_gid_info == NULL) {
58570Sstevel@tonic-gate if (taskq_dispatch(system_taskq,
58580Sstevel@tonic-gate ibdm_saa_handle_new_gid, (void *)gid_info,
58590Sstevel@tonic-gate TQ_NOSLEEP) == NULL) {
58600Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "\tsaa_event_cb: "
58610Sstevel@tonic-gate "new_gid taskq_dispatch failed");
58620Sstevel@tonic-gate return;
58630Sstevel@tonic-gate }
58640Sstevel@tonic-gate }
58650Sstevel@tonic-gate
58660Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
58670Sstevel@tonic-gate ibdm.ibdm_busy &= ~IBDM_BUSY;
58680Sstevel@tonic-gate cv_broadcast(&ibdm.ibdm_busy_cv);
58690Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
58700Sstevel@tonic-gate return;
58710Sstevel@tonic-gate }
58720Sstevel@tonic-gate
58730Sstevel@tonic-gate if (ibmf_saa_event != IBMF_SAA_EVENT_GID_UNAVAILABLE)
58740Sstevel@tonic-gate return;
58750Sstevel@tonic-gate
587610231SRajkumar.Sivaprakasam@Sun.COM /*
587710231SRajkumar.Sivaprakasam@Sun.COM * GID UNAVAIL EVENT: Try to locate the GID in the GID list.
587810231SRajkumar.Sivaprakasam@Sun.COM * If we don't find it we just return.
587910231SRajkumar.Sivaprakasam@Sun.COM */
588010231SRajkumar.Sivaprakasam@Sun.COM mutex_enter(&ibdm.ibdm_mutex);
588110231SRajkumar.Sivaprakasam@Sun.COM gid_info = ibdm.ibdm_dp_gidlist_head;
588210231SRajkumar.Sivaprakasam@Sun.COM while (gid_info) {
588310231SRajkumar.Sivaprakasam@Sun.COM if (gid_info->gl_portguid ==
588410231SRajkumar.Sivaprakasam@Sun.COM event_details->ie_gid.gid_guid) {
588510231SRajkumar.Sivaprakasam@Sun.COM break;
588610231SRajkumar.Sivaprakasam@Sun.COM }
588710231SRajkumar.Sivaprakasam@Sun.COM gid_info = gid_info->gl_next;
588810231SRajkumar.Sivaprakasam@Sun.COM }
588910231SRajkumar.Sivaprakasam@Sun.COM mutex_exit(&ibdm.ibdm_mutex);
589010231SRajkumar.Sivaprakasam@Sun.COM if (gid_info == NULL) {
58910Sstevel@tonic-gate IBTF_DPRINTF_L2("ibdm", "\tsaa_event_cb: "
589210231SRajkumar.Sivaprakasam@Sun.COM "GID for GUID %llX not found during GID UNAVAIL event",
589310231SRajkumar.Sivaprakasam@Sun.COM event_details->ie_gid.gid_guid);
58940Sstevel@tonic-gate return;
58950Sstevel@tonic-gate }
589610231SRajkumar.Sivaprakasam@Sun.COM
589710231SRajkumar.Sivaprakasam@Sun.COM /*
589810231SRajkumar.Sivaprakasam@Sun.COM * If this GID is DM capable, we'll have to check whether this DGID
589910231SRajkumar.Sivaprakasam@Sun.COM * is reachable via another port.
590010231SRajkumar.Sivaprakasam@Sun.COM */
590110231SRajkumar.Sivaprakasam@Sun.COM if (gid_info->gl_is_dm_capable == B_TRUE) {
590210231SRajkumar.Sivaprakasam@Sun.COM event_arg = (ibdm_saa_event_arg_t *)kmem_alloc(
590310231SRajkumar.Sivaprakasam@Sun.COM sizeof (ibdm_saa_event_arg_t), KM_SLEEP);
590410231SRajkumar.Sivaprakasam@Sun.COM event_arg->ibmf_saa_handle = ibmf_saa_handle;
590510231SRajkumar.Sivaprakasam@Sun.COM event_arg->ibmf_saa_event = ibmf_saa_event;
590610231SRajkumar.Sivaprakasam@Sun.COM bcopy(event_details, &event_arg->event_details,
590710231SRajkumar.Sivaprakasam@Sun.COM sizeof (ibmf_saa_event_details_t));
590810231SRajkumar.Sivaprakasam@Sun.COM event_arg->callback_arg = callback_arg;
590910231SRajkumar.Sivaprakasam@Sun.COM
591010231SRajkumar.Sivaprakasam@Sun.COM if (taskq_dispatch(system_taskq, ibdm_saa_event_taskq,
591110231SRajkumar.Sivaprakasam@Sun.COM (void *)event_arg, TQ_NOSLEEP) == NULL) {
591210231SRajkumar.Sivaprakasam@Sun.COM IBTF_DPRINTF_L2("ibdm", "\tsaa_event_cb: "
591310231SRajkumar.Sivaprakasam@Sun.COM "taskq_dispatch failed");
591410231SRajkumar.Sivaprakasam@Sun.COM ibdm_free_saa_event_arg(event_arg);
591510231SRajkumar.Sivaprakasam@Sun.COM return;
591610231SRajkumar.Sivaprakasam@Sun.COM }
591710231SRajkumar.Sivaprakasam@Sun.COM }
59180Sstevel@tonic-gate }
59190Sstevel@tonic-gate
59200Sstevel@tonic-gate /*
59210Sstevel@tonic-gate * Handle a new GID discovered by GID_AVAILABLE saa event.
59220Sstevel@tonic-gate */
59230Sstevel@tonic-gate void
ibdm_saa_handle_new_gid(void * arg)59240Sstevel@tonic-gate ibdm_saa_handle_new_gid(void *arg)
59250Sstevel@tonic-gate {
59260Sstevel@tonic-gate ibdm_dp_gidinfo_t *gid_info;
59270Sstevel@tonic-gate ibdm_hca_list_t *hca_list = NULL;
59280Sstevel@tonic-gate ibdm_port_attr_t *port = NULL;
59290Sstevel@tonic-gate ibdm_ioc_info_t *ioc_list = NULL;
59300Sstevel@tonic-gate
59310Sstevel@tonic-gate IBTF_DPRINTF_L4(ibdm_string, "\tsaa_handle_new_gid(%p)", arg);
59320Sstevel@tonic-gate
59330Sstevel@tonic-gate gid_info = (ibdm_dp_gidinfo_t *)arg;
59340Sstevel@tonic-gate
59350Sstevel@tonic-gate /*
59360Sstevel@tonic-gate * Ensure that no other sweep / probe has completed
59370Sstevel@tonic-gate * probing this gid.
59380Sstevel@tonic-gate */
59390Sstevel@tonic-gate mutex_enter(&gid_info->gl_mutex);
59400Sstevel@tonic-gate if (gid_info->gl_state != IBDM_GID_PROBE_NOT_DONE) {
59410Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
59420Sstevel@tonic-gate return;
59430Sstevel@tonic-gate }
59440Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
59450Sstevel@tonic-gate
59460Sstevel@tonic-gate /*
59470Sstevel@tonic-gate * Parse HCAs to fill gl_hca_list
59480Sstevel@tonic-gate */
59490Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_hl_mutex);
59500Sstevel@tonic-gate for (ibdm_get_next_port(&hca_list, &port, 1); port;
59510Sstevel@tonic-gate ibdm_get_next_port(&hca_list, &port, 1)) {
59520Sstevel@tonic-gate if (ibdm_port_reachable(port->pa_sa_hdl,
59536262Seota gid_info->gl_portguid) == B_TRUE) {
59540Sstevel@tonic-gate ibdm_addto_glhcalist(gid_info, hca_list);
59550Sstevel@tonic-gate }
59560Sstevel@tonic-gate }
59570Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_hl_mutex);
59580Sstevel@tonic-gate
59590Sstevel@tonic-gate /*
59600Sstevel@tonic-gate * Ensure no other probe / sweep fabric is in
59610Sstevel@tonic-gate * progress.
59620Sstevel@tonic-gate */
59630Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
59640Sstevel@tonic-gate while (ibdm.ibdm_busy & IBDM_BUSY)
59650Sstevel@tonic-gate cv_wait(&ibdm.ibdm_busy_cv, &ibdm.ibdm_mutex);
59660Sstevel@tonic-gate ibdm.ibdm_busy |= IBDM_BUSY;
59670Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
59680Sstevel@tonic-gate
59690Sstevel@tonic-gate /*
59700Sstevel@tonic-gate * New IOU probe it, to check if new IOCs
59710Sstevel@tonic-gate */
59720Sstevel@tonic-gate IBTF_DPRINTF_L4(ibdm_string, "\tsaa_handle_new_gid: "
59730Sstevel@tonic-gate "new GID : probing");
59740Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
59750Sstevel@tonic-gate ibdm.ibdm_ngid_probes_in_progress++;
59760Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
59770Sstevel@tonic-gate mutex_enter(&gid_info->gl_mutex);
59780Sstevel@tonic-gate gid_info->gl_reprobe_flag = 0;
59790Sstevel@tonic-gate gid_info->gl_state = IBDM_GID_PROBE_NOT_DONE;
59800Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
59810Sstevel@tonic-gate ibdm_probe_gid_thread((void *)gid_info);
59820Sstevel@tonic-gate
59830Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
59840Sstevel@tonic-gate ibdm_wait_probe_completion();
59850Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
59860Sstevel@tonic-gate
59870Sstevel@tonic-gate if (gid_info->gl_iou == NULL) {
59880Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
59890Sstevel@tonic-gate ibdm.ibdm_busy &= ~IBDM_BUSY;
59900Sstevel@tonic-gate cv_broadcast(&ibdm.ibdm_busy_cv);
59910Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
59920Sstevel@tonic-gate return;
59930Sstevel@tonic-gate }
59940Sstevel@tonic-gate
59950Sstevel@tonic-gate /*
59960Sstevel@tonic-gate * Update GID list in all IOCs affected by this
59970Sstevel@tonic-gate */
59980Sstevel@tonic-gate ioc_list = ibdm_update_ioc_gidlist(gid_info, 1);
59990Sstevel@tonic-gate
60000Sstevel@tonic-gate /*
60010Sstevel@tonic-gate * Pass on the IOCs with updated GIDs to IBnexus
60020Sstevel@tonic-gate */
60030Sstevel@tonic-gate if (ioc_list) {
60040Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_ibnex_mutex);
60050Sstevel@tonic-gate if (ibdm.ibdm_ibnex_callback != NULL) {
60060Sstevel@tonic-gate (*ibdm.ibdm_ibnex_callback)((void *)ioc_list,
60070Sstevel@tonic-gate IBDM_EVENT_IOC_PROP_UPDATE);
60080Sstevel@tonic-gate }
60090Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_ibnex_mutex);
60100Sstevel@tonic-gate }
60110Sstevel@tonic-gate
60120Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
60130Sstevel@tonic-gate ibdm.ibdm_busy &= ~IBDM_BUSY;
60140Sstevel@tonic-gate cv_broadcast(&ibdm.ibdm_busy_cv);
60150Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
60160Sstevel@tonic-gate }
60170Sstevel@tonic-gate
60180Sstevel@tonic-gate /*
60190Sstevel@tonic-gate * ibdm_saa_event_taskq :
60200Sstevel@tonic-gate * GID_UNAVAILABLE Event handling requires ibdm_hl_mutex to be
60210Sstevel@tonic-gate * held. The GID_UNAVAILABLE handling is done in a taskq to
60220Sstevel@tonic-gate * prevent deadlocks with HCA port down notifications which hold
60230Sstevel@tonic-gate * ibdm_hl_mutex.
60240Sstevel@tonic-gate */
60250Sstevel@tonic-gate void
ibdm_saa_event_taskq(void * arg)60260Sstevel@tonic-gate ibdm_saa_event_taskq(void *arg)
60270Sstevel@tonic-gate {
60280Sstevel@tonic-gate ibdm_saa_event_arg_t *event_arg;
60290Sstevel@tonic-gate ibmf_saa_handle_t ibmf_saa_handle;
60300Sstevel@tonic-gate ibmf_saa_subnet_event_t ibmf_saa_event;
60310Sstevel@tonic-gate ibmf_saa_event_details_t *event_details;
60320Sstevel@tonic-gate void *callback_arg;
60330Sstevel@tonic-gate
60340Sstevel@tonic-gate ibdm_dp_gidinfo_t *gid_info;
60350Sstevel@tonic-gate ibdm_port_attr_t *hca_port, *port = NULL;
60360Sstevel@tonic-gate ibdm_hca_list_t *hca_list = NULL;
60370Sstevel@tonic-gate int sa_handle_valid = 0;
60380Sstevel@tonic-gate ibdm_ioc_info_t *ioc_list = NULL;
60390Sstevel@tonic-gate
60400Sstevel@tonic-gate _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*event_arg));
60410Sstevel@tonic-gate
60420Sstevel@tonic-gate event_arg = (ibdm_saa_event_arg_t *)arg;
60430Sstevel@tonic-gate ibmf_saa_handle = event_arg->ibmf_saa_handle;
60440Sstevel@tonic-gate ibmf_saa_event = event_arg->ibmf_saa_event;
60450Sstevel@tonic-gate event_details = &event_arg->event_details;
60460Sstevel@tonic-gate callback_arg = event_arg->callback_arg;
60470Sstevel@tonic-gate
60480Sstevel@tonic-gate ASSERT(callback_arg != NULL);
60490Sstevel@tonic-gate ASSERT(ibmf_saa_event == IBMF_SAA_EVENT_GID_UNAVAILABLE);
60500Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tsaa_event_taskq(%x, %x, %x, %x)",
60510Sstevel@tonic-gate ibmf_saa_handle, ibmf_saa_event, event_details,
60520Sstevel@tonic-gate callback_arg);
60530Sstevel@tonic-gate
60540Sstevel@tonic-gate hca_port = (ibdm_port_attr_t *)callback_arg;
60550Sstevel@tonic-gate
60560Sstevel@tonic-gate /* Check if the port_attr is still valid */
60570Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_hl_mutex);
60580Sstevel@tonic-gate for (ibdm_get_next_port(&hca_list, &port, 0); port;
60590Sstevel@tonic-gate ibdm_get_next_port(&hca_list, &port, 0)) {
60600Sstevel@tonic-gate if (port == hca_port && port->pa_port_guid ==
60610Sstevel@tonic-gate hca_port->pa_port_guid) {
60620Sstevel@tonic-gate if (ibmf_saa_handle == hca_port->pa_sa_hdl)
60630Sstevel@tonic-gate sa_handle_valid = 1;
60640Sstevel@tonic-gate break;
60650Sstevel@tonic-gate }
60660Sstevel@tonic-gate }
60670Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_hl_mutex);
60680Sstevel@tonic-gate if (sa_handle_valid == 0) {
60690Sstevel@tonic-gate ibdm_free_saa_event_arg(event_arg);
60700Sstevel@tonic-gate return;
60710Sstevel@tonic-gate }
60720Sstevel@tonic-gate
60730Sstevel@tonic-gate if (hca_port && (hca_port->pa_sa_hdl == NULL ||
60740Sstevel@tonic-gate ibmf_saa_handle != hca_port->pa_sa_hdl)) {
60750Sstevel@tonic-gate ibdm_free_saa_event_arg(event_arg);
60760Sstevel@tonic-gate return;
60770Sstevel@tonic-gate }
60780Sstevel@tonic-gate hca_list = NULL;
60790Sstevel@tonic-gate port = NULL;
60800Sstevel@tonic-gate
60810Sstevel@tonic-gate /*
60820Sstevel@tonic-gate * Check if the GID is visible to other HCA ports.
60830Sstevel@tonic-gate * Return if so.
60840Sstevel@tonic-gate */
60850Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_hl_mutex);
60860Sstevel@tonic-gate for (ibdm_get_next_port(&hca_list, &port, 1); port;
60870Sstevel@tonic-gate ibdm_get_next_port(&hca_list, &port, 1)) {
60880Sstevel@tonic-gate if (ibdm_port_reachable(port->pa_sa_hdl,
60896262Seota event_details->ie_gid.gid_guid) == B_TRUE) {
60900Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_hl_mutex);
60910Sstevel@tonic-gate ibdm_free_saa_event_arg(event_arg);
60920Sstevel@tonic-gate return;
60930Sstevel@tonic-gate }
60940Sstevel@tonic-gate }
60950Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_hl_mutex);
60960Sstevel@tonic-gate
60970Sstevel@tonic-gate /*
60980Sstevel@tonic-gate * Ensure no other probe / sweep fabric is in
60990Sstevel@tonic-gate * progress.
61000Sstevel@tonic-gate */
61010Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
61020Sstevel@tonic-gate while (ibdm.ibdm_busy & IBDM_BUSY)
61030Sstevel@tonic-gate cv_wait(&ibdm.ibdm_busy_cv, &ibdm.ibdm_mutex);
61040Sstevel@tonic-gate ibdm.ibdm_busy |= IBDM_BUSY;
61050Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
61060Sstevel@tonic-gate
61070Sstevel@tonic-gate /*
61080Sstevel@tonic-gate * If this GID is no longer in GID list, return
61090Sstevel@tonic-gate * GID_UNAVAILABLE may be reported for multiple HCA
61100Sstevel@tonic-gate * ports.
61110Sstevel@tonic-gate */
61120Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
61130Sstevel@tonic-gate gid_info = ibdm.ibdm_dp_gidlist_head;
61140Sstevel@tonic-gate while (gid_info) {
61150Sstevel@tonic-gate if (gid_info->gl_portguid ==
61160Sstevel@tonic-gate event_details->ie_gid.gid_guid) {
61170Sstevel@tonic-gate break;
61180Sstevel@tonic-gate }
61190Sstevel@tonic-gate gid_info = gid_info->gl_next;
61200Sstevel@tonic-gate }
61210Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
61220Sstevel@tonic-gate if (gid_info == NULL) {
61230Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
61240Sstevel@tonic-gate ibdm.ibdm_busy &= ~IBDM_BUSY;
61250Sstevel@tonic-gate cv_broadcast(&ibdm.ibdm_busy_cv);
61260Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
61270Sstevel@tonic-gate ibdm_free_saa_event_arg(event_arg);
61280Sstevel@tonic-gate return;
61290Sstevel@tonic-gate }
61300Sstevel@tonic-gate
61310Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tGID (prefix %x, guid %llx) "
61320Sstevel@tonic-gate "Unavailable notification",
61330Sstevel@tonic-gate event_details->ie_gid.gid_prefix,
61340Sstevel@tonic-gate event_details->ie_gid.gid_guid);
61350Sstevel@tonic-gate
61360Sstevel@tonic-gate /*
61370Sstevel@tonic-gate * Update GID list in all IOCs affected by this
61380Sstevel@tonic-gate */
61390Sstevel@tonic-gate if (gid_info->gl_state == IBDM_GID_PROBING_SKIPPED ||
61400Sstevel@tonic-gate gid_info->gl_state == IBDM_GID_PROBING_COMPLETE)
61410Sstevel@tonic-gate ioc_list = ibdm_update_ioc_gidlist(gid_info, 0);
61420Sstevel@tonic-gate
61430Sstevel@tonic-gate /*
61440Sstevel@tonic-gate * Remove GID from the global GID list
61450Sstevel@tonic-gate * Handle the case where all port GIDs for an
61460Sstevel@tonic-gate * IOU have been hot-removed. Check both gid_info
61470Sstevel@tonic-gate * & ioc_info for checking ngids.
61480Sstevel@tonic-gate */
61490Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
61500Sstevel@tonic-gate if (gid_info->gl_iou != NULL && gid_info->gl_ngids == 0) {
61510Sstevel@tonic-gate mutex_enter(&gid_info->gl_mutex);
61524024Spramodbg (void) ibdm_free_iou_info(gid_info, &gid_info->gl_iou);
61530Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
61540Sstevel@tonic-gate }
61550Sstevel@tonic-gate if (gid_info->gl_prev != NULL)
61560Sstevel@tonic-gate gid_info->gl_prev->gl_next = gid_info->gl_next;
61570Sstevel@tonic-gate if (gid_info->gl_next != NULL)
61580Sstevel@tonic-gate gid_info->gl_next->gl_prev = gid_info->gl_prev;
61590Sstevel@tonic-gate
61600Sstevel@tonic-gate if (gid_info == ibdm.ibdm_dp_gidlist_head)
61610Sstevel@tonic-gate ibdm.ibdm_dp_gidlist_head = gid_info->gl_next;
61620Sstevel@tonic-gate if (gid_info == ibdm.ibdm_dp_gidlist_tail)
61630Sstevel@tonic-gate ibdm.ibdm_dp_gidlist_tail = gid_info->gl_prev;
61640Sstevel@tonic-gate ibdm.ibdm_ngids--;
61650Sstevel@tonic-gate
61660Sstevel@tonic-gate ibdm.ibdm_busy &= ~IBDM_BUSY;
61670Sstevel@tonic-gate cv_broadcast(&ibdm.ibdm_busy_cv);
61680Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
61690Sstevel@tonic-gate
61706262Seota /* free the hca_list on this gid_info */
61716262Seota ibdm_delete_glhca_list(gid_info);
61726262Seota
61730Sstevel@tonic-gate mutex_destroy(&gid_info->gl_mutex);
61740Sstevel@tonic-gate kmem_free(gid_info, sizeof (ibdm_dp_gidinfo_t));
61750Sstevel@tonic-gate
61760Sstevel@tonic-gate /*
61770Sstevel@tonic-gate * Pass on the IOCs with updated GIDs to IBnexus
61780Sstevel@tonic-gate */
61790Sstevel@tonic-gate if (ioc_list) {
61800Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tGID_UNAVAILABLE "
61810Sstevel@tonic-gate "IOC_PROP_UPDATE for %p\n", ioc_list);
61820Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_ibnex_mutex);
61830Sstevel@tonic-gate if (ibdm.ibdm_ibnex_callback != NULL) {
61840Sstevel@tonic-gate (*ibdm.ibdm_ibnex_callback)((void *)
61856262Seota ioc_list, IBDM_EVENT_IOC_PROP_UPDATE);
61860Sstevel@tonic-gate }
61870Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_ibnex_mutex);
61880Sstevel@tonic-gate }
61890Sstevel@tonic-gate
61900Sstevel@tonic-gate ibdm_free_saa_event_arg(event_arg);
61910Sstevel@tonic-gate }
61920Sstevel@tonic-gate
61930Sstevel@tonic-gate
61940Sstevel@tonic-gate static int
ibdm_cmp_gid_list(ibdm_gid_t * new,ibdm_gid_t * prev)61950Sstevel@tonic-gate ibdm_cmp_gid_list(ibdm_gid_t *new, ibdm_gid_t *prev)
61960Sstevel@tonic-gate {
61970Sstevel@tonic-gate ibdm_gid_t *scan_new, *scan_prev;
61980Sstevel@tonic-gate int cmp_failed = 0;
61990Sstevel@tonic-gate
62000Sstevel@tonic-gate ASSERT(new != NULL);
62010Sstevel@tonic-gate ASSERT(prev != NULL);
62020Sstevel@tonic-gate
62030Sstevel@tonic-gate /*
62040Sstevel@tonic-gate * Search for each new gid anywhere in the prev GID list.
62050Sstevel@tonic-gate * Note that the gid list could have been re-ordered.
62060Sstevel@tonic-gate */
62070Sstevel@tonic-gate for (scan_new = new; scan_new; scan_new = scan_new->gid_next) {
62080Sstevel@tonic-gate for (scan_prev = prev, cmp_failed = 1; scan_prev;
62090Sstevel@tonic-gate scan_prev = scan_prev->gid_next) {
62100Sstevel@tonic-gate if (scan_prev->gid_dgid_hi == scan_new->gid_dgid_hi &&
62110Sstevel@tonic-gate scan_prev->gid_dgid_lo == scan_new->gid_dgid_lo) {
62120Sstevel@tonic-gate cmp_failed = 0;
62130Sstevel@tonic-gate break;
62140Sstevel@tonic-gate }
62150Sstevel@tonic-gate }
62160Sstevel@tonic-gate
62170Sstevel@tonic-gate if (cmp_failed)
62180Sstevel@tonic-gate return (1);
62190Sstevel@tonic-gate }
62200Sstevel@tonic-gate return (0);
62210Sstevel@tonic-gate }
62220Sstevel@tonic-gate
62230Sstevel@tonic-gate /*
62240Sstevel@tonic-gate * This is always called in a single thread
62250Sstevel@tonic-gate * This function updates the gid_list and serv_list of IOC
62260Sstevel@tonic-gate * The current gid_list is in ioc_info_t(contains only port
62270Sstevel@tonic-gate * guids for which probe is done) & gidinfo_t(other port gids)
62280Sstevel@tonic-gate * The gids in both locations are used for comparision.
62290Sstevel@tonic-gate */
62300Sstevel@tonic-gate static void
ibdm_reprobe_update_port_srv(ibdm_ioc_info_t * ioc,ibdm_dp_gidinfo_t * gidinfo)62310Sstevel@tonic-gate ibdm_reprobe_update_port_srv(ibdm_ioc_info_t *ioc, ibdm_dp_gidinfo_t *gidinfo)
62320Sstevel@tonic-gate {
62330Sstevel@tonic-gate ibdm_gid_t *cur_gid_list;
62340Sstevel@tonic-gate uint_t cur_nportgids;
62350Sstevel@tonic-gate
62360Sstevel@tonic-gate ASSERT(MUTEX_HELD(&ibdm.ibdm_mutex));
62370Sstevel@tonic-gate
62380Sstevel@tonic-gate ioc->ioc_info_updated.ib_prop_updated = 0;
62390Sstevel@tonic-gate
62400Sstevel@tonic-gate
62410Sstevel@tonic-gate /* Current GID list in gid_info only */
62420Sstevel@tonic-gate cur_gid_list = gidinfo->gl_gid;
62430Sstevel@tonic-gate cur_nportgids = gidinfo->gl_ngids;
62440Sstevel@tonic-gate
62454024Spramodbg if (ioc->ioc_prev_serv_cnt !=
62464024Spramodbg ioc->ioc_profile.ioc_service_entries ||
62474024Spramodbg ibdm_serv_cmp(&ioc->ioc_serv[0], &ioc->ioc_prev_serv[0],
62484024Spramodbg ioc->ioc_prev_serv_cnt))
62490Sstevel@tonic-gate ioc->ioc_info_updated.ib_srv_prop_updated = 1;
62500Sstevel@tonic-gate
62510Sstevel@tonic-gate if (ioc->ioc_prev_nportgids != cur_nportgids ||
62520Sstevel@tonic-gate ioc->ioc_prev_gid_list == NULL || cur_gid_list == NULL) {
62530Sstevel@tonic-gate ioc->ioc_info_updated.ib_gid_prop_updated = 1;
62540Sstevel@tonic-gate } else if (ibdm_cmp_gid_list(ioc->ioc_prev_gid_list, cur_gid_list)) {
62550Sstevel@tonic-gate ioc->ioc_info_updated.ib_gid_prop_updated = 1;
62560Sstevel@tonic-gate }
62570Sstevel@tonic-gate
62580Sstevel@tonic-gate /* Zero out previous entries */
62590Sstevel@tonic-gate ibdm_free_gid_list(ioc->ioc_prev_gid_list);
62600Sstevel@tonic-gate if (ioc->ioc_prev_serv)
62610Sstevel@tonic-gate kmem_free(ioc->ioc_prev_serv, ioc->ioc_prev_serv_cnt *
62620Sstevel@tonic-gate sizeof (ibdm_srvents_info_t));
62630Sstevel@tonic-gate ioc->ioc_prev_serv_cnt = 0;
62640Sstevel@tonic-gate ioc->ioc_prev_nportgids = 0;
62650Sstevel@tonic-gate ioc->ioc_prev_serv = NULL;
62660Sstevel@tonic-gate ioc->ioc_prev_gid_list = NULL;
62670Sstevel@tonic-gate }
62680Sstevel@tonic-gate
62690Sstevel@tonic-gate /*
62700Sstevel@tonic-gate * Handle GID removal. This returns gid_info of an GID for the same
62710Sstevel@tonic-gate * node GUID, if found. For an GID with IOU information, the same
62720Sstevel@tonic-gate * gid_info is returned if no gid_info with same node_guid is found.
62730Sstevel@tonic-gate */
62740Sstevel@tonic-gate static ibdm_dp_gidinfo_t *
ibdm_handle_gid_rm(ibdm_dp_gidinfo_t * rm_gid)62750Sstevel@tonic-gate ibdm_handle_gid_rm(ibdm_dp_gidinfo_t *rm_gid)
62760Sstevel@tonic-gate {
62770Sstevel@tonic-gate ibdm_dp_gidinfo_t *gid_list;
62780Sstevel@tonic-gate
62790Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\thandle_gid_rm(0x%p)", rm_gid);
62800Sstevel@tonic-gate
62810Sstevel@tonic-gate if (rm_gid->gl_iou == NULL) {
62820Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\thandle_gid_rm NO iou");
62830Sstevel@tonic-gate /*
62840Sstevel@tonic-gate * Search for a GID with same node_guid and
62850Sstevel@tonic-gate * gl_iou != NULL
62860Sstevel@tonic-gate */
62870Sstevel@tonic-gate for (gid_list = ibdm.ibdm_dp_gidlist_head; gid_list;
62880Sstevel@tonic-gate gid_list = gid_list->gl_next) {
62890Sstevel@tonic-gate if (gid_list->gl_iou != NULL && (gid_list->gl_nodeguid
62900Sstevel@tonic-gate == rm_gid->gl_nodeguid))
62910Sstevel@tonic-gate break;
62920Sstevel@tonic-gate }
62930Sstevel@tonic-gate
62940Sstevel@tonic-gate if (gid_list)
62950Sstevel@tonic-gate ibdm_rmfrom_glgid_list(gid_list, rm_gid);
62960Sstevel@tonic-gate
62970Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\thandle_gid_rm ret %p", gid_list);
62980Sstevel@tonic-gate return (gid_list);
62990Sstevel@tonic-gate } else {
63000Sstevel@tonic-gate /*
63010Sstevel@tonic-gate * Search for a GID with same node_guid and
63020Sstevel@tonic-gate * gl_iou == NULL
63030Sstevel@tonic-gate */
63040Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\thandle_gid_rm with iou");
63050Sstevel@tonic-gate for (gid_list = ibdm.ibdm_dp_gidlist_head; gid_list;
63060Sstevel@tonic-gate gid_list = gid_list->gl_next) {
63070Sstevel@tonic-gate if (gid_list->gl_iou == NULL && (gid_list->gl_nodeguid
63080Sstevel@tonic-gate == rm_gid->gl_nodeguid))
63090Sstevel@tonic-gate break;
63100Sstevel@tonic-gate }
63110Sstevel@tonic-gate
63120Sstevel@tonic-gate if (gid_list) {
63130Sstevel@tonic-gate /*
63140Sstevel@tonic-gate * Copy the following fields from rm_gid :
63150Sstevel@tonic-gate * 1. gl_state
63160Sstevel@tonic-gate * 2. gl_iou
63170Sstevel@tonic-gate * 3. gl_gid & gl_ngids
63180Sstevel@tonic-gate *
63190Sstevel@tonic-gate * Note : Function is synchronized by
63200Sstevel@tonic-gate * ibdm_busy flag.
63210Sstevel@tonic-gate *
63220Sstevel@tonic-gate * Note : Redirect info is initialized if
63230Sstevel@tonic-gate * any MADs for the GID fail
63240Sstevel@tonic-gate */
63250Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\thandle_gid_rm "
63260Sstevel@tonic-gate "copying info to GID with gl_iou != NULl");
63270Sstevel@tonic-gate gid_list->gl_state = rm_gid->gl_state;
63280Sstevel@tonic-gate gid_list->gl_iou = rm_gid->gl_iou;
63290Sstevel@tonic-gate gid_list->gl_gid = rm_gid->gl_gid;
63300Sstevel@tonic-gate gid_list->gl_ngids = rm_gid->gl_ngids;
63310Sstevel@tonic-gate
63320Sstevel@tonic-gate /* Remove the GID from gl_gid list */
63330Sstevel@tonic-gate ibdm_rmfrom_glgid_list(gid_list, rm_gid);
63340Sstevel@tonic-gate } else {
63350Sstevel@tonic-gate /*
63360Sstevel@tonic-gate * Handle a case where all GIDs to the IOU have
63370Sstevel@tonic-gate * been removed.
63380Sstevel@tonic-gate */
63390Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\thandle_gid_rm 0 GID "
63400Sstevel@tonic-gate "to IOU");
63410Sstevel@tonic-gate
63420Sstevel@tonic-gate ibdm_rmfrom_glgid_list(rm_gid, rm_gid);
63430Sstevel@tonic-gate return (rm_gid);
63440Sstevel@tonic-gate }
63450Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\thandle_gid_rm ret %p", gid_list);
63460Sstevel@tonic-gate return (gid_list);
63470Sstevel@tonic-gate }
63480Sstevel@tonic-gate }
63490Sstevel@tonic-gate
63500Sstevel@tonic-gate static void
ibdm_rmfrom_glgid_list(ibdm_dp_gidinfo_t * gid_info,ibdm_dp_gidinfo_t * rm_gid)63510Sstevel@tonic-gate ibdm_rmfrom_glgid_list(ibdm_dp_gidinfo_t *gid_info,
63520Sstevel@tonic-gate ibdm_dp_gidinfo_t *rm_gid)
63530Sstevel@tonic-gate {
63540Sstevel@tonic-gate ibdm_gid_t *tmp, *prev;
63550Sstevel@tonic-gate
63560Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\trmfrom_glgid (%p, %p)",
63570Sstevel@tonic-gate gid_info, rm_gid);
63580Sstevel@tonic-gate
63590Sstevel@tonic-gate for (tmp = gid_info->gl_gid, prev = NULL; tmp; ) {
63600Sstevel@tonic-gate if (tmp->gid_dgid_hi == rm_gid->gl_dgid_hi &&
63610Sstevel@tonic-gate tmp->gid_dgid_lo == rm_gid->gl_dgid_lo) {
63620Sstevel@tonic-gate if (prev == NULL)
63630Sstevel@tonic-gate gid_info->gl_gid = tmp->gid_next;
63640Sstevel@tonic-gate else
63650Sstevel@tonic-gate prev->gid_next = tmp->gid_next;
63660Sstevel@tonic-gate
63670Sstevel@tonic-gate kmem_free(tmp, sizeof (ibdm_gid_t));
63680Sstevel@tonic-gate gid_info->gl_ngids--;
63690Sstevel@tonic-gate break;
63700Sstevel@tonic-gate } else {
63710Sstevel@tonic-gate prev = tmp;
63720Sstevel@tonic-gate tmp = tmp->gid_next;
63730Sstevel@tonic-gate }
63740Sstevel@tonic-gate }
63750Sstevel@tonic-gate }
63760Sstevel@tonic-gate
63770Sstevel@tonic-gate static void
ibdm_addto_gidlist(ibdm_gid_t ** src_ptr,ibdm_gid_t * dest)63780Sstevel@tonic-gate ibdm_addto_gidlist(ibdm_gid_t **src_ptr, ibdm_gid_t *dest)
63790Sstevel@tonic-gate {
63800Sstevel@tonic-gate ibdm_gid_t *head = NULL, *new, *tail;
63810Sstevel@tonic-gate
63820Sstevel@tonic-gate /* First copy the destination */
63830Sstevel@tonic-gate for (; dest; dest = dest->gid_next) {
63840Sstevel@tonic-gate new = kmem_zalloc(sizeof (ibdm_gid_t), KM_SLEEP);
63850Sstevel@tonic-gate new->gid_dgid_hi = dest->gid_dgid_hi;
63860Sstevel@tonic-gate new->gid_dgid_lo = dest->gid_dgid_lo;
63870Sstevel@tonic-gate new->gid_next = head;
63880Sstevel@tonic-gate head = new;
63890Sstevel@tonic-gate }
63900Sstevel@tonic-gate
63910Sstevel@tonic-gate /* Insert this to the source */
63920Sstevel@tonic-gate if (*src_ptr == NULL)
63930Sstevel@tonic-gate *src_ptr = head;
63940Sstevel@tonic-gate else {
63950Sstevel@tonic-gate for (tail = *src_ptr; tail->gid_next != NULL;
63960Sstevel@tonic-gate tail = tail->gid_next)
63970Sstevel@tonic-gate ;
63980Sstevel@tonic-gate
63990Sstevel@tonic-gate tail->gid_next = head;
64000Sstevel@tonic-gate }
64010Sstevel@tonic-gate }
64020Sstevel@tonic-gate
64030Sstevel@tonic-gate static void
ibdm_free_gid_list(ibdm_gid_t * head)64040Sstevel@tonic-gate ibdm_free_gid_list(ibdm_gid_t *head)
64050Sstevel@tonic-gate {
64060Sstevel@tonic-gate ibdm_gid_t *delete;
64070Sstevel@tonic-gate
64080Sstevel@tonic-gate for (delete = head; delete; ) {
64090Sstevel@tonic-gate head = delete->gid_next;
64100Sstevel@tonic-gate kmem_free(delete, sizeof (ibdm_gid_t));
64110Sstevel@tonic-gate delete = head;
64120Sstevel@tonic-gate }
64130Sstevel@tonic-gate }
64140Sstevel@tonic-gate
64150Sstevel@tonic-gate /*
64160Sstevel@tonic-gate * This function rescans the DM capable GIDs (gl_state is
64170Sstevel@tonic-gate * GID_PROBE_COMPLETE or IBDM_GID_PROBING_SKIPPED.This
64180Sstevel@tonic-gate * basically checks if the DM capable GID is reachable. If
64190Sstevel@tonic-gate * not this is handled the same way as GID_UNAVAILABLE,
64200Sstevel@tonic-gate * except that notifications are not send to IBnexus.
64210Sstevel@tonic-gate *
64220Sstevel@tonic-gate * This function also initializes the ioc_prev_list for
64230Sstevel@tonic-gate * a particular IOC (when called from probe_ioc, with
64240Sstevel@tonic-gate * ioc_guidp != NULL) or all IOCs for the gid (called from
64250Sstevel@tonic-gate * sweep_fabric, ioc_guidp == NULL).
64260Sstevel@tonic-gate */
64270Sstevel@tonic-gate static void
ibdm_rescan_gidlist(ib_guid_t * ioc_guidp)64280Sstevel@tonic-gate ibdm_rescan_gidlist(ib_guid_t *ioc_guidp)
64290Sstevel@tonic-gate {
64300Sstevel@tonic-gate ibdm_dp_gidinfo_t *gid_info, *tmp;
64310Sstevel@tonic-gate int ii, niocs, found;
64320Sstevel@tonic-gate ibdm_hca_list_t *hca_list = NULL;
64330Sstevel@tonic-gate ibdm_port_attr_t *port = NULL;
64340Sstevel@tonic-gate ibdm_ioc_info_t *ioc_list;
64350Sstevel@tonic-gate
64360Sstevel@tonic-gate for (gid_info = ibdm.ibdm_dp_gidlist_head; gid_info; ) {
64370Sstevel@tonic-gate found = 0;
64380Sstevel@tonic-gate if (gid_info->gl_state != IBDM_GID_PROBING_SKIPPED &&
64390Sstevel@tonic-gate gid_info->gl_state != IBDM_GID_PROBING_COMPLETE) {
64400Sstevel@tonic-gate gid_info = gid_info->gl_next;
64410Sstevel@tonic-gate continue;
64420Sstevel@tonic-gate }
64430Sstevel@tonic-gate
64440Sstevel@tonic-gate /*
64450Sstevel@tonic-gate * Check if the GID is visible to any HCA ports.
64460Sstevel@tonic-gate * Return if so.
64470Sstevel@tonic-gate */
64480Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_hl_mutex);
64490Sstevel@tonic-gate for (ibdm_get_next_port(&hca_list, &port, 1); port;
64500Sstevel@tonic-gate ibdm_get_next_port(&hca_list, &port, 1)) {
64510Sstevel@tonic-gate if (ibdm_port_reachable(port->pa_sa_hdl,
64526262Seota gid_info->gl_dgid_lo) == B_TRUE) {
64530Sstevel@tonic-gate found = 1;
64540Sstevel@tonic-gate break;
64550Sstevel@tonic-gate }
64560Sstevel@tonic-gate }
64570Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_hl_mutex);
64580Sstevel@tonic-gate
64590Sstevel@tonic-gate if (found) {
64600Sstevel@tonic-gate if (gid_info->gl_iou == NULL) {
64610Sstevel@tonic-gate gid_info = gid_info->gl_next;
64620Sstevel@tonic-gate continue;
64630Sstevel@tonic-gate }
64640Sstevel@tonic-gate
64650Sstevel@tonic-gate /* Intialize the ioc_prev_gid_list */
64660Sstevel@tonic-gate niocs =
64670Sstevel@tonic-gate gid_info->gl_iou->iou_info.iou_num_ctrl_slots;
64680Sstevel@tonic-gate for (ii = 0; ii < niocs; ii++) {
64690Sstevel@tonic-gate ioc_list = IBDM_GIDINFO2IOCINFO(gid_info, ii);
64700Sstevel@tonic-gate
64710Sstevel@tonic-gate if (ioc_guidp == NULL || (*ioc_guidp ==
64720Sstevel@tonic-gate ioc_list->ioc_profile.ioc_guid)) {
64730Sstevel@tonic-gate /* Add info of GIDs in gid_info also */
64740Sstevel@tonic-gate ibdm_addto_gidlist(
64750Sstevel@tonic-gate &ioc_list->ioc_prev_gid_list,
64760Sstevel@tonic-gate gid_info->gl_gid);
64770Sstevel@tonic-gate ioc_list->ioc_prev_nportgids =
64780Sstevel@tonic-gate gid_info->gl_ngids;
64790Sstevel@tonic-gate }
64800Sstevel@tonic-gate }
64810Sstevel@tonic-gate gid_info = gid_info->gl_next;
64820Sstevel@tonic-gate continue;
64830Sstevel@tonic-gate }
64840Sstevel@tonic-gate
64850Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\trescan_gidlist "
64860Sstevel@tonic-gate "deleted port GUID %llx",
64870Sstevel@tonic-gate gid_info->gl_dgid_lo);
64880Sstevel@tonic-gate
64890Sstevel@tonic-gate /*
64900Sstevel@tonic-gate * Update GID list in all IOCs affected by this
64910Sstevel@tonic-gate */
64920Sstevel@tonic-gate ioc_list = ibdm_update_ioc_gidlist(gid_info, 0);
64930Sstevel@tonic-gate
64940Sstevel@tonic-gate /*
64950Sstevel@tonic-gate * Remove GID from the global GID list
64960Sstevel@tonic-gate * Handle the case where all port GIDs for an
64970Sstevel@tonic-gate * IOU have been hot-removed.
64980Sstevel@tonic-gate */
64990Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
65000Sstevel@tonic-gate if (gid_info->gl_iou != NULL && gid_info->gl_ngids == 0) {
65010Sstevel@tonic-gate mutex_enter(&gid_info->gl_mutex);
65024024Spramodbg (void) ibdm_free_iou_info(gid_info, &gid_info->gl_iou);
65030Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
65040Sstevel@tonic-gate }
65056262Seota
65060Sstevel@tonic-gate tmp = gid_info->gl_next;
65070Sstevel@tonic-gate if (gid_info->gl_prev != NULL)
65080Sstevel@tonic-gate gid_info->gl_prev->gl_next = gid_info->gl_next;
65090Sstevel@tonic-gate if (gid_info->gl_next != NULL)
65100Sstevel@tonic-gate gid_info->gl_next->gl_prev = gid_info->gl_prev;
65110Sstevel@tonic-gate
65120Sstevel@tonic-gate if (gid_info == ibdm.ibdm_dp_gidlist_head)
65130Sstevel@tonic-gate ibdm.ibdm_dp_gidlist_head = gid_info->gl_next;
65140Sstevel@tonic-gate if (gid_info == ibdm.ibdm_dp_gidlist_tail)
65150Sstevel@tonic-gate ibdm.ibdm_dp_gidlist_tail = gid_info->gl_prev;
65160Sstevel@tonic-gate ibdm.ibdm_ngids--;
65176262Seota mutex_exit(&ibdm.ibdm_mutex);
65186262Seota
65196262Seota /* free the hca_list on this gid_info */
65206262Seota ibdm_delete_glhca_list(gid_info);
65210Sstevel@tonic-gate
65220Sstevel@tonic-gate mutex_destroy(&gid_info->gl_mutex);
65230Sstevel@tonic-gate kmem_free(gid_info, sizeof (ibdm_dp_gidinfo_t));
65246262Seota
65250Sstevel@tonic-gate gid_info = tmp;
65260Sstevel@tonic-gate
65270Sstevel@tonic-gate /*
65280Sstevel@tonic-gate * Pass on the IOCs with updated GIDs to IBnexus
65290Sstevel@tonic-gate */
65300Sstevel@tonic-gate if (ioc_list) {
65310Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\trescan_gidlist "
65320Sstevel@tonic-gate "IOC_PROP_UPDATE for %p\n", ioc_list);
65330Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_ibnex_mutex);
65340Sstevel@tonic-gate if (ibdm.ibdm_ibnex_callback != NULL) {
65350Sstevel@tonic-gate (*ibdm.ibdm_ibnex_callback)((void *)
65360Sstevel@tonic-gate ioc_list, IBDM_EVENT_IOC_PROP_UPDATE);
65370Sstevel@tonic-gate }
65380Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_ibnex_mutex);
65390Sstevel@tonic-gate }
65400Sstevel@tonic-gate }
65410Sstevel@tonic-gate }
65420Sstevel@tonic-gate
65430Sstevel@tonic-gate /*
65440Sstevel@tonic-gate * This function notifies IBnex of IOCs on this GID.
65450Sstevel@tonic-gate * Notification is for GIDs with gl_reprobe_flag set.
65460Sstevel@tonic-gate * The flag is set when IOC probe / fabric sweep
65470Sstevel@tonic-gate * probes a GID starting from CLASS port info.
65480Sstevel@tonic-gate *
65490Sstevel@tonic-gate * IBnexus will have information of a reconnected IOC
65500Sstevel@tonic-gate * if it had probed it before. If this is a new IOC,
65510Sstevel@tonic-gate * IBnexus ignores the notification.
65520Sstevel@tonic-gate *
65530Sstevel@tonic-gate * This function should be called with no locks held.
65540Sstevel@tonic-gate */
65550Sstevel@tonic-gate static void
ibdm_notify_newgid_iocs(ibdm_dp_gidinfo_t * gid_info)65560Sstevel@tonic-gate ibdm_notify_newgid_iocs(ibdm_dp_gidinfo_t *gid_info)
65570Sstevel@tonic-gate {
65580Sstevel@tonic-gate ibdm_ioc_info_t *ioc_list;
65590Sstevel@tonic-gate
65600Sstevel@tonic-gate if (gid_info->gl_reprobe_flag == 0 ||
65610Sstevel@tonic-gate gid_info->gl_iou == NULL)
65620Sstevel@tonic-gate return;
65630Sstevel@tonic-gate
65640Sstevel@tonic-gate ioc_list = ibdm_update_ioc_gidlist(gid_info, -1);
65650Sstevel@tonic-gate
65660Sstevel@tonic-gate /*
65670Sstevel@tonic-gate * Pass on the IOCs with updated GIDs to IBnexus
65680Sstevel@tonic-gate */
65690Sstevel@tonic-gate if (ioc_list) {
65700Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_ibnex_mutex);
65710Sstevel@tonic-gate if (ibdm.ibdm_ibnex_callback != NULL) {
65720Sstevel@tonic-gate (*ibdm.ibdm_ibnex_callback)((void *)ioc_list,
65730Sstevel@tonic-gate IBDM_EVENT_IOC_PROP_UPDATE);
65740Sstevel@tonic-gate }
65750Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_ibnex_mutex);
65760Sstevel@tonic-gate }
65770Sstevel@tonic-gate }
65780Sstevel@tonic-gate
65790Sstevel@tonic-gate
65800Sstevel@tonic-gate static void
ibdm_free_saa_event_arg(ibdm_saa_event_arg_t * arg)65810Sstevel@tonic-gate ibdm_free_saa_event_arg(ibdm_saa_event_arg_t *arg)
65820Sstevel@tonic-gate {
65830Sstevel@tonic-gate if (arg != NULL)
65840Sstevel@tonic-gate kmem_free(arg, sizeof (ibdm_saa_event_arg_t));
65850Sstevel@tonic-gate }
65860Sstevel@tonic-gate
65870Sstevel@tonic-gate /*
65880Sstevel@tonic-gate * This function parses the list of HCAs and HCA ports
65890Sstevel@tonic-gate * to return the port_attr of the next HCA port. A port
65900Sstevel@tonic-gate * connected to IB fabric (port_state active) is returned,
65910Sstevel@tonic-gate * if connected_flag is set.
65920Sstevel@tonic-gate */
65930Sstevel@tonic-gate static void
ibdm_get_next_port(ibdm_hca_list_t ** inp_hcap,ibdm_port_attr_t ** inp_portp,int connect_flag)65940Sstevel@tonic-gate ibdm_get_next_port(ibdm_hca_list_t **inp_hcap,
65950Sstevel@tonic-gate ibdm_port_attr_t **inp_portp, int connect_flag)
65960Sstevel@tonic-gate {
65970Sstevel@tonic-gate int ii;
65980Sstevel@tonic-gate ibdm_port_attr_t *port, *next_port = NULL;
65990Sstevel@tonic-gate ibdm_port_attr_t *inp_port;
66000Sstevel@tonic-gate ibdm_hca_list_t *hca_list;
66010Sstevel@tonic-gate int found = 0;
66020Sstevel@tonic-gate
66030Sstevel@tonic-gate ASSERT(MUTEX_HELD(&ibdm.ibdm_hl_mutex));
66040Sstevel@tonic-gate IBTF_DPRINTF_L4(ibdm_string, "\tget_next_port(%p, %p, %x)",
66050Sstevel@tonic-gate inp_hcap, inp_portp, connect_flag);
66060Sstevel@tonic-gate
66070Sstevel@tonic-gate hca_list = *inp_hcap;
66080Sstevel@tonic-gate inp_port = *inp_portp;
66090Sstevel@tonic-gate
66100Sstevel@tonic-gate if (hca_list == NULL)
66110Sstevel@tonic-gate hca_list = ibdm.ibdm_hca_list_head;
66120Sstevel@tonic-gate
66130Sstevel@tonic-gate for (; hca_list; hca_list = hca_list->hl_next) {
66140Sstevel@tonic-gate for (ii = 0; ii < hca_list->hl_nports; ii++) {
66150Sstevel@tonic-gate port = &hca_list->hl_port_attr[ii];
66160Sstevel@tonic-gate
66170Sstevel@tonic-gate /*
66180Sstevel@tonic-gate * inp_port != NULL;
66190Sstevel@tonic-gate * Skip till we find the matching port
66200Sstevel@tonic-gate */
66210Sstevel@tonic-gate if (inp_port && !found) {
66220Sstevel@tonic-gate if (inp_port == port)
66230Sstevel@tonic-gate found = 1;
66240Sstevel@tonic-gate continue;
66250Sstevel@tonic-gate }
66260Sstevel@tonic-gate
66270Sstevel@tonic-gate if (!connect_flag) {
66280Sstevel@tonic-gate next_port = port;
66290Sstevel@tonic-gate break;
66300Sstevel@tonic-gate }
66310Sstevel@tonic-gate
66320Sstevel@tonic-gate if (port->pa_sa_hdl == NULL)
66330Sstevel@tonic-gate ibdm_initialize_port(port);
66340Sstevel@tonic-gate if (port->pa_sa_hdl == NULL)
66350Sstevel@tonic-gate (void) ibdm_fini_port(port);
66360Sstevel@tonic-gate else if (next_port == NULL &&
66370Sstevel@tonic-gate port->pa_sa_hdl != NULL &&
66380Sstevel@tonic-gate port->pa_state == IBT_PORT_ACTIVE) {
66390Sstevel@tonic-gate next_port = port;
66400Sstevel@tonic-gate break;
66410Sstevel@tonic-gate }
66420Sstevel@tonic-gate }
66430Sstevel@tonic-gate
66440Sstevel@tonic-gate if (next_port)
66450Sstevel@tonic-gate break;
66460Sstevel@tonic-gate }
66470Sstevel@tonic-gate
66480Sstevel@tonic-gate IBTF_DPRINTF_L4(ibdm_string, "\tget_next_port : "
66490Sstevel@tonic-gate "returns hca_list %p port %p", hca_list, next_port);
66500Sstevel@tonic-gate *inp_hcap = hca_list;
66510Sstevel@tonic-gate *inp_portp = next_port;
66520Sstevel@tonic-gate }
66530Sstevel@tonic-gate
66540Sstevel@tonic-gate static void
ibdm_add_to_gl_gid(ibdm_dp_gidinfo_t * nodegid,ibdm_dp_gidinfo_t * addgid)66550Sstevel@tonic-gate ibdm_add_to_gl_gid(ibdm_dp_gidinfo_t *nodegid, ibdm_dp_gidinfo_t *addgid)
66560Sstevel@tonic-gate {
66570Sstevel@tonic-gate ibdm_gid_t *tmp;
66580Sstevel@tonic-gate
66590Sstevel@tonic-gate tmp = kmem_zalloc(sizeof (ibdm_gid_t), KM_SLEEP);
66600Sstevel@tonic-gate tmp->gid_dgid_hi = addgid->gl_dgid_hi;
66610Sstevel@tonic-gate tmp->gid_dgid_lo = addgid->gl_dgid_lo;
66620Sstevel@tonic-gate
66630Sstevel@tonic-gate mutex_enter(&nodegid->gl_mutex);
66640Sstevel@tonic-gate tmp->gid_next = nodegid->gl_gid;
66650Sstevel@tonic-gate nodegid->gl_gid = tmp;
66660Sstevel@tonic-gate nodegid->gl_ngids++;
66670Sstevel@tonic-gate mutex_exit(&nodegid->gl_mutex);
66680Sstevel@tonic-gate }
66690Sstevel@tonic-gate
66700Sstevel@tonic-gate static void
ibdm_addto_glhcalist(ibdm_dp_gidinfo_t * gid_info,ibdm_hca_list_t * hca)66710Sstevel@tonic-gate ibdm_addto_glhcalist(ibdm_dp_gidinfo_t *gid_info,
66720Sstevel@tonic-gate ibdm_hca_list_t *hca)
66730Sstevel@tonic-gate {
66740Sstevel@tonic-gate ibdm_hca_list_t *head, *prev = NULL, *temp;
66750Sstevel@tonic-gate
66760Sstevel@tonic-gate IBTF_DPRINTF_L4(ibdm_string, "\taddto_glhcalist(%p, %p) "
66770Sstevel@tonic-gate ": gl_hca_list %p", gid_info, hca, gid_info->gl_hca_list);
66780Sstevel@tonic-gate ASSERT(!MUTEX_HELD(&gid_info->gl_mutex));
66796262Seota
66800Sstevel@tonic-gate mutex_enter(&gid_info->gl_mutex);
66810Sstevel@tonic-gate head = gid_info->gl_hca_list;
66820Sstevel@tonic-gate if (head == NULL) {
66830Sstevel@tonic-gate head = ibdm_dup_hca_attr(hca);
66840Sstevel@tonic-gate head->hl_next = NULL;
66850Sstevel@tonic-gate gid_info->gl_hca_list = head;
66860Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
66870Sstevel@tonic-gate IBTF_DPRINTF_L4(ibdm_string, "\tadd_to_glhcalist: "
66880Sstevel@tonic-gate "gid %p, gl_hca_list %p", gid_info,
66890Sstevel@tonic-gate gid_info->gl_hca_list);
66900Sstevel@tonic-gate return;
66910Sstevel@tonic-gate }
66920Sstevel@tonic-gate
66930Sstevel@tonic-gate /* Check if already in the list */
66940Sstevel@tonic-gate while (head) {
66950Sstevel@tonic-gate if (head->hl_hca_guid == hca->hl_hca_guid) {
66960Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
66970Sstevel@tonic-gate IBTF_DPRINTF_L4(ibdm_string,
66983826Shiremath "\taddto_glhcalist : gid %p hca %p dup",
66990Sstevel@tonic-gate gid_info, hca);
67000Sstevel@tonic-gate return;
67010Sstevel@tonic-gate }
67020Sstevel@tonic-gate prev = head;
67030Sstevel@tonic-gate head = head->hl_next;
67040Sstevel@tonic-gate }
67050Sstevel@tonic-gate
67060Sstevel@tonic-gate /* Add this HCA to gl_hca_list */
67070Sstevel@tonic-gate temp = ibdm_dup_hca_attr(hca);
67080Sstevel@tonic-gate temp->hl_next = NULL;
67090Sstevel@tonic-gate prev->hl_next = temp;
67100Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
67110Sstevel@tonic-gate
67120Sstevel@tonic-gate IBTF_DPRINTF_L4(ibdm_string, "\tadd_to_glhcalist: "
67130Sstevel@tonic-gate "gid %p, gl_hca_list %p", gid_info, gid_info->gl_hca_list);
67140Sstevel@tonic-gate }
67150Sstevel@tonic-gate
67160Sstevel@tonic-gate static void
ibdm_delete_glhca_list(ibdm_dp_gidinfo_t * gid_info)67170Sstevel@tonic-gate ibdm_delete_glhca_list(ibdm_dp_gidinfo_t *gid_info)
67180Sstevel@tonic-gate {
67190Sstevel@tonic-gate ASSERT(!MUTEX_HELD(&gid_info->gl_mutex));
67200Sstevel@tonic-gate ASSERT(!MUTEX_HELD(&ibdm.ibdm_mutex));
67210Sstevel@tonic-gate
67220Sstevel@tonic-gate mutex_enter(&gid_info->gl_mutex);
67230Sstevel@tonic-gate if (gid_info->gl_hca_list)
67240Sstevel@tonic-gate ibdm_ibnex_free_hca_list(gid_info->gl_hca_list);
67250Sstevel@tonic-gate gid_info->gl_hca_list = NULL;
67260Sstevel@tonic-gate mutex_exit(&gid_info->gl_mutex);
67270Sstevel@tonic-gate }
67280Sstevel@tonic-gate
67290Sstevel@tonic-gate
67300Sstevel@tonic-gate static void
ibdm_reset_all_dgids(ibmf_saa_handle_t port_sa_hdl)67310Sstevel@tonic-gate ibdm_reset_all_dgids(ibmf_saa_handle_t port_sa_hdl)
67320Sstevel@tonic-gate {
67330Sstevel@tonic-gate IBTF_DPRINTF_L4(ibdm_string, "\treset_all_dgids(%X)",
67340Sstevel@tonic-gate port_sa_hdl);
67350Sstevel@tonic-gate
6736*12723SRamaswamy.Tummala@Sun.COM if (ibdm_enumerate_iocs == 0)
6737*12723SRamaswamy.Tummala@Sun.COM return;
6738*12723SRamaswamy.Tummala@Sun.COM
67390Sstevel@tonic-gate ASSERT(!MUTEX_HELD(&ibdm.ibdm_mutex));
67400Sstevel@tonic-gate ASSERT(!MUTEX_HELD(&ibdm.ibdm_hl_mutex));
67410Sstevel@tonic-gate
67420Sstevel@tonic-gate /* Check : Not busy in another probe / sweep */
67430Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
67440Sstevel@tonic-gate if ((ibdm.ibdm_busy & IBDM_BUSY) == 0) {
67450Sstevel@tonic-gate ibdm_dp_gidinfo_t *gid_info;
67460Sstevel@tonic-gate
67470Sstevel@tonic-gate ibdm.ibdm_busy |= IBDM_BUSY;
67480Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
67490Sstevel@tonic-gate
67500Sstevel@tonic-gate /*
67510Sstevel@tonic-gate * Check if any GID is using the SA & IBMF handle
67520Sstevel@tonic-gate * of HCA port going down. Reset ibdm_dp_gidinfo_t
67530Sstevel@tonic-gate * using another HCA port which can reach the GID.
67540Sstevel@tonic-gate * This is for DM capable GIDs only, no need to do
67550Sstevel@tonic-gate * this for others
67560Sstevel@tonic-gate *
67570Sstevel@tonic-gate * Delete the GID if no alternate HCA port to reach
67580Sstevel@tonic-gate * it is found.
67590Sstevel@tonic-gate */
67600Sstevel@tonic-gate for (gid_info = ibdm.ibdm_dp_gidlist_head; gid_info; ) {
67610Sstevel@tonic-gate ibdm_dp_gidinfo_t *tmp;
67620Sstevel@tonic-gate
67630Sstevel@tonic-gate IBTF_DPRINTF_L4(ibdm_string, "\tevent_hdlr "
67640Sstevel@tonic-gate "checking gidinfo %p", gid_info);
67650Sstevel@tonic-gate
67662927Spramodbg if (gid_info->gl_sa_hdl == port_sa_hdl) {
67670Sstevel@tonic-gate IBTF_DPRINTF_L3(ibdm_string,
67680Sstevel@tonic-gate "\tevent_hdlr: down HCA port hdl "
67690Sstevel@tonic-gate "matches gid %p", gid_info);
67700Sstevel@tonic-gate
67712927Spramodbg /*
67722927Spramodbg * The non-DM GIDs can come back
67732927Spramodbg * with a new subnet prefix, when
67742927Spramodbg * the HCA port commes up again. To
67752927Spramodbg * avoid issues, delete non-DM
67762927Spramodbg * capable GIDs, if the gid was
67772927Spramodbg * discovered using the HCA port
67782927Spramodbg * going down. This is ensured by
67792927Spramodbg * setting gl_disconnected to 1.
67802927Spramodbg */
678110231SRajkumar.Sivaprakasam@Sun.COM if (gid_info->gl_is_dm_capable == B_FALSE)
67822927Spramodbg gid_info->gl_disconnected = 1;
67832927Spramodbg else
67842927Spramodbg ibdm_reset_gidinfo(gid_info);
67852927Spramodbg
67860Sstevel@tonic-gate if (gid_info->gl_disconnected) {
67870Sstevel@tonic-gate IBTF_DPRINTF_L3(ibdm_string,
67880Sstevel@tonic-gate "\tevent_hdlr: deleting"
67890Sstevel@tonic-gate " gid %p", gid_info);
67900Sstevel@tonic-gate tmp = gid_info;
67910Sstevel@tonic-gate gid_info = gid_info->gl_next;
67920Sstevel@tonic-gate ibdm_delete_gidinfo(tmp);
67930Sstevel@tonic-gate } else
67940Sstevel@tonic-gate gid_info = gid_info->gl_next;
67950Sstevel@tonic-gate } else
67960Sstevel@tonic-gate gid_info = gid_info->gl_next;
67970Sstevel@tonic-gate }
67980Sstevel@tonic-gate
67990Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
68000Sstevel@tonic-gate ibdm.ibdm_busy &= ~IBDM_BUSY;
68010Sstevel@tonic-gate cv_signal(&ibdm.ibdm_busy_cv);
68020Sstevel@tonic-gate }
68030Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
68040Sstevel@tonic-gate }
68050Sstevel@tonic-gate
68060Sstevel@tonic-gate static void
ibdm_reset_gidinfo(ibdm_dp_gidinfo_t * gidinfo)68070Sstevel@tonic-gate ibdm_reset_gidinfo(ibdm_dp_gidinfo_t *gidinfo)
68080Sstevel@tonic-gate {
68090Sstevel@tonic-gate ibdm_hca_list_t *hca_list = NULL;
68100Sstevel@tonic-gate ibdm_port_attr_t *port = NULL;
68110Sstevel@tonic-gate int gid_reinited = 0;
68120Sstevel@tonic-gate sa_node_record_t *nr, *tmp;
68130Sstevel@tonic-gate sa_portinfo_record_t *pi;
68140Sstevel@tonic-gate size_t nr_len = 0, pi_len = 0;
68150Sstevel@tonic-gate size_t path_len;
68160Sstevel@tonic-gate ib_gid_t sgid, dgid;
68170Sstevel@tonic-gate int ret, ii, nrecords;
68180Sstevel@tonic-gate sa_path_record_t *path;
68190Sstevel@tonic-gate uint8_t npaths = 1;
68203826Shiremath ibdm_pkey_tbl_t *pkey_tbl;
68210Sstevel@tonic-gate
68220Sstevel@tonic-gate IBTF_DPRINTF_L4(ibdm_string, "\treset_gidinfo(%p)", gidinfo);
68230Sstevel@tonic-gate
68240Sstevel@tonic-gate /*
68250Sstevel@tonic-gate * Get list of all the ports reachable from the local known HCA
68260Sstevel@tonic-gate * ports which are active
68270Sstevel@tonic-gate */
68280Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_hl_mutex);
68290Sstevel@tonic-gate for (ibdm_get_next_port(&hca_list, &port, 1); port;
68300Sstevel@tonic-gate ibdm_get_next_port(&hca_list, &port, 1)) {
68310Sstevel@tonic-gate
68320Sstevel@tonic-gate
68330Sstevel@tonic-gate /*
68340Sstevel@tonic-gate * Get the path and re-populate the gidinfo.
68350Sstevel@tonic-gate * Getting the path is the same probe_ioc
68360Sstevel@tonic-gate * Init the gid info as in ibdm_create_gidinfo()
68370Sstevel@tonic-gate */
68380Sstevel@tonic-gate nr = ibdm_get_node_records(port->pa_sa_hdl, &nr_len,
68390Sstevel@tonic-gate gidinfo->gl_nodeguid);
68400Sstevel@tonic-gate if (nr == NULL) {
68410Sstevel@tonic-gate IBTF_DPRINTF_L4(ibdm_string,
68420Sstevel@tonic-gate "\treset_gidinfo : no records");
68430Sstevel@tonic-gate continue;
68440Sstevel@tonic-gate }
68450Sstevel@tonic-gate
68460Sstevel@tonic-gate nrecords = (nr_len / sizeof (sa_node_record_t));
68470Sstevel@tonic-gate for (tmp = nr, ii = 0; (ii < nrecords); ii++, tmp++) {
68480Sstevel@tonic-gate if (tmp->NodeInfo.PortGUID == gidinfo->gl_portguid)
68490Sstevel@tonic-gate break;
68500Sstevel@tonic-gate }
68510Sstevel@tonic-gate
68520Sstevel@tonic-gate if (ii == nrecords) {
68530Sstevel@tonic-gate IBTF_DPRINTF_L4(ibdm_string,
68540Sstevel@tonic-gate "\treset_gidinfo : no record for portguid");
68550Sstevel@tonic-gate kmem_free(nr, nr_len);
68560Sstevel@tonic-gate continue;
68570Sstevel@tonic-gate }
68580Sstevel@tonic-gate
68590Sstevel@tonic-gate pi = ibdm_get_portinfo(port->pa_sa_hdl, &pi_len, tmp->LID);
68600Sstevel@tonic-gate if (pi == NULL) {
68610Sstevel@tonic-gate IBTF_DPRINTF_L4(ibdm_string,
68620Sstevel@tonic-gate "\treset_gidinfo : no portinfo");
68630Sstevel@tonic-gate kmem_free(nr, nr_len);
68640Sstevel@tonic-gate continue;
68650Sstevel@tonic-gate }
68660Sstevel@tonic-gate
68670Sstevel@tonic-gate sgid.gid_prefix = port->pa_sn_prefix;
68680Sstevel@tonic-gate sgid.gid_guid = port->pa_port_guid;
68690Sstevel@tonic-gate dgid.gid_prefix = pi->PortInfo.GidPrefix;
68700Sstevel@tonic-gate dgid.gid_guid = tmp->NodeInfo.PortGUID;
68710Sstevel@tonic-gate
68720Sstevel@tonic-gate ret = ibmf_saa_gid_to_pathrecords(port->pa_sa_hdl, sgid, dgid,
68730Sstevel@tonic-gate IBMF_SAA_PKEY_WC, 0, B_TRUE, &npaths, 0, &path_len, &path);
68740Sstevel@tonic-gate
68752259Shiremath if ((ret != IBMF_SUCCESS) || path == NULL) {
68760Sstevel@tonic-gate IBTF_DPRINTF_L4(ibdm_string,
68770Sstevel@tonic-gate "\treset_gidinfo : no paths");
68780Sstevel@tonic-gate kmem_free(pi, pi_len);
68790Sstevel@tonic-gate kmem_free(nr, nr_len);
68800Sstevel@tonic-gate continue;
68810Sstevel@tonic-gate }
68820Sstevel@tonic-gate
68830Sstevel@tonic-gate gidinfo->gl_dgid_hi = path->DGID.gid_prefix;
68840Sstevel@tonic-gate gidinfo->gl_dgid_lo = path->DGID.gid_guid;
68850Sstevel@tonic-gate gidinfo->gl_sgid_hi = path->SGID.gid_prefix;
68860Sstevel@tonic-gate gidinfo->gl_sgid_lo = path->SGID.gid_guid;
68873826Shiremath gidinfo->gl_p_key = path->P_Key;
68883826Shiremath gidinfo->gl_sa_hdl = port->pa_sa_hdl;
68890Sstevel@tonic-gate gidinfo->gl_ibmf_hdl = port->pa_ibmf_hdl;
68903826Shiremath gidinfo->gl_slid = path->SLID;
68913826Shiremath gidinfo->gl_dlid = path->DLID;
68920Sstevel@tonic-gate /* Reset redirect info, next MAD will set if redirected */
68936699Seota gidinfo->gl_redirected = 0;
68946699Seota gidinfo->gl_devid = (*tmp).NodeInfo.DeviceID;
68956699Seota gidinfo->gl_SL = path->SL;
68960Sstevel@tonic-gate
68973826Shiremath gidinfo->gl_qp_hdl = IBMF_QP_HANDLE_DEFAULT;
68983826Shiremath for (ii = 0; ii < port->pa_npkeys; ii++) {
68993826Shiremath if (port->pa_pkey_tbl == NULL)
69003826Shiremath break;
69013826Shiremath
69023826Shiremath pkey_tbl = &port->pa_pkey_tbl[ii];
69033826Shiremath if ((gidinfo->gl_p_key == pkey_tbl->pt_pkey) &&
69043826Shiremath (pkey_tbl->pt_qp_hdl != NULL)) {
69053826Shiremath gidinfo->gl_qp_hdl = pkey_tbl->pt_qp_hdl;
69063826Shiremath break;
69073826Shiremath }
69083826Shiremath }
69093826Shiremath
69103826Shiremath if (gidinfo->gl_qp_hdl == NULL)
69113826Shiremath IBTF_DPRINTF_L2(ibdm_string,
69123826Shiremath "\treset_gid_info: No matching Pkey");
69133826Shiremath else
69143826Shiremath gid_reinited = 1;
69150Sstevel@tonic-gate
69160Sstevel@tonic-gate kmem_free(path, path_len);
69170Sstevel@tonic-gate kmem_free(pi, pi_len);
69180Sstevel@tonic-gate kmem_free(nr, nr_len);
69190Sstevel@tonic-gate break;
69200Sstevel@tonic-gate }
69210Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_hl_mutex);
69220Sstevel@tonic-gate
69230Sstevel@tonic-gate if (!gid_reinited)
69240Sstevel@tonic-gate gidinfo->gl_disconnected = 1;
69250Sstevel@tonic-gate }
69260Sstevel@tonic-gate
69270Sstevel@tonic-gate static void
ibdm_delete_gidinfo(ibdm_dp_gidinfo_t * gidinfo)69280Sstevel@tonic-gate ibdm_delete_gidinfo(ibdm_dp_gidinfo_t *gidinfo)
69290Sstevel@tonic-gate {
69300Sstevel@tonic-gate ibdm_ioc_info_t *ioc_list;
69311912Spramodbg int in_gidlist = 0;
69321912Spramodbg
69331912Spramodbg /*
69341912Spramodbg * Check if gidinfo has been inserted into the
69351912Spramodbg * ibdm_dp_gidlist_head list. gl_next or gl_prev
69361912Spramodbg * != NULL, if gidinfo is the list.
69371912Spramodbg */
69381912Spramodbg if (gidinfo->gl_prev != NULL ||
69392927Spramodbg gidinfo->gl_next != NULL ||
69402927Spramodbg ibdm.ibdm_dp_gidlist_head == gidinfo)
69411912Spramodbg in_gidlist = 1;
69420Sstevel@tonic-gate
69430Sstevel@tonic-gate ioc_list = ibdm_update_ioc_gidlist(gidinfo, 0);
69440Sstevel@tonic-gate
69450Sstevel@tonic-gate /*
69460Sstevel@tonic-gate * Remove GID from the global GID list
69470Sstevel@tonic-gate * Handle the case where all port GIDs for an
69480Sstevel@tonic-gate * IOU have been hot-removed.
69490Sstevel@tonic-gate */
69500Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_mutex);
69510Sstevel@tonic-gate if (gidinfo->gl_iou != NULL && gidinfo->gl_ngids == 0) {
69520Sstevel@tonic-gate mutex_enter(&gidinfo->gl_mutex);
69534024Spramodbg (void) ibdm_free_iou_info(gidinfo, &gidinfo->gl_iou);
69540Sstevel@tonic-gate mutex_exit(&gidinfo->gl_mutex);
69550Sstevel@tonic-gate }
69561912Spramodbg
69572927Spramodbg /* Delete gl_hca_list */
69582927Spramodbg mutex_exit(&ibdm.ibdm_mutex);
69592927Spramodbg ibdm_delete_glhca_list(gidinfo);
69602927Spramodbg mutex_enter(&ibdm.ibdm_mutex);
69612927Spramodbg
69621912Spramodbg if (in_gidlist) {
69631912Spramodbg if (gidinfo->gl_prev != NULL)
69641912Spramodbg gidinfo->gl_prev->gl_next = gidinfo->gl_next;
69651912Spramodbg if (gidinfo->gl_next != NULL)
69661912Spramodbg gidinfo->gl_next->gl_prev = gidinfo->gl_prev;
69671912Spramodbg
69681912Spramodbg if (gidinfo == ibdm.ibdm_dp_gidlist_head)
69691912Spramodbg ibdm.ibdm_dp_gidlist_head = gidinfo->gl_next;
69701912Spramodbg if (gidinfo == ibdm.ibdm_dp_gidlist_tail)
69711912Spramodbg ibdm.ibdm_dp_gidlist_tail = gidinfo->gl_prev;
69721912Spramodbg ibdm.ibdm_ngids--;
69731912Spramodbg }
69740Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_mutex);
69750Sstevel@tonic-gate
69760Sstevel@tonic-gate mutex_destroy(&gidinfo->gl_mutex);
69776262Seota cv_destroy(&gidinfo->gl_probe_cv);
69780Sstevel@tonic-gate kmem_free(gidinfo, sizeof (ibdm_dp_gidinfo_t));
69790Sstevel@tonic-gate
69800Sstevel@tonic-gate /*
69810Sstevel@tonic-gate * Pass on the IOCs with updated GIDs to IBnexus
69820Sstevel@tonic-gate */
69830Sstevel@tonic-gate if (ioc_list) {
69840Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tdelete_gidinfo "
69850Sstevel@tonic-gate "IOC_PROP_UPDATE for %p\n", ioc_list);
69860Sstevel@tonic-gate mutex_enter(&ibdm.ibdm_ibnex_mutex);
69870Sstevel@tonic-gate if (ibdm.ibdm_ibnex_callback != NULL) {
69880Sstevel@tonic-gate (*ibdm.ibdm_ibnex_callback)((void *)
69890Sstevel@tonic-gate ioc_list, IBDM_EVENT_IOC_PROP_UPDATE);
69900Sstevel@tonic-gate }
69910Sstevel@tonic-gate mutex_exit(&ibdm.ibdm_ibnex_mutex);
69920Sstevel@tonic-gate }
69930Sstevel@tonic-gate }
69940Sstevel@tonic-gate
69951093Shiremath
69961093Shiremath static void
ibdm_fill_srv_attr_mod(ib_mad_hdr_t * hdr,ibdm_timeout_cb_args_t * cb_args)69971093Shiremath ibdm_fill_srv_attr_mod(ib_mad_hdr_t *hdr, ibdm_timeout_cb_args_t *cb_args)
69981093Shiremath {
69991093Shiremath uint32_t attr_mod;
70001093Shiremath
70011093Shiremath attr_mod = (cb_args->cb_ioc_num + 1) << 16;
70021093Shiremath attr_mod |= cb_args->cb_srvents_start;
70031093Shiremath attr_mod |= (cb_args->cb_srvents_end) << 8;
70041093Shiremath hdr->AttributeModifier = h2b32(attr_mod);
70051093Shiremath }
70061093Shiremath
70071093Shiremath static void
ibdm_bump_transactionID(ibdm_dp_gidinfo_t * gid_info)70081093Shiremath ibdm_bump_transactionID(ibdm_dp_gidinfo_t *gid_info)
70091093Shiremath {
70101093Shiremath ASSERT(MUTEX_HELD(&gid_info->gl_mutex));
70111093Shiremath gid_info->gl_transactionID++;
70121093Shiremath if (gid_info->gl_transactionID == gid_info->gl_max_transactionID) {
70131093Shiremath IBTF_DPRINTF_L4(ibdm_string,
70141093Shiremath "\tbump_transactionID(%p), wrapup", gid_info);
70151093Shiremath gid_info->gl_transactionID = gid_info->gl_min_transactionID;
70161093Shiremath }
70171093Shiremath }
70181093Shiremath
70194024Spramodbg /*
70204024Spramodbg * gl_prev_iou is set for *non-reprobe* sweeep requests, which
70214024Spramodbg * detected that ChangeID in IOU info has changed. The service
70224024Spramodbg * entry also may have changed. Check if service entry in IOC
70234024Spramodbg * has changed wrt the prev iou, if so notify to IB Nexus.
70244024Spramodbg */
70254024Spramodbg static ibdm_ioc_info_t *
ibdm_handle_prev_iou()70264024Spramodbg ibdm_handle_prev_iou()
70274024Spramodbg {
70284024Spramodbg ibdm_dp_gidinfo_t *gid_info;
70294024Spramodbg ibdm_ioc_info_t *ioc_list_head = NULL, *ioc_list;
70304024Spramodbg ibdm_ioc_info_t *prev_ioc, *ioc;
70314024Spramodbg int ii, jj, niocs, prev_niocs;
70324024Spramodbg
70334024Spramodbg ASSERT(MUTEX_HELD(&ibdm.ibdm_mutex));
70344024Spramodbg
70354024Spramodbg IBTF_DPRINTF_L4(ibdm_string, "\thandle_prev_iou enter");
70364024Spramodbg for (gid_info = ibdm.ibdm_dp_gidlist_head; gid_info;
70374024Spramodbg gid_info = gid_info->gl_next) {
70384024Spramodbg if (gid_info->gl_prev_iou == NULL)
70394024Spramodbg continue;
70404024Spramodbg
70414024Spramodbg IBTF_DPRINTF_L4(ibdm_string, "\thandle_prev_iou gid %p",
70424024Spramodbg gid_info);
70434024Spramodbg niocs = gid_info->gl_iou->iou_info.iou_num_ctrl_slots;
70444024Spramodbg prev_niocs =
70454024Spramodbg gid_info->gl_prev_iou->iou_info.iou_num_ctrl_slots;
70464024Spramodbg for (ii = 0; ii < niocs; ii++) {
70474024Spramodbg ioc = IBDM_GIDINFO2IOCINFO(gid_info, ii);
70484024Spramodbg
70494024Spramodbg /* Find matching IOC */
70504024Spramodbg for (jj = 0; jj < prev_niocs; jj++) {
70514024Spramodbg prev_ioc = (ibdm_ioc_info_t *)
70524024Spramodbg &gid_info->gl_prev_iou->iou_ioc_info[jj];
70534024Spramodbg if (prev_ioc->ioc_profile.ioc_guid ==
70544024Spramodbg ioc->ioc_profile.ioc_guid)
70554024Spramodbg break;
70564024Spramodbg }
70574024Spramodbg if (jj == prev_niocs)
70584024Spramodbg prev_ioc = NULL;
70594024Spramodbg if (ioc == NULL || prev_ioc == NULL)
70604024Spramodbg continue;
70614024Spramodbg if ((ioc->ioc_profile.ioc_service_entries !=
70624024Spramodbg prev_ioc->ioc_profile.ioc_service_entries) ||
70634024Spramodbg ibdm_serv_cmp(&ioc->ioc_serv[0],
70644024Spramodbg &prev_ioc->ioc_serv[0],
70654024Spramodbg ioc->ioc_profile.ioc_service_entries) != 0) {
70664024Spramodbg IBTF_DPRINTF_L4(ibdm_string,
70674024Spramodbg "/thandle_prev_iou modified IOC: "
70684024Spramodbg "current ioc %p, old ioc %p",
70694024Spramodbg ioc, prev_ioc);
70706262Seota mutex_enter(&gid_info->gl_mutex);
70714024Spramodbg ioc_list = ibdm_dup_ioc_info(ioc, gid_info);
70726262Seota mutex_exit(&gid_info->gl_mutex);
70734024Spramodbg ioc_list->ioc_info_updated.ib_prop_updated
70744024Spramodbg = 0;
70754024Spramodbg ioc_list->ioc_info_updated.ib_srv_prop_updated
70764024Spramodbg = 1;
70774024Spramodbg
70784024Spramodbg if (ioc_list_head == NULL)
70794024Spramodbg ioc_list_head = ioc_list;
70804024Spramodbg else {
70814024Spramodbg ioc_list_head->ioc_next = ioc_list;
70824024Spramodbg ioc_list_head = ioc_list;
70834024Spramodbg }
70844024Spramodbg }
70854024Spramodbg }
70864024Spramodbg
70874024Spramodbg mutex_enter(&gid_info->gl_mutex);
70884024Spramodbg (void) ibdm_free_iou_info(gid_info, &gid_info->gl_prev_iou);
70894024Spramodbg mutex_exit(&gid_info->gl_mutex);
70904024Spramodbg }
70914024Spramodbg IBTF_DPRINTF_L4(ibdm_string, "\thandle_prev_iouret %p",
70924024Spramodbg ioc_list_head);
70934024Spramodbg return (ioc_list_head);
70944024Spramodbg }
70954024Spramodbg
70964024Spramodbg /*
70974024Spramodbg * Compares two service entries lists, returns 0 if same, returns 1
70984024Spramodbg * if no match.
70994024Spramodbg */
71004024Spramodbg static int
ibdm_serv_cmp(ibdm_srvents_info_t * serv1,ibdm_srvents_info_t * serv2,int nserv)71014024Spramodbg ibdm_serv_cmp(ibdm_srvents_info_t *serv1, ibdm_srvents_info_t *serv2,
71024024Spramodbg int nserv)
71034024Spramodbg {
71044024Spramodbg int ii;
71054024Spramodbg
71064024Spramodbg IBTF_DPRINTF_L4(ibdm_string, "\tserv_cmp: enter");
71074024Spramodbg for (ii = 0; ii < nserv; ii++, serv1++, serv2++) {
71084024Spramodbg if (serv1->se_attr.srv_id != serv2->se_attr.srv_id ||
71096262Seota bcmp(serv1->se_attr.srv_name,
71106262Seota serv2->se_attr.srv_name,
71116262Seota IB_DM_MAX_SVC_NAME_LEN) != 0) {
71124024Spramodbg IBTF_DPRINTF_L4(ibdm_string, "\tserv_cmp: ret 1");
71134024Spramodbg return (1);
71144024Spramodbg }
71154024Spramodbg }
71164024Spramodbg IBTF_DPRINTF_L4(ibdm_string, "\tserv_cmp: ret 0");
71174024Spramodbg return (0);
71184024Spramodbg }
71194024Spramodbg
71200Sstevel@tonic-gate /* For debugging purpose only */
71210Sstevel@tonic-gate #ifdef DEBUG
71220Sstevel@tonic-gate void
ibdm_dump_mad_hdr(ib_mad_hdr_t * mad_hdr)71236262Seota ibdm_dump_mad_hdr(ib_mad_hdr_t *mad_hdr)
71246262Seota {
71256262Seota IBTF_DPRINTF_L4("ibdm", "\t\t MAD Header info");
71266262Seota IBTF_DPRINTF_L4("ibdm", "\t\t ---------------");
71276262Seota
71286262Seota IBTF_DPRINTF_L4("ibdm", "\tBase version : 0x%x"
71296262Seota "\tMgmt Class : 0x%x", mad_hdr->BaseVersion, mad_hdr->MgmtClass);
71306262Seota IBTF_DPRINTF_L4("ibdm", "\tClass version : 0x%x"
71316262Seota "\tR Method : 0x%x",
71326262Seota mad_hdr->ClassVersion, mad_hdr->R_Method);
71336262Seota IBTF_DPRINTF_L4("ibdm", "\tMAD Status : 0x%x"
71346262Seota "\tTransaction ID : 0x%llx",
71356262Seota b2h16(mad_hdr->Status), b2h64(mad_hdr->TransactionID));
71366262Seota IBTF_DPRINTF_L4("ibdm", "\t Attribute ID : 0x%x"
71376262Seota "\tAttribute Modified : 0x%lx",
71386262Seota b2h16(mad_hdr->AttributeID), b2h32(mad_hdr->AttributeModifier));
71396262Seota }
71406262Seota
71416262Seota
71426262Seota void
ibdm_dump_ibmf_msg(ibmf_msg_t * ibmf_msg,int flag)71430Sstevel@tonic-gate ibdm_dump_ibmf_msg(ibmf_msg_t *ibmf_msg, int flag)
71440Sstevel@tonic-gate {
71450Sstevel@tonic-gate ib_mad_hdr_t *mad_hdr;
71460Sstevel@tonic-gate
71470Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\t\t(IBMF_PKT): Local address info");
71480Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\t\t ------------------");
71490Sstevel@tonic-gate
71500Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tLocal Lid : 0x%x\tRemote Lid : 0x%x"
71510Sstevel@tonic-gate " Remote Qp : 0x%x", ibmf_msg->im_local_addr.ia_local_lid,
71520Sstevel@tonic-gate ibmf_msg->im_local_addr.ia_remote_lid,
71530Sstevel@tonic-gate ibmf_msg->im_local_addr.ia_remote_qno);
71546699Seota IBTF_DPRINTF_L4("ibdm", "\tP_key : 0x%x\tQ_key : 0x%x"
71556699Seota " SL : 0x%x", ibmf_msg->im_local_addr.ia_p_key,
71566699Seota ibmf_msg->im_local_addr.ia_q_key,
71576699Seota ibmf_msg->im_local_addr.ia_service_level);
71580Sstevel@tonic-gate
71590Sstevel@tonic-gate if (flag)
71600Sstevel@tonic-gate mad_hdr = (ib_mad_hdr_t *)IBDM_OUT_IBMFMSG_MADHDR(ibmf_msg);
71610Sstevel@tonic-gate else
71620Sstevel@tonic-gate mad_hdr = IBDM_IN_IBMFMSG_MADHDR(ibmf_msg);
71630Sstevel@tonic-gate
71646262Seota ibdm_dump_mad_hdr(mad_hdr);
71650Sstevel@tonic-gate }
71660Sstevel@tonic-gate
71676699Seota
71680Sstevel@tonic-gate void
ibdm_dump_path_info(sa_path_record_t * path)71690Sstevel@tonic-gate ibdm_dump_path_info(sa_path_record_t *path)
71700Sstevel@tonic-gate {
71710Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\t\t Path information");
71720Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\t\t ----------------");
71730Sstevel@tonic-gate
71740Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\t DGID hi : %llx\tDGID lo : %llx",
71750Sstevel@tonic-gate path->DGID.gid_prefix, path->DGID.gid_guid);
71760Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\t SGID hi : %llx\tSGID lo : %llx",
71770Sstevel@tonic-gate path->SGID.gid_prefix, path->SGID.gid_guid);
71786699Seota IBTF_DPRINTF_L4("ibdm", "\t SLID : %x\t\tDlID : %x",
71790Sstevel@tonic-gate path->SLID, path->DLID);
71806699Seota IBTF_DPRINTF_L4("ibdm", "\t P Key : %x\t\tSL : %x",
71816699Seota path->P_Key, path->SL);
71820Sstevel@tonic-gate }
71830Sstevel@tonic-gate
71840Sstevel@tonic-gate
71850Sstevel@tonic-gate void
ibdm_dump_classportinfo(ib_mad_classportinfo_t * classportinfo)71866262Seota ibdm_dump_classportinfo(ib_mad_classportinfo_t *classportinfo)
71870Sstevel@tonic-gate {
71880Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\t\t CLASSPORT INFO");
71890Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\t\t --------------");
71900Sstevel@tonic-gate
71910Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\t Response Time Value : 0x%x",
71920Sstevel@tonic-gate ((b2h32(classportinfo->RespTimeValue)) & 0x1F));
71930Sstevel@tonic-gate
71946262Seota IBTF_DPRINTF_L4("ibdm", "\t Redirected GID hi : 0x%llx",
71950Sstevel@tonic-gate b2h64(classportinfo->RedirectGID_hi));
71966262Seota IBTF_DPRINTF_L4("ibdm", "\t Redirected GID lo : 0x%llx",
71970Sstevel@tonic-gate b2h64(classportinfo->RedirectGID_lo));
71986699Seota IBTF_DPRINTF_L4("ibdm", "\t Redirected TC : 0x%x",
71996699Seota classportinfo->RedirectTC);
72006699Seota IBTF_DPRINTF_L4("ibdm", "\t Redirected SL : 0x%x",
72016699Seota classportinfo->RedirectSL);
72026699Seota IBTF_DPRINTF_L4("ibdm", "\t Redirected FL : 0x%x",
72036699Seota classportinfo->RedirectFL);
72046699Seota IBTF_DPRINTF_L4("ibdm", "\t Redirected LID : 0x%x",
72056699Seota b2h16(classportinfo->RedirectLID));
72066699Seota IBTF_DPRINTF_L4("ibdm", "\t Redirected P KEY : 0x%x",
72076699Seota b2h16(classportinfo->RedirectP_Key));
72086699Seota IBTF_DPRINTF_L4("ibdm", "\t Redirected QP : 0x%x",
72096699Seota classportinfo->RedirectQP);
72106699Seota IBTF_DPRINTF_L4("ibdm", "\t Redirected Q KEY : 0x%x",
72116699Seota b2h32(classportinfo->RedirectQ_Key));
72126699Seota IBTF_DPRINTF_L4("ibdm", "\t Trap GID hi : 0x%llx",
72136262Seota b2h64(classportinfo->TrapGID_hi));
72146699Seota IBTF_DPRINTF_L4("ibdm", "\t Trap GID lo : 0x%llx",
72156262Seota b2h64(classportinfo->TrapGID_lo));
72166699Seota IBTF_DPRINTF_L4("ibdm", "\t Trap TC : 0x%x",
72176699Seota classportinfo->TrapTC);
72186699Seota IBTF_DPRINTF_L4("ibdm", "\t Trap SL : 0x%x",
72196699Seota classportinfo->TrapSL);
72206699Seota IBTF_DPRINTF_L4("ibdm", "\t Trap FL : 0x%x",
72216699Seota classportinfo->TrapFL);
72226699Seota IBTF_DPRINTF_L4("ibdm", "\t Trap LID : 0x%x",
72236262Seota b2h16(classportinfo->TrapLID));
72246699Seota IBTF_DPRINTF_L4("ibdm", "\t Trap P_Key : 0x%x",
72256262Seota b2h16(classportinfo->TrapP_Key));
72266699Seota IBTF_DPRINTF_L4("ibdm", "\t Trap HL : 0x%x",
72276699Seota classportinfo->TrapHL);
72286699Seota IBTF_DPRINTF_L4("ibdm", "\t Trap QP : 0x%x",
72296699Seota classportinfo->TrapQP);
72306699Seota IBTF_DPRINTF_L4("ibdm", "\t Trap Q_Key : 0x%x",
72316262Seota b2h32(classportinfo->TrapQ_Key));
72320Sstevel@tonic-gate }
72330Sstevel@tonic-gate
72340Sstevel@tonic-gate
72350Sstevel@tonic-gate void
ibdm_dump_iounitinfo(ib_dm_io_unitinfo_t * iou_info)72360Sstevel@tonic-gate ibdm_dump_iounitinfo(ib_dm_io_unitinfo_t *iou_info)
72370Sstevel@tonic-gate {
72380Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\t\t I/O UnitInfo");
72390Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\t\t ------------");
72400Sstevel@tonic-gate
72410Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tChange ID : 0x%x",
72420Sstevel@tonic-gate b2h16(iou_info->iou_changeid));
72430Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\t#of ctrl slots : %d",
72440Sstevel@tonic-gate iou_info->iou_num_ctrl_slots);
72450Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tIOU flag : 0x%x",
72460Sstevel@tonic-gate iou_info->iou_flag);
72470Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tContrl list byte 0 : 0x%x",
72480Sstevel@tonic-gate iou_info->iou_ctrl_list[0]);
72490Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tContrl list byte 1 : 0x%x",
72500Sstevel@tonic-gate iou_info->iou_ctrl_list[1]);
72510Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tContrl list byte 2 : 0x%x",
72520Sstevel@tonic-gate iou_info->iou_ctrl_list[2]);
72530Sstevel@tonic-gate }
72540Sstevel@tonic-gate
72550Sstevel@tonic-gate
72560Sstevel@tonic-gate void
ibdm_dump_ioc_profile(ib_dm_ioc_ctrl_profile_t * ioc)72570Sstevel@tonic-gate ibdm_dump_ioc_profile(ib_dm_ioc_ctrl_profile_t *ioc)
72580Sstevel@tonic-gate {
72590Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\t\t IOC Controller Profile");
72600Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\t\t ----------------------");
72610Sstevel@tonic-gate
72620Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tIOC Guid : %llx", ioc->ioc_guid);
72630Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tVendorID : 0x%x", ioc->ioc_vendorid);
72640Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tDevice Id : 0x%x", ioc->ioc_deviceid);
72650Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tDevice Ver : 0x%x", ioc->ioc_device_ver);
72660Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tSubsys ID : 0x%x", ioc->ioc_subsys_id);
72670Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tIO class : 0x%x", ioc->ioc_io_class);
72680Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tIO subclass : 0x%x", ioc->ioc_io_subclass);
72690Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tProtocol : 0x%x", ioc->ioc_protocol);
72700Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tProtocolV : 0x%x", ioc->ioc_protocol_ver);
72710Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tmsg qdepth : %d", ioc->ioc_send_msg_qdepth);
72720Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\trdma qdepth : %d",
72736262Seota ioc->ioc_rdma_read_qdepth);
72740Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tsndmsg sz : %d", ioc->ioc_send_msg_sz);
72750Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\trdma xfersz : %d", ioc->ioc_rdma_xfer_sz);
72760Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\topcal mask : 0x%x",
72776262Seota ioc->ioc_ctrl_opcap_mask);
72780Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tsrventries : %x", ioc->ioc_service_entries);
72790Sstevel@tonic-gate }
72800Sstevel@tonic-gate
72810Sstevel@tonic-gate
72820Sstevel@tonic-gate void
ibdm_dump_service_entries(ib_dm_srv_t * srv_ents)72830Sstevel@tonic-gate ibdm_dump_service_entries(ib_dm_srv_t *srv_ents)
72840Sstevel@tonic-gate {
72850Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm",
72860Sstevel@tonic-gate "\thandle_srventry_mad: service id : %llx", srv_ents->srv_id);
72870Sstevel@tonic-gate
72880Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\thandle_srventry_mad: "
72890Sstevel@tonic-gate "Service Name : %s", srv_ents->srv_name);
72900Sstevel@tonic-gate }
72910Sstevel@tonic-gate
72920Sstevel@tonic-gate int ibdm_allow_sweep_fabric_timestamp = 1;
72930Sstevel@tonic-gate
72940Sstevel@tonic-gate void
ibdm_dump_sweep_fabric_timestamp(int flag)72950Sstevel@tonic-gate ibdm_dump_sweep_fabric_timestamp(int flag)
72960Sstevel@tonic-gate {
72970Sstevel@tonic-gate static hrtime_t x;
72980Sstevel@tonic-gate if (flag) {
72990Sstevel@tonic-gate if (ibdm_allow_sweep_fabric_timestamp) {
73000Sstevel@tonic-gate IBTF_DPRINTF_L4("ibdm", "\tTime taken to complete "
73010Sstevel@tonic-gate "sweep %lld ms", ((gethrtime() - x)/ 1000000));
73020Sstevel@tonic-gate }
73030Sstevel@tonic-gate x = 0;
73040Sstevel@tonic-gate } else
73050Sstevel@tonic-gate x = gethrtime();
73060Sstevel@tonic-gate }
73070Sstevel@tonic-gate #endif
7308