xref: /onnv-gate/usr/src/uts/common/io/ib/mgt/ibdm/ibdm.c (revision 12723:a1945ef29715)
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