xref: /illumos-gate/usr/src/uts/common/io/ib/mgt/ibdm/ibdm.c (revision fc8ae2ec)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
505fa0d51Spramodbg  * Common Development and Distribution License (the "License").
605fa0d51Spramodbg  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
228d61a337SJustin Frank  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
237c478bd9Sstevel@tonic-gate  */
24e1d3217bSJosef 'Jeff' Sipek /*
25e1d3217bSJosef 'Jeff' Sipek  * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
26e1d3217bSJosef 'Jeff' Sipek  */
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate /*
297c478bd9Sstevel@tonic-gate  * ibdm.c
307c478bd9Sstevel@tonic-gate  *
317c478bd9Sstevel@tonic-gate  * This file contains the InifiniBand Device Manager (IBDM) support functions.
327c478bd9Sstevel@tonic-gate  * IB nexus driver will only be the client for the IBDM module.
337c478bd9Sstevel@tonic-gate  *
347c478bd9Sstevel@tonic-gate  * IBDM registers with IBTF for HCA arrival/removal notification.
357c478bd9Sstevel@tonic-gate  * IBDM registers with SA access to send DM MADs to discover the IOC's behind
367c478bd9Sstevel@tonic-gate  * the IOU's.
377c478bd9Sstevel@tonic-gate  *
387c478bd9Sstevel@tonic-gate  * IB nexus driver registers with IBDM to find the information about the
397c478bd9Sstevel@tonic-gate  * HCA's and IOC's (behind the IOU) present on the IB fabric.
407c478bd9Sstevel@tonic-gate  */
417c478bd9Sstevel@tonic-gate 
42e1d3217bSJosef 'Jeff' Sipek #include <sys/sysmacros.h>
437c478bd9Sstevel@tonic-gate #include <sys/systm.h>
447c478bd9Sstevel@tonic-gate #include <sys/taskq.h>
457c478bd9Sstevel@tonic-gate #include <sys/ib/mgt/ibdm/ibdm_impl.h>
4653c1b7a3Seota #include <sys/ib/mgt/ibmf/ibmf_impl.h>
47dcf1eb70SSudhakar Dindukurti #include <sys/ib/ibtl/impl/ibtl_ibnex.h>
487c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
497c478bd9Sstevel@tonic-gate 
507c478bd9Sstevel@tonic-gate /* Function Prototype declarations */
51add2b70bSpramodbg static int	ibdm_free_iou_info(ibdm_dp_gidinfo_t *, ibdm_iou_info_t **);
527c478bd9Sstevel@tonic-gate static int	ibdm_fini(void);
537c478bd9Sstevel@tonic-gate static int	ibdm_init(void);
547c478bd9Sstevel@tonic-gate static int	ibdm_get_reachable_ports(ibdm_port_attr_t *,
557c478bd9Sstevel@tonic-gate 			ibdm_hca_list_t *);
567c478bd9Sstevel@tonic-gate static ibdm_dp_gidinfo_t *ibdm_check_dgid(ib_guid_t, ib_sn_prefix_t);
577c478bd9Sstevel@tonic-gate static ibdm_dp_gidinfo_t *ibdm_check_dest_nodeguid(ibdm_dp_gidinfo_t *);
5853c1b7a3Seota static boolean_t ibdm_is_cisco(ib_guid_t);
5953c1b7a3Seota static boolean_t ibdm_is_cisco_switch(ibdm_dp_gidinfo_t *);
6053c1b7a3Seota static void	ibdm_wait_cisco_probe_completion(ibdm_dp_gidinfo_t *);
6153c1b7a3Seota static int	ibdm_set_classportinfo(ibdm_dp_gidinfo_t *);
627c478bd9Sstevel@tonic-gate static int	ibdm_send_classportinfo(ibdm_dp_gidinfo_t *);
637c478bd9Sstevel@tonic-gate static int	ibdm_send_iounitinfo(ibdm_dp_gidinfo_t *);
647c478bd9Sstevel@tonic-gate static int	ibdm_is_dev_mgt_supported(ibdm_dp_gidinfo_t *);
657c478bd9Sstevel@tonic-gate static int	ibdm_get_node_port_guids(ibmf_saa_handle_t, ib_lid_t,
667c478bd9Sstevel@tonic-gate 		    ib_guid_t *, ib_guid_t *);
677c478bd9Sstevel@tonic-gate static int	ibdm_retry_command(ibdm_timeout_cb_args_t *);
687c478bd9Sstevel@tonic-gate static int	ibdm_get_diagcode(ibdm_dp_gidinfo_t *, int);
697c478bd9Sstevel@tonic-gate static int	ibdm_verify_mad_status(ib_mad_hdr_t *);
707c478bd9Sstevel@tonic-gate static int	ibdm_handle_redirection(ibmf_msg_t *,
717c478bd9Sstevel@tonic-gate 		    ibdm_dp_gidinfo_t *, int *);
727c478bd9Sstevel@tonic-gate static void	ibdm_wait_probe_completion(void);
737c478bd9Sstevel@tonic-gate static void	ibdm_sweep_fabric(int);
747c478bd9Sstevel@tonic-gate static void	ibdm_probe_gid_thread(void *);
757c478bd9Sstevel@tonic-gate static void	ibdm_wakeup_probe_gid_cv(void);
767c478bd9Sstevel@tonic-gate static void	ibdm_port_attr_ibmf_init(ibdm_port_attr_t *, ib_pkey_t, int);
777c478bd9Sstevel@tonic-gate static int	ibdm_port_attr_ibmf_fini(ibdm_port_attr_t *, int);
787c478bd9Sstevel@tonic-gate static void	ibdm_update_port_attr(ibdm_port_attr_t *);
797c478bd9Sstevel@tonic-gate static void	ibdm_handle_hca_attach(ib_guid_t);
807c478bd9Sstevel@tonic-gate static void	ibdm_handle_srventry_mad(ibmf_msg_t *,
817c478bd9Sstevel@tonic-gate 		    ibdm_dp_gidinfo_t *, int *);
827c478bd9Sstevel@tonic-gate static void	ibdm_ibmf_recv_cb(ibmf_handle_t, ibmf_msg_t *, void *);
837c478bd9Sstevel@tonic-gate static void	ibdm_recv_incoming_mad(void *);
847c478bd9Sstevel@tonic-gate static void	ibdm_process_incoming_mad(ibmf_handle_t, ibmf_msg_t *, void *);
857c478bd9Sstevel@tonic-gate static void	ibdm_ibmf_send_cb(ibmf_handle_t, ibmf_msg_t *, void *);
867c478bd9Sstevel@tonic-gate static void	ibdm_pkt_timeout_hdlr(void *arg);
877c478bd9Sstevel@tonic-gate static void	ibdm_initialize_port(ibdm_port_attr_t *);
8876c04273SRajkumar Sivaprakasam static void	ibdm_update_port_pkeys(ibdm_port_attr_t *port);
897c478bd9Sstevel@tonic-gate static void	ibdm_handle_diagcode(ibmf_msg_t *, ibdm_dp_gidinfo_t *, int *);
907c478bd9Sstevel@tonic-gate static void	ibdm_probe_gid(ibdm_dp_gidinfo_t *);
917c478bd9Sstevel@tonic-gate static void	ibdm_alloc_send_buffers(ibmf_msg_t *);
927c478bd9Sstevel@tonic-gate static void	ibdm_free_send_buffers(ibmf_msg_t *);
937c478bd9Sstevel@tonic-gate static void	ibdm_handle_hca_detach(ib_guid_t);
94dcf1eb70SSudhakar Dindukurti static void	ibdm_handle_port_change_event(ibt_async_event_t *);
957c478bd9Sstevel@tonic-gate static int	ibdm_fini_port(ibdm_port_attr_t *);
967c478bd9Sstevel@tonic-gate static int	ibdm_uninit_hca(ibdm_hca_list_t *);
9753c1b7a3Seota static void	ibdm_handle_setclassportinfo(ibmf_handle_t, ibmf_msg_t *,
9853c1b7a3Seota 		    ibdm_dp_gidinfo_t *, int *);
997c478bd9Sstevel@tonic-gate static void	ibdm_handle_iounitinfo(ibmf_handle_t,
1007c478bd9Sstevel@tonic-gate 		    ibmf_msg_t *, ibdm_dp_gidinfo_t *, int *);
1017c478bd9Sstevel@tonic-gate static void	ibdm_handle_ioc_profile(ibmf_handle_t,
1027c478bd9Sstevel@tonic-gate 		    ibmf_msg_t *, ibdm_dp_gidinfo_t *, int *);
1037c478bd9Sstevel@tonic-gate static void	ibdm_event_hdlr(void *, ibt_hca_hdl_t,
1047c478bd9Sstevel@tonic-gate 		    ibt_async_code_t, ibt_async_event_t *);
1057c478bd9Sstevel@tonic-gate static void	ibdm_handle_classportinfo(ibmf_handle_t,
1067c478bd9Sstevel@tonic-gate 		    ibmf_msg_t *, ibdm_dp_gidinfo_t *, int *);
1077c478bd9Sstevel@tonic-gate static void	ibdm_update_ioc_port_gidlist(ibdm_ioc_info_t *,
1087c478bd9Sstevel@tonic-gate 		    ibdm_dp_gidinfo_t *);
1097c478bd9Sstevel@tonic-gate 
1107c478bd9Sstevel@tonic-gate static ibdm_hca_list_t		*ibdm_dup_hca_attr(ibdm_hca_list_t *);
1117c478bd9Sstevel@tonic-gate static ibdm_ioc_info_t		*ibdm_dup_ioc_info(ibdm_ioc_info_t *,
1127c478bd9Sstevel@tonic-gate 				    ibdm_dp_gidinfo_t *gid_list);
1137c478bd9Sstevel@tonic-gate static void			ibdm_probe_ioc(ib_guid_t, ib_guid_t, int);
1147c478bd9Sstevel@tonic-gate static ibdm_ioc_info_t		*ibdm_is_ioc_present(ib_guid_t,
1157c478bd9Sstevel@tonic-gate 				    ibdm_dp_gidinfo_t *, int *);
1167c478bd9Sstevel@tonic-gate static ibdm_port_attr_t		*ibdm_get_port_attr(ibt_async_event_t *,
1177c478bd9Sstevel@tonic-gate 				    ibdm_hca_list_t **);
1187c478bd9Sstevel@tonic-gate static sa_node_record_t		*ibdm_get_node_records(ibmf_saa_handle_t,
1197c478bd9Sstevel@tonic-gate 				    size_t *, ib_guid_t);
12053c1b7a3Seota static int			ibdm_get_node_record_by_port(ibmf_saa_handle_t,
12153c1b7a3Seota 				    ib_guid_t, sa_node_record_t **, size_t *);
1227c478bd9Sstevel@tonic-gate static sa_portinfo_record_t	*ibdm_get_portinfo(ibmf_saa_handle_t, size_t *,
1237c478bd9Sstevel@tonic-gate 				    ib_lid_t);
1247c478bd9Sstevel@tonic-gate static ibdm_dp_gidinfo_t	*ibdm_create_gid_info(ibdm_port_attr_t *,
1257c478bd9Sstevel@tonic-gate 				    ib_gid_t, ib_gid_t);
1267c478bd9Sstevel@tonic-gate static ibdm_dp_gidinfo_t	*ibdm_find_gid(ib_guid_t, ib_guid_t);
1277c478bd9Sstevel@tonic-gate static int	ibdm_send_ioc_profile(ibdm_dp_gidinfo_t *, uint8_t);
1287c478bd9Sstevel@tonic-gate static ibdm_ioc_info_t	*ibdm_update_ioc_gidlist(ibdm_dp_gidinfo_t *, int);
1297c478bd9Sstevel@tonic-gate static void	ibdm_saa_event_cb(ibmf_saa_handle_t, ibmf_saa_subnet_event_t,
1307c478bd9Sstevel@tonic-gate 		    ibmf_saa_event_details_t *, void *);
1317c478bd9Sstevel@tonic-gate static void	ibdm_reprobe_update_port_srv(ibdm_ioc_info_t *,
1327c478bd9Sstevel@tonic-gate     ibdm_dp_gidinfo_t *);
1337c478bd9Sstevel@tonic-gate static ibdm_dp_gidinfo_t *ibdm_handle_gid_rm(ibdm_dp_gidinfo_t *);
1347c478bd9Sstevel@tonic-gate static void ibdm_rmfrom_glgid_list(ibdm_dp_gidinfo_t *,
1357c478bd9Sstevel@tonic-gate     ibdm_dp_gidinfo_t *);
1367c478bd9Sstevel@tonic-gate static void ibdm_addto_gidlist(ibdm_gid_t **, ibdm_gid_t *);
1377c478bd9Sstevel@tonic-gate static void ibdm_free_gid_list(ibdm_gid_t *);
1387c478bd9Sstevel@tonic-gate static void ibdm_rescan_gidlist(ib_guid_t *ioc_guid);
1397c478bd9Sstevel@tonic-gate static void ibdm_notify_newgid_iocs(ibdm_dp_gidinfo_t *);
1407c478bd9Sstevel@tonic-gate static void ibdm_saa_event_taskq(void *);
1417c478bd9Sstevel@tonic-gate static void ibdm_free_saa_event_arg(ibdm_saa_event_arg_t *);
1427c478bd9Sstevel@tonic-gate static void ibdm_get_next_port(ibdm_hca_list_t **,
1437c478bd9Sstevel@tonic-gate     ibdm_port_attr_t **, int);
1447c478bd9Sstevel@tonic-gate static void ibdm_add_to_gl_gid(ibdm_dp_gidinfo_t *,
1457c478bd9Sstevel@tonic-gate     ibdm_dp_gidinfo_t *);
1467c478bd9Sstevel@tonic-gate static void ibdm_addto_glhcalist(ibdm_dp_gidinfo_t *,
1477c478bd9Sstevel@tonic-gate     ibdm_hca_list_t *);
1487c478bd9Sstevel@tonic-gate static void ibdm_delete_glhca_list(ibdm_dp_gidinfo_t *);
1497c478bd9Sstevel@tonic-gate static void ibdm_saa_handle_new_gid(void *);
1507c478bd9Sstevel@tonic-gate static void ibdm_reset_all_dgids(ibmf_saa_handle_t);
1517c478bd9Sstevel@tonic-gate static void ibdm_reset_gidinfo(ibdm_dp_gidinfo_t *);
1527c478bd9Sstevel@tonic-gate static void ibdm_delete_gidinfo(ibdm_dp_gidinfo_t *);
1539d3d2ed0Shiremath static void ibdm_fill_srv_attr_mod(ib_mad_hdr_t *, ibdm_timeout_cb_args_t *);
1549d3d2ed0Shiremath static void ibdm_bump_transactionID(ibdm_dp_gidinfo_t *);
155add2b70bSpramodbg static ibdm_ioc_info_t	*ibdm_handle_prev_iou();
156add2b70bSpramodbg static int ibdm_serv_cmp(ibdm_srvents_info_t *, ibdm_srvents_info_t *,
157add2b70bSpramodbg     int);
15818edb70cSeota static ibdm_ioc_info_t *ibdm_get_ioc_info_with_gid(ib_guid_t,
15918edb70cSeota     ibdm_dp_gidinfo_t **);
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate int	ibdm_dft_timeout	= IBDM_DFT_TIMEOUT;
1627c478bd9Sstevel@tonic-gate int	ibdm_dft_retry_cnt	= IBDM_DFT_NRETRIES;
1637c478bd9Sstevel@tonic-gate #ifdef DEBUG
1647c478bd9Sstevel@tonic-gate int	ibdm_ignore_saa_event = 0;
1657c478bd9Sstevel@tonic-gate #endif
166c44ec8d2SRamaswamy Tummala int	ibdm_enumerate_iocs = 0;
1677c478bd9Sstevel@tonic-gate 
1687c478bd9Sstevel@tonic-gate /* Modload support */
1697c478bd9Sstevel@tonic-gate static struct modlmisc ibdm_modlmisc	= {
1707c478bd9Sstevel@tonic-gate 	&mod_miscops,
17100a3eaf3SRamaswamy Tummala 	"InfiniBand Device Manager"
1727c478bd9Sstevel@tonic-gate };
1737c478bd9Sstevel@tonic-gate 
1747c478bd9Sstevel@tonic-gate struct modlinkage ibdm_modlinkage = {
1757c478bd9Sstevel@tonic-gate 	MODREV_1,
1767c478bd9Sstevel@tonic-gate 	(void *)&ibdm_modlmisc,
1777c478bd9Sstevel@tonic-gate 	NULL
1787c478bd9Sstevel@tonic-gate };
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate static ibt_clnt_modinfo_t ibdm_ibt_modinfo = {
18103494a98SBill Taylor 	IBTI_V_CURR,
1827c478bd9Sstevel@tonic-gate 	IBT_DM,
1837c478bd9Sstevel@tonic-gate 	ibdm_event_hdlr,
1847c478bd9Sstevel@tonic-gate 	NULL,
1857c478bd9Sstevel@tonic-gate 	"ibdm"
1867c478bd9Sstevel@tonic-gate };
1877c478bd9Sstevel@tonic-gate 
1887c478bd9Sstevel@tonic-gate /* Global variables */
1897c478bd9Sstevel@tonic-gate ibdm_t	ibdm;
1907c478bd9Sstevel@tonic-gate int	ibdm_taskq_enable = IBDM_ENABLE_TASKQ_HANDLING;
1917c478bd9Sstevel@tonic-gate char	*ibdm_string = "ibdm";
1927c478bd9Sstevel@tonic-gate 
1937c478bd9Sstevel@tonic-gate _NOTE(SCHEME_PROTECTS_DATA("Serialized access by cv",
1947c478bd9Sstevel@tonic-gate     ibdm.ibdm_dp_gidlist_head))
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate /*
1977c478bd9Sstevel@tonic-gate  * _init
1987c478bd9Sstevel@tonic-gate  *	Loadable module init, called before any other module.
1997c478bd9Sstevel@tonic-gate  *	Initialize mutex
2007c478bd9Sstevel@tonic-gate  *	Register with IBTF
2017c478bd9Sstevel@tonic-gate  */
2027c478bd9Sstevel@tonic-gate int
_init(void)2037c478bd9Sstevel@tonic-gate _init(void)
2047c478bd9Sstevel@tonic-gate {
2057c478bd9Sstevel@tonic-gate 	int		err;
2067c478bd9Sstevel@tonic-gate 
2077c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\t_init: addr of ibdm %p", &ibdm);
2087c478bd9Sstevel@tonic-gate 
2097c478bd9Sstevel@tonic-gate 	if ((err = ibdm_init()) != IBDM_SUCCESS) {
2107c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibdm", "_init: ibdm_init failed 0x%x", err);
2117c478bd9Sstevel@tonic-gate 		(void) ibdm_fini();
2127c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
2137c478bd9Sstevel@tonic-gate 	}
2147c478bd9Sstevel@tonic-gate 
2157c478bd9Sstevel@tonic-gate 	if ((err = mod_install(&ibdm_modlinkage)) != 0) {
2167c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibdm", "_init: mod_install failed 0x%x", err);
2177c478bd9Sstevel@tonic-gate 		(void) ibdm_fini();
2187c478bd9Sstevel@tonic-gate 	}
2197c478bd9Sstevel@tonic-gate 	return (err);
2207c478bd9Sstevel@tonic-gate }
2217c478bd9Sstevel@tonic-gate 
2227c478bd9Sstevel@tonic-gate 
2237c478bd9Sstevel@tonic-gate int
_fini(void)2247c478bd9Sstevel@tonic-gate _fini(void)
2257c478bd9Sstevel@tonic-gate {
2267c478bd9Sstevel@tonic-gate 	int err;
2277c478bd9Sstevel@tonic-gate 
2287c478bd9Sstevel@tonic-gate 	if ((err = ibdm_fini()) != IBDM_SUCCESS) {
2297c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibdm", "_fini: ibdm_fini failed 0x%x", err);
2307c478bd9Sstevel@tonic-gate 		(void) ibdm_init();
2317c478bd9Sstevel@tonic-gate 		return (EBUSY);
2327c478bd9Sstevel@tonic-gate 	}
2337c478bd9Sstevel@tonic-gate 
2347c478bd9Sstevel@tonic-gate 	if ((err = mod_remove(&ibdm_modlinkage)) != 0) {
2357c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibdm", "_fini: mod_remove failed 0x%x", err);
2367c478bd9Sstevel@tonic-gate 		(void) ibdm_init();
2377c478bd9Sstevel@tonic-gate 	}
2387c478bd9Sstevel@tonic-gate 	return (err);
2397c478bd9Sstevel@tonic-gate }
2407c478bd9Sstevel@tonic-gate 
2417c478bd9Sstevel@tonic-gate 
2427c478bd9Sstevel@tonic-gate int
_info(struct modinfo * modinfop)2437c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop)
2447c478bd9Sstevel@tonic-gate {
2457c478bd9Sstevel@tonic-gate 	return (mod_info(&ibdm_modlinkage, modinfop));
2467c478bd9Sstevel@tonic-gate }
2477c478bd9Sstevel@tonic-gate 
2487c478bd9Sstevel@tonic-gate 
2497c478bd9Sstevel@tonic-gate /*
2507c478bd9Sstevel@tonic-gate  * ibdm_init():
2517c478bd9Sstevel@tonic-gate  * 	Register with IBTF
2527c478bd9Sstevel@tonic-gate  *	Allocate memory for the HCAs
2537c478bd9Sstevel@tonic-gate  *	Allocate minor-nodes for the HCAs
2547c478bd9Sstevel@tonic-gate  */
2557c478bd9Sstevel@tonic-gate static int
ibdm_init(void)2567c478bd9Sstevel@tonic-gate ibdm_init(void)
2577c478bd9Sstevel@tonic-gate {
2587c478bd9Sstevel@tonic-gate 	int			i, hca_count;
2597c478bd9Sstevel@tonic-gate 	ib_guid_t		*hca_guids;
2607c478bd9Sstevel@tonic-gate 	ibt_status_t		status;
2617c478bd9Sstevel@tonic-gate 
2627c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tibdm_init:");
2637c478bd9Sstevel@tonic-gate 	if (!(ibdm.ibdm_state & IBDM_LOCKS_ALLOCED)) {
2647c478bd9Sstevel@tonic-gate 		mutex_init(&ibdm.ibdm_mutex, NULL, MUTEX_DEFAULT, NULL);
2657c478bd9Sstevel@tonic-gate 		mutex_init(&ibdm.ibdm_hl_mutex, NULL, MUTEX_DEFAULT, NULL);
2667c478bd9Sstevel@tonic-gate 		mutex_init(&ibdm.ibdm_ibnex_mutex, NULL, MUTEX_DEFAULT, NULL);
26700a3eaf3SRamaswamy Tummala 		cv_init(&ibdm.ibdm_port_settle_cv, NULL, CV_DRIVER, NULL);
2687c478bd9Sstevel@tonic-gate 		mutex_enter(&ibdm.ibdm_mutex);
2697c478bd9Sstevel@tonic-gate 		ibdm.ibdm_state |= IBDM_LOCKS_ALLOCED;
2707c478bd9Sstevel@tonic-gate 	}
2717c478bd9Sstevel@tonic-gate 
2727c478bd9Sstevel@tonic-gate 	if (!(ibdm.ibdm_state & IBDM_IBT_ATTACHED)) {
2737c478bd9Sstevel@tonic-gate 		if ((status = ibt_attach(&ibdm_ibt_modinfo, NULL, NULL,
2747c478bd9Sstevel@tonic-gate 		    (void *)&ibdm.ibdm_ibt_clnt_hdl)) != IBT_SUCCESS) {
2757c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibdm", "ibdm_init: ibt_attach "
2767c478bd9Sstevel@tonic-gate 			    "failed %x", status);
2777c478bd9Sstevel@tonic-gate 			mutex_exit(&ibdm.ibdm_mutex);
2787c478bd9Sstevel@tonic-gate 			return (IBDM_FAILURE);
2797c478bd9Sstevel@tonic-gate 		}
2807c478bd9Sstevel@tonic-gate 
2817c478bd9Sstevel@tonic-gate 		ibdm.ibdm_state |= IBDM_IBT_ATTACHED;
2827c478bd9Sstevel@tonic-gate 		mutex_exit(&ibdm.ibdm_mutex);
2837c478bd9Sstevel@tonic-gate 	}
2847c478bd9Sstevel@tonic-gate 
2857c478bd9Sstevel@tonic-gate 
2867c478bd9Sstevel@tonic-gate 	if (!(ibdm.ibdm_state & IBDM_HCA_ATTACHED)) {
2877c478bd9Sstevel@tonic-gate 		hca_count = ibt_get_hca_list(&hca_guids);
2887c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibdm", "ibdm_init: num_hcas = %d", hca_count);
2897c478bd9Sstevel@tonic-gate 		for (i = 0; i < hca_count; i++)
2907c478bd9Sstevel@tonic-gate 			(void) ibdm_handle_hca_attach(hca_guids[i]);
2917c478bd9Sstevel@tonic-gate 		if (hca_count)
2927c478bd9Sstevel@tonic-gate 			ibt_free_hca_list(hca_guids, hca_count);
2937c478bd9Sstevel@tonic-gate 
2947c478bd9Sstevel@tonic-gate 		mutex_enter(&ibdm.ibdm_mutex);
2957c478bd9Sstevel@tonic-gate 		ibdm.ibdm_state |= IBDM_HCA_ATTACHED;
2967c478bd9Sstevel@tonic-gate 		mutex_exit(&ibdm.ibdm_mutex);
2977c478bd9Sstevel@tonic-gate 	}
2987c478bd9Sstevel@tonic-gate 
2997c478bd9Sstevel@tonic-gate 	if (!(ibdm.ibdm_state & IBDM_CVS_ALLOCED)) {
3007c478bd9Sstevel@tonic-gate 		cv_init(&ibdm.ibdm_probe_cv, NULL, CV_DRIVER, NULL);
3017c478bd9Sstevel@tonic-gate 		cv_init(&ibdm.ibdm_busy_cv, NULL, CV_DRIVER, NULL);
3027c478bd9Sstevel@tonic-gate 		mutex_enter(&ibdm.ibdm_mutex);
3037c478bd9Sstevel@tonic-gate 		ibdm.ibdm_state |= IBDM_CVS_ALLOCED;
3047c478bd9Sstevel@tonic-gate 		mutex_exit(&ibdm.ibdm_mutex);
3057c478bd9Sstevel@tonic-gate 	}
3067c478bd9Sstevel@tonic-gate 	return (IBDM_SUCCESS);
3077c478bd9Sstevel@tonic-gate }
3087c478bd9Sstevel@tonic-gate 
3097c478bd9Sstevel@tonic-gate 
3107c478bd9Sstevel@tonic-gate static int
ibdm_free_iou_info(ibdm_dp_gidinfo_t * gid_info,ibdm_iou_info_t ** ioup)311add2b70bSpramodbg ibdm_free_iou_info(ibdm_dp_gidinfo_t *gid_info, ibdm_iou_info_t **ioup)
3127c478bd9Sstevel@tonic-gate {
3137c478bd9Sstevel@tonic-gate 	int			ii, k, niocs;
3147c478bd9Sstevel@tonic-gate 	size_t			size;
3157c478bd9Sstevel@tonic-gate 	ibdm_gid_t		*delete, *head;
3167c478bd9Sstevel@tonic-gate 	timeout_id_t		timeout_id;
3177c478bd9Sstevel@tonic-gate 	ibdm_ioc_info_t		*ioc;
318add2b70bSpramodbg 	ibdm_iou_info_t		*gl_iou = *ioup;
3197c478bd9Sstevel@tonic-gate 
3207c478bd9Sstevel@tonic-gate 	ASSERT(mutex_owned(&gid_info->gl_mutex));
321add2b70bSpramodbg 	if (gl_iou == NULL) {
3227c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibdm", "\tibdm_free_iou_info: No IOU");
3237c478bd9Sstevel@tonic-gate 		return (0);
3247c478bd9Sstevel@tonic-gate 	}
3257c478bd9Sstevel@tonic-gate 
326add2b70bSpramodbg 	niocs = gl_iou->iou_info.iou_num_ctrl_slots;
3277c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tfree_iou_info: gid_info = %p, niocs %d",
3287c478bd9Sstevel@tonic-gate 	    gid_info, niocs);
3297c478bd9Sstevel@tonic-gate 
3307c478bd9Sstevel@tonic-gate 	for (ii = 0; ii < niocs; ii++) {
331add2b70bSpramodbg 		ioc = (ibdm_ioc_info_t *)&gl_iou->iou_ioc_info[ii];
3327c478bd9Sstevel@tonic-gate 
3337c478bd9Sstevel@tonic-gate 		/* handle the case where an ioc_timeout_id is scheduled */
3347c478bd9Sstevel@tonic-gate 		if (ioc->ioc_timeout_id) {
3357c478bd9Sstevel@tonic-gate 			timeout_id = ioc->ioc_timeout_id;
33618edb70cSeota 			ioc->ioc_timeout_id = 0;
3377c478bd9Sstevel@tonic-gate 			mutex_exit(&gid_info->gl_mutex);
3387c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L5("ibdm", "free_iou_info: "
3397c478bd9Sstevel@tonic-gate 			    "ioc_timeout_id = 0x%x", timeout_id);
3407c478bd9Sstevel@tonic-gate 			if (untimeout(timeout_id) == -1) {
3417c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibdm", "free_iou_info: "
3427c478bd9Sstevel@tonic-gate 				    "untimeout ioc_timeout_id failed");
3437c478bd9Sstevel@tonic-gate 				mutex_enter(&gid_info->gl_mutex);
3447c478bd9Sstevel@tonic-gate 				return (-1);
3457c478bd9Sstevel@tonic-gate 			}
3467c478bd9Sstevel@tonic-gate 			mutex_enter(&gid_info->gl_mutex);
3477c478bd9Sstevel@tonic-gate 		}
3487c478bd9Sstevel@tonic-gate 
3497c478bd9Sstevel@tonic-gate 		/* handle the case where an ioc_dc_timeout_id is scheduled */
3507c478bd9Sstevel@tonic-gate 		if (ioc->ioc_dc_timeout_id) {
3517c478bd9Sstevel@tonic-gate 			timeout_id = ioc->ioc_dc_timeout_id;
35218edb70cSeota 			ioc->ioc_dc_timeout_id = 0;
3537c478bd9Sstevel@tonic-gate 			mutex_exit(&gid_info->gl_mutex);
3547c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L5("ibdm", "free_iou_info: "
3557c478bd9Sstevel@tonic-gate 			    "ioc_dc_timeout_id = 0x%x", timeout_id);
3567c478bd9Sstevel@tonic-gate 			if (untimeout(timeout_id) == -1) {
3577c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibdm", "free_iou_info: "
3587c478bd9Sstevel@tonic-gate 				    "untimeout ioc_dc_timeout_id failed");
3597c478bd9Sstevel@tonic-gate 				mutex_enter(&gid_info->gl_mutex);
3607c478bd9Sstevel@tonic-gate 				return (-1);
3617c478bd9Sstevel@tonic-gate 			}
3627c478bd9Sstevel@tonic-gate 			mutex_enter(&gid_info->gl_mutex);
3637c478bd9Sstevel@tonic-gate 		}
3647c478bd9Sstevel@tonic-gate 
3657c478bd9Sstevel@tonic-gate 		/* handle the case where serv[k].se_timeout_id is scheduled */
3667c478bd9Sstevel@tonic-gate 		for (k = 0; k < ioc->ioc_profile.ioc_service_entries; k++) {
3677c478bd9Sstevel@tonic-gate 			if (ioc->ioc_serv[k].se_timeout_id) {
3687c478bd9Sstevel@tonic-gate 				timeout_id = ioc->ioc_serv[k].se_timeout_id;
36918edb70cSeota 				ioc->ioc_serv[k].se_timeout_id = 0;
3707c478bd9Sstevel@tonic-gate 				mutex_exit(&gid_info->gl_mutex);
3717c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L5("ibdm", "free_iou_info: "
3727c478bd9Sstevel@tonic-gate 				    "ioc->ioc_serv[%d].se_timeout_id = 0x%x",
3737c478bd9Sstevel@tonic-gate 				    k, timeout_id);
3747c478bd9Sstevel@tonic-gate 				if (untimeout(timeout_id) == -1) {
3757c478bd9Sstevel@tonic-gate 					IBTF_DPRINTF_L2("ibdm", "free_iou_info:"
3767c478bd9Sstevel@tonic-gate 					    " untimeout se_timeout_id failed");
3777c478bd9Sstevel@tonic-gate 					mutex_enter(&gid_info->gl_mutex);
3787c478bd9Sstevel@tonic-gate 					return (-1);
3797c478bd9Sstevel@tonic-gate 				}
3807c478bd9Sstevel@tonic-gate 				mutex_enter(&gid_info->gl_mutex);
3817c478bd9Sstevel@tonic-gate 			}
3827c478bd9Sstevel@tonic-gate 		}
3837c478bd9Sstevel@tonic-gate 
384add2b70bSpramodbg 		/* delete GID list in IOC */
3857c478bd9Sstevel@tonic-gate 		head = ioc->ioc_gid_list;
3867c478bd9Sstevel@tonic-gate 		while (head) {
3877c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibdm", "\tibdm_free_iou_info: "
3887c478bd9Sstevel@tonic-gate 			    "Deleting gid_list struct %p", head);
3897c478bd9Sstevel@tonic-gate 			delete = head;
3907c478bd9Sstevel@tonic-gate 			head = head->gid_next;
3917c478bd9Sstevel@tonic-gate 			kmem_free(delete, sizeof (ibdm_gid_t));
3927c478bd9Sstevel@tonic-gate 		}
3937c478bd9Sstevel@tonic-gate 		ioc->ioc_gid_list = NULL;
3947c478bd9Sstevel@tonic-gate 
3957c478bd9Sstevel@tonic-gate 		/* delete ioc_serv */
3967c478bd9Sstevel@tonic-gate 		size = ioc->ioc_profile.ioc_service_entries *
3977c478bd9Sstevel@tonic-gate 		    sizeof (ibdm_srvents_info_t);
3987c478bd9Sstevel@tonic-gate 		if (ioc->ioc_serv && size) {
3997c478bd9Sstevel@tonic-gate 			kmem_free(ioc->ioc_serv, size);
4007c478bd9Sstevel@tonic-gate 			ioc->ioc_serv = NULL;
4017c478bd9Sstevel@tonic-gate 		}
4027c478bd9Sstevel@tonic-gate 	}
40353c1b7a3Seota 	/*
40453c1b7a3Seota 	 * Clear the IBDM_CISCO_PROBE_DONE flag to get the IO Unit information
40553c1b7a3Seota 	 * via the switch during the probe process.
40653c1b7a3Seota 	 */
40753c1b7a3Seota 	gid_info->gl_flag &= ~IBDM_CISCO_PROBE_DONE;
4087c478bd9Sstevel@tonic-gate 
4097c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tibdm_free_iou_info: deleting IOU & IOC");
4107c478bd9Sstevel@tonic-gate 	size = sizeof (ibdm_iou_info_t) + niocs * sizeof (ibdm_ioc_info_t);
411add2b70bSpramodbg 	kmem_free(gl_iou, size);
412add2b70bSpramodbg 	*ioup = NULL;
4137c478bd9Sstevel@tonic-gate 	return (0);
4147c478bd9Sstevel@tonic-gate }
4157c478bd9Sstevel@tonic-gate 
4167c478bd9Sstevel@tonic-gate 
4177c478bd9Sstevel@tonic-gate /*
4187c478bd9Sstevel@tonic-gate  * ibdm_fini():
4197c478bd9Sstevel@tonic-gate  * 	Un-register with IBTF
4207c478bd9Sstevel@tonic-gate  *	De allocate memory for the GID info
4217c478bd9Sstevel@tonic-gate  */
4227c478bd9Sstevel@tonic-gate static int
ibdm_fini()4237c478bd9Sstevel@tonic-gate ibdm_fini()
4247c478bd9Sstevel@tonic-gate {
4257c478bd9Sstevel@tonic-gate 	int			ii;
4267c478bd9Sstevel@tonic-gate 	ibdm_hca_list_t		*hca_list, *temp;
4277c478bd9Sstevel@tonic-gate 	ibdm_dp_gidinfo_t	*gid_info, *tmp;
4287c478bd9Sstevel@tonic-gate 	ibdm_gid_t		*head, *delete;
4297c478bd9Sstevel@tonic-gate 
4307c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tibdm_fini");
4317c478bd9Sstevel@tonic-gate 
4327c478bd9Sstevel@tonic-gate 	mutex_enter(&ibdm.ibdm_hl_mutex);
4337c478bd9Sstevel@tonic-gate 	if (ibdm.ibdm_state & IBDM_IBT_ATTACHED) {
4347c478bd9Sstevel@tonic-gate 		if (ibt_detach(ibdm.ibdm_ibt_clnt_hdl) != IBT_SUCCESS) {
4357c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibdm", "\t_fini: ibt_detach failed");
4367c478bd9Sstevel@tonic-gate 			mutex_exit(&ibdm.ibdm_hl_mutex);
4377c478bd9Sstevel@tonic-gate 			return (IBDM_FAILURE);
4387c478bd9Sstevel@tonic-gate 		}
4397c478bd9Sstevel@tonic-gate 		ibdm.ibdm_state &= ~IBDM_IBT_ATTACHED;
4407c478bd9Sstevel@tonic-gate 		ibdm.ibdm_ibt_clnt_hdl = NULL;
4417c478bd9Sstevel@tonic-gate 	}
4427c478bd9Sstevel@tonic-gate 
4437c478bd9Sstevel@tonic-gate 	hca_list = ibdm.ibdm_hca_list_head;
4447c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tibdm_fini: nhcas %d", ibdm.ibdm_hca_count);
4457c478bd9Sstevel@tonic-gate 	for (ii = 0; ii < ibdm.ibdm_hca_count; ii++) {
4467c478bd9Sstevel@tonic-gate 		temp = hca_list;
4477c478bd9Sstevel@tonic-gate 		hca_list = hca_list->hl_next;
4487c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibdm", "\tibdm_fini: hca %p", temp);
4497c478bd9Sstevel@tonic-gate 		if (ibdm_uninit_hca(temp) != IBDM_SUCCESS) {
4507c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibdm", "\tibdm_fini: "
4517c478bd9Sstevel@tonic-gate 			    "uninit_hca %p failed", temp);
4527c478bd9Sstevel@tonic-gate 			mutex_exit(&ibdm.ibdm_hl_mutex);
4537c478bd9Sstevel@tonic-gate 			return (IBDM_FAILURE);
4547c478bd9Sstevel@tonic-gate 		}
4557c478bd9Sstevel@tonic-gate 	}
4567c478bd9Sstevel@tonic-gate 	mutex_exit(&ibdm.ibdm_hl_mutex);
4577c478bd9Sstevel@tonic-gate 
4587c478bd9Sstevel@tonic-gate 	mutex_enter(&ibdm.ibdm_mutex);
4597c478bd9Sstevel@tonic-gate 	if (ibdm.ibdm_state & IBDM_HCA_ATTACHED)
4607c478bd9Sstevel@tonic-gate 		ibdm.ibdm_state &= ~IBDM_HCA_ATTACHED;
4617c478bd9Sstevel@tonic-gate 
4627c478bd9Sstevel@tonic-gate 	gid_info = ibdm.ibdm_dp_gidlist_head;
4637c478bd9Sstevel@tonic-gate 	while (gid_info) {
4647c478bd9Sstevel@tonic-gate 		mutex_enter(&gid_info->gl_mutex);
465add2b70bSpramodbg 		(void) ibdm_free_iou_info(gid_info, &gid_info->gl_iou);
4667c478bd9Sstevel@tonic-gate 		mutex_exit(&gid_info->gl_mutex);
4677c478bd9Sstevel@tonic-gate 		ibdm_delete_glhca_list(gid_info);
4687c478bd9Sstevel@tonic-gate 
4697c478bd9Sstevel@tonic-gate 		tmp = gid_info;
4707c478bd9Sstevel@tonic-gate 		gid_info = gid_info->gl_next;
4717c478bd9Sstevel@tonic-gate 		mutex_destroy(&tmp->gl_mutex);
4727c478bd9Sstevel@tonic-gate 		head = tmp->gl_gid;
4737c478bd9Sstevel@tonic-gate 		while (head) {
4747c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibdm",
4757c478bd9Sstevel@tonic-gate 			    "\tibdm_fini: Deleting gid structs");
4767c478bd9Sstevel@tonic-gate 			delete = head;
4777c478bd9Sstevel@tonic-gate 			head = head->gid_next;
4787c478bd9Sstevel@tonic-gate 			kmem_free(delete, sizeof (ibdm_gid_t));
4797c478bd9Sstevel@tonic-gate 		}
4807c478bd9Sstevel@tonic-gate 		kmem_free(tmp, sizeof (ibdm_dp_gidinfo_t));
4817c478bd9Sstevel@tonic-gate 	}
4827c478bd9Sstevel@tonic-gate 	mutex_exit(&ibdm.ibdm_mutex);
4837c478bd9Sstevel@tonic-gate 
4847c478bd9Sstevel@tonic-gate 	if (ibdm.ibdm_state & IBDM_LOCKS_ALLOCED) {
4857c478bd9Sstevel@tonic-gate 		ibdm.ibdm_state &= ~IBDM_LOCKS_ALLOCED;
4867c478bd9Sstevel@tonic-gate 		mutex_destroy(&ibdm.ibdm_mutex);
4877c478bd9Sstevel@tonic-gate 		mutex_destroy(&ibdm.ibdm_hl_mutex);
4887c478bd9Sstevel@tonic-gate 		mutex_destroy(&ibdm.ibdm_ibnex_mutex);
48900a3eaf3SRamaswamy Tummala 		cv_destroy(&ibdm.ibdm_port_settle_cv);
4907c478bd9Sstevel@tonic-gate 	}
4917c478bd9Sstevel@tonic-gate 	if (ibdm.ibdm_state & IBDM_CVS_ALLOCED) {
4927c478bd9Sstevel@tonic-gate 		ibdm.ibdm_state &= ~IBDM_CVS_ALLOCED;
4937c478bd9Sstevel@tonic-gate 		cv_destroy(&ibdm.ibdm_probe_cv);
4947c478bd9Sstevel@tonic-gate 		cv_destroy(&ibdm.ibdm_busy_cv);
4957c478bd9Sstevel@tonic-gate 	}
4967c478bd9Sstevel@tonic-gate 	return (IBDM_SUCCESS);
4977c478bd9Sstevel@tonic-gate }
4987c478bd9Sstevel@tonic-gate 
4997c478bd9Sstevel@tonic-gate 
5007c478bd9Sstevel@tonic-gate /*
5017c478bd9Sstevel@tonic-gate  * ibdm_event_hdlr()
5027c478bd9Sstevel@tonic-gate  *
5037c478bd9Sstevel@tonic-gate  *	IBDM registers  this asynchronous event handler at the time of
5047c478bd9Sstevel@tonic-gate  *	ibt_attach. IBDM support the following async events. For other
5057c478bd9Sstevel@tonic-gate  *	event, simply returns success.
5067c478bd9Sstevel@tonic-gate  *	IBT_HCA_ATTACH_EVENT:
5077c478bd9Sstevel@tonic-gate  *		Retrieves the  information about all the port that are
5087c478bd9Sstevel@tonic-gate  *		present on this HCA,  allocates  the  port  attributes
5097c478bd9Sstevel@tonic-gate  *		structure  and calls IB  nexus  callback  routine with
5107c478bd9Sstevel@tonic-gate  *		the port attributes structure as an input argument.
5117c478bd9Sstevel@tonic-gate  *	IBT_HCA_DETACH_EVENT:
5127c478bd9Sstevel@tonic-gate  *		Retrieves the information about all the ports that are
5137c478bd9Sstevel@tonic-gate  *		present on  this HCA and  calls IB nexus callback with
5147c478bd9Sstevel@tonic-gate  *		port guid as an argument
5157c478bd9Sstevel@tonic-gate  *	IBT_EVENT_PORT_UP:
5167c478bd9Sstevel@tonic-gate  *		Register with IBMF and SA access
5177c478bd9Sstevel@tonic-gate  *		Setup IBMF receive callback routine
5187c478bd9Sstevel@tonic-gate  *	IBT_EVENT_PORT_DOWN:
5197c478bd9Sstevel@tonic-gate  *		Un-Register with IBMF and SA access
5207c478bd9Sstevel@tonic-gate  *		Teardown IBMF receive callback routine
5217c478bd9Sstevel@tonic-gate  */
5227c478bd9Sstevel@tonic-gate /*ARGSUSED*/
5237c478bd9Sstevel@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)5247c478bd9Sstevel@tonic-gate ibdm_event_hdlr(void *clnt_hdl,
5257c478bd9Sstevel@tonic-gate     ibt_hca_hdl_t hca_hdl, ibt_async_code_t code, ibt_async_event_t *event)
5267c478bd9Sstevel@tonic-gate {
5277c478bd9Sstevel@tonic-gate 	ibdm_hca_list_t		*hca_list;
5287c478bd9Sstevel@tonic-gate 	ibdm_port_attr_t	*port;
5297c478bd9Sstevel@tonic-gate 	ibmf_saa_handle_t	port_sa_hdl;
5307c478bd9Sstevel@tonic-gate 
5317c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tevent_hdlr: async code 0x%x", code);
5327c478bd9Sstevel@tonic-gate 
5337c478bd9Sstevel@tonic-gate 	switch (code) {
5347c478bd9Sstevel@tonic-gate 	case IBT_HCA_ATTACH_EVENT:	/* New HCA registered with IBTF */
5357c478bd9Sstevel@tonic-gate 		ibdm_handle_hca_attach(event->ev_hca_guid);
5367c478bd9Sstevel@tonic-gate 		break;
5377c478bd9Sstevel@tonic-gate 
5387c478bd9Sstevel@tonic-gate 	case IBT_HCA_DETACH_EVENT:	/* HCA unregistered with IBTF */
5397c478bd9Sstevel@tonic-gate 		ibdm_handle_hca_detach(event->ev_hca_guid);
5407c478bd9Sstevel@tonic-gate 		mutex_enter(&ibdm.ibdm_ibnex_mutex);
5417c478bd9Sstevel@tonic-gate 		if (ibdm.ibdm_ibnex_callback != NULL) {
5427c478bd9Sstevel@tonic-gate 			(*ibdm.ibdm_ibnex_callback)((void *)
5437c478bd9Sstevel@tonic-gate 			    &event->ev_hca_guid, IBDM_EVENT_HCA_REMOVED);
5447c478bd9Sstevel@tonic-gate 		}
5457c478bd9Sstevel@tonic-gate 		mutex_exit(&ibdm.ibdm_ibnex_mutex);
5467c478bd9Sstevel@tonic-gate 		break;
5477c478bd9Sstevel@tonic-gate 
5487c478bd9Sstevel@tonic-gate 	case IBT_EVENT_PORT_UP:
5497c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibdm", "\tevent_hdlr: PORT_UP");
5507c478bd9Sstevel@tonic-gate 		mutex_enter(&ibdm.ibdm_hl_mutex);
5517c478bd9Sstevel@tonic-gate 		port = ibdm_get_port_attr(event, &hca_list);
5527c478bd9Sstevel@tonic-gate 		if (port == NULL) {
5537c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibdm",
55453c1b7a3Seota 			    "\tevent_hdlr: HCA not present");
5557c478bd9Sstevel@tonic-gate 			mutex_exit(&ibdm.ibdm_hl_mutex);
5567c478bd9Sstevel@tonic-gate 			break;
5577c478bd9Sstevel@tonic-gate 		}
5587c478bd9Sstevel@tonic-gate 		ibdm_initialize_port(port);
5597c478bd9Sstevel@tonic-gate 		hca_list->hl_nports_active++;
56000a3eaf3SRamaswamy Tummala 		cv_broadcast(&ibdm.ibdm_port_settle_cv);
5617c478bd9Sstevel@tonic-gate 		mutex_exit(&ibdm.ibdm_hl_mutex);
562dcf1eb70SSudhakar Dindukurti 
563dcf1eb70SSudhakar Dindukurti 		/* Inform IB nexus driver */
564dcf1eb70SSudhakar Dindukurti 		mutex_enter(&ibdm.ibdm_ibnex_mutex);
565dcf1eb70SSudhakar Dindukurti 		if (ibdm.ibdm_ibnex_callback != NULL) {
566dcf1eb70SSudhakar Dindukurti 			(*ibdm.ibdm_ibnex_callback)((void *)
567dcf1eb70SSudhakar Dindukurti 			    &event->ev_hca_guid, IBDM_EVENT_PORT_UP);
568dcf1eb70SSudhakar Dindukurti 		}
569dcf1eb70SSudhakar Dindukurti 		mutex_exit(&ibdm.ibdm_ibnex_mutex);
5707c478bd9Sstevel@tonic-gate 		break;
5717c478bd9Sstevel@tonic-gate 
5727c478bd9Sstevel@tonic-gate 	case IBT_ERROR_PORT_DOWN:
5737c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibdm", "\tevent_hdlr: PORT_DOWN");
5747c478bd9Sstevel@tonic-gate 		mutex_enter(&ibdm.ibdm_hl_mutex);
5757c478bd9Sstevel@tonic-gate 		port = ibdm_get_port_attr(event, &hca_list);
5767c478bd9Sstevel@tonic-gate 		if (port == NULL) {
5777c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibdm",
57853c1b7a3Seota 			    "\tevent_hdlr: HCA not present");
5797c478bd9Sstevel@tonic-gate 			mutex_exit(&ibdm.ibdm_hl_mutex);
5807c478bd9Sstevel@tonic-gate 			break;
5817c478bd9Sstevel@tonic-gate 		}
5827c478bd9Sstevel@tonic-gate 		hca_list->hl_nports_active--;
5837c478bd9Sstevel@tonic-gate 		port_sa_hdl = port->pa_sa_hdl;
5847c478bd9Sstevel@tonic-gate 		(void) ibdm_fini_port(port);
585a1e3386eShiremath 		port->pa_state = IBT_PORT_DOWN;
58600a3eaf3SRamaswamy Tummala 		cv_broadcast(&ibdm.ibdm_port_settle_cv);
5877c478bd9Sstevel@tonic-gate 		mutex_exit(&ibdm.ibdm_hl_mutex);
5887c478bd9Sstevel@tonic-gate 		ibdm_reset_all_dgids(port_sa_hdl);
5897c478bd9Sstevel@tonic-gate 		break;
5907c478bd9Sstevel@tonic-gate 
59176c04273SRajkumar Sivaprakasam 	case IBT_PORT_CHANGE_EVENT:
59276c04273SRajkumar Sivaprakasam 		IBTF_DPRINTF_L4("ibdm", "\tevent_hdlr: PORT_CHANGE");
593dcf1eb70SSudhakar Dindukurti 		if (event->ev_port_flags & IBT_PORT_CHANGE_PKEY)
594dcf1eb70SSudhakar Dindukurti 			ibdm_handle_port_change_event(event);
59576c04273SRajkumar Sivaprakasam 		break;
59676c04273SRajkumar Sivaprakasam 
5977c478bd9Sstevel@tonic-gate 	default:		/* Ignore all other events/errors */
5987c478bd9Sstevel@tonic-gate 		break;
5997c478bd9Sstevel@tonic-gate 	}
6007c478bd9Sstevel@tonic-gate }
6017c478bd9Sstevel@tonic-gate 
602dcf1eb70SSudhakar Dindukurti static void
ibdm_handle_port_change_event(ibt_async_event_t * event)603dcf1eb70SSudhakar Dindukurti ibdm_handle_port_change_event(ibt_async_event_t *event)
604dcf1eb70SSudhakar Dindukurti {
605dcf1eb70SSudhakar Dindukurti 	ibdm_port_attr_t	*port;
606dcf1eb70SSudhakar Dindukurti 	ibdm_hca_list_t		*hca_list;
607dcf1eb70SSudhakar Dindukurti 
608dcf1eb70SSudhakar Dindukurti 	IBTF_DPRINTF_L2("ibdm", "\tibdm_handle_port_change_event:"
609dcf1eb70SSudhakar Dindukurti 	    " HCA guid  %llx", event->ev_hca_guid);
610dcf1eb70SSudhakar Dindukurti 	mutex_enter(&ibdm.ibdm_hl_mutex);
611dcf1eb70SSudhakar Dindukurti 	port = ibdm_get_port_attr(event, &hca_list);
612dcf1eb70SSudhakar Dindukurti 	if (port == NULL) {
613dcf1eb70SSudhakar Dindukurti 		IBTF_DPRINTF_L2("ibdm", "\tevent_hdlr: HCA not present");
614dcf1eb70SSudhakar Dindukurti 		mutex_exit(&ibdm.ibdm_hl_mutex);
615dcf1eb70SSudhakar Dindukurti 		return;
616dcf1eb70SSudhakar Dindukurti 	}
617dcf1eb70SSudhakar Dindukurti 	ibdm_update_port_pkeys(port);
618dcf1eb70SSudhakar Dindukurti 	cv_broadcast(&ibdm.ibdm_port_settle_cv);
619dcf1eb70SSudhakar Dindukurti 	mutex_exit(&ibdm.ibdm_hl_mutex);
620dcf1eb70SSudhakar Dindukurti 
621dcf1eb70SSudhakar Dindukurti 	/* Inform IB nexus driver */
622dcf1eb70SSudhakar Dindukurti 	mutex_enter(&ibdm.ibdm_ibnex_mutex);
623dcf1eb70SSudhakar Dindukurti 	if (ibdm.ibdm_ibnex_callback != NULL) {
624dcf1eb70SSudhakar Dindukurti 		(*ibdm.ibdm_ibnex_callback)((void *)
625dcf1eb70SSudhakar Dindukurti 		    &event->ev_hca_guid, IBDM_EVENT_PORT_PKEY_CHANGE);
626dcf1eb70SSudhakar Dindukurti 	}
627dcf1eb70SSudhakar Dindukurti 	mutex_exit(&ibdm.ibdm_ibnex_mutex);
628dcf1eb70SSudhakar Dindukurti }
6297c478bd9Sstevel@tonic-gate 
63076c04273SRajkumar Sivaprakasam /*
63176c04273SRajkumar Sivaprakasam  * ibdm_update_port_pkeys()
63276c04273SRajkumar Sivaprakasam  *	Update the pkey table
63376c04273SRajkumar Sivaprakasam  *	Update the port attributes
63476c04273SRajkumar Sivaprakasam  */
63576c04273SRajkumar Sivaprakasam static void
ibdm_update_port_pkeys(ibdm_port_attr_t * port)63676c04273SRajkumar Sivaprakasam ibdm_update_port_pkeys(ibdm_port_attr_t *port)
63776c04273SRajkumar Sivaprakasam {
63876c04273SRajkumar Sivaprakasam 	uint_t				nports, size;
63976c04273SRajkumar Sivaprakasam 	uint_t				pkey_idx, opkey_idx;
64076c04273SRajkumar Sivaprakasam 	uint16_t			npkeys;
64176c04273SRajkumar Sivaprakasam 	ibt_hca_portinfo_t		*pinfop;
64276c04273SRajkumar Sivaprakasam 	ib_pkey_t			pkey;
64376c04273SRajkumar Sivaprakasam 	ibdm_pkey_tbl_t			*pkey_tbl;
64476c04273SRajkumar Sivaprakasam 	ibdm_port_attr_t		newport;
64576c04273SRajkumar Sivaprakasam 
64676c04273SRajkumar Sivaprakasam 	IBTF_DPRINTF_L4("ibdm", "\tupdate_port_pkeys:");
64776c04273SRajkumar Sivaprakasam 	ASSERT(MUTEX_HELD(&ibdm.ibdm_hl_mutex));
64876c04273SRajkumar Sivaprakasam 
64976c04273SRajkumar Sivaprakasam 	/* Check whether the port is active */
65076c04273SRajkumar Sivaprakasam 	if (ibt_get_port_state(port->pa_hca_hdl, port->pa_port_num, NULL,
65176c04273SRajkumar Sivaprakasam 	    NULL) != IBT_SUCCESS)
65276c04273SRajkumar Sivaprakasam 		return;
65376c04273SRajkumar Sivaprakasam 
65476c04273SRajkumar Sivaprakasam 	if (ibt_query_hca_ports(port->pa_hca_hdl, port->pa_port_num,
65576c04273SRajkumar Sivaprakasam 	    &pinfop, &nports, &size) != IBT_SUCCESS) {
65676c04273SRajkumar Sivaprakasam 		/* This should not occur */
65776c04273SRajkumar Sivaprakasam 		port->pa_npkeys = 0;
65876c04273SRajkumar Sivaprakasam 		port->pa_pkey_tbl = NULL;
65976c04273SRajkumar Sivaprakasam 		return;
66076c04273SRajkumar Sivaprakasam 	}
66176c04273SRajkumar Sivaprakasam 
66276c04273SRajkumar Sivaprakasam 	npkeys = pinfop->p_pkey_tbl_sz;
66376c04273SRajkumar Sivaprakasam 	pkey_tbl = kmem_zalloc(npkeys * sizeof (ibdm_pkey_tbl_t), KM_SLEEP);
66476c04273SRajkumar Sivaprakasam 	newport.pa_pkey_tbl = pkey_tbl;
66576c04273SRajkumar Sivaprakasam 	newport.pa_ibmf_hdl = port->pa_ibmf_hdl;
66676c04273SRajkumar Sivaprakasam 
66776c04273SRajkumar Sivaprakasam 	for (pkey_idx = 0; pkey_idx < npkeys; pkey_idx++) {
66876c04273SRajkumar Sivaprakasam 		pkey = pkey_tbl[pkey_idx].pt_pkey =
66976c04273SRajkumar Sivaprakasam 		    pinfop->p_pkey_tbl[pkey_idx];
67076c04273SRajkumar Sivaprakasam 		/*
67176c04273SRajkumar Sivaprakasam 		 * Is this pkey present in the current table ?
67276c04273SRajkumar Sivaprakasam 		 */
67376c04273SRajkumar Sivaprakasam 		for (opkey_idx = 0; opkey_idx < port->pa_npkeys; opkey_idx++) {
67476c04273SRajkumar Sivaprakasam 			if (pkey == port->pa_pkey_tbl[opkey_idx].pt_pkey) {
67576c04273SRajkumar Sivaprakasam 				pkey_tbl[pkey_idx].pt_qp_hdl =
67676c04273SRajkumar Sivaprakasam 				    port->pa_pkey_tbl[opkey_idx].pt_qp_hdl;
67776c04273SRajkumar Sivaprakasam 				port->pa_pkey_tbl[opkey_idx].pt_qp_hdl = NULL;
67876c04273SRajkumar Sivaprakasam 				break;
67976c04273SRajkumar Sivaprakasam 			}
68076c04273SRajkumar Sivaprakasam 		}
68176c04273SRajkumar Sivaprakasam 
68276c04273SRajkumar Sivaprakasam 		if (opkey_idx == port->pa_npkeys) {
68376c04273SRajkumar Sivaprakasam 			pkey = pkey_tbl[pkey_idx].pt_pkey;
68476c04273SRajkumar Sivaprakasam 			if (IBDM_INVALID_PKEY(pkey)) {
68576c04273SRajkumar Sivaprakasam 				pkey_tbl[pkey_idx].pt_qp_hdl = NULL;
68676c04273SRajkumar Sivaprakasam 				continue;
68776c04273SRajkumar Sivaprakasam 			}
68876c04273SRajkumar Sivaprakasam 			ibdm_port_attr_ibmf_init(&newport, pkey, pkey_idx);
68976c04273SRajkumar Sivaprakasam 		}
69076c04273SRajkumar Sivaprakasam 	}
69176c04273SRajkumar Sivaprakasam 
69276c04273SRajkumar Sivaprakasam 	for (opkey_idx = 0; opkey_idx < port->pa_npkeys; opkey_idx++) {
69376c04273SRajkumar Sivaprakasam 		if (port->pa_pkey_tbl[opkey_idx].pt_qp_hdl != NULL) {
69476c04273SRajkumar Sivaprakasam 			if (ibdm_port_attr_ibmf_fini(port, opkey_idx) !=
69576c04273SRajkumar Sivaprakasam 			    IBDM_SUCCESS) {
69676c04273SRajkumar Sivaprakasam 				IBTF_DPRINTF_L2("ibdm", "\tupdate_port_pkeys: "
69776c04273SRajkumar Sivaprakasam 				    "ibdm_port_attr_ibmf_fini failed for "
69876c04273SRajkumar Sivaprakasam 				    "port pkey 0x%x",
69976c04273SRajkumar Sivaprakasam 				    port->pa_pkey_tbl[opkey_idx].pt_pkey);
70076c04273SRajkumar Sivaprakasam 			}
70176c04273SRajkumar Sivaprakasam 		}
70276c04273SRajkumar Sivaprakasam 	}
70376c04273SRajkumar Sivaprakasam 
70476c04273SRajkumar Sivaprakasam 	if (port->pa_pkey_tbl != NULL) {
70576c04273SRajkumar Sivaprakasam 		kmem_free(port->pa_pkey_tbl,
70676c04273SRajkumar Sivaprakasam 		    port->pa_npkeys * sizeof (ibdm_pkey_tbl_t));
70776c04273SRajkumar Sivaprakasam 	}
70876c04273SRajkumar Sivaprakasam 
70976c04273SRajkumar Sivaprakasam 	port->pa_npkeys = npkeys;
71076c04273SRajkumar Sivaprakasam 	port->pa_pkey_tbl = pkey_tbl;
71176c04273SRajkumar Sivaprakasam 	port->pa_sn_prefix = pinfop->p_sgid_tbl[0].gid_prefix;
71276c04273SRajkumar Sivaprakasam 	port->pa_state = pinfop->p_linkstate;
71376c04273SRajkumar Sivaprakasam 	ibt_free_portinfo(pinfop, size);
71476c04273SRajkumar Sivaprakasam }
71576c04273SRajkumar Sivaprakasam 
7167c478bd9Sstevel@tonic-gate /*
7177c478bd9Sstevel@tonic-gate  * ibdm_initialize_port()
7187c478bd9Sstevel@tonic-gate  *	Register with IBMF
7197c478bd9Sstevel@tonic-gate  *	Register with SA access
7207c478bd9Sstevel@tonic-gate  *	Register a receive callback routine with IBMF. IBMF invokes
7217c478bd9Sstevel@tonic-gate  *	this routine whenever a MAD arrives at this port.
7227c478bd9Sstevel@tonic-gate  *	Update the port attributes
7237c478bd9Sstevel@tonic-gate  */
7247c478bd9Sstevel@tonic-gate static void
ibdm_initialize_port(ibdm_port_attr_t * port)7257c478bd9Sstevel@tonic-gate ibdm_initialize_port(ibdm_port_attr_t *port)
7267c478bd9Sstevel@tonic-gate {
7277c478bd9Sstevel@tonic-gate 	int				ii;
7287c478bd9Sstevel@tonic-gate 	uint_t				nports, size;
7297c478bd9Sstevel@tonic-gate 	uint_t				pkey_idx;
7307c478bd9Sstevel@tonic-gate 	ib_pkey_t			pkey;
7317c478bd9Sstevel@tonic-gate 	ibt_hca_portinfo_t		*pinfop;
7327c478bd9Sstevel@tonic-gate 	ibmf_register_info_t		ibmf_reg;
7337c478bd9Sstevel@tonic-gate 	ibmf_saa_subnet_event_args_t	event_args;
7347c478bd9Sstevel@tonic-gate 
7357c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tinitialize_port:");
7367c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ibdm.ibdm_hl_mutex));
7377c478bd9Sstevel@tonic-gate 
7387c478bd9Sstevel@tonic-gate 	/* Check whether the port is active */
7397c478bd9Sstevel@tonic-gate 	if (ibt_get_port_state(port->pa_hca_hdl, port->pa_port_num, NULL,
7407c478bd9Sstevel@tonic-gate 	    NULL) != IBT_SUCCESS)
7417c478bd9Sstevel@tonic-gate 		return;
7427c478bd9Sstevel@tonic-gate 
743c44ec8d2SRamaswamy Tummala 	if (port->pa_sa_hdl != NULL || port->pa_pkey_tbl != NULL)
7447c478bd9Sstevel@tonic-gate 		return;
7457c478bd9Sstevel@tonic-gate 
7467c478bd9Sstevel@tonic-gate 	if (ibt_query_hca_ports(port->pa_hca_hdl, port->pa_port_num,
7477c478bd9Sstevel@tonic-gate 	    &pinfop, &nports, &size) != IBT_SUCCESS) {
7487c478bd9Sstevel@tonic-gate 		/* This should not occur */
7497c478bd9Sstevel@tonic-gate 		port->pa_npkeys		= 0;
7507c478bd9Sstevel@tonic-gate 		port->pa_pkey_tbl	= NULL;
7517c478bd9Sstevel@tonic-gate 		return;
7527c478bd9Sstevel@tonic-gate 	}
7537c478bd9Sstevel@tonic-gate 	port->pa_sn_prefix = pinfop->p_sgid_tbl[0].gid_prefix;
7547c478bd9Sstevel@tonic-gate 
7557c478bd9Sstevel@tonic-gate 	port->pa_state		= pinfop->p_linkstate;
7567c478bd9Sstevel@tonic-gate 	port->pa_npkeys		= pinfop->p_pkey_tbl_sz;
7577c478bd9Sstevel@tonic-gate 	port->pa_pkey_tbl	= (ibdm_pkey_tbl_t *)kmem_zalloc(
7587c478bd9Sstevel@tonic-gate 	    port->pa_npkeys * sizeof (ibdm_pkey_tbl_t), KM_SLEEP);
7597c478bd9Sstevel@tonic-gate 
7607c478bd9Sstevel@tonic-gate 	for (pkey_idx = 0; pkey_idx < port->pa_npkeys; pkey_idx++)
7617c478bd9Sstevel@tonic-gate 		port->pa_pkey_tbl[pkey_idx].pt_pkey =
7627c478bd9Sstevel@tonic-gate 		    pinfop->p_pkey_tbl[pkey_idx];
7637c478bd9Sstevel@tonic-gate 
7647c478bd9Sstevel@tonic-gate 	ibt_free_portinfo(pinfop, size);
7657c478bd9Sstevel@tonic-gate 
766c44ec8d2SRamaswamy Tummala 	if (ibdm_enumerate_iocs) {
767c44ec8d2SRamaswamy Tummala 		event_args.is_event_callback = ibdm_saa_event_cb;
768c44ec8d2SRamaswamy Tummala 		event_args.is_event_callback_arg = port;
769c44ec8d2SRamaswamy Tummala 		if (ibmf_sa_session_open(port->pa_port_guid, 0, &event_args,
770c44ec8d2SRamaswamy Tummala 		    IBMF_VERSION, 0, &port->pa_sa_hdl) != IBMF_SUCCESS) {
771c44ec8d2SRamaswamy Tummala 			IBTF_DPRINTF_L2("ibdm", "\tinitialize_port: "
772c44ec8d2SRamaswamy Tummala 			    "sa access registration failed");
773c44ec8d2SRamaswamy Tummala 			(void) ibdm_fini_port(port);
774c44ec8d2SRamaswamy Tummala 			return;
775c44ec8d2SRamaswamy Tummala 		}
7767c478bd9Sstevel@tonic-gate 
777c44ec8d2SRamaswamy Tummala 		ibmf_reg.ir_ci_guid		= port->pa_hca_guid;
778c44ec8d2SRamaswamy Tummala 		ibmf_reg.ir_port_num		= port->pa_port_num;
779c44ec8d2SRamaswamy Tummala 		ibmf_reg.ir_client_class	= DEV_MGT_MANAGER;
780c44ec8d2SRamaswamy Tummala 
781c44ec8d2SRamaswamy Tummala 		if (ibmf_register(&ibmf_reg, IBMF_VERSION, 0, NULL, NULL,
782c44ec8d2SRamaswamy Tummala 		    &port->pa_ibmf_hdl, &port->pa_ibmf_caps) != IBMF_SUCCESS) {
783c44ec8d2SRamaswamy Tummala 			IBTF_DPRINTF_L2("ibdm", "\tinitialize_port: "
784c44ec8d2SRamaswamy Tummala 			    "IBMF registration failed");
785c44ec8d2SRamaswamy Tummala 			(void) ibdm_fini_port(port);
786c44ec8d2SRamaswamy Tummala 			return;
787c44ec8d2SRamaswamy Tummala 		}
788c44ec8d2SRamaswamy Tummala 
789c44ec8d2SRamaswamy Tummala 		if (ibmf_setup_async_cb(port->pa_ibmf_hdl,
790c44ec8d2SRamaswamy Tummala 		    IBMF_QP_HANDLE_DEFAULT,
791c44ec8d2SRamaswamy Tummala 		    ibdm_ibmf_recv_cb, 0, 0) != IBMF_SUCCESS) {
792c44ec8d2SRamaswamy Tummala 			IBTF_DPRINTF_L2("ibdm", "\tinitialize_port: "
793c44ec8d2SRamaswamy Tummala 			    "IBMF setup recv cb failed");
794c44ec8d2SRamaswamy Tummala 			(void) ibdm_fini_port(port);
795c44ec8d2SRamaswamy Tummala 			return;
796c44ec8d2SRamaswamy Tummala 		}
797c44ec8d2SRamaswamy Tummala 	} else {
798c44ec8d2SRamaswamy Tummala 		port->pa_sa_hdl = NULL;
799c44ec8d2SRamaswamy Tummala 		port->pa_ibmf_hdl = NULL;
8007c478bd9Sstevel@tonic-gate 	}
8017c478bd9Sstevel@tonic-gate 
8027c478bd9Sstevel@tonic-gate 	for (ii = 0; ii < port->pa_npkeys; ii++) {
8037c478bd9Sstevel@tonic-gate 		pkey = port->pa_pkey_tbl[ii].pt_pkey;
8047c478bd9Sstevel@tonic-gate 		if (IBDM_INVALID_PKEY(pkey)) {
8057c478bd9Sstevel@tonic-gate 			port->pa_pkey_tbl[ii].pt_qp_hdl = NULL;
8067c478bd9Sstevel@tonic-gate 			continue;
8077c478bd9Sstevel@tonic-gate 		}
8087c478bd9Sstevel@tonic-gate 		ibdm_port_attr_ibmf_init(port, pkey, ii);
8097c478bd9Sstevel@tonic-gate 	}
8107c478bd9Sstevel@tonic-gate }
8117c478bd9Sstevel@tonic-gate 
8127c478bd9Sstevel@tonic-gate 
8137c478bd9Sstevel@tonic-gate /*
8147c478bd9Sstevel@tonic-gate  * ibdm_port_attr_ibmf_init:
8157c478bd9Sstevel@tonic-gate  *	With IBMF - Alloc QP Handle and Setup Async callback
8167c478bd9Sstevel@tonic-gate  */
8177c478bd9Sstevel@tonic-gate static void
ibdm_port_attr_ibmf_init(ibdm_port_attr_t * port,ib_pkey_t pkey,int ii)8187c478bd9Sstevel@tonic-gate ibdm_port_attr_ibmf_init(ibdm_port_attr_t *port, ib_pkey_t pkey, int ii)
8197c478bd9Sstevel@tonic-gate {
8207c478bd9Sstevel@tonic-gate 	int ret;
8217c478bd9Sstevel@tonic-gate 
822c44ec8d2SRamaswamy Tummala 	if (ibdm_enumerate_iocs == 0) {
823c44ec8d2SRamaswamy Tummala 		port->pa_pkey_tbl[ii].pt_qp_hdl = NULL;
824c44ec8d2SRamaswamy Tummala 		return;
825c44ec8d2SRamaswamy Tummala 	}
826c44ec8d2SRamaswamy Tummala 
8277c478bd9Sstevel@tonic-gate 	if ((ret = ibmf_alloc_qp(port->pa_ibmf_hdl, pkey, IB_GSI_QKEY,
8287c478bd9Sstevel@tonic-gate 	    IBMF_ALT_QP_MAD_NO_RMPP, &port->pa_pkey_tbl[ii].pt_qp_hdl)) !=
8297c478bd9Sstevel@tonic-gate 	    IBMF_SUCCESS) {
8307c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibdm", "\tport_attr_ibmf_init: "
8317c478bd9Sstevel@tonic-gate 		    "IBMF failed to alloc qp %d", ret);
8327c478bd9Sstevel@tonic-gate 		port->pa_pkey_tbl[ii].pt_qp_hdl = NULL;
8337c478bd9Sstevel@tonic-gate 		return;
8347c478bd9Sstevel@tonic-gate 	}
8357c478bd9Sstevel@tonic-gate 
8367c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tport_attr_ibmf_init: QP handle is %p",
8377c478bd9Sstevel@tonic-gate 	    port->pa_ibmf_hdl);
8387c478bd9Sstevel@tonic-gate 
8397c478bd9Sstevel@tonic-gate 	if ((ret = ibmf_setup_async_cb(port->pa_ibmf_hdl,
8407c478bd9Sstevel@tonic-gate 	    port->pa_pkey_tbl[ii].pt_qp_hdl, ibdm_ibmf_recv_cb, 0, 0)) !=
8417c478bd9Sstevel@tonic-gate 	    IBMF_SUCCESS) {
8427c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibdm", "\tport_attr_ibmf_init: "
8437c478bd9Sstevel@tonic-gate 		    "IBMF setup recv cb failed %d", ret);
8447c478bd9Sstevel@tonic-gate 		(void) ibmf_free_qp(port->pa_ibmf_hdl,
8457c478bd9Sstevel@tonic-gate 		    &port->pa_pkey_tbl[ii].pt_qp_hdl, 0);
8467c478bd9Sstevel@tonic-gate 		port->pa_pkey_tbl[ii].pt_qp_hdl = NULL;
8477c478bd9Sstevel@tonic-gate 	}
8487c478bd9Sstevel@tonic-gate }
8497c478bd9Sstevel@tonic-gate 
8507c478bd9Sstevel@tonic-gate 
8517c478bd9Sstevel@tonic-gate /*
8527c478bd9Sstevel@tonic-gate  * ibdm_get_port_attr()
8537c478bd9Sstevel@tonic-gate  *	Get port attributes from HCA guid and port number
8547c478bd9Sstevel@tonic-gate  *	Return pointer to ibdm_port_attr_t on Success
8557c478bd9Sstevel@tonic-gate  *	and NULL on failure
8567c478bd9Sstevel@tonic-gate  */
8577c478bd9Sstevel@tonic-gate static ibdm_port_attr_t *
ibdm_get_port_attr(ibt_async_event_t * event,ibdm_hca_list_t ** retval)8587c478bd9Sstevel@tonic-gate ibdm_get_port_attr(ibt_async_event_t *event, ibdm_hca_list_t **retval)
8597c478bd9Sstevel@tonic-gate {
8607c478bd9Sstevel@tonic-gate 	ibdm_hca_list_t		*hca_list;
8617c478bd9Sstevel@tonic-gate 	ibdm_port_attr_t	*port_attr;
8627c478bd9Sstevel@tonic-gate 	int			ii;
8637c478bd9Sstevel@tonic-gate 
8647c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tget_port_attr: port# %d", event->ev_port);
8657c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ibdm.ibdm_hl_mutex));
8667c478bd9Sstevel@tonic-gate 	hca_list = ibdm.ibdm_hca_list_head;
8677c478bd9Sstevel@tonic-gate 	while (hca_list) {
8687c478bd9Sstevel@tonic-gate 		if (hca_list->hl_hca_guid == event->ev_hca_guid) {
8697c478bd9Sstevel@tonic-gate 			for (ii = 0; ii < hca_list->hl_nports; ii++) {
8707c478bd9Sstevel@tonic-gate 				port_attr = &hca_list->hl_port_attr[ii];
8717c478bd9Sstevel@tonic-gate 				if (port_attr->pa_port_num == event->ev_port) {
8727c478bd9Sstevel@tonic-gate 					*retval = hca_list;
8737c478bd9Sstevel@tonic-gate 					return (port_attr);
8747c478bd9Sstevel@tonic-gate 				}
8757c478bd9Sstevel@tonic-gate 			}
8767c478bd9Sstevel@tonic-gate 		}
8777c478bd9Sstevel@tonic-gate 		hca_list = hca_list->hl_next;
8787c478bd9Sstevel@tonic-gate 	}
8797c478bd9Sstevel@tonic-gate 	return (NULL);
8807c478bd9Sstevel@tonic-gate }
8817c478bd9Sstevel@tonic-gate 
8827c478bd9Sstevel@tonic-gate 
8837c478bd9Sstevel@tonic-gate /*
8847c478bd9Sstevel@tonic-gate  * ibdm_update_port_attr()
8857c478bd9Sstevel@tonic-gate  *	Update the port attributes
8867c478bd9Sstevel@tonic-gate  */
8877c478bd9Sstevel@tonic-gate static void
ibdm_update_port_attr(ibdm_port_attr_t * port)8887c478bd9Sstevel@tonic-gate ibdm_update_port_attr(ibdm_port_attr_t *port)
8897c478bd9Sstevel@tonic-gate {
8907c478bd9Sstevel@tonic-gate 	uint_t			nports, size;
8917c478bd9Sstevel@tonic-gate 	uint_t			pkey_idx;
8927c478bd9Sstevel@tonic-gate 	ibt_hca_portinfo_t	*portinfop;
8937c478bd9Sstevel@tonic-gate 
8947c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tupdate_port_attr: Begin");
8957c478bd9Sstevel@tonic-gate 	if (ibt_query_hca_ports(port->pa_hca_hdl,
8967c478bd9Sstevel@tonic-gate 	    port->pa_port_num, &portinfop, &nports, &size) != IBT_SUCCESS) {
8977c478bd9Sstevel@tonic-gate 		/* This should not occur */
8987c478bd9Sstevel@tonic-gate 		port->pa_npkeys		= 0;
8997c478bd9Sstevel@tonic-gate 		port->pa_pkey_tbl	= NULL;
9007c478bd9Sstevel@tonic-gate 		return;
9017c478bd9Sstevel@tonic-gate 	}
9027c478bd9Sstevel@tonic-gate 	port->pa_sn_prefix = portinfop->p_sgid_tbl[0].gid_prefix;
9037c478bd9Sstevel@tonic-gate 
9047c478bd9Sstevel@tonic-gate 	port->pa_state		= portinfop->p_linkstate;
9057c478bd9Sstevel@tonic-gate 
9067c478bd9Sstevel@tonic-gate 	/*
9077c478bd9Sstevel@tonic-gate 	 * PKey information in portinfo valid only if port is
9087c478bd9Sstevel@tonic-gate 	 * ACTIVE. Bail out if not.
9097c478bd9Sstevel@tonic-gate 	 */
9107c478bd9Sstevel@tonic-gate 	if (port->pa_state != IBT_PORT_ACTIVE) {
9117c478bd9Sstevel@tonic-gate 		port->pa_npkeys		= 0;
9127c478bd9Sstevel@tonic-gate 		port->pa_pkey_tbl	= NULL;
9137c478bd9Sstevel@tonic-gate 		ibt_free_portinfo(portinfop, size);
9147c478bd9Sstevel@tonic-gate 		return;
9157c478bd9Sstevel@tonic-gate 	}
9167c478bd9Sstevel@tonic-gate 
9177c478bd9Sstevel@tonic-gate 	port->pa_npkeys		= portinfop->p_pkey_tbl_sz;
9187c478bd9Sstevel@tonic-gate 	port->pa_pkey_tbl	= (ibdm_pkey_tbl_t *)kmem_zalloc(
9197c478bd9Sstevel@tonic-gate 	    port->pa_npkeys * sizeof (ibdm_pkey_tbl_t), KM_SLEEP);
9207c478bd9Sstevel@tonic-gate 
9217c478bd9Sstevel@tonic-gate 	for (pkey_idx = 0; pkey_idx < port->pa_npkeys; pkey_idx++) {
9227c478bd9Sstevel@tonic-gate 		port->pa_pkey_tbl[pkey_idx].pt_pkey =
9237c478bd9Sstevel@tonic-gate 		    portinfop->p_pkey_tbl[pkey_idx];
9247c478bd9Sstevel@tonic-gate 	}
9257c478bd9Sstevel@tonic-gate 	ibt_free_portinfo(portinfop, size);
9267c478bd9Sstevel@tonic-gate }
9277c478bd9Sstevel@tonic-gate 
9287c478bd9Sstevel@tonic-gate 
9297c478bd9Sstevel@tonic-gate /*
9307c478bd9Sstevel@tonic-gate  * ibdm_handle_hca_attach()
9317c478bd9Sstevel@tonic-gate  */
9327c478bd9Sstevel@tonic-gate static void
ibdm_handle_hca_attach(ib_guid_t hca_guid)9337c478bd9Sstevel@tonic-gate ibdm_handle_hca_attach(ib_guid_t hca_guid)
9347c478bd9Sstevel@tonic-gate {
9357c478bd9Sstevel@tonic-gate 	uint_t			size;
9367c478bd9Sstevel@tonic-gate 	uint_t			ii, nports;
9377c478bd9Sstevel@tonic-gate 	ibt_status_t		status;
9387c478bd9Sstevel@tonic-gate 	ibt_hca_hdl_t		hca_hdl;
9397c478bd9Sstevel@tonic-gate 	ibt_hca_attr_t		*hca_attr;
9407c478bd9Sstevel@tonic-gate 	ibdm_hca_list_t		*hca_list, *temp;
9417c478bd9Sstevel@tonic-gate 	ibdm_port_attr_t	*port_attr;
9427c478bd9Sstevel@tonic-gate 	ibt_hca_portinfo_t	*portinfop;
9437c478bd9Sstevel@tonic-gate 
9447c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm",
9457c478bd9Sstevel@tonic-gate 	    "\thandle_hca_attach: hca_guid = 0x%llX", hca_guid);
9467c478bd9Sstevel@tonic-gate 
9477c478bd9Sstevel@tonic-gate 	/* open the HCA first */
9487c478bd9Sstevel@tonic-gate 	if ((status = ibt_open_hca(ibdm.ibdm_ibt_clnt_hdl, hca_guid,
9497c478bd9Sstevel@tonic-gate 	    &hca_hdl)) != IBT_SUCCESS) {
9507c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibdm", "\thandle_hca_attach: "
9517c478bd9Sstevel@tonic-gate 		    "open_hca failed, status 0x%x", status);
9527c478bd9Sstevel@tonic-gate 		return;
9537c478bd9Sstevel@tonic-gate 	}
9547c478bd9Sstevel@tonic-gate 
9557c478bd9Sstevel@tonic-gate 	hca_attr = (ibt_hca_attr_t *)
9567c478bd9Sstevel@tonic-gate 	    kmem_alloc(sizeof (ibt_hca_attr_t), KM_SLEEP);
9577c478bd9Sstevel@tonic-gate 	/* ibt_query_hca always returns IBT_SUCCESS */
9587c478bd9Sstevel@tonic-gate 	(void) ibt_query_hca(hca_hdl, hca_attr);
9597c478bd9Sstevel@tonic-gate 
9607c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tvid: 0x%x, pid: 0x%x, ver: 0x%x,"
9617c478bd9Sstevel@tonic-gate 	    " #ports: %d", hca_attr->hca_vendor_id, hca_attr->hca_device_id,
9627c478bd9Sstevel@tonic-gate 	    hca_attr->hca_version_id, hca_attr->hca_nports);
9637c478bd9Sstevel@tonic-gate 
9647c478bd9Sstevel@tonic-gate 	if ((status = ibt_query_hca_ports(hca_hdl, 0, &portinfop, &nports,
9657c478bd9Sstevel@tonic-gate 	    &size)) != IBT_SUCCESS) {
9667c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibdm", "\thandle_hca_attach: "
9677c478bd9Sstevel@tonic-gate 		    "ibt_query_hca_ports failed, status 0x%x", status);
9687c478bd9Sstevel@tonic-gate 		kmem_free(hca_attr, sizeof (ibt_hca_attr_t));
9697c478bd9Sstevel@tonic-gate 		(void) ibt_close_hca(hca_hdl);
9707c478bd9Sstevel@tonic-gate 		return;
9717c478bd9Sstevel@tonic-gate 	}
9727c478bd9Sstevel@tonic-gate 	hca_list = (ibdm_hca_list_t *)
9737c478bd9Sstevel@tonic-gate 	    kmem_zalloc((sizeof (ibdm_hca_list_t)), KM_SLEEP);
9747c478bd9Sstevel@tonic-gate 	hca_list->hl_port_attr = (ibdm_port_attr_t *)kmem_zalloc(
9757c478bd9Sstevel@tonic-gate 	    (sizeof (ibdm_port_attr_t) * hca_attr->hca_nports), KM_SLEEP);
9767c478bd9Sstevel@tonic-gate 	hca_list->hl_hca_guid = hca_attr->hca_node_guid;
9777c478bd9Sstevel@tonic-gate 	hca_list->hl_nports = hca_attr->hca_nports;
978e1d3217bSJosef 'Jeff' Sipek 	hca_list->hl_attach_time = gethrtime();
9797c478bd9Sstevel@tonic-gate 	hca_list->hl_hca_hdl = hca_hdl;
9807c478bd9Sstevel@tonic-gate 
9817c478bd9Sstevel@tonic-gate 	/*
9827c478bd9Sstevel@tonic-gate 	 * Init a dummy port attribute for the HCA node
9837c478bd9Sstevel@tonic-gate 	 * This is for Per-HCA Node. Initialize port_attr :
9847c478bd9Sstevel@tonic-gate 	 * 	hca_guid & port_guid -> hca_guid
9857c478bd9Sstevel@tonic-gate 	 *	npkeys, pkey_tbl is NULL
9867c478bd9Sstevel@tonic-gate 	 *	port_num, sn_prefix is 0
9877c478bd9Sstevel@tonic-gate 	 *	vendorid, product_id, dev_version from HCA
9887c478bd9Sstevel@tonic-gate 	 *	pa_state is IBT_PORT_ACTIVE
9897c478bd9Sstevel@tonic-gate 	 */
9907c478bd9Sstevel@tonic-gate 	hca_list->hl_hca_port_attr = (ibdm_port_attr_t *)kmem_zalloc(
9917c478bd9Sstevel@tonic-gate 	    sizeof (ibdm_port_attr_t), KM_SLEEP);
9927c478bd9Sstevel@tonic-gate 	port_attr = hca_list->hl_hca_port_attr;
9937c478bd9Sstevel@tonic-gate 	port_attr->pa_vendorid  = hca_attr->hca_vendor_id;
9947c478bd9Sstevel@tonic-gate 	port_attr->pa_productid	= hca_attr->hca_device_id;
9957c478bd9Sstevel@tonic-gate 	port_attr->pa_dev_version = hca_attr->hca_version_id;
9967c478bd9Sstevel@tonic-gate 	port_attr->pa_hca_guid	= hca_attr->hca_node_guid;
9977c478bd9Sstevel@tonic-gate 	port_attr->pa_hca_hdl	= hca_list->hl_hca_hdl;
9987c478bd9Sstevel@tonic-gate 	port_attr->pa_port_guid	= hca_attr->hca_node_guid;
9997c478bd9Sstevel@tonic-gate 	port_attr->pa_state	= IBT_PORT_ACTIVE;
10007c478bd9Sstevel@tonic-gate 
10017c478bd9Sstevel@tonic-gate 
10027c478bd9Sstevel@tonic-gate 	for (ii = 0; ii < nports; ii++) {
10037c478bd9Sstevel@tonic-gate 		port_attr		= &hca_list->hl_port_attr[ii];
10047c478bd9Sstevel@tonic-gate 		port_attr->pa_vendorid	= hca_attr->hca_vendor_id;
10057c478bd9Sstevel@tonic-gate 		port_attr->pa_productid	= hca_attr->hca_device_id;
10067c478bd9Sstevel@tonic-gate 		port_attr->pa_dev_version = hca_attr->hca_version_id;
10077c478bd9Sstevel@tonic-gate 		port_attr->pa_hca_guid	= hca_attr->hca_node_guid;
10087c478bd9Sstevel@tonic-gate 		port_attr->pa_hca_hdl	= hca_list->hl_hca_hdl;
10097c478bd9Sstevel@tonic-gate 		port_attr->pa_port_guid	= portinfop[ii].p_sgid_tbl->gid_guid;
10107c478bd9Sstevel@tonic-gate 		port_attr->pa_sn_prefix	= portinfop[ii].p_sgid_tbl->gid_prefix;
10117c478bd9Sstevel@tonic-gate 		port_attr->pa_port_num	= portinfop[ii].p_port_num;
10127c478bd9Sstevel@tonic-gate 		port_attr->pa_state	= portinfop[ii].p_linkstate;
10137c478bd9Sstevel@tonic-gate 
10147c478bd9Sstevel@tonic-gate 		/*
10157c478bd9Sstevel@tonic-gate 		 * Register with IBMF, SA access when the port is in
10167c478bd9Sstevel@tonic-gate 		 * ACTIVE state. Also register a callback routine
10177c478bd9Sstevel@tonic-gate 		 * with IBMF to receive incoming DM MAD's.
10187c478bd9Sstevel@tonic-gate 		 * The IBDM event handler takes care of registration of
10197c478bd9Sstevel@tonic-gate 		 * port which are not active.
10207c478bd9Sstevel@tonic-gate 		 */
10217c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibdm",
10227c478bd9Sstevel@tonic-gate 		    "\thandle_hca_attach: port guid %llx Port state 0x%x",
10237c478bd9Sstevel@tonic-gate 		    port_attr->pa_port_guid, portinfop[ii].p_linkstate);
10247c478bd9Sstevel@tonic-gate 
10257c478bd9Sstevel@tonic-gate 		if (portinfop[ii].p_linkstate == IBT_PORT_ACTIVE) {
10267c478bd9Sstevel@tonic-gate 			mutex_enter(&ibdm.ibdm_hl_mutex);
10277c478bd9Sstevel@tonic-gate 			hca_list->hl_nports_active++;
10287c478bd9Sstevel@tonic-gate 			ibdm_initialize_port(port_attr);
102900a3eaf3SRamaswamy Tummala 			cv_broadcast(&ibdm.ibdm_port_settle_cv);
10307c478bd9Sstevel@tonic-gate 			mutex_exit(&ibdm.ibdm_hl_mutex);
10317c478bd9Sstevel@tonic-gate 		}
10327c478bd9Sstevel@tonic-gate 	}
10337c478bd9Sstevel@tonic-gate 	mutex_enter(&ibdm.ibdm_hl_mutex);
10347c478bd9Sstevel@tonic-gate 	for (temp = ibdm.ibdm_hca_list_head; temp; temp = temp->hl_next) {
10357c478bd9Sstevel@tonic-gate 		if (temp->hl_hca_guid == hca_guid) {
10367c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibdm", "hca_attach: HCA %llX "
10377c478bd9Sstevel@tonic-gate 			    "already seen by IBDM", hca_guid);
10387c478bd9Sstevel@tonic-gate 			mutex_exit(&ibdm.ibdm_hl_mutex);
10397c478bd9Sstevel@tonic-gate 			(void) ibdm_uninit_hca(hca_list);
10407c478bd9Sstevel@tonic-gate 			return;
10417c478bd9Sstevel@tonic-gate 		}
10427c478bd9Sstevel@tonic-gate 	}
10437c478bd9Sstevel@tonic-gate 	ibdm.ibdm_hca_count++;
10447c478bd9Sstevel@tonic-gate 	if (ibdm.ibdm_hca_list_head == NULL) {
10457c478bd9Sstevel@tonic-gate 		ibdm.ibdm_hca_list_head = hca_list;
10467c478bd9Sstevel@tonic-gate 		ibdm.ibdm_hca_list_tail = hca_list;
10477c478bd9Sstevel@tonic-gate 	} else {
10487c478bd9Sstevel@tonic-gate 		ibdm.ibdm_hca_list_tail->hl_next = hca_list;
10497c478bd9Sstevel@tonic-gate 		ibdm.ibdm_hca_list_tail = hca_list;
10507c478bd9Sstevel@tonic-gate 	}
10517c478bd9Sstevel@tonic-gate 	mutex_exit(&ibdm.ibdm_hl_mutex);
10527c478bd9Sstevel@tonic-gate 	mutex_enter(&ibdm.ibdm_ibnex_mutex);
10537c478bd9Sstevel@tonic-gate 	if (ibdm.ibdm_ibnex_callback != NULL) {
10547c478bd9Sstevel@tonic-gate 		(*ibdm.ibdm_ibnex_callback)((void *)
10557c478bd9Sstevel@tonic-gate 		    &hca_guid, IBDM_EVENT_HCA_ADDED);
10567c478bd9Sstevel@tonic-gate 	}
10577c478bd9Sstevel@tonic-gate 	mutex_exit(&ibdm.ibdm_ibnex_mutex);
10587c478bd9Sstevel@tonic-gate 
10597c478bd9Sstevel@tonic-gate 	kmem_free(hca_attr, sizeof (ibt_hca_attr_t));
10607c478bd9Sstevel@tonic-gate 	ibt_free_portinfo(portinfop, size);
10617c478bd9Sstevel@tonic-gate }
10627c478bd9Sstevel@tonic-gate 
10637c478bd9Sstevel@tonic-gate 
10647c478bd9Sstevel@tonic-gate /*
10657c478bd9Sstevel@tonic-gate  * ibdm_handle_hca_detach()
10667c478bd9Sstevel@tonic-gate  */
10677c478bd9Sstevel@tonic-gate static void
ibdm_handle_hca_detach(ib_guid_t hca_guid)10687c478bd9Sstevel@tonic-gate ibdm_handle_hca_detach(ib_guid_t hca_guid)
10697c478bd9Sstevel@tonic-gate {
10707c478bd9Sstevel@tonic-gate 	ibdm_hca_list_t		*head, *prev = NULL;
10714f1d42a6Spramodbg 	size_t			len;
1072e4ac07a3Shiremath 	ibdm_dp_gidinfo_t	*gidinfo;
10738d61a337SJustin Frank 	ibdm_port_attr_t	*port_attr;
10748d61a337SJustin Frank 	int			i;
10757c478bd9Sstevel@tonic-gate 
10767c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm",
10777c478bd9Sstevel@tonic-gate 	    "\thandle_hca_detach: hca_guid = 0x%llx", hca_guid);
10787c478bd9Sstevel@tonic-gate 
10797c478bd9Sstevel@tonic-gate 	/* Make sure no probes are running */
10807c478bd9Sstevel@tonic-gate 	mutex_enter(&ibdm.ibdm_mutex);
10817c478bd9Sstevel@tonic-gate 	while (ibdm.ibdm_busy & IBDM_BUSY)
10827c478bd9Sstevel@tonic-gate 		cv_wait(&ibdm.ibdm_busy_cv, &ibdm.ibdm_mutex);
10837c478bd9Sstevel@tonic-gate 	ibdm.ibdm_busy |= IBDM_BUSY;
10847c478bd9Sstevel@tonic-gate 	mutex_exit(&ibdm.ibdm_mutex);
10857c478bd9Sstevel@tonic-gate 
10867c478bd9Sstevel@tonic-gate 	mutex_enter(&ibdm.ibdm_hl_mutex);
10877c478bd9Sstevel@tonic-gate 	head = ibdm.ibdm_hca_list_head;
10887c478bd9Sstevel@tonic-gate 	while (head) {
10897c478bd9Sstevel@tonic-gate 		if (head->hl_hca_guid == hca_guid) {
10907c478bd9Sstevel@tonic-gate 			if (prev == NULL)
10917c478bd9Sstevel@tonic-gate 				ibdm.ibdm_hca_list_head = head->hl_next;
10927c478bd9Sstevel@tonic-gate 			else
10937c478bd9Sstevel@tonic-gate 				prev->hl_next = head->hl_next;
109400a3eaf3SRamaswamy Tummala 			if (ibdm.ibdm_hca_list_tail == head)
109500a3eaf3SRamaswamy Tummala 				ibdm.ibdm_hca_list_tail = prev;
10967c478bd9Sstevel@tonic-gate 			ibdm.ibdm_hca_count--;
10977c478bd9Sstevel@tonic-gate 			break;
10987c478bd9Sstevel@tonic-gate 		}
10997c478bd9Sstevel@tonic-gate 		prev = head;
11007c478bd9Sstevel@tonic-gate 		head = head->hl_next;
11017c478bd9Sstevel@tonic-gate 	}
11027c478bd9Sstevel@tonic-gate 	mutex_exit(&ibdm.ibdm_hl_mutex);
11037c478bd9Sstevel@tonic-gate 	if (ibdm_uninit_hca(head) != IBDM_SUCCESS)
11047c478bd9Sstevel@tonic-gate 		(void) ibdm_handle_hca_attach(hca_guid);
11057c478bd9Sstevel@tonic-gate 
1106c44ec8d2SRamaswamy Tummala #ifdef DEBUG
1107c44ec8d2SRamaswamy Tummala 	if (ibdm_enumerate_iocs == 0) {
1108c44ec8d2SRamaswamy Tummala 		ASSERT(ibdm.ibdm_dp_gidlist_head == NULL);
1109c44ec8d2SRamaswamy Tummala 	}
1110c44ec8d2SRamaswamy Tummala #endif
1111c44ec8d2SRamaswamy Tummala 
1112e4ac07a3Shiremath 	/*
1113e4ac07a3Shiremath 	 * Now clean up the HCA lists in the gidlist.
1114e4ac07a3Shiremath 	 */
1115e4ac07a3Shiremath 	for (gidinfo = ibdm.ibdm_dp_gidlist_head; gidinfo; gidinfo =
1116e4ac07a3Shiremath 	    gidinfo->gl_next) {
1117e4ac07a3Shiremath 		prev = NULL;
1118e4ac07a3Shiremath 		head = gidinfo->gl_hca_list;
1119e4ac07a3Shiremath 		while (head) {
1120e4ac07a3Shiremath 			if (head->hl_hca_guid == hca_guid) {
1121e4ac07a3Shiremath 				if (prev == NULL)
1122e4ac07a3Shiremath 					gidinfo->gl_hca_list =
1123e4ac07a3Shiremath 					    head->hl_next;
1124e4ac07a3Shiremath 				else
1125e4ac07a3Shiremath 					prev->hl_next = head->hl_next;
11268d61a337SJustin Frank 				for (i = 0; i < head->hl_nports; i++) {
11278d61a337SJustin Frank 					port_attr = &head->hl_port_attr[i];
11288d61a337SJustin Frank 					if (port_attr->pa_pkey_tbl != NULL)
11298d61a337SJustin Frank 						kmem_free(
11308d61a337SJustin Frank 						    port_attr->pa_pkey_tbl,
11318d61a337SJustin Frank 						    port_attr->pa_npkeys *
11328d61a337SJustin Frank 						    sizeof (ibdm_pkey_tbl_t));
11338d61a337SJustin Frank 				}
11344f1d42a6Spramodbg 				len = sizeof (ibdm_hca_list_t) +
11354f1d42a6Spramodbg 				    (head->hl_nports *
11364f1d42a6Spramodbg 				    sizeof (ibdm_port_attr_t));
11374f1d42a6Spramodbg 				kmem_free(head, len);
11384f1d42a6Spramodbg 
1139e4ac07a3Shiremath 				break;
1140e4ac07a3Shiremath 			}
1141e4ac07a3Shiremath 			prev = head;
1142e4ac07a3Shiremath 			head = head->hl_next;
1143e4ac07a3Shiremath 		}
1144e4ac07a3Shiremath 	}
1145e4ac07a3Shiremath 
11467c478bd9Sstevel@tonic-gate 	mutex_enter(&ibdm.ibdm_mutex);
11477c478bd9Sstevel@tonic-gate 	ibdm.ibdm_busy &= ~IBDM_BUSY;
11487c478bd9Sstevel@tonic-gate 	cv_broadcast(&ibdm.ibdm_busy_cv);
11497c478bd9Sstevel@tonic-gate 	mutex_exit(&ibdm.ibdm_mutex);
11507c478bd9Sstevel@tonic-gate }
11517c478bd9Sstevel@tonic-gate 
11527c478bd9Sstevel@tonic-gate 
11537c478bd9Sstevel@tonic-gate static int
ibdm_uninit_hca(ibdm_hca_list_t * head)11547c478bd9Sstevel@tonic-gate ibdm_uninit_hca(ibdm_hca_list_t *head)
11557c478bd9Sstevel@tonic-gate {
11567c478bd9Sstevel@tonic-gate 	int			ii;
11577c478bd9Sstevel@tonic-gate 	ibdm_port_attr_t	*port_attr;
11587c478bd9Sstevel@tonic-gate 
11597c478bd9Sstevel@tonic-gate 	for (ii = 0; ii < head->hl_nports; ii++) {
11607c478bd9Sstevel@tonic-gate 		port_attr = &head->hl_port_attr[ii];
11617c478bd9Sstevel@tonic-gate 		if (ibdm_fini_port(port_attr) != IBDM_SUCCESS) {
11627c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibdm", "uninit_hca: HCA %p port 0x%x "
11637c478bd9Sstevel@tonic-gate 			    "ibdm_fini_port() failed", head, ii);
11647c478bd9Sstevel@tonic-gate 			return (IBDM_FAILURE);
11657c478bd9Sstevel@tonic-gate 		}
11667c478bd9Sstevel@tonic-gate 	}
11677c478bd9Sstevel@tonic-gate 	if (head->hl_hca_hdl)
1168dcf1eb70SSudhakar Dindukurti 		if (ibt_close_hca(head->hl_hca_hdl) != IBT_SUCCESS) {
1169dcf1eb70SSudhakar Dindukurti 			IBTF_DPRINTF_L2("ibdm", "uninit_hca: "
1170dcf1eb70SSudhakar Dindukurti 			    "ibt_close_hca() failed");
11717c478bd9Sstevel@tonic-gate 			return (IBDM_FAILURE);
1172dcf1eb70SSudhakar Dindukurti 		}
11737c478bd9Sstevel@tonic-gate 	kmem_free(head->hl_port_attr,
11747c478bd9Sstevel@tonic-gate 	    head->hl_nports * sizeof (ibdm_port_attr_t));
11757c478bd9Sstevel@tonic-gate 	kmem_free(head->hl_hca_port_attr, sizeof (ibdm_port_attr_t));
11767c478bd9Sstevel@tonic-gate 	kmem_free(head, sizeof (ibdm_hca_list_t));
11777c478bd9Sstevel@tonic-gate 	return (IBDM_SUCCESS);
11787c478bd9Sstevel@tonic-gate }
11797c478bd9Sstevel@tonic-gate 
11807c478bd9Sstevel@tonic-gate 
11817c478bd9Sstevel@tonic-gate /*
11827c478bd9Sstevel@tonic-gate  * For each port on the HCA,
11837c478bd9Sstevel@tonic-gate  *	1) Teardown IBMF receive callback function
11847c478bd9Sstevel@tonic-gate  *	2) Unregister with IBMF
11857c478bd9Sstevel@tonic-gate  *	3) Unregister with SA access
11867c478bd9Sstevel@tonic-gate  */
11877c478bd9Sstevel@tonic-gate static int
ibdm_fini_port(ibdm_port_attr_t * port_attr)11887c478bd9Sstevel@tonic-gate ibdm_fini_port(ibdm_port_attr_t *port_attr)
11897c478bd9Sstevel@tonic-gate {
11907c478bd9Sstevel@tonic-gate 	int	ii, ibmf_status;
11917c478bd9Sstevel@tonic-gate 
11927c478bd9Sstevel@tonic-gate 	for (ii = 0; ii < port_attr->pa_npkeys; ii++) {
11937c478bd9Sstevel@tonic-gate 		if (port_attr->pa_pkey_tbl == NULL)
11947c478bd9Sstevel@tonic-gate 			break;
11957c478bd9Sstevel@tonic-gate 		if (!port_attr->pa_pkey_tbl[ii].pt_qp_hdl)
11967c478bd9Sstevel@tonic-gate 			continue;
11977c478bd9Sstevel@tonic-gate 		if (ibdm_port_attr_ibmf_fini(port_attr, ii) != IBDM_SUCCESS) {
11987c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibdm", "\tfini_port: "
11997c478bd9Sstevel@tonic-gate 			    "ibdm_port_attr_ibmf_fini failed for "
12007c478bd9Sstevel@tonic-gate 			    "port pkey 0x%x", ii);
12017c478bd9Sstevel@tonic-gate 			return (IBDM_FAILURE);
12027c478bd9Sstevel@tonic-gate 		}
12037c478bd9Sstevel@tonic-gate 	}
12047c478bd9Sstevel@tonic-gate 
12057c478bd9Sstevel@tonic-gate 	if (port_attr->pa_ibmf_hdl) {
12067c478bd9Sstevel@tonic-gate 		ibmf_status = ibmf_tear_down_async_cb(port_attr->pa_ibmf_hdl,
12077c478bd9Sstevel@tonic-gate 		    IBMF_QP_HANDLE_DEFAULT, 0);
12087c478bd9Sstevel@tonic-gate 		if (ibmf_status != IBMF_SUCCESS) {
12097c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibdm", "\tfini_port: "
12107c478bd9Sstevel@tonic-gate 			    "ibmf_tear_down_async_cb failed %d", ibmf_status);
12117c478bd9Sstevel@tonic-gate 			return (IBDM_FAILURE);
12127c478bd9Sstevel@tonic-gate 		}
12137c478bd9Sstevel@tonic-gate 
12147c478bd9Sstevel@tonic-gate 		ibmf_status = ibmf_unregister(&port_attr->pa_ibmf_hdl, 0);
12157c478bd9Sstevel@tonic-gate 		if (ibmf_status != IBMF_SUCCESS) {
1216dcf1eb70SSudhakar Dindukurti 			IBTF_DPRINTF_L2("ibdm", "\tfini_port: "
12177c478bd9Sstevel@tonic-gate 			    "ibmf_unregister failed %d", ibmf_status);
12187c478bd9Sstevel@tonic-gate 			return (IBDM_FAILURE);
12197c478bd9Sstevel@tonic-gate 		}
12207c478bd9Sstevel@tonic-gate 
12217c478bd9Sstevel@tonic-gate 		port_attr->pa_ibmf_hdl = NULL;
12227c478bd9Sstevel@tonic-gate 	}
12237c478bd9Sstevel@tonic-gate 
12247c478bd9Sstevel@tonic-gate 	if (port_attr->pa_sa_hdl) {
12257c478bd9Sstevel@tonic-gate 		ibmf_status = ibmf_sa_session_close(&port_attr->pa_sa_hdl, 0);
12267c478bd9Sstevel@tonic-gate 		if (ibmf_status != IBMF_SUCCESS) {
1227dcf1eb70SSudhakar Dindukurti 			IBTF_DPRINTF_L2("ibdm", "\tfini_port: "
12287c478bd9Sstevel@tonic-gate 			    "ibmf_sa_session_close failed %d", ibmf_status);
12297c478bd9Sstevel@tonic-gate 			return (IBDM_FAILURE);
12307c478bd9Sstevel@tonic-gate 		}
12317c478bd9Sstevel@tonic-gate 		port_attr->pa_sa_hdl = NULL;
12327c478bd9Sstevel@tonic-gate 	}
12337c478bd9Sstevel@tonic-gate 
12347c478bd9Sstevel@tonic-gate 	if (port_attr->pa_pkey_tbl != NULL) {
12357c478bd9Sstevel@tonic-gate 		kmem_free(port_attr->pa_pkey_tbl,
12367c478bd9Sstevel@tonic-gate 		    port_attr->pa_npkeys * sizeof (ibdm_pkey_tbl_t));
12377c478bd9Sstevel@tonic-gate 		port_attr->pa_pkey_tbl = NULL;
12387c478bd9Sstevel@tonic-gate 		port_attr->pa_npkeys = 0;
12397c478bd9Sstevel@tonic-gate 	}
12407c478bd9Sstevel@tonic-gate 
12417c478bd9Sstevel@tonic-gate 	return (IBDM_SUCCESS);
12427c478bd9Sstevel@tonic-gate }
12437c478bd9Sstevel@tonic-gate 
12447c478bd9Sstevel@tonic-gate 
12457c478bd9Sstevel@tonic-gate /*
12467c478bd9Sstevel@tonic-gate  * ibdm_port_attr_ibmf_fini:
12477c478bd9Sstevel@tonic-gate  *	With IBMF - Tear down Async callback and free QP Handle
12487c478bd9Sstevel@tonic-gate  */
12497c478bd9Sstevel@tonic-gate static int
ibdm_port_attr_ibmf_fini(ibdm_port_attr_t * port_attr,int ii)12507c478bd9Sstevel@tonic-gate ibdm_port_attr_ibmf_fini(ibdm_port_attr_t *port_attr, int ii)
12517c478bd9Sstevel@tonic-gate {
12527c478bd9Sstevel@tonic-gate 	int ibmf_status;
12537c478bd9Sstevel@tonic-gate 
12547c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L5("ibdm", "\tport_attr_ibmf_fini:");
12557c478bd9Sstevel@tonic-gate 
1256c44ec8d2SRamaswamy Tummala 	if (ibdm_enumerate_iocs == 0) {
1257c44ec8d2SRamaswamy Tummala 		ASSERT(port_attr->pa_pkey_tbl[ii].pt_qp_hdl == NULL);
1258c44ec8d2SRamaswamy Tummala 		return (IBDM_SUCCESS);
1259c44ec8d2SRamaswamy Tummala 	}
1260c44ec8d2SRamaswamy Tummala 
12617c478bd9Sstevel@tonic-gate 	if (port_attr->pa_pkey_tbl[ii].pt_qp_hdl) {
12627c478bd9Sstevel@tonic-gate 		ibmf_status = ibmf_tear_down_async_cb(port_attr->pa_ibmf_hdl,
12637c478bd9Sstevel@tonic-gate 		    port_attr->pa_pkey_tbl[ii].pt_qp_hdl, 0);
12647c478bd9Sstevel@tonic-gate 		if (ibmf_status != IBMF_SUCCESS) {
12657c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibdm", "\tport_attr_ibmf_fini: "
12667c478bd9Sstevel@tonic-gate 			    "ibmf_tear_down_async_cb failed %d", ibmf_status);
12677c478bd9Sstevel@tonic-gate 			return (IBDM_FAILURE);
12687c478bd9Sstevel@tonic-gate 		}
12697c478bd9Sstevel@tonic-gate 		ibmf_status = ibmf_free_qp(port_attr->pa_ibmf_hdl,
12707c478bd9Sstevel@tonic-gate 		    &port_attr->pa_pkey_tbl[ii].pt_qp_hdl, 0);
12717c478bd9Sstevel@tonic-gate 		if (ibmf_status != IBMF_SUCCESS) {
12727c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibdm", "\tport_attr_ibmf_fini: "
12737c478bd9Sstevel@tonic-gate 			    "ibmf_free_qp failed %d", ibmf_status);
12747c478bd9Sstevel@tonic-gate 			return (IBDM_FAILURE);
12757c478bd9Sstevel@tonic-gate 		}
12767c478bd9Sstevel@tonic-gate 		port_attr->pa_pkey_tbl[ii].pt_qp_hdl = NULL;
12777c478bd9Sstevel@tonic-gate 	}
12787c478bd9Sstevel@tonic-gate 	return (IBDM_SUCCESS);
12797c478bd9Sstevel@tonic-gate }
12807c478bd9Sstevel@tonic-gate 
12817c478bd9Sstevel@tonic-gate 
12827c478bd9Sstevel@tonic-gate /*
12837c478bd9Sstevel@tonic-gate  * ibdm_gid_decr_pending:
12847c478bd9Sstevel@tonic-gate  *	decrement gl_pending_cmds. If zero wakeup sleeping threads
12857c478bd9Sstevel@tonic-gate  */
12867c478bd9Sstevel@tonic-gate static void
ibdm_gid_decr_pending(ibdm_dp_gidinfo_t * gidinfo)12877c478bd9Sstevel@tonic-gate ibdm_gid_decr_pending(ibdm_dp_gidinfo_t *gidinfo)
12887c478bd9Sstevel@tonic-gate {
12897c478bd9Sstevel@tonic-gate 	mutex_enter(&ibdm.ibdm_mutex);
12907c478bd9Sstevel@tonic-gate 	mutex_enter(&gidinfo->gl_mutex);
12917c478bd9Sstevel@tonic-gate 	if (--gidinfo->gl_pending_cmds == 0) {
12927c478bd9Sstevel@tonic-gate 		/*
12937c478bd9Sstevel@tonic-gate 		 * Handle DGID getting removed.
12947c478bd9Sstevel@tonic-gate 		 */
12957c478bd9Sstevel@tonic-gate 		if (gidinfo->gl_disconnected) {
12967c478bd9Sstevel@tonic-gate 			mutex_exit(&gidinfo->gl_mutex);
12977c478bd9Sstevel@tonic-gate 			mutex_exit(&ibdm.ibdm_mutex);
12987c478bd9Sstevel@tonic-gate 
12997c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L3(ibdm_string, "\tgid_decr_pending: "
13007c478bd9Sstevel@tonic-gate 			    "gidinfo %p hot removal", gidinfo);
13017c478bd9Sstevel@tonic-gate 			ibdm_delete_gidinfo(gidinfo);
13027c478bd9Sstevel@tonic-gate 
13037c478bd9Sstevel@tonic-gate 			mutex_enter(&ibdm.ibdm_mutex);
13047c478bd9Sstevel@tonic-gate 			ibdm.ibdm_ngid_probes_in_progress--;
13057c478bd9Sstevel@tonic-gate 			ibdm_wait_probe_completion();
13067c478bd9Sstevel@tonic-gate 			mutex_exit(&ibdm.ibdm_mutex);
13077c478bd9Sstevel@tonic-gate 			return;
13087c478bd9Sstevel@tonic-gate 		}
13097c478bd9Sstevel@tonic-gate 		mutex_exit(&gidinfo->gl_mutex);
13107c478bd9Sstevel@tonic-gate 		mutex_exit(&ibdm.ibdm_mutex);
13117c478bd9Sstevel@tonic-gate 		ibdm_notify_newgid_iocs(gidinfo);
13127c478bd9Sstevel@tonic-gate 		mutex_enter(&ibdm.ibdm_mutex);
13137c478bd9Sstevel@tonic-gate 		mutex_enter(&gidinfo->gl_mutex);
13147c478bd9Sstevel@tonic-gate 
13157c478bd9Sstevel@tonic-gate 		ibdm.ibdm_ngid_probes_in_progress--;
13167c478bd9Sstevel@tonic-gate 		ibdm_wait_probe_completion();
13177c478bd9Sstevel@tonic-gate 	}
13187c478bd9Sstevel@tonic-gate 	mutex_exit(&gidinfo->gl_mutex);
13197c478bd9Sstevel@tonic-gate 	mutex_exit(&ibdm.ibdm_mutex);
13207c478bd9Sstevel@tonic-gate }
13217c478bd9Sstevel@tonic-gate 
13227c478bd9Sstevel@tonic-gate 
13237c478bd9Sstevel@tonic-gate /*
13247c478bd9Sstevel@tonic-gate  * ibdm_wait_probe_completion:
13257c478bd9Sstevel@tonic-gate  *	wait for probing to complete
13267c478bd9Sstevel@tonic-gate  */
13277c478bd9Sstevel@tonic-gate static void
ibdm_wait_probe_completion(void)13287c478bd9Sstevel@tonic-gate ibdm_wait_probe_completion(void)
13297c478bd9Sstevel@tonic-gate {
13307c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ibdm.ibdm_mutex));
13317c478bd9Sstevel@tonic-gate 	if (ibdm.ibdm_ngid_probes_in_progress) {
13327c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibdm",	"\twait for probe complete");
13337c478bd9Sstevel@tonic-gate 		ibdm.ibdm_busy |= IBDM_PROBE_IN_PROGRESS;
13347c478bd9Sstevel@tonic-gate 		while (ibdm.ibdm_busy & IBDM_PROBE_IN_PROGRESS)
13357c478bd9Sstevel@tonic-gate 			cv_wait(&ibdm.ibdm_probe_cv, &ibdm.ibdm_mutex);
13367c478bd9Sstevel@tonic-gate 	}
13377c478bd9Sstevel@tonic-gate }
13387c478bd9Sstevel@tonic-gate 
13397c478bd9Sstevel@tonic-gate 
134053c1b7a3Seota /*
134153c1b7a3Seota  * ibdm_wait_cisco_probe_completion:
134253c1b7a3Seota  *	wait for the reply from the Cisco FC GW switch after a setclassportinfo
134353c1b7a3Seota  *	request is sent. This wait can be achieved on each gid.
134453c1b7a3Seota  */
134553c1b7a3Seota static void
ibdm_wait_cisco_probe_completion(ibdm_dp_gidinfo_t * gidinfo)134653c1b7a3Seota ibdm_wait_cisco_probe_completion(ibdm_dp_gidinfo_t *gidinfo)
134753c1b7a3Seota {
134853c1b7a3Seota 	ASSERT(MUTEX_HELD(&gidinfo->gl_mutex));
134953c1b7a3Seota 	IBTF_DPRINTF_L4("ibdm",	"\twait for cisco probe complete");
135053c1b7a3Seota 	gidinfo->gl_flag |= IBDM_CISCO_PROBE;
135153c1b7a3Seota 	while (gidinfo->gl_flag & IBDM_CISCO_PROBE)
135253c1b7a3Seota 		cv_wait(&gidinfo->gl_probe_cv, &gidinfo->gl_mutex);
135353c1b7a3Seota }
135453c1b7a3Seota 
135553c1b7a3Seota 
13567c478bd9Sstevel@tonic-gate /*
13577c478bd9Sstevel@tonic-gate  * ibdm_wakeup_probe_gid_cv:
13587c478bd9Sstevel@tonic-gate  *	wakeup waiting threads (based on ibdm_ngid_probes_in_progress)
13597c478bd9Sstevel@tonic-gate  */
13607c478bd9Sstevel@tonic-gate static void
ibdm_wakeup_probe_gid_cv(void)13617c478bd9Sstevel@tonic-gate ibdm_wakeup_probe_gid_cv(void)
13627c478bd9Sstevel@tonic-gate {
13637c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ibdm.ibdm_mutex));
13647c478bd9Sstevel@tonic-gate 	if (!ibdm.ibdm_ngid_probes_in_progress) {
13657c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibdm", "wakeup_probe_gid_thread: Wakeup");
13667c478bd9Sstevel@tonic-gate 		ibdm.ibdm_busy &= ~IBDM_PROBE_IN_PROGRESS;
13677c478bd9Sstevel@tonic-gate 		cv_broadcast(&ibdm.ibdm_probe_cv);
13687c478bd9Sstevel@tonic-gate 	}
13697c478bd9Sstevel@tonic-gate 
13707c478bd9Sstevel@tonic-gate }
13717c478bd9Sstevel@tonic-gate 
13727c478bd9Sstevel@tonic-gate 
13737c478bd9Sstevel@tonic-gate /*
13747c478bd9Sstevel@tonic-gate  * ibdm_sweep_fabric(reprobe_flag)
13757c478bd9Sstevel@tonic-gate  *	Find all possible Managed IOU's and their IOC's that are visible
13767c478bd9Sstevel@tonic-gate  *	to the host. The algorithm used is as follows
13777c478bd9Sstevel@tonic-gate  *
13787c478bd9Sstevel@tonic-gate  *	Send a "bus walk" request for each port on the host HCA to SA access
13797c478bd9Sstevel@tonic-gate  *	SA returns complete set of GID's that are reachable from
13807c478bd9Sstevel@tonic-gate  *	source port. This is done in parallel.
13817c478bd9Sstevel@tonic-gate  *
13827c478bd9Sstevel@tonic-gate  *	Initialize GID state to IBDM_GID_PROBE_NOT_DONE
13837c478bd9Sstevel@tonic-gate  *
13847c478bd9Sstevel@tonic-gate  *	Sort the GID list and eliminate duplicate GID's
13857c478bd9Sstevel@tonic-gate  *		1) Use DGID for sorting
13867c478bd9Sstevel@tonic-gate  *		2) use PortGuid for sorting
13877c478bd9Sstevel@tonic-gate  *			Send SA query to retrieve NodeRecord and
13887c478bd9Sstevel@tonic-gate  *			extract PortGuid from that.
13897c478bd9Sstevel@tonic-gate  *
13907c478bd9Sstevel@tonic-gate  *	Set GID state to IBDM_GID_PROBE_FAILED to all the ports that dont
13917c478bd9Sstevel@tonic-gate  *	support DM MAD's
13927c478bd9Sstevel@tonic-gate  *		Send a "Portinfo" query to get the port capabilities and
13937c478bd9Sstevel@tonic-gate  *		then check for DM MAD's support
13947c478bd9Sstevel@tonic-gate  *
13957c478bd9Sstevel@tonic-gate  *	Send "ClassPortInfo" request for all the GID's in parallel,
13967c478bd9Sstevel@tonic-gate  *	set the GID state to IBDM_GET_CLASSPORTINFO and wait on the
13977c478bd9Sstevel@tonic-gate  *	cv_signal to complete.
13987c478bd9Sstevel@tonic-gate  *
13997c478bd9Sstevel@tonic-gate  *	When DM agent on the remote GID sends back the response, IBMF
14007c478bd9Sstevel@tonic-gate  *	invokes DM callback routine.
14017c478bd9Sstevel@tonic-gate  *
14027c478bd9Sstevel@tonic-gate  *	If the response is proper, send "IOUnitInfo" request and set
14037c478bd9Sstevel@tonic-gate  *	GID state to IBDM_GET_IOUNITINFO.
14047c478bd9Sstevel@tonic-gate  *
14057c478bd9Sstevel@tonic-gate  *	If the response is proper, send "IocProfileInfo" request to
14067c478bd9Sstevel@tonic-gate  *	all the IOC simultaneously and set GID state to IBDM_GET_IOC_DETAILS.
14077c478bd9Sstevel@tonic-gate  *
14087c478bd9Sstevel@tonic-gate  *	Send request to get Service entries simultaneously
14097c478bd9Sstevel@tonic-gate  *
14107c478bd9Sstevel@tonic-gate  *	Signal the waiting thread when received response for all the commands.
14117c478bd9Sstevel@tonic-gate  *
14127c478bd9Sstevel@tonic-gate  *	Set the GID state to IBDM_GID_PROBE_FAILED when received a error
14137c478bd9Sstevel@tonic-gate  *	response during the probing period.
14147c478bd9Sstevel@tonic-gate  *
14157c478bd9Sstevel@tonic-gate  *	Note:
14167c478bd9Sstevel@tonic-gate  *	ibdm.ibdm_ngid_probes_in_progress and ibdm_gid_list_t:gl_pending_cmds
14177c478bd9Sstevel@tonic-gate  *	keep track of number commands in progress at any point of time.
14187c478bd9Sstevel@tonic-gate  *	MAD transaction ID is used to identify a particular GID
14197c478bd9Sstevel@tonic-gate  *	TBD: Consider registering the IBMF receive callback on demand
14207c478bd9Sstevel@tonic-gate  *
14217c478bd9Sstevel@tonic-gate  *	Note: This routine must be called with ibdm.ibdm_mutex held
14227c478bd9Sstevel@tonic-gate  *	TBD: Re probe the failure GID (for certain failures) when requested
14237c478bd9Sstevel@tonic-gate  *	     for fabric sweep next time
14247c478bd9Sstevel@tonic-gate  *
14257c478bd9Sstevel@tonic-gate  *	Parameters : If reprobe_flag is set, All IOCs will be reprobed.
14267c478bd9Sstevel@tonic-gate  */
14277c478bd9Sstevel@tonic-gate static void
ibdm_sweep_fabric(int reprobe_flag)14287c478bd9Sstevel@tonic-gate ibdm_sweep_fabric(int reprobe_flag)
14297c478bd9Sstevel@tonic-gate {
14307c478bd9Sstevel@tonic-gate 	int			ii;
14317c478bd9Sstevel@tonic-gate 	int			new_paths = 0;
14327c478bd9Sstevel@tonic-gate 	uint8_t			niocs;
14337c478bd9Sstevel@tonic-gate 	taskqid_t		tid;
14347c478bd9Sstevel@tonic-gate 	ibdm_ioc_info_t		*ioc;
14357c478bd9Sstevel@tonic-gate 	ibdm_hca_list_t		*hca_list = NULL;
14367c478bd9Sstevel@tonic-gate 	ibdm_port_attr_t	*port = NULL;
14377c478bd9Sstevel@tonic-gate 	ibdm_dp_gidinfo_t 	*gid_info;
14387c478bd9Sstevel@tonic-gate 
14397c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tsweep_fabric: Enter");
14407c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ibdm.ibdm_mutex));
14417c478bd9Sstevel@tonic-gate 
14427c478bd9Sstevel@tonic-gate 	/*
14437c478bd9Sstevel@tonic-gate 	 * Check whether a sweep already in progress. If so, just
14447c478bd9Sstevel@tonic-gate 	 * wait for the fabric sweep to complete
14457c478bd9Sstevel@tonic-gate 	 */
14467c478bd9Sstevel@tonic-gate 	while (ibdm.ibdm_busy & IBDM_BUSY)
14477c478bd9Sstevel@tonic-gate 		cv_wait(&ibdm.ibdm_busy_cv, &ibdm.ibdm_mutex);
14487c478bd9Sstevel@tonic-gate 	ibdm.ibdm_busy |= IBDM_BUSY;
14497c478bd9Sstevel@tonic-gate 	mutex_exit(&ibdm.ibdm_mutex);
14507c478bd9Sstevel@tonic-gate 
14517c478bd9Sstevel@tonic-gate 	ibdm_dump_sweep_fabric_timestamp(0);
14527c478bd9Sstevel@tonic-gate 
14537c478bd9Sstevel@tonic-gate 	/* Rescan the GID list for any removed GIDs for reprobe */
14547c478bd9Sstevel@tonic-gate 	if (reprobe_flag)
14557c478bd9Sstevel@tonic-gate 		ibdm_rescan_gidlist(NULL);
14567c478bd9Sstevel@tonic-gate 
14577c478bd9Sstevel@tonic-gate 	/*
14587c478bd9Sstevel@tonic-gate 	 * Get list of all the ports reachable from the local known HCA
14597c478bd9Sstevel@tonic-gate 	 * ports which are active
14607c478bd9Sstevel@tonic-gate 	 */
14617c478bd9Sstevel@tonic-gate 	mutex_enter(&ibdm.ibdm_hl_mutex);
14627c478bd9Sstevel@tonic-gate 	for (ibdm_get_next_port(&hca_list, &port, 1); port;
14637c478bd9Sstevel@tonic-gate 	    ibdm_get_next_port(&hca_list, &port, 1)) {
14647c478bd9Sstevel@tonic-gate 		/*
14657c478bd9Sstevel@tonic-gate 		 * Get PATHS to all the reachable ports from
14667c478bd9Sstevel@tonic-gate 		 * SGID and update the global ibdm structure.
14677c478bd9Sstevel@tonic-gate 		 */
14687c478bd9Sstevel@tonic-gate 		new_paths = ibdm_get_reachable_ports(port, hca_list);
14697c478bd9Sstevel@tonic-gate 		ibdm.ibdm_ngids += new_paths;
14707c478bd9Sstevel@tonic-gate 	}
14717c478bd9Sstevel@tonic-gate 	mutex_exit(&ibdm.ibdm_hl_mutex);
14727c478bd9Sstevel@tonic-gate 
14737c478bd9Sstevel@tonic-gate 	mutex_enter(&ibdm.ibdm_mutex);
14747c478bd9Sstevel@tonic-gate 	ibdm.ibdm_ngid_probes_in_progress += ibdm.ibdm_ngids;
14757c478bd9Sstevel@tonic-gate 	mutex_exit(&ibdm.ibdm_mutex);
14767c478bd9Sstevel@tonic-gate 
14777c478bd9Sstevel@tonic-gate 	/* Send a request to probe GIDs asynchronously. */
14787c478bd9Sstevel@tonic-gate 	for (gid_info = ibdm.ibdm_dp_gidlist_head; gid_info;
14797c478bd9Sstevel@tonic-gate 	    gid_info = gid_info->gl_next) {
14807c478bd9Sstevel@tonic-gate 		mutex_enter(&gid_info->gl_mutex);
14817c478bd9Sstevel@tonic-gate 		gid_info->gl_reprobe_flag = reprobe_flag;
14827c478bd9Sstevel@tonic-gate 		mutex_exit(&gid_info->gl_mutex);
14837c478bd9Sstevel@tonic-gate 
14847c478bd9Sstevel@tonic-gate 		/* process newly encountered GIDs */
14857c478bd9Sstevel@tonic-gate 		tid = taskq_dispatch(system_taskq, ibdm_probe_gid_thread,
14867c478bd9Sstevel@tonic-gate 		    (void *)gid_info, TQ_NOSLEEP);
14877c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibdm", "\tsweep_fabric: gid_info = %p"
14887c478bd9Sstevel@tonic-gate 		    " taskq_id = %x", gid_info, tid);
14897c478bd9Sstevel@tonic-gate 		/* taskq failed to dispatch call it directly */
1490*fc8ae2ecSToomas Soome 		if (tid == TASKQID_INVALID)
14917c478bd9Sstevel@tonic-gate 			ibdm_probe_gid_thread((void *)gid_info);
14927c478bd9Sstevel@tonic-gate 	}
14937c478bd9Sstevel@tonic-gate 
14947c478bd9Sstevel@tonic-gate 	mutex_enter(&ibdm.ibdm_mutex);
14957c478bd9Sstevel@tonic-gate 	ibdm_wait_probe_completion();
14967c478bd9Sstevel@tonic-gate 
14977c478bd9Sstevel@tonic-gate 	/*
14987c478bd9Sstevel@tonic-gate 	 * Update the properties, if reprobe_flag is set
14997c478bd9Sstevel@tonic-gate 	 * Skip if gl_reprobe_flag is set, this will be
15007c478bd9Sstevel@tonic-gate 	 * a re-inserted / new GID, for which notifications
15017c478bd9Sstevel@tonic-gate 	 * have already been send.
15027c478bd9Sstevel@tonic-gate 	 */
15037c478bd9Sstevel@tonic-gate 	if (reprobe_flag) {
15047c478bd9Sstevel@tonic-gate 		for (gid_info = ibdm.ibdm_dp_gidlist_head; gid_info;
15057c478bd9Sstevel@tonic-gate 		    gid_info = gid_info->gl_next) {
15067c478bd9Sstevel@tonic-gate 			if (gid_info->gl_iou == NULL)
15077c478bd9Sstevel@tonic-gate 				continue;
15087c478bd9Sstevel@tonic-gate 			if (gid_info->gl_reprobe_flag) {
15097c478bd9Sstevel@tonic-gate 				gid_info->gl_reprobe_flag = 0;
15107c478bd9Sstevel@tonic-gate 				continue;
15117c478bd9Sstevel@tonic-gate 			}
15127c478bd9Sstevel@tonic-gate 
15137c478bd9Sstevel@tonic-gate 			niocs = gid_info->gl_iou->iou_info.iou_num_ctrl_slots;
15147c478bd9Sstevel@tonic-gate 			for (ii = 0; ii < niocs; ii++) {
15157c478bd9Sstevel@tonic-gate 				ioc = IBDM_GIDINFO2IOCINFO(gid_info, ii);
15167c478bd9Sstevel@tonic-gate 				if (ioc)
15177c478bd9Sstevel@tonic-gate 					ibdm_reprobe_update_port_srv(ioc,
15187c478bd9Sstevel@tonic-gate 					    gid_info);
15197c478bd9Sstevel@tonic-gate 			}
15207c478bd9Sstevel@tonic-gate 		}
1521add2b70bSpramodbg 	} else if (ibdm.ibdm_prev_iou) {
1522add2b70bSpramodbg 		ibdm_ioc_info_t	*ioc_list;
1523add2b70bSpramodbg 
1524add2b70bSpramodbg 		/*
1525add2b70bSpramodbg 		 * Get the list of IOCs which have changed.
1526add2b70bSpramodbg 		 * If any IOCs have changed, Notify IBNexus
1527add2b70bSpramodbg 		 */
1528add2b70bSpramodbg 		ibdm.ibdm_prev_iou = 0;
1529add2b70bSpramodbg 		ioc_list = ibdm_handle_prev_iou();
1530add2b70bSpramodbg 		if (ioc_list) {
1531add2b70bSpramodbg 			if (ibdm.ibdm_ibnex_callback != NULL) {
1532add2b70bSpramodbg 				(*ibdm.ibdm_ibnex_callback)(
1533add2b70bSpramodbg 				    (void *)ioc_list,
1534add2b70bSpramodbg 				    IBDM_EVENT_IOC_PROP_UPDATE);
1535add2b70bSpramodbg 			}
1536add2b70bSpramodbg 		}
15377c478bd9Sstevel@tonic-gate 	}
1538add2b70bSpramodbg 
15397c478bd9Sstevel@tonic-gate 	ibdm_dump_sweep_fabric_timestamp(1);
15407c478bd9Sstevel@tonic-gate 
15417c478bd9Sstevel@tonic-gate 	ibdm.ibdm_busy &= ~IBDM_BUSY;
15427c478bd9Sstevel@tonic-gate 	cv_broadcast(&ibdm.ibdm_busy_cv);
15437c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L5("ibdm", "\tsweep_fabric: EXIT");
15447c478bd9Sstevel@tonic-gate }
15457c478bd9Sstevel@tonic-gate 
15467c478bd9Sstevel@tonic-gate 
154753c1b7a3Seota /*
154853c1b7a3Seota  * ibdm_is_cisco:
154953c1b7a3Seota  * 	Check if this is a Cisco device or not.
155053c1b7a3Seota  */
155153c1b7a3Seota static boolean_t
ibdm_is_cisco(ib_guid_t guid)155253c1b7a3Seota ibdm_is_cisco(ib_guid_t guid)
155353c1b7a3Seota {
155453c1b7a3Seota 	if ((guid >> IBDM_OUI_GUID_SHIFT) == IBDM_CISCO_COMPANY_ID)
155553c1b7a3Seota 		return (B_TRUE);
155653c1b7a3Seota 	return (B_FALSE);
155753c1b7a3Seota }
155853c1b7a3Seota 
155953c1b7a3Seota 
156053c1b7a3Seota /*
156153c1b7a3Seota  * ibdm_is_cisco_switch:
156253c1b7a3Seota  * 	Check if this switch is a CISCO switch or not.
156353c1b7a3Seota  * 	Note that if this switch is already activated, ibdm_is_cisco_switch()
156453c1b7a3Seota  * 	returns B_FALSE not to re-activate it again.
156553c1b7a3Seota  */
156653c1b7a3Seota static boolean_t
ibdm_is_cisco_switch(ibdm_dp_gidinfo_t * gid_info)156753c1b7a3Seota ibdm_is_cisco_switch(ibdm_dp_gidinfo_t *gid_info)
156853c1b7a3Seota {
156953c1b7a3Seota 	int company_id, device_id;
157053c1b7a3Seota 	ASSERT(gid_info != 0);
157153c1b7a3Seota 	ASSERT(MUTEX_HELD(&gid_info->gl_mutex));
157253c1b7a3Seota 
157353c1b7a3Seota 	/*
157453c1b7a3Seota 	 * If this switch is already activated, don't re-activate it.
157553c1b7a3Seota 	 */
157653c1b7a3Seota 	if (gid_info->gl_flag & IBDM_CISCO_PROBE_DONE)
157753c1b7a3Seota 		return (B_FALSE);
157853c1b7a3Seota 
157953c1b7a3Seota 	/*
158053c1b7a3Seota 	 * Check if this switch is a Cisco FC GW or not.
158153c1b7a3Seota 	 * Use the node guid (the OUI part) instead of the vendor id
158253c1b7a3Seota 	 * since the vendor id is zero in practice.
158353c1b7a3Seota 	 */
158453c1b7a3Seota 	company_id = gid_info->gl_nodeguid >> IBDM_OUI_GUID_SHIFT;
158553c1b7a3Seota 	device_id = gid_info->gl_devid;
158653c1b7a3Seota 
158753c1b7a3Seota 	if (company_id == IBDM_CISCO_COMPANY_ID &&
158853c1b7a3Seota 	    device_id == IBDM_CISCO_DEVICE_ID)
158953c1b7a3Seota 		return (B_TRUE);
159053c1b7a3Seota 	return (B_FALSE);
159153c1b7a3Seota }
159253c1b7a3Seota 
159353c1b7a3Seota 
15947c478bd9Sstevel@tonic-gate /*
15957c478bd9Sstevel@tonic-gate  * ibdm_probe_gid_thread:
15967c478bd9Sstevel@tonic-gate  *	thread that does the actual work for sweeping the fabric
15977c478bd9Sstevel@tonic-gate  *	for a given GID
15987c478bd9Sstevel@tonic-gate  */
15997c478bd9Sstevel@tonic-gate static void
ibdm_probe_gid_thread(void * args)16007c478bd9Sstevel@tonic-gate ibdm_probe_gid_thread(void *args)
16017c478bd9Sstevel@tonic-gate {
16027c478bd9Sstevel@tonic-gate 	int			reprobe_flag;
16037c478bd9Sstevel@tonic-gate 	ib_guid_t		node_guid;
16047c478bd9Sstevel@tonic-gate 	ib_guid_t		port_guid;
16057c478bd9Sstevel@tonic-gate 	ibdm_dp_gidinfo_t	*gid_info;
16067c478bd9Sstevel@tonic-gate 
16077c478bd9Sstevel@tonic-gate 	gid_info = (ibdm_dp_gidinfo_t *)args;
16087c478bd9Sstevel@tonic-gate 	reprobe_flag = gid_info->gl_reprobe_flag;
16097c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tprobe_gid_thread: gid_info = %p, flag = %d",
16107c478bd9Sstevel@tonic-gate 	    gid_info, reprobe_flag);
16117c478bd9Sstevel@tonic-gate 	ASSERT(gid_info != NULL);
16127c478bd9Sstevel@tonic-gate 	ASSERT(gid_info->gl_pending_cmds == 0);
16137c478bd9Sstevel@tonic-gate 
16147c478bd9Sstevel@tonic-gate 	if (gid_info->gl_state != IBDM_GID_PROBE_NOT_DONE &&
16157c478bd9Sstevel@tonic-gate 	    reprobe_flag == 0) {
16167c478bd9Sstevel@tonic-gate 		/*
16177c478bd9Sstevel@tonic-gate 		 * This GID may have been already probed. Send
16187c478bd9Sstevel@tonic-gate 		 * in a CLP to check if IOUnitInfo changed?
16197c478bd9Sstevel@tonic-gate 		 * Explicitly set gl_reprobe_flag to 0 so that
16207c478bd9Sstevel@tonic-gate 		 * IBnex is not notified on completion
16217c478bd9Sstevel@tonic-gate 		 */
16227c478bd9Sstevel@tonic-gate 		if (gid_info->gl_state == IBDM_GID_PROBING_COMPLETE) {
16237c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibdm", "\tprobe_gid_thread: "
16247c478bd9Sstevel@tonic-gate 			    "get new IOCs information");
16257c478bd9Sstevel@tonic-gate 			mutex_enter(&gid_info->gl_mutex);
16267c478bd9Sstevel@tonic-gate 			gid_info->gl_pending_cmds++;
16277c478bd9Sstevel@tonic-gate 			gid_info->gl_state = IBDM_GET_IOUNITINFO;
16287c478bd9Sstevel@tonic-gate 			gid_info->gl_reprobe_flag = 0;
16297c478bd9Sstevel@tonic-gate 			mutex_exit(&gid_info->gl_mutex);
16307c478bd9Sstevel@tonic-gate 			if (ibdm_send_iounitinfo(gid_info) != IBDM_SUCCESS) {
16317c478bd9Sstevel@tonic-gate 				mutex_enter(&gid_info->gl_mutex);
163253c1b7a3Seota 				--gid_info->gl_pending_cmds;
16337c478bd9Sstevel@tonic-gate 				mutex_exit(&gid_info->gl_mutex);
16347c478bd9Sstevel@tonic-gate 				mutex_enter(&ibdm.ibdm_mutex);
16357c478bd9Sstevel@tonic-gate 				--ibdm.ibdm_ngid_probes_in_progress;
16367c478bd9Sstevel@tonic-gate 				ibdm_wakeup_probe_gid_cv();
16377c478bd9Sstevel@tonic-gate 				mutex_exit(&ibdm.ibdm_mutex);
16387c478bd9Sstevel@tonic-gate 			}
16397c478bd9Sstevel@tonic-gate 		} else {
16407c478bd9Sstevel@tonic-gate 			mutex_enter(&ibdm.ibdm_mutex);
16417c478bd9Sstevel@tonic-gate 			--ibdm.ibdm_ngid_probes_in_progress;
16427c478bd9Sstevel@tonic-gate 			ibdm_wakeup_probe_gid_cv();
16437c478bd9Sstevel@tonic-gate 			mutex_exit(&ibdm.ibdm_mutex);
16447c478bd9Sstevel@tonic-gate 		}
16457c478bd9Sstevel@tonic-gate 		return;
16467c478bd9Sstevel@tonic-gate 	} else if (reprobe_flag && gid_info->gl_state ==
16477c478bd9Sstevel@tonic-gate 	    IBDM_GID_PROBING_COMPLETE) {
16487c478bd9Sstevel@tonic-gate 		/*
16497c478bd9Sstevel@tonic-gate 		 * Reprobe all IOCs for the GID which has completed
16507c478bd9Sstevel@tonic-gate 		 * probe. Skip other port GIDs to same IOU.
16517c478bd9Sstevel@tonic-gate 		 * Explicitly set gl_reprobe_flag to 0 so that
16527c478bd9Sstevel@tonic-gate 		 * IBnex is not notified on completion
16537c478bd9Sstevel@tonic-gate 		 */
16547c478bd9Sstevel@tonic-gate 		ibdm_ioc_info_t *ioc_info;
16557c478bd9Sstevel@tonic-gate 		uint8_t		niocs, ii;
16567c478bd9Sstevel@tonic-gate 
165705fa0d51Spramodbg 		ASSERT(gid_info->gl_iou);
16587c478bd9Sstevel@tonic-gate 		mutex_enter(&gid_info->gl_mutex);
16597c478bd9Sstevel@tonic-gate 		niocs = gid_info->gl_iou->iou_info.iou_num_ctrl_slots;
16607c478bd9Sstevel@tonic-gate 		gid_info->gl_state = IBDM_GET_IOC_DETAILS;
16617c478bd9Sstevel@tonic-gate 		gid_info->gl_pending_cmds += niocs;
16627c478bd9Sstevel@tonic-gate 		gid_info->gl_reprobe_flag = 0;
16637c478bd9Sstevel@tonic-gate 		mutex_exit(&gid_info->gl_mutex);
16647c478bd9Sstevel@tonic-gate 		for (ii = 0; ii < niocs; ii++) {
16657c478bd9Sstevel@tonic-gate 			uchar_t			slot_info;
16667c478bd9Sstevel@tonic-gate 			ib_dm_io_unitinfo_t	*giou_info;
16677c478bd9Sstevel@tonic-gate 
16687c478bd9Sstevel@tonic-gate 			/*
16697c478bd9Sstevel@tonic-gate 			 * Check whether IOC is present in the slot
16707c478bd9Sstevel@tonic-gate 			 * Series of nibbles (in the field
16717c478bd9Sstevel@tonic-gate 			 * iou_ctrl_list) represents a slot in the
16727c478bd9Sstevel@tonic-gate 			 * IOU.
16737c478bd9Sstevel@tonic-gate 			 * Byte format: 76543210
16747c478bd9Sstevel@tonic-gate 			 * Bits 0-3 of first byte represent Slot 2
16757c478bd9Sstevel@tonic-gate 			 * bits 4-7 of first byte represent slot 1,
16767c478bd9Sstevel@tonic-gate 			 * bits 0-3 of second byte represent slot 4
16777c478bd9Sstevel@tonic-gate 			 * and so on
16787c478bd9Sstevel@tonic-gate 			 * Each 4-bit nibble has the following meaning
16797c478bd9Sstevel@tonic-gate 			 * 0x0 : IOC not installed
16807c478bd9Sstevel@tonic-gate 			 * 0x1 : IOC is present
16817c478bd9Sstevel@tonic-gate 			 * 0xf : Slot does not exist
16827c478bd9Sstevel@tonic-gate 			 * and all other values are reserved.
16837c478bd9Sstevel@tonic-gate 			 */
16847c478bd9Sstevel@tonic-gate 			ioc_info = IBDM_GIDINFO2IOCINFO(gid_info, ii);
16857c478bd9Sstevel@tonic-gate 			giou_info = &gid_info->gl_iou->iou_info;
16867c478bd9Sstevel@tonic-gate 			slot_info = giou_info->iou_ctrl_list[(ii/2)];
16877c478bd9Sstevel@tonic-gate 			if ((ii % 2) == 0)
16887c478bd9Sstevel@tonic-gate 				slot_info = (slot_info >> 4);
16897c478bd9Sstevel@tonic-gate 
16907c478bd9Sstevel@tonic-gate 			if ((slot_info & 0xf) != 1) {
16917c478bd9Sstevel@tonic-gate 				ioc_info->ioc_state =
16927c478bd9Sstevel@tonic-gate 				    IBDM_IOC_STATE_PROBE_FAILED;
16937c478bd9Sstevel@tonic-gate 				ibdm_gid_decr_pending(gid_info);
16947c478bd9Sstevel@tonic-gate 				continue;
16957c478bd9Sstevel@tonic-gate 			}
16967c478bd9Sstevel@tonic-gate 
16977c478bd9Sstevel@tonic-gate 			if (ibdm_send_ioc_profile(gid_info, ii) !=
16987c478bd9Sstevel@tonic-gate 			    IBDM_SUCCESS) {
16997c478bd9Sstevel@tonic-gate 				ibdm_gid_decr_pending(gid_info);
17007c478bd9Sstevel@tonic-gate 			}
17017c478bd9Sstevel@tonic-gate 		}
17027c478bd9Sstevel@tonic-gate 
17037c478bd9Sstevel@tonic-gate 		return;
17047c478bd9Sstevel@tonic-gate 	} else if (gid_info->gl_state != IBDM_GID_PROBE_NOT_DONE) {
17057c478bd9Sstevel@tonic-gate 		mutex_enter(&ibdm.ibdm_mutex);
17067c478bd9Sstevel@tonic-gate 		--ibdm.ibdm_ngid_probes_in_progress;
17077c478bd9Sstevel@tonic-gate 		ibdm_wakeup_probe_gid_cv();
17087c478bd9Sstevel@tonic-gate 		mutex_exit(&ibdm.ibdm_mutex);
17097c478bd9Sstevel@tonic-gate 		return;
17107c478bd9Sstevel@tonic-gate 	}
17117c478bd9Sstevel@tonic-gate 
17127c478bd9Sstevel@tonic-gate 	/*
17137c478bd9Sstevel@tonic-gate 	 * Check whether the destination GID supports DM agents. If
17147c478bd9Sstevel@tonic-gate 	 * not, stop probing the GID and continue with the next GID
17157c478bd9Sstevel@tonic-gate 	 * in the list.
17167c478bd9Sstevel@tonic-gate 	 */
17177c478bd9Sstevel@tonic-gate 	if (ibdm_is_dev_mgt_supported(gid_info) != IBDM_SUCCESS) {
17187c478bd9Sstevel@tonic-gate 		mutex_enter(&gid_info->gl_mutex);
17197c478bd9Sstevel@tonic-gate 		gid_info->gl_state = IBDM_GID_PROBING_FAILED;
17208e55d263SRajkumar Sivaprakasam 		gid_info->gl_is_dm_capable = B_FALSE;
17217c478bd9Sstevel@tonic-gate 		mutex_exit(&gid_info->gl_mutex);
17227c478bd9Sstevel@tonic-gate 		ibdm_delete_glhca_list(gid_info);
17237c478bd9Sstevel@tonic-gate 		mutex_enter(&ibdm.ibdm_mutex);
17247c478bd9Sstevel@tonic-gate 		--ibdm.ibdm_ngid_probes_in_progress;
17257c478bd9Sstevel@tonic-gate 		ibdm_wakeup_probe_gid_cv();
17267c478bd9Sstevel@tonic-gate 		mutex_exit(&ibdm.ibdm_mutex);
17277c478bd9Sstevel@tonic-gate 		return;
17287c478bd9Sstevel@tonic-gate 	}
17297c478bd9Sstevel@tonic-gate 
17308e55d263SRajkumar Sivaprakasam 	/*
17318e55d263SRajkumar Sivaprakasam 	 * This GID is Device management capable
17328e55d263SRajkumar Sivaprakasam 	 */
17338e55d263SRajkumar Sivaprakasam 	mutex_enter(&gid_info->gl_mutex);
17348e55d263SRajkumar Sivaprakasam 	gid_info->gl_is_dm_capable = B_TRUE;
17358e55d263SRajkumar Sivaprakasam 	mutex_exit(&gid_info->gl_mutex);
17368e55d263SRajkumar Sivaprakasam 
17377c478bd9Sstevel@tonic-gate 	/* Get the nodeguid and portguid of the port */
17387c478bd9Sstevel@tonic-gate 	if (ibdm_get_node_port_guids(gid_info->gl_sa_hdl, gid_info->gl_dlid,
17397c478bd9Sstevel@tonic-gate 	    &node_guid, &port_guid) != IBDM_SUCCESS) {
17407c478bd9Sstevel@tonic-gate 		mutex_enter(&gid_info->gl_mutex);
17417c478bd9Sstevel@tonic-gate 		gid_info->gl_state = IBDM_GID_PROBING_FAILED;
17427c478bd9Sstevel@tonic-gate 		mutex_exit(&gid_info->gl_mutex);
17437c478bd9Sstevel@tonic-gate 		ibdm_delete_glhca_list(gid_info);
17447c478bd9Sstevel@tonic-gate 		mutex_enter(&ibdm.ibdm_mutex);
17457c478bd9Sstevel@tonic-gate 		--ibdm.ibdm_ngid_probes_in_progress;
17467c478bd9Sstevel@tonic-gate 		ibdm_wakeup_probe_gid_cv();
17477c478bd9Sstevel@tonic-gate 		mutex_exit(&ibdm.ibdm_mutex);
17487c478bd9Sstevel@tonic-gate 		return;
17497c478bd9Sstevel@tonic-gate 	}
17507c478bd9Sstevel@tonic-gate 
17517c478bd9Sstevel@tonic-gate 	/*
17527c478bd9Sstevel@tonic-gate 	 * Check whether we already knew about this NodeGuid
17537c478bd9Sstevel@tonic-gate 	 * If so, do not probe the GID and continue with the
17547c478bd9Sstevel@tonic-gate 	 * next  GID  in the gid  list. Set the GID state to
17557c478bd9Sstevel@tonic-gate 	 * probing done.
17567c478bd9Sstevel@tonic-gate 	 */
17577c478bd9Sstevel@tonic-gate 	mutex_enter(&ibdm.ibdm_mutex);
17587c478bd9Sstevel@tonic-gate 	gid_info->gl_nodeguid = node_guid;
17597c478bd9Sstevel@tonic-gate 	gid_info->gl_portguid = port_guid;
17607c478bd9Sstevel@tonic-gate 	if (ibdm_check_dest_nodeguid(gid_info) != NULL) {
17617c478bd9Sstevel@tonic-gate 		mutex_exit(&ibdm.ibdm_mutex);
17627c478bd9Sstevel@tonic-gate 		mutex_enter(&gid_info->gl_mutex);
17637c478bd9Sstevel@tonic-gate 		gid_info->gl_state = IBDM_GID_PROBING_SKIPPED;
17647c478bd9Sstevel@tonic-gate 		mutex_exit(&gid_info->gl_mutex);
17657c478bd9Sstevel@tonic-gate 		ibdm_delete_glhca_list(gid_info);
17667c478bd9Sstevel@tonic-gate 		mutex_enter(&ibdm.ibdm_mutex);
17677c478bd9Sstevel@tonic-gate 		--ibdm.ibdm_ngid_probes_in_progress;
17687c478bd9Sstevel@tonic-gate 		ibdm_wakeup_probe_gid_cv();
17697c478bd9Sstevel@tonic-gate 		mutex_exit(&ibdm.ibdm_mutex);
17707c478bd9Sstevel@tonic-gate 		return;
17717c478bd9Sstevel@tonic-gate 	}
17727c478bd9Sstevel@tonic-gate 	ibdm_add_to_gl_gid(gid_info, gid_info);
17737c478bd9Sstevel@tonic-gate 	mutex_exit(&ibdm.ibdm_mutex);
17747c478bd9Sstevel@tonic-gate 
17757c478bd9Sstevel@tonic-gate 	/*
17767c478bd9Sstevel@tonic-gate 	 * New or reinserted GID : Enable notification to IBnex
17777c478bd9Sstevel@tonic-gate 	 */
17787c478bd9Sstevel@tonic-gate 	mutex_enter(&gid_info->gl_mutex);
17797c478bd9Sstevel@tonic-gate 	gid_info->gl_reprobe_flag = 1;
178053c1b7a3Seota 
178153c1b7a3Seota 	/*
178253c1b7a3Seota 	 * A Cisco FC GW needs the special handling to get IOUnitInfo.
178353c1b7a3Seota 	 */
178453c1b7a3Seota 	if (ibdm_is_cisco_switch(gid_info)) {
178553c1b7a3Seota 		gid_info->gl_pending_cmds++;
178653c1b7a3Seota 		gid_info->gl_state = IBDM_SET_CLASSPORTINFO;
178753c1b7a3Seota 		mutex_exit(&gid_info->gl_mutex);
178853c1b7a3Seota 
178953c1b7a3Seota 		if (ibdm_set_classportinfo(gid_info) != IBDM_SUCCESS) {
179053c1b7a3Seota 			mutex_enter(&gid_info->gl_mutex);
179153c1b7a3Seota 			gid_info->gl_state = IBDM_GID_PROBING_FAILED;
179253c1b7a3Seota 			--gid_info->gl_pending_cmds;
179353c1b7a3Seota 			mutex_exit(&gid_info->gl_mutex);
179453c1b7a3Seota 
179553c1b7a3Seota 			/* free the hca_list on this gid_info */
179653c1b7a3Seota 			ibdm_delete_glhca_list(gid_info);
179753c1b7a3Seota 
179853c1b7a3Seota 			mutex_enter(&ibdm.ibdm_mutex);
179953c1b7a3Seota 			--ibdm.ibdm_ngid_probes_in_progress;
180053c1b7a3Seota 			ibdm_wakeup_probe_gid_cv();
180153c1b7a3Seota 			mutex_exit(&ibdm.ibdm_mutex);
180253c1b7a3Seota 
180353c1b7a3Seota 			return;
180453c1b7a3Seota 		}
180553c1b7a3Seota 
180653c1b7a3Seota 		mutex_enter(&gid_info->gl_mutex);
180753c1b7a3Seota 		ibdm_wait_cisco_probe_completion(gid_info);
180853c1b7a3Seota 
180953c1b7a3Seota 		IBTF_DPRINTF_L4("ibdm", "\tibdm_probe_gid_thread: "
181053c1b7a3Seota 		    "CISCO Wakeup signal received");
181153c1b7a3Seota 	}
181253c1b7a3Seota 
181353c1b7a3Seota 	/* move on to the 'GET_CLASSPORTINFO' stage */
181453c1b7a3Seota 	gid_info->gl_pending_cmds++;
181553c1b7a3Seota 	gid_info->gl_state = IBDM_GET_CLASSPORTINFO;
18167c478bd9Sstevel@tonic-gate 	mutex_exit(&gid_info->gl_mutex);
18177c478bd9Sstevel@tonic-gate 
181853c1b7a3Seota 	IBTF_DPRINTF_L3(ibdm_string, "\tibdm_probe_gid_thread: "
181953c1b7a3Seota 	    "%d: gid_info %p gl_state %d pending_cmds %d",
182053c1b7a3Seota 	    __LINE__, gid_info, gid_info->gl_state,
182153c1b7a3Seota 	    gid_info->gl_pending_cmds);
182253c1b7a3Seota 
18237c478bd9Sstevel@tonic-gate 	/*
18247c478bd9Sstevel@tonic-gate 	 * Send ClassPortInfo request to the GID asynchronously.
18257c478bd9Sstevel@tonic-gate 	 */
18267c478bd9Sstevel@tonic-gate 	if (ibdm_send_classportinfo(gid_info) != IBDM_SUCCESS) {
182753c1b7a3Seota 
18287c478bd9Sstevel@tonic-gate 		mutex_enter(&gid_info->gl_mutex);
18297c478bd9Sstevel@tonic-gate 		gid_info->gl_state = IBDM_GID_PROBING_FAILED;
183053c1b7a3Seota 		--gid_info->gl_pending_cmds;
18317c478bd9Sstevel@tonic-gate 		mutex_exit(&gid_info->gl_mutex);
183253c1b7a3Seota 
183353c1b7a3Seota 		/* free the hca_list on this gid_info */
18347c478bd9Sstevel@tonic-gate 		ibdm_delete_glhca_list(gid_info);
183553c1b7a3Seota 
18367c478bd9Sstevel@tonic-gate 		mutex_enter(&ibdm.ibdm_mutex);
18377c478bd9Sstevel@tonic-gate 		--ibdm.ibdm_ngid_probes_in_progress;
18387c478bd9Sstevel@tonic-gate 		ibdm_wakeup_probe_gid_cv();
18397c478bd9Sstevel@tonic-gate 		mutex_exit(&ibdm.ibdm_mutex);
184053c1b7a3Seota 
18417c478bd9Sstevel@tonic-gate 		return;
18427c478bd9Sstevel@tonic-gate 	}
18437c478bd9Sstevel@tonic-gate }
18447c478bd9Sstevel@tonic-gate 
18457c478bd9Sstevel@tonic-gate 
18467c478bd9Sstevel@tonic-gate /*
18477c478bd9Sstevel@tonic-gate  * ibdm_check_dest_nodeguid
18487c478bd9Sstevel@tonic-gate  *	Searches for the NodeGuid in the GID list
18497c478bd9Sstevel@tonic-gate  *	Returns matching gid_info if found and otherwise NULL
18507c478bd9Sstevel@tonic-gate  *
18517c478bd9Sstevel@tonic-gate  *	This function is called to handle new GIDs discovered
18527c478bd9Sstevel@tonic-gate  *	during device sweep / probe or for GID_AVAILABLE event.
18537c478bd9Sstevel@tonic-gate  *
18547c478bd9Sstevel@tonic-gate  *	Parameter :
18557c478bd9Sstevel@tonic-gate  *		gid_info	GID to check
18567c478bd9Sstevel@tonic-gate  */
18577c478bd9Sstevel@tonic-gate static ibdm_dp_gidinfo_t *
ibdm_check_dest_nodeguid(ibdm_dp_gidinfo_t * gid_info)18587c478bd9Sstevel@tonic-gate ibdm_check_dest_nodeguid(ibdm_dp_gidinfo_t *gid_info)
18597c478bd9Sstevel@tonic-gate {
18607c478bd9Sstevel@tonic-gate 	ibdm_dp_gidinfo_t	*gid_list;
18617c478bd9Sstevel@tonic-gate 	ibdm_gid_t		*tmp;
18627c478bd9Sstevel@tonic-gate 
18637c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tcheck_dest_nodeguid");
18647c478bd9Sstevel@tonic-gate 
18657c478bd9Sstevel@tonic-gate 	gid_list = ibdm.ibdm_dp_gidlist_head;
18667c478bd9Sstevel@tonic-gate 	while (gid_list) {
18677c478bd9Sstevel@tonic-gate 		if ((gid_list != gid_info) &&
18687c478bd9Sstevel@tonic-gate 		    (gid_info->gl_nodeguid == gid_list->gl_nodeguid)) {
18697c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibdm",
18707c478bd9Sstevel@tonic-gate 			    "\tcheck_dest_nodeguid: NodeGuid is present");
18717c478bd9Sstevel@tonic-gate 
18727c478bd9Sstevel@tonic-gate 			/* Add to gid_list */
18737c478bd9Sstevel@tonic-gate 			tmp = kmem_zalloc(sizeof (ibdm_gid_t),
18747c478bd9Sstevel@tonic-gate 			    KM_SLEEP);
18757c478bd9Sstevel@tonic-gate 			tmp->gid_dgid_hi = gid_info->gl_dgid_hi;
18767c478bd9Sstevel@tonic-gate 			tmp->gid_dgid_lo = gid_info->gl_dgid_lo;
18777c478bd9Sstevel@tonic-gate 			tmp->gid_next = gid_list->gl_gid;
18787c478bd9Sstevel@tonic-gate 			gid_list->gl_gid = tmp;
18797c478bd9Sstevel@tonic-gate 			gid_list->gl_ngids++;
18807c478bd9Sstevel@tonic-gate 			return (gid_list);
18817c478bd9Sstevel@tonic-gate 		}
18827c478bd9Sstevel@tonic-gate 
18837c478bd9Sstevel@tonic-gate 		gid_list = gid_list->gl_next;
18847c478bd9Sstevel@tonic-gate 	}
18857c478bd9Sstevel@tonic-gate 
18867c478bd9Sstevel@tonic-gate 	return (NULL);
18877c478bd9Sstevel@tonic-gate }
18887c478bd9Sstevel@tonic-gate 
18897c478bd9Sstevel@tonic-gate 
18907c478bd9Sstevel@tonic-gate /*
18917c478bd9Sstevel@tonic-gate  * ibdm_is_dev_mgt_supported
18927c478bd9Sstevel@tonic-gate  *	Get the PortInfo attribute (SA Query)
18937c478bd9Sstevel@tonic-gate  *	Check "CompatabilityMask" field in the Portinfo.
18947c478bd9Sstevel@tonic-gate  *	Return IBDM_SUCCESS if DM MAD's supported (if bit 19 set)
18957c478bd9Sstevel@tonic-gate  *	by the port, otherwise IBDM_FAILURE
18967c478bd9Sstevel@tonic-gate  */
18977c478bd9Sstevel@tonic-gate static int
ibdm_is_dev_mgt_supported(ibdm_dp_gidinfo_t * gid_info)18987c478bd9Sstevel@tonic-gate ibdm_is_dev_mgt_supported(ibdm_dp_gidinfo_t *gid_info)
18997c478bd9Sstevel@tonic-gate {
19007c478bd9Sstevel@tonic-gate 	int			ret;
19017c478bd9Sstevel@tonic-gate 	size_t			length = 0;
19027c478bd9Sstevel@tonic-gate 	sa_portinfo_record_t	req, *resp = NULL;
19037c478bd9Sstevel@tonic-gate 	ibmf_saa_access_args_t	qargs;
19047c478bd9Sstevel@tonic-gate 
19057c478bd9Sstevel@tonic-gate 	bzero(&req, sizeof (sa_portinfo_record_t));
19067c478bd9Sstevel@tonic-gate 	req.EndportLID	= gid_info->gl_dlid;
19077c478bd9Sstevel@tonic-gate 
19087c478bd9Sstevel@tonic-gate 	qargs.sq_attr_id	= SA_PORTINFORECORD_ATTRID;
19097c478bd9Sstevel@tonic-gate 	qargs.sq_access_type	= IBMF_SAA_RETRIEVE;
19107c478bd9Sstevel@tonic-gate 	qargs.sq_component_mask = SA_PORTINFO_COMPMASK_PORTLID;
19117c478bd9Sstevel@tonic-gate 	qargs.sq_template	= &req;
19127c478bd9Sstevel@tonic-gate 	qargs.sq_callback	= NULL;
19137c478bd9Sstevel@tonic-gate 	qargs.sq_callback_arg	= NULL;
19147c478bd9Sstevel@tonic-gate 
19157c478bd9Sstevel@tonic-gate 	ret = ibmf_sa_access(gid_info->gl_sa_hdl,
19167c478bd9Sstevel@tonic-gate 	    &qargs, 0, &length, (void **)&resp);
19177c478bd9Sstevel@tonic-gate 
19187c478bd9Sstevel@tonic-gate 	if ((ret != IBMF_SUCCESS) || (length == 0) || (resp == NULL)) {
19197c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibdm", "\tis_dev_mgt_supported:"
19207c478bd9Sstevel@tonic-gate 		    "failed to get PORTINFO attribute %d", ret);
19217c478bd9Sstevel@tonic-gate 		return (IBDM_FAILURE);
19227c478bd9Sstevel@tonic-gate 	}
19237c478bd9Sstevel@tonic-gate 
19247c478bd9Sstevel@tonic-gate 	if (resp->PortInfo.CapabilityMask & SM_CAP_MASK_IS_DM_SUPPD) {
19257c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibdm", "\tis_dev_mgt_supported: SUPPD !!");
19267c478bd9Sstevel@tonic-gate 		ret = IBDM_SUCCESS;
19277c478bd9Sstevel@tonic-gate 	} else {
19287c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibdm", "\tis_dev_mgt_supported: "
19297c478bd9Sstevel@tonic-gate 		    "Not SUPPD !!, cap 0x%x", resp->PortInfo.CapabilityMask);
19307c478bd9Sstevel@tonic-gate 		ret = IBDM_FAILURE;
19317c478bd9Sstevel@tonic-gate 	}
19327c478bd9Sstevel@tonic-gate 	kmem_free(resp, length);
19337c478bd9Sstevel@tonic-gate 	return (ret);
19347c478bd9Sstevel@tonic-gate }
19357c478bd9Sstevel@tonic-gate 
19367c478bd9Sstevel@tonic-gate 
19377c478bd9Sstevel@tonic-gate /*
19387c478bd9Sstevel@tonic-gate  * ibdm_get_node_port_guids()
19397c478bd9Sstevel@tonic-gate  *	Get the NodeInfoRecord of the port
19407c478bd9Sstevel@tonic-gate  *	Save NodeGuid and PortGUID values in the GID list structure.
19417c478bd9Sstevel@tonic-gate  *	Return IBDM_SUCCESS/IBDM_FAILURE
19427c478bd9Sstevel@tonic-gate  */
19437c478bd9Sstevel@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)19447c478bd9Sstevel@tonic-gate ibdm_get_node_port_guids(ibmf_saa_handle_t sa_hdl, ib_lid_t dlid,
19457c478bd9Sstevel@tonic-gate     ib_guid_t *node_guid, ib_guid_t *port_guid)
19467c478bd9Sstevel@tonic-gate {
19477c478bd9Sstevel@tonic-gate 	int			ret;
19487c478bd9Sstevel@tonic-gate 	size_t			length = 0;
19497c478bd9Sstevel@tonic-gate 	sa_node_record_t	req, *resp = NULL;
19507c478bd9Sstevel@tonic-gate 	ibmf_saa_access_args_t	qargs;
19517c478bd9Sstevel@tonic-gate 
19527c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tget_node_port_guids");
19537c478bd9Sstevel@tonic-gate 
19547c478bd9Sstevel@tonic-gate 	bzero(&req, sizeof (sa_node_record_t));
19557c478bd9Sstevel@tonic-gate 	req.LID = dlid;
19567c478bd9Sstevel@tonic-gate 
19577c478bd9Sstevel@tonic-gate 	qargs.sq_attr_id	= SA_NODERECORD_ATTRID;
19587c478bd9Sstevel@tonic-gate 	qargs.sq_access_type	= IBMF_SAA_RETRIEVE;
19597c478bd9Sstevel@tonic-gate 	qargs.sq_component_mask = SA_NODEINFO_COMPMASK_NODELID;
19607c478bd9Sstevel@tonic-gate 	qargs.sq_template	= &req;
19617c478bd9Sstevel@tonic-gate 	qargs.sq_callback	= NULL;
19627c478bd9Sstevel@tonic-gate 	qargs.sq_callback_arg	= NULL;
19637c478bd9Sstevel@tonic-gate 
19647c478bd9Sstevel@tonic-gate 	ret = ibmf_sa_access(sa_hdl, &qargs, 0, &length, (void **)&resp);
19657c478bd9Sstevel@tonic-gate 	if ((ret != IBMF_SUCCESS) || (length == 0) || (resp == NULL)) {
19667c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibdm", "\tget_node_port_guids:"
19677c478bd9Sstevel@tonic-gate 		    " SA Retrieve Failed: %d", ret);
19687c478bd9Sstevel@tonic-gate 		return (IBDM_FAILURE);
19697c478bd9Sstevel@tonic-gate 	}
19707c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tget_node_port_guids: NodeGuid %llx Port"
19717c478bd9Sstevel@tonic-gate 	    "GUID %llx", resp->NodeInfo.NodeGUID, resp->NodeInfo.NodeGUID);
19727c478bd9Sstevel@tonic-gate 
19737c478bd9Sstevel@tonic-gate 	*node_guid = resp->NodeInfo.NodeGUID;
19747c478bd9Sstevel@tonic-gate 	*port_guid = resp->NodeInfo.PortGUID;
19757c478bd9Sstevel@tonic-gate 	kmem_free(resp, length);
19767c478bd9Sstevel@tonic-gate 	return (IBDM_SUCCESS);
19777c478bd9Sstevel@tonic-gate }
19787c478bd9Sstevel@tonic-gate 
19797c478bd9Sstevel@tonic-gate 
19807c478bd9Sstevel@tonic-gate /*
19817c478bd9Sstevel@tonic-gate  * ibdm_get_reachable_ports()
19827c478bd9Sstevel@tonic-gate  *	Get list of the destination GID (and its path  records) by
19837c478bd9Sstevel@tonic-gate  *	querying the SA access.
19847c478bd9Sstevel@tonic-gate  *
19857c478bd9Sstevel@tonic-gate  *	Returns Number paths
19867c478bd9Sstevel@tonic-gate  */
19877c478bd9Sstevel@tonic-gate static int
ibdm_get_reachable_ports(ibdm_port_attr_t * portinfo,ibdm_hca_list_t * hca)19887c478bd9Sstevel@tonic-gate ibdm_get_reachable_ports(ibdm_port_attr_t *portinfo, ibdm_hca_list_t *hca)
19897c478bd9Sstevel@tonic-gate {
19907c478bd9Sstevel@tonic-gate 	uint_t			ii, jj, nrecs;
19917c478bd9Sstevel@tonic-gate 	uint_t			npaths = 0;
19927c478bd9Sstevel@tonic-gate 	size_t			length;
19937c478bd9Sstevel@tonic-gate 	ib_gid_t		sgid;
19947c478bd9Sstevel@tonic-gate 	ibdm_pkey_tbl_t		*pkey_tbl;
19957c478bd9Sstevel@tonic-gate 	sa_path_record_t	*result;
19967c478bd9Sstevel@tonic-gate 	sa_path_record_t	*precp;
19977c478bd9Sstevel@tonic-gate 	ibdm_dp_gidinfo_t	*gid_info;
19987c478bd9Sstevel@tonic-gate 
19997c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ibdm.ibdm_hl_mutex));
20007c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tget_reachable_ports: portinfo %p", portinfo);
20017c478bd9Sstevel@tonic-gate 
20027c478bd9Sstevel@tonic-gate 	sgid.gid_prefix = portinfo->pa_sn_prefix;
20037c478bd9Sstevel@tonic-gate 	sgid.gid_guid	= portinfo->pa_port_guid;
20047c478bd9Sstevel@tonic-gate 
20057c478bd9Sstevel@tonic-gate 	/* get reversible paths */
20067c478bd9Sstevel@tonic-gate 	if (portinfo->pa_sa_hdl && ibmf_saa_paths_from_gid(portinfo->pa_sa_hdl,
20077c478bd9Sstevel@tonic-gate 	    sgid, IBMF_SAA_PKEY_WC, B_TRUE, 0, &nrecs, &length, &result)
20087c478bd9Sstevel@tonic-gate 	    != IBMF_SUCCESS) {
20097c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibdm",
20107c478bd9Sstevel@tonic-gate 		    "\tget_reachable_ports: Getting path records failed");
20117c478bd9Sstevel@tonic-gate 		return (0);
20127c478bd9Sstevel@tonic-gate 	}
20137c478bd9Sstevel@tonic-gate 
20147c478bd9Sstevel@tonic-gate 	for (ii = 0; ii < nrecs; ii++) {
201553c1b7a3Seota 		sa_node_record_t *nrec;
201653c1b7a3Seota 		size_t length;
201753c1b7a3Seota 
20187c478bd9Sstevel@tonic-gate 		precp = &result[ii];
20197c478bd9Sstevel@tonic-gate 		if ((gid_info = ibdm_check_dgid(precp->DGID.gid_guid,
20207c478bd9Sstevel@tonic-gate 		    precp->DGID.gid_prefix)) != NULL) {
2021a1e3386eShiremath 			IBTF_DPRINTF_L5("ibdm", "\tget_reachable_ports: "
20227c478bd9Sstevel@tonic-gate 			    "Already exists nrecs %d, ii %d", nrecs, ii);
20237c478bd9Sstevel@tonic-gate 			ibdm_addto_glhcalist(gid_info, hca);
20247c478bd9Sstevel@tonic-gate 			continue;
20257c478bd9Sstevel@tonic-gate 		}
20267c478bd9Sstevel@tonic-gate 		/*
20277c478bd9Sstevel@tonic-gate 		 * This is a new GID. Allocate a GID structure and
20287c478bd9Sstevel@tonic-gate 		 * initialize the structure
20297c478bd9Sstevel@tonic-gate 		 * gl_state is initialized to IBDM_GID_PROBE_NOT_DONE (0)
20307c478bd9Sstevel@tonic-gate 		 * by kmem_zalloc call
20317c478bd9Sstevel@tonic-gate 		 */
20327c478bd9Sstevel@tonic-gate 		gid_info = kmem_zalloc(sizeof (ibdm_dp_gidinfo_t), KM_SLEEP);
20337c478bd9Sstevel@tonic-gate 		mutex_init(&gid_info->gl_mutex, NULL, MUTEX_DEFAULT, NULL);
203453c1b7a3Seota 		cv_init(&gid_info->gl_probe_cv, NULL, CV_DRIVER, NULL);
20357c478bd9Sstevel@tonic-gate 		gid_info->gl_dgid_hi		= precp->DGID.gid_prefix;
20367c478bd9Sstevel@tonic-gate 		gid_info->gl_dgid_lo		= precp->DGID.gid_guid;
20377c478bd9Sstevel@tonic-gate 		gid_info->gl_sgid_hi		= precp->SGID.gid_prefix;
20387c478bd9Sstevel@tonic-gate 		gid_info->gl_sgid_lo		= precp->SGID.gid_guid;
20397c478bd9Sstevel@tonic-gate 		gid_info->gl_p_key		= precp->P_Key;
20407c478bd9Sstevel@tonic-gate 		gid_info->gl_sa_hdl		= portinfo->pa_sa_hdl;
20417c478bd9Sstevel@tonic-gate 		gid_info->gl_ibmf_hdl		= portinfo->pa_ibmf_hdl;
20427c478bd9Sstevel@tonic-gate 		gid_info->gl_slid		= precp->SLID;
20437c478bd9Sstevel@tonic-gate 		gid_info->gl_dlid		= precp->DLID;
20449d3d2ed0Shiremath 		gid_info->gl_transactionID	= (++ibdm.ibdm_transactionID)
20459d3d2ed0Shiremath 		    << IBDM_GID_TRANSACTIONID_SHIFT;
20469d3d2ed0Shiremath 		gid_info->gl_min_transactionID  = gid_info->gl_transactionID;
20479d3d2ed0Shiremath 		gid_info->gl_max_transactionID  = (ibdm.ibdm_transactionID +1)
20489d3d2ed0Shiremath 		    << IBDM_GID_TRANSACTIONID_SHIFT;
204918edb70cSeota 		gid_info->gl_SL			= precp->SL;
205053c1b7a3Seota 
205153c1b7a3Seota 		/*
205253c1b7a3Seota 		 * get the node record with this guid if the destination
205353c1b7a3Seota 		 * device is a Cisco one.
205453c1b7a3Seota 		 */
205553c1b7a3Seota 		if (ibdm_is_cisco(precp->DGID.gid_guid) &&
205653c1b7a3Seota 		    (gid_info->gl_nodeguid == 0 || gid_info->gl_devid == 0) &&
205753c1b7a3Seota 		    ibdm_get_node_record_by_port(portinfo->pa_sa_hdl,
205853c1b7a3Seota 		    precp->DGID.gid_guid, &nrec, &length) == IBDM_SUCCESS) {
205953c1b7a3Seota 			gid_info->gl_nodeguid = nrec->NodeInfo.NodeGUID;
206053c1b7a3Seota 			gid_info->gl_devid = nrec->NodeInfo.DeviceID;
206153c1b7a3Seota 			kmem_free(nrec, length);
206253c1b7a3Seota 		}
206353c1b7a3Seota 
20647c478bd9Sstevel@tonic-gate 		ibdm_addto_glhcalist(gid_info,  hca);
20657c478bd9Sstevel@tonic-gate 
20667c478bd9Sstevel@tonic-gate 		ibdm_dump_path_info(precp);
20677c478bd9Sstevel@tonic-gate 
20687c478bd9Sstevel@tonic-gate 		gid_info->gl_qp_hdl = NULL;
20699d3d2ed0Shiremath 		ASSERT(portinfo->pa_pkey_tbl != NULL &&
20709d3d2ed0Shiremath 		    portinfo->pa_npkeys != 0);
20717c478bd9Sstevel@tonic-gate 
20727c478bd9Sstevel@tonic-gate 		for (jj = 0; jj < portinfo->pa_npkeys; jj++) {
20737c478bd9Sstevel@tonic-gate 			pkey_tbl = &portinfo->pa_pkey_tbl[jj];
20747c478bd9Sstevel@tonic-gate 			if ((gid_info->gl_p_key == pkey_tbl->pt_pkey) &&
20757c478bd9Sstevel@tonic-gate 			    (pkey_tbl->pt_qp_hdl != NULL)) {
20767c478bd9Sstevel@tonic-gate 				gid_info->gl_qp_hdl = pkey_tbl->pt_qp_hdl;
20777c478bd9Sstevel@tonic-gate 				break;
20787c478bd9Sstevel@tonic-gate 			}
20797c478bd9Sstevel@tonic-gate 		}
20807c478bd9Sstevel@tonic-gate 
20819d3d2ed0Shiremath 		/*
20829d3d2ed0Shiremath 		 * QP handle for GID not initialized. No matching Pkey
20839d3d2ed0Shiremath 		 * was found!! ibdm should *not* hit this case. Flag an
20849d3d2ed0Shiremath 		 * error and drop the GID if ibdm does encounter this.
20859d3d2ed0Shiremath 		 */
20867c478bd9Sstevel@tonic-gate 		if (gid_info->gl_qp_hdl == NULL) {
20879d3d2ed0Shiremath 			IBTF_DPRINTF_L2(ibdm_string,
20889d3d2ed0Shiremath 			    "\tget_reachable_ports: No matching Pkey");
20899d3d2ed0Shiremath 			ibdm_delete_gidinfo(gid_info);
20907c478bd9Sstevel@tonic-gate 			continue;
20917c478bd9Sstevel@tonic-gate 		}
20927c478bd9Sstevel@tonic-gate 		if (ibdm.ibdm_dp_gidlist_head == NULL) {
20937c478bd9Sstevel@tonic-gate 			ibdm.ibdm_dp_gidlist_head = gid_info;
20947c478bd9Sstevel@tonic-gate 			ibdm.ibdm_dp_gidlist_tail = gid_info;
20957c478bd9Sstevel@tonic-gate 		} else {
20967c478bd9Sstevel@tonic-gate 			ibdm.ibdm_dp_gidlist_tail->gl_next = gid_info;
20977c478bd9Sstevel@tonic-gate 			gid_info->gl_prev = ibdm.ibdm_dp_gidlist_tail;
20987c478bd9Sstevel@tonic-gate 			ibdm.ibdm_dp_gidlist_tail = gid_info;
20997c478bd9Sstevel@tonic-gate 		}
21007c478bd9Sstevel@tonic-gate 		npaths++;
21017c478bd9Sstevel@tonic-gate 	}
21027c478bd9Sstevel@tonic-gate 	kmem_free(result, length);
21037c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tget_reachable_ports: npaths = %d", npaths);
21047c478bd9Sstevel@tonic-gate 	return (npaths);
21057c478bd9Sstevel@tonic-gate }
21067c478bd9Sstevel@tonic-gate 
21077c478bd9Sstevel@tonic-gate 
21087c478bd9Sstevel@tonic-gate /*
21097c478bd9Sstevel@tonic-gate  * ibdm_check_dgid()
21107c478bd9Sstevel@tonic-gate  *	Look in the global list to check whether we know this DGID already
21117c478bd9Sstevel@tonic-gate  *	Return IBDM_GID_PRESENT/IBDM_GID_NOT_PRESENT
21127c478bd9Sstevel@tonic-gate  */
21137c478bd9Sstevel@tonic-gate static ibdm_dp_gidinfo_t *
ibdm_check_dgid(ib_guid_t guid,ib_sn_prefix_t prefix)21147c478bd9Sstevel@tonic-gate ibdm_check_dgid(ib_guid_t guid, ib_sn_prefix_t prefix)
21157c478bd9Sstevel@tonic-gate {
21167c478bd9Sstevel@tonic-gate 	ibdm_dp_gidinfo_t	*gid_list;
21177c478bd9Sstevel@tonic-gate 
21187c478bd9Sstevel@tonic-gate 	for (gid_list = ibdm.ibdm_dp_gidlist_head; gid_list;
21197c478bd9Sstevel@tonic-gate 	    gid_list = gid_list->gl_next) {
21207c478bd9Sstevel@tonic-gate 		if ((guid == gid_list->gl_dgid_lo) &&
21217c478bd9Sstevel@tonic-gate 		    (prefix == gid_list->gl_dgid_hi)) {
21227c478bd9Sstevel@tonic-gate 			break;
21237c478bd9Sstevel@tonic-gate 		}
21247c478bd9Sstevel@tonic-gate 	}
21257c478bd9Sstevel@tonic-gate 	return (gid_list);
21267c478bd9Sstevel@tonic-gate }
21277c478bd9Sstevel@tonic-gate 
21287c478bd9Sstevel@tonic-gate 
21297c478bd9Sstevel@tonic-gate /*
21307c478bd9Sstevel@tonic-gate  * ibdm_find_gid()
21317c478bd9Sstevel@tonic-gate  *	Look in the global list to find a GID entry with matching
21327c478bd9Sstevel@tonic-gate  *	port & node GUID.
21337c478bd9Sstevel@tonic-gate  *	Return pointer to gidinfo if found, else return NULL
21347c478bd9Sstevel@tonic-gate  */
21357c478bd9Sstevel@tonic-gate static ibdm_dp_gidinfo_t *
ibdm_find_gid(ib_guid_t nodeguid,ib_guid_t portguid)21367c478bd9Sstevel@tonic-gate ibdm_find_gid(ib_guid_t nodeguid, ib_guid_t portguid)
21377c478bd9Sstevel@tonic-gate {
21387c478bd9Sstevel@tonic-gate 	ibdm_dp_gidinfo_t	*gid_list;
21397c478bd9Sstevel@tonic-gate 
21407c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "ibdm_find_gid(%llx, %llx)\n",
21417c478bd9Sstevel@tonic-gate 	    nodeguid, portguid);
21427c478bd9Sstevel@tonic-gate 
21437c478bd9Sstevel@tonic-gate 	for (gid_list = ibdm.ibdm_dp_gidlist_head; gid_list;
21447c478bd9Sstevel@tonic-gate 	    gid_list = gid_list->gl_next) {
21457c478bd9Sstevel@tonic-gate 		if ((portguid == gid_list->gl_portguid) &&
21467c478bd9Sstevel@tonic-gate 		    (nodeguid == gid_list->gl_nodeguid)) {
21477c478bd9Sstevel@tonic-gate 			break;
21487c478bd9Sstevel@tonic-gate 		}
21497c478bd9Sstevel@tonic-gate 	}
21507c478bd9Sstevel@tonic-gate 
21517c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "ibdm_find_gid : returned %p\n",
21527c478bd9Sstevel@tonic-gate 	    gid_list);
21537c478bd9Sstevel@tonic-gate 	return (gid_list);
21547c478bd9Sstevel@tonic-gate }
21557c478bd9Sstevel@tonic-gate 
21567c478bd9Sstevel@tonic-gate 
215753c1b7a3Seota /*
215853c1b7a3Seota  * ibdm_set_classportinfo()
215953c1b7a3Seota  *	ibdm_set_classportinfo() is a function to activate a Cisco FC GW
216053c1b7a3Seota  *	by sending the setClassPortInfo request with the trapLID, trapGID
216153c1b7a3Seota  *	and etc. to the gateway since the gateway doesn't provide the IO
216253c1b7a3Seota  *	Unit Information othewise. This behavior is the Cisco specific one,
216353c1b7a3Seota  *	and this function is called to a Cisco FC GW only.
216453c1b7a3Seota  *	Returns IBDM_SUCCESS/IBDM_FAILURE
216553c1b7a3Seota  */
216653c1b7a3Seota static int
ibdm_set_classportinfo(ibdm_dp_gidinfo_t * gid_info)216753c1b7a3Seota ibdm_set_classportinfo(ibdm_dp_gidinfo_t *gid_info)
216853c1b7a3Seota {
216953c1b7a3Seota 	ibmf_msg_t		*msg;
217053c1b7a3Seota 	ib_mad_hdr_t		*hdr;
217153c1b7a3Seota 	ibdm_timeout_cb_args_t	*cb_args;
217253c1b7a3Seota 	void			*data;
217353c1b7a3Seota 	ib_mad_classportinfo_t *cpi;
217453c1b7a3Seota 
217553c1b7a3Seota 	IBTF_DPRINTF_L4("ibdm",
217653c1b7a3Seota 	    "\tset_classportinfo: gid info 0x%p", gid_info);
217753c1b7a3Seota 
217853c1b7a3Seota 	/*
217953c1b7a3Seota 	 * Send command to set classportinfo attribute. Allocate a IBMF
218053c1b7a3Seota 	 * packet and initialize the packet.
218153c1b7a3Seota 	 */
218253c1b7a3Seota 	if (ibmf_alloc_msg(gid_info->gl_ibmf_hdl, IBMF_ALLOC_SLEEP,
218353c1b7a3Seota 	    &msg) != IBMF_SUCCESS) {
218453c1b7a3Seota 		IBTF_DPRINTF_L4("ibdm", "\tset_classportinfo: pkt alloc fail");
218553c1b7a3Seota 		return (IBDM_FAILURE);
218653c1b7a3Seota 	}
218753c1b7a3Seota 
218818edb70cSeota 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*msg))
218953c1b7a3Seota 	ibdm_alloc_send_buffers(msg);
219018edb70cSeota 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*msg))
219153c1b7a3Seota 
219253c1b7a3Seota 	msg->im_local_addr.ia_local_lid		= gid_info->gl_slid;
219353c1b7a3Seota 	msg->im_local_addr.ia_remote_lid	= gid_info->gl_dlid;
219453c1b7a3Seota 	msg->im_local_addr.ia_remote_qno	= 1;
219553c1b7a3Seota 	msg->im_local_addr.ia_p_key		= gid_info->gl_p_key;
219653c1b7a3Seota 	msg->im_local_addr.ia_q_key		= IB_GSI_QKEY;
219718edb70cSeota 	msg->im_local_addr.ia_service_level	= gid_info->gl_SL;
219853c1b7a3Seota 
219953c1b7a3Seota 	hdr			= IBDM_OUT_IBMFMSG_MADHDR(msg);
220053c1b7a3Seota 	hdr->BaseVersion	= MAD_CLASS_BASE_VERS_1;
220153c1b7a3Seota 	hdr->MgmtClass		= MAD_MGMT_CLASS_DEV_MGT;
220253c1b7a3Seota 	hdr->ClassVersion	= IB_DM_CLASS_VERSION_1;
220353c1b7a3Seota 	hdr->R_Method		= IB_DM_DEVMGT_METHOD_SET;
220453c1b7a3Seota 	hdr->Status		= 0;
220553c1b7a3Seota 	hdr->TransactionID	= h2b64(gid_info->gl_transactionID);
220653c1b7a3Seota 	hdr->AttributeID	= h2b16(IB_DM_ATTR_CLASSPORTINFO);
220753c1b7a3Seota 	hdr->AttributeModifier	= 0;
220853c1b7a3Seota 
220953c1b7a3Seota 	data = msg->im_msgbufs_send.im_bufs_cl_data;
221053c1b7a3Seota 	cpi = (ib_mad_classportinfo_t *)data;
221153c1b7a3Seota 
221253c1b7a3Seota 	/*
221353c1b7a3Seota 	 * Set the classportinfo values to activate this Cisco FC GW.
221453c1b7a3Seota 	 */
221553c1b7a3Seota 	cpi->TrapGID_hi = h2b64(gid_info->gl_sgid_hi);
221653c1b7a3Seota 	cpi->TrapGID_lo = h2b64(gid_info->gl_sgid_lo);
221753c1b7a3Seota 	cpi->TrapLID = h2b16(gid_info->gl_slid);
221818edb70cSeota 	cpi->TrapSL = gid_info->gl_SL;
221953c1b7a3Seota 	cpi->TrapP_Key = h2b16(gid_info->gl_p_key);
222053c1b7a3Seota 	cpi->TrapQP = h2b32((((ibmf_alt_qp_t *)gid_info->gl_qp_hdl)->isq_qpn));
222153c1b7a3Seota 	cpi->TrapQ_Key = h2b32((((ibmf_alt_qp_t *)
222253c1b7a3Seota 	    gid_info->gl_qp_hdl)->isq_qkey));
222353c1b7a3Seota 
222453c1b7a3Seota 	cb_args = &gid_info->gl_cpi_cb_args;
222553c1b7a3Seota 	cb_args->cb_gid_info = gid_info;
222653c1b7a3Seota 	cb_args->cb_retry_count	= ibdm_dft_retry_cnt;
222753c1b7a3Seota 	cb_args->cb_req_type = IBDM_REQ_TYPE_CLASSPORTINFO;
222853c1b7a3Seota 
222918edb70cSeota 	mutex_enter(&gid_info->gl_mutex);
223053c1b7a3Seota 	gid_info->gl_timeout_id = timeout(ibdm_pkt_timeout_hdlr,
223153c1b7a3Seota 	    cb_args, IBDM_TIMEOUT_VALUE(ibdm_dft_timeout));
223218edb70cSeota 	mutex_exit(&gid_info->gl_mutex);
223353c1b7a3Seota 
223453c1b7a3Seota 	IBTF_DPRINTF_L5("ibdm", "\tset_classportinfo: "
223553c1b7a3Seota 	    "timeout id %x", gid_info->gl_timeout_id);
223653c1b7a3Seota 
223753c1b7a3Seota 	if (ibmf_msg_transport(gid_info->gl_ibmf_hdl, gid_info->gl_qp_hdl,
223853c1b7a3Seota 	    msg, NULL, ibdm_ibmf_send_cb, cb_args, 0) != IBMF_SUCCESS) {
223953c1b7a3Seota 		IBTF_DPRINTF_L2("ibdm",
224053c1b7a3Seota 		    "\tset_classportinfo: ibmf send failed");
224153c1b7a3Seota 		ibdm_ibmf_send_cb(gid_info->gl_ibmf_hdl, msg, cb_args);
224253c1b7a3Seota 	}
224353c1b7a3Seota 
224453c1b7a3Seota 	return (IBDM_SUCCESS);
224553c1b7a3Seota }
224653c1b7a3Seota 
224753c1b7a3Seota 
22487c478bd9Sstevel@tonic-gate /*
22497c478bd9Sstevel@tonic-gate  * ibdm_send_classportinfo()
22507c478bd9Sstevel@tonic-gate  *	Send classportinfo request. When the request is completed
22517c478bd9Sstevel@tonic-gate  *	IBMF calls ibdm_classportinfo_cb routine to inform about
22527c478bd9Sstevel@tonic-gate  *	the completion.
22537c478bd9Sstevel@tonic-gate  *	Returns IBDM_SUCCESS/IBDM_FAILURE
22547c478bd9Sstevel@tonic-gate  */
22557c478bd9Sstevel@tonic-gate static int
ibdm_send_classportinfo(ibdm_dp_gidinfo_t * gid_info)22567c478bd9Sstevel@tonic-gate ibdm_send_classportinfo(ibdm_dp_gidinfo_t *gid_info)
22577c478bd9Sstevel@tonic-gate {
22587c478bd9Sstevel@tonic-gate 	ibmf_msg_t		*msg;
22597c478bd9Sstevel@tonic-gate 	ib_mad_hdr_t		*hdr;
22607c478bd9Sstevel@tonic-gate 	ibdm_timeout_cb_args_t	*cb_args;
22617c478bd9Sstevel@tonic-gate 
22627c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm",
22637c478bd9Sstevel@tonic-gate 	    "\tsend_classportinfo: gid info 0x%p", gid_info);
22647c478bd9Sstevel@tonic-gate 
22657c478bd9Sstevel@tonic-gate 	/*
22667c478bd9Sstevel@tonic-gate 	 * Send command to get classportinfo attribute. Allocate a IBMF
22677c478bd9Sstevel@tonic-gate 	 * packet and initialize the packet.
22687c478bd9Sstevel@tonic-gate 	 */
22697c478bd9Sstevel@tonic-gate 	if (ibmf_alloc_msg(gid_info->gl_ibmf_hdl, IBMF_ALLOC_SLEEP,
22707c478bd9Sstevel@tonic-gate 	    &msg) != IBMF_SUCCESS) {
22717c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibdm", "\tsend_classportinfo: pkt alloc fail");
22727c478bd9Sstevel@tonic-gate 		return (IBDM_FAILURE);
22737c478bd9Sstevel@tonic-gate 	}
22747c478bd9Sstevel@tonic-gate 
227518edb70cSeota 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*msg))
22767c478bd9Sstevel@tonic-gate 	ibdm_alloc_send_buffers(msg);
227718edb70cSeota 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*msg))
22787c478bd9Sstevel@tonic-gate 
22797c478bd9Sstevel@tonic-gate 	msg->im_local_addr.ia_local_lid		= gid_info->gl_slid;
22807c478bd9Sstevel@tonic-gate 	msg->im_local_addr.ia_remote_lid	= gid_info->gl_dlid;
22817c478bd9Sstevel@tonic-gate 	msg->im_local_addr.ia_remote_qno	= 1;
22827c478bd9Sstevel@tonic-gate 	msg->im_local_addr.ia_p_key		= gid_info->gl_p_key;
22837c478bd9Sstevel@tonic-gate 	msg->im_local_addr.ia_q_key		= IB_GSI_QKEY;
228418edb70cSeota 	msg->im_local_addr.ia_service_level	= gid_info->gl_SL;
22857c478bd9Sstevel@tonic-gate 
22867c478bd9Sstevel@tonic-gate 	hdr			= IBDM_OUT_IBMFMSG_MADHDR(msg);
22877c478bd9Sstevel@tonic-gate 	hdr->BaseVersion	= MAD_CLASS_BASE_VERS_1;
22887c478bd9Sstevel@tonic-gate 	hdr->MgmtClass		= MAD_MGMT_CLASS_DEV_MGT;
22897c478bd9Sstevel@tonic-gate 	hdr->ClassVersion	= IB_DM_CLASS_VERSION_1;
22907c478bd9Sstevel@tonic-gate 	hdr->R_Method		= IB_DM_DEVMGT_METHOD_GET;
22917c478bd9Sstevel@tonic-gate 	hdr->Status		= 0;
22927c478bd9Sstevel@tonic-gate 	hdr->TransactionID	= h2b64(gid_info->gl_transactionID);
22937c478bd9Sstevel@tonic-gate 	hdr->AttributeID	= h2b16(IB_DM_ATTR_CLASSPORTINFO);
22947c478bd9Sstevel@tonic-gate 	hdr->AttributeModifier	= 0;
22957c478bd9Sstevel@tonic-gate 
22967c478bd9Sstevel@tonic-gate 	cb_args = &gid_info->gl_cpi_cb_args;
22977c478bd9Sstevel@tonic-gate 	cb_args->cb_gid_info = gid_info;
22987c478bd9Sstevel@tonic-gate 	cb_args->cb_retry_count	= ibdm_dft_retry_cnt;
22997c478bd9Sstevel@tonic-gate 	cb_args->cb_req_type = IBDM_REQ_TYPE_CLASSPORTINFO;
23007c478bd9Sstevel@tonic-gate 
230118edb70cSeota 	mutex_enter(&gid_info->gl_mutex);
23027c478bd9Sstevel@tonic-gate 	gid_info->gl_timeout_id = timeout(ibdm_pkt_timeout_hdlr,
23037c478bd9Sstevel@tonic-gate 	    cb_args, IBDM_TIMEOUT_VALUE(ibdm_dft_timeout));
230418edb70cSeota 	mutex_exit(&gid_info->gl_mutex);
23057c478bd9Sstevel@tonic-gate 
23067c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L5("ibdm", "\tsend_classportinfo: "
23077c478bd9Sstevel@tonic-gate 	    "timeout id %x", gid_info->gl_timeout_id);
23087c478bd9Sstevel@tonic-gate 
23097c478bd9Sstevel@tonic-gate 	if (ibmf_msg_transport(gid_info->gl_ibmf_hdl, gid_info->gl_qp_hdl,
23107c478bd9Sstevel@tonic-gate 	    msg, NULL, ibdm_ibmf_send_cb, cb_args, 0) != IBMF_SUCCESS) {
23117c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibdm",
23127c478bd9Sstevel@tonic-gate 		    "\tsend_classportinfo: ibmf send failed");
23137c478bd9Sstevel@tonic-gate 		ibdm_ibmf_send_cb(gid_info->gl_ibmf_hdl, msg, cb_args);
23147c478bd9Sstevel@tonic-gate 	}
23157c478bd9Sstevel@tonic-gate 
23167c478bd9Sstevel@tonic-gate 	return (IBDM_SUCCESS);
23177c478bd9Sstevel@tonic-gate }
23187c478bd9Sstevel@tonic-gate 
23197c478bd9Sstevel@tonic-gate 
232053c1b7a3Seota /*
232153c1b7a3Seota  * ibdm_handle_setclassportinfo()
232253c1b7a3Seota  *	Invoked by the IBMF when setClassPortInfo request is completed.
232353c1b7a3Seota  */
232453c1b7a3Seota static void
ibdm_handle_setclassportinfo(ibmf_handle_t ibmf_hdl,ibmf_msg_t * msg,ibdm_dp_gidinfo_t * gid_info,int * flag)232553c1b7a3Seota ibdm_handle_setclassportinfo(ibmf_handle_t ibmf_hdl,
232653c1b7a3Seota     ibmf_msg_t *msg, ibdm_dp_gidinfo_t *gid_info, int *flag)
232753c1b7a3Seota {
232853c1b7a3Seota 	void			*data;
232953c1b7a3Seota 	timeout_id_t		timeout_id;
233053c1b7a3Seota 	ib_mad_classportinfo_t *cpi;
233153c1b7a3Seota 
233253c1b7a3Seota 	IBTF_DPRINTF_L4("ibdm", "\thandle_setclassportinfo:ibmf hdl "
233353c1b7a3Seota 	    "%p msg %p gid info %p", ibmf_hdl, msg, gid_info);
233453c1b7a3Seota 
233553c1b7a3Seota 	if (IBDM_IN_IBMFMSG_ATTR(msg) != IB_DM_ATTR_CLASSPORTINFO) {
233653c1b7a3Seota 		IBTF_DPRINTF_L4("ibdm", "\thandle_setclassportinfo: "
233753c1b7a3Seota 		    "Not a ClassPortInfo resp");
233853c1b7a3Seota 		*flag |= IBDM_IBMF_PKT_UNEXP_RESP;
233953c1b7a3Seota 		return;
234053c1b7a3Seota 	}
234153c1b7a3Seota 
234253c1b7a3Seota 	/*
234353c1b7a3Seota 	 * Verify whether timeout handler is created/active.
234453c1b7a3Seota 	 * If created/ active,  cancel the timeout  handler
234553c1b7a3Seota 	 */
234653c1b7a3Seota 	mutex_enter(&gid_info->gl_mutex);
234753c1b7a3Seota 	if (gid_info->gl_state != IBDM_SET_CLASSPORTINFO) {
234853c1b7a3Seota 		IBTF_DPRINTF_L2("ibdm", "\thandle_setclassportinfo:DUP resp");
234953c1b7a3Seota 		*flag |= IBDM_IBMF_PKT_DUP_RESP;
235053c1b7a3Seota 		mutex_exit(&gid_info->gl_mutex);
235153c1b7a3Seota 		return;
235253c1b7a3Seota 	}
235353c1b7a3Seota 	ibdm_bump_transactionID(gid_info);
235453c1b7a3Seota 
235553c1b7a3Seota 	gid_info->gl_iou_cb_args.cb_req_type = 0;
235653c1b7a3Seota 	if (gid_info->gl_timeout_id) {
235753c1b7a3Seota 		timeout_id = gid_info->gl_timeout_id;
235853c1b7a3Seota 		mutex_exit(&gid_info->gl_mutex);
235953c1b7a3Seota 		IBTF_DPRINTF_L5("ibdm", "handle_setlassportinfo: "
236053c1b7a3Seota 		    "gl_timeout_id = 0x%x", timeout_id);
236153c1b7a3Seota 		if (untimeout(timeout_id) == -1) {
236253c1b7a3Seota 			IBTF_DPRINTF_L2("ibdm", "handle_setclassportinfo: "
236353c1b7a3Seota 			    "untimeout gl_timeout_id failed");
236453c1b7a3Seota 		}
236553c1b7a3Seota 		mutex_enter(&gid_info->gl_mutex);
236653c1b7a3Seota 		gid_info->gl_timeout_id = 0;
236753c1b7a3Seota 	}
236853c1b7a3Seota 	mutex_exit(&gid_info->gl_mutex);
236953c1b7a3Seota 
237053c1b7a3Seota 	data = msg->im_msgbufs_recv.im_bufs_cl_data;
237153c1b7a3Seota 	cpi = (ib_mad_classportinfo_t *)data;
237253c1b7a3Seota 
237353c1b7a3Seota 	ibdm_dump_classportinfo(cpi);
237453c1b7a3Seota }
237553c1b7a3Seota 
237653c1b7a3Seota 
23777c478bd9Sstevel@tonic-gate /*
23787c478bd9Sstevel@tonic-gate  * ibdm_handle_classportinfo()
23797c478bd9Sstevel@tonic-gate  *	Invoked by the IBMF when the classportinfo request is completed.
23807c478bd9Sstevel@tonic-gate  */
23817c478bd9Sstevel@tonic-gate static void
ibdm_handle_classportinfo(ibmf_handle_t ibmf_hdl,ibmf_msg_t * msg,ibdm_dp_gidinfo_t * gid_info,int * flag)23827c478bd9Sstevel@tonic-gate ibdm_handle_classportinfo(ibmf_handle_t ibmf_hdl,
23837c478bd9Sstevel@tonic-gate     ibmf_msg_t *msg, ibdm_dp_gidinfo_t *gid_info, int *flag)
23847c478bd9Sstevel@tonic-gate {
23857c478bd9Sstevel@tonic-gate 	void			*data;
23867c478bd9Sstevel@tonic-gate 	timeout_id_t		timeout_id;
23877c478bd9Sstevel@tonic-gate 	ib_mad_hdr_t		*hdr;
238853c1b7a3Seota 	ib_mad_classportinfo_t *cpi;
23897c478bd9Sstevel@tonic-gate 
23907c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\thandle_classportinfo:ibmf hdl "
23917c478bd9Sstevel@tonic-gate 	    "%p msg %p gid info %p", ibmf_hdl, msg, gid_info);
23927c478bd9Sstevel@tonic-gate 
23937c478bd9Sstevel@tonic-gate 	if (IBDM_IN_IBMFMSG_ATTR(msg) != IB_DM_ATTR_CLASSPORTINFO) {
23947c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibdm", "\thandle_classportinfo: "
23957c478bd9Sstevel@tonic-gate 		    "Not a ClassPortInfo resp");
23967c478bd9Sstevel@tonic-gate 		*flag |= IBDM_IBMF_PKT_UNEXP_RESP;
23977c478bd9Sstevel@tonic-gate 		return;
23987c478bd9Sstevel@tonic-gate 	}
23997c478bd9Sstevel@tonic-gate 
24007c478bd9Sstevel@tonic-gate 	/*
24017c478bd9Sstevel@tonic-gate 	 * Verify whether timeout handler is created/active.
24027c478bd9Sstevel@tonic-gate 	 * If created/ active,  cancel the timeout  handler
24037c478bd9Sstevel@tonic-gate 	 */
24047c478bd9Sstevel@tonic-gate 	mutex_enter(&gid_info->gl_mutex);
24059d3d2ed0Shiremath 	ibdm_bump_transactionID(gid_info);
24067c478bd9Sstevel@tonic-gate 	if (gid_info->gl_state != IBDM_GET_CLASSPORTINFO) {
24077c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibdm", "\thandle_classportinfo:DUP resp");
24087c478bd9Sstevel@tonic-gate 		*flag |= IBDM_IBMF_PKT_DUP_RESP;
24097c478bd9Sstevel@tonic-gate 		mutex_exit(&gid_info->gl_mutex);
24107c478bd9Sstevel@tonic-gate 		return;
24117c478bd9Sstevel@tonic-gate 	}
24127c478bd9Sstevel@tonic-gate 	gid_info->gl_iou_cb_args.cb_req_type = 0;
24137c478bd9Sstevel@tonic-gate 	if (gid_info->gl_timeout_id) {
24147c478bd9Sstevel@tonic-gate 		timeout_id = gid_info->gl_timeout_id;
24157c478bd9Sstevel@tonic-gate 		mutex_exit(&gid_info->gl_mutex);
24167c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L5("ibdm", "handle_ioclassportinfo: "
24177c478bd9Sstevel@tonic-gate 		    "gl_timeout_id = 0x%x", timeout_id);
24187c478bd9Sstevel@tonic-gate 		if (untimeout(timeout_id) == -1) {
24197c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibdm", "handle_classportinfo: "
24207c478bd9Sstevel@tonic-gate 			    "untimeout gl_timeout_id failed");
24217c478bd9Sstevel@tonic-gate 		}
24227c478bd9Sstevel@tonic-gate 		mutex_enter(&gid_info->gl_mutex);
24237c478bd9Sstevel@tonic-gate 		gid_info->gl_timeout_id = 0;
24247c478bd9Sstevel@tonic-gate 	}
24257c478bd9Sstevel@tonic-gate 	gid_info->gl_state = IBDM_GET_IOUNITINFO;
24267c478bd9Sstevel@tonic-gate 	gid_info->gl_pending_cmds++;
24277c478bd9Sstevel@tonic-gate 	mutex_exit(&gid_info->gl_mutex);
24287c478bd9Sstevel@tonic-gate 
24297c478bd9Sstevel@tonic-gate 	data = msg->im_msgbufs_recv.im_bufs_cl_data;
243053c1b7a3Seota 	cpi = (ib_mad_classportinfo_t *)data;
24317c478bd9Sstevel@tonic-gate 
24327c478bd9Sstevel@tonic-gate 	/*
24337c478bd9Sstevel@tonic-gate 	 * Cache the "RespTimeValue" and redirection information in the
24347c478bd9Sstevel@tonic-gate 	 * global gid list data structure. This cached information will
24357c478bd9Sstevel@tonic-gate 	 * be used to send any further requests to the GID.
24367c478bd9Sstevel@tonic-gate 	 */
24377c478bd9Sstevel@tonic-gate 	gid_info->gl_resp_timeout	=
243853c1b7a3Seota 	    (b2h32(cpi->RespTimeValue) & 0x1F);
24397c478bd9Sstevel@tonic-gate 
24407c478bd9Sstevel@tonic-gate 	gid_info->gl_redirected		= ((IBDM_IN_IBMFMSG_STATUS(msg) &
24417c478bd9Sstevel@tonic-gate 	    MAD_STATUS_REDIRECT_REQUIRED) ? B_TRUE: B_FALSE);
24427c478bd9Sstevel@tonic-gate 	gid_info->gl_redirect_dlid	= b2h16(cpi->RedirectLID);
24437c478bd9Sstevel@tonic-gate 	gid_info->gl_redirect_QP	= (b2h32(cpi->RedirectQP) & 0xffffff);
24447c478bd9Sstevel@tonic-gate 	gid_info->gl_redirect_pkey	= b2h16(cpi->RedirectP_Key);
24457c478bd9Sstevel@tonic-gate 	gid_info->gl_redirect_qkey	= b2h32(cpi->RedirectQ_Key);
24467c478bd9Sstevel@tonic-gate 	gid_info->gl_redirectGID_hi	= b2h64(cpi->RedirectGID_hi);
24477c478bd9Sstevel@tonic-gate 	gid_info->gl_redirectGID_lo	= b2h64(cpi->RedirectGID_lo);
244818edb70cSeota 	gid_info->gl_redirectSL		= cpi->RedirectSL;
24497c478bd9Sstevel@tonic-gate 
24507c478bd9Sstevel@tonic-gate 	ibdm_dump_classportinfo(cpi);
24517c478bd9Sstevel@tonic-gate 
24527c478bd9Sstevel@tonic-gate 	/*
24537c478bd9Sstevel@tonic-gate 	 * Send IOUnitInfo request
24547c478bd9Sstevel@tonic-gate 	 * Reuse previously allocated IBMF packet for sending ClassPortInfo
24557c478bd9Sstevel@tonic-gate 	 * Check whether DM agent on the remote node requested redirection
24567c478bd9Sstevel@tonic-gate 	 * If so, send the request to the redirect DGID/DLID/PKEY/QP.
24577c478bd9Sstevel@tonic-gate 	 */
245818edb70cSeota 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*msg))
24597c478bd9Sstevel@tonic-gate 	ibdm_alloc_send_buffers(msg);
246018edb70cSeota 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*msg))
24617c478bd9Sstevel@tonic-gate 	msg->im_local_addr.ia_local_lid	= gid_info->gl_slid;
24627c478bd9Sstevel@tonic-gate 	msg->im_local_addr.ia_remote_lid	= gid_info->gl_dlid;
24637c478bd9Sstevel@tonic-gate 
24647c478bd9Sstevel@tonic-gate 	if (gid_info->gl_redirected == B_TRUE) {
24657c478bd9Sstevel@tonic-gate 		if (gid_info->gl_redirect_dlid != 0) {
24667c478bd9Sstevel@tonic-gate 			msg->im_local_addr.ia_remote_lid =
246753c1b7a3Seota 			    gid_info->gl_redirect_dlid;
24687c478bd9Sstevel@tonic-gate 		}
24697c478bd9Sstevel@tonic-gate 		msg->im_local_addr.ia_remote_qno = gid_info->gl_redirect_QP;
24707c478bd9Sstevel@tonic-gate 		msg->im_local_addr.ia_p_key = gid_info->gl_redirect_pkey;
24717c478bd9Sstevel@tonic-gate 		msg->im_local_addr.ia_q_key = gid_info->gl_redirect_qkey;
247218edb70cSeota 		msg->im_local_addr.ia_service_level = gid_info->gl_redirectSL;
24737c478bd9Sstevel@tonic-gate 	} else {
24747c478bd9Sstevel@tonic-gate 		msg->im_local_addr.ia_remote_qno = 1;
24757c478bd9Sstevel@tonic-gate 		msg->im_local_addr.ia_p_key = gid_info->gl_p_key;
24767c478bd9Sstevel@tonic-gate 		msg->im_local_addr.ia_q_key = IB_GSI_QKEY;
247718edb70cSeota 		msg->im_local_addr.ia_service_level = gid_info->gl_SL;
24787c478bd9Sstevel@tonic-gate 	}
24797c478bd9Sstevel@tonic-gate 
24807c478bd9Sstevel@tonic-gate 	hdr			= IBDM_OUT_IBMFMSG_MADHDR(msg);
24817c478bd9Sstevel@tonic-gate 	hdr->BaseVersion	= MAD_CLASS_BASE_VERS_1;
24827c478bd9Sstevel@tonic-gate 	hdr->MgmtClass		= MAD_MGMT_CLASS_DEV_MGT;
24837c478bd9Sstevel@tonic-gate 	hdr->ClassVersion	= IB_DM_CLASS_VERSION_1;
24847c478bd9Sstevel@tonic-gate 	hdr->R_Method		= IB_DM_DEVMGT_METHOD_GET;
24857c478bd9Sstevel@tonic-gate 	hdr->Status		= 0;
24867c478bd9Sstevel@tonic-gate 	hdr->TransactionID	= h2b64(gid_info->gl_transactionID);
24877c478bd9Sstevel@tonic-gate 	hdr->AttributeID	= h2b16(IB_DM_ATTR_IO_UNITINFO);
24887c478bd9Sstevel@tonic-gate 	hdr->AttributeModifier	= 0;
24897c478bd9Sstevel@tonic-gate 
24907c478bd9Sstevel@tonic-gate 	gid_info->gl_iou_cb_args.cb_req_type = IBDM_REQ_TYPE_IOUINFO;
24917c478bd9Sstevel@tonic-gate 	gid_info->gl_iou_cb_args.cb_gid_info = gid_info;
24927c478bd9Sstevel@tonic-gate 	gid_info->gl_iou_cb_args.cb_retry_count = ibdm_dft_retry_cnt;
24937c478bd9Sstevel@tonic-gate 
249418edb70cSeota 	mutex_enter(&gid_info->gl_mutex);
24957c478bd9Sstevel@tonic-gate 	gid_info->gl_timeout_id = timeout(ibdm_pkt_timeout_hdlr,
24967c478bd9Sstevel@tonic-gate 	    &gid_info->gl_iou_cb_args, IBDM_TIMEOUT_VALUE(ibdm_dft_timeout));
249718edb70cSeota 	mutex_exit(&gid_info->gl_mutex);
24987c478bd9Sstevel@tonic-gate 
24997c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L5("ibdm", "handle_classportinfo:"
25007c478bd9Sstevel@tonic-gate 	    "timeout %x", gid_info->gl_timeout_id);
25017c478bd9Sstevel@tonic-gate 
25027c478bd9Sstevel@tonic-gate 	if (ibmf_msg_transport(ibmf_hdl, gid_info->gl_qp_hdl, msg, NULL,
25037c478bd9Sstevel@tonic-gate 	    ibdm_ibmf_send_cb, &gid_info->gl_iou_cb_args, 0) != IBMF_SUCCESS) {
25047c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibdm",
25057c478bd9Sstevel@tonic-gate 		    "\thandle_classportinfo: msg transport failed");
25067c478bd9Sstevel@tonic-gate 		ibdm_ibmf_send_cb(ibmf_hdl, msg, &gid_info->gl_iou_cb_args);
25077c478bd9Sstevel@tonic-gate 	}
25087c478bd9Sstevel@tonic-gate 	(*flag) |= IBDM_IBMF_PKT_REUSED;
25097c478bd9Sstevel@tonic-gate }
25107c478bd9Sstevel@tonic-gate 
25117c478bd9Sstevel@tonic-gate 
25127c478bd9Sstevel@tonic-gate /*
25137c478bd9Sstevel@tonic-gate  * ibdm_send_iounitinfo:
25147c478bd9Sstevel@tonic-gate  *	Sends a DM request to get IOU unitinfo.
25157c478bd9Sstevel@tonic-gate  */
25167c478bd9Sstevel@tonic-gate static int
ibdm_send_iounitinfo(ibdm_dp_gidinfo_t * gid_info)25177c478bd9Sstevel@tonic-gate ibdm_send_iounitinfo(ibdm_dp_gidinfo_t *gid_info)
25187c478bd9Sstevel@tonic-gate {
25197c478bd9Sstevel@tonic-gate 	ibmf_msg_t	*msg;
25207c478bd9Sstevel@tonic-gate 	ib_mad_hdr_t	*hdr;
25217c478bd9Sstevel@tonic-gate 
25227c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tsend_iounitinfo: gid info 0x%p", gid_info);
25237c478bd9Sstevel@tonic-gate 
25247c478bd9Sstevel@tonic-gate 	/*
25257c478bd9Sstevel@tonic-gate 	 * Send command to get iounitinfo attribute. Allocate a IBMF
25267c478bd9Sstevel@tonic-gate 	 * packet and initialize the packet.
25277c478bd9Sstevel@tonic-gate 	 */
25287c478bd9Sstevel@tonic-gate 	if (ibmf_alloc_msg(gid_info->gl_ibmf_hdl, IBMF_ALLOC_SLEEP, &msg) !=
25297c478bd9Sstevel@tonic-gate 	    IBMF_SUCCESS) {
25307c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibdm", "\tsend_iounitinfo: pkt alloc fail");
25317c478bd9Sstevel@tonic-gate 		return (IBDM_FAILURE);
25327c478bd9Sstevel@tonic-gate 	}
25337c478bd9Sstevel@tonic-gate 
25349d3d2ed0Shiremath 	mutex_enter(&gid_info->gl_mutex);
25359d3d2ed0Shiremath 	ibdm_bump_transactionID(gid_info);
25369d3d2ed0Shiremath 	mutex_exit(&gid_info->gl_mutex);
25379d3d2ed0Shiremath 
25389d3d2ed0Shiremath 
253918edb70cSeota 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*msg))
25407c478bd9Sstevel@tonic-gate 	ibdm_alloc_send_buffers(msg);
254118edb70cSeota 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*msg))
25427c478bd9Sstevel@tonic-gate 	msg->im_local_addr.ia_local_lid		= gid_info->gl_slid;
25437c478bd9Sstevel@tonic-gate 	msg->im_local_addr.ia_remote_lid	= gid_info->gl_dlid;
25447c478bd9Sstevel@tonic-gate 	msg->im_local_addr.ia_remote_qno	= 1;
25457c478bd9Sstevel@tonic-gate 	msg->im_local_addr.ia_p_key		= gid_info->gl_p_key;
25467c478bd9Sstevel@tonic-gate 	msg->im_local_addr.ia_q_key		= IB_GSI_QKEY;
254718edb70cSeota 	msg->im_local_addr.ia_service_level	= gid_info->gl_SL;
25487c478bd9Sstevel@tonic-gate 
25497c478bd9Sstevel@tonic-gate 	hdr			= IBDM_OUT_IBMFMSG_MADHDR(msg);
25507c478bd9Sstevel@tonic-gate 	hdr->BaseVersion	= MAD_CLASS_BASE_VERS_1;
25517c478bd9Sstevel@tonic-gate 	hdr->MgmtClass		= MAD_MGMT_CLASS_DEV_MGT;
25527c478bd9Sstevel@tonic-gate 	hdr->ClassVersion	= IB_DM_CLASS_VERSION_1;
25537c478bd9Sstevel@tonic-gate 	hdr->R_Method		= IB_DM_DEVMGT_METHOD_GET;
25547c478bd9Sstevel@tonic-gate 	hdr->Status		= 0;
25557c478bd9Sstevel@tonic-gate 	hdr->TransactionID	= h2b64(gid_info->gl_transactionID);
25567c478bd9Sstevel@tonic-gate 	hdr->AttributeID	= h2b16(IB_DM_ATTR_IO_UNITINFO);
25577c478bd9Sstevel@tonic-gate 	hdr->AttributeModifier	= 0;
25587c478bd9Sstevel@tonic-gate 
25597c478bd9Sstevel@tonic-gate 	gid_info->gl_iou_cb_args.cb_gid_info = gid_info;
25607c478bd9Sstevel@tonic-gate 	gid_info->gl_iou_cb_args.cb_retry_count = ibdm_dft_retry_cnt;
25617c478bd9Sstevel@tonic-gate 	gid_info->gl_iou_cb_args.cb_req_type = IBDM_REQ_TYPE_IOUINFO;
25627c478bd9Sstevel@tonic-gate 
256318edb70cSeota 	mutex_enter(&gid_info->gl_mutex);
25647c478bd9Sstevel@tonic-gate 	gid_info->gl_timeout_id = timeout(ibdm_pkt_timeout_hdlr,
25657c478bd9Sstevel@tonic-gate 	    &gid_info->gl_iou_cb_args, IBDM_TIMEOUT_VALUE(ibdm_dft_timeout));
256618edb70cSeota 	mutex_exit(&gid_info->gl_mutex);
25677c478bd9Sstevel@tonic-gate 
25687c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L5("ibdm", "send_iouunitinfo:"
25697c478bd9Sstevel@tonic-gate 	    "timeout %x", gid_info->gl_timeout_id);
25707c478bd9Sstevel@tonic-gate 
25717c478bd9Sstevel@tonic-gate 	if (ibmf_msg_transport(gid_info->gl_ibmf_hdl, gid_info->gl_qp_hdl, msg,
25727c478bd9Sstevel@tonic-gate 	    NULL, ibdm_ibmf_send_cb, &gid_info->gl_iou_cb_args, 0) !=
25737c478bd9Sstevel@tonic-gate 	    IBMF_SUCCESS) {
25747c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibdm", "\tsend_iounitinfo: ibmf send failed");
25757c478bd9Sstevel@tonic-gate 		ibdm_ibmf_send_cb(gid_info->gl_ibmf_hdl,
25767c478bd9Sstevel@tonic-gate 		    msg, &gid_info->gl_iou_cb_args);
25777c478bd9Sstevel@tonic-gate 	}
25787c478bd9Sstevel@tonic-gate 	return (IBDM_SUCCESS);
25797c478bd9Sstevel@tonic-gate }
25807c478bd9Sstevel@tonic-gate 
25817c478bd9Sstevel@tonic-gate /*
25827c478bd9Sstevel@tonic-gate  * ibdm_handle_iounitinfo()
25837c478bd9Sstevel@tonic-gate  *	Invoked by the IBMF when IO Unitinfo request is completed.
25847c478bd9Sstevel@tonic-gate  */
25857c478bd9Sstevel@tonic-gate static void
ibdm_handle_iounitinfo(ibmf_handle_t ibmf_hdl,ibmf_msg_t * msg,ibdm_dp_gidinfo_t * gid_info,int * flag)25867c478bd9Sstevel@tonic-gate ibdm_handle_iounitinfo(ibmf_handle_t ibmf_hdl,
25877c478bd9Sstevel@tonic-gate     ibmf_msg_t *msg, ibdm_dp_gidinfo_t *gid_info, int *flag)
25887c478bd9Sstevel@tonic-gate {
25897c478bd9Sstevel@tonic-gate 	int			ii, first = B_TRUE;
25907c478bd9Sstevel@tonic-gate 	int			num_iocs;
25917c478bd9Sstevel@tonic-gate 	size_t			size;
25927c478bd9Sstevel@tonic-gate 	uchar_t			slot_info;
25937c478bd9Sstevel@tonic-gate 	timeout_id_t		timeout_id;
25947c478bd9Sstevel@tonic-gate 	ib_mad_hdr_t		*hdr;
25957c478bd9Sstevel@tonic-gate 	ibdm_ioc_info_t		*ioc_info;
25967c478bd9Sstevel@tonic-gate 	ib_dm_io_unitinfo_t	*iou_info;
25977c478bd9Sstevel@tonic-gate 	ib_dm_io_unitinfo_t	*giou_info;
25987c478bd9Sstevel@tonic-gate 	ibdm_timeout_cb_args_t	*cb_args;
25997c478bd9Sstevel@tonic-gate 
26007c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\thandle_iouintinfo:"
26017c478bd9Sstevel@tonic-gate 	    " ibmf hdl %p pkt %p gid info %p", ibmf_hdl, msg, gid_info);
26027c478bd9Sstevel@tonic-gate 
26037c478bd9Sstevel@tonic-gate 	if (IBDM_IN_IBMFMSG_ATTR(msg) != IB_DM_ATTR_IO_UNITINFO) {
26047c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibdm", "\thandle_iounitinfo: "
26057c478bd9Sstevel@tonic-gate 		    "Unexpected response");
26067c478bd9Sstevel@tonic-gate 		(*flag) |= IBDM_IBMF_PKT_UNEXP_RESP;
26077c478bd9Sstevel@tonic-gate 		return;
26087c478bd9Sstevel@tonic-gate 	}
26097c478bd9Sstevel@tonic-gate 
26107c478bd9Sstevel@tonic-gate 	mutex_enter(&gid_info->gl_mutex);
26117c478bd9Sstevel@tonic-gate 	if (gid_info->gl_state != IBDM_GET_IOUNITINFO) {
26127c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibdm",
26137c478bd9Sstevel@tonic-gate 		    "\thandle_iounitinfo: DUP resp");
26147c478bd9Sstevel@tonic-gate 		mutex_exit(&gid_info->gl_mutex);
26157c478bd9Sstevel@tonic-gate 		(*flag) = IBDM_IBMF_PKT_DUP_RESP;
26167c478bd9Sstevel@tonic-gate 		return;
26177c478bd9Sstevel@tonic-gate 	}
26187c478bd9Sstevel@tonic-gate 	gid_info->gl_iou_cb_args.cb_req_type = 0;
26197c478bd9Sstevel@tonic-gate 	if (gid_info->gl_timeout_id) {
26207c478bd9Sstevel@tonic-gate 		timeout_id = gid_info->gl_timeout_id;
26217c478bd9Sstevel@tonic-gate 		mutex_exit(&gid_info->gl_mutex);
26227c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L5("ibdm", "handle_iounitinfo: "
26237c478bd9Sstevel@tonic-gate 		    "gl_timeout_id = 0x%x", timeout_id);
26247c478bd9Sstevel@tonic-gate 		if (untimeout(timeout_id) == -1) {
26257c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibdm", "handle_iounitinfo: "
26267c478bd9Sstevel@tonic-gate 			    "untimeout gl_timeout_id failed");
26277c478bd9Sstevel@tonic-gate 		}
26287c478bd9Sstevel@tonic-gate 		mutex_enter(&gid_info->gl_mutex);
26297c478bd9Sstevel@tonic-gate 		gid_info->gl_timeout_id = 0;
26307c478bd9Sstevel@tonic-gate 	}
26317c478bd9Sstevel@tonic-gate 	gid_info->gl_state = IBDM_GET_IOC_DETAILS;
26327c478bd9Sstevel@tonic-gate 
26337c478bd9Sstevel@tonic-gate 	iou_info = IBDM_IN_IBMFMSG2IOU(msg);
26347c478bd9Sstevel@tonic-gate 	ibdm_dump_iounitinfo(iou_info);
26357c478bd9Sstevel@tonic-gate 	num_iocs = iou_info->iou_num_ctrl_slots;
26367c478bd9Sstevel@tonic-gate 	/*
26377c478bd9Sstevel@tonic-gate 	 * check if number of IOCs reported is zero? if yes, return.
26387c478bd9Sstevel@tonic-gate 	 * when num_iocs are reported zero internal IOC database needs
26397c478bd9Sstevel@tonic-gate 	 * to be updated. To ensure that save the number of IOCs in
26407c478bd9Sstevel@tonic-gate 	 * the new field "gl_num_iocs". Use a new field instead of
26417c478bd9Sstevel@tonic-gate 	 * "giou_info->iou_num_ctrl_slots" as that would prevent
26427c478bd9Sstevel@tonic-gate 	 * an unnecessary kmem_alloc/kmem_free when num_iocs is 0.
26437c478bd9Sstevel@tonic-gate 	 */
26447c478bd9Sstevel@tonic-gate 	if (num_iocs == 0 && gid_info->gl_num_iocs == 0) {
26457c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibdm", "\thandle_iounitinfo: no IOC's");
26467c478bd9Sstevel@tonic-gate 		mutex_exit(&gid_info->gl_mutex);
26477c478bd9Sstevel@tonic-gate 		return;
26487c478bd9Sstevel@tonic-gate 	}
26497c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\thandle_iounitinfo: num_iocs = %d", num_iocs);
26507c478bd9Sstevel@tonic-gate 
26517c478bd9Sstevel@tonic-gate 	/*
26527c478bd9Sstevel@tonic-gate 	 * if there is an existing gl_iou (IOU has been probed before)
26537c478bd9Sstevel@tonic-gate 	 * check if the "iou_changeid" is same as saved entry in
26547c478bd9Sstevel@tonic-gate 	 * "giou_info->iou_changeid".
26557c478bd9Sstevel@tonic-gate 	 * (note: this logic can prevent IOC enumeration if a given
26567c478bd9Sstevel@tonic-gate 	 * vendor doesn't support setting iou_changeid field for its IOU)
26577c478bd9Sstevel@tonic-gate 	 *
26587c478bd9Sstevel@tonic-gate 	 * if there is an existing gl_iou and iou_changeid has changed :
26597c478bd9Sstevel@tonic-gate 	 * free up existing gl_iou info and its related structures.
26607c478bd9Sstevel@tonic-gate 	 * reallocate gl_iou info all over again.
26617c478bd9Sstevel@tonic-gate 	 * if we donot free this up; then this leads to memory leaks
26627c478bd9Sstevel@tonic-gate 	 */
26637c478bd9Sstevel@tonic-gate 	if (gid_info->gl_iou) {
26647c478bd9Sstevel@tonic-gate 		giou_info = &gid_info->gl_iou->iou_info;
2665add2b70bSpramodbg 		if (b2h16(iou_info->iou_changeid) ==
2666add2b70bSpramodbg 		    giou_info->iou_changeid) {
26677c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L3("ibdm",
26687c478bd9Sstevel@tonic-gate 			    "\thandle_iounitinfo: no IOCs changed");
26697c478bd9Sstevel@tonic-gate 			gid_info->gl_state = IBDM_GID_PROBING_COMPLETE;
26707c478bd9Sstevel@tonic-gate 			mutex_exit(&gid_info->gl_mutex);
26717c478bd9Sstevel@tonic-gate 			return;
26727c478bd9Sstevel@tonic-gate 		}
2673add2b70bSpramodbg 
2674add2b70bSpramodbg 		/*
2675add2b70bSpramodbg 		 * Store the iou info as prev_iou to be used after
2676add2b70bSpramodbg 		 * sweep is done.
2677add2b70bSpramodbg 		 */
2678add2b70bSpramodbg 		ASSERT(gid_info->gl_prev_iou == NULL);
2679add2b70bSpramodbg 		IBTF_DPRINTF_L4(ibdm_string,
2680add2b70bSpramodbg 		    "\thandle_iounitinfo: setting gl_prev_iou %p",
2681add2b70bSpramodbg 		    gid_info->gl_prev_iou);
2682add2b70bSpramodbg 		gid_info->gl_prev_iou = gid_info->gl_iou;
2683add2b70bSpramodbg 		ibdm.ibdm_prev_iou = 1;
2684add2b70bSpramodbg 		gid_info->gl_iou = NULL;
26857c478bd9Sstevel@tonic-gate 	}
26867c478bd9Sstevel@tonic-gate 
26877c478bd9Sstevel@tonic-gate 	size = sizeof (ibdm_iou_info_t) + num_iocs * sizeof (ibdm_ioc_info_t);
26887c478bd9Sstevel@tonic-gate 	gid_info->gl_iou = (ibdm_iou_info_t *)kmem_zalloc(size, KM_SLEEP);
26897c478bd9Sstevel@tonic-gate 	giou_info = &gid_info->gl_iou->iou_info;
26907c478bd9Sstevel@tonic-gate 	gid_info->gl_iou->iou_ioc_info = (ibdm_ioc_info_t *)
269153c1b7a3Seota 	    ((char *)gid_info->gl_iou + sizeof (ibdm_iou_info_t));
26927c478bd9Sstevel@tonic-gate 
26937c478bd9Sstevel@tonic-gate 	giou_info->iou_num_ctrl_slots	= gid_info->gl_num_iocs	= num_iocs;
26947c478bd9Sstevel@tonic-gate 	giou_info->iou_flag		= iou_info->iou_flag;
26957c478bd9Sstevel@tonic-gate 	bcopy(iou_info->iou_ctrl_list, giou_info->iou_ctrl_list, 128);
26967c478bd9Sstevel@tonic-gate 	giou_info->iou_changeid	= b2h16(iou_info->iou_changeid);
269753c1b7a3Seota 	gid_info->gl_pending_cmds++; /* for diag code */
26987c478bd9Sstevel@tonic-gate 	mutex_exit(&gid_info->gl_mutex);
26997c478bd9Sstevel@tonic-gate 
27007c478bd9Sstevel@tonic-gate 	if (ibdm_get_diagcode(gid_info, 0) != IBDM_SUCCESS) {
27017c478bd9Sstevel@tonic-gate 		mutex_enter(&gid_info->gl_mutex);
27027c478bd9Sstevel@tonic-gate 		gid_info->gl_pending_cmds--;
27037c478bd9Sstevel@tonic-gate 		mutex_exit(&gid_info->gl_mutex);
27047c478bd9Sstevel@tonic-gate 	}
27057c478bd9Sstevel@tonic-gate 	/*
27067c478bd9Sstevel@tonic-gate 	 * Parallelize getting IOC controller profiles from here.
27077c478bd9Sstevel@tonic-gate 	 * Allocate IBMF packets and send commands to get IOC profile for
27087c478bd9Sstevel@tonic-gate 	 * each IOC present on the IOU.
27097c478bd9Sstevel@tonic-gate 	 */
27107c478bd9Sstevel@tonic-gate 	for (ii = 0; ii < num_iocs; ii++) {
27117c478bd9Sstevel@tonic-gate 		/*
27127c478bd9Sstevel@tonic-gate 		 * Check whether IOC is present in the slot
27137c478bd9Sstevel@tonic-gate 		 * Series of nibbles (in the field iou_ctrl_list) represents
27147c478bd9Sstevel@tonic-gate 		 * a slot in the IOU.
27157c478bd9Sstevel@tonic-gate 		 * Byte format: 76543210
27167c478bd9Sstevel@tonic-gate 		 * Bits 0-3 of first byte represent Slot 2
27177c478bd9Sstevel@tonic-gate 		 * bits 4-7 of first byte represent slot 1,
27187c478bd9Sstevel@tonic-gate 		 * bits 0-3 of second byte represent slot 4 and so on
27197c478bd9Sstevel@tonic-gate 		 * Each 4-bit nibble has the following meaning
27207c478bd9Sstevel@tonic-gate 		 * 0x0 : IOC not installed
27217c478bd9Sstevel@tonic-gate 		 * 0x1 : IOC is present
27227c478bd9Sstevel@tonic-gate 		 * 0xf : Slot does not exist
27237c478bd9Sstevel@tonic-gate 		 * and all other values are reserved.
27247c478bd9Sstevel@tonic-gate 		 */
27257c478bd9Sstevel@tonic-gate 		ioc_info = IBDM_GIDINFO2IOCINFO(gid_info, ii);
27267c478bd9Sstevel@tonic-gate 		slot_info = giou_info->iou_ctrl_list[(ii/2)];
27277c478bd9Sstevel@tonic-gate 		if ((ii % 2) == 0)
27287c478bd9Sstevel@tonic-gate 			slot_info = (slot_info >> 4);
27297c478bd9Sstevel@tonic-gate 
27307c478bd9Sstevel@tonic-gate 		if ((slot_info & 0xf) != 1) {
27317c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibdm", "\thandle_iouintinfo: "
27327c478bd9Sstevel@tonic-gate 			    "No IOC is present in the slot = %d", ii);
27337c478bd9Sstevel@tonic-gate 			ioc_info->ioc_state = IBDM_IOC_STATE_PROBE_FAILED;
27347c478bd9Sstevel@tonic-gate 			continue;
27357c478bd9Sstevel@tonic-gate 		}
27367c478bd9Sstevel@tonic-gate 
27379d3d2ed0Shiremath 		mutex_enter(&gid_info->gl_mutex);
27389d3d2ed0Shiremath 		ibdm_bump_transactionID(gid_info);
27399d3d2ed0Shiremath 		mutex_exit(&gid_info->gl_mutex);
27409d3d2ed0Shiremath 
27417c478bd9Sstevel@tonic-gate 		/*
27427c478bd9Sstevel@tonic-gate 		 * Re use the already allocated packet (for IOUnitinfo) to
27437c478bd9Sstevel@tonic-gate 		 * send the first IOC controller attribute. Allocate new
27447c478bd9Sstevel@tonic-gate 		 * IBMF packets for the rest of the IOC's
27457c478bd9Sstevel@tonic-gate 		 */
27467c478bd9Sstevel@tonic-gate 		if (first != B_TRUE) {
27477c478bd9Sstevel@tonic-gate 			msg = NULL;
27487c478bd9Sstevel@tonic-gate 			if (ibmf_alloc_msg(ibmf_hdl, IBMF_ALLOC_SLEEP,
27497c478bd9Sstevel@tonic-gate 			    &msg) != IBMF_SUCCESS) {
27507c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L4("ibdm", "\thandle_iouintinfo: "
27517c478bd9Sstevel@tonic-gate 				    "IBMF packet allocation failed");
27527c478bd9Sstevel@tonic-gate 				continue;
27537c478bd9Sstevel@tonic-gate 			}
27547c478bd9Sstevel@tonic-gate 
27557c478bd9Sstevel@tonic-gate 		}
27567c478bd9Sstevel@tonic-gate 
27577c478bd9Sstevel@tonic-gate 		/* allocate send buffers for all messages */
275818edb70cSeota 		_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*msg))
27597c478bd9Sstevel@tonic-gate 		ibdm_alloc_send_buffers(msg);
276018edb70cSeota 		_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*msg))
27617c478bd9Sstevel@tonic-gate 
27627c478bd9Sstevel@tonic-gate 		msg->im_local_addr.ia_local_lid	= gid_info->gl_slid;
27637c478bd9Sstevel@tonic-gate 		msg->im_local_addr.ia_remote_lid	= gid_info->gl_dlid;
27647c478bd9Sstevel@tonic-gate 		if (gid_info->gl_redirected == B_TRUE) {
27657c478bd9Sstevel@tonic-gate 			if (gid_info->gl_redirect_dlid != 0) {
27667c478bd9Sstevel@tonic-gate 				msg->im_local_addr.ia_remote_lid =
276753c1b7a3Seota 				    gid_info->gl_redirect_dlid;
27687c478bd9Sstevel@tonic-gate 			}
27697c478bd9Sstevel@tonic-gate 			msg->im_local_addr.ia_remote_qno =
277053c1b7a3Seota 			    gid_info->gl_redirect_QP;
27717c478bd9Sstevel@tonic-gate 			msg->im_local_addr.ia_p_key =
277253c1b7a3Seota 			    gid_info->gl_redirect_pkey;
27737c478bd9Sstevel@tonic-gate 			msg->im_local_addr.ia_q_key =
277453c1b7a3Seota 			    gid_info->gl_redirect_qkey;
277518edb70cSeota 			msg->im_local_addr.ia_service_level =
277618edb70cSeota 			    gid_info->gl_redirectSL;
27777c478bd9Sstevel@tonic-gate 		} else {
27787c478bd9Sstevel@tonic-gate 			msg->im_local_addr.ia_remote_qno = 1;
27797c478bd9Sstevel@tonic-gate 			msg->im_local_addr.ia_p_key = gid_info->gl_p_key;
27807c478bd9Sstevel@tonic-gate 			msg->im_local_addr.ia_q_key = IB_GSI_QKEY;
278118edb70cSeota 			msg->im_local_addr.ia_service_level = gid_info->gl_SL;
27827c478bd9Sstevel@tonic-gate 		}
27837c478bd9Sstevel@tonic-gate 
27847c478bd9Sstevel@tonic-gate 		hdr			= IBDM_OUT_IBMFMSG_MADHDR(msg);
27857c478bd9Sstevel@tonic-gate 		hdr->BaseVersion	= MAD_CLASS_BASE_VERS_1;
27867c478bd9Sstevel@tonic-gate 		hdr->MgmtClass		= MAD_MGMT_CLASS_DEV_MGT;
27877c478bd9Sstevel@tonic-gate 		hdr->ClassVersion	= IB_DM_CLASS_VERSION_1;
27887c478bd9Sstevel@tonic-gate 		hdr->R_Method		= IB_DM_DEVMGT_METHOD_GET;
27897c478bd9Sstevel@tonic-gate 		hdr->Status		= 0;
27907c478bd9Sstevel@tonic-gate 		hdr->TransactionID	= h2b64(gid_info->gl_transactionID);
27917c478bd9Sstevel@tonic-gate 		hdr->AttributeID	= h2b16(IB_DM_ATTR_IOC_CTRL_PROFILE);
27927c478bd9Sstevel@tonic-gate 		hdr->AttributeModifier 	= h2b32(ii + 1);
27937c478bd9Sstevel@tonic-gate 
27947c478bd9Sstevel@tonic-gate 		ioc_info->ioc_state	= IBDM_IOC_STATE_PROBE_INVALID;
27957c478bd9Sstevel@tonic-gate 		cb_args			= &ioc_info->ioc_cb_args;
27967c478bd9Sstevel@tonic-gate 		cb_args->cb_gid_info	= gid_info;
27977c478bd9Sstevel@tonic-gate 		cb_args->cb_retry_count	= ibdm_dft_retry_cnt;
27987c478bd9Sstevel@tonic-gate 		cb_args->cb_req_type	= IBDM_REQ_TYPE_IOCINFO;
27997c478bd9Sstevel@tonic-gate 		cb_args->cb_ioc_num	= ii;
28007c478bd9Sstevel@tonic-gate 
280153c1b7a3Seota 		mutex_enter(&gid_info->gl_mutex);
280253c1b7a3Seota 		gid_info->gl_pending_cmds++; /* for diag code */
280353c1b7a3Seota 
28047c478bd9Sstevel@tonic-gate 		ioc_info->ioc_timeout_id = timeout(ibdm_pkt_timeout_hdlr,
28057c478bd9Sstevel@tonic-gate 		    cb_args, IBDM_TIMEOUT_VALUE(ibdm_dft_timeout));
280618edb70cSeota 		mutex_exit(&gid_info->gl_mutex);
28077c478bd9Sstevel@tonic-gate 
28087c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L5("ibdm", "\thandle_iounitinfo:"
28097c478bd9Sstevel@tonic-gate 		    "timeout 0x%x, ioc_num %d", ioc_info->ioc_timeout_id, ii);
28107c478bd9Sstevel@tonic-gate 
28117c478bd9Sstevel@tonic-gate 		if (ibmf_msg_transport(ibmf_hdl, gid_info->gl_qp_hdl, msg,
28127c478bd9Sstevel@tonic-gate 		    NULL, ibdm_ibmf_send_cb, cb_args, 0) != IBMF_SUCCESS) {
28137c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibdm",
28147c478bd9Sstevel@tonic-gate 			    "\thandle_iounitinfo: msg transport failed");
28157c478bd9Sstevel@tonic-gate 			ibdm_ibmf_send_cb(ibmf_hdl, msg, cb_args);
28167c478bd9Sstevel@tonic-gate 		}
28177c478bd9Sstevel@tonic-gate 		(*flag) |= IBDM_IBMF_PKT_REUSED;
28187c478bd9Sstevel@tonic-gate 		first = B_FALSE;
28197c478bd9Sstevel@tonic-gate 		gid_info->gl_iou->iou_niocs_probe_in_progress++;
28207c478bd9Sstevel@tonic-gate 	}
28217c478bd9Sstevel@tonic-gate }
28227c478bd9Sstevel@tonic-gate 
28237c478bd9Sstevel@tonic-gate 
28247c478bd9Sstevel@tonic-gate /*
28257c478bd9Sstevel@tonic-gate  * ibdm_handle_ioc_profile()
28267c478bd9Sstevel@tonic-gate  *	Invoked by the IBMF when the IOCControllerProfile request
28277c478bd9Sstevel@tonic-gate  *	gets completed
28287c478bd9Sstevel@tonic-gate  */
28297c478bd9Sstevel@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)28307c478bd9Sstevel@tonic-gate ibdm_handle_ioc_profile(ibmf_handle_t ibmf_hdl,
28317c478bd9Sstevel@tonic-gate     ibmf_msg_t *msg, ibdm_dp_gidinfo_t *gid_info, int *flag)
28327c478bd9Sstevel@tonic-gate {
28337c478bd9Sstevel@tonic-gate 	int				first = B_TRUE, reprobe = 0;
28347c478bd9Sstevel@tonic-gate 	uint_t				ii, ioc_no, srv_start;
28357c478bd9Sstevel@tonic-gate 	uint_t				nserv_entries;
28367c478bd9Sstevel@tonic-gate 	timeout_id_t			timeout_id;
28377c478bd9Sstevel@tonic-gate 	ib_mad_hdr_t			*hdr;
28387c478bd9Sstevel@tonic-gate 	ibdm_ioc_info_t			*ioc_info;
28397c478bd9Sstevel@tonic-gate 	ibdm_timeout_cb_args_t		*cb_args;
28407c478bd9Sstevel@tonic-gate 	ib_dm_ioc_ctrl_profile_t	*ioc, *gioc;
28417c478bd9Sstevel@tonic-gate 
28427c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\thandle_ioc_profile:"
28437c478bd9Sstevel@tonic-gate 	    " ibmf hdl %p msg %p gid info %p", ibmf_hdl, msg, gid_info);
28447c478bd9Sstevel@tonic-gate 
28457c478bd9Sstevel@tonic-gate 	ioc = IBDM_IN_IBMFMSG2IOC(msg);
28467c478bd9Sstevel@tonic-gate 	/*
28477c478bd9Sstevel@tonic-gate 	 * Check whether we know this IOC already
28487c478bd9Sstevel@tonic-gate 	 * This will return NULL if reprobe is in progress
28497c478bd9Sstevel@tonic-gate 	 * IBDM_IOC_STATE_REPROBE_PROGRESS will be set.
28507c478bd9Sstevel@tonic-gate 	 * Do not hold mutexes here.
28517c478bd9Sstevel@tonic-gate 	 */
28527c478bd9Sstevel@tonic-gate 	if (ibdm_is_ioc_present(ioc->ioc_guid, gid_info, flag) != NULL) {
28537c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibdm", "\thandle_ioc_profile:"
285453c1b7a3Seota 		    "IOC guid %llx is present", ioc->ioc_guid);
28557c478bd9Sstevel@tonic-gate 		return;
28567c478bd9Sstevel@tonic-gate 	}
28577c478bd9Sstevel@tonic-gate 	ioc_no = IBDM_IN_IBMFMSG_ATTRMOD(msg);
28587c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\thandle_ioc_profile: ioc_no = %d", ioc_no-1);
28597c478bd9Sstevel@tonic-gate 
28607c478bd9Sstevel@tonic-gate 	/* Make sure that IOC index is with the valid range */
28617c478bd9Sstevel@tonic-gate 	if (IBDM_IS_IOC_NUM_INVALID(ioc_no, gid_info)) {
28627c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibdm", "\thandle_ioc_profile: "
28637c478bd9Sstevel@tonic-gate 		    "IOC index Out of range, index %d", ioc);
28647c478bd9Sstevel@tonic-gate 		(*flag) |= IBDM_IBMF_PKT_UNEXP_RESP;
28657c478bd9Sstevel@tonic-gate 		return;
28667c478bd9Sstevel@tonic-gate 	}
28677c478bd9Sstevel@tonic-gate 	ioc_info = &gid_info->gl_iou->iou_ioc_info[ioc_no - 1];
28687c478bd9Sstevel@tonic-gate 	ioc_info->ioc_iou_info = gid_info->gl_iou;
28697c478bd9Sstevel@tonic-gate 
28707c478bd9Sstevel@tonic-gate 	mutex_enter(&gid_info->gl_mutex);
28717c478bd9Sstevel@tonic-gate 	if (ioc_info->ioc_state == IBDM_IOC_STATE_REPROBE_PROGRESS) {
28727c478bd9Sstevel@tonic-gate 		reprobe = 1;
28737c478bd9Sstevel@tonic-gate 		ioc_info->ioc_prev_serv = ioc_info->ioc_serv;
28747c478bd9Sstevel@tonic-gate 		ioc_info->ioc_serv = NULL;
28757c478bd9Sstevel@tonic-gate 		ioc_info->ioc_prev_serv_cnt =
28767c478bd9Sstevel@tonic-gate 		    ioc_info->ioc_profile.ioc_service_entries;
28777c478bd9Sstevel@tonic-gate 	} else if (ioc_info->ioc_state != IBDM_IOC_STATE_PROBE_INVALID) {
28787c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibdm", "\thandle_ioc_profile: DUP response"
28797c478bd9Sstevel@tonic-gate 		    "ioc %d, ioc_state %x", ioc_no - 1, ioc_info->ioc_state);
28807c478bd9Sstevel@tonic-gate 		mutex_exit(&gid_info->gl_mutex);
28817c478bd9Sstevel@tonic-gate 		(*flag) |= IBDM_IBMF_PKT_DUP_RESP;
28827c478bd9Sstevel@tonic-gate 		return;
28837c478bd9Sstevel@tonic-gate 	}
28847c478bd9Sstevel@tonic-gate 	ioc_info->ioc_cb_args.cb_req_type = 0;
28857c478bd9Sstevel@tonic-gate 	if (ioc_info->ioc_timeout_id) {
28867c478bd9Sstevel@tonic-gate 		timeout_id = ioc_info->ioc_timeout_id;
288718edb70cSeota 		ioc_info->ioc_timeout_id = 0;
28887c478bd9Sstevel@tonic-gate 		mutex_exit(&gid_info->gl_mutex);
28897c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L5("ibdm", "handle_ioc_profile: "
28907c478bd9Sstevel@tonic-gate 		    "ioc_timeout_id = 0x%x", timeout_id);
28917c478bd9Sstevel@tonic-gate 		if (untimeout(timeout_id) == -1) {
28927c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibdm", "handle_ioc_profile: "
28937c478bd9Sstevel@tonic-gate 			    "untimeout ioc_timeout_id failed");
28947c478bd9Sstevel@tonic-gate 		}
28957c478bd9Sstevel@tonic-gate 		mutex_enter(&gid_info->gl_mutex);
28967c478bd9Sstevel@tonic-gate 	}
28977c478bd9Sstevel@tonic-gate 
28987c478bd9Sstevel@tonic-gate 	ioc_info->ioc_state = IBDM_IOC_STATE_PROBE_SUCCESS;
28997c478bd9Sstevel@tonic-gate 	if (reprobe == 0) {
29007c478bd9Sstevel@tonic-gate 		ioc_info->ioc_iou_guid = gid_info->gl_nodeguid;
29017c478bd9Sstevel@tonic-gate 		ioc_info->ioc_nodeguid = gid_info->gl_nodeguid;
29027c478bd9Sstevel@tonic-gate 	}
29037c478bd9Sstevel@tonic-gate 
29047c478bd9Sstevel@tonic-gate 	/*
29057c478bd9Sstevel@tonic-gate 	 * Save all the IOC information in the global structures.
29067c478bd9Sstevel@tonic-gate 	 * Note the wire format is Big Endian and the Sparc process also
29077c478bd9Sstevel@tonic-gate 	 * big endian. So, there is no need to convert the data fields
29087c478bd9Sstevel@tonic-gate 	 * The conversion routines used below are ineffective on Sparc
29097c478bd9Sstevel@tonic-gate 	 * machines where as they will be effective on little endian
29107c478bd9Sstevel@tonic-gate 	 * machines such as Intel processors.
29117c478bd9Sstevel@tonic-gate 	 */
29127c478bd9Sstevel@tonic-gate 	gioc = (ib_dm_ioc_ctrl_profile_t *)&ioc_info->ioc_profile;
29137c478bd9Sstevel@tonic-gate 
29147c478bd9Sstevel@tonic-gate 	/*
29157c478bd9Sstevel@tonic-gate 	 * Restrict updates to onlyport GIDs and service entries during reprobe
29167c478bd9Sstevel@tonic-gate 	 */
29177c478bd9Sstevel@tonic-gate 	if (reprobe == 0) {
29187c478bd9Sstevel@tonic-gate 		gioc->ioc_guid			= b2h64(ioc->ioc_guid);
29197c478bd9Sstevel@tonic-gate 		gioc->ioc_vendorid		=
29209d3d2ed0Shiremath 		    ((b2h32(ioc->ioc_vendorid) & IB_DM_VENDORID_MASK)
29219d3d2ed0Shiremath 		    >> IB_DM_VENDORID_SHIFT);
29227c478bd9Sstevel@tonic-gate 		gioc->ioc_deviceid		= b2h32(ioc->ioc_deviceid);
29237c478bd9Sstevel@tonic-gate 		gioc->ioc_device_ver		= b2h16(ioc->ioc_device_ver);
29247c478bd9Sstevel@tonic-gate 		gioc->ioc_subsys_vendorid	=
29259d3d2ed0Shiremath 		    ((b2h32(ioc->ioc_subsys_vendorid) & IB_DM_VENDORID_MASK)
29269d3d2ed0Shiremath 		    >> IB_DM_VENDORID_SHIFT);
29277c478bd9Sstevel@tonic-gate 		gioc->ioc_subsys_id		= b2h32(ioc->ioc_subsys_id);
29287c478bd9Sstevel@tonic-gate 		gioc->ioc_io_class		= b2h16(ioc->ioc_io_class);
29297c478bd9Sstevel@tonic-gate 		gioc->ioc_io_subclass		= b2h16(ioc->ioc_io_subclass);
29307c478bd9Sstevel@tonic-gate 		gioc->ioc_protocol		= b2h16(ioc->ioc_protocol);
29317c478bd9Sstevel@tonic-gate 		gioc->ioc_protocol_ver		= b2h16(ioc->ioc_protocol_ver);
29327c478bd9Sstevel@tonic-gate 		gioc->ioc_send_msg_qdepth	=
29337c478bd9Sstevel@tonic-gate 		    b2h16(ioc->ioc_send_msg_qdepth);
29347c478bd9Sstevel@tonic-gate 		gioc->ioc_rdma_read_qdepth	=
29357c478bd9Sstevel@tonic-gate 		    b2h16(ioc->ioc_rdma_read_qdepth);
29367c478bd9Sstevel@tonic-gate 		gioc->ioc_send_msg_sz		= b2h32(ioc->ioc_send_msg_sz);
29377c478bd9Sstevel@tonic-gate 		gioc->ioc_rdma_xfer_sz		= b2h32(ioc->ioc_rdma_xfer_sz);
29387c478bd9Sstevel@tonic-gate 		gioc->ioc_ctrl_opcap_mask	= ioc->ioc_ctrl_opcap_mask;
29397c478bd9Sstevel@tonic-gate 		bcopy(ioc->ioc_id_string, gioc->ioc_id_string,
29407c478bd9Sstevel@tonic-gate 		    IB_DM_IOC_ID_STRING_LEN);
29417c478bd9Sstevel@tonic-gate 
29427c478bd9Sstevel@tonic-gate 		ioc_info->ioc_iou_diagcode = gid_info->gl_iou->iou_diagcode;
29437c478bd9Sstevel@tonic-gate 		ioc_info->ioc_iou_dc_valid = gid_info->gl_iou->iou_dc_valid;
29447c478bd9Sstevel@tonic-gate 		ioc_info->ioc_diagdeviceid = (IB_DM_IOU_DEVICEID_MASK &
29457c478bd9Sstevel@tonic-gate 		    gid_info->gl_iou->iou_info.iou_flag) ? B_TRUE : B_FALSE;
29467c478bd9Sstevel@tonic-gate 
294753c1b7a3Seota 		if (ioc_info->ioc_diagdeviceid == B_TRUE) {
29487c478bd9Sstevel@tonic-gate 			gid_info->gl_pending_cmds++;
294953c1b7a3Seota 			IBTF_DPRINTF_L3(ibdm_string,
295053c1b7a3Seota 			    "\tibdm_handle_ioc_profile: "
295153c1b7a3Seota 			    "%d: gid_info %p gl_state %d pending_cmds %d",
295253c1b7a3Seota 			    __LINE__, gid_info, gid_info->gl_state,
295353c1b7a3Seota 			    gid_info->gl_pending_cmds);
295453c1b7a3Seota 		}
29557c478bd9Sstevel@tonic-gate 	}
29567c478bd9Sstevel@tonic-gate 	gioc->ioc_service_entries	= ioc->ioc_service_entries;
29577c478bd9Sstevel@tonic-gate 	mutex_exit(&gid_info->gl_mutex);
29587c478bd9Sstevel@tonic-gate 
29597c478bd9Sstevel@tonic-gate 	ibdm_dump_ioc_profile(gioc);
29607c478bd9Sstevel@tonic-gate 
29617c478bd9Sstevel@tonic-gate 	if ((ioc_info->ioc_diagdeviceid == B_TRUE) && (reprobe == 0)) {
29627c478bd9Sstevel@tonic-gate 		if (ibdm_get_diagcode(gid_info, ioc_no) != IBDM_SUCCESS) {
29637c478bd9Sstevel@tonic-gate 			mutex_enter(&gid_info->gl_mutex);
29647c478bd9Sstevel@tonic-gate 			gid_info->gl_pending_cmds--;
29657c478bd9Sstevel@tonic-gate 			mutex_exit(&gid_info->gl_mutex);
29667c478bd9Sstevel@tonic-gate 		}
29677c478bd9Sstevel@tonic-gate 	}
29687c478bd9Sstevel@tonic-gate 	ioc_info->ioc_serv = (ibdm_srvents_info_t *)kmem_zalloc(
29697c478bd9Sstevel@tonic-gate 	    (gioc->ioc_service_entries * sizeof (ibdm_srvents_info_t)),
29707c478bd9Sstevel@tonic-gate 	    KM_SLEEP);
29717c478bd9Sstevel@tonic-gate 
29727c478bd9Sstevel@tonic-gate 	/*
29737c478bd9Sstevel@tonic-gate 	 * In one single request, maximum number of requests that can be
29747c478bd9Sstevel@tonic-gate 	 * obtained is 4. If number of service entries are more than four,
29757c478bd9Sstevel@tonic-gate 	 * calculate number requests needed and send them parallelly.
29767c478bd9Sstevel@tonic-gate 	 */
29777c478bd9Sstevel@tonic-gate 	nserv_entries = ioc->ioc_service_entries;
29787c478bd9Sstevel@tonic-gate 	ii = 0;
29797c478bd9Sstevel@tonic-gate 	while (nserv_entries) {
29809d3d2ed0Shiremath 		mutex_enter(&gid_info->gl_mutex);
298153c1b7a3Seota 		gid_info->gl_pending_cmds++;
29829d3d2ed0Shiremath 		ibdm_bump_transactionID(gid_info);
29839d3d2ed0Shiremath 		mutex_exit(&gid_info->gl_mutex);
29849d3d2ed0Shiremath 
29857c478bd9Sstevel@tonic-gate 		if (first != B_TRUE) {
29867c478bd9Sstevel@tonic-gate 			if (ibmf_alloc_msg(ibmf_hdl, IBMF_ALLOC_SLEEP,
29877c478bd9Sstevel@tonic-gate 			    &msg) != IBMF_SUCCESS) {
29887c478bd9Sstevel@tonic-gate 				continue;
29897c478bd9Sstevel@tonic-gate 			}
29907c478bd9Sstevel@tonic-gate 
29917c478bd9Sstevel@tonic-gate 		}
299218edb70cSeota 		_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*msg))
29937c478bd9Sstevel@tonic-gate 		ibdm_alloc_send_buffers(msg);
299418edb70cSeota 		_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*msg))
29957c478bd9Sstevel@tonic-gate 		msg->im_local_addr.ia_local_lid	= gid_info->gl_slid;
29967c478bd9Sstevel@tonic-gate 		msg->im_local_addr.ia_remote_lid	= gid_info->gl_dlid;
29977c478bd9Sstevel@tonic-gate 		if (gid_info->gl_redirected == B_TRUE) {
29987c478bd9Sstevel@tonic-gate 			if (gid_info->gl_redirect_dlid != 0) {
29997c478bd9Sstevel@tonic-gate 				msg->im_local_addr.ia_remote_lid =
30007c478bd9Sstevel@tonic-gate 				    gid_info->gl_redirect_dlid;
30017c478bd9Sstevel@tonic-gate 			}
30027c478bd9Sstevel@tonic-gate 			msg->im_local_addr.ia_remote_qno =
30037c478bd9Sstevel@tonic-gate 			    gid_info->gl_redirect_QP;
30047c478bd9Sstevel@tonic-gate 			msg->im_local_addr.ia_p_key =
30057c478bd9Sstevel@tonic-gate 			    gid_info->gl_redirect_pkey;
30067c478bd9Sstevel@tonic-gate 			msg->im_local_addr.ia_q_key =
30077c478bd9Sstevel@tonic-gate 			    gid_info->gl_redirect_qkey;
300818edb70cSeota 			msg->im_local_addr.ia_service_level =
300918edb70cSeota 			    gid_info->gl_redirectSL;
30107c478bd9Sstevel@tonic-gate 		} else {
30117c478bd9Sstevel@tonic-gate 			msg->im_local_addr.ia_remote_qno = 1;
30127c478bd9Sstevel@tonic-gate 			msg->im_local_addr.ia_p_key = gid_info->gl_p_key;
30137c478bd9Sstevel@tonic-gate 			msg->im_local_addr.ia_q_key = IB_GSI_QKEY;
301418edb70cSeota 			msg->im_local_addr.ia_service_level = gid_info->gl_SL;
30157c478bd9Sstevel@tonic-gate 		}
30167c478bd9Sstevel@tonic-gate 
30177c478bd9Sstevel@tonic-gate 		hdr			= IBDM_OUT_IBMFMSG_MADHDR(msg);
30187c478bd9Sstevel@tonic-gate 		hdr->BaseVersion	= MAD_CLASS_BASE_VERS_1;
30197c478bd9Sstevel@tonic-gate 		hdr->MgmtClass		= MAD_MGMT_CLASS_DEV_MGT;
30207c478bd9Sstevel@tonic-gate 		hdr->ClassVersion	= IB_DM_CLASS_VERSION_1;
30217c478bd9Sstevel@tonic-gate 		hdr->R_Method		= IB_DM_DEVMGT_METHOD_GET;
30227c478bd9Sstevel@tonic-gate 		hdr->Status		= 0;
30237c478bd9Sstevel@tonic-gate 		hdr->TransactionID	= h2b64(gid_info->gl_transactionID);
30247c478bd9Sstevel@tonic-gate 		hdr->AttributeID	= h2b16(IB_DM_ATTR_SERVICE_ENTRIES);
30257c478bd9Sstevel@tonic-gate 
30267c478bd9Sstevel@tonic-gate 		srv_start = ii * 4;
30277c478bd9Sstevel@tonic-gate 		cb_args = &ioc_info->ioc_serv[srv_start].se_cb_args;
30287c478bd9Sstevel@tonic-gate 		cb_args->cb_gid_info	= gid_info;
30297c478bd9Sstevel@tonic-gate 		cb_args->cb_retry_count	= ibdm_dft_retry_cnt;
30307c478bd9Sstevel@tonic-gate 		cb_args->cb_req_type	= IBDM_REQ_TYPE_SRVENTS;
30317c478bd9Sstevel@tonic-gate 		cb_args->cb_srvents_start = srv_start;
30327c478bd9Sstevel@tonic-gate 		cb_args->cb_ioc_num	= ioc_no - 1;
30337c478bd9Sstevel@tonic-gate 
30347c478bd9Sstevel@tonic-gate 		if (nserv_entries >= IBDM_MAX_SERV_ENTRIES_PER_REQ) {
30357c478bd9Sstevel@tonic-gate 			nserv_entries -= IBDM_MAX_SERV_ENTRIES_PER_REQ;
30367c478bd9Sstevel@tonic-gate 			cb_args->cb_srvents_end = (cb_args->cb_srvents_start +
30377c478bd9Sstevel@tonic-gate 			    IBDM_MAX_SERV_ENTRIES_PER_REQ - 1);
30387c478bd9Sstevel@tonic-gate 		} else {
30397c478bd9Sstevel@tonic-gate 			cb_args->cb_srvents_end =
30407c478bd9Sstevel@tonic-gate 			    (cb_args->cb_srvents_start + nserv_entries - 1);
30417c478bd9Sstevel@tonic-gate 			nserv_entries = 0;
30427c478bd9Sstevel@tonic-gate 		}
304318edb70cSeota 		_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*hdr))
30449d3d2ed0Shiremath 		ibdm_fill_srv_attr_mod(hdr, cb_args);
304518edb70cSeota 		_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*hdr))
30467c478bd9Sstevel@tonic-gate 
304718edb70cSeota 		mutex_enter(&gid_info->gl_mutex);
30487c478bd9Sstevel@tonic-gate 		ioc_info->ioc_serv[srv_start].se_timeout_id = timeout(
30497c478bd9Sstevel@tonic-gate 		    ibdm_pkt_timeout_hdlr, cb_args,
30507c478bd9Sstevel@tonic-gate 		    IBDM_TIMEOUT_VALUE(ibdm_dft_timeout));
305118edb70cSeota 		mutex_exit(&gid_info->gl_mutex);
30527c478bd9Sstevel@tonic-gate 
30537c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L5("ibdm", "\thandle_ioc_profile:"
30547c478bd9Sstevel@tonic-gate 		    "timeout %x, ioc %d srv %d",
30557c478bd9Sstevel@tonic-gate 		    ioc_info->ioc_serv[srv_start].se_timeout_id,
30567c478bd9Sstevel@tonic-gate 		    ioc_no - 1, srv_start);
30577c478bd9Sstevel@tonic-gate 
30587c478bd9Sstevel@tonic-gate 		if (ibmf_msg_transport(ibmf_hdl, gid_info->gl_qp_hdl, msg,
30597c478bd9Sstevel@tonic-gate 		    NULL, ibdm_ibmf_send_cb, cb_args, 0) != IBMF_SUCCESS) {
30607c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibdm",
30617c478bd9Sstevel@tonic-gate 			    "\thandle_ioc_profile: msg send failed");
30627c478bd9Sstevel@tonic-gate 			ibdm_ibmf_send_cb(ibmf_hdl, msg, cb_args);
30637c478bd9Sstevel@tonic-gate 		}
30647c478bd9Sstevel@tonic-gate 		(*flag) |= IBDM_IBMF_PKT_REUSED;
30657c478bd9Sstevel@tonic-gate 		first = B_FALSE;
30667c478bd9Sstevel@tonic-gate 		ii++;
30677c478bd9Sstevel@tonic-gate 	}
30687c478bd9Sstevel@tonic-gate }
30697c478bd9Sstevel@tonic-gate 
30707c478bd9Sstevel@tonic-gate 
30717c478bd9Sstevel@tonic-gate /*
30727c478bd9Sstevel@tonic-gate  * ibdm_handle_srventry_mad()
30737c478bd9Sstevel@tonic-gate  */
30747c478bd9Sstevel@tonic-gate static void
ibdm_handle_srventry_mad(ibmf_msg_t * msg,ibdm_dp_gidinfo_t * gid_info,int * flag)30757c478bd9Sstevel@tonic-gate ibdm_handle_srventry_mad(ibmf_msg_t *msg,
30767c478bd9Sstevel@tonic-gate     ibdm_dp_gidinfo_t *gid_info, int *flag)
30777c478bd9Sstevel@tonic-gate {
30787c478bd9Sstevel@tonic-gate 	uint_t			ii, ioc_no, attrmod;
30797c478bd9Sstevel@tonic-gate 	uint_t			nentries, start, end;
30807c478bd9Sstevel@tonic-gate 	timeout_id_t		timeout_id;
30817c478bd9Sstevel@tonic-gate 	ib_dm_srv_t		*srv_ents;
30827c478bd9Sstevel@tonic-gate 	ibdm_ioc_info_t		*ioc_info;
30837c478bd9Sstevel@tonic-gate 	ibdm_srvents_info_t	*gsrv_ents;
30847c478bd9Sstevel@tonic-gate 
30857c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\thandle_srventry_mad:"
30867c478bd9Sstevel@tonic-gate 	    " IBMF msg %p gid info %p", msg, gid_info);
30877c478bd9Sstevel@tonic-gate 
30887c478bd9Sstevel@tonic-gate 	srv_ents = IBDM_IN_IBMFMSG2SRVENT(msg);
30897c478bd9Sstevel@tonic-gate 	/*
30907c478bd9Sstevel@tonic-gate 	 * Get the start and end index of the service entries
30917c478bd9Sstevel@tonic-gate 	 * Upper 16 bits identify the IOC
30927c478bd9Sstevel@tonic-gate 	 * Lower 16 bits specify the range of service entries
30937c478bd9Sstevel@tonic-gate 	 * 	LSB specifies (Big endian) end of the range
30947c478bd9Sstevel@tonic-gate 	 * 	MSB specifies (Big endian) start of the range
30957c478bd9Sstevel@tonic-gate 	 */
30967c478bd9Sstevel@tonic-gate 	attrmod = IBDM_IN_IBMFMSG_ATTRMOD(msg);
30977c478bd9Sstevel@tonic-gate 	ioc_no	= ((attrmod >> 16) & IBDM_16_BIT_MASK);
30989d3d2ed0Shiremath 	end	= ((attrmod >> 8) & IBDM_8_BIT_MASK);
30999d3d2ed0Shiremath 	start	= (attrmod & IBDM_8_BIT_MASK);
31007c478bd9Sstevel@tonic-gate 
31017c478bd9Sstevel@tonic-gate 	/* Make sure that IOC index is with the valid range */
31027c478bd9Sstevel@tonic-gate 	if ((ioc_no < 1) |
31037c478bd9Sstevel@tonic-gate 	    (ioc_no > gid_info->gl_iou->iou_info.iou_num_ctrl_slots)) {
31047c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibdm", "\thandle_srventry_mad: "
31057c478bd9Sstevel@tonic-gate 		    "IOC index Out of range, index %d", ioc_no);
31067c478bd9Sstevel@tonic-gate 		(*flag) |= IBDM_IBMF_PKT_UNEXP_RESP;
31077c478bd9Sstevel@tonic-gate 		return;
31087c478bd9Sstevel@tonic-gate 	}
31097c478bd9Sstevel@tonic-gate 	ioc_info = IBDM_GIDINFO2IOCINFO(gid_info, (ioc_no -1));
31107c478bd9Sstevel@tonic-gate 
31117c478bd9Sstevel@tonic-gate 	/*
31127c478bd9Sstevel@tonic-gate 	 * Make sure that the "start" and "end" service indexes are
31137c478bd9Sstevel@tonic-gate 	 * with in the valid range
31147c478bd9Sstevel@tonic-gate 	 */
31157c478bd9Sstevel@tonic-gate 	nentries = ioc_info->ioc_profile.ioc_service_entries;
31167c478bd9Sstevel@tonic-gate 	if ((start > end) | (start >= nentries) | (end >= nentries)) {
31177c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibdm", "\thandle_srventry_mad: "
31187c478bd9Sstevel@tonic-gate 		    "Attr modifier 0x%x, #Serv entries %d", attrmod, nentries);
31197c478bd9Sstevel@tonic-gate 		(*flag) |= IBDM_IBMF_PKT_UNEXP_RESP;
31207c478bd9Sstevel@tonic-gate 		return;
31217c478bd9Sstevel@tonic-gate 	}
31227c478bd9Sstevel@tonic-gate 	gsrv_ents = &ioc_info->ioc_serv[start];
31237c478bd9Sstevel@tonic-gate 	mutex_enter(&gid_info->gl_mutex);
31247c478bd9Sstevel@tonic-gate 	if (gsrv_ents->se_state != IBDM_SE_INVALID) {
31257c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibdm", "\thandle_srventry_mad: "
312653c1b7a3Seota 		    "already known, ioc %d, srv %d, se_state %x",
31277c478bd9Sstevel@tonic-gate 		    ioc_no - 1, start, gsrv_ents->se_state);
31287c478bd9Sstevel@tonic-gate 		mutex_exit(&gid_info->gl_mutex);
31297c478bd9Sstevel@tonic-gate 		(*flag) |= IBDM_IBMF_PKT_DUP_RESP;
31307c478bd9Sstevel@tonic-gate 		return;
31317c478bd9Sstevel@tonic-gate 	}
31327c478bd9Sstevel@tonic-gate 	ioc_info->ioc_serv[start].se_cb_args.cb_req_type = 0;
31337c478bd9Sstevel@tonic-gate 	if (ioc_info->ioc_serv[start].se_timeout_id) {
31347c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibdm",
31357c478bd9Sstevel@tonic-gate 		    "\thandle_srventry_mad: ioc %d start %d", ioc_no, start);
31367c478bd9Sstevel@tonic-gate 		timeout_id = ioc_info->ioc_serv[start].se_timeout_id;
313718edb70cSeota 		ioc_info->ioc_serv[start].se_timeout_id = 0;
31387c478bd9Sstevel@tonic-gate 		mutex_exit(&gid_info->gl_mutex);
31397c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L5("ibdm", "handle_srverntry_mad: "
31407c478bd9Sstevel@tonic-gate 		    "se_timeout_id = 0x%x", timeout_id);
31417c478bd9Sstevel@tonic-gate 		if (untimeout(timeout_id) == -1) {
31427c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibdm", "handle_srventry_mad: "
31437c478bd9Sstevel@tonic-gate 			    "untimeout se_timeout_id failed");
31447c478bd9Sstevel@tonic-gate 		}
31457c478bd9Sstevel@tonic-gate 		mutex_enter(&gid_info->gl_mutex);
31467c478bd9Sstevel@tonic-gate 	}
31477c478bd9Sstevel@tonic-gate 
31487c478bd9Sstevel@tonic-gate 	gsrv_ents->se_state = IBDM_SE_VALID;
31497c478bd9Sstevel@tonic-gate 	mutex_exit(&gid_info->gl_mutex);
31507c478bd9Sstevel@tonic-gate 	for (ii = start; ii <= end; ii++, srv_ents++, gsrv_ents++) {
31519d3d2ed0Shiremath 		gsrv_ents->se_attr.srv_id = b2h64(srv_ents->srv_id);
31527c478bd9Sstevel@tonic-gate 		bcopy(srv_ents->srv_name,
31537c478bd9Sstevel@tonic-gate 		    gsrv_ents->se_attr.srv_name, IB_DM_MAX_SVC_NAME_LEN);
31547c478bd9Sstevel@tonic-gate 		ibdm_dump_service_entries(&gsrv_ents->se_attr);
31557c478bd9Sstevel@tonic-gate 	}
31567c478bd9Sstevel@tonic-gate }
31577c478bd9Sstevel@tonic-gate 
31587c478bd9Sstevel@tonic-gate 
31597c478bd9Sstevel@tonic-gate /*
31607c478bd9Sstevel@tonic-gate  * ibdm_get_diagcode:
31617c478bd9Sstevel@tonic-gate  *	Send request to get IOU/IOC diag code
31627c478bd9Sstevel@tonic-gate  *	Returns IBDM_SUCCESS/IBDM_FAILURE
31637c478bd9Sstevel@tonic-gate  */
31647c478bd9Sstevel@tonic-gate static int
ibdm_get_diagcode(ibdm_dp_gidinfo_t * gid_info,int attr)31657c478bd9Sstevel@tonic-gate ibdm_get_diagcode(ibdm_dp_gidinfo_t *gid_info, int attr)
31667c478bd9Sstevel@tonic-gate {
31677c478bd9Sstevel@tonic-gate 	ibmf_msg_t		*msg;
31687c478bd9Sstevel@tonic-gate 	ib_mad_hdr_t		*hdr;
31697c478bd9Sstevel@tonic-gate 	ibdm_ioc_info_t		*ioc;
31707c478bd9Sstevel@tonic-gate 	ibdm_timeout_cb_args_t	*cb_args;
31717c478bd9Sstevel@tonic-gate 	timeout_id_t		*timeout_id;
31727c478bd9Sstevel@tonic-gate 
31737c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tget_diagcode: gid info %p, attr = %d",
31747c478bd9Sstevel@tonic-gate 	    gid_info, attr);
31757c478bd9Sstevel@tonic-gate 
31767c478bd9Sstevel@tonic-gate 	if (ibmf_alloc_msg(gid_info->gl_ibmf_hdl, IBMF_ALLOC_SLEEP,
31777c478bd9Sstevel@tonic-gate 	    &msg) != IBMF_SUCCESS) {
31787c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibdm", "\tget_diagcode: pkt alloc fail");
31797c478bd9Sstevel@tonic-gate 		return (IBDM_FAILURE);
31807c478bd9Sstevel@tonic-gate 	}
31817c478bd9Sstevel@tonic-gate 
318218edb70cSeota 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*msg))
31837c478bd9Sstevel@tonic-gate 	ibdm_alloc_send_buffers(msg);
318418edb70cSeota 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*msg))
31857c478bd9Sstevel@tonic-gate 
31869d3d2ed0Shiremath 	mutex_enter(&gid_info->gl_mutex);
31879d3d2ed0Shiremath 	ibdm_bump_transactionID(gid_info);
31889d3d2ed0Shiremath 	mutex_exit(&gid_info->gl_mutex);
31899d3d2ed0Shiremath 
31907c478bd9Sstevel@tonic-gate 	msg->im_local_addr.ia_local_lid	= gid_info->gl_slid;
31917c478bd9Sstevel@tonic-gate 	msg->im_local_addr.ia_remote_lid	= gid_info->gl_dlid;
31927c478bd9Sstevel@tonic-gate 	if (gid_info->gl_redirected == B_TRUE) {
31937c478bd9Sstevel@tonic-gate 		if (gid_info->gl_redirect_dlid != 0) {
31947c478bd9Sstevel@tonic-gate 			msg->im_local_addr.ia_remote_lid =
31957c478bd9Sstevel@tonic-gate 			    gid_info->gl_redirect_dlid;
31967c478bd9Sstevel@tonic-gate 		}
31977c478bd9Sstevel@tonic-gate 
31987c478bd9Sstevel@tonic-gate 		msg->im_local_addr.ia_remote_qno = gid_info->gl_redirect_QP;
31997c478bd9Sstevel@tonic-gate 		msg->im_local_addr.ia_p_key = gid_info->gl_redirect_pkey;
32007c478bd9Sstevel@tonic-gate 		msg->im_local_addr.ia_q_key = gid_info->gl_redirect_qkey;
320118edb70cSeota 		msg->im_local_addr.ia_service_level = gid_info->gl_redirectSL;
32027c478bd9Sstevel@tonic-gate 	} else {
32037c478bd9Sstevel@tonic-gate 		msg->im_local_addr.ia_remote_qno = 1;
32047c478bd9Sstevel@tonic-gate 		msg->im_local_addr.ia_p_key = gid_info->gl_p_key;
32057c478bd9Sstevel@tonic-gate 		msg->im_local_addr.ia_q_key = IB_GSI_QKEY;
320618edb70cSeota 		msg->im_local_addr.ia_service_level = gid_info->gl_SL;
32077c478bd9Sstevel@tonic-gate 	}
32087c478bd9Sstevel@tonic-gate 
32097c478bd9Sstevel@tonic-gate 	hdr			= IBDM_OUT_IBMFMSG_MADHDR(msg);
32107c478bd9Sstevel@tonic-gate 	hdr->BaseVersion	= MAD_CLASS_BASE_VERS_1;
32117c478bd9Sstevel@tonic-gate 	hdr->MgmtClass		= MAD_MGMT_CLASS_DEV_MGT;
32127c478bd9Sstevel@tonic-gate 	hdr->ClassVersion	= IB_DM_CLASS_VERSION_1;
32137c478bd9Sstevel@tonic-gate 	hdr->R_Method		= IB_DM_DEVMGT_METHOD_GET;
32147c478bd9Sstevel@tonic-gate 	hdr->Status		= 0;
32157c478bd9Sstevel@tonic-gate 	hdr->TransactionID	= h2b64(gid_info->gl_transactionID);
32167c478bd9Sstevel@tonic-gate 
32177c478bd9Sstevel@tonic-gate 	hdr->AttributeID	= h2b16(IB_DM_ATTR_DIAG_CODE);
32187c478bd9Sstevel@tonic-gate 	hdr->AttributeModifier	= h2b32(attr);
32197c478bd9Sstevel@tonic-gate 
32207c478bd9Sstevel@tonic-gate 	if (attr == 0) {
32217c478bd9Sstevel@tonic-gate 		cb_args = &gid_info->gl_iou_cb_args;
32227c478bd9Sstevel@tonic-gate 		gid_info->gl_iou->iou_dc_valid = B_FALSE;
32237c478bd9Sstevel@tonic-gate 		cb_args->cb_ioc_num	= 0;
32247c478bd9Sstevel@tonic-gate 		cb_args->cb_req_type	= IBDM_REQ_TYPE_IOU_DIAGCODE;
32257c478bd9Sstevel@tonic-gate 		timeout_id = &gid_info->gl_timeout_id;
32267c478bd9Sstevel@tonic-gate 	} else {
32277c478bd9Sstevel@tonic-gate 		ioc = IBDM_GIDINFO2IOCINFO(gid_info, (attr - 1));
32287c478bd9Sstevel@tonic-gate 		ioc->ioc_dc_valid = B_FALSE;
32297c478bd9Sstevel@tonic-gate 		cb_args = &ioc->ioc_dc_cb_args;
32307c478bd9Sstevel@tonic-gate 		cb_args->cb_ioc_num	= attr - 1;
32317c478bd9Sstevel@tonic-gate 		cb_args->cb_req_type	= IBDM_REQ_TYPE_IOC_DIAGCODE;
32327c478bd9Sstevel@tonic-gate 		timeout_id = &ioc->ioc_dc_timeout_id;
32337c478bd9Sstevel@tonic-gate 	}
32347c478bd9Sstevel@tonic-gate 	cb_args->cb_gid_info	= gid_info;
32357c478bd9Sstevel@tonic-gate 	cb_args->cb_retry_count	= ibdm_dft_retry_cnt;
32367c478bd9Sstevel@tonic-gate 	cb_args->cb_srvents_start = 0;
32377c478bd9Sstevel@tonic-gate 
323818edb70cSeota 	mutex_enter(&gid_info->gl_mutex);
32397c478bd9Sstevel@tonic-gate 	*timeout_id = timeout(ibdm_pkt_timeout_hdlr,
32407c478bd9Sstevel@tonic-gate 	    cb_args, IBDM_TIMEOUT_VALUE(ibdm_dft_timeout));
324118edb70cSeota 	mutex_exit(&gid_info->gl_mutex);
32427c478bd9Sstevel@tonic-gate 
32437c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L5("ibdm", "\tget_diagcode:"
32447c478bd9Sstevel@tonic-gate 	    "timeout %x, ioc %d", *timeout_id, cb_args->cb_ioc_num);
32457c478bd9Sstevel@tonic-gate 
32467c478bd9Sstevel@tonic-gate 	if (ibmf_msg_transport(gid_info->gl_ibmf_hdl, gid_info->gl_qp_hdl,
32477c478bd9Sstevel@tonic-gate 	    msg, NULL, ibdm_ibmf_send_cb, cb_args, 0) != IBMF_SUCCESS) {
32487c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibdm", "\tget_diagcode: ibmf send failed");
32497c478bd9Sstevel@tonic-gate 		ibdm_ibmf_send_cb(gid_info->gl_ibmf_hdl, msg, cb_args);
32507c478bd9Sstevel@tonic-gate 	}
32517c478bd9Sstevel@tonic-gate 	return (IBDM_SUCCESS);
32527c478bd9Sstevel@tonic-gate }
32537c478bd9Sstevel@tonic-gate 
32547c478bd9Sstevel@tonic-gate /*
32557c478bd9Sstevel@tonic-gate  * ibdm_handle_diagcode:
32567c478bd9Sstevel@tonic-gate  *	Process the DiagCode MAD response and update local DM
32577c478bd9Sstevel@tonic-gate  *	data structure.
32587c478bd9Sstevel@tonic-gate  */
32597c478bd9Sstevel@tonic-gate static void
ibdm_handle_diagcode(ibmf_msg_t * ibmf_msg,ibdm_dp_gidinfo_t * gid_info,int * flag)32607c478bd9Sstevel@tonic-gate ibdm_handle_diagcode(ibmf_msg_t *ibmf_msg,
32617c478bd9Sstevel@tonic-gate     ibdm_dp_gidinfo_t *gid_info, int *flag)
32627c478bd9Sstevel@tonic-gate {
32637c478bd9Sstevel@tonic-gate 	uint16_t	attrmod, *diagcode;
32647c478bd9Sstevel@tonic-gate 	ibdm_iou_info_t	*iou;
32657c478bd9Sstevel@tonic-gate 	ibdm_ioc_info_t	*ioc;
32667c478bd9Sstevel@tonic-gate 	timeout_id_t	timeout_id;
32677c478bd9Sstevel@tonic-gate 	ibdm_timeout_cb_args_t	*cb_args;
32687c478bd9Sstevel@tonic-gate 
32697c478bd9Sstevel@tonic-gate 	diagcode = (uint16_t *)ibmf_msg->im_msgbufs_recv.im_bufs_cl_data;
32707c478bd9Sstevel@tonic-gate 
32717c478bd9Sstevel@tonic-gate 	mutex_enter(&gid_info->gl_mutex);
32727c478bd9Sstevel@tonic-gate 	attrmod = IBDM_IN_IBMFMSG_ATTRMOD(ibmf_msg);
32737c478bd9Sstevel@tonic-gate 	iou = gid_info->gl_iou;
32747c478bd9Sstevel@tonic-gate 	if (attrmod == 0) {
32757c478bd9Sstevel@tonic-gate 		if (iou->iou_dc_valid != B_FALSE) {
32767c478bd9Sstevel@tonic-gate 			(*flag) |= IBDM_IBMF_PKT_DUP_RESP;
32777c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibdm",
32787c478bd9Sstevel@tonic-gate 			    "\thandle_diagcode: Duplicate IOU DiagCode");
32797c478bd9Sstevel@tonic-gate 			mutex_exit(&gid_info->gl_mutex);
32807c478bd9Sstevel@tonic-gate 			return;
32817c478bd9Sstevel@tonic-gate 		}
32827c478bd9Sstevel@tonic-gate 		cb_args = &gid_info->gl_iou_cb_args;
32837c478bd9Sstevel@tonic-gate 		cb_args->cb_req_type = 0;
32847c478bd9Sstevel@tonic-gate 		iou->iou_diagcode = b2h16(*diagcode);
32857c478bd9Sstevel@tonic-gate 		iou->iou_dc_valid = B_TRUE;
32867c478bd9Sstevel@tonic-gate 		if (gid_info->gl_timeout_id) {
32877c478bd9Sstevel@tonic-gate 			timeout_id = gid_info->gl_timeout_id;
32887c478bd9Sstevel@tonic-gate 			mutex_exit(&gid_info->gl_mutex);
32897c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L5("ibdm", "\thandle_diagcode: "
32907c478bd9Sstevel@tonic-gate 			    "gl_timeout_id = 0x%x", timeout_id);
32917c478bd9Sstevel@tonic-gate 			if (untimeout(timeout_id) == -1) {
32927c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibdm", "handle_diagcode: "
32937c478bd9Sstevel@tonic-gate 				    "untimeout gl_timeout_id failed");
32947c478bd9Sstevel@tonic-gate 			}
32957c478bd9Sstevel@tonic-gate 			mutex_enter(&gid_info->gl_mutex);
32967c478bd9Sstevel@tonic-gate 			gid_info->gl_timeout_id = 0;
32977c478bd9Sstevel@tonic-gate 		}
32987c478bd9Sstevel@tonic-gate 	} else {
32997c478bd9Sstevel@tonic-gate 		ioc = IBDM_GIDINFO2IOCINFO(gid_info, (attrmod - 1));
33007c478bd9Sstevel@tonic-gate 		if (ioc->ioc_dc_valid != B_FALSE) {
33017c478bd9Sstevel@tonic-gate 			(*flag) |= IBDM_IBMF_PKT_DUP_RESP;
33027c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibdm",
33037c478bd9Sstevel@tonic-gate 			    "\thandle_diagcode: Duplicate IOC DiagCode");
33047c478bd9Sstevel@tonic-gate 			mutex_exit(&gid_info->gl_mutex);
33057c478bd9Sstevel@tonic-gate 			return;
33067c478bd9Sstevel@tonic-gate 		}
33077c478bd9Sstevel@tonic-gate 		cb_args = &ioc->ioc_dc_cb_args;
33087c478bd9Sstevel@tonic-gate 		cb_args->cb_req_type = 0;
33097c478bd9Sstevel@tonic-gate 		ioc->ioc_diagcode = b2h16(*diagcode);
33107c478bd9Sstevel@tonic-gate 		ioc->ioc_dc_valid = B_TRUE;
33117c478bd9Sstevel@tonic-gate 		timeout_id = iou->iou_ioc_info[attrmod - 1].ioc_dc_timeout_id;
33127c478bd9Sstevel@tonic-gate 		if (timeout_id) {
331318edb70cSeota 			iou->iou_ioc_info[attrmod - 1].ioc_dc_timeout_id = 0;
33147c478bd9Sstevel@tonic-gate 			mutex_exit(&gid_info->gl_mutex);
33157c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L5("ibdm", "handle_diagcode: "
33167c478bd9Sstevel@tonic-gate 			    "timeout_id = 0x%x", timeout_id);
33177c478bd9Sstevel@tonic-gate 			if (untimeout(timeout_id) == -1) {
33187c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibdm", "\thandle_diagcode: "
33197c478bd9Sstevel@tonic-gate 				    "untimeout ioc_dc_timeout_id failed");
33207c478bd9Sstevel@tonic-gate 			}
33217c478bd9Sstevel@tonic-gate 			mutex_enter(&gid_info->gl_mutex);
33227c478bd9Sstevel@tonic-gate 		}
33237c478bd9Sstevel@tonic-gate 	}
33247c478bd9Sstevel@tonic-gate 	mutex_exit(&gid_info->gl_mutex);
33257c478bd9Sstevel@tonic-gate 
33267c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\thandle_diagcode: DiagCode : 0x%x"
33277c478bd9Sstevel@tonic-gate 	    "attrmod : 0x%x", b2h16(*diagcode), attrmod);
33287c478bd9Sstevel@tonic-gate }
33297c478bd9Sstevel@tonic-gate 
33307c478bd9Sstevel@tonic-gate 
33317c478bd9Sstevel@tonic-gate /*
33327c478bd9Sstevel@tonic-gate  * ibdm_is_ioc_present()
33337c478bd9Sstevel@tonic-gate  *	Return ibdm_ioc_info_t if IOC guid is found in the global gid list
33347c478bd9Sstevel@tonic-gate  */
33357c478bd9Sstevel@tonic-gate static ibdm_ioc_info_t *
ibdm_is_ioc_present(ib_guid_t ioc_guid,ibdm_dp_gidinfo_t * gid_info,int * flag)33367c478bd9Sstevel@tonic-gate ibdm_is_ioc_present(ib_guid_t ioc_guid,
33377c478bd9Sstevel@tonic-gate     ibdm_dp_gidinfo_t *gid_info, int *flag)
33387c478bd9Sstevel@tonic-gate {
33397c478bd9Sstevel@tonic-gate 	int				ii;
33407c478bd9Sstevel@tonic-gate 	ibdm_ioc_info_t			*ioc;
33417c478bd9Sstevel@tonic-gate 	ibdm_dp_gidinfo_t		*head;
33427c478bd9Sstevel@tonic-gate 	ib_dm_io_unitinfo_t		*iou;
33437c478bd9Sstevel@tonic-gate 
33447c478bd9Sstevel@tonic-gate 	mutex_enter(&ibdm.ibdm_mutex);
33457c478bd9Sstevel@tonic-gate 	head = ibdm.ibdm_dp_gidlist_head;
33467c478bd9Sstevel@tonic-gate 	while (head) {
33477c478bd9Sstevel@tonic-gate 		mutex_enter(&head->gl_mutex);
33487c478bd9Sstevel@tonic-gate 		if (head->gl_iou == NULL) {
33497c478bd9Sstevel@tonic-gate 			mutex_exit(&head->gl_mutex);
33507c478bd9Sstevel@tonic-gate 			head = head->gl_next;
33517c478bd9Sstevel@tonic-gate 			continue;
33527c478bd9Sstevel@tonic-gate 		}
33537c478bd9Sstevel@tonic-gate 		iou = &head->gl_iou->iou_info;
33547c478bd9Sstevel@tonic-gate 		for (ii = 0; ii < iou->iou_num_ctrl_slots; ii++) {
33557c478bd9Sstevel@tonic-gate 			ioc = IBDM_GIDINFO2IOCINFO(head, ii);
33567c478bd9Sstevel@tonic-gate 			if ((ioc->ioc_state == IBDM_IOC_STATE_PROBE_SUCCESS) &&
33577c478bd9Sstevel@tonic-gate 			    (ioc->ioc_profile.ioc_guid == ioc_guid)) {
33587c478bd9Sstevel@tonic-gate 				if (gid_info == head) {
33597c478bd9Sstevel@tonic-gate 					*flag |= IBDM_IBMF_PKT_DUP_RESP;
33607c478bd9Sstevel@tonic-gate 				} else if (ibdm_check_dgid(head->gl_dgid_lo,
33617c478bd9Sstevel@tonic-gate 				    head->gl_dgid_hi) != NULL) {
33627c478bd9Sstevel@tonic-gate 					IBTF_DPRINTF_L4("ibdm", "\tis_ioc_"
33637c478bd9Sstevel@tonic-gate 					    "present: gid not present");
33647c478bd9Sstevel@tonic-gate 					ibdm_add_to_gl_gid(gid_info, head);
33657c478bd9Sstevel@tonic-gate 				}
33667c478bd9Sstevel@tonic-gate 				mutex_exit(&head->gl_mutex);
33677c478bd9Sstevel@tonic-gate 				mutex_exit(&ibdm.ibdm_mutex);
33687c478bd9Sstevel@tonic-gate 				return (ioc);
33697c478bd9Sstevel@tonic-gate 			}
33707c478bd9Sstevel@tonic-gate 		}
33717c478bd9Sstevel@tonic-gate 		mutex_exit(&head->gl_mutex);
33727c478bd9Sstevel@tonic-gate 		head = head->gl_next;
33737c478bd9Sstevel@tonic-gate 	}
33747c478bd9Sstevel@tonic-gate 	mutex_exit(&ibdm.ibdm_mutex);
33757c478bd9Sstevel@tonic-gate 	return (NULL);
33767c478bd9Sstevel@tonic-gate }
33777c478bd9Sstevel@tonic-gate 
33787c478bd9Sstevel@tonic-gate 
33797c478bd9Sstevel@tonic-gate /*
33807c478bd9Sstevel@tonic-gate  * ibdm_ibmf_send_cb()
33817c478bd9Sstevel@tonic-gate  *	IBMF invokes this callback routine after posting the DM MAD to
33827c478bd9Sstevel@tonic-gate  *	the HCA.
33837c478bd9Sstevel@tonic-gate  */
33847c478bd9Sstevel@tonic-gate /*ARGSUSED*/
33857c478bd9Sstevel@tonic-gate static void
ibdm_ibmf_send_cb(ibmf_handle_t ibmf_hdl,ibmf_msg_t * ibmf_msg,void * arg)33867c478bd9Sstevel@tonic-gate ibdm_ibmf_send_cb(ibmf_handle_t ibmf_hdl, ibmf_msg_t *ibmf_msg, void *arg)
33877c478bd9Sstevel@tonic-gate {
33887c478bd9Sstevel@tonic-gate 	ibdm_dump_ibmf_msg(ibmf_msg, 1);
33897c478bd9Sstevel@tonic-gate 	ibdm_free_send_buffers(ibmf_msg);
33907c478bd9Sstevel@tonic-gate 	if (ibmf_free_msg(ibmf_hdl, &ibmf_msg) != IBMF_SUCCESS) {
33917c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibdm",
33927c478bd9Sstevel@tonic-gate 		    "\tibmf_send_cb: IBMF free msg failed");
33937c478bd9Sstevel@tonic-gate 	}
33947c478bd9Sstevel@tonic-gate }
33957c478bd9Sstevel@tonic-gate 
33967c478bd9Sstevel@tonic-gate 
33977c478bd9Sstevel@tonic-gate /*
33987c478bd9Sstevel@tonic-gate  * ibdm_ibmf_recv_cb()
33997c478bd9Sstevel@tonic-gate  *	Invoked by the IBMF when a response to the one of the DM requests
34007c478bd9Sstevel@tonic-gate  *	is received.
34017c478bd9Sstevel@tonic-gate  */
34027c478bd9Sstevel@tonic-gate /*ARGSUSED*/
34037c478bd9Sstevel@tonic-gate static void
ibdm_ibmf_recv_cb(ibmf_handle_t ibmf_hdl,ibmf_msg_t * msg,void * arg)34047c478bd9Sstevel@tonic-gate ibdm_ibmf_recv_cb(ibmf_handle_t ibmf_hdl, ibmf_msg_t *msg, void *arg)
34057c478bd9Sstevel@tonic-gate {
34067c478bd9Sstevel@tonic-gate 	ibdm_taskq_args_t	*taskq_args;
34077c478bd9Sstevel@tonic-gate 
34087c478bd9Sstevel@tonic-gate 	/*
34097c478bd9Sstevel@tonic-gate 	 * If the taskq enable is set then dispatch a taskq to process
34107c478bd9Sstevel@tonic-gate 	 * the MAD, otherwise just process it on this thread
34117c478bd9Sstevel@tonic-gate 	 */
34127c478bd9Sstevel@tonic-gate 	if (ibdm_taskq_enable != IBDM_ENABLE_TASKQ_HANDLING) {
34137c478bd9Sstevel@tonic-gate 		ibdm_process_incoming_mad(ibmf_hdl, msg, arg);
34147c478bd9Sstevel@tonic-gate 		return;
34157c478bd9Sstevel@tonic-gate 	}
34167c478bd9Sstevel@tonic-gate 
34177c478bd9Sstevel@tonic-gate 	/*
34187c478bd9Sstevel@tonic-gate 	 * create a taskq and dispatch it to process the incoming MAD
34197c478bd9Sstevel@tonic-gate 	 */
34207c478bd9Sstevel@tonic-gate 	taskq_args = kmem_alloc(sizeof (ibdm_taskq_args_t), KM_NOSLEEP);
34217c478bd9Sstevel@tonic-gate 	if (taskq_args == NULL) {
34227c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibdm", "ibmf_recv_cb: kmem_alloc failed for"
34237c478bd9Sstevel@tonic-gate 		    "taskq_args");
34247c478bd9Sstevel@tonic-gate 		if (ibmf_free_msg(ibmf_hdl, &msg) != IBMF_SUCCESS) {
34257c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibmf_recv_cb",
34267c478bd9Sstevel@tonic-gate 			    "\tibmf_recv_cb: IBMF free msg failed");
34277c478bd9Sstevel@tonic-gate 		}
34287c478bd9Sstevel@tonic-gate 		return;
34297c478bd9Sstevel@tonic-gate 	}
34307c478bd9Sstevel@tonic-gate 	taskq_args->tq_ibmf_handle = ibmf_hdl;
34317c478bd9Sstevel@tonic-gate 	taskq_args->tq_ibmf_msg = msg;
34327c478bd9Sstevel@tonic-gate 	taskq_args->tq_args = arg;
34337c478bd9Sstevel@tonic-gate 
34347c478bd9Sstevel@tonic-gate 	if (taskq_dispatch(system_taskq, ibdm_recv_incoming_mad, taskq_args,
3435*fc8ae2ecSToomas Soome 	    TQ_NOSLEEP) == TASKQID_INVALID) {
34367c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibdm", "ibmf_recv_cb: taskq_dispatch failed");
34377c478bd9Sstevel@tonic-gate 		if (ibmf_free_msg(ibmf_hdl, &msg) != IBMF_SUCCESS) {
34387c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibmf_recv_cb",
34397c478bd9Sstevel@tonic-gate 			    "\tibmf_recv_cb: IBMF free msg failed");
34407c478bd9Sstevel@tonic-gate 		}
34417c478bd9Sstevel@tonic-gate 		kmem_free(taskq_args, sizeof (ibdm_taskq_args_t));
34427c478bd9Sstevel@tonic-gate 		return;
34437c478bd9Sstevel@tonic-gate 	}
34447c478bd9Sstevel@tonic-gate 
34457c478bd9Sstevel@tonic-gate 	/* taskq_args are deleted in ibdm_recv_incoming_mad() */
34467c478bd9Sstevel@tonic-gate }
34477c478bd9Sstevel@tonic-gate 
34487c478bd9Sstevel@tonic-gate 
34497c478bd9Sstevel@tonic-gate void
ibdm_recv_incoming_mad(void * args)34507c478bd9Sstevel@tonic-gate ibdm_recv_incoming_mad(void *args)
34517c478bd9Sstevel@tonic-gate {
34527c478bd9Sstevel@tonic-gate 	ibdm_taskq_args_t	*taskq_args;
34537c478bd9Sstevel@tonic-gate 
34547c478bd9Sstevel@tonic-gate 	taskq_args = (ibdm_taskq_args_t *)args;
34557c478bd9Sstevel@tonic-gate 
34567c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tibdm_recv_incoming_mad: "
34577c478bd9Sstevel@tonic-gate 	    "Processing incoming MAD via taskq");
34587c478bd9Sstevel@tonic-gate 
34597c478bd9Sstevel@tonic-gate 	ibdm_process_incoming_mad(taskq_args->tq_ibmf_handle,
34607c478bd9Sstevel@tonic-gate 	    taskq_args->tq_ibmf_msg, taskq_args->tq_args);
34617c478bd9Sstevel@tonic-gate 
34627c478bd9Sstevel@tonic-gate 	kmem_free(taskq_args, sizeof (ibdm_taskq_args_t));
34637c478bd9Sstevel@tonic-gate }
34647c478bd9Sstevel@tonic-gate 
34657c478bd9Sstevel@tonic-gate 
34667c478bd9Sstevel@tonic-gate /*
34677c478bd9Sstevel@tonic-gate  * Calls ibdm_process_incoming_mad with all function arguments  extracted
34687c478bd9Sstevel@tonic-gate  * from args
34697c478bd9Sstevel@tonic-gate  */
34707c478bd9Sstevel@tonic-gate /*ARGSUSED*/
34717c478bd9Sstevel@tonic-gate static void
ibdm_process_incoming_mad(ibmf_handle_t ibmf_hdl,ibmf_msg_t * msg,void * arg)34727c478bd9Sstevel@tonic-gate ibdm_process_incoming_mad(ibmf_handle_t ibmf_hdl, ibmf_msg_t *msg, void *arg)
34737c478bd9Sstevel@tonic-gate {
34747c478bd9Sstevel@tonic-gate 	int			flag = 0;
34757c478bd9Sstevel@tonic-gate 	int			ret;
34767c478bd9Sstevel@tonic-gate 	uint64_t		transaction_id;
34777c478bd9Sstevel@tonic-gate 	ib_mad_hdr_t		*hdr;
34787c478bd9Sstevel@tonic-gate 	ibdm_dp_gidinfo_t	*gid_info = NULL;
34797c478bd9Sstevel@tonic-gate 
34807c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm",
34817c478bd9Sstevel@tonic-gate 	    "\tprocess_incoming_mad: ibmf hdl %p pkt %p", ibmf_hdl, msg);
34827c478bd9Sstevel@tonic-gate 	ibdm_dump_ibmf_msg(msg, 0);
34837c478bd9Sstevel@tonic-gate 
34847c478bd9Sstevel@tonic-gate 	/*
34857c478bd9Sstevel@tonic-gate 	 * IBMF calls this routine for every DM MAD that arrives at this port.
34867c478bd9Sstevel@tonic-gate 	 * But we handle only the responses for requests we sent. We drop all
34877c478bd9Sstevel@tonic-gate 	 * the DM packets that does not have response bit set in the MAD
34887c478bd9Sstevel@tonic-gate 	 * header(this eliminates all the requests sent to this port).
34897c478bd9Sstevel@tonic-gate 	 * We handle only DM class version 1 MAD's
34907c478bd9Sstevel@tonic-gate 	 */
34917c478bd9Sstevel@tonic-gate 	hdr = IBDM_IN_IBMFMSG_MADHDR(msg);
34927c478bd9Sstevel@tonic-gate 	if (ibdm_verify_mad_status(hdr) != IBDM_SUCCESS) {
34937c478bd9Sstevel@tonic-gate 		if (ibmf_free_msg(ibmf_hdl, &msg) != IBMF_SUCCESS) {
34947c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibdm", "\tprocess_incoming_mad: "
34957c478bd9Sstevel@tonic-gate 			    "IBMF free msg failed DM request drop it");
34967c478bd9Sstevel@tonic-gate 		}
34977c478bd9Sstevel@tonic-gate 		return;
34987c478bd9Sstevel@tonic-gate 	}
34997c478bd9Sstevel@tonic-gate 
35007c478bd9Sstevel@tonic-gate 	transaction_id = b2h64(hdr->TransactionID);
35017c478bd9Sstevel@tonic-gate 
35027c478bd9Sstevel@tonic-gate 	mutex_enter(&ibdm.ibdm_mutex);
35037c478bd9Sstevel@tonic-gate 	gid_info = ibdm.ibdm_dp_gidlist_head;
35047c478bd9Sstevel@tonic-gate 	while (gid_info) {
35059d3d2ed0Shiremath 		if ((gid_info->gl_transactionID  &
35069d3d2ed0Shiremath 		    IBDM_GID_TRANSACTIONID_MASK) ==
35079d3d2ed0Shiremath 		    (transaction_id & IBDM_GID_TRANSACTIONID_MASK))
35087c478bd9Sstevel@tonic-gate 			break;
35097c478bd9Sstevel@tonic-gate 		gid_info = gid_info->gl_next;
35107c478bd9Sstevel@tonic-gate 	}
35117c478bd9Sstevel@tonic-gate 	mutex_exit(&ibdm.ibdm_mutex);
35127c478bd9Sstevel@tonic-gate 
35137c478bd9Sstevel@tonic-gate 	if (gid_info == NULL) {
35147c478bd9Sstevel@tonic-gate 		/* Drop the packet */
35157c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibdm", "process_incoming_mad: transaction ID"
35167c478bd9Sstevel@tonic-gate 		    " does not match: 0x%llx", transaction_id);
35177c478bd9Sstevel@tonic-gate 		if (ibmf_free_msg(ibmf_hdl, &msg) != IBMF_SUCCESS) {
35187c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibdm", "process_incoming_mad: "
35197c478bd9Sstevel@tonic-gate 			    "IBMF free msg failed DM request drop it");
35207c478bd9Sstevel@tonic-gate 		}
35217c478bd9Sstevel@tonic-gate 		return;
35227c478bd9Sstevel@tonic-gate 	}
35237c478bd9Sstevel@tonic-gate 
35247c478bd9Sstevel@tonic-gate 	/* Handle redirection for all the MAD's, except ClassPortInfo */
35257c478bd9Sstevel@tonic-gate 	if (((IBDM_IN_IBMFMSG_STATUS(msg) & MAD_STATUS_REDIRECT_REQUIRED)) &&
352653c1b7a3Seota 	    (IBDM_IN_IBMFMSG_ATTR(msg) != IB_DM_ATTR_CLASSPORTINFO)) {
35277c478bd9Sstevel@tonic-gate 		ret = ibdm_handle_redirection(msg, gid_info, &flag);
35287c478bd9Sstevel@tonic-gate 		if (ret == IBDM_SUCCESS) {
35297c478bd9Sstevel@tonic-gate 			return;
35307c478bd9Sstevel@tonic-gate 		}
35317c478bd9Sstevel@tonic-gate 	} else {
35327c478bd9Sstevel@tonic-gate 		uint_t gl_state;
35337c478bd9Sstevel@tonic-gate 
35347c478bd9Sstevel@tonic-gate 		mutex_enter(&gid_info->gl_mutex);
35357c478bd9Sstevel@tonic-gate 		gl_state = gid_info->gl_state;
35367c478bd9Sstevel@tonic-gate 		mutex_exit(&gid_info->gl_mutex);
35377c478bd9Sstevel@tonic-gate 
35387c478bd9Sstevel@tonic-gate 		switch (gl_state) {
353953c1b7a3Seota 
354053c1b7a3Seota 		case IBDM_SET_CLASSPORTINFO:
354153c1b7a3Seota 			ibdm_handle_setclassportinfo(
354253c1b7a3Seota 			    ibmf_hdl, msg, gid_info, &flag);
354353c1b7a3Seota 			break;
354453c1b7a3Seota 
35457c478bd9Sstevel@tonic-gate 		case IBDM_GET_CLASSPORTINFO:
35467c478bd9Sstevel@tonic-gate 			ibdm_handle_classportinfo(
35477c478bd9Sstevel@tonic-gate 			    ibmf_hdl, msg, gid_info, &flag);
35487c478bd9Sstevel@tonic-gate 			break;
35497c478bd9Sstevel@tonic-gate 
35507c478bd9Sstevel@tonic-gate 		case IBDM_GET_IOUNITINFO:
35517c478bd9Sstevel@tonic-gate 			ibdm_handle_iounitinfo(ibmf_hdl, msg, gid_info, &flag);
35527c478bd9Sstevel@tonic-gate 			break;
35537c478bd9Sstevel@tonic-gate 
35547c478bd9Sstevel@tonic-gate 		case IBDM_GET_IOC_DETAILS:
35557c478bd9Sstevel@tonic-gate 			switch (IBDM_IN_IBMFMSG_ATTR(msg)) {
35567c478bd9Sstevel@tonic-gate 
35577c478bd9Sstevel@tonic-gate 			case IB_DM_ATTR_SERVICE_ENTRIES:
35587c478bd9Sstevel@tonic-gate 				ibdm_handle_srventry_mad(msg, gid_info, &flag);
35597c478bd9Sstevel@tonic-gate 				break;
35607c478bd9Sstevel@tonic-gate 
35617c478bd9Sstevel@tonic-gate 			case IB_DM_ATTR_IOC_CTRL_PROFILE:
35627c478bd9Sstevel@tonic-gate 				ibdm_handle_ioc_profile(
35637c478bd9Sstevel@tonic-gate 				    ibmf_hdl, msg, gid_info, &flag);
35647c478bd9Sstevel@tonic-gate 				break;
35657c478bd9Sstevel@tonic-gate 
35667c478bd9Sstevel@tonic-gate 			case IB_DM_ATTR_DIAG_CODE:
35677c478bd9Sstevel@tonic-gate 				ibdm_handle_diagcode(msg, gid_info, &flag);
35687c478bd9Sstevel@tonic-gate 				break;
35697c478bd9Sstevel@tonic-gate 
35707c478bd9Sstevel@tonic-gate 			default:
35717c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibdm", "process_incoming_mad: "
35727c478bd9Sstevel@tonic-gate 				    "Error state, wrong attribute :-(");
35737c478bd9Sstevel@tonic-gate 				(void) ibmf_free_msg(ibmf_hdl, &msg);
35747c478bd9Sstevel@tonic-gate 				return;
35757c478bd9Sstevel@tonic-gate 			}
35767c478bd9Sstevel@tonic-gate 			break;
35777c478bd9Sstevel@tonic-gate 		default:
35787c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibdm",
35797c478bd9Sstevel@tonic-gate 			    "process_incoming_mad: Dropping the packet"
35807c478bd9Sstevel@tonic-gate 			    " gl_state %x", gl_state);
35817c478bd9Sstevel@tonic-gate 			if (ibmf_free_msg(ibmf_hdl, &msg) != IBMF_SUCCESS) {
35827c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibdm", "process_incoming_mad: "
35837c478bd9Sstevel@tonic-gate 				    "IBMF free msg failed DM request drop it");
35847c478bd9Sstevel@tonic-gate 			}
35857c478bd9Sstevel@tonic-gate 			return;
35867c478bd9Sstevel@tonic-gate 		}
35877c478bd9Sstevel@tonic-gate 	}
35887c478bd9Sstevel@tonic-gate 
35897c478bd9Sstevel@tonic-gate 	if ((flag & IBDM_IBMF_PKT_DUP_RESP) ||
35907c478bd9Sstevel@tonic-gate 	    (flag & IBDM_IBMF_PKT_UNEXP_RESP)) {
35917c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibdm",
35927c478bd9Sstevel@tonic-gate 		    "\tprocess_incoming_mad:Dup/unexp resp : 0x%x", flag);
35937c478bd9Sstevel@tonic-gate 		if (ibmf_free_msg(ibmf_hdl, &msg) != IBMF_SUCCESS) {
35947c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibdm", "process_incoming_mad: "
35957c478bd9Sstevel@tonic-gate 			    "IBMF free msg failed DM request drop it");
35967c478bd9Sstevel@tonic-gate 		}
35977c478bd9Sstevel@tonic-gate 		return;
35987c478bd9Sstevel@tonic-gate 	}
35997c478bd9Sstevel@tonic-gate 
36007c478bd9Sstevel@tonic-gate 	mutex_enter(&gid_info->gl_mutex);
36017c478bd9Sstevel@tonic-gate 	if (gid_info->gl_pending_cmds < 1) {
36027c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibdm",
36037c478bd9Sstevel@tonic-gate 		    "\tprocess_incoming_mad: pending commands negative");
36047c478bd9Sstevel@tonic-gate 	}
36057c478bd9Sstevel@tonic-gate 	if (--gid_info->gl_pending_cmds) {
36067c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibdm", "\tprocess_incoming_mad: "
36077c478bd9Sstevel@tonic-gate 		    "gid_info %p pending cmds %d",
36087c478bd9Sstevel@tonic-gate 		    gid_info, gid_info->gl_pending_cmds);
36097c478bd9Sstevel@tonic-gate 		mutex_exit(&gid_info->gl_mutex);
36107c478bd9Sstevel@tonic-gate 	} else {
361153c1b7a3Seota 		uint_t prev_state;
36127c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibdm", "\tprocess_incoming_mad: Probing DONE");
361353c1b7a3Seota 		prev_state = gid_info->gl_state;
36147c478bd9Sstevel@tonic-gate 		gid_info->gl_state = IBDM_GID_PROBING_COMPLETE;
361553c1b7a3Seota 		if (prev_state == IBDM_SET_CLASSPORTINFO) {
36167c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibdm",
361753c1b7a3Seota 			    "\tprocess_incoming_mad: "
361853c1b7a3Seota 			    "Setclassportinfo for Cisco FC GW is done.");
361953c1b7a3Seota 			gid_info->gl_flag &= ~IBDM_CISCO_PROBE;
362053c1b7a3Seota 			gid_info->gl_flag |= IBDM_CISCO_PROBE_DONE;
362153c1b7a3Seota 			mutex_exit(&gid_info->gl_mutex);
362253c1b7a3Seota 			cv_broadcast(&gid_info->gl_probe_cv);
362353c1b7a3Seota 		} else {
362453c1b7a3Seota 			mutex_exit(&gid_info->gl_mutex);
362553c1b7a3Seota 			ibdm_notify_newgid_iocs(gid_info);
362653c1b7a3Seota 			mutex_enter(&ibdm.ibdm_mutex);
362753c1b7a3Seota 			if (--ibdm.ibdm_ngid_probes_in_progress == 0) {
362853c1b7a3Seota 				IBTF_DPRINTF_L4("ibdm",
362953c1b7a3Seota 				    "\tprocess_incoming_mad: Wakeup");
363053c1b7a3Seota 				ibdm.ibdm_busy &= ~IBDM_PROBE_IN_PROGRESS;
363153c1b7a3Seota 				cv_broadcast(&ibdm.ibdm_probe_cv);
363253c1b7a3Seota 			}
363353c1b7a3Seota 			mutex_exit(&ibdm.ibdm_mutex);
36347c478bd9Sstevel@tonic-gate 		}
36357c478bd9Sstevel@tonic-gate 	}
36367c478bd9Sstevel@tonic-gate 
36377c478bd9Sstevel@tonic-gate 	/*
36387c478bd9Sstevel@tonic-gate 	 * Do not deallocate the IBMF packet if atleast one request
36397c478bd9Sstevel@tonic-gate 	 * is posted. IBMF packet is reused.
36407c478bd9Sstevel@tonic-gate 	 */
36417c478bd9Sstevel@tonic-gate 	if (!(flag & IBDM_IBMF_PKT_REUSED)) {
36427c478bd9Sstevel@tonic-gate 		if (ibmf_free_msg(ibmf_hdl, &msg) != IBMF_SUCCESS) {
36437c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibdm", "\tprocess_incoming_mad: "
36447c478bd9Sstevel@tonic-gate 			    "IBMF free msg failed DM request drop it");
36457c478bd9Sstevel@tonic-gate 		}
36467c478bd9Sstevel@tonic-gate 	}
36477c478bd9Sstevel@tonic-gate }
36487c478bd9Sstevel@tonic-gate 
36497c478bd9Sstevel@tonic-gate 
36507c478bd9Sstevel@tonic-gate /*
36517c478bd9Sstevel@tonic-gate  * ibdm_verify_mad_status()
36527c478bd9Sstevel@tonic-gate  *	Verifies the MAD status
36537c478bd9Sstevel@tonic-gate  *	Returns IBDM_SUCCESS if status is correct
36547c478bd9Sstevel@tonic-gate  *	Returns IBDM_FAILURE for bogus MAD status
36557c478bd9Sstevel@tonic-gate  */
36567c478bd9Sstevel@tonic-gate static int
ibdm_verify_mad_status(ib_mad_hdr_t * hdr)36577c478bd9Sstevel@tonic-gate ibdm_verify_mad_status(ib_mad_hdr_t *hdr)
36587c478bd9Sstevel@tonic-gate {
36597c478bd9Sstevel@tonic-gate 	int	ret = 0;
36607c478bd9Sstevel@tonic-gate 
36617c478bd9Sstevel@tonic-gate 	if ((hdr->R_Method != IB_DM_DEVMGT_METHOD_GET_RESP) ||
36627c478bd9Sstevel@tonic-gate 	    (hdr->ClassVersion != IB_DM_CLASS_VERSION_1)) {
36637c478bd9Sstevel@tonic-gate 		return (IBDM_FAILURE);
36647c478bd9Sstevel@tonic-gate 	}
36657c478bd9Sstevel@tonic-gate 
36667c478bd9Sstevel@tonic-gate 	if (b2h16(hdr->Status) == 0)
36677c478bd9Sstevel@tonic-gate 		ret = IBDM_SUCCESS;
36687c478bd9Sstevel@tonic-gate 	else if ((b2h16(hdr->Status) & 0x1f) == MAD_STATUS_REDIRECT_REQUIRED)
36697c478bd9Sstevel@tonic-gate 		ret = IBDM_SUCCESS;
36707c478bd9Sstevel@tonic-gate 	else {
3671a1e3386eShiremath 		IBTF_DPRINTF_L2("ibdm",
3672a1e3386eShiremath 		    "\tverify_mad_status: Status : 0x%x", b2h16(hdr->Status));
36737c478bd9Sstevel@tonic-gate 		ret = IBDM_FAILURE;
36747c478bd9Sstevel@tonic-gate 	}
36757c478bd9Sstevel@tonic-gate 	return (ret);
36767c478bd9Sstevel@tonic-gate }
36777c478bd9Sstevel@tonic-gate 
36787c478bd9Sstevel@tonic-gate 
36797c478bd9Sstevel@tonic-gate 
36807c478bd9Sstevel@tonic-gate /*
36817c478bd9Sstevel@tonic-gate  * ibdm_handle_redirection()
36827c478bd9Sstevel@tonic-gate  *	Returns IBDM_SUCCESS/IBDM_FAILURE
36837c478bd9Sstevel@tonic-gate  */
36847c478bd9Sstevel@tonic-gate static int
ibdm_handle_redirection(ibmf_msg_t * msg,ibdm_dp_gidinfo_t * gid_info,int * flag)36857c478bd9Sstevel@tonic-gate ibdm_handle_redirection(ibmf_msg_t *msg,
36867c478bd9Sstevel@tonic-gate     ibdm_dp_gidinfo_t *gid_info, int *flag)
36877c478bd9Sstevel@tonic-gate {
36887c478bd9Sstevel@tonic-gate 	int			attrmod, ioc_no, start;
36897c478bd9Sstevel@tonic-gate 	void			*data;
36907c478bd9Sstevel@tonic-gate 	timeout_id_t		*timeout_id;
36917c478bd9Sstevel@tonic-gate 	ib_mad_hdr_t		*hdr;
36927c478bd9Sstevel@tonic-gate 	ibdm_ioc_info_t		*ioc = NULL;
36937c478bd9Sstevel@tonic-gate 	ibdm_timeout_cb_args_t	*cb_args;
369453c1b7a3Seota 	ib_mad_classportinfo_t	*cpi;
36957c478bd9Sstevel@tonic-gate 
36967c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\thandle_redirection: Enter");
36977c478bd9Sstevel@tonic-gate 	mutex_enter(&gid_info->gl_mutex);
36987c478bd9Sstevel@tonic-gate 	switch (gid_info->gl_state) {
36997c478bd9Sstevel@tonic-gate 	case IBDM_GET_IOUNITINFO:
37007c478bd9Sstevel@tonic-gate 		cb_args		= &gid_info->gl_iou_cb_args;
37017c478bd9Sstevel@tonic-gate 		timeout_id	= &gid_info->gl_timeout_id;
37027c478bd9Sstevel@tonic-gate 		break;
37037c478bd9Sstevel@tonic-gate 
37047c478bd9Sstevel@tonic-gate 	case IBDM_GET_IOC_DETAILS:
37057c478bd9Sstevel@tonic-gate 		attrmod	= IBDM_IN_IBMFMSG_ATTRMOD(msg);
37067c478bd9Sstevel@tonic-gate 		switch (IBDM_IN_IBMFMSG_ATTR(msg)) {
37077c478bd9Sstevel@tonic-gate 
37087c478bd9Sstevel@tonic-gate 		case IB_DM_ATTR_DIAG_CODE:
37097c478bd9Sstevel@tonic-gate 			if (attrmod == 0) {
37107c478bd9Sstevel@tonic-gate 				cb_args = &gid_info->gl_iou_cb_args;
37117c478bd9Sstevel@tonic-gate 				timeout_id = &gid_info->gl_timeout_id;
37127c478bd9Sstevel@tonic-gate 				break;
37137c478bd9Sstevel@tonic-gate 			}
37147c478bd9Sstevel@tonic-gate 			if (IBDM_IS_IOC_NUM_INVALID(attrmod, gid_info)) {
37157c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibdm", "\thandle_redirction:"
37167c478bd9Sstevel@tonic-gate 				    "IOC# Out of range %d", attrmod);
37177c478bd9Sstevel@tonic-gate 				(*flag) |= IBDM_IBMF_PKT_UNEXP_RESP;
37187c478bd9Sstevel@tonic-gate 				mutex_exit(&gid_info->gl_mutex);
37197c478bd9Sstevel@tonic-gate 				return (IBDM_FAILURE);
37207c478bd9Sstevel@tonic-gate 			}
37217c478bd9Sstevel@tonic-gate 			ioc	= IBDM_GIDINFO2IOCINFO(gid_info, (attrmod -1));
37227c478bd9Sstevel@tonic-gate 			cb_args = &ioc->ioc_dc_cb_args;
37237c478bd9Sstevel@tonic-gate 			timeout_id = &ioc->ioc_dc_timeout_id;
37247c478bd9Sstevel@tonic-gate 			break;
37257c478bd9Sstevel@tonic-gate 
37267c478bd9Sstevel@tonic-gate 		case IB_DM_ATTR_IOC_CTRL_PROFILE:
37277c478bd9Sstevel@tonic-gate 			if (IBDM_IS_IOC_NUM_INVALID(attrmod, gid_info)) {
37287c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibdm", "\thandle_redirction:"
37297c478bd9Sstevel@tonic-gate 				    "IOC# Out of range %d", attrmod);
37307c478bd9Sstevel@tonic-gate 				(*flag) |= IBDM_IBMF_PKT_UNEXP_RESP;
37317c478bd9Sstevel@tonic-gate 				mutex_exit(&gid_info->gl_mutex);
37327c478bd9Sstevel@tonic-gate 				return (IBDM_FAILURE);
37337c478bd9Sstevel@tonic-gate 			}
37347c478bd9Sstevel@tonic-gate 			ioc	= IBDM_GIDINFO2IOCINFO(gid_info, (attrmod -1));
37357c478bd9Sstevel@tonic-gate 			cb_args = &ioc->ioc_cb_args;
37367c478bd9Sstevel@tonic-gate 			timeout_id = &ioc->ioc_timeout_id;
37377c478bd9Sstevel@tonic-gate 			break;
37387c478bd9Sstevel@tonic-gate 
37397c478bd9Sstevel@tonic-gate 		case IB_DM_ATTR_SERVICE_ENTRIES:
37407c478bd9Sstevel@tonic-gate 			ioc_no	= ((attrmod >> 16) & IBDM_16_BIT_MASK);
37417c478bd9Sstevel@tonic-gate 			if (IBDM_IS_IOC_NUM_INVALID(ioc_no, gid_info)) {
37427c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibdm", "\thandle_redirction:"
37437c478bd9Sstevel@tonic-gate 				    "IOC# Out of range %d", ioc_no);
37447c478bd9Sstevel@tonic-gate 				(*flag) |= IBDM_IBMF_PKT_UNEXP_RESP;
37457c478bd9Sstevel@tonic-gate 				mutex_exit(&gid_info->gl_mutex);
37467c478bd9Sstevel@tonic-gate 				return (IBDM_FAILURE);
37477c478bd9Sstevel@tonic-gate 			}
37489d3d2ed0Shiremath 			start 	= (attrmod & IBDM_8_BIT_MASK);
37497c478bd9Sstevel@tonic-gate 			ioc	= IBDM_GIDINFO2IOCINFO(gid_info, (ioc_no -1));
37507c478bd9Sstevel@tonic-gate 			if (start > ioc->ioc_profile.ioc_service_entries) {
37517c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibdm", "\thandle_redirction:"
37527c478bd9Sstevel@tonic-gate 				    " SE index Out of range %d", start);
37537c478bd9Sstevel@tonic-gate 				(*flag) |= IBDM_IBMF_PKT_UNEXP_RESP;
37547c478bd9Sstevel@tonic-gate 				mutex_exit(&gid_info->gl_mutex);
37557c478bd9Sstevel@tonic-gate 				return (IBDM_FAILURE);
37567c478bd9Sstevel@tonic-gate 			}
37577c478bd9Sstevel@tonic-gate 			cb_args = &ioc->ioc_serv[start].se_cb_args;
37587c478bd9Sstevel@tonic-gate 			timeout_id = &ioc->ioc_serv[start].se_timeout_id;
37597c478bd9Sstevel@tonic-gate 			break;
37607c478bd9Sstevel@tonic-gate 
37617c478bd9Sstevel@tonic-gate 		default:
37627c478bd9Sstevel@tonic-gate 			/* ERROR State */
37637c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibdm",
37647c478bd9Sstevel@tonic-gate 			    "\thandle_redirection: wrong attribute :-(");
37657c478bd9Sstevel@tonic-gate 			(*flag) |= IBDM_IBMF_PKT_UNEXP_RESP;
37667c478bd9Sstevel@tonic-gate 			mutex_exit(&gid_info->gl_mutex);
37677c478bd9Sstevel@tonic-gate 			return (IBDM_FAILURE);
37687c478bd9Sstevel@tonic-gate 		}
37697c478bd9Sstevel@tonic-gate 		break;
37707c478bd9Sstevel@tonic-gate 	default:
37717c478bd9Sstevel@tonic-gate 		/* ERROR State */
37727c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibdm",
37737c478bd9Sstevel@tonic-gate 		    "\thandle_redirection: Error state :-(");
37747c478bd9Sstevel@tonic-gate 		(*flag) |= IBDM_IBMF_PKT_UNEXP_RESP;
37757c478bd9Sstevel@tonic-gate 		mutex_exit(&gid_info->gl_mutex);
37767c478bd9Sstevel@tonic-gate 		return (IBDM_FAILURE);
37777c478bd9Sstevel@tonic-gate 	}
37787c478bd9Sstevel@tonic-gate 	if ((*timeout_id) != 0) {
37797c478bd9Sstevel@tonic-gate 		mutex_exit(&gid_info->gl_mutex);
37807c478bd9Sstevel@tonic-gate 		if (untimeout(*timeout_id) == -1) {
37817c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibdm", "\thandle_redirection: "
37827c478bd9Sstevel@tonic-gate 			    "untimeout failed %x", *timeout_id);
37837c478bd9Sstevel@tonic-gate 		} else {
37847c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L5("ibdm",
37857c478bd9Sstevel@tonic-gate 			    "\thandle_redirection: timeout %x", *timeout_id);
37867c478bd9Sstevel@tonic-gate 		}
37877c478bd9Sstevel@tonic-gate 		mutex_enter(&gid_info->gl_mutex);
37887c478bd9Sstevel@tonic-gate 		*timeout_id = 0;
37897c478bd9Sstevel@tonic-gate 	}
37907c478bd9Sstevel@tonic-gate 
37917c478bd9Sstevel@tonic-gate 	data = msg->im_msgbufs_recv.im_bufs_cl_data;
379253c1b7a3Seota 	cpi = (ib_mad_classportinfo_t *)data;
37937c478bd9Sstevel@tonic-gate 
37947c478bd9Sstevel@tonic-gate 	gid_info->gl_resp_timeout	=
379553c1b7a3Seota 	    (b2h32(cpi->RespTimeValue) & 0x1F);
37967c478bd9Sstevel@tonic-gate 
37977c478bd9Sstevel@tonic-gate 	gid_info->gl_redirected		= B_TRUE;
37987c478bd9Sstevel@tonic-gate 	gid_info->gl_redirect_dlid	= b2h16(cpi->RedirectLID);
37997c478bd9Sstevel@tonic-gate 	gid_info->gl_redirect_QP	= (b2h32(cpi->RedirectQP) & 0xffffff);
38007c478bd9Sstevel@tonic-gate 	gid_info->gl_redirect_pkey	= b2h16(cpi->RedirectP_Key);
38017c478bd9Sstevel@tonic-gate 	gid_info->gl_redirect_qkey	= b2h32(cpi->RedirectQ_Key);
38027c478bd9Sstevel@tonic-gate 	gid_info->gl_redirectGID_hi	= b2h64(cpi->RedirectGID_hi);
38037c478bd9Sstevel@tonic-gate 	gid_info->gl_redirectGID_lo	= b2h64(cpi->RedirectGID_lo);
380418edb70cSeota 	gid_info->gl_redirectSL		= cpi->RedirectSL;
38057c478bd9Sstevel@tonic-gate 
38067c478bd9Sstevel@tonic-gate 	if (gid_info->gl_redirect_dlid != 0) {
38077c478bd9Sstevel@tonic-gate 		msg->im_local_addr.ia_remote_lid =
380853c1b7a3Seota 		    gid_info->gl_redirect_dlid;
38097c478bd9Sstevel@tonic-gate 	}
38109d3d2ed0Shiremath 	ibdm_bump_transactionID(gid_info);
38117c478bd9Sstevel@tonic-gate 	mutex_exit(&gid_info->gl_mutex);
38127c478bd9Sstevel@tonic-gate 
381318edb70cSeota 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*msg, *hdr))
38147c478bd9Sstevel@tonic-gate 	ibdm_alloc_send_buffers(msg);
38157c478bd9Sstevel@tonic-gate 
38167c478bd9Sstevel@tonic-gate 	hdr			= IBDM_OUT_IBMFMSG_MADHDR(msg);
38177c478bd9Sstevel@tonic-gate 	hdr->BaseVersion	= MAD_CLASS_BASE_VERS_1;
38187c478bd9Sstevel@tonic-gate 	hdr->MgmtClass		= MAD_MGMT_CLASS_DEV_MGT;
38197c478bd9Sstevel@tonic-gate 	hdr->ClassVersion	= IB_DM_CLASS_VERSION_1;
38207c478bd9Sstevel@tonic-gate 	hdr->R_Method		= IB_DM_DEVMGT_METHOD_GET;
38217c478bd9Sstevel@tonic-gate 	hdr->Status		= 0;
38227c478bd9Sstevel@tonic-gate 	hdr->TransactionID	= h2b64(gid_info->gl_transactionID);
38237c478bd9Sstevel@tonic-gate 	hdr->AttributeID	=
382453c1b7a3Seota 	    msg->im_msgbufs_recv.im_bufs_mad_hdr->AttributeID;
38257c478bd9Sstevel@tonic-gate 	hdr->AttributeModifier	=
382653c1b7a3Seota 	    msg->im_msgbufs_recv.im_bufs_mad_hdr->AttributeModifier;
382718edb70cSeota 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*msg, *hdr))
38287c478bd9Sstevel@tonic-gate 
38297c478bd9Sstevel@tonic-gate 	msg->im_local_addr.ia_remote_qno = gid_info->gl_redirect_QP;
38307c478bd9Sstevel@tonic-gate 	msg->im_local_addr.ia_p_key = gid_info->gl_redirect_pkey;
38317c478bd9Sstevel@tonic-gate 	msg->im_local_addr.ia_q_key = gid_info->gl_redirect_qkey;
383218edb70cSeota 	msg->im_local_addr.ia_service_level = gid_info->gl_redirectSL;
38337c478bd9Sstevel@tonic-gate 
383418edb70cSeota 	mutex_enter(&gid_info->gl_mutex);
38357c478bd9Sstevel@tonic-gate 	*timeout_id = timeout(ibdm_pkt_timeout_hdlr,
38367c478bd9Sstevel@tonic-gate 	    cb_args, IBDM_TIMEOUT_VALUE(ibdm_dft_timeout));
383718edb70cSeota 	mutex_exit(&gid_info->gl_mutex);
38387c478bd9Sstevel@tonic-gate 
38397c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L5("ibdm", "\thandle_redirect:"
38407c478bd9Sstevel@tonic-gate 	    "timeout %x", *timeout_id);
38417c478bd9Sstevel@tonic-gate 
38427c478bd9Sstevel@tonic-gate 	if (ibmf_msg_transport(gid_info->gl_ibmf_hdl, gid_info->gl_qp_hdl,
38437c478bd9Sstevel@tonic-gate 	    msg, NULL, ibdm_ibmf_send_cb, cb_args, 0) != IBMF_SUCCESS) {
38447c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibdm", "\thandle_redirection:"
38457c478bd9Sstevel@tonic-gate 		    "message transport failed");
38467c478bd9Sstevel@tonic-gate 		ibdm_ibmf_send_cb(gid_info->gl_ibmf_hdl, msg, cb_args);
38477c478bd9Sstevel@tonic-gate 	}
38487c478bd9Sstevel@tonic-gate 	(*flag) |= IBDM_IBMF_PKT_REUSED;
38497c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\thandle_redirection: Exit");
38507c478bd9Sstevel@tonic-gate 	return (IBDM_SUCCESS);
38517c478bd9Sstevel@tonic-gate }
38527c478bd9Sstevel@tonic-gate 
38537c478bd9Sstevel@tonic-gate 
38547c478bd9Sstevel@tonic-gate /*
38557c478bd9Sstevel@tonic-gate  * ibdm_pkt_timeout_hdlr
38567c478bd9Sstevel@tonic-gate  *	This  timeout  handler is  registed for every  IBMF  packet that is
38577c478bd9Sstevel@tonic-gate  *	sent through the IBMF.  It gets called when no response is received
38587c478bd9Sstevel@tonic-gate  *	within the specified time for the packet. No retries for the failed
38597c478bd9Sstevel@tonic-gate  *	commands  currently.  Drops the failed  IBMF packet and  update the
38607c478bd9Sstevel@tonic-gate  *	pending list commands.
38617c478bd9Sstevel@tonic-gate  */
38627c478bd9Sstevel@tonic-gate static void
ibdm_pkt_timeout_hdlr(void * arg)38637c478bd9Sstevel@tonic-gate ibdm_pkt_timeout_hdlr(void *arg)
38647c478bd9Sstevel@tonic-gate {
38657c478bd9Sstevel@tonic-gate 	ibdm_iou_info_t		*iou;
38667c478bd9Sstevel@tonic-gate 	ibdm_ioc_info_t		*ioc;
38677c478bd9Sstevel@tonic-gate 	ibdm_timeout_cb_args_t	*cb_args = arg;
38687c478bd9Sstevel@tonic-gate 	ibdm_dp_gidinfo_t	*gid_info;
38697c478bd9Sstevel@tonic-gate 	int			srv_ent;
387005fa0d51Spramodbg 	uint_t			new_gl_state;
38717c478bd9Sstevel@tonic-gate 
38727c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L2("ibdm", "\tpkt_timeout_hdlr: gid_info: %p "
38737c478bd9Sstevel@tonic-gate 	    "rtype 0x%x iocidx 0x%x srvidx %d", cb_args->cb_gid_info,
38747c478bd9Sstevel@tonic-gate 	    cb_args->cb_req_type, cb_args->cb_ioc_num,
38757c478bd9Sstevel@tonic-gate 	    cb_args->cb_srvents_start);
38767c478bd9Sstevel@tonic-gate 
38777c478bd9Sstevel@tonic-gate 	gid_info = cb_args->cb_gid_info;
38787c478bd9Sstevel@tonic-gate 	mutex_enter(&gid_info->gl_mutex);
38797c478bd9Sstevel@tonic-gate 
38807c478bd9Sstevel@tonic-gate 	if ((gid_info->gl_state == IBDM_GID_PROBING_COMPLETE) ||
38817c478bd9Sstevel@tonic-gate 	    (cb_args->cb_req_type == 0)) {
38827c478bd9Sstevel@tonic-gate 
38837c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibdm", "\tpkt_timeout_hdlr: req completed"
38847c478bd9Sstevel@tonic-gate 		    "rtype 0x%x iocidx 0x%x srvidx %d", cb_args->cb_req_type,
38857c478bd9Sstevel@tonic-gate 		    cb_args->cb_ioc_num, cb_args->cb_srvents_start);
38867c478bd9Sstevel@tonic-gate 
38877c478bd9Sstevel@tonic-gate 		if (gid_info->gl_timeout_id)
38887c478bd9Sstevel@tonic-gate 			gid_info->gl_timeout_id = 0;
38897c478bd9Sstevel@tonic-gate 		mutex_exit(&gid_info->gl_mutex);
38907c478bd9Sstevel@tonic-gate 		return;
38917c478bd9Sstevel@tonic-gate 	}
38927c478bd9Sstevel@tonic-gate 	if (cb_args->cb_retry_count) {
38937c478bd9Sstevel@tonic-gate 		cb_args->cb_retry_count--;
389418edb70cSeota 		/*
389518edb70cSeota 		 * A new timeout_id is set inside ibdm_retry_command().
389618edb70cSeota 		 * When the function returns an error, the timeout_id
389718edb70cSeota 		 * is reset (to zero) in the switch statement below.
389818edb70cSeota 		 */
38997c478bd9Sstevel@tonic-gate 		if (ibdm_retry_command(cb_args) == IBDM_SUCCESS) {
39007c478bd9Sstevel@tonic-gate 			mutex_exit(&gid_info->gl_mutex);
39017c478bd9Sstevel@tonic-gate 			return;
39027c478bd9Sstevel@tonic-gate 		}
39037c478bd9Sstevel@tonic-gate 		cb_args->cb_retry_count = 0;
39047c478bd9Sstevel@tonic-gate 	}
39057c478bd9Sstevel@tonic-gate 
39067c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L2("ibdm", "\tpkt_timeout_hdlr: command failed: gid %p"
39077c478bd9Sstevel@tonic-gate 	    " rtype 0x%x iocidx 0x%x srvidx %d", cb_args->cb_gid_info,
39087c478bd9Sstevel@tonic-gate 	    cb_args->cb_req_type, cb_args->cb_ioc_num,
39097c478bd9Sstevel@tonic-gate 	    cb_args->cb_srvents_start);
39107c478bd9Sstevel@tonic-gate 
39117c478bd9Sstevel@tonic-gate 	switch (cb_args->cb_req_type) {
39127c478bd9Sstevel@tonic-gate 
39137c478bd9Sstevel@tonic-gate 	case IBDM_REQ_TYPE_CLASSPORTINFO:
39147c478bd9Sstevel@tonic-gate 	case IBDM_REQ_TYPE_IOUINFO:
391505fa0d51Spramodbg 		new_gl_state = IBDM_GID_PROBING_FAILED;
39167c478bd9Sstevel@tonic-gate 		if (gid_info->gl_timeout_id)
39177c478bd9Sstevel@tonic-gate 			gid_info->gl_timeout_id = 0;
39187c478bd9Sstevel@tonic-gate 		break;
391918edb70cSeota 
39207c478bd9Sstevel@tonic-gate 	case IBDM_REQ_TYPE_IOCINFO:
392118edb70cSeota 		new_gl_state = IBDM_GID_PROBING_COMPLETE;
39227c478bd9Sstevel@tonic-gate 		iou = gid_info->gl_iou;
39237c478bd9Sstevel@tonic-gate 		ioc = &iou->iou_ioc_info[cb_args->cb_ioc_num];
39247c478bd9Sstevel@tonic-gate 		ioc->ioc_state = IBDM_IOC_STATE_PROBE_FAILED;
39257c478bd9Sstevel@tonic-gate 		if (ioc->ioc_timeout_id)
39267c478bd9Sstevel@tonic-gate 			ioc->ioc_timeout_id = 0;
39277c478bd9Sstevel@tonic-gate 		break;
392818edb70cSeota 
39297c478bd9Sstevel@tonic-gate 	case IBDM_REQ_TYPE_SRVENTS:
393018edb70cSeota 		new_gl_state = IBDM_GID_PROBING_COMPLETE;
39317c478bd9Sstevel@tonic-gate 		iou = gid_info->gl_iou;
39327c478bd9Sstevel@tonic-gate 		ioc = &iou->iou_ioc_info[cb_args->cb_ioc_num];
39337c478bd9Sstevel@tonic-gate 		ioc->ioc_state = IBDM_IOC_STATE_PROBE_FAILED;
39347c478bd9Sstevel@tonic-gate 		srv_ent = cb_args->cb_srvents_start;
39357c478bd9Sstevel@tonic-gate 		if (ioc->ioc_serv[srv_ent].se_timeout_id)
39367c478bd9Sstevel@tonic-gate 			ioc->ioc_serv[srv_ent].se_timeout_id = 0;
39377c478bd9Sstevel@tonic-gate 		break;
393818edb70cSeota 
39397c478bd9Sstevel@tonic-gate 	case IBDM_REQ_TYPE_IOU_DIAGCODE:
394018edb70cSeota 		new_gl_state = IBDM_GID_PROBING_COMPLETE;
39417c478bd9Sstevel@tonic-gate 		iou = gid_info->gl_iou;
39427c478bd9Sstevel@tonic-gate 		iou->iou_dc_valid = B_FALSE;
39437c478bd9Sstevel@tonic-gate 		if (gid_info->gl_timeout_id)
39447c478bd9Sstevel@tonic-gate 			gid_info->gl_timeout_id = 0;
39457c478bd9Sstevel@tonic-gate 		break;
394618edb70cSeota 
39477c478bd9Sstevel@tonic-gate 	case IBDM_REQ_TYPE_IOC_DIAGCODE:
394818edb70cSeota 		new_gl_state = IBDM_GID_PROBING_COMPLETE;
39497c478bd9Sstevel@tonic-gate 		iou = gid_info->gl_iou;
39507c478bd9Sstevel@tonic-gate 		ioc = &iou->iou_ioc_info[cb_args->cb_ioc_num];
39517c478bd9Sstevel@tonic-gate 		ioc->ioc_dc_valid = B_FALSE;
39527c478bd9Sstevel@tonic-gate 		if (ioc->ioc_dc_timeout_id)
39537c478bd9Sstevel@tonic-gate 			ioc->ioc_dc_timeout_id = 0;
39547c478bd9Sstevel@tonic-gate 		break;
395518edb70cSeota 
395653c1b7a3Seota 	default: /* ERROR State */
395753c1b7a3Seota 		new_gl_state = IBDM_GID_PROBING_FAILED;
395853c1b7a3Seota 		if (gid_info->gl_timeout_id)
395953c1b7a3Seota 			gid_info->gl_timeout_id = 0;
396018edb70cSeota 		IBTF_DPRINTF_L2("ibdm",
396118edb70cSeota 		    "\tpkt_timeout_hdlr: wrong request type.");
396253c1b7a3Seota 		break;
39637c478bd9Sstevel@tonic-gate 	}
396418edb70cSeota 
396518edb70cSeota 	--gid_info->gl_pending_cmds; /* decrease the counter */
396618edb70cSeota 
396718edb70cSeota 	if (gid_info->gl_pending_cmds == 0) {
396805fa0d51Spramodbg 		gid_info->gl_state = new_gl_state;
39697c478bd9Sstevel@tonic-gate 		mutex_exit(&gid_info->gl_mutex);
397018edb70cSeota 		/*
397118edb70cSeota 		 * Delete this gid_info if the gid probe fails.
397218edb70cSeota 		 */
397318edb70cSeota 		if (new_gl_state == IBDM_GID_PROBING_FAILED) {
397418edb70cSeota 			ibdm_delete_glhca_list(gid_info);
397518edb70cSeota 		}
39767c478bd9Sstevel@tonic-gate 		ibdm_notify_newgid_iocs(gid_info);
39777c478bd9Sstevel@tonic-gate 		mutex_enter(&ibdm.ibdm_mutex);
39787c478bd9Sstevel@tonic-gate 		if (--ibdm.ibdm_ngid_probes_in_progress == 0) {
39797c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibdm", "\tpkt_timeout_hdlr: Wakeup");
39807c478bd9Sstevel@tonic-gate 			ibdm.ibdm_busy &= ~IBDM_PROBE_IN_PROGRESS;
39817c478bd9Sstevel@tonic-gate 			cv_broadcast(&ibdm.ibdm_probe_cv);
39827c478bd9Sstevel@tonic-gate 		}
39837c478bd9Sstevel@tonic-gate 		mutex_exit(&ibdm.ibdm_mutex);
398418edb70cSeota 	} else {
398518edb70cSeota 		/*
398618edb70cSeota 		 * Reset gl_pending_cmd if the extra timeout happens since
398718edb70cSeota 		 * gl_pending_cmd becomes negative as a result.
398818edb70cSeota 		 */
398918edb70cSeota 		if (gid_info->gl_pending_cmds < 0) {
399018edb70cSeota 			gid_info->gl_pending_cmds = 0;
399118edb70cSeota 			IBTF_DPRINTF_L2("ibdm",
399218edb70cSeota 			    "\tpkt_timeout_hdlr: extra timeout request."
399318edb70cSeota 			    " reset gl_pending_cmds");
399418edb70cSeota 		}
39957c478bd9Sstevel@tonic-gate 		mutex_exit(&gid_info->gl_mutex);
399618edb70cSeota 		/*
399718edb70cSeota 		 * Delete this gid_info if the gid probe fails.
399818edb70cSeota 		 */
399918edb70cSeota 		if (new_gl_state == IBDM_GID_PROBING_FAILED) {
400018edb70cSeota 			ibdm_delete_glhca_list(gid_info);
400118edb70cSeota 		}
400218edb70cSeota 	}
40037c478bd9Sstevel@tonic-gate }
40047c478bd9Sstevel@tonic-gate 
40057c478bd9Sstevel@tonic-gate 
40067c478bd9Sstevel@tonic-gate /*
40077c478bd9Sstevel@tonic-gate  * ibdm_retry_command()
40087c478bd9Sstevel@tonic-gate  *	Retries the failed command.
40097c478bd9Sstevel@tonic-gate  *	Returns IBDM_FAILURE/IBDM_SUCCESS
40107c478bd9Sstevel@tonic-gate  */
40117c478bd9Sstevel@tonic-gate static int
ibdm_retry_command(ibdm_timeout_cb_args_t * cb_args)40127c478bd9Sstevel@tonic-gate ibdm_retry_command(ibdm_timeout_cb_args_t *cb_args)
40137c478bd9Sstevel@tonic-gate {
4014a1e3386eShiremath 	int			ret;
40157c478bd9Sstevel@tonic-gate 	ibmf_msg_t		*msg;
40167c478bd9Sstevel@tonic-gate 	ib_mad_hdr_t		*hdr;
40177c478bd9Sstevel@tonic-gate 	ibdm_dp_gidinfo_t	*gid_info = cb_args->cb_gid_info;
40187c478bd9Sstevel@tonic-gate 	timeout_id_t		*timeout_id;
40197c478bd9Sstevel@tonic-gate 	ibdm_ioc_info_t		*ioc;
40207c478bd9Sstevel@tonic-gate 	int			ioc_no;
402118edb70cSeota 	ASSERT(MUTEX_HELD(&gid_info->gl_mutex));
40227c478bd9Sstevel@tonic-gate 
40237c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L2("ibdm", "\tretry_command: gid_info: %p "
40247c478bd9Sstevel@tonic-gate 	    "rtype 0x%x iocidx 0x%x srvidx %d", cb_args->cb_gid_info,
40257c478bd9Sstevel@tonic-gate 	    cb_args->cb_req_type, cb_args->cb_ioc_num,
40267c478bd9Sstevel@tonic-gate 	    cb_args->cb_srvents_start);
40277c478bd9Sstevel@tonic-gate 
40287c478bd9Sstevel@tonic-gate 	ret = ibmf_alloc_msg(gid_info->gl_ibmf_hdl, IBMF_ALLOC_NOSLEEP, &msg);
40297c478bd9Sstevel@tonic-gate 
40307c478bd9Sstevel@tonic-gate 
40317c478bd9Sstevel@tonic-gate 	/*
40327c478bd9Sstevel@tonic-gate 	 * Reset the gid if alloc_msg failed with BAD_HANDLE
40337c478bd9Sstevel@tonic-gate 	 * ibdm_reset_gidinfo reinits the gid_info
40347c478bd9Sstevel@tonic-gate 	 */
40357c478bd9Sstevel@tonic-gate 	if (ret == IBMF_BAD_HANDLE) {
40367c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L3(ibdm_string, "\tretry_command: gid %p hdl bad",
40377c478bd9Sstevel@tonic-gate 		    gid_info);
40387c478bd9Sstevel@tonic-gate 
40397c478bd9Sstevel@tonic-gate 		mutex_exit(&gid_info->gl_mutex);
40407c478bd9Sstevel@tonic-gate 		ibdm_reset_gidinfo(gid_info);
40417c478bd9Sstevel@tonic-gate 		mutex_enter(&gid_info->gl_mutex);
40427c478bd9Sstevel@tonic-gate 
40437c478bd9Sstevel@tonic-gate 		/* Retry alloc */
40447c478bd9Sstevel@tonic-gate 		ret = ibmf_alloc_msg(gid_info->gl_ibmf_hdl, IBMF_ALLOC_NOSLEEP,
40457c478bd9Sstevel@tonic-gate 		    &msg);
40467c478bd9Sstevel@tonic-gate 	}
40477c478bd9Sstevel@tonic-gate 
40487c478bd9Sstevel@tonic-gate 	if (ret != IBDM_SUCCESS) {
40497c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibdm", "\tretry_command: alloc failed: %p "
40507c478bd9Sstevel@tonic-gate 		    "rtype 0x%x iocidx 0x%x srvidx %d", cb_args->cb_gid_info,
40517c478bd9Sstevel@tonic-gate 		    cb_args->cb_req_type, cb_args->cb_ioc_num,
40527c478bd9Sstevel@tonic-gate 		    cb_args->cb_srvents_start);
40537c478bd9Sstevel@tonic-gate 		return (IBDM_FAILURE);
40547c478bd9Sstevel@tonic-gate 	}
40557c478bd9Sstevel@tonic-gate 
405618edb70cSeota 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*msg))
40577c478bd9Sstevel@tonic-gate 	ibdm_alloc_send_buffers(msg);
405818edb70cSeota 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*msg))
40597c478bd9Sstevel@tonic-gate 
40609d3d2ed0Shiremath 	ibdm_bump_transactionID(gid_info);
40619d3d2ed0Shiremath 
40627c478bd9Sstevel@tonic-gate 	msg->im_local_addr.ia_local_lid	= gid_info->gl_slid;
40637c478bd9Sstevel@tonic-gate 	msg->im_local_addr.ia_remote_lid	= gid_info->gl_dlid;
40647c478bd9Sstevel@tonic-gate 	if (gid_info->gl_redirected == B_TRUE) {
40657c478bd9Sstevel@tonic-gate 		if (gid_info->gl_redirect_dlid != 0) {
40667c478bd9Sstevel@tonic-gate 			msg->im_local_addr.ia_remote_lid =
406753c1b7a3Seota 			    gid_info->gl_redirect_dlid;
40687c478bd9Sstevel@tonic-gate 		}
40697c478bd9Sstevel@tonic-gate 		msg->im_local_addr.ia_remote_qno = gid_info->gl_redirect_QP;
40707c478bd9Sstevel@tonic-gate 		msg->im_local_addr.ia_p_key = gid_info->gl_redirect_pkey;
40717c478bd9Sstevel@tonic-gate 		msg->im_local_addr.ia_q_key = gid_info->gl_redirect_qkey;
407218edb70cSeota 		msg->im_local_addr.ia_service_level = gid_info->gl_redirectSL;
40737c478bd9Sstevel@tonic-gate 	} else {
40747c478bd9Sstevel@tonic-gate 		msg->im_local_addr.ia_remote_qno = 1;
40757c478bd9Sstevel@tonic-gate 		msg->im_local_addr.ia_p_key = gid_info->gl_p_key;
40767c478bd9Sstevel@tonic-gate 		msg->im_local_addr.ia_q_key = IB_GSI_QKEY;
407718edb70cSeota 		msg->im_local_addr.ia_service_level = gid_info->gl_SL;
40787c478bd9Sstevel@tonic-gate 	}
40797c478bd9Sstevel@tonic-gate 	hdr = IBDM_OUT_IBMFMSG_MADHDR(msg);
408018edb70cSeota 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*hdr))
40817c478bd9Sstevel@tonic-gate 	hdr->BaseVersion	= MAD_CLASS_BASE_VERS_1;
40827c478bd9Sstevel@tonic-gate 	hdr->MgmtClass		= MAD_MGMT_CLASS_DEV_MGT;
40837c478bd9Sstevel@tonic-gate 	hdr->ClassVersion	= IB_DM_CLASS_VERSION_1;
40847c478bd9Sstevel@tonic-gate 	hdr->R_Method		= IB_DM_DEVMGT_METHOD_GET;
40857c478bd9Sstevel@tonic-gate 	hdr->Status		= 0;
40867c478bd9Sstevel@tonic-gate 	hdr->TransactionID	= h2b64(gid_info->gl_transactionID);
40877c478bd9Sstevel@tonic-gate 
40887c478bd9Sstevel@tonic-gate 	switch (cb_args->cb_req_type) {
40897c478bd9Sstevel@tonic-gate 	case IBDM_REQ_TYPE_CLASSPORTINFO:
40907c478bd9Sstevel@tonic-gate 		hdr->AttributeID = h2b16(IB_DM_ATTR_CLASSPORTINFO);
40917c478bd9Sstevel@tonic-gate 		hdr->AttributeModifier = 0;
40927c478bd9Sstevel@tonic-gate 		timeout_id = &gid_info->gl_timeout_id;
40937c478bd9Sstevel@tonic-gate 		break;
40947c478bd9Sstevel@tonic-gate 	case IBDM_REQ_TYPE_IOUINFO:
40957c478bd9Sstevel@tonic-gate 		hdr->AttributeID = h2b16(IB_DM_ATTR_IO_UNITINFO);
40967c478bd9Sstevel@tonic-gate 		hdr->AttributeModifier = 0;
40977c478bd9Sstevel@tonic-gate 		timeout_id = &gid_info->gl_timeout_id;
40987c478bd9Sstevel@tonic-gate 		break;
40997c478bd9Sstevel@tonic-gate 	case IBDM_REQ_TYPE_IOCINFO:
41007c478bd9Sstevel@tonic-gate 		hdr->AttributeID = h2b16(IB_DM_ATTR_IOC_CTRL_PROFILE);
41017c478bd9Sstevel@tonic-gate 		hdr->AttributeModifier = h2b32(cb_args->cb_ioc_num + 1);
41027c478bd9Sstevel@tonic-gate 		ioc = IBDM_GIDINFO2IOCINFO(gid_info, cb_args->cb_ioc_num);
41037c478bd9Sstevel@tonic-gate 		timeout_id = &ioc->ioc_timeout_id;
41047c478bd9Sstevel@tonic-gate 		break;
41057c478bd9Sstevel@tonic-gate 	case IBDM_REQ_TYPE_SRVENTS:
41067c478bd9Sstevel@tonic-gate 		hdr->AttributeID = h2b16(IB_DM_ATTR_SERVICE_ENTRIES);
41079d3d2ed0Shiremath 		ibdm_fill_srv_attr_mod(hdr, cb_args);
41087c478bd9Sstevel@tonic-gate 		ioc = IBDM_GIDINFO2IOCINFO(gid_info, cb_args->cb_ioc_num);
41097c478bd9Sstevel@tonic-gate 		timeout_id =
41107c478bd9Sstevel@tonic-gate 		    &ioc->ioc_serv[cb_args->cb_srvents_start].se_timeout_id;
41117c478bd9Sstevel@tonic-gate 		break;
41127c478bd9Sstevel@tonic-gate 	case IBDM_REQ_TYPE_IOU_DIAGCODE:
41137c478bd9Sstevel@tonic-gate 		hdr->AttributeID = h2b16(IB_DM_ATTR_DIAG_CODE);
41147c478bd9Sstevel@tonic-gate 		hdr->AttributeModifier = 0;
41157c478bd9Sstevel@tonic-gate 		timeout_id = &gid_info->gl_timeout_id;
41167c478bd9Sstevel@tonic-gate 		break;
41177c478bd9Sstevel@tonic-gate 	case IBDM_REQ_TYPE_IOC_DIAGCODE:
41187c478bd9Sstevel@tonic-gate 		hdr->AttributeID = h2b16(IB_DM_ATTR_DIAG_CODE);
41197c478bd9Sstevel@tonic-gate 		hdr->AttributeModifier = h2b32(cb_args->cb_ioc_num + 1);
41207c478bd9Sstevel@tonic-gate 		ioc_no = cb_args->cb_ioc_num;
41217c478bd9Sstevel@tonic-gate 		ioc = &gid_info->gl_iou->iou_ioc_info[ioc_no];
41227c478bd9Sstevel@tonic-gate 		timeout_id = &ioc->ioc_dc_timeout_id;
41237c478bd9Sstevel@tonic-gate 		break;
41247c478bd9Sstevel@tonic-gate 	}
412518edb70cSeota 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*hdr))
41267c478bd9Sstevel@tonic-gate 
41277c478bd9Sstevel@tonic-gate 	*timeout_id = timeout(ibdm_pkt_timeout_hdlr,
41287c478bd9Sstevel@tonic-gate 	    cb_args, IBDM_TIMEOUT_VALUE(ibdm_dft_timeout));
41297c478bd9Sstevel@tonic-gate 
413018edb70cSeota 	mutex_exit(&gid_info->gl_mutex);
413118edb70cSeota 
41327c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L5("ibdm", "\tretry_command: %p,%x,%d,%d:"
41337c478bd9Sstevel@tonic-gate 	    "timeout %x", cb_args->cb_req_type, cb_args->cb_ioc_num,
41347c478bd9Sstevel@tonic-gate 	    cb_args->cb_srvents_start, *timeout_id);
41357c478bd9Sstevel@tonic-gate 
4136a1e3386eShiremath 	if (ibmf_msg_transport(gid_info->gl_ibmf_hdl,
41377c478bd9Sstevel@tonic-gate 	    gid_info->gl_qp_hdl, msg, NULL, ibdm_ibmf_send_cb,
4138a1e3386eShiremath 	    cb_args, 0) != IBMF_SUCCESS) {
41397c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibdm", "\tretry_command: send failed: %p "
41407c478bd9Sstevel@tonic-gate 		    "rtype 0x%x iocidx 0x%x srvidx %d", cb_args->cb_gid_info,
41417c478bd9Sstevel@tonic-gate 		    cb_args->cb_req_type, cb_args->cb_ioc_num,
41427c478bd9Sstevel@tonic-gate 		    cb_args->cb_srvents_start);
41437c478bd9Sstevel@tonic-gate 		ibdm_ibmf_send_cb(gid_info->gl_ibmf_hdl, msg, cb_args);
41447c478bd9Sstevel@tonic-gate 	}
41457c478bd9Sstevel@tonic-gate 	mutex_enter(&gid_info->gl_mutex);
4146a1e3386eShiremath 	return (IBDM_SUCCESS);
41477c478bd9Sstevel@tonic-gate }
41487c478bd9Sstevel@tonic-gate 
41497c478bd9Sstevel@tonic-gate 
41507c478bd9Sstevel@tonic-gate /*
41517c478bd9Sstevel@tonic-gate  * ibdm_update_ioc_port_gidlist()
41527c478bd9Sstevel@tonic-gate  */
41537c478bd9Sstevel@tonic-gate static void
ibdm_update_ioc_port_gidlist(ibdm_ioc_info_t * dest,ibdm_dp_gidinfo_t * gid_info)41547c478bd9Sstevel@tonic-gate ibdm_update_ioc_port_gidlist(ibdm_ioc_info_t *dest,
41557c478bd9Sstevel@tonic-gate     ibdm_dp_gidinfo_t *gid_info)
41567c478bd9Sstevel@tonic-gate {
41577c478bd9Sstevel@tonic-gate 	int		ii, ngid_ents;
41587c478bd9Sstevel@tonic-gate 	ibdm_gid_t	*tmp;
41597c478bd9Sstevel@tonic-gate 	ibdm_hca_list_t	*gid_hca_head, *temp;
41607c478bd9Sstevel@tonic-gate 	ibdm_hca_list_t	*ioc_head = NULL;
416153c1b7a3Seota 	ASSERT(MUTEX_HELD(&gid_info->gl_mutex));
41627c478bd9Sstevel@tonic-gate 
41637c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L5("ibdm", "\tupdate_ioc_port_gidlist: Enter");
41647c478bd9Sstevel@tonic-gate 
41657c478bd9Sstevel@tonic-gate 	ngid_ents = gid_info->gl_ngids;
41667c478bd9Sstevel@tonic-gate 	dest->ioc_nportgids = ngid_ents;
41677c478bd9Sstevel@tonic-gate 	dest->ioc_gid_list = kmem_zalloc(sizeof (ibdm_gid_t) *
41687c478bd9Sstevel@tonic-gate 	    ngid_ents, KM_SLEEP);
41697c478bd9Sstevel@tonic-gate 	tmp = gid_info->gl_gid;
41707c478bd9Sstevel@tonic-gate 	for (ii = 0; (ii < ngid_ents) && (tmp); ii++) {
41717c478bd9Sstevel@tonic-gate 		dest->ioc_gid_list[ii].gid_dgid_hi = tmp->gid_dgid_hi;
41727c478bd9Sstevel@tonic-gate 		dest->ioc_gid_list[ii].gid_dgid_lo = tmp->gid_dgid_lo;
41737c478bd9Sstevel@tonic-gate 		tmp = tmp->gid_next;
41747c478bd9Sstevel@tonic-gate 	}
41757c478bd9Sstevel@tonic-gate 
41767c478bd9Sstevel@tonic-gate 	gid_hca_head = gid_info->gl_hca_list;
41777c478bd9Sstevel@tonic-gate 	while (gid_hca_head) {
41787c478bd9Sstevel@tonic-gate 		temp = ibdm_dup_hca_attr(gid_hca_head);
41797c478bd9Sstevel@tonic-gate 		temp->hl_next = ioc_head;
41807c478bd9Sstevel@tonic-gate 		ioc_head = temp;
41817c478bd9Sstevel@tonic-gate 		gid_hca_head = gid_hca_head->hl_next;
41827c478bd9Sstevel@tonic-gate 	}
41837c478bd9Sstevel@tonic-gate 	dest->ioc_hca_list = ioc_head;
41847c478bd9Sstevel@tonic-gate }
41857c478bd9Sstevel@tonic-gate 
41867c478bd9Sstevel@tonic-gate 
41877c478bd9Sstevel@tonic-gate /*
41887c478bd9Sstevel@tonic-gate  * ibdm_alloc_send_buffers()
418953c1b7a3Seota  *	Allocates memory for the IBMF send buffer to send and/or receive
419053c1b7a3Seota  *	the Device Management MAD packet.
41917c478bd9Sstevel@tonic-gate  */
41927c478bd9Sstevel@tonic-gate static void
ibdm_alloc_send_buffers(ibmf_msg_t * msgp)41937c478bd9Sstevel@tonic-gate ibdm_alloc_send_buffers(ibmf_msg_t *msgp)
41947c478bd9Sstevel@tonic-gate {
41957c478bd9Sstevel@tonic-gate 	msgp->im_msgbufs_send.im_bufs_mad_hdr =
41967c478bd9Sstevel@tonic-gate 	    kmem_zalloc(IBDM_MAD_SIZE, KM_SLEEP);
419753c1b7a3Seota 
419853c1b7a3Seota 	msgp->im_msgbufs_send.im_bufs_cl_hdr = (uchar_t *)
41997c478bd9Sstevel@tonic-gate 	    msgp->im_msgbufs_send.im_bufs_mad_hdr + sizeof (ib_mad_hdr_t);
420053c1b7a3Seota 	msgp->im_msgbufs_send.im_bufs_cl_hdr_len = IBDM_DM_MAD_HDR_SZ;
420153c1b7a3Seota 
420253c1b7a3Seota 	msgp->im_msgbufs_send.im_bufs_cl_data =
420353c1b7a3Seota 	    ((char *)msgp->im_msgbufs_send.im_bufs_cl_hdr + IBDM_DM_MAD_HDR_SZ);
42047c478bd9Sstevel@tonic-gate 	msgp->im_msgbufs_send.im_bufs_cl_data_len =
420553c1b7a3Seota 	    IBDM_MAD_SIZE - sizeof (ib_mad_hdr_t) - IBDM_DM_MAD_HDR_SZ;
42067c478bd9Sstevel@tonic-gate }
42077c478bd9Sstevel@tonic-gate 
42087c478bd9Sstevel@tonic-gate 
42097c478bd9Sstevel@tonic-gate /*
42107c478bd9Sstevel@tonic-gate  * ibdm_alloc_send_buffers()
42117c478bd9Sstevel@tonic-gate  *	De-allocates memory for the IBMF send buffer
42127c478bd9Sstevel@tonic-gate  */
42137c478bd9Sstevel@tonic-gate static void
ibdm_free_send_buffers(ibmf_msg_t * msgp)42147c478bd9Sstevel@tonic-gate ibdm_free_send_buffers(ibmf_msg_t *msgp)
42157c478bd9Sstevel@tonic-gate {
42167c478bd9Sstevel@tonic-gate 	if (msgp->im_msgbufs_send.im_bufs_mad_hdr != NULL)
42177c478bd9Sstevel@tonic-gate 		kmem_free(msgp->im_msgbufs_send.im_bufs_mad_hdr, IBDM_MAD_SIZE);
42187c478bd9Sstevel@tonic-gate }
42197c478bd9Sstevel@tonic-gate 
42207c478bd9Sstevel@tonic-gate /*
42217c478bd9Sstevel@tonic-gate  * ibdm_probe_ioc()
42227c478bd9Sstevel@tonic-gate  *  	1. Gets the node records for the port GUID. This detects all the port
42237c478bd9Sstevel@tonic-gate  *  		to the IOU.
42247c478bd9Sstevel@tonic-gate  *	2. Selectively probes all the IOC, given it's node GUID
42257c478bd9Sstevel@tonic-gate  *	3. In case of reprobe, only the IOC to be reprobed is send the IOC
42267c478bd9Sstevel@tonic-gate  *		Controller Profile asynchronously
42277c478bd9Sstevel@tonic-gate  */
42287c478bd9Sstevel@tonic-gate /*ARGSUSED*/
42297c478bd9Sstevel@tonic-gate static void
ibdm_probe_ioc(ib_guid_t nodeguid,ib_guid_t ioc_guid,int reprobe_flag)42307c478bd9Sstevel@tonic-gate ibdm_probe_ioc(ib_guid_t nodeguid, ib_guid_t ioc_guid, int reprobe_flag)
42317c478bd9Sstevel@tonic-gate {
42327c478bd9Sstevel@tonic-gate 	int			ii, nrecords;
42337c478bd9Sstevel@tonic-gate 	size_t			nr_len = 0, pi_len = 0;
42347c478bd9Sstevel@tonic-gate 	ib_gid_t		sgid, dgid;
42357c478bd9Sstevel@tonic-gate 	ibdm_hca_list_t		*hca_list = NULL;
42367c478bd9Sstevel@tonic-gate 	sa_node_record_t	*nr, *tmp;
42377c478bd9Sstevel@tonic-gate 	ibdm_port_attr_t	*port = NULL;
42387c478bd9Sstevel@tonic-gate 	ibdm_dp_gidinfo_t	*reprobe_gid, *new_gid, *node_gid;
42397c478bd9Sstevel@tonic-gate 	ibdm_dp_gidinfo_t	*temp_gidinfo;
42407c478bd9Sstevel@tonic-gate 	ibdm_gid_t		*temp_gid;
42417c478bd9Sstevel@tonic-gate 	sa_portinfo_record_t	*pi;
42427c478bd9Sstevel@tonic-gate 
4243a1e3386eShiremath 	IBTF_DPRINTF_L4("ibdm", "\tprobe_ioc(%llx, %llx, %x): Begin",
42447c478bd9Sstevel@tonic-gate 	    nodeguid, ioc_guid, reprobe_flag);
42457c478bd9Sstevel@tonic-gate 
42467c478bd9Sstevel@tonic-gate 	/* Rescan the GID list for any removed GIDs for reprobe */
42477c478bd9Sstevel@tonic-gate 	if (reprobe_flag)
42487c478bd9Sstevel@tonic-gate 		ibdm_rescan_gidlist(&ioc_guid);
42497c478bd9Sstevel@tonic-gate 
42507c478bd9Sstevel@tonic-gate 	mutex_enter(&ibdm.ibdm_hl_mutex);
42517c478bd9Sstevel@tonic-gate 	for (ibdm_get_next_port(&hca_list, &port, 1); port;
42527c478bd9Sstevel@tonic-gate 	    ibdm_get_next_port(&hca_list, &port, 1)) {
42537c478bd9Sstevel@tonic-gate 		reprobe_gid = new_gid = node_gid = NULL;
42547c478bd9Sstevel@tonic-gate 
42557c478bd9Sstevel@tonic-gate 		nr = ibdm_get_node_records(port->pa_sa_hdl, &nr_len, nodeguid);
42567c478bd9Sstevel@tonic-gate 		if (nr == NULL) {
42577c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibdm", "\tprobe_ioc: no records");
42587c478bd9Sstevel@tonic-gate 			continue;
42597c478bd9Sstevel@tonic-gate 		}
42607c478bd9Sstevel@tonic-gate 		nrecords = (nr_len / sizeof (sa_node_record_t));
42617c478bd9Sstevel@tonic-gate 		for (tmp = nr, ii = 0;  (ii < nrecords); ii++, tmp++) {
426253c1b7a3Seota 			if ((pi = ibdm_get_portinfo(
426353c1b7a3Seota 			    port->pa_sa_hdl, &pi_len, tmp->LID)) ==  NULL) {
426453c1b7a3Seota 				IBTF_DPRINTF_L4("ibdm",
426553c1b7a3Seota 				    "\tibdm_get_portinfo: no portinfo recs");
426653c1b7a3Seota 				continue;
426753c1b7a3Seota 			}
42687c478bd9Sstevel@tonic-gate 
426953c1b7a3Seota 			/*
427053c1b7a3Seota 			 * If Device Management is not supported on
427153c1b7a3Seota 			 * this port, skip the rest.
427253c1b7a3Seota 			 */
427353c1b7a3Seota 			if (!(pi->PortInfo.CapabilityMask &
42747c478bd9Sstevel@tonic-gate 			    SM_CAP_MASK_IS_DM_SUPPD)) {
427553c1b7a3Seota 				kmem_free(pi, pi_len);
427653c1b7a3Seota 				continue;
427753c1b7a3Seota 			}
42787c478bd9Sstevel@tonic-gate 
427953c1b7a3Seota 			/*
428053c1b7a3Seota 			 * For reprobes: Check if GID, already in
428153c1b7a3Seota 			 * the list. If so, set the state to SKIPPED
428253c1b7a3Seota 			 */
428353c1b7a3Seota 			if (((temp_gidinfo = ibdm_find_gid(nodeguid,
428453c1b7a3Seota 			    tmp->NodeInfo.PortGUID)) != NULL) &&
428553c1b7a3Seota 			    temp_gidinfo->gl_state ==
428653c1b7a3Seota 			    IBDM_GID_PROBING_COMPLETE) {
428753c1b7a3Seota 				ASSERT(reprobe_gid == NULL);
428853c1b7a3Seota 				ibdm_addto_glhcalist(temp_gidinfo,
428953c1b7a3Seota 				    hca_list);
429053c1b7a3Seota 				reprobe_gid = temp_gidinfo;
429153c1b7a3Seota 				kmem_free(pi, pi_len);
429253c1b7a3Seota 				continue;
429353c1b7a3Seota 			} else if (temp_gidinfo != NULL) {
429453c1b7a3Seota 				kmem_free(pi, pi_len);
429553c1b7a3Seota 				ibdm_addto_glhcalist(temp_gidinfo,
429653c1b7a3Seota 				    hca_list);
429753c1b7a3Seota 				continue;
429853c1b7a3Seota 			}
42997c478bd9Sstevel@tonic-gate 
430053c1b7a3Seota 			IBTF_DPRINTF_L4("ibdm", "\tprobe_ioc : "
430153c1b7a3Seota 			    "create_gid : prefix %llx, guid %llx\n",
430253c1b7a3Seota 			    pi->PortInfo.GidPrefix,
430353c1b7a3Seota 			    tmp->NodeInfo.PortGUID);
430453c1b7a3Seota 
430553c1b7a3Seota 			sgid.gid_prefix = port->pa_sn_prefix;
430653c1b7a3Seota 			sgid.gid_guid = port->pa_port_guid;
430753c1b7a3Seota 			dgid.gid_prefix = pi->PortInfo.GidPrefix;
430853c1b7a3Seota 			dgid.gid_guid = tmp->NodeInfo.PortGUID;
430953c1b7a3Seota 			new_gid = ibdm_create_gid_info(port, sgid,
431053c1b7a3Seota 			    dgid);
431153c1b7a3Seota 			if (new_gid == NULL) {
431253c1b7a3Seota 				IBTF_DPRINTF_L2("ibdm", "\tprobe_ioc: "
431353c1b7a3Seota 				    "create_gid_info failed\n");
43147c478bd9Sstevel@tonic-gate 				kmem_free(pi, pi_len);
431553c1b7a3Seota 				continue;
43167c478bd9Sstevel@tonic-gate 			}
431753c1b7a3Seota 			if (node_gid == NULL) {
431853c1b7a3Seota 				node_gid = new_gid;
431953c1b7a3Seota 				ibdm_add_to_gl_gid(node_gid, node_gid);
432053c1b7a3Seota 			} else {
432153c1b7a3Seota 				IBTF_DPRINTF_L4("ibdm",
432253c1b7a3Seota 				    "\tprobe_ioc: new gid");
432353c1b7a3Seota 				temp_gid = kmem_zalloc(
432453c1b7a3Seota 				    sizeof (ibdm_gid_t), KM_SLEEP);
432553c1b7a3Seota 				temp_gid->gid_dgid_hi =
432653c1b7a3Seota 				    new_gid->gl_dgid_hi;
432753c1b7a3Seota 				temp_gid->gid_dgid_lo =
432853c1b7a3Seota 				    new_gid->gl_dgid_lo;
432953c1b7a3Seota 				temp_gid->gid_next = node_gid->gl_gid;
433053c1b7a3Seota 				node_gid->gl_gid = temp_gid;
433153c1b7a3Seota 				node_gid->gl_ngids++;
433253c1b7a3Seota 			}
43338e55d263SRajkumar Sivaprakasam 			new_gid->gl_is_dm_capable = B_TRUE;
433453c1b7a3Seota 			new_gid->gl_nodeguid = nodeguid;
433553c1b7a3Seota 			new_gid->gl_portguid = dgid.gid_guid;
433653c1b7a3Seota 			ibdm_addto_glhcalist(new_gid, hca_list);
433753c1b7a3Seota 
433853c1b7a3Seota 			/*
433953c1b7a3Seota 			 * Set the state to skipped as all these
434053c1b7a3Seota 			 * gids point to the same node.
434153c1b7a3Seota 			 * We (re)probe only one GID below and reset
434253c1b7a3Seota 			 * state appropriately
434353c1b7a3Seota 			 */
434453c1b7a3Seota 			new_gid->gl_state = IBDM_GID_PROBING_SKIPPED;
434553c1b7a3Seota 			new_gid->gl_devid = (*tmp).NodeInfo.DeviceID;
434653c1b7a3Seota 			kmem_free(pi, pi_len);
43477c478bd9Sstevel@tonic-gate 		}
43487c478bd9Sstevel@tonic-gate 		kmem_free(nr, nr_len);
43497c478bd9Sstevel@tonic-gate 
43507c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibdm", "\tprobe_ioc : reprobe_flag %d "
43517c478bd9Sstevel@tonic-gate 		    "reprobe_gid %p new_gid %p node_gid %p",
43527c478bd9Sstevel@tonic-gate 		    reprobe_flag, reprobe_gid, new_gid, node_gid);
43537c478bd9Sstevel@tonic-gate 
43547c478bd9Sstevel@tonic-gate 		if (reprobe_flag != 0 && reprobe_gid != NULL) {
43557c478bd9Sstevel@tonic-gate 			int	niocs, jj;
43567c478bd9Sstevel@tonic-gate 			ibdm_ioc_info_t *tmp_ioc;
43577c478bd9Sstevel@tonic-gate 			int ioc_matched = 0;
43587c478bd9Sstevel@tonic-gate 
43597c478bd9Sstevel@tonic-gate 			mutex_exit(&ibdm.ibdm_hl_mutex);
43607c478bd9Sstevel@tonic-gate 			mutex_enter(&reprobe_gid->gl_mutex);
43617c478bd9Sstevel@tonic-gate 			reprobe_gid->gl_state = IBDM_GET_IOC_DETAILS;
43627c478bd9Sstevel@tonic-gate 			niocs =
43637c478bd9Sstevel@tonic-gate 			    reprobe_gid->gl_iou->iou_info.iou_num_ctrl_slots;
43647c478bd9Sstevel@tonic-gate 			reprobe_gid->gl_pending_cmds++;
43657c478bd9Sstevel@tonic-gate 			mutex_exit(&reprobe_gid->gl_mutex);
43667c478bd9Sstevel@tonic-gate 
43677c478bd9Sstevel@tonic-gate 			for (jj = 0; jj < niocs; jj++) {
43687c478bd9Sstevel@tonic-gate 				tmp_ioc =
43697c478bd9Sstevel@tonic-gate 				    IBDM_GIDINFO2IOCINFO(reprobe_gid, jj);
43707c478bd9Sstevel@tonic-gate 				if (tmp_ioc->ioc_profile.ioc_guid != ioc_guid)
43717c478bd9Sstevel@tonic-gate 					continue;
43727c478bd9Sstevel@tonic-gate 
43737c478bd9Sstevel@tonic-gate 				ioc_matched = 1;
43747c478bd9Sstevel@tonic-gate 
43757c478bd9Sstevel@tonic-gate 				/*
43767c478bd9Sstevel@tonic-gate 				 * Explicitly set gl_reprobe_flag to 0 so that
43777c478bd9Sstevel@tonic-gate 				 * IBnex is not notified on completion
43787c478bd9Sstevel@tonic-gate 				 */
43797c478bd9Sstevel@tonic-gate 				mutex_enter(&reprobe_gid->gl_mutex);
43807c478bd9Sstevel@tonic-gate 				reprobe_gid->gl_reprobe_flag = 0;
43817c478bd9Sstevel@tonic-gate 				mutex_exit(&reprobe_gid->gl_mutex);
43827c478bd9Sstevel@tonic-gate 
43837c478bd9Sstevel@tonic-gate 				mutex_enter(&ibdm.ibdm_mutex);
43847c478bd9Sstevel@tonic-gate 				ibdm.ibdm_ngid_probes_in_progress++;
43857c478bd9Sstevel@tonic-gate 				mutex_exit(&ibdm.ibdm_mutex);
43867c478bd9Sstevel@tonic-gate 				if (ibdm_send_ioc_profile(reprobe_gid, jj) !=
43877c478bd9Sstevel@tonic-gate 				    IBDM_SUCCESS) {
43887c478bd9Sstevel@tonic-gate 					IBTF_DPRINTF_L4("ibdm",
43897c478bd9Sstevel@tonic-gate 					    "\tprobe_ioc: "
43907c478bd9Sstevel@tonic-gate 					    "send_ioc_profile failed "
43917c478bd9Sstevel@tonic-gate 					    "for ioc %d", jj);
43927c478bd9Sstevel@tonic-gate 					ibdm_gid_decr_pending(reprobe_gid);
43937c478bd9Sstevel@tonic-gate 					break;
43947c478bd9Sstevel@tonic-gate 				}
43957c478bd9Sstevel@tonic-gate 				mutex_enter(&ibdm.ibdm_mutex);
43967c478bd9Sstevel@tonic-gate 				ibdm_wait_probe_completion();
43977c478bd9Sstevel@tonic-gate 				mutex_exit(&ibdm.ibdm_mutex);
43987c478bd9Sstevel@tonic-gate 				break;
43997c478bd9Sstevel@tonic-gate 			}
44007c478bd9Sstevel@tonic-gate 			if (ioc_matched == 0)
44017c478bd9Sstevel@tonic-gate 				ibdm_gid_decr_pending(reprobe_gid);
44027c478bd9Sstevel@tonic-gate 			else {
44037c478bd9Sstevel@tonic-gate 				mutex_enter(&ibdm.ibdm_hl_mutex);
44047c478bd9Sstevel@tonic-gate 				break;
44057c478bd9Sstevel@tonic-gate 			}
44067c478bd9Sstevel@tonic-gate 		} else if (new_gid != NULL) {
44077c478bd9Sstevel@tonic-gate 			mutex_exit(&ibdm.ibdm_hl_mutex);
44087c478bd9Sstevel@tonic-gate 			node_gid = node_gid ? node_gid : new_gid;
44097c478bd9Sstevel@tonic-gate 
44107c478bd9Sstevel@tonic-gate 			/*
44117c478bd9Sstevel@tonic-gate 			 * New or reinserted GID : Enable notification
44127c478bd9Sstevel@tonic-gate 			 * to IBnex
44137c478bd9Sstevel@tonic-gate 			 */
44147c478bd9Sstevel@tonic-gate 			mutex_enter(&node_gid->gl_mutex);
44157c478bd9Sstevel@tonic-gate 			node_gid->gl_reprobe_flag = 1;
44167c478bd9Sstevel@tonic-gate 			mutex_exit(&node_gid->gl_mutex);
44177c478bd9Sstevel@tonic-gate 
44187c478bd9Sstevel@tonic-gate 			ibdm_probe_gid(node_gid);
44197c478bd9Sstevel@tonic-gate 
44207c478bd9Sstevel@tonic-gate 			mutex_enter(&ibdm.ibdm_hl_mutex);
44217c478bd9Sstevel@tonic-gate 		}
44227c478bd9Sstevel@tonic-gate 	}
44237c478bd9Sstevel@tonic-gate 	mutex_exit(&ibdm.ibdm_hl_mutex);
44247c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tprobe_ioc : End\n");
44257c478bd9Sstevel@tonic-gate }
44267c478bd9Sstevel@tonic-gate 
44277c478bd9Sstevel@tonic-gate 
44287c478bd9Sstevel@tonic-gate /*
44297c478bd9Sstevel@tonic-gate  * ibdm_probe_gid()
44307c478bd9Sstevel@tonic-gate  *	Selectively probes the GID
44317c478bd9Sstevel@tonic-gate  */
44327c478bd9Sstevel@tonic-gate static void
ibdm_probe_gid(ibdm_dp_gidinfo_t * gid_info)44337c478bd9Sstevel@tonic-gate ibdm_probe_gid(ibdm_dp_gidinfo_t *gid_info)
44347c478bd9Sstevel@tonic-gate {
44357c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tprobe_gid:");
443653c1b7a3Seota 
443753c1b7a3Seota 	/*
443853c1b7a3Seota 	 * A Cisco FC GW needs the special handling to get IOUnitInfo.
443953c1b7a3Seota 	 */
44407c478bd9Sstevel@tonic-gate 	mutex_enter(&gid_info->gl_mutex);
444153c1b7a3Seota 	if (ibdm_is_cisco_switch(gid_info)) {
444253c1b7a3Seota 		gid_info->gl_pending_cmds++;
444353c1b7a3Seota 		gid_info->gl_state = IBDM_SET_CLASSPORTINFO;
444453c1b7a3Seota 		mutex_exit(&gid_info->gl_mutex);
444553c1b7a3Seota 
444653c1b7a3Seota 		if (ibdm_set_classportinfo(gid_info) != IBDM_SUCCESS) {
444753c1b7a3Seota 
444853c1b7a3Seota 			mutex_enter(&gid_info->gl_mutex);
444953c1b7a3Seota 			gid_info->gl_state = IBDM_GID_PROBING_FAILED;
445053c1b7a3Seota 			--gid_info->gl_pending_cmds;
445153c1b7a3Seota 			mutex_exit(&gid_info->gl_mutex);
445253c1b7a3Seota 
445353c1b7a3Seota 			/* free the hca_list on this gid_info */
445453c1b7a3Seota 			ibdm_delete_glhca_list(gid_info);
445553c1b7a3Seota 			gid_info = gid_info->gl_next;
445653c1b7a3Seota 			return;
445753c1b7a3Seota 		}
445853c1b7a3Seota 
445953c1b7a3Seota 		mutex_enter(&gid_info->gl_mutex);
446053c1b7a3Seota 		ibdm_wait_cisco_probe_completion(gid_info);
446153c1b7a3Seota 
446253c1b7a3Seota 		IBTF_DPRINTF_L4("ibdm",
446353c1b7a3Seota 		    "\tprobe_gid: CISCO Wakeup signal received");
446453c1b7a3Seota 	}
446553c1b7a3Seota 
446653c1b7a3Seota 	/* move on to the 'GET_CLASSPORTINFO' stage */
44677c478bd9Sstevel@tonic-gate 	gid_info->gl_pending_cmds++;
44687c478bd9Sstevel@tonic-gate 	gid_info->gl_state = IBDM_GET_CLASSPORTINFO;
44697c478bd9Sstevel@tonic-gate 	mutex_exit(&gid_info->gl_mutex);
447053c1b7a3Seota 
44717c478bd9Sstevel@tonic-gate 	if (ibdm_send_classportinfo(gid_info) != IBDM_SUCCESS) {
447253c1b7a3Seota 
44737c478bd9Sstevel@tonic-gate 		mutex_enter(&gid_info->gl_mutex);
44747c478bd9Sstevel@tonic-gate 		gid_info->gl_state = IBDM_GID_PROBING_FAILED;
44757c478bd9Sstevel@tonic-gate 		--gid_info->gl_pending_cmds;
44767c478bd9Sstevel@tonic-gate 		mutex_exit(&gid_info->gl_mutex);
447753c1b7a3Seota 
447853c1b7a3Seota 		/* free the hca_list on this gid_info */
44797c478bd9Sstevel@tonic-gate 		ibdm_delete_glhca_list(gid_info);
44807c478bd9Sstevel@tonic-gate 		gid_info = gid_info->gl_next;
44817c478bd9Sstevel@tonic-gate 		return;
44827c478bd9Sstevel@tonic-gate 	}
448353c1b7a3Seota 
44847c478bd9Sstevel@tonic-gate 	mutex_enter(&ibdm.ibdm_mutex);
44857c478bd9Sstevel@tonic-gate 	ibdm.ibdm_ngid_probes_in_progress++;
44867c478bd9Sstevel@tonic-gate 	gid_info = gid_info->gl_next;
44877c478bd9Sstevel@tonic-gate 	ibdm_wait_probe_completion();
44887c478bd9Sstevel@tonic-gate 	mutex_exit(&ibdm.ibdm_mutex);
448953c1b7a3Seota 
44907c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tprobe_gid: Wakeup signal received");
44917c478bd9Sstevel@tonic-gate }
44927c478bd9Sstevel@tonic-gate 
44937c478bd9Sstevel@tonic-gate 
44947c478bd9Sstevel@tonic-gate /*
44957c478bd9Sstevel@tonic-gate  * ibdm_create_gid_info()
44967c478bd9Sstevel@tonic-gate  *	Allocates a gid_info structure and initializes
44977c478bd9Sstevel@tonic-gate  *	Returns pointer to the structure on success
44987c478bd9Sstevel@tonic-gate  *	and NULL on failure
44997c478bd9Sstevel@tonic-gate  */
45007c478bd9Sstevel@tonic-gate static ibdm_dp_gidinfo_t *
ibdm_create_gid_info(ibdm_port_attr_t * port,ib_gid_t sgid,ib_gid_t dgid)45017c478bd9Sstevel@tonic-gate ibdm_create_gid_info(ibdm_port_attr_t *port, ib_gid_t sgid, ib_gid_t dgid)
45027c478bd9Sstevel@tonic-gate {
45037c478bd9Sstevel@tonic-gate 	uint8_t			ii, npaths;
45047c478bd9Sstevel@tonic-gate 	sa_path_record_t	*path;
45057c478bd9Sstevel@tonic-gate 	size_t			len;
45067c478bd9Sstevel@tonic-gate 	ibdm_pkey_tbl_t		*pkey_tbl;
45077c478bd9Sstevel@tonic-gate 	ibdm_dp_gidinfo_t	*gid_info = NULL;
45087c478bd9Sstevel@tonic-gate 	int			ret;
45097c478bd9Sstevel@tonic-gate 
45107c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tcreate_gid_info: Begin");
45117c478bd9Sstevel@tonic-gate 	npaths = 1;
45127c478bd9Sstevel@tonic-gate 
45137c478bd9Sstevel@tonic-gate 	/* query for reversible paths */
45147c478bd9Sstevel@tonic-gate 	if (port->pa_sa_hdl)
45157c478bd9Sstevel@tonic-gate 		ret = ibmf_saa_gid_to_pathrecords(port->pa_sa_hdl,
45167c478bd9Sstevel@tonic-gate 		    sgid, dgid, IBMF_SAA_PKEY_WC, 0, B_TRUE, &npaths, 0,
45177c478bd9Sstevel@tonic-gate 		    &len, &path);
45187c478bd9Sstevel@tonic-gate 	else
45197c478bd9Sstevel@tonic-gate 		return (NULL);
45207c478bd9Sstevel@tonic-gate 
45217c478bd9Sstevel@tonic-gate 	if (ret == IBMF_SUCCESS && path) {
45227c478bd9Sstevel@tonic-gate 		ibdm_dump_path_info(path);
45237c478bd9Sstevel@tonic-gate 
45247c478bd9Sstevel@tonic-gate 		gid_info = kmem_zalloc(
45257c478bd9Sstevel@tonic-gate 		    sizeof (ibdm_dp_gidinfo_t), KM_SLEEP);
45267c478bd9Sstevel@tonic-gate 		mutex_init(&gid_info->gl_mutex, NULL, MUTEX_DEFAULT, NULL);
452753c1b7a3Seota 		cv_init(&gid_info->gl_probe_cv, NULL, CV_DRIVER, NULL);
45287c478bd9Sstevel@tonic-gate 		gid_info->gl_dgid_hi		= path->DGID.gid_prefix;
45297c478bd9Sstevel@tonic-gate 		gid_info->gl_dgid_lo		= path->DGID.gid_guid;
45307c478bd9Sstevel@tonic-gate 		gid_info->gl_sgid_hi		= path->SGID.gid_prefix;
45317c478bd9Sstevel@tonic-gate 		gid_info->gl_sgid_lo		= path->SGID.gid_guid;
45327c478bd9Sstevel@tonic-gate 		gid_info->gl_p_key		= path->P_Key;
45337c478bd9Sstevel@tonic-gate 		gid_info->gl_sa_hdl		= port->pa_sa_hdl;
45347c478bd9Sstevel@tonic-gate 		gid_info->gl_ibmf_hdl		= port->pa_ibmf_hdl;
45357c478bd9Sstevel@tonic-gate 		gid_info->gl_slid		= path->SLID;
45367c478bd9Sstevel@tonic-gate 		gid_info->gl_dlid		= path->DLID;
45379d3d2ed0Shiremath 		gid_info->gl_transactionID	= (++ibdm.ibdm_transactionID)
45389d3d2ed0Shiremath 		    << IBDM_GID_TRANSACTIONID_SHIFT;
45399d3d2ed0Shiremath 		gid_info->gl_min_transactionID  = gid_info->gl_transactionID;
45409d3d2ed0Shiremath 		gid_info->gl_max_transactionID  = (ibdm.ibdm_transactionID +1)
45419d3d2ed0Shiremath 		    << IBDM_GID_TRANSACTIONID_SHIFT;
454218edb70cSeota 		gid_info->gl_SL			= path->SL;
45437c478bd9Sstevel@tonic-gate 
45447c478bd9Sstevel@tonic-gate 		gid_info->gl_qp_hdl = IBMF_QP_HANDLE_DEFAULT;
45457c478bd9Sstevel@tonic-gate 		for (ii = 0; ii < port->pa_npkeys; ii++) {
45467c478bd9Sstevel@tonic-gate 			if (port->pa_pkey_tbl == NULL)
45477c478bd9Sstevel@tonic-gate 				break;
45487c478bd9Sstevel@tonic-gate 
45497c478bd9Sstevel@tonic-gate 			pkey_tbl = &port->pa_pkey_tbl[ii];
45507c478bd9Sstevel@tonic-gate 			if ((gid_info->gl_p_key == pkey_tbl->pt_pkey) &&
45517c478bd9Sstevel@tonic-gate 			    (pkey_tbl->pt_qp_hdl != NULL)) {
45527c478bd9Sstevel@tonic-gate 				gid_info->gl_qp_hdl = pkey_tbl->pt_qp_hdl;
45537c478bd9Sstevel@tonic-gate 				break;
45547c478bd9Sstevel@tonic-gate 			}
45557c478bd9Sstevel@tonic-gate 		}
45567c478bd9Sstevel@tonic-gate 		kmem_free(path, len);
45579d3d2ed0Shiremath 
45589d3d2ed0Shiremath 		/*
45599d3d2ed0Shiremath 		 * QP handle for GID not initialized. No matching Pkey
45609d3d2ed0Shiremath 		 * was found!! ibdm should *not* hit this case. Flag an
45619d3d2ed0Shiremath 		 * error and drop the GID if ibdm does encounter this.
45629d3d2ed0Shiremath 		 */
45639d3d2ed0Shiremath 		if (gid_info->gl_qp_hdl == NULL) {
45649d3d2ed0Shiremath 			IBTF_DPRINTF_L2(ibdm_string,
45659d3d2ed0Shiremath 			    "\tcreate_gid_info: No matching Pkey");
45669d3d2ed0Shiremath 			ibdm_delete_gidinfo(gid_info);
45679d3d2ed0Shiremath 			return (NULL);
45689d3d2ed0Shiremath 		}
45699d3d2ed0Shiremath 
45707c478bd9Sstevel@tonic-gate 		ibdm.ibdm_ngids++;
45717c478bd9Sstevel@tonic-gate 		if (ibdm.ibdm_dp_gidlist_head == NULL) {
45727c478bd9Sstevel@tonic-gate 			ibdm.ibdm_dp_gidlist_head = gid_info;
45737c478bd9Sstevel@tonic-gate 			ibdm.ibdm_dp_gidlist_tail = gid_info;
45747c478bd9Sstevel@tonic-gate 		} else {
45757c478bd9Sstevel@tonic-gate 			ibdm.ibdm_dp_gidlist_tail->gl_next = gid_info;
45767c478bd9Sstevel@tonic-gate 			gid_info->gl_prev = ibdm.ibdm_dp_gidlist_tail;
45777c478bd9Sstevel@tonic-gate 			ibdm.ibdm_dp_gidlist_tail = gid_info;
45787c478bd9Sstevel@tonic-gate 		}
45797c478bd9Sstevel@tonic-gate 	}
45807c478bd9Sstevel@tonic-gate 
45817c478bd9Sstevel@tonic-gate 	return (gid_info);
45827c478bd9Sstevel@tonic-gate }
45837c478bd9Sstevel@tonic-gate 
45847c478bd9Sstevel@tonic-gate 
45857c478bd9Sstevel@tonic-gate /*
45867c478bd9Sstevel@tonic-gate  * ibdm_get_node_records
45877c478bd9Sstevel@tonic-gate  *	Sends a SA query to get the NODE record
45887c478bd9Sstevel@tonic-gate  *	Returns pointer to the sa_node_record_t on success
45897c478bd9Sstevel@tonic-gate  *	and NULL on failure
45907c478bd9Sstevel@tonic-gate  */
45917c478bd9Sstevel@tonic-gate static sa_node_record_t *
ibdm_get_node_records(ibmf_saa_handle_t sa_hdl,size_t * length,ib_guid_t guid)45927c478bd9Sstevel@tonic-gate ibdm_get_node_records(ibmf_saa_handle_t sa_hdl, size_t *length, ib_guid_t guid)
45937c478bd9Sstevel@tonic-gate {
45947c478bd9Sstevel@tonic-gate 	sa_node_record_t	req, *resp = NULL;
45957c478bd9Sstevel@tonic-gate 	ibmf_saa_access_args_t	args;
45967c478bd9Sstevel@tonic-gate 	int			ret;
45977c478bd9Sstevel@tonic-gate 
45987c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tget_node_records: Begin");
45997c478bd9Sstevel@tonic-gate 
46007c478bd9Sstevel@tonic-gate 	bzero(&req, sizeof (sa_node_record_t));
46017c478bd9Sstevel@tonic-gate 	req.NodeInfo.NodeGUID = guid;
46027c478bd9Sstevel@tonic-gate 
46037c478bd9Sstevel@tonic-gate 	args.sq_attr_id		= SA_NODERECORD_ATTRID;
46047c478bd9Sstevel@tonic-gate 	args.sq_access_type 	= IBMF_SAA_RETRIEVE;
46057c478bd9Sstevel@tonic-gate 	args.sq_component_mask 	= SA_NODEINFO_COMPMASK_NODEGUID;
46067c478bd9Sstevel@tonic-gate 	args.sq_template	= &req;
46077c478bd9Sstevel@tonic-gate 	args.sq_callback	= NULL;
46087c478bd9Sstevel@tonic-gate 	args.sq_callback_arg 	= NULL;
46097c478bd9Sstevel@tonic-gate 
46107c478bd9Sstevel@tonic-gate 	ret = ibmf_sa_access(sa_hdl, &args, 0, length, (void **) &resp);
46117c478bd9Sstevel@tonic-gate 	if (ret != IBMF_SUCCESS) {
46127c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibdm", "\tget_node_records:"
46137c478bd9Sstevel@tonic-gate 		    " SA Retrieve Failed: %d", ret);
46147c478bd9Sstevel@tonic-gate 		return (NULL);
46157c478bd9Sstevel@tonic-gate 	}
46167c478bd9Sstevel@tonic-gate 	if ((resp == NULL) || (*length == 0)) {
46177c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibdm", "\tget_node_records: No records");
46187c478bd9Sstevel@tonic-gate 		return (NULL);
46197c478bd9Sstevel@tonic-gate 	}
46207c478bd9Sstevel@tonic-gate 
46217c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tget_node_records: NodeGuid %llx "
46227c478bd9Sstevel@tonic-gate 	    "PortGUID %llx", resp->NodeInfo.NodeGUID, resp->NodeInfo.PortGUID);
46237c478bd9Sstevel@tonic-gate 
46247c478bd9Sstevel@tonic-gate 	return (resp);
46257c478bd9Sstevel@tonic-gate }
46267c478bd9Sstevel@tonic-gate 
46277c478bd9Sstevel@tonic-gate 
46287c478bd9Sstevel@tonic-gate /*
46297c478bd9Sstevel@tonic-gate  * ibdm_get_portinfo()
46307c478bd9Sstevel@tonic-gate  *	Sends a SA query to get the PortInfo record
46317c478bd9Sstevel@tonic-gate  *	Returns pointer to the sa_portinfo_record_t on success
46327c478bd9Sstevel@tonic-gate  *	and NULL on failure
46337c478bd9Sstevel@tonic-gate  */
46347c478bd9Sstevel@tonic-gate static sa_portinfo_record_t *
ibdm_get_portinfo(ibmf_saa_handle_t sa_hdl,size_t * length,ib_lid_t lid)46357c478bd9Sstevel@tonic-gate ibdm_get_portinfo(ibmf_saa_handle_t sa_hdl, size_t *length, ib_lid_t lid)
46367c478bd9Sstevel@tonic-gate {
46377c478bd9Sstevel@tonic-gate 	sa_portinfo_record_t	req, *resp = NULL;
46387c478bd9Sstevel@tonic-gate 	ibmf_saa_access_args_t	args;
46397c478bd9Sstevel@tonic-gate 	int			ret;
46407c478bd9Sstevel@tonic-gate 
46417c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tget_portinfo: Begin");
46427c478bd9Sstevel@tonic-gate 
46437c478bd9Sstevel@tonic-gate 	bzero(&req, sizeof (sa_portinfo_record_t));
46447c478bd9Sstevel@tonic-gate 	req.EndportLID	= lid;
46457c478bd9Sstevel@tonic-gate 
46467c478bd9Sstevel@tonic-gate 	args.sq_attr_id		= SA_PORTINFORECORD_ATTRID;
46477c478bd9Sstevel@tonic-gate 	args.sq_access_type	= IBMF_SAA_RETRIEVE;
46487c478bd9Sstevel@tonic-gate 	args.sq_component_mask	= SA_PORTINFO_COMPMASK_PORTLID;
46497c478bd9Sstevel@tonic-gate 	args.sq_template	= &req;
46507c478bd9Sstevel@tonic-gate 	args.sq_callback	= NULL;
46517c478bd9Sstevel@tonic-gate 	args.sq_callback_arg	= NULL;
46527c478bd9Sstevel@tonic-gate 
46537c478bd9Sstevel@tonic-gate 	ret = ibmf_sa_access(sa_hdl, &args, 0, length, (void **) &resp);
46547c478bd9Sstevel@tonic-gate 	if (ret != IBMF_SUCCESS) {
46557c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibdm", "\tget_portinfo:"
46567c478bd9Sstevel@tonic-gate 		    " SA Retrieve Failed: 0x%X", ret);
46577c478bd9Sstevel@tonic-gate 		return (NULL);
46587c478bd9Sstevel@tonic-gate 	}
46597c478bd9Sstevel@tonic-gate 	if ((*length == 0) || (resp == NULL))
46607c478bd9Sstevel@tonic-gate 		return (NULL);
46617c478bd9Sstevel@tonic-gate 
46627c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tget_portinfo: GidPrefix %llx Cap 0x%x",
46637c478bd9Sstevel@tonic-gate 	    resp->PortInfo.GidPrefix, resp->PortInfo.CapabilityMask);
46647c478bd9Sstevel@tonic-gate 	return (resp);
46657c478bd9Sstevel@tonic-gate }
46667c478bd9Sstevel@tonic-gate 
46677c478bd9Sstevel@tonic-gate 
46687c478bd9Sstevel@tonic-gate /*
46697c478bd9Sstevel@tonic-gate  * ibdm_ibnex_register_callback
46707c478bd9Sstevel@tonic-gate  *	IB nexus callback routine for HCA attach and detach notification
46717c478bd9Sstevel@tonic-gate  */
46727c478bd9Sstevel@tonic-gate void
ibdm_ibnex_register_callback(ibdm_callback_t ibnex_dm_callback)46737c478bd9Sstevel@tonic-gate ibdm_ibnex_register_callback(ibdm_callback_t ibnex_dm_callback)
46747c478bd9Sstevel@tonic-gate {
46757c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tibnex_register_callbacks");
46767c478bd9Sstevel@tonic-gate 	mutex_enter(&ibdm.ibdm_ibnex_mutex);
46777c478bd9Sstevel@tonic-gate 	ibdm.ibdm_ibnex_callback = ibnex_dm_callback;
46787c478bd9Sstevel@tonic-gate 	mutex_exit(&ibdm.ibdm_ibnex_mutex);
46797c478bd9Sstevel@tonic-gate }
46807c478bd9Sstevel@tonic-gate 
46817c478bd9Sstevel@tonic-gate 
46827c478bd9Sstevel@tonic-gate /*
46837c478bd9Sstevel@tonic-gate  * ibdm_ibnex_unregister_callbacks
46847c478bd9Sstevel@tonic-gate  */
46857c478bd9Sstevel@tonic-gate void
ibdm_ibnex_unregister_callback()46867c478bd9Sstevel@tonic-gate ibdm_ibnex_unregister_callback()
46877c478bd9Sstevel@tonic-gate {
46887c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tibnex_unregister_callbacks");
46897c478bd9Sstevel@tonic-gate 	mutex_enter(&ibdm.ibdm_ibnex_mutex);
46907c478bd9Sstevel@tonic-gate 	ibdm.ibdm_ibnex_callback = NULL;
46917c478bd9Sstevel@tonic-gate 	mutex_exit(&ibdm.ibdm_ibnex_mutex);
46927c478bd9Sstevel@tonic-gate }
46937c478bd9Sstevel@tonic-gate 
46947c478bd9Sstevel@tonic-gate /*
469500a3eaf3SRamaswamy Tummala  * ibdm_get_waittime()
46967c478bd9Sstevel@tonic-gate  *	Calculates the wait time based on the last HCA attach time
46977c478bd9Sstevel@tonic-gate  */
4698e1d3217bSJosef 'Jeff' Sipek static clock_t
ibdm_get_waittime(ib_guid_t hca_guid,int dft_wait_sec)4699e1d3217bSJosef 'Jeff' Sipek ibdm_get_waittime(ib_guid_t hca_guid, int dft_wait_sec)
47007c478bd9Sstevel@tonic-gate {
4701e1d3217bSJosef 'Jeff' Sipek 	const hrtime_t	dft_wait = dft_wait_sec * NANOSEC;
4702e1d3217bSJosef 'Jeff' Sipek 	hrtime_t	temp, wait_time = 0;
4703e1d3217bSJosef 'Jeff' Sipek 	clock_t		usecs;
4704e1d3217bSJosef 'Jeff' Sipek 	int		i;
47057c478bd9Sstevel@tonic-gate 	ibdm_hca_list_t	*hca;
47067c478bd9Sstevel@tonic-gate 
470700a3eaf3SRamaswamy Tummala 	IBTF_DPRINTF_L4("ibdm", "\tget_waittime hcaguid:%llx"
470800a3eaf3SRamaswamy Tummala 	    "\tport settling time %d", hca_guid, dft_wait);
470900a3eaf3SRamaswamy Tummala 
471000a3eaf3SRamaswamy Tummala 	ASSERT(mutex_owned(&ibdm.ibdm_hl_mutex));
47117c478bd9Sstevel@tonic-gate 
47127c478bd9Sstevel@tonic-gate 	hca = ibdm.ibdm_hca_list_head;
47137c478bd9Sstevel@tonic-gate 
4714e1d3217bSJosef 'Jeff' Sipek 	for (i = 0; i < ibdm.ibdm_hca_count; i++, hca = hca->hl_next) {
4715e1d3217bSJosef 'Jeff' Sipek 		if (hca->hl_nports == hca->hl_nports_active)
4716e1d3217bSJosef 'Jeff' Sipek 			continue;
47177c478bd9Sstevel@tonic-gate 
4718e1d3217bSJosef 'Jeff' Sipek 		if (hca_guid && (hca_guid != hca->hl_hca_guid))
4719e1d3217bSJosef 'Jeff' Sipek 			continue;
4720e1d3217bSJosef 'Jeff' Sipek 
4721e1d3217bSJosef 'Jeff' Sipek 		temp = gethrtime() - hca->hl_attach_time;
4722e1d3217bSJosef 'Jeff' Sipek 		temp = MAX(0, (dft_wait - temp));
4723e1d3217bSJosef 'Jeff' Sipek 
4724e1d3217bSJosef 'Jeff' Sipek 		if (hca_guid) {
4725e1d3217bSJosef 'Jeff' Sipek 			wait_time = temp;
4726e1d3217bSJosef 'Jeff' Sipek 			break;
47277c478bd9Sstevel@tonic-gate 		}
4728e1d3217bSJosef 'Jeff' Sipek 
4729e1d3217bSJosef 'Jeff' Sipek 		wait_time = MAX(temp, wait_time);
47307c478bd9Sstevel@tonic-gate 	}
4731e1d3217bSJosef 'Jeff' Sipek 
4732e1d3217bSJosef 'Jeff' Sipek 	/* convert to microseconds */
4733e1d3217bSJosef 'Jeff' Sipek 	usecs = MIN(wait_time, dft_wait) / (NANOSEC / MICROSEC);
4734e1d3217bSJosef 'Jeff' Sipek 
4735e1d3217bSJosef 'Jeff' Sipek 	IBTF_DPRINTF_L2("ibdm", "\tget_waittime: wait_time = %ld usecs",
4736e1d3217bSJosef 'Jeff' Sipek 	    (long)usecs);
4737e1d3217bSJosef 'Jeff' Sipek 
4738e1d3217bSJosef 'Jeff' Sipek 	return (drv_usectohz(usecs));
47397c478bd9Sstevel@tonic-gate }
47407c478bd9Sstevel@tonic-gate 
474100a3eaf3SRamaswamy Tummala void
ibdm_ibnex_port_settle_wait(ib_guid_t hca_guid,int dft_wait)474200a3eaf3SRamaswamy Tummala ibdm_ibnex_port_settle_wait(ib_guid_t hca_guid, int dft_wait)
474300a3eaf3SRamaswamy Tummala {
4744e1d3217bSJosef 'Jeff' Sipek 	clock_t wait_time;
474500a3eaf3SRamaswamy Tummala 
474600a3eaf3SRamaswamy Tummala 	mutex_enter(&ibdm.ibdm_hl_mutex);
474700a3eaf3SRamaswamy Tummala 
4748e1d3217bSJosef 'Jeff' Sipek 	while ((wait_time = ibdm_get_waittime(hca_guid, dft_wait)) > 0)
4749d3d50737SRafael Vanoni 		(void) cv_reltimedwait(&ibdm.ibdm_port_settle_cv,
4750e1d3217bSJosef 'Jeff' Sipek 		    &ibdm.ibdm_hl_mutex, wait_time, TR_CLOCK_TICK);
475100a3eaf3SRamaswamy Tummala 
475200a3eaf3SRamaswamy Tummala 	mutex_exit(&ibdm.ibdm_hl_mutex);
475300a3eaf3SRamaswamy Tummala }
475400a3eaf3SRamaswamy Tummala 
47557c478bd9Sstevel@tonic-gate 
47567c478bd9Sstevel@tonic-gate /*
47577c478bd9Sstevel@tonic-gate  * ibdm_ibnex_probe_hcaport
47587c478bd9Sstevel@tonic-gate  *	Probes the presence of HCA port (with HCA dip and port number)
47597c478bd9Sstevel@tonic-gate  *	Returns port attributes structure on SUCCESS
47607c478bd9Sstevel@tonic-gate  */
47617c478bd9Sstevel@tonic-gate ibdm_port_attr_t *
ibdm_ibnex_probe_hcaport(ib_guid_t hca_guid,uint8_t port_num)47627c478bd9Sstevel@tonic-gate ibdm_ibnex_probe_hcaport(ib_guid_t hca_guid, uint8_t port_num)
47637c478bd9Sstevel@tonic-gate {
47647c478bd9Sstevel@tonic-gate 	int			ii, jj;
47657c478bd9Sstevel@tonic-gate 	ibdm_hca_list_t		*hca_list;
47667c478bd9Sstevel@tonic-gate 	ibdm_port_attr_t	*port_attr;
47677c478bd9Sstevel@tonic-gate 
47687c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tibnex_probe_hcaport:");
47697c478bd9Sstevel@tonic-gate 
47707c478bd9Sstevel@tonic-gate 	mutex_enter(&ibdm.ibdm_hl_mutex);
47717c478bd9Sstevel@tonic-gate 	hca_list = ibdm.ibdm_hca_list_head;
47727c478bd9Sstevel@tonic-gate 	for (ii = 0; ii < ibdm.ibdm_hca_count; ii++) {
47737c478bd9Sstevel@tonic-gate 		if (hca_list->hl_hca_guid == hca_guid) {
47747c478bd9Sstevel@tonic-gate 			for (jj = 0; jj < hca_list->hl_nports; jj++) {
47757c478bd9Sstevel@tonic-gate 				if (hca_list->hl_port_attr[jj].pa_port_num ==
47767c478bd9Sstevel@tonic-gate 				    port_num) {
47777c478bd9Sstevel@tonic-gate 					break;
47787c478bd9Sstevel@tonic-gate 				}
47797c478bd9Sstevel@tonic-gate 			}
47807c478bd9Sstevel@tonic-gate 			if (jj != hca_list->hl_nports)
47817c478bd9Sstevel@tonic-gate 				break;
47827c478bd9Sstevel@tonic-gate 		}
47837c478bd9Sstevel@tonic-gate 		hca_list = hca_list->hl_next;
47847c478bd9Sstevel@tonic-gate 	}
47857c478bd9Sstevel@tonic-gate 	if (ii == ibdm.ibdm_hca_count) {
47867c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibdm", "\tibnex_probe_hcaport: not found");
47877c478bd9Sstevel@tonic-gate 		mutex_exit(&ibdm.ibdm_hl_mutex);
47887c478bd9Sstevel@tonic-gate 		return (NULL);
47897c478bd9Sstevel@tonic-gate 	}
47907c478bd9Sstevel@tonic-gate 	port_attr = (ibdm_port_attr_t *)kmem_zalloc(
47917c478bd9Sstevel@tonic-gate 	    sizeof (ibdm_port_attr_t), KM_SLEEP);
47927c478bd9Sstevel@tonic-gate 	bcopy((char *)&hca_list->hl_port_attr[jj],
47937c478bd9Sstevel@tonic-gate 	    port_attr, sizeof (ibdm_port_attr_t));
47947c478bd9Sstevel@tonic-gate 	ibdm_update_port_attr(port_attr);
47957c478bd9Sstevel@tonic-gate 
47967c478bd9Sstevel@tonic-gate 	mutex_exit(&ibdm.ibdm_hl_mutex);
47977c478bd9Sstevel@tonic-gate 	return (port_attr);
47987c478bd9Sstevel@tonic-gate }
47997c478bd9Sstevel@tonic-gate 
48007c478bd9Sstevel@tonic-gate 
48017c478bd9Sstevel@tonic-gate /*
48027c478bd9Sstevel@tonic-gate  * ibdm_ibnex_get_port_attrs
48037c478bd9Sstevel@tonic-gate  *	Scan all HCAs for a matching port_guid.
48047c478bd9Sstevel@tonic-gate  *	Returns "port attributes" structure on success.
48057c478bd9Sstevel@tonic-gate  */
48067c478bd9Sstevel@tonic-gate ibdm_port_attr_t *
ibdm_ibnex_get_port_attrs(ib_guid_t port_guid)48077c478bd9Sstevel@tonic-gate ibdm_ibnex_get_port_attrs(ib_guid_t port_guid)
48087c478bd9Sstevel@tonic-gate {
48097c478bd9Sstevel@tonic-gate 	int			ii, jj;
48107c478bd9Sstevel@tonic-gate 	ibdm_hca_list_t		*hca_list;
48117c478bd9Sstevel@tonic-gate 	ibdm_port_attr_t	*port_attr;
48127c478bd9Sstevel@tonic-gate 
48137c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tibnex_get_port_attrs:");
48147c478bd9Sstevel@tonic-gate 
48157c478bd9Sstevel@tonic-gate 	mutex_enter(&ibdm.ibdm_hl_mutex);
48167c478bd9Sstevel@tonic-gate 	hca_list = ibdm.ibdm_hca_list_head;
48177c478bd9Sstevel@tonic-gate 
48187c478bd9Sstevel@tonic-gate 	for (ii = 0; ii < ibdm.ibdm_hca_count; ii++) {
48197c478bd9Sstevel@tonic-gate 		for (jj = 0; jj < hca_list->hl_nports; jj++) {
48207c478bd9Sstevel@tonic-gate 			if (hca_list->hl_port_attr[jj].pa_port_guid ==
482153c1b7a3Seota 			    port_guid) {
48227c478bd9Sstevel@tonic-gate 				break;
48237c478bd9Sstevel@tonic-gate 			}
48247c478bd9Sstevel@tonic-gate 		}
48257c478bd9Sstevel@tonic-gate 		if (jj != hca_list->hl_nports)
48267c478bd9Sstevel@tonic-gate 			break;
48277c478bd9Sstevel@tonic-gate 		hca_list = hca_list->hl_next;
48287c478bd9Sstevel@tonic-gate 	}
48297c478bd9Sstevel@tonic-gate 
48307c478bd9Sstevel@tonic-gate 	if (ii == ibdm.ibdm_hca_count) {
48317c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibdm", "\tibnex_get_port_attrs: not found");
48327c478bd9Sstevel@tonic-gate 		mutex_exit(&ibdm.ibdm_hl_mutex);
48337c478bd9Sstevel@tonic-gate 		return (NULL);
48347c478bd9Sstevel@tonic-gate 	}
48357c478bd9Sstevel@tonic-gate 
48367c478bd9Sstevel@tonic-gate 	port_attr = (ibdm_port_attr_t *)kmem_alloc(sizeof (ibdm_port_attr_t),
48377c478bd9Sstevel@tonic-gate 	    KM_SLEEP);
48387c478bd9Sstevel@tonic-gate 	bcopy((char *)&hca_list->hl_port_attr[jj], port_attr,
48397c478bd9Sstevel@tonic-gate 	    sizeof (ibdm_port_attr_t));
48407c478bd9Sstevel@tonic-gate 	ibdm_update_port_attr(port_attr);
48417c478bd9Sstevel@tonic-gate 
48427c478bd9Sstevel@tonic-gate 	mutex_exit(&ibdm.ibdm_hl_mutex);
48437c478bd9Sstevel@tonic-gate 	return (port_attr);
48447c478bd9Sstevel@tonic-gate }
48457c478bd9Sstevel@tonic-gate 
48467c478bd9Sstevel@tonic-gate 
48477c478bd9Sstevel@tonic-gate /*
48487c478bd9Sstevel@tonic-gate  * ibdm_ibnex_free_port_attr()
48497c478bd9Sstevel@tonic-gate  */
48507c478bd9Sstevel@tonic-gate void
ibdm_ibnex_free_port_attr(ibdm_port_attr_t * port_attr)48517c478bd9Sstevel@tonic-gate ibdm_ibnex_free_port_attr(ibdm_port_attr_t *port_attr)
48527c478bd9Sstevel@tonic-gate {
48537c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tibnex_free_port_attr:");
48547c478bd9Sstevel@tonic-gate 	if (port_attr) {
48557c478bd9Sstevel@tonic-gate 		if (port_attr->pa_pkey_tbl != NULL) {
48567c478bd9Sstevel@tonic-gate 			kmem_free(port_attr->pa_pkey_tbl,
48577c478bd9Sstevel@tonic-gate 			    (port_attr->pa_npkeys * sizeof (ibdm_pkey_tbl_t)));
48587c478bd9Sstevel@tonic-gate 		}
48597c478bd9Sstevel@tonic-gate 		kmem_free(port_attr, sizeof (ibdm_port_attr_t));
48607c478bd9Sstevel@tonic-gate 	}
48617c478bd9Sstevel@tonic-gate }
48627c478bd9Sstevel@tonic-gate 
48637c478bd9Sstevel@tonic-gate 
48647c478bd9Sstevel@tonic-gate /*
48657c478bd9Sstevel@tonic-gate  * ibdm_ibnex_get_hca_list()
48667c478bd9Sstevel@tonic-gate  *	Returns portinfo for all the port for all the HCA's
48677c478bd9Sstevel@tonic-gate  */
48687c478bd9Sstevel@tonic-gate void
ibdm_ibnex_get_hca_list(ibdm_hca_list_t ** hca,int * count)48697c478bd9Sstevel@tonic-gate ibdm_ibnex_get_hca_list(ibdm_hca_list_t **hca, int *count)
48707c478bd9Sstevel@tonic-gate {
48717c478bd9Sstevel@tonic-gate 	ibdm_hca_list_t		*head = NULL, *temp, *temp1;
48727c478bd9Sstevel@tonic-gate 	int			ii;
48737c478bd9Sstevel@tonic-gate 
48747c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tibnex_get_hca_list:");
48757c478bd9Sstevel@tonic-gate 
48767c478bd9Sstevel@tonic-gate 	mutex_enter(&ibdm.ibdm_hl_mutex);
48777c478bd9Sstevel@tonic-gate 	temp = ibdm.ibdm_hca_list_head;
48787c478bd9Sstevel@tonic-gate 	for (ii = 0; ii < ibdm.ibdm_hca_count; ii++) {
48797c478bd9Sstevel@tonic-gate 		temp1 = ibdm_dup_hca_attr(temp);
48807c478bd9Sstevel@tonic-gate 		temp1->hl_next = head;
48817c478bd9Sstevel@tonic-gate 		head = temp1;
48827c478bd9Sstevel@tonic-gate 		temp = temp->hl_next;
48837c478bd9Sstevel@tonic-gate 	}
48847c478bd9Sstevel@tonic-gate 	*count = ibdm.ibdm_hca_count;
48857c478bd9Sstevel@tonic-gate 	*hca = head;
48867c478bd9Sstevel@tonic-gate 	mutex_exit(&ibdm.ibdm_hl_mutex);
48877c478bd9Sstevel@tonic-gate }
48887c478bd9Sstevel@tonic-gate 
48897c478bd9Sstevel@tonic-gate 
48907c478bd9Sstevel@tonic-gate /*
48917c478bd9Sstevel@tonic-gate  * ibdm_ibnex_get_hca_info_by_guid()
48927c478bd9Sstevel@tonic-gate  */
48937c478bd9Sstevel@tonic-gate ibdm_hca_list_t	*
ibdm_ibnex_get_hca_info_by_guid(ib_guid_t hca_guid)48947c478bd9Sstevel@tonic-gate ibdm_ibnex_get_hca_info_by_guid(ib_guid_t hca_guid)
48957c478bd9Sstevel@tonic-gate {
48967c478bd9Sstevel@tonic-gate 	ibdm_hca_list_t		*head = NULL, *hca = NULL;
48977c478bd9Sstevel@tonic-gate 
48987c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tibnex_get_hca_info_by_dip");
48997c478bd9Sstevel@tonic-gate 
49007c478bd9Sstevel@tonic-gate 	mutex_enter(&ibdm.ibdm_hl_mutex);
49017c478bd9Sstevel@tonic-gate 	head = ibdm.ibdm_hca_list_head;
49027c478bd9Sstevel@tonic-gate 	while (head) {
49037c478bd9Sstevel@tonic-gate 		if (head->hl_hca_guid == hca_guid) {
49047c478bd9Sstevel@tonic-gate 			hca = ibdm_dup_hca_attr(head);
49057c478bd9Sstevel@tonic-gate 			hca->hl_next = NULL;
49067c478bd9Sstevel@tonic-gate 			break;
49077c478bd9Sstevel@tonic-gate 		}
49087c478bd9Sstevel@tonic-gate 		head = head->hl_next;
49097c478bd9Sstevel@tonic-gate 	}
49107c478bd9Sstevel@tonic-gate 	mutex_exit(&ibdm.ibdm_hl_mutex);
49117c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tibnex_get_hca_info_by_dip %p", hca);
49127c478bd9Sstevel@tonic-gate 	return (hca);
49137c478bd9Sstevel@tonic-gate }
49147c478bd9Sstevel@tonic-gate 
49157c478bd9Sstevel@tonic-gate 
49167c478bd9Sstevel@tonic-gate /*
49177c478bd9Sstevel@tonic-gate  * ibdm_dup_hca_attr()
49187c478bd9Sstevel@tonic-gate  *	Allocate a new HCA attribute strucuture and initialize
49197c478bd9Sstevel@tonic-gate  *	hca attribute structure with the incoming HCA attributes
49207c478bd9Sstevel@tonic-gate  *	returned the allocated hca attributes.
49217c478bd9Sstevel@tonic-gate  */
49227c478bd9Sstevel@tonic-gate static ibdm_hca_list_t *
ibdm_dup_hca_attr(ibdm_hca_list_t * in_hca)49237c478bd9Sstevel@tonic-gate ibdm_dup_hca_attr(ibdm_hca_list_t *in_hca)
49247c478bd9Sstevel@tonic-gate {
49257c478bd9Sstevel@tonic-gate 	int			len;
49267c478bd9Sstevel@tonic-gate 	ibdm_hca_list_t		*out_hca;
49277c478bd9Sstevel@tonic-gate 
49287c478bd9Sstevel@tonic-gate 	len = sizeof (ibdm_hca_list_t) +
49297c478bd9Sstevel@tonic-gate 	    (in_hca->hl_nports * sizeof (ibdm_port_attr_t));
49307c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tdup_hca_attr len %d", len);
49317c478bd9Sstevel@tonic-gate 	out_hca = (ibdm_hca_list_t *)kmem_alloc(len, KM_SLEEP);
49327c478bd9Sstevel@tonic-gate 	bcopy((char *)in_hca,
493353c1b7a3Seota 	    (char *)out_hca, sizeof (ibdm_hca_list_t));
49347c478bd9Sstevel@tonic-gate 	if (in_hca->hl_nports) {
49357c478bd9Sstevel@tonic-gate 		out_hca->hl_port_attr = (ibdm_port_attr_t *)
493653c1b7a3Seota 		    ((char *)out_hca + sizeof (ibdm_hca_list_t));
49377c478bd9Sstevel@tonic-gate 		bcopy((char *)in_hca->hl_port_attr,
493853c1b7a3Seota 		    (char *)out_hca->hl_port_attr,
493953c1b7a3Seota 		    (in_hca->hl_nports * sizeof (ibdm_port_attr_t)));
49407c478bd9Sstevel@tonic-gate 		for (len = 0; len < out_hca->hl_nports; len++)
49417c478bd9Sstevel@tonic-gate 			ibdm_update_port_attr(&out_hca->hl_port_attr[len]);
49427c478bd9Sstevel@tonic-gate 	}
49437c478bd9Sstevel@tonic-gate 	return (out_hca);
49447c478bd9Sstevel@tonic-gate }
49457c478bd9Sstevel@tonic-gate 
49467c478bd9Sstevel@tonic-gate 
49477c478bd9Sstevel@tonic-gate /*
49487c478bd9Sstevel@tonic-gate  * ibdm_ibnex_free_hca_list()
49497c478bd9Sstevel@tonic-gate  *	Free one/more HCA lists
49507c478bd9Sstevel@tonic-gate  */
49517c478bd9Sstevel@tonic-gate void
ibdm_ibnex_free_hca_list(ibdm_hca_list_t * hca_list)49527c478bd9Sstevel@tonic-gate ibdm_ibnex_free_hca_list(ibdm_hca_list_t *hca_list)
49537c478bd9Sstevel@tonic-gate {
49544f1d42a6Spramodbg 	int			ii;
49554f1d42a6Spramodbg 	size_t			len;
49567c478bd9Sstevel@tonic-gate 	ibdm_hca_list_t 	*temp;
49577c478bd9Sstevel@tonic-gate 	ibdm_port_attr_t	*port;
49587c478bd9Sstevel@tonic-gate 
49597c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tibnex_free_hca_list:");
49607c478bd9Sstevel@tonic-gate 	ASSERT(hca_list);
49617c478bd9Sstevel@tonic-gate 	while (hca_list) {
49627c478bd9Sstevel@tonic-gate 		temp = hca_list;
49637c478bd9Sstevel@tonic-gate 		hca_list = hca_list->hl_next;
49647c478bd9Sstevel@tonic-gate 		for (ii = 0; ii < temp->hl_nports; ii++) {
49657c478bd9Sstevel@tonic-gate 			port = &temp->hl_port_attr[ii];
49667c478bd9Sstevel@tonic-gate 			len = (port->pa_npkeys * sizeof (ibdm_pkey_tbl_t));
49677c478bd9Sstevel@tonic-gate 			if (len != 0)
49687c478bd9Sstevel@tonic-gate 				kmem_free(port->pa_pkey_tbl, len);
49697c478bd9Sstevel@tonic-gate 		}
49707c478bd9Sstevel@tonic-gate 		len = sizeof (ibdm_hca_list_t) + (temp->hl_nports *
497153c1b7a3Seota 		    sizeof (ibdm_port_attr_t));
49727c478bd9Sstevel@tonic-gate 		kmem_free(temp, len);
49737c478bd9Sstevel@tonic-gate 	}
49747c478bd9Sstevel@tonic-gate }
49757c478bd9Sstevel@tonic-gate 
49767c478bd9Sstevel@tonic-gate 
49777c478bd9Sstevel@tonic-gate /*
49787c478bd9Sstevel@tonic-gate  * ibdm_ibnex_probe_iocguid()
49797c478bd9Sstevel@tonic-gate  *	Probes the IOC on the fabric and returns the IOC information
49807c478bd9Sstevel@tonic-gate  *	if present. Otherwise, NULL is returned
49817c478bd9Sstevel@tonic-gate  */
49827c478bd9Sstevel@tonic-gate /* ARGSUSED */
49837c478bd9Sstevel@tonic-gate ibdm_ioc_info_t *
ibdm_ibnex_probe_ioc(ib_guid_t iou,ib_guid_t ioc_guid,int reprobe_flag)49847c478bd9Sstevel@tonic-gate ibdm_ibnex_probe_ioc(ib_guid_t iou, ib_guid_t ioc_guid, int reprobe_flag)
49857c478bd9Sstevel@tonic-gate {
49867c478bd9Sstevel@tonic-gate 	int			k;
49877c478bd9Sstevel@tonic-gate 	ibdm_ioc_info_t		*ioc_info;
498818edb70cSeota 	ibdm_dp_gidinfo_t	*gid_info; /* used as index and arg */
498918edb70cSeota 	timeout_id_t		*timeout_id;
49907c478bd9Sstevel@tonic-gate 
49917c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tibnex_probe_ioc: (%llX, %llX, %d) Begin",
49927c478bd9Sstevel@tonic-gate 	    iou, ioc_guid, reprobe_flag);
4993c44ec8d2SRamaswamy Tummala 
4994c44ec8d2SRamaswamy Tummala 	if (ibdm_enumerate_iocs == 0)
4995c44ec8d2SRamaswamy Tummala 		return (NULL);
4996c44ec8d2SRamaswamy Tummala 
49977c478bd9Sstevel@tonic-gate 	/* Check whether we know this already */
499818edb70cSeota 	ioc_info = ibdm_get_ioc_info_with_gid(ioc_guid, &gid_info);
49997c478bd9Sstevel@tonic-gate 	if (ioc_info == NULL) {
50007c478bd9Sstevel@tonic-gate 		mutex_enter(&ibdm.ibdm_mutex);
50017c478bd9Sstevel@tonic-gate 		while (ibdm.ibdm_busy & IBDM_BUSY)
50027c478bd9Sstevel@tonic-gate 			cv_wait(&ibdm.ibdm_busy_cv, &ibdm.ibdm_mutex);
50037c478bd9Sstevel@tonic-gate 		ibdm.ibdm_busy |= IBDM_BUSY;
50047c478bd9Sstevel@tonic-gate 		mutex_exit(&ibdm.ibdm_mutex);
50057c478bd9Sstevel@tonic-gate 		ibdm_probe_ioc(iou, ioc_guid, 0);
50067c478bd9Sstevel@tonic-gate 		mutex_enter(&ibdm.ibdm_mutex);
50077c478bd9Sstevel@tonic-gate 		ibdm.ibdm_busy &= ~IBDM_BUSY;
50087c478bd9Sstevel@tonic-gate 		cv_broadcast(&ibdm.ibdm_busy_cv);
50097c478bd9Sstevel@tonic-gate 		mutex_exit(&ibdm.ibdm_mutex);
501018edb70cSeota 		ioc_info = ibdm_get_ioc_info_with_gid(ioc_guid, &gid_info);
50117c478bd9Sstevel@tonic-gate 	} else if (reprobe_flag) {	/* Handle Reprobe for the IOC */
501218edb70cSeota 		ASSERT(gid_info != NULL);
50137c478bd9Sstevel@tonic-gate 		/* Free the ioc_list before reprobe; and cancel any timers */
50147c478bd9Sstevel@tonic-gate 		mutex_enter(&ibdm.ibdm_mutex);
501518edb70cSeota 		mutex_enter(&gid_info->gl_mutex);
50167c478bd9Sstevel@tonic-gate 		if (ioc_info->ioc_timeout_id) {
501718edb70cSeota 			timeout_id = ioc_info->ioc_timeout_id;
501818edb70cSeota 			ioc_info->ioc_timeout_id = 0;
501918edb70cSeota 			mutex_exit(&gid_info->gl_mutex);
50207c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L5("ibdm", "\tprobe_ioc: "
502118edb70cSeota 			    "ioc_timeout_id = 0x%x", timeout_id);
502218edb70cSeota 			if (untimeout(timeout_id) == -1) {
50237c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibdm", "\tprobe_ioc: "
50247c478bd9Sstevel@tonic-gate 				    "untimeout ioc_timeout_id failed");
50257c478bd9Sstevel@tonic-gate 			}
502618edb70cSeota 			mutex_enter(&gid_info->gl_mutex);
50277c478bd9Sstevel@tonic-gate 		}
50287c478bd9Sstevel@tonic-gate 		if (ioc_info->ioc_dc_timeout_id) {
502918edb70cSeota 			timeout_id = ioc_info->ioc_dc_timeout_id;
503018edb70cSeota 			ioc_info->ioc_dc_timeout_id = 0;
503118edb70cSeota 			mutex_exit(&gid_info->gl_mutex);
50327c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L5("ibdm", "\tprobe_ioc: "
503318edb70cSeota 			    "ioc_dc_timeout_id = 0x%x", timeout_id);
503418edb70cSeota 			if (untimeout(timeout_id) == -1) {
50357c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibdm", "\tprobe_ioc: "
50367c478bd9Sstevel@tonic-gate 				    "untimeout ioc_dc_timeout_id failed");
50377c478bd9Sstevel@tonic-gate 			}
503818edb70cSeota 			mutex_enter(&gid_info->gl_mutex);
50397c478bd9Sstevel@tonic-gate 		}
50407c478bd9Sstevel@tonic-gate 		for (k = 0; k < ioc_info->ioc_profile.ioc_service_entries; k++)
50417c478bd9Sstevel@tonic-gate 			if (ioc_info->ioc_serv[k].se_timeout_id) {
504218edb70cSeota 				timeout_id = ioc_info->ioc_serv[k].
504318edb70cSeota 				    se_timeout_id;
504418edb70cSeota 				ioc_info->ioc_serv[k].se_timeout_id = 0;
504518edb70cSeota 				mutex_exit(&gid_info->gl_mutex);
50467c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L5("ibdm", "\tprobe_ioc: "
50477c478bd9Sstevel@tonic-gate 				    "ioc_info->ioc_serv[k].se_timeout_id = %x",
504818edb70cSeota 				    k, timeout_id);
504918edb70cSeota 				if (untimeout(timeout_id) == -1) {
50507c478bd9Sstevel@tonic-gate 					IBTF_DPRINTF_L2("ibdm", "\tprobe_ioc: "
50517c478bd9Sstevel@tonic-gate 					    "untimeout se_timeout_id %d "
50527c478bd9Sstevel@tonic-gate 					    "failed", k);
50537c478bd9Sstevel@tonic-gate 				}
505418edb70cSeota 				mutex_enter(&gid_info->gl_mutex);
50557c478bd9Sstevel@tonic-gate 			}
505618edb70cSeota 		mutex_exit(&gid_info->gl_mutex);
50577c478bd9Sstevel@tonic-gate 		mutex_exit(&ibdm.ibdm_mutex);
50587c478bd9Sstevel@tonic-gate 		ibdm_ibnex_free_ioc_list(ioc_info);
50597c478bd9Sstevel@tonic-gate 
50607c478bd9Sstevel@tonic-gate 		mutex_enter(&ibdm.ibdm_mutex);
50617c478bd9Sstevel@tonic-gate 		while (ibdm.ibdm_busy & IBDM_BUSY)
50627c478bd9Sstevel@tonic-gate 			cv_wait(&ibdm.ibdm_busy_cv, &ibdm.ibdm_mutex);
50637c478bd9Sstevel@tonic-gate 		ibdm.ibdm_busy |= IBDM_BUSY;
50647c478bd9Sstevel@tonic-gate 		mutex_exit(&ibdm.ibdm_mutex);
50657c478bd9Sstevel@tonic-gate 
50667c478bd9Sstevel@tonic-gate 		ibdm_probe_ioc(iou, ioc_guid, 1);
50677c478bd9Sstevel@tonic-gate 
50687c478bd9Sstevel@tonic-gate 		/*
50697c478bd9Sstevel@tonic-gate 		 * Skip if gl_reprobe_flag is set, this will be
50707c478bd9Sstevel@tonic-gate 		 * a re-inserted / new GID, for which notifications
50717c478bd9Sstevel@tonic-gate 		 * have already been send.
50727c478bd9Sstevel@tonic-gate 		 */
50737c478bd9Sstevel@tonic-gate 		for (gid_info = ibdm.ibdm_dp_gidlist_head; gid_info;
50747c478bd9Sstevel@tonic-gate 		    gid_info = gid_info->gl_next) {
50757c478bd9Sstevel@tonic-gate 			uint8_t			ii, niocs;
50767c478bd9Sstevel@tonic-gate 			ibdm_ioc_info_t		*ioc;
50777c478bd9Sstevel@tonic-gate 
50787c478bd9Sstevel@tonic-gate 			if (gid_info->gl_iou == NULL)
50797c478bd9Sstevel@tonic-gate 				continue;
50807c478bd9Sstevel@tonic-gate 
50817c478bd9Sstevel@tonic-gate 			if (gid_info->gl_reprobe_flag) {
50827c478bd9Sstevel@tonic-gate 				gid_info->gl_reprobe_flag = 0;
50837c478bd9Sstevel@tonic-gate 				continue;
50847c478bd9Sstevel@tonic-gate 			}
50857c478bd9Sstevel@tonic-gate 
50867c478bd9Sstevel@tonic-gate 			niocs = gid_info->gl_iou->iou_info.iou_num_ctrl_slots;
50877c478bd9Sstevel@tonic-gate 			for (ii = 0; ii < niocs; ii++) {
50887c478bd9Sstevel@tonic-gate 				ioc = IBDM_GIDINFO2IOCINFO(gid_info, ii);
50897c478bd9Sstevel@tonic-gate 				if (ioc->ioc_profile.ioc_guid == ioc_guid) {
50907c478bd9Sstevel@tonic-gate 					mutex_enter(&ibdm.ibdm_mutex);
50917c478bd9Sstevel@tonic-gate 					ibdm_reprobe_update_port_srv(ioc,
50927c478bd9Sstevel@tonic-gate 					    gid_info);
50937c478bd9Sstevel@tonic-gate 					mutex_exit(&ibdm.ibdm_mutex);
50947c478bd9Sstevel@tonic-gate 				}
50957c478bd9Sstevel@tonic-gate 			}
50967c478bd9Sstevel@tonic-gate 		}
50977c478bd9Sstevel@tonic-gate 		mutex_enter(&ibdm.ibdm_mutex);
50987c478bd9Sstevel@tonic-gate 		ibdm.ibdm_busy &= ~IBDM_BUSY;
50997c478bd9Sstevel@tonic-gate 		cv_broadcast(&ibdm.ibdm_busy_cv);
51007c478bd9Sstevel@tonic-gate 		mutex_exit(&ibdm.ibdm_mutex);
51017c478bd9Sstevel@tonic-gate 
510218edb70cSeota 		ioc_info = ibdm_get_ioc_info_with_gid(ioc_guid, &gid_info);
51037c478bd9Sstevel@tonic-gate 	}
51047c478bd9Sstevel@tonic-gate 	return (ioc_info);
51057c478bd9Sstevel@tonic-gate }
51067c478bd9Sstevel@tonic-gate 
51077c478bd9Sstevel@tonic-gate 
51087c478bd9Sstevel@tonic-gate /*
510918edb70cSeota  * ibdm_get_ioc_info_with_gid()
51107c478bd9Sstevel@tonic-gate  *	Returns pointer to ibdm_ioc_info_t if it finds
511118edb70cSeota  *	matching record for the ioc_guid. Otherwise NULL is returned.
511218edb70cSeota  *	The pointer to gid_info is set to the second argument in case that
511318edb70cSeota  *	the non-NULL value returns (and the second argument is not NULL).
511418edb70cSeota  *
511518edb70cSeota  * Note. use the same strings as "ibnex_get_ioc_info" in
511618edb70cSeota  *       IBTF_DPRINTF() to keep compatibility.
51177c478bd9Sstevel@tonic-gate  */
511818edb70cSeota static ibdm_ioc_info_t *
ibdm_get_ioc_info_with_gid(ib_guid_t ioc_guid,ibdm_dp_gidinfo_t ** gid_info)511918edb70cSeota ibdm_get_ioc_info_with_gid(ib_guid_t ioc_guid,
512018edb70cSeota     ibdm_dp_gidinfo_t **gid_info)
51217c478bd9Sstevel@tonic-gate {
51227c478bd9Sstevel@tonic-gate 	int			ii;
51237c478bd9Sstevel@tonic-gate 	ibdm_ioc_info_t		*ioc = NULL, *tmp = NULL;
51247c478bd9Sstevel@tonic-gate 	ibdm_dp_gidinfo_t	*gid_list;
51257c478bd9Sstevel@tonic-gate 	ib_dm_io_unitinfo_t	*iou;
51267c478bd9Sstevel@tonic-gate 
51277c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tibnex_get_ioc_info: GUID %llx", ioc_guid);
51287c478bd9Sstevel@tonic-gate 
51297c478bd9Sstevel@tonic-gate 	mutex_enter(&ibdm.ibdm_mutex);
51307c478bd9Sstevel@tonic-gate 	while (ibdm.ibdm_busy & IBDM_BUSY)
51317c478bd9Sstevel@tonic-gate 		cv_wait(&ibdm.ibdm_busy_cv, &ibdm.ibdm_mutex);
51327c478bd9Sstevel@tonic-gate 	ibdm.ibdm_busy |= IBDM_BUSY;
51337c478bd9Sstevel@tonic-gate 
513418edb70cSeota 	if (gid_info)
513518edb70cSeota 		*gid_info = NULL; /* clear the value of gid_info */
513618edb70cSeota 
51377c478bd9Sstevel@tonic-gate 	gid_list = ibdm.ibdm_dp_gidlist_head;
51387c478bd9Sstevel@tonic-gate 	while (gid_list) {
51397c478bd9Sstevel@tonic-gate 		mutex_enter(&gid_list->gl_mutex);
51407c478bd9Sstevel@tonic-gate 		if (gid_list->gl_state != IBDM_GID_PROBING_COMPLETE) {
51417c478bd9Sstevel@tonic-gate 			mutex_exit(&gid_list->gl_mutex);
51427c478bd9Sstevel@tonic-gate 			gid_list = gid_list->gl_next;
51437c478bd9Sstevel@tonic-gate 			continue;
51447c478bd9Sstevel@tonic-gate 		}
51457c478bd9Sstevel@tonic-gate 		if (gid_list->gl_iou == NULL) {
51467c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibdm",
51477c478bd9Sstevel@tonic-gate 			    "\tget_ioc_info: No IOU info");
51487c478bd9Sstevel@tonic-gate 			mutex_exit(&gid_list->gl_mutex);
51497c478bd9Sstevel@tonic-gate 			gid_list = gid_list->gl_next;
51507c478bd9Sstevel@tonic-gate 			continue;
51517c478bd9Sstevel@tonic-gate 		}
51527c478bd9Sstevel@tonic-gate 		iou = &gid_list->gl_iou->iou_info;
51537c478bd9Sstevel@tonic-gate 		for (ii = 0; ii < iou->iou_num_ctrl_slots; ii++) {
51547c478bd9Sstevel@tonic-gate 			tmp = IBDM_GIDINFO2IOCINFO(gid_list, ii);
51557c478bd9Sstevel@tonic-gate 			if ((tmp->ioc_profile.ioc_guid == ioc_guid) &&
51567c478bd9Sstevel@tonic-gate 			    (tmp->ioc_state == IBDM_IOC_STATE_PROBE_SUCCESS)) {
51577c478bd9Sstevel@tonic-gate 				ioc = ibdm_dup_ioc_info(tmp, gid_list);
515818edb70cSeota 				if (gid_info)
515918edb70cSeota 					*gid_info = gid_list; /* set this ptr */
51607c478bd9Sstevel@tonic-gate 				mutex_exit(&gid_list->gl_mutex);
51617c478bd9Sstevel@tonic-gate 				ibdm.ibdm_busy &= ~IBDM_BUSY;
51627c478bd9Sstevel@tonic-gate 				cv_broadcast(&ibdm.ibdm_busy_cv);
51637c478bd9Sstevel@tonic-gate 				mutex_exit(&ibdm.ibdm_mutex);
51647c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L4("ibdm", "\tget_ioc_info: End");
51657c478bd9Sstevel@tonic-gate 				return (ioc);
51667c478bd9Sstevel@tonic-gate 			}
51677c478bd9Sstevel@tonic-gate 		}
51687c478bd9Sstevel@tonic-gate 		if (ii == iou->iou_num_ctrl_slots)
51697c478bd9Sstevel@tonic-gate 			ioc = NULL;
51707c478bd9Sstevel@tonic-gate 
51717c478bd9Sstevel@tonic-gate 		mutex_exit(&gid_list->gl_mutex);
51727c478bd9Sstevel@tonic-gate 		gid_list = gid_list->gl_next;
51737c478bd9Sstevel@tonic-gate 	}
51747c478bd9Sstevel@tonic-gate 
51757c478bd9Sstevel@tonic-gate 	ibdm.ibdm_busy &= ~IBDM_BUSY;
51767c478bd9Sstevel@tonic-gate 	cv_broadcast(&ibdm.ibdm_busy_cv);
51777c478bd9Sstevel@tonic-gate 	mutex_exit(&ibdm.ibdm_mutex);
51787c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tget_ioc_info: failure End");
51797c478bd9Sstevel@tonic-gate 	return (ioc);
51807c478bd9Sstevel@tonic-gate }
51817c478bd9Sstevel@tonic-gate 
518218edb70cSeota /*
518318edb70cSeota  * ibdm_ibnex_get_ioc_info()
518418edb70cSeota  *	Returns pointer to ibdm_ioc_info_t if it finds
518518edb70cSeota  *	matching record for the ioc_guid, otherwise NULL
518618edb70cSeota  *	is returned
518718edb70cSeota  *
518818edb70cSeota  * Note. this is a wrapper function to ibdm_get_ioc_info_with_gid() now.
518918edb70cSeota  */
519018edb70cSeota ibdm_ioc_info_t *
ibdm_ibnex_get_ioc_info(ib_guid_t ioc_guid)519118edb70cSeota ibdm_ibnex_get_ioc_info(ib_guid_t ioc_guid)
519218edb70cSeota {
5193c44ec8d2SRamaswamy Tummala 	if (ibdm_enumerate_iocs == 0)
5194c44ec8d2SRamaswamy Tummala 		return (NULL);
5195c44ec8d2SRamaswamy Tummala 
519618edb70cSeota 	/* will not use the gid_info pointer, so the second arg is NULL */
519718edb70cSeota 	return (ibdm_get_ioc_info_with_gid(ioc_guid, NULL));
519818edb70cSeota }
51997c478bd9Sstevel@tonic-gate 
52007c478bd9Sstevel@tonic-gate /*
52017c478bd9Sstevel@tonic-gate  * ibdm_ibnex_get_ioc_count()
52027c478bd9Sstevel@tonic-gate  *	Returns number of ibdm_ioc_info_t it finds
52037c478bd9Sstevel@tonic-gate  */
52047c478bd9Sstevel@tonic-gate int
ibdm_ibnex_get_ioc_count(void)52057c478bd9Sstevel@tonic-gate ibdm_ibnex_get_ioc_count(void)
52067c478bd9Sstevel@tonic-gate {
52077c478bd9Sstevel@tonic-gate 	int			count = 0, k;
52087c478bd9Sstevel@tonic-gate 	ibdm_ioc_info_t		*ioc;
52097c478bd9Sstevel@tonic-gate 	ibdm_dp_gidinfo_t	*gid_list;
52107c478bd9Sstevel@tonic-gate 
5211c44ec8d2SRamaswamy Tummala 	if (ibdm_enumerate_iocs == 0)
5212c44ec8d2SRamaswamy Tummala 		return (0);
5213c44ec8d2SRamaswamy Tummala 
52147c478bd9Sstevel@tonic-gate 	mutex_enter(&ibdm.ibdm_mutex);
52157c478bd9Sstevel@tonic-gate 	ibdm_sweep_fabric(0);
52167c478bd9Sstevel@tonic-gate 
52177c478bd9Sstevel@tonic-gate 	while (ibdm.ibdm_busy & IBDM_BUSY)
52187c478bd9Sstevel@tonic-gate 		cv_wait(&ibdm.ibdm_busy_cv, &ibdm.ibdm_mutex);
52197c478bd9Sstevel@tonic-gate 	ibdm.ibdm_busy |= IBDM_BUSY;
52207c478bd9Sstevel@tonic-gate 
52217c478bd9Sstevel@tonic-gate 	for (gid_list = ibdm.ibdm_dp_gidlist_head; gid_list;
52227c478bd9Sstevel@tonic-gate 	    gid_list = gid_list->gl_next) {
52237c478bd9Sstevel@tonic-gate 		mutex_enter(&gid_list->gl_mutex);
52247c478bd9Sstevel@tonic-gate 		if ((gid_list->gl_state != IBDM_GID_PROBING_COMPLETE) ||
52257c478bd9Sstevel@tonic-gate 		    (gid_list->gl_iou == NULL)) {
52267c478bd9Sstevel@tonic-gate 			mutex_exit(&gid_list->gl_mutex);
52277c478bd9Sstevel@tonic-gate 			continue;
52287c478bd9Sstevel@tonic-gate 		}
52297c478bd9Sstevel@tonic-gate 		for (k = 0; k < gid_list->gl_iou->iou_info.iou_num_ctrl_slots;
52307c478bd9Sstevel@tonic-gate 		    k++) {
52317c478bd9Sstevel@tonic-gate 			ioc = IBDM_GIDINFO2IOCINFO(gid_list, k);
52327c478bd9Sstevel@tonic-gate 			if (ioc->ioc_state == IBDM_IOC_STATE_PROBE_SUCCESS)
52337c478bd9Sstevel@tonic-gate 				++count;
52347c478bd9Sstevel@tonic-gate 		}
52357c478bd9Sstevel@tonic-gate 		mutex_exit(&gid_list->gl_mutex);
52367c478bd9Sstevel@tonic-gate 	}
52377c478bd9Sstevel@tonic-gate 	ibdm.ibdm_busy &= ~IBDM_BUSY;
52387c478bd9Sstevel@tonic-gate 	cv_broadcast(&ibdm.ibdm_busy_cv);
52397c478bd9Sstevel@tonic-gate 	mutex_exit(&ibdm.ibdm_mutex);
52407c478bd9Sstevel@tonic-gate 
52417c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tget_ioc_count: count = %d", count);
52427c478bd9Sstevel@tonic-gate 	return (count);
52437c478bd9Sstevel@tonic-gate }
52447c478bd9Sstevel@tonic-gate 
52457c478bd9Sstevel@tonic-gate 
52467c478bd9Sstevel@tonic-gate /*
52477c478bd9Sstevel@tonic-gate  * ibdm_ibnex_get_ioc_list()
52487c478bd9Sstevel@tonic-gate  *	Returns information about all the IOCs present on the fabric.
52497c478bd9Sstevel@tonic-gate  *	Reprobes the IOCs and the GID list if list_flag is set to REPROBE_ALL.
52507c478bd9Sstevel@tonic-gate  *	Does not sweep fabric if DONOT_PROBE is set
52517c478bd9Sstevel@tonic-gate  */
52527c478bd9Sstevel@tonic-gate ibdm_ioc_info_t *
ibdm_ibnex_get_ioc_list(ibdm_ibnex_get_ioclist_mtd_t list_flag)52537c478bd9Sstevel@tonic-gate ibdm_ibnex_get_ioc_list(ibdm_ibnex_get_ioclist_mtd_t list_flag)
52547c478bd9Sstevel@tonic-gate {
52557c478bd9Sstevel@tonic-gate 	int			ii;
52567c478bd9Sstevel@tonic-gate 	ibdm_ioc_info_t		*ioc_list = NULL, *tmp, *ioc;
52577c478bd9Sstevel@tonic-gate 	ibdm_dp_gidinfo_t	*gid_list;
52587c478bd9Sstevel@tonic-gate 	ib_dm_io_unitinfo_t	*iou;
52597c478bd9Sstevel@tonic-gate 
52607c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tget_ioc_list: Enter");
52617c478bd9Sstevel@tonic-gate 
5262c44ec8d2SRamaswamy Tummala 	if (ibdm_enumerate_iocs == 0)
5263c44ec8d2SRamaswamy Tummala 		return (NULL);
5264c44ec8d2SRamaswamy Tummala 
52657c478bd9Sstevel@tonic-gate 	mutex_enter(&ibdm.ibdm_mutex);
52667c478bd9Sstevel@tonic-gate 	if (list_flag != IBDM_IBNEX_DONOT_PROBE)
52677c478bd9Sstevel@tonic-gate 		ibdm_sweep_fabric(list_flag == IBDM_IBNEX_REPROBE_ALL);
52687c478bd9Sstevel@tonic-gate 
52697c478bd9Sstevel@tonic-gate 	while (ibdm.ibdm_busy & IBDM_BUSY)
52707c478bd9Sstevel@tonic-gate 		cv_wait(&ibdm.ibdm_busy_cv, &ibdm.ibdm_mutex);
52717c478bd9Sstevel@tonic-gate 	ibdm.ibdm_busy |= IBDM_BUSY;
52727c478bd9Sstevel@tonic-gate 
52737c478bd9Sstevel@tonic-gate 	gid_list = ibdm.ibdm_dp_gidlist_head;
52747c478bd9Sstevel@tonic-gate 	while (gid_list) {
52757c478bd9Sstevel@tonic-gate 		mutex_enter(&gid_list->gl_mutex);
52767c478bd9Sstevel@tonic-gate 		if (gid_list->gl_state != IBDM_GID_PROBING_COMPLETE) {
52777c478bd9Sstevel@tonic-gate 			mutex_exit(&gid_list->gl_mutex);
52787c478bd9Sstevel@tonic-gate 			gid_list = gid_list->gl_next;
52797c478bd9Sstevel@tonic-gate 			continue;
52807c478bd9Sstevel@tonic-gate 		}
52817c478bd9Sstevel@tonic-gate 		if (gid_list->gl_iou == NULL) {
52827c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibdm",
52837c478bd9Sstevel@tonic-gate 			    "\tget_ioc_list: No IOU info");
52847c478bd9Sstevel@tonic-gate 			mutex_exit(&gid_list->gl_mutex);
52857c478bd9Sstevel@tonic-gate 			gid_list = gid_list->gl_next;
52867c478bd9Sstevel@tonic-gate 			continue;
52877c478bd9Sstevel@tonic-gate 		}
52887c478bd9Sstevel@tonic-gate 		iou = &gid_list->gl_iou->iou_info;
52897c478bd9Sstevel@tonic-gate 		for (ii = 0; ii < iou->iou_num_ctrl_slots; ii++) {
52907c478bd9Sstevel@tonic-gate 			ioc = IBDM_GIDINFO2IOCINFO(gid_list, ii);
52917c478bd9Sstevel@tonic-gate 			if (ioc->ioc_state == IBDM_IOC_STATE_PROBE_SUCCESS) {
52927c478bd9Sstevel@tonic-gate 				tmp = ibdm_dup_ioc_info(ioc, gid_list);
52937c478bd9Sstevel@tonic-gate 				tmp->ioc_next = ioc_list;
52947c478bd9Sstevel@tonic-gate 				ioc_list = tmp;
52957c478bd9Sstevel@tonic-gate 			}
52967c478bd9Sstevel@tonic-gate 		}
52977c478bd9Sstevel@tonic-gate 		mutex_exit(&gid_list->gl_mutex);
52987c478bd9Sstevel@tonic-gate 		gid_list = gid_list->gl_next;
52997c478bd9Sstevel@tonic-gate 	}
53007c478bd9Sstevel@tonic-gate 	ibdm.ibdm_busy &= ~IBDM_BUSY;
53017c478bd9Sstevel@tonic-gate 	cv_broadcast(&ibdm.ibdm_busy_cv);
53027c478bd9Sstevel@tonic-gate 	mutex_exit(&ibdm.ibdm_mutex);
53037c478bd9Sstevel@tonic-gate 
53047c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tget_ioc_list: End");
53057c478bd9Sstevel@tonic-gate 	return (ioc_list);
53067c478bd9Sstevel@tonic-gate }
53077c478bd9Sstevel@tonic-gate 
53087c478bd9Sstevel@tonic-gate /*
53097c478bd9Sstevel@tonic-gate  * ibdm_dup_ioc_info()
53107c478bd9Sstevel@tonic-gate  *	Duplicate the IOC information and return the IOC
53117c478bd9Sstevel@tonic-gate  *	information.
53127c478bd9Sstevel@tonic-gate  */
53137c478bd9Sstevel@tonic-gate static ibdm_ioc_info_t *
ibdm_dup_ioc_info(ibdm_ioc_info_t * in_ioc,ibdm_dp_gidinfo_t * gid_list)53147c478bd9Sstevel@tonic-gate ibdm_dup_ioc_info(ibdm_ioc_info_t *in_ioc, ibdm_dp_gidinfo_t *gid_list)
53157c478bd9Sstevel@tonic-gate {
53167c478bd9Sstevel@tonic-gate 	ibdm_ioc_info_t	*out_ioc;
53177c478bd9Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*out_ioc));
531853c1b7a3Seota 	ASSERT(MUTEX_HELD(&gid_list->gl_mutex));
53197c478bd9Sstevel@tonic-gate 
53207c478bd9Sstevel@tonic-gate 	out_ioc = kmem_alloc(sizeof (ibdm_ioc_info_t), KM_SLEEP);
53217c478bd9Sstevel@tonic-gate 	bcopy(in_ioc, out_ioc, sizeof (ibdm_ioc_info_t));
53227c478bd9Sstevel@tonic-gate 	ibdm_update_ioc_port_gidlist(out_ioc, gid_list);
53237c478bd9Sstevel@tonic-gate 	out_ioc->ioc_iou_dc_valid = gid_list->gl_iou->iou_dc_valid;
53247c478bd9Sstevel@tonic-gate 	out_ioc->ioc_iou_diagcode = gid_list->gl_iou->iou_diagcode;
53257c478bd9Sstevel@tonic-gate 
53267c478bd9Sstevel@tonic-gate 	return (out_ioc);
53277c478bd9Sstevel@tonic-gate }
53287c478bd9Sstevel@tonic-gate 
53297c478bd9Sstevel@tonic-gate 
53307c478bd9Sstevel@tonic-gate /*
53317c478bd9Sstevel@tonic-gate  * ibdm_free_ioc_list()
53327c478bd9Sstevel@tonic-gate  *	Deallocate memory for IOC list structure
53337c478bd9Sstevel@tonic-gate  */
53347c478bd9Sstevel@tonic-gate void
ibdm_ibnex_free_ioc_list(ibdm_ioc_info_t * ioc)53357c478bd9Sstevel@tonic-gate ibdm_ibnex_free_ioc_list(ibdm_ioc_info_t *ioc)
53367c478bd9Sstevel@tonic-gate {
53377c478bd9Sstevel@tonic-gate 	ibdm_ioc_info_t *temp;
53387c478bd9Sstevel@tonic-gate 
53397c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tibnex_free_ioc_list:");
53407c478bd9Sstevel@tonic-gate 	while (ioc) {
53417c478bd9Sstevel@tonic-gate 		temp = ioc;
53427c478bd9Sstevel@tonic-gate 		ioc = ioc->ioc_next;
53437c478bd9Sstevel@tonic-gate 		kmem_free(temp->ioc_gid_list,
53447c478bd9Sstevel@tonic-gate 		    (sizeof (ibdm_gid_t) * temp->ioc_nportgids));
53457c478bd9Sstevel@tonic-gate 		if (temp->ioc_hca_list)
53467c478bd9Sstevel@tonic-gate 			ibdm_ibnex_free_hca_list(temp->ioc_hca_list);
53477c478bd9Sstevel@tonic-gate 		kmem_free(temp, sizeof (ibdm_ioc_info_t));
53487c478bd9Sstevel@tonic-gate 	}
53497c478bd9Sstevel@tonic-gate }
53507c478bd9Sstevel@tonic-gate 
53517c478bd9Sstevel@tonic-gate 
53527c478bd9Sstevel@tonic-gate /*
53537c478bd9Sstevel@tonic-gate  * ibdm_ibnex_update_pkey_tbls
53547c478bd9Sstevel@tonic-gate  *	Updates the DM P_Key database.
53557c478bd9Sstevel@tonic-gate  *	NOTE: Two cases are handled here: P_Key being added or removed.
53567c478bd9Sstevel@tonic-gate  *
53577c478bd9Sstevel@tonic-gate  * Arguments		: NONE
53587c478bd9Sstevel@tonic-gate  * Return Values	: NONE
53597c478bd9Sstevel@tonic-gate  */
53607c478bd9Sstevel@tonic-gate void
ibdm_ibnex_update_pkey_tbls(void)53617c478bd9Sstevel@tonic-gate ibdm_ibnex_update_pkey_tbls(void)
53627c478bd9Sstevel@tonic-gate {
53637c478bd9Sstevel@tonic-gate 	int			h, pp, pidx;
53647c478bd9Sstevel@tonic-gate 	uint_t			nports;
53657c478bd9Sstevel@tonic-gate 	uint_t			size;
53667c478bd9Sstevel@tonic-gate 	ib_pkey_t		new_pkey;
53677c478bd9Sstevel@tonic-gate 	ib_pkey_t		*orig_pkey;
53687c478bd9Sstevel@tonic-gate 	ibdm_hca_list_t		*hca_list;
53697c478bd9Sstevel@tonic-gate 	ibdm_port_attr_t	*port;
53707c478bd9Sstevel@tonic-gate 	ibt_hca_portinfo_t	*pinfop;
53717c478bd9Sstevel@tonic-gate 
53727c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tibnex_update_pkey_tbls:");
53737c478bd9Sstevel@tonic-gate 
53747c478bd9Sstevel@tonic-gate 	mutex_enter(&ibdm.ibdm_hl_mutex);
53757c478bd9Sstevel@tonic-gate 	hca_list = ibdm.ibdm_hca_list_head;
53767c478bd9Sstevel@tonic-gate 
53777c478bd9Sstevel@tonic-gate 	for (h = 0; h < ibdm.ibdm_hca_count; h++) {
53787c478bd9Sstevel@tonic-gate 
53797c478bd9Sstevel@tonic-gate 		/* This updates P_Key Tables for all ports of this HCA */
53807c478bd9Sstevel@tonic-gate 		(void) ibt_query_hca_ports(hca_list->hl_hca_hdl, 0, &pinfop,
53817c478bd9Sstevel@tonic-gate 		    &nports, &size);
53827c478bd9Sstevel@tonic-gate 
53837c478bd9Sstevel@tonic-gate 		/* number of ports shouldn't have changed */
53847c478bd9Sstevel@tonic-gate 		ASSERT(nports == hca_list->hl_nports);
53857c478bd9Sstevel@tonic-gate 
53867c478bd9Sstevel@tonic-gate 		for (pp = 0; pp < hca_list->hl_nports; pp++) {
53877c478bd9Sstevel@tonic-gate 			port = &hca_list->hl_port_attr[pp];
53887c478bd9Sstevel@tonic-gate 
53897c478bd9Sstevel@tonic-gate 			/*
53907c478bd9Sstevel@tonic-gate 			 * First figure out the P_Keys from IBTL.
53917c478bd9Sstevel@tonic-gate 			 * Three things could have happened:
53927c478bd9Sstevel@tonic-gate 			 *	New P_Keys added
53937c478bd9Sstevel@tonic-gate 			 *	Existing P_Keys removed
53947c478bd9Sstevel@tonic-gate 			 *	Both of the above two
53957c478bd9Sstevel@tonic-gate 			 *
53967c478bd9Sstevel@tonic-gate 			 * Loop through the P_Key Indices and check if a
53977c478bd9Sstevel@tonic-gate 			 * give P_Key_Ix matches that of the one seen by
53987c478bd9Sstevel@tonic-gate 			 * IBDM. If they match no action is needed.
53997c478bd9Sstevel@tonic-gate 			 *
54007c478bd9Sstevel@tonic-gate 			 * If they don't match:
54017c478bd9Sstevel@tonic-gate 			 *	1. if orig_pkey is invalid and new_pkey is valid
54027c478bd9Sstevel@tonic-gate 			 *		---> add new_pkey to DM database
54037c478bd9Sstevel@tonic-gate 			 *	2. if orig_pkey is valid and new_pkey is invalid
54047c478bd9Sstevel@tonic-gate 			 *		---> remove orig_pkey from DM database
54057c478bd9Sstevel@tonic-gate 			 *	3. if orig_pkey and new_pkey are both valid:
54067c478bd9Sstevel@tonic-gate 			 *		---> remov orig_pkey from DM database
54077c478bd9Sstevel@tonic-gate 			 *		---> add new_pkey to DM database
54087c478bd9Sstevel@tonic-gate 			 *	4. if orig_pkey and new_pkey are both invalid:
54097c478bd9Sstevel@tonic-gate 			 *		---> do nothing. Updated DM database.
54107c478bd9Sstevel@tonic-gate 			 */
54117c478bd9Sstevel@tonic-gate 
54127c478bd9Sstevel@tonic-gate 			for (pidx = 0; pidx < port->pa_npkeys; pidx++) {
54137c478bd9Sstevel@tonic-gate 				new_pkey = pinfop[pp].p_pkey_tbl[pidx];
54147c478bd9Sstevel@tonic-gate 				orig_pkey = &port->pa_pkey_tbl[pidx].pt_pkey;
54157c478bd9Sstevel@tonic-gate 
54167c478bd9Sstevel@tonic-gate 				/* keys match - do nothing */
54177c478bd9Sstevel@tonic-gate 				if (*orig_pkey == new_pkey)
54187c478bd9Sstevel@tonic-gate 					continue;
54197c478bd9Sstevel@tonic-gate 
54207c478bd9Sstevel@tonic-gate 				if (IBDM_INVALID_PKEY(*orig_pkey) &&
54217c478bd9Sstevel@tonic-gate 				    !IBDM_INVALID_PKEY(new_pkey)) {
54227c478bd9Sstevel@tonic-gate 					/* P_Key was added */
54237c478bd9Sstevel@tonic-gate 					IBTF_DPRINTF_L5("ibdm",
54247c478bd9Sstevel@tonic-gate 					    "\tibnex_update_pkey_tbls: new "
54257c478bd9Sstevel@tonic-gate 					    "P_Key added = 0x%x", new_pkey);
54267c478bd9Sstevel@tonic-gate 					*orig_pkey = new_pkey;
54277c478bd9Sstevel@tonic-gate 					ibdm_port_attr_ibmf_init(port,
54287c478bd9Sstevel@tonic-gate 					    new_pkey, pp);
54297c478bd9Sstevel@tonic-gate 				} else if (!IBDM_INVALID_PKEY(*orig_pkey) &&
54307c478bd9Sstevel@tonic-gate 				    IBDM_INVALID_PKEY(new_pkey)) {
54317c478bd9Sstevel@tonic-gate 					/* P_Key was removed */
54327c478bd9Sstevel@tonic-gate 					IBTF_DPRINTF_L5("ibdm",
54337c478bd9Sstevel@tonic-gate 					    "\tibnex_update_pkey_tbls: P_Key "
54347c478bd9Sstevel@tonic-gate 					    "removed = 0x%x", *orig_pkey);
54357c478bd9Sstevel@tonic-gate 					*orig_pkey = new_pkey;
54367c478bd9Sstevel@tonic-gate 					(void) ibdm_port_attr_ibmf_fini(port,
54377c478bd9Sstevel@tonic-gate 					    pidx);
54387c478bd9Sstevel@tonic-gate 				} else if (!IBDM_INVALID_PKEY(*orig_pkey) &&
54397c478bd9Sstevel@tonic-gate 				    !IBDM_INVALID_PKEY(new_pkey)) {
54407c478bd9Sstevel@tonic-gate 					/* P_Key were replaced */
54417c478bd9Sstevel@tonic-gate 					IBTF_DPRINTF_L5("ibdm",
54427c478bd9Sstevel@tonic-gate 					    "\tibnex_update_pkey_tbls: P_Key "
54437c478bd9Sstevel@tonic-gate 					    "replaced 0x%x with 0x%x",
54447c478bd9Sstevel@tonic-gate 					    *orig_pkey, new_pkey);
54457c478bd9Sstevel@tonic-gate 					(void) ibdm_port_attr_ibmf_fini(port,
54467c478bd9Sstevel@tonic-gate 					    pidx);
54477c478bd9Sstevel@tonic-gate 					*orig_pkey = new_pkey;
54487c478bd9Sstevel@tonic-gate 					ibdm_port_attr_ibmf_init(port,
54497c478bd9Sstevel@tonic-gate 					    new_pkey, pp);
54507c478bd9Sstevel@tonic-gate 				} else {
54517c478bd9Sstevel@tonic-gate 					/*
54527c478bd9Sstevel@tonic-gate 					 * P_Keys are invalid
54537c478bd9Sstevel@tonic-gate 					 * set anyway to reflect if
54547c478bd9Sstevel@tonic-gate 					 * INVALID_FULL was changed to
54557c478bd9Sstevel@tonic-gate 					 * INVALID_LIMITED or vice-versa.
54567c478bd9Sstevel@tonic-gate 					 */
54577c478bd9Sstevel@tonic-gate 					*orig_pkey = new_pkey;
54587c478bd9Sstevel@tonic-gate 				} /* end of else */
54597c478bd9Sstevel@tonic-gate 
54607c478bd9Sstevel@tonic-gate 			} /* loop of p_key index */
54617c478bd9Sstevel@tonic-gate 
54627c478bd9Sstevel@tonic-gate 		} /* loop of #ports of HCA */
54637c478bd9Sstevel@tonic-gate 
54647c478bd9Sstevel@tonic-gate 		ibt_free_portinfo(pinfop, size);
54657c478bd9Sstevel@tonic-gate 		hca_list = hca_list->hl_next;
54667c478bd9Sstevel@tonic-gate 
54677c478bd9Sstevel@tonic-gate 	} /* loop for all HCAs in the system */
54687c478bd9Sstevel@tonic-gate 
54697c478bd9Sstevel@tonic-gate 	mutex_exit(&ibdm.ibdm_hl_mutex);
54707c478bd9Sstevel@tonic-gate }
54717c478bd9Sstevel@tonic-gate 
54727c478bd9Sstevel@tonic-gate 
54737c478bd9Sstevel@tonic-gate /*
54747c478bd9Sstevel@tonic-gate  * ibdm_send_ioc_profile()
54757c478bd9Sstevel@tonic-gate  *	Send IOC Controller Profile request. When the request is completed
54767c478bd9Sstevel@tonic-gate  *	IBMF calls ibdm_process_incoming_mad routine to inform about
54777c478bd9Sstevel@tonic-gate  *	the completion.
54787c478bd9Sstevel@tonic-gate  */
54797c478bd9Sstevel@tonic-gate static int
ibdm_send_ioc_profile(ibdm_dp_gidinfo_t * gid_info,uint8_t ioc_no)54807c478bd9Sstevel@tonic-gate ibdm_send_ioc_profile(ibdm_dp_gidinfo_t *gid_info, uint8_t ioc_no)
54817c478bd9Sstevel@tonic-gate {
54827c478bd9Sstevel@tonic-gate 	ibmf_msg_t		*msg;
54837c478bd9Sstevel@tonic-gate 	ib_mad_hdr_t	*hdr;
54847c478bd9Sstevel@tonic-gate 	ibdm_ioc_info_t	*ioc_info = &(gid_info->gl_iou->iou_ioc_info[ioc_no]);
54857c478bd9Sstevel@tonic-gate 	ibdm_timeout_cb_args_t	*cb_args;
54867c478bd9Sstevel@tonic-gate 
54877c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tsend_ioc_profile: "
54887c478bd9Sstevel@tonic-gate 	    "gid info 0x%p, ioc_no = %d", gid_info, ioc_no);
54897c478bd9Sstevel@tonic-gate 
54907c478bd9Sstevel@tonic-gate 	/*
54917c478bd9Sstevel@tonic-gate 	 * Send command to get IOC profile.
54927c478bd9Sstevel@tonic-gate 	 * Allocate a IBMF packet and initialize the packet.
54937c478bd9Sstevel@tonic-gate 	 */
54947c478bd9Sstevel@tonic-gate 	if (ibmf_alloc_msg(gid_info->gl_ibmf_hdl, IBMF_ALLOC_SLEEP,
54957c478bd9Sstevel@tonic-gate 	    &msg) != IBMF_SUCCESS) {
5496dcf1eb70SSudhakar Dindukurti 		IBTF_DPRINTF_L2("ibdm", "\tsend_ioc_profile: pkt alloc fail");
54977c478bd9Sstevel@tonic-gate 		return (IBDM_FAILURE);
54987c478bd9Sstevel@tonic-gate 	}
54997c478bd9Sstevel@tonic-gate 
550018edb70cSeota 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*msg))
55017c478bd9Sstevel@tonic-gate 	ibdm_alloc_send_buffers(msg);
550218edb70cSeota 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*msg))
55037c478bd9Sstevel@tonic-gate 
55049d3d2ed0Shiremath 	mutex_enter(&gid_info->gl_mutex);
55059d3d2ed0Shiremath 	ibdm_bump_transactionID(gid_info);
55069d3d2ed0Shiremath 	mutex_exit(&gid_info->gl_mutex);
55079d3d2ed0Shiremath 
55087c478bd9Sstevel@tonic-gate 	msg->im_local_addr.ia_local_lid	= gid_info->gl_slid;
55097c478bd9Sstevel@tonic-gate 	msg->im_local_addr.ia_remote_lid	= gid_info->gl_dlid;
55107c478bd9Sstevel@tonic-gate 	if (gid_info->gl_redirected == B_TRUE) {
55117c478bd9Sstevel@tonic-gate 		if (gid_info->gl_redirect_dlid != 0) {
55127c478bd9Sstevel@tonic-gate 			msg->im_local_addr.ia_remote_lid =
55137c478bd9Sstevel@tonic-gate 			    gid_info->gl_redirect_dlid;
55147c478bd9Sstevel@tonic-gate 		}
55157c478bd9Sstevel@tonic-gate 		msg->im_local_addr.ia_remote_qno = gid_info->gl_redirect_QP;
55167c478bd9Sstevel@tonic-gate 		msg->im_local_addr.ia_p_key = gid_info->gl_redirect_pkey;
55177c478bd9Sstevel@tonic-gate 		msg->im_local_addr.ia_q_key = gid_info->gl_redirect_qkey;
551818edb70cSeota 		msg->im_local_addr.ia_service_level = gid_info->gl_redirectSL;
55197c478bd9Sstevel@tonic-gate 	} else {
55207c478bd9Sstevel@tonic-gate 		msg->im_local_addr.ia_remote_qno = 1;
55217c478bd9Sstevel@tonic-gate 		msg->im_local_addr.ia_p_key = gid_info->gl_p_key;
55227c478bd9Sstevel@tonic-gate 		msg->im_local_addr.ia_q_key = IB_GSI_QKEY;
552318edb70cSeota 		msg->im_local_addr.ia_service_level = gid_info->gl_SL;
55247c478bd9Sstevel@tonic-gate 	}
55257c478bd9Sstevel@tonic-gate 
55267c478bd9Sstevel@tonic-gate 	hdr			= IBDM_OUT_IBMFMSG_MADHDR(msg);
55277c478bd9Sstevel@tonic-gate 	hdr->BaseVersion	= MAD_CLASS_BASE_VERS_1;
55287c478bd9Sstevel@tonic-gate 	hdr->MgmtClass		= MAD_MGMT_CLASS_DEV_MGT;
55297c478bd9Sstevel@tonic-gate 	hdr->ClassVersion	= IB_DM_CLASS_VERSION_1;
55307c478bd9Sstevel@tonic-gate 	hdr->R_Method		= IB_DM_DEVMGT_METHOD_GET;
55317c478bd9Sstevel@tonic-gate 	hdr->Status		= 0;
55327c478bd9Sstevel@tonic-gate 	hdr->TransactionID	= h2b64(gid_info->gl_transactionID);
55337c478bd9Sstevel@tonic-gate 	hdr->AttributeID	= h2b16(IB_DM_ATTR_IOC_CTRL_PROFILE);
55347c478bd9Sstevel@tonic-gate 	hdr->AttributeModifier 	= h2b32(ioc_no + 1);
55357c478bd9Sstevel@tonic-gate 
55367c478bd9Sstevel@tonic-gate 	ioc_info->ioc_state	= IBDM_IOC_STATE_REPROBE_PROGRESS;
55377c478bd9Sstevel@tonic-gate 	cb_args			= &ioc_info->ioc_cb_args;
55387c478bd9Sstevel@tonic-gate 	cb_args->cb_gid_info	= gid_info;
55397c478bd9Sstevel@tonic-gate 	cb_args->cb_retry_count	= ibdm_dft_retry_cnt;
55407c478bd9Sstevel@tonic-gate 	cb_args->cb_req_type	= IBDM_REQ_TYPE_IOCINFO;
55417c478bd9Sstevel@tonic-gate 	cb_args->cb_ioc_num	= ioc_no;
55427c478bd9Sstevel@tonic-gate 
554318edb70cSeota 	mutex_enter(&gid_info->gl_mutex);
55447c478bd9Sstevel@tonic-gate 	ioc_info->ioc_timeout_id = timeout(ibdm_pkt_timeout_hdlr,
55457c478bd9Sstevel@tonic-gate 	    cb_args, IBDM_TIMEOUT_VALUE(ibdm_dft_timeout));
554618edb70cSeota 	mutex_exit(&gid_info->gl_mutex);
55477c478bd9Sstevel@tonic-gate 
55487c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L5("ibdm", "\tsend_ioc_profile:"
55497c478bd9Sstevel@tonic-gate 	    "timeout %x", ioc_info->ioc_timeout_id);
55507c478bd9Sstevel@tonic-gate 
55517c478bd9Sstevel@tonic-gate 	if (ibmf_msg_transport(gid_info->gl_ibmf_hdl, gid_info->gl_qp_hdl, msg,
55527c478bd9Sstevel@tonic-gate 	    NULL, ibdm_ibmf_send_cb, cb_args, 0) != IBMF_SUCCESS) {
55537c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibdm",
55547c478bd9Sstevel@tonic-gate 		    "\tsend_ioc_profile: msg transport failed");
55557c478bd9Sstevel@tonic-gate 		ibdm_ibmf_send_cb(gid_info->gl_ibmf_hdl, msg, cb_args);
55567c478bd9Sstevel@tonic-gate 	}
55577c478bd9Sstevel@tonic-gate 	ioc_info->ioc_state = IBDM_IOC_STATE_REPROBE_PROGRESS;
55587c478bd9Sstevel@tonic-gate 	return (IBDM_SUCCESS);
55597c478bd9Sstevel@tonic-gate }
55607c478bd9Sstevel@tonic-gate 
55617c478bd9Sstevel@tonic-gate 
55627c478bd9Sstevel@tonic-gate /*
55637c478bd9Sstevel@tonic-gate  * ibdm_port_reachable
556453c1b7a3Seota  *	Returns B_TRUE if the port GID is reachable by sending
556553c1b7a3Seota  *	a SA query to get the NODE record for this port GUID.
556653c1b7a3Seota  */
556753c1b7a3Seota static boolean_t
ibdm_port_reachable(ibmf_saa_handle_t sa_hdl,ib_guid_t guid)556853c1b7a3Seota ibdm_port_reachable(ibmf_saa_handle_t sa_hdl, ib_guid_t guid)
556953c1b7a3Seota {
557053c1b7a3Seota 	sa_node_record_t *resp;
557153c1b7a3Seota 	size_t length;
557253c1b7a3Seota 
557353c1b7a3Seota 	/*
557453c1b7a3Seota 	 * Verify if it's reachable by getting the node record.
557553c1b7a3Seota 	 */
557653c1b7a3Seota 	if (ibdm_get_node_record_by_port(sa_hdl, guid, &resp, &length) ==
557753c1b7a3Seota 	    IBDM_SUCCESS) {
557853c1b7a3Seota 		kmem_free(resp, length);
557953c1b7a3Seota 		return (B_TRUE);
558053c1b7a3Seota 	}
558153c1b7a3Seota 	return (B_FALSE);
558253c1b7a3Seota }
558353c1b7a3Seota 
558453c1b7a3Seota /*
558553c1b7a3Seota  * ibdm_get_node_record_by_port
55867c478bd9Sstevel@tonic-gate  *	Sends a SA query to get the NODE record for port GUID
558753c1b7a3Seota  *	Returns IBDM_SUCCESS if the port GID is reachable.
558853c1b7a3Seota  *
558953c1b7a3Seota  *      Note: the caller must be responsible for freeing the resource
559053c1b7a3Seota  *      by calling kmem_free(resp, length) later.
55917c478bd9Sstevel@tonic-gate  */
55927c478bd9Sstevel@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)559353c1b7a3Seota ibdm_get_node_record_by_port(ibmf_saa_handle_t sa_hdl, ib_guid_t guid,
559453c1b7a3Seota     sa_node_record_t **resp, size_t *length)
55957c478bd9Sstevel@tonic-gate {
559653c1b7a3Seota 	sa_node_record_t	req;
55977c478bd9Sstevel@tonic-gate 	ibmf_saa_access_args_t	args;
55987c478bd9Sstevel@tonic-gate 	int			ret;
559953c1b7a3Seota 	ASSERT(resp != NULL && length != NULL);
56007c478bd9Sstevel@tonic-gate 
56017c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tport_reachable: port_guid %llx",
56027c478bd9Sstevel@tonic-gate 	    guid);
56037c478bd9Sstevel@tonic-gate 
56047c478bd9Sstevel@tonic-gate 	bzero(&req, sizeof (sa_node_record_t));
56057c478bd9Sstevel@tonic-gate 	req.NodeInfo.PortGUID = guid;
56067c478bd9Sstevel@tonic-gate 
56077c478bd9Sstevel@tonic-gate 	args.sq_attr_id		= SA_NODERECORD_ATTRID;
56087c478bd9Sstevel@tonic-gate 	args.sq_access_type 	= IBMF_SAA_RETRIEVE;
56097c478bd9Sstevel@tonic-gate 	args.sq_component_mask 	= SA_NODEINFO_COMPMASK_PORTGUID;
56107c478bd9Sstevel@tonic-gate 	args.sq_template	= &req;
56117c478bd9Sstevel@tonic-gate 	args.sq_callback	= NULL;
56127c478bd9Sstevel@tonic-gate 	args.sq_callback_arg 	= NULL;
56137c478bd9Sstevel@tonic-gate 
561453c1b7a3Seota 	ret = ibmf_sa_access(sa_hdl, &args, 0, length, (void **) resp);
56157c478bd9Sstevel@tonic-gate 	if (ret != IBMF_SUCCESS) {
56167c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibdm", "\tport_reachable:"
56177c478bd9Sstevel@tonic-gate 		    " SA Retrieve Failed: %d", ret);
56187c478bd9Sstevel@tonic-gate 		return (IBDM_FAILURE);
56197c478bd9Sstevel@tonic-gate 	}
562053c1b7a3Seota 	if (*resp == NULL || *length == 0) {
56217c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibdm", "\tport_reachable: No records");
56227c478bd9Sstevel@tonic-gate 		return (IBDM_FAILURE);
56237c478bd9Sstevel@tonic-gate 	}
56248b2e16e7Seota 	/*
56258b2e16e7Seota 	 * There is one NodeRecord on each endport on a subnet.
56268b2e16e7Seota 	 */
56278b2e16e7Seota 	ASSERT(*length == sizeof (sa_node_record_t));
56287c478bd9Sstevel@tonic-gate 
56297c478bd9Sstevel@tonic-gate 	return (IBDM_SUCCESS);
56307c478bd9Sstevel@tonic-gate }
56317c478bd9Sstevel@tonic-gate 
563253c1b7a3Seota 
56337c478bd9Sstevel@tonic-gate /*
56347c478bd9Sstevel@tonic-gate  * Update the gidlist for all affected IOCs when GID becomes
56357c478bd9Sstevel@tonic-gate  * available/unavailable.
56367c478bd9Sstevel@tonic-gate  *
56377c478bd9Sstevel@tonic-gate  * Parameters :
56387c478bd9Sstevel@tonic-gate  *	gidinfo - Incoming / Outgoing GID.
56397c478bd9Sstevel@tonic-gate  *	add_flag - 1 for GID added, 0 for GID removed.
56407c478bd9Sstevel@tonic-gate  *		- (-1) : IOC gid list updated, ioc_list required.
56417c478bd9Sstevel@tonic-gate  *
56427c478bd9Sstevel@tonic-gate  * This function gets the GID for the node GUID corresponding to the
56437c478bd9Sstevel@tonic-gate  * port GID. Gets the IOU info
56447c478bd9Sstevel@tonic-gate  */
56457c478bd9Sstevel@tonic-gate static ibdm_ioc_info_t *
ibdm_update_ioc_gidlist(ibdm_dp_gidinfo_t * gid_info,int avail_flag)56467c478bd9Sstevel@tonic-gate ibdm_update_ioc_gidlist(ibdm_dp_gidinfo_t *gid_info, int avail_flag)
56477c478bd9Sstevel@tonic-gate {
56487c478bd9Sstevel@tonic-gate 	ibdm_dp_gidinfo_t	*node_gid = NULL;
56497c478bd9Sstevel@tonic-gate 	uint8_t	niocs, ii;
56507c478bd9Sstevel@tonic-gate 	ibdm_ioc_info_t	*ioc, *ioc_list = NULL, *tmp;
56517c478bd9Sstevel@tonic-gate 
56527c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tupdate_ioc_gidlist");
56537c478bd9Sstevel@tonic-gate 
56547c478bd9Sstevel@tonic-gate 	switch (avail_flag) {
56557c478bd9Sstevel@tonic-gate 		case 1 :
56567c478bd9Sstevel@tonic-gate 			node_gid = ibdm_check_dest_nodeguid(gid_info);
56577c478bd9Sstevel@tonic-gate 			break;
56587c478bd9Sstevel@tonic-gate 		case 0 :
56597c478bd9Sstevel@tonic-gate 			node_gid = ibdm_handle_gid_rm(gid_info);
56607c478bd9Sstevel@tonic-gate 			break;
56617c478bd9Sstevel@tonic-gate 		case -1 :
56627c478bd9Sstevel@tonic-gate 			node_gid = gid_info;
56637c478bd9Sstevel@tonic-gate 			break;
56647c478bd9Sstevel@tonic-gate 		default :
56657c478bd9Sstevel@tonic-gate 			break;
56667c478bd9Sstevel@tonic-gate 	}
56677c478bd9Sstevel@tonic-gate 
56687c478bd9Sstevel@tonic-gate 	if (node_gid == NULL) {
56697c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibdm", "\tupdate_ioc_gidlist: "
56707c478bd9Sstevel@tonic-gate 		    "No node GID found, port gid 0x%p, avail_flag %d",
56717c478bd9Sstevel@tonic-gate 		    gid_info, avail_flag);
56727c478bd9Sstevel@tonic-gate 		return (NULL);
56737c478bd9Sstevel@tonic-gate 	}
56747c478bd9Sstevel@tonic-gate 
56757c478bd9Sstevel@tonic-gate 	mutex_enter(&node_gid->gl_mutex);
56767c478bd9Sstevel@tonic-gate 	if ((node_gid->gl_state != IBDM_GID_PROBING_COMPLETE &&
56777c478bd9Sstevel@tonic-gate 	    node_gid->gl_state != IBDM_GID_PROBING_SKIPPED) ||
56787c478bd9Sstevel@tonic-gate 	    node_gid->gl_iou == NULL) {
56797c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibdm", "\tupdate_ioc_gidlist "
56807c478bd9Sstevel@tonic-gate 		    "gl_state %x, gl_iou %p", node_gid->gl_state,
56817c478bd9Sstevel@tonic-gate 		    node_gid->gl_iou);
56827c478bd9Sstevel@tonic-gate 		mutex_exit(&node_gid->gl_mutex);
56837c478bd9Sstevel@tonic-gate 		return (NULL);
56847c478bd9Sstevel@tonic-gate 	}
56857c478bd9Sstevel@tonic-gate 
56867c478bd9Sstevel@tonic-gate 	niocs = node_gid->gl_iou->iou_info.iou_num_ctrl_slots;
56877c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tupdate_ioc_gidlist : niocs %x",
56887c478bd9Sstevel@tonic-gate 	    niocs);
56897c478bd9Sstevel@tonic-gate 	for (ii = 0; ii < niocs; ii++) {
56907c478bd9Sstevel@tonic-gate 		ioc = IBDM_GIDINFO2IOCINFO(node_gid, ii);
56917c478bd9Sstevel@tonic-gate 		/*
56927c478bd9Sstevel@tonic-gate 		 * Skip IOCs for which probe is not complete or
56937c478bd9Sstevel@tonic-gate 		 * reprobe is progress
56947c478bd9Sstevel@tonic-gate 		 */
56957c478bd9Sstevel@tonic-gate 		if (ioc->ioc_state == IBDM_IOC_STATE_PROBE_SUCCESS) {
56967c478bd9Sstevel@tonic-gate 			tmp = ibdm_dup_ioc_info(ioc, node_gid);
56977c478bd9Sstevel@tonic-gate 			tmp->ioc_info_updated.ib_gid_prop_updated = 1;
56987c478bd9Sstevel@tonic-gate 			tmp->ioc_next = ioc_list;
56997c478bd9Sstevel@tonic-gate 			ioc_list = tmp;
57007c478bd9Sstevel@tonic-gate 		}
57017c478bd9Sstevel@tonic-gate 	}
57027c478bd9Sstevel@tonic-gate 	mutex_exit(&node_gid->gl_mutex);
57037c478bd9Sstevel@tonic-gate 
57047c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tupdate_ioc_gidlist : return %p",
57057c478bd9Sstevel@tonic-gate 	    ioc_list);
57067c478bd9Sstevel@tonic-gate 	return (ioc_list);
57077c478bd9Sstevel@tonic-gate }
57087c478bd9Sstevel@tonic-gate 
57097c478bd9Sstevel@tonic-gate /*
57107c478bd9Sstevel@tonic-gate  * ibdm_saa_event_cb :
57117c478bd9Sstevel@tonic-gate  *	Event handling which does *not* require ibdm_hl_mutex to be
57127c478bd9Sstevel@tonic-gate  *	held are executed in the same thread. This is to prevent
57137c478bd9Sstevel@tonic-gate  *	deadlocks with HCA port down notifications which hold the
57147c478bd9Sstevel@tonic-gate  *	ibdm_hl_mutex.
57157c478bd9Sstevel@tonic-gate  *
57167c478bd9Sstevel@tonic-gate  *	GID_AVAILABLE event is handled here. A taskq is spawned to
57177c478bd9Sstevel@tonic-gate  *	handle GID_UNAVAILABLE.
57187c478bd9Sstevel@tonic-gate  *
57197c478bd9Sstevel@tonic-gate  *	A new mutex ibdm_ibnex_mutex has been introduced to protect
57207c478bd9Sstevel@tonic-gate  *	ibnex_callback. This has been done to prevent any possible
57217c478bd9Sstevel@tonic-gate  *	deadlock (described above) while handling GID_AVAILABLE.
57227c478bd9Sstevel@tonic-gate  *
57237c478bd9Sstevel@tonic-gate  *	IBMF calls the event callback for a HCA port. The SA handle
57247c478bd9Sstevel@tonic-gate  *	for this port would be valid, till the callback returns.
57257c478bd9Sstevel@tonic-gate  *	IBDM calling IBDM using the above SA handle should be valid.
57267c478bd9Sstevel@tonic-gate  *
57277c478bd9Sstevel@tonic-gate  *	IBDM will additionally  check (SA handle != NULL), before
57287c478bd9Sstevel@tonic-gate  *	calling IBMF.
57297c478bd9Sstevel@tonic-gate  */
57307c478bd9Sstevel@tonic-gate /*ARGSUSED*/
57317c478bd9Sstevel@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)57327c478bd9Sstevel@tonic-gate ibdm_saa_event_cb(ibmf_saa_handle_t ibmf_saa_handle,
57337c478bd9Sstevel@tonic-gate     ibmf_saa_subnet_event_t ibmf_saa_event,
57347c478bd9Sstevel@tonic-gate     ibmf_saa_event_details_t *event_details, void *callback_arg)
57357c478bd9Sstevel@tonic-gate {
57367c478bd9Sstevel@tonic-gate 	ibdm_saa_event_arg_t *event_arg;
57377c478bd9Sstevel@tonic-gate 	ib_gid_t		sgid, dgid;
57387c478bd9Sstevel@tonic-gate 	ibdm_port_attr_t	*hca_port;
57397c478bd9Sstevel@tonic-gate 	ibdm_dp_gidinfo_t	*gid_info, *node_gid_info = NULL;
574053c1b7a3Seota 	sa_node_record_t *nrec;
574153c1b7a3Seota 	size_t length;
57427c478bd9Sstevel@tonic-gate 
57437c478bd9Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*event_arg));
57447c478bd9Sstevel@tonic-gate 
57457c478bd9Sstevel@tonic-gate 	hca_port = (ibdm_port_attr_t *)callback_arg;
57467c478bd9Sstevel@tonic-gate 
57477c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tsaa_event_cb(%x, %x, %x, %x)\n",
57487c478bd9Sstevel@tonic-gate 	    ibmf_saa_handle, ibmf_saa_event, event_details,
57497c478bd9Sstevel@tonic-gate 	    callback_arg);
5750c44ec8d2SRamaswamy Tummala 
57517c478bd9Sstevel@tonic-gate #ifdef DEBUG
57527c478bd9Sstevel@tonic-gate 	if (ibdm_ignore_saa_event)
57537c478bd9Sstevel@tonic-gate 		return;
57547c478bd9Sstevel@tonic-gate #endif
57557c478bd9Sstevel@tonic-gate 
57567c478bd9Sstevel@tonic-gate 	if (ibmf_saa_event == IBMF_SAA_EVENT_GID_AVAILABLE) {
57577c478bd9Sstevel@tonic-gate 		/*
57587c478bd9Sstevel@tonic-gate 		 * Ensure no other probe / sweep fabric is in
57597c478bd9Sstevel@tonic-gate 		 * progress.
57607c478bd9Sstevel@tonic-gate 		 */
57617c478bd9Sstevel@tonic-gate 		mutex_enter(&ibdm.ibdm_mutex);
57627c478bd9Sstevel@tonic-gate 		while (ibdm.ibdm_busy & IBDM_BUSY)
57637c478bd9Sstevel@tonic-gate 			cv_wait(&ibdm.ibdm_busy_cv, &ibdm.ibdm_mutex);
57647c478bd9Sstevel@tonic-gate 		ibdm.ibdm_busy |= IBDM_BUSY;
57657c478bd9Sstevel@tonic-gate 		mutex_exit(&ibdm.ibdm_mutex);
57667c478bd9Sstevel@tonic-gate 
57677c478bd9Sstevel@tonic-gate 		/*
57687c478bd9Sstevel@tonic-gate 		 * If we already know about this GID, return.
57697c478bd9Sstevel@tonic-gate 		 * GID_AVAILABLE may be reported for multiple HCA
57707c478bd9Sstevel@tonic-gate 		 * ports.
57717c478bd9Sstevel@tonic-gate 		 */
57727c478bd9Sstevel@tonic-gate 		if ((ibdm_check_dgid(event_details->ie_gid.gid_guid,
57737c478bd9Sstevel@tonic-gate 		    event_details->ie_gid.gid_prefix))  != NULL) {
57747c478bd9Sstevel@tonic-gate 			mutex_enter(&ibdm.ibdm_mutex);
57757c478bd9Sstevel@tonic-gate 			ibdm.ibdm_busy &= ~IBDM_BUSY;
57767c478bd9Sstevel@tonic-gate 			cv_broadcast(&ibdm.ibdm_busy_cv);
57777c478bd9Sstevel@tonic-gate 			mutex_exit(&ibdm.ibdm_mutex);
57787c478bd9Sstevel@tonic-gate 			return;
57797c478bd9Sstevel@tonic-gate 		}
57807c478bd9Sstevel@tonic-gate 
57817c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibdm", "\tGID (prefix %x, guid %llx) "
57827c478bd9Sstevel@tonic-gate 		    "Insertion notified",
57837c478bd9Sstevel@tonic-gate 		    event_details->ie_gid.gid_prefix,
57847c478bd9Sstevel@tonic-gate 		    event_details->ie_gid.gid_guid);
57857c478bd9Sstevel@tonic-gate 
57867c478bd9Sstevel@tonic-gate 		/* This is a new gid, insert it to GID list */
57877c478bd9Sstevel@tonic-gate 		sgid.gid_prefix = hca_port->pa_sn_prefix;
57887c478bd9Sstevel@tonic-gate 		sgid.gid_guid = hca_port->pa_port_guid;
57897c478bd9Sstevel@tonic-gate 		dgid.gid_prefix = event_details->ie_gid.gid_prefix;
57907c478bd9Sstevel@tonic-gate 		dgid.gid_guid = event_details->ie_gid.gid_guid;
57917c478bd9Sstevel@tonic-gate 		gid_info = ibdm_create_gid_info(hca_port, sgid, dgid);
57927c478bd9Sstevel@tonic-gate 		if (gid_info == NULL) {
57937c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibdm", "\tGID_AVAILABLE: "
57947c478bd9Sstevel@tonic-gate 			    "create_gid_info returned NULL");
57957c478bd9Sstevel@tonic-gate 			mutex_enter(&ibdm.ibdm_mutex);
57967c478bd9Sstevel@tonic-gate 			ibdm.ibdm_busy &= ~IBDM_BUSY;
57977c478bd9Sstevel@tonic-gate 			cv_broadcast(&ibdm.ibdm_busy_cv);
57987c478bd9Sstevel@tonic-gate 			mutex_exit(&ibdm.ibdm_mutex);
57997c478bd9Sstevel@tonic-gate 			return;
58007c478bd9Sstevel@tonic-gate 		}
58017c478bd9Sstevel@tonic-gate 		mutex_enter(&gid_info->gl_mutex);
58027c478bd9Sstevel@tonic-gate 		gid_info->gl_state = IBDM_GID_PROBING_SKIPPED;
58037c478bd9Sstevel@tonic-gate 		mutex_exit(&gid_info->gl_mutex);
58047c478bd9Sstevel@tonic-gate 
58057c478bd9Sstevel@tonic-gate 		/* Get the node GUID */
580653c1b7a3Seota 		if (ibdm_get_node_record_by_port(ibmf_saa_handle, dgid.gid_guid,
580753c1b7a3Seota 		    &nrec, &length) != IBDM_SUCCESS) {
58087c478bd9Sstevel@tonic-gate 			/*
58097c478bd9Sstevel@tonic-gate 			 * Set the state to PROBE_NOT_DONE for the
58107c478bd9Sstevel@tonic-gate 			 * next sweep to probe it
58117c478bd9Sstevel@tonic-gate 			 */
58127c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L2("ibdm", "\tsaa_event_taskq: "
58137c478bd9Sstevel@tonic-gate 			    "Skipping GID : port GUID not found");
58147c478bd9Sstevel@tonic-gate 			mutex_enter(&gid_info->gl_mutex);
58157c478bd9Sstevel@tonic-gate 			gid_info->gl_state = IBDM_GID_PROBE_NOT_DONE;
58167c478bd9Sstevel@tonic-gate 			mutex_exit(&gid_info->gl_mutex);
58177c478bd9Sstevel@tonic-gate 			mutex_enter(&ibdm.ibdm_mutex);
58187c478bd9Sstevel@tonic-gate 			ibdm.ibdm_busy &= ~IBDM_BUSY;
58197c478bd9Sstevel@tonic-gate 			cv_broadcast(&ibdm.ibdm_busy_cv);
58207c478bd9Sstevel@tonic-gate 			mutex_exit(&ibdm.ibdm_mutex);
58217c478bd9Sstevel@tonic-gate 			return;
58227c478bd9Sstevel@tonic-gate 		}
582353c1b7a3Seota 		gid_info->gl_nodeguid = nrec->NodeInfo.NodeGUID;
582453c1b7a3Seota 		gid_info->gl_devid = nrec->NodeInfo.DeviceID;
582553c1b7a3Seota 		kmem_free(nrec, length);
58267c478bd9Sstevel@tonic-gate 		gid_info->gl_portguid = dgid.gid_guid;
58277c478bd9Sstevel@tonic-gate 
58287c478bd9Sstevel@tonic-gate 		/*
58297c478bd9Sstevel@tonic-gate 		 * Get the gid info with the same node GUID.
58307c478bd9Sstevel@tonic-gate 		 */
58317c478bd9Sstevel@tonic-gate 		mutex_enter(&ibdm.ibdm_mutex);
58327c478bd9Sstevel@tonic-gate 		node_gid_info = ibdm.ibdm_dp_gidlist_head;
58337c478bd9Sstevel@tonic-gate 		while (node_gid_info) {
58347c478bd9Sstevel@tonic-gate 			if (node_gid_info->gl_nodeguid ==
58357c478bd9Sstevel@tonic-gate 			    gid_info->gl_nodeguid &&
58367c478bd9Sstevel@tonic-gate 			    node_gid_info->gl_iou != NULL) {
58377c478bd9Sstevel@tonic-gate 				break;
58387c478bd9Sstevel@tonic-gate 			}
58397c478bd9Sstevel@tonic-gate 			node_gid_info = node_gid_info->gl_next;
58407c478bd9Sstevel@tonic-gate 		}
58417c478bd9Sstevel@tonic-gate 		mutex_exit(&ibdm.ibdm_mutex);
58427c478bd9Sstevel@tonic-gate 
58437c478bd9Sstevel@tonic-gate 		/*
58447c478bd9Sstevel@tonic-gate 		 * Handling a new GID requires filling of gl_hca_list.
58457c478bd9Sstevel@tonic-gate 		 * This require ibdm hca_list to be parsed and hence
58467c478bd9Sstevel@tonic-gate 		 * holding the ibdm_hl_mutex. Spawning a new thread to
58477c478bd9Sstevel@tonic-gate 		 * handle this.
58487c478bd9Sstevel@tonic-gate 		 */
58497c478bd9Sstevel@tonic-gate 		if (node_gid_info == NULL) {
58507c478bd9Sstevel@tonic-gate 			if (taskq_dispatch(system_taskq,
58517c478bd9Sstevel@tonic-gate 			    ibdm_saa_handle_new_gid, (void *)gid_info,
5852*fc8ae2ecSToomas Soome 			    TQ_NOSLEEP) == TASKQID_INVALID) {
58537c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L2("ibdm", "\tsaa_event_cb: "
58547c478bd9Sstevel@tonic-gate 				    "new_gid taskq_dispatch failed");
58557c478bd9Sstevel@tonic-gate 				return;
58567c478bd9Sstevel@tonic-gate 			}
58577c478bd9Sstevel@tonic-gate 		}
58587c478bd9Sstevel@tonic-gate 
58597c478bd9Sstevel@tonic-gate 		mutex_enter(&ibdm.ibdm_mutex);
58607c478bd9Sstevel@tonic-gate 		ibdm.ibdm_busy &= ~IBDM_BUSY;
58617c478bd9Sstevel@tonic-gate 		cv_broadcast(&ibdm.ibdm_busy_cv);
58627c478bd9Sstevel@tonic-gate 		mutex_exit(&ibdm.ibdm_mutex);
58637c478bd9Sstevel@tonic-gate 		return;
58647c478bd9Sstevel@tonic-gate 	}
58657c478bd9Sstevel@tonic-gate 
58667c478bd9Sstevel@tonic-gate 	if (ibmf_saa_event != IBMF_SAA_EVENT_GID_UNAVAILABLE)
58677c478bd9Sstevel@tonic-gate 		return;
58687c478bd9Sstevel@tonic-gate 
58698e55d263SRajkumar Sivaprakasam 	/*
58708e55d263SRajkumar Sivaprakasam 	 * GID UNAVAIL EVENT: Try to locate the GID in the GID list.
58718e55d263SRajkumar Sivaprakasam 	 * If we don't find it we just return.
58728e55d263SRajkumar Sivaprakasam 	 */
58738e55d263SRajkumar Sivaprakasam 	mutex_enter(&ibdm.ibdm_mutex);
58748e55d263SRajkumar Sivaprakasam 	gid_info = ibdm.ibdm_dp_gidlist_head;
58758e55d263SRajkumar Sivaprakasam 	while (gid_info) {
58768e55d263SRajkumar Sivaprakasam 		if (gid_info->gl_portguid ==
58778e55d263SRajkumar Sivaprakasam 		    event_details->ie_gid.gid_guid) {
58788e55d263SRajkumar Sivaprakasam 			break;
58798e55d263SRajkumar Sivaprakasam 		}
58808e55d263SRajkumar Sivaprakasam 		gid_info = gid_info->gl_next;
58818e55d263SRajkumar Sivaprakasam 	}
58828e55d263SRajkumar Sivaprakasam 	mutex_exit(&ibdm.ibdm_mutex);
58838e55d263SRajkumar Sivaprakasam 	if (gid_info == NULL) {
58847c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L2("ibdm", "\tsaa_event_cb: "
58858e55d263SRajkumar Sivaprakasam 		    "GID for GUID %llX not found during GID UNAVAIL event",
58868e55d263SRajkumar Sivaprakasam 		    event_details->ie_gid.gid_guid);
58877c478bd9Sstevel@tonic-gate 		return;
58887c478bd9Sstevel@tonic-gate 	}
58898e55d263SRajkumar Sivaprakasam 
58908e55d263SRajkumar Sivaprakasam 	/*
58918e55d263SRajkumar Sivaprakasam 	 * If this GID is DM capable, we'll have to check whether this DGID
58928e55d263SRajkumar Sivaprakasam 	 * is reachable via another port.
58938e55d263SRajkumar Sivaprakasam 	 */
58948e55d263SRajkumar Sivaprakasam 	if (gid_info->gl_is_dm_capable == B_TRUE) {
58958e55d263SRajkumar Sivaprakasam 		event_arg = (ibdm_saa_event_arg_t *)kmem_alloc(
58968e55d263SRajkumar Sivaprakasam 		    sizeof (ibdm_saa_event_arg_t), KM_SLEEP);
58978e55d263SRajkumar Sivaprakasam 		event_arg->ibmf_saa_handle = ibmf_saa_handle;
58988e55d263SRajkumar Sivaprakasam 		event_arg->ibmf_saa_event = ibmf_saa_event;
58998e55d263SRajkumar Sivaprakasam 		bcopy(event_details, &event_arg->event_details,
59008e55d263SRajkumar Sivaprakasam 		    sizeof (ibmf_saa_event_details_t));
59018e55d263SRajkumar Sivaprakasam 		event_arg->callback_arg = callback_arg;
59028e55d263SRajkumar Sivaprakasam 
59038e55d263SRajkumar Sivaprakasam 		if (taskq_dispatch(system_taskq, ibdm_saa_event_taskq,
5904*fc8ae2ecSToomas Soome 		    (void *)event_arg, TQ_NOSLEEP) == TASKQID_INVALID) {
59058e55d263SRajkumar Sivaprakasam 			IBTF_DPRINTF_L2("ibdm", "\tsaa_event_cb: "
59068e55d263SRajkumar Sivaprakasam 			    "taskq_dispatch failed");
59078e55d263SRajkumar Sivaprakasam 			ibdm_free_saa_event_arg(event_arg);
59088e55d263SRajkumar Sivaprakasam 			return;
59098e55d263SRajkumar Sivaprakasam 		}
59108e55d263SRajkumar Sivaprakasam 	}
59117c478bd9Sstevel@tonic-gate }
59127c478bd9Sstevel@tonic-gate 
59137c478bd9Sstevel@tonic-gate /*
59147c478bd9Sstevel@tonic-gate  * Handle a new GID discovered by GID_AVAILABLE saa event.
59157c478bd9Sstevel@tonic-gate  */
59167c478bd9Sstevel@tonic-gate void
ibdm_saa_handle_new_gid(void * arg)59177c478bd9Sstevel@tonic-gate ibdm_saa_handle_new_gid(void *arg)
59187c478bd9Sstevel@tonic-gate {
59197c478bd9Sstevel@tonic-gate 	ibdm_dp_gidinfo_t	*gid_info;
59207c478bd9Sstevel@tonic-gate 	ibdm_hca_list_t		*hca_list = NULL;
59217c478bd9Sstevel@tonic-gate 	ibdm_port_attr_t	*port = NULL;
59227c478bd9Sstevel@tonic-gate 	ibdm_ioc_info_t		*ioc_list = NULL;
59237c478bd9Sstevel@tonic-gate 
59247c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4(ibdm_string, "\tsaa_handle_new_gid(%p)", arg);
59257c478bd9Sstevel@tonic-gate 
59267c478bd9Sstevel@tonic-gate 	gid_info = (ibdm_dp_gidinfo_t *)arg;
59277c478bd9Sstevel@tonic-gate 
59287c478bd9Sstevel@tonic-gate 	/*
59297c478bd9Sstevel@tonic-gate 	 * Ensure that no other sweep / probe has completed
59307c478bd9Sstevel@tonic-gate 	 * probing this gid.
59317c478bd9Sstevel@tonic-gate 	 */
59327c478bd9Sstevel@tonic-gate 	mutex_enter(&gid_info->gl_mutex);
59337c478bd9Sstevel@tonic-gate 	if (gid_info->gl_state != IBDM_GID_PROBE_NOT_DONE) {
59347c478bd9Sstevel@tonic-gate 		mutex_exit(&gid_info->gl_mutex);
59357c478bd9Sstevel@tonic-gate 		return;
59367c478bd9Sstevel@tonic-gate 	}
59377c478bd9Sstevel@tonic-gate 	mutex_exit(&gid_info->gl_mutex);
59387c478bd9Sstevel@tonic-gate 
59397c478bd9Sstevel@tonic-gate 	/*
59407c478bd9Sstevel@tonic-gate 	 * Parse HCAs to fill gl_hca_list
59417c478bd9Sstevel@tonic-gate 	 */
59427c478bd9Sstevel@tonic-gate 	mutex_enter(&ibdm.ibdm_hl_mutex);
59437c478bd9Sstevel@tonic-gate 	for (ibdm_get_next_port(&hca_list, &port, 1); port;
59447c478bd9Sstevel@tonic-gate 	    ibdm_get_next_port(&hca_list, &port, 1)) {
59457c478bd9Sstevel@tonic-gate 		if (ibdm_port_reachable(port->pa_sa_hdl,
594653c1b7a3Seota 		    gid_info->gl_portguid) == B_TRUE) {
59477c478bd9Sstevel@tonic-gate 			ibdm_addto_glhcalist(gid_info, hca_list);
59487c478bd9Sstevel@tonic-gate 		}
59497c478bd9Sstevel@tonic-gate 	}
59507c478bd9Sstevel@tonic-gate 	mutex_exit(&ibdm.ibdm_hl_mutex);
59517c478bd9Sstevel@tonic-gate 
59527c478bd9Sstevel@tonic-gate 	/*
59537c478bd9Sstevel@tonic-gate 	 * Ensure no other probe / sweep fabric is in
59547c478bd9Sstevel@tonic-gate 	 * progress.
59557c478bd9Sstevel@tonic-gate 	 */
59567c478bd9Sstevel@tonic-gate 	mutex_enter(&ibdm.ibdm_mutex);
59577c478bd9Sstevel@tonic-gate 	while (ibdm.ibdm_busy & IBDM_BUSY)
59587c478bd9Sstevel@tonic-gate 		cv_wait(&ibdm.ibdm_busy_cv, &ibdm.ibdm_mutex);
59597c478bd9Sstevel@tonic-gate 	ibdm.ibdm_busy |= IBDM_BUSY;
59607c478bd9Sstevel@tonic-gate 	mutex_exit(&ibdm.ibdm_mutex);
59617c478bd9Sstevel@tonic-gate 
59627c478bd9Sstevel@tonic-gate 	/*
59637c478bd9Sstevel@tonic-gate 	 * New IOU probe it, to check if new IOCs
59647c478bd9Sstevel@tonic-gate 	 */
59657c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4(ibdm_string, "\tsaa_handle_new_gid: "
59667c478bd9Sstevel@tonic-gate 	    "new GID : probing");
59677c478bd9Sstevel@tonic-gate 	mutex_enter(&ibdm.ibdm_mutex);
59687c478bd9Sstevel@tonic-gate 	ibdm.ibdm_ngid_probes_in_progress++;
59697c478bd9Sstevel@tonic-gate 	mutex_exit(&ibdm.ibdm_mutex);
59707c478bd9Sstevel@tonic-gate 	mutex_enter(&gid_info->gl_mutex);
59717c478bd9Sstevel@tonic-gate 	gid_info->gl_reprobe_flag = 0;
59727c478bd9Sstevel@tonic-gate 	gid_info->gl_state = IBDM_GID_PROBE_NOT_DONE;
59737c478bd9Sstevel@tonic-gate 	mutex_exit(&gid_info->gl_mutex);
59747c478bd9Sstevel@tonic-gate 	ibdm_probe_gid_thread((void *)gid_info);
59757c478bd9Sstevel@tonic-gate 
59767c478bd9Sstevel@tonic-gate 	mutex_enter(&ibdm.ibdm_mutex);
59777c478bd9Sstevel@tonic-gate 	ibdm_wait_probe_completion();
59787c478bd9Sstevel@tonic-gate 	mutex_exit(&ibdm.ibdm_mutex);
59797c478bd9Sstevel@tonic-gate 
59807c478bd9Sstevel@tonic-gate 	if (gid_info->gl_iou == NULL) {
59817c478bd9Sstevel@tonic-gate 		mutex_enter(&ibdm.ibdm_mutex);
59827c478bd9Sstevel@tonic-gate 		ibdm.ibdm_busy &= ~IBDM_BUSY;
59837c478bd9Sstevel@tonic-gate 		cv_broadcast(&ibdm.ibdm_busy_cv);
59847c478bd9Sstevel@tonic-gate 		mutex_exit(&ibdm.ibdm_mutex);
59857c478bd9Sstevel@tonic-gate 		return;
59867c478bd9Sstevel@tonic-gate 	}
59877c478bd9Sstevel@tonic-gate 
59887c478bd9Sstevel@tonic-gate 	/*
59897c478bd9Sstevel@tonic-gate 	 * Update GID list in all IOCs affected by this
59907c478bd9Sstevel@tonic-gate 	 */
59917c478bd9Sstevel@tonic-gate 	ioc_list = ibdm_update_ioc_gidlist(gid_info, 1);
59927c478bd9Sstevel@tonic-gate 
59937c478bd9Sstevel@tonic-gate 	/*
59947c478bd9Sstevel@tonic-gate 	 * Pass on the IOCs with updated GIDs to IBnexus
59957c478bd9Sstevel@tonic-gate 	 */
59967c478bd9Sstevel@tonic-gate 	if (ioc_list) {
59977c478bd9Sstevel@tonic-gate 		mutex_enter(&ibdm.ibdm_ibnex_mutex);
59987c478bd9Sstevel@tonic-gate 		if (ibdm.ibdm_ibnex_callback != NULL) {
59997c478bd9Sstevel@tonic-gate 			(*ibdm.ibdm_ibnex_callback)((void *)ioc_list,
60007c478bd9Sstevel@tonic-gate 			    IBDM_EVENT_IOC_PROP_UPDATE);
60017c478bd9Sstevel@tonic-gate 		}
60027c478bd9Sstevel@tonic-gate 		mutex_exit(&ibdm.ibdm_ibnex_mutex);
60037c478bd9Sstevel@tonic-gate 	}
60047c478bd9Sstevel@tonic-gate 
60057c478bd9Sstevel@tonic-gate 	mutex_enter(&ibdm.ibdm_mutex);
60067c478bd9Sstevel@tonic-gate 	ibdm.ibdm_busy &= ~IBDM_BUSY;
60077c478bd9Sstevel@tonic-gate 	cv_broadcast(&ibdm.ibdm_busy_cv);
60087c478bd9Sstevel@tonic-gate 	mutex_exit(&ibdm.ibdm_mutex);
60097c478bd9Sstevel@tonic-gate }
60107c478bd9Sstevel@tonic-gate 
60117c478bd9Sstevel@tonic-gate /*
60127c478bd9Sstevel@tonic-gate  * ibdm_saa_event_taskq :
60137c478bd9Sstevel@tonic-gate  *	GID_UNAVAILABLE Event handling requires ibdm_hl_mutex to be
60147c478bd9Sstevel@tonic-gate  *	held. The GID_UNAVAILABLE handling is done in a taskq to
60157c478bd9Sstevel@tonic-gate  *	prevent deadlocks with HCA port down notifications which hold
60167c478bd9Sstevel@tonic-gate  *	ibdm_hl_mutex.
60177c478bd9Sstevel@tonic-gate  */
60187c478bd9Sstevel@tonic-gate void
ibdm_saa_event_taskq(void * arg)60197c478bd9Sstevel@tonic-gate ibdm_saa_event_taskq(void *arg)
60207c478bd9Sstevel@tonic-gate {
60217c478bd9Sstevel@tonic-gate 	ibdm_saa_event_arg_t *event_arg;
60227c478bd9Sstevel@tonic-gate 	ibmf_saa_handle_t ibmf_saa_handle;
60237c478bd9Sstevel@tonic-gate 	ibmf_saa_subnet_event_t ibmf_saa_event;
60247c478bd9Sstevel@tonic-gate 	ibmf_saa_event_details_t *event_details;
60257c478bd9Sstevel@tonic-gate 	void *callback_arg;
60267c478bd9Sstevel@tonic-gate 
60277c478bd9Sstevel@tonic-gate 	ibdm_dp_gidinfo_t	*gid_info;
60287c478bd9Sstevel@tonic-gate 	ibdm_port_attr_t	*hca_port, *port = NULL;
60297c478bd9Sstevel@tonic-gate 	ibdm_hca_list_t		*hca_list = NULL;
60307c478bd9Sstevel@tonic-gate 	int	sa_handle_valid = 0;
60317c478bd9Sstevel@tonic-gate 	ibdm_ioc_info_t		*ioc_list = NULL;
60327c478bd9Sstevel@tonic-gate 
60337c478bd9Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*event_arg));
60347c478bd9Sstevel@tonic-gate 
60357c478bd9Sstevel@tonic-gate 	event_arg = (ibdm_saa_event_arg_t *)arg;
60367c478bd9Sstevel@tonic-gate 	ibmf_saa_handle = event_arg->ibmf_saa_handle;
60377c478bd9Sstevel@tonic-gate 	ibmf_saa_event = event_arg->ibmf_saa_event;
60387c478bd9Sstevel@tonic-gate 	event_details = &event_arg->event_details;
60397c478bd9Sstevel@tonic-gate 	callback_arg = event_arg->callback_arg;
60407c478bd9Sstevel@tonic-gate 
60417c478bd9Sstevel@tonic-gate 	ASSERT(callback_arg != NULL);
60427c478bd9Sstevel@tonic-gate 	ASSERT(ibmf_saa_event == IBMF_SAA_EVENT_GID_UNAVAILABLE);
60437c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tsaa_event_taskq(%x, %x, %x, %x)",
60447c478bd9Sstevel@tonic-gate 	    ibmf_saa_handle, ibmf_saa_event, event_details,
60457c478bd9Sstevel@tonic-gate 	    callback_arg);
60467c478bd9Sstevel@tonic-gate 
60477c478bd9Sstevel@tonic-gate 	hca_port = (ibdm_port_attr_t *)callback_arg;
60487c478bd9Sstevel@tonic-gate 
60497c478bd9Sstevel@tonic-gate 	/* Check if the port_attr is still valid */
60507c478bd9Sstevel@tonic-gate 	mutex_enter(&ibdm.ibdm_hl_mutex);
60517c478bd9Sstevel@tonic-gate 	for (ibdm_get_next_port(&hca_list, &port, 0); port;
60527c478bd9Sstevel@tonic-gate 	    ibdm_get_next_port(&hca_list, &port, 0)) {
60537c478bd9Sstevel@tonic-gate 		if (port == hca_port && port->pa_port_guid ==
60547c478bd9Sstevel@tonic-gate 		    hca_port->pa_port_guid) {
60557c478bd9Sstevel@tonic-gate 			if (ibmf_saa_handle == hca_port->pa_sa_hdl)
60567c478bd9Sstevel@tonic-gate 				sa_handle_valid = 1;
60577c478bd9Sstevel@tonic-gate 			break;
60587c478bd9Sstevel@tonic-gate 		}
60597c478bd9Sstevel@tonic-gate 	}
60607c478bd9Sstevel@tonic-gate 	mutex_exit(&ibdm.ibdm_hl_mutex);
60617c478bd9Sstevel@tonic-gate 	if (sa_handle_valid == 0) {
60627c478bd9Sstevel@tonic-gate 		ibdm_free_saa_event_arg(event_arg);
60637c478bd9Sstevel@tonic-gate 		return;
60647c478bd9Sstevel@tonic-gate 	}
60657c478bd9Sstevel@tonic-gate 
60667c478bd9Sstevel@tonic-gate 	if (hca_port && (hca_port->pa_sa_hdl == NULL ||
60677c478bd9Sstevel@tonic-gate 	    ibmf_saa_handle != hca_port->pa_sa_hdl)) {
60687c478bd9Sstevel@tonic-gate 		ibdm_free_saa_event_arg(event_arg);
60697c478bd9Sstevel@tonic-gate 		return;
60707c478bd9Sstevel@tonic-gate 	}
60717c478bd9Sstevel@tonic-gate 	hca_list = NULL;
60727c478bd9Sstevel@tonic-gate 	port = NULL;
60737c478bd9Sstevel@tonic-gate 
60747c478bd9Sstevel@tonic-gate 	/*
60757c478bd9Sstevel@tonic-gate 	 * Check if the GID is visible to other HCA ports.
60767c478bd9Sstevel@tonic-gate 	 * Return if so.
60777c478bd9Sstevel@tonic-gate 	 */
60787c478bd9Sstevel@tonic-gate 	mutex_enter(&ibdm.ibdm_hl_mutex);
60797c478bd9Sstevel@tonic-gate 	for (ibdm_get_next_port(&hca_list, &port, 1); port;
60807c478bd9Sstevel@tonic-gate 	    ibdm_get_next_port(&hca_list, &port, 1)) {
60817c478bd9Sstevel@tonic-gate 		if (ibdm_port_reachable(port->pa_sa_hdl,
608253c1b7a3Seota 		    event_details->ie_gid.gid_guid) == B_TRUE) {
60837c478bd9Sstevel@tonic-gate 			mutex_exit(&ibdm.ibdm_hl_mutex);
60847c478bd9Sstevel@tonic-gate 			ibdm_free_saa_event_arg(event_arg);
60857c478bd9Sstevel@tonic-gate 			return;
60867c478bd9Sstevel@tonic-gate 		}
60877c478bd9Sstevel@tonic-gate 	}
60887c478bd9Sstevel@tonic-gate 	mutex_exit(&ibdm.ibdm_hl_mutex);
60897c478bd9Sstevel@tonic-gate 
60907c478bd9Sstevel@tonic-gate 	/*
60917c478bd9Sstevel@tonic-gate 	 * Ensure no other probe / sweep fabric is in
60927c478bd9Sstevel@tonic-gate 	 * progress.
60937c478bd9Sstevel@tonic-gate 	 */
60947c478bd9Sstevel@tonic-gate 	mutex_enter(&ibdm.ibdm_mutex);
60957c478bd9Sstevel@tonic-gate 	while (ibdm.ibdm_busy & IBDM_BUSY)
60967c478bd9Sstevel@tonic-gate 		cv_wait(&ibdm.ibdm_busy_cv, &ibdm.ibdm_mutex);
60977c478bd9Sstevel@tonic-gate 	ibdm.ibdm_busy |= IBDM_BUSY;
60987c478bd9Sstevel@tonic-gate 	mutex_exit(&ibdm.ibdm_mutex);
60997c478bd9Sstevel@tonic-gate 
61007c478bd9Sstevel@tonic-gate 	/*
61017c478bd9Sstevel@tonic-gate 	 * If this GID is no longer in GID list, return
61027c478bd9Sstevel@tonic-gate 	 * GID_UNAVAILABLE may be reported for multiple HCA
61037c478bd9Sstevel@tonic-gate 	 * ports.
61047c478bd9Sstevel@tonic-gate 	 */
61057c478bd9Sstevel@tonic-gate 	mutex_enter(&ibdm.ibdm_mutex);
61067c478bd9Sstevel@tonic-gate 	gid_info = ibdm.ibdm_dp_gidlist_head;
61077c478bd9Sstevel@tonic-gate 	while (gid_info) {
61087c478bd9Sstevel@tonic-gate 		if (gid_info->gl_portguid ==
61097c478bd9Sstevel@tonic-gate 		    event_details->ie_gid.gid_guid) {
61107c478bd9Sstevel@tonic-gate 			break;
61117c478bd9Sstevel@tonic-gate 		}
61127c478bd9Sstevel@tonic-gate 		gid_info = gid_info->gl_next;
61137c478bd9Sstevel@tonic-gate 	}
61147c478bd9Sstevel@tonic-gate 	mutex_exit(&ibdm.ibdm_mutex);
61157c478bd9Sstevel@tonic-gate 	if (gid_info == NULL) {
61167c478bd9Sstevel@tonic-gate 		mutex_enter(&ibdm.ibdm_mutex);
61177c478bd9Sstevel@tonic-gate 		ibdm.ibdm_busy &= ~IBDM_BUSY;
61187c478bd9Sstevel@tonic-gate 		cv_broadcast(&ibdm.ibdm_busy_cv);
61197c478bd9Sstevel@tonic-gate 		mutex_exit(&ibdm.ibdm_mutex);
61207c478bd9Sstevel@tonic-gate 		ibdm_free_saa_event_arg(event_arg);
61217c478bd9Sstevel@tonic-gate 		return;
61227c478bd9Sstevel@tonic-gate 	}
61237c478bd9Sstevel@tonic-gate 
61247c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tGID (prefix %x, guid %llx) "
61257c478bd9Sstevel@tonic-gate 	    "Unavailable notification",
61267c478bd9Sstevel@tonic-gate 	    event_details->ie_gid.gid_prefix,
61277c478bd9Sstevel@tonic-gate 	    event_details->ie_gid.gid_guid);
61287c478bd9Sstevel@tonic-gate 
61297c478bd9Sstevel@tonic-gate 	/*
61307c478bd9Sstevel@tonic-gate 	 * Update GID list in all IOCs affected by this
61317c478bd9Sstevel@tonic-gate 	 */
61327c478bd9Sstevel@tonic-gate 	if (gid_info->gl_state == IBDM_GID_PROBING_SKIPPED ||
61337c478bd9Sstevel@tonic-gate 	    gid_info->gl_state == IBDM_GID_PROBING_COMPLETE)
61347c478bd9Sstevel@tonic-gate 		ioc_list = ibdm_update_ioc_gidlist(gid_info, 0);
61357c478bd9Sstevel@tonic-gate 
61367c478bd9Sstevel@tonic-gate 	/*
61377c478bd9Sstevel@tonic-gate 	 * Remove GID from the global GID list
61387c478bd9Sstevel@tonic-gate 	 * Handle the case where all port GIDs for an
61397c478bd9Sstevel@tonic-gate 	 * IOU have been hot-removed. Check both gid_info
61407c478bd9Sstevel@tonic-gate 	 * & ioc_info for checking ngids.
61417c478bd9Sstevel@tonic-gate 	 */
61427c478bd9Sstevel@tonic-gate 	mutex_enter(&ibdm.ibdm_mutex);
61437c478bd9Sstevel@tonic-gate 	if (gid_info->gl_iou != NULL && gid_info->gl_ngids == 0) {
61447c478bd9Sstevel@tonic-gate 		mutex_enter(&gid_info->gl_mutex);
6145add2b70bSpramodbg 		(void) ibdm_free_iou_info(gid_info, &gid_info->gl_iou);
61467c478bd9Sstevel@tonic-gate 		mutex_exit(&gid_info->gl_mutex);
61477c478bd9Sstevel@tonic-gate 	}
61487c478bd9Sstevel@tonic-gate 	if (gid_info->gl_prev != NULL)
61497c478bd9Sstevel@tonic-gate 		gid_info->gl_prev->gl_next = gid_info->gl_next;
61507c478bd9Sstevel@tonic-gate 	if (gid_info->gl_next != NULL)
61517c478bd9Sstevel@tonic-gate 		gid_info->gl_next->gl_prev = gid_info->gl_prev;
61527c478bd9Sstevel@tonic-gate 
61537c478bd9Sstevel@tonic-gate 	if (gid_info == ibdm.ibdm_dp_gidlist_head)
61547c478bd9Sstevel@tonic-gate 		ibdm.ibdm_dp_gidlist_head = gid_info->gl_next;
61557c478bd9Sstevel@tonic-gate 	if (gid_info == ibdm.ibdm_dp_gidlist_tail)
61567c478bd9Sstevel@tonic-gate 		ibdm.ibdm_dp_gidlist_tail = gid_info->gl_prev;
61577c478bd9Sstevel@tonic-gate 	ibdm.ibdm_ngids--;
61587c478bd9Sstevel@tonic-gate 
61597c478bd9Sstevel@tonic-gate 	ibdm.ibdm_busy &= ~IBDM_BUSY;
61607c478bd9Sstevel@tonic-gate 	cv_broadcast(&ibdm.ibdm_busy_cv);
61617c478bd9Sstevel@tonic-gate 	mutex_exit(&ibdm.ibdm_mutex);
61627c478bd9Sstevel@tonic-gate 
616353c1b7a3Seota 	/* free the hca_list on this gid_info */
616453c1b7a3Seota 	ibdm_delete_glhca_list(gid_info);
616553c1b7a3Seota 
61667c478bd9Sstevel@tonic-gate 	mutex_destroy(&gid_info->gl_mutex);
61677c478bd9Sstevel@tonic-gate 	kmem_free(gid_info, sizeof (ibdm_dp_gidinfo_t));
61687c478bd9Sstevel@tonic-gate 
61697c478bd9Sstevel@tonic-gate 	/*
61707c478bd9Sstevel@tonic-gate 	 * Pass on the IOCs with updated GIDs to IBnexus
61717c478bd9Sstevel@tonic-gate 	 */
61727c478bd9Sstevel@tonic-gate 	if (ioc_list) {
61737c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibdm", "\tGID_UNAVAILABLE "
61747c478bd9Sstevel@tonic-gate 		    "IOC_PROP_UPDATE for %p\n", ioc_list);
61757c478bd9Sstevel@tonic-gate 		mutex_enter(&ibdm.ibdm_ibnex_mutex);
61767c478bd9Sstevel@tonic-gate 		if (ibdm.ibdm_ibnex_callback != NULL) {
61777c478bd9Sstevel@tonic-gate 			(*ibdm.ibdm_ibnex_callback)((void *)
617853c1b7a3Seota 			    ioc_list, IBDM_EVENT_IOC_PROP_UPDATE);
61797c478bd9Sstevel@tonic-gate 		}
61807c478bd9Sstevel@tonic-gate 		mutex_exit(&ibdm.ibdm_ibnex_mutex);
61817c478bd9Sstevel@tonic-gate 	}
61827c478bd9Sstevel@tonic-gate 
61837c478bd9Sstevel@tonic-gate 	ibdm_free_saa_event_arg(event_arg);
61847c478bd9Sstevel@tonic-gate }
61857c478bd9Sstevel@tonic-gate 
61867c478bd9Sstevel@tonic-gate 
61877c478bd9Sstevel@tonic-gate static int
ibdm_cmp_gid_list(ibdm_gid_t * new,ibdm_gid_t * prev)61887c478bd9Sstevel@tonic-gate ibdm_cmp_gid_list(ibdm_gid_t *new, ibdm_gid_t *prev)
61897c478bd9Sstevel@tonic-gate {
61907c478bd9Sstevel@tonic-gate 	ibdm_gid_t		*scan_new, *scan_prev;
61917c478bd9Sstevel@tonic-gate 	int	cmp_failed = 0;
61927c478bd9Sstevel@tonic-gate 
61937c478bd9Sstevel@tonic-gate 	ASSERT(new != NULL);
61947c478bd9Sstevel@tonic-gate 	ASSERT(prev != NULL);
61957c478bd9Sstevel@tonic-gate 
61967c478bd9Sstevel@tonic-gate 	/*
61977c478bd9Sstevel@tonic-gate 	 * Search for each new gid anywhere in the prev GID list.
61987c478bd9Sstevel@tonic-gate 	 * Note that the gid list could have been re-ordered.
61997c478bd9Sstevel@tonic-gate 	 */
62007c478bd9Sstevel@tonic-gate 	for (scan_new = new; scan_new; scan_new = scan_new->gid_next) {
62017c478bd9Sstevel@tonic-gate 		for (scan_prev = prev, cmp_failed = 1; scan_prev;
62027c478bd9Sstevel@tonic-gate 		    scan_prev = scan_prev->gid_next) {
62037c478bd9Sstevel@tonic-gate 			if (scan_prev->gid_dgid_hi == scan_new->gid_dgid_hi &&
62047c478bd9Sstevel@tonic-gate 			    scan_prev->gid_dgid_lo == scan_new->gid_dgid_lo) {
62057c478bd9Sstevel@tonic-gate 				cmp_failed = 0;
62067c478bd9Sstevel@tonic-gate 				break;
62077c478bd9Sstevel@tonic-gate 			}
62087c478bd9Sstevel@tonic-gate 		}
62097c478bd9Sstevel@tonic-gate 
62107c478bd9Sstevel@tonic-gate 		if (cmp_failed)
62117c478bd9Sstevel@tonic-gate 			return (1);
62127c478bd9Sstevel@tonic-gate 	}
62137c478bd9Sstevel@tonic-gate 	return (0);
62147c478bd9Sstevel@tonic-gate }
62157c478bd9Sstevel@tonic-gate 
62167c478bd9Sstevel@tonic-gate /*
62177c478bd9Sstevel@tonic-gate  * This is always called in a single thread
62187c478bd9Sstevel@tonic-gate  * This function updates the gid_list and serv_list of IOC
62197c478bd9Sstevel@tonic-gate  * The current gid_list is in ioc_info_t(contains only port
62207c478bd9Sstevel@tonic-gate  * guids for which probe is done) & gidinfo_t(other port gids)
62217c478bd9Sstevel@tonic-gate  * The gids in both locations are used for comparision.
62227c478bd9Sstevel@tonic-gate  */
62237c478bd9Sstevel@tonic-gate static void
ibdm_reprobe_update_port_srv(ibdm_ioc_info_t * ioc,ibdm_dp_gidinfo_t * gidinfo)62247c478bd9Sstevel@tonic-gate ibdm_reprobe_update_port_srv(ibdm_ioc_info_t *ioc, ibdm_dp_gidinfo_t *gidinfo)
62257c478bd9Sstevel@tonic-gate {
62267c478bd9Sstevel@tonic-gate 	ibdm_gid_t		*cur_gid_list;
62277c478bd9Sstevel@tonic-gate 	uint_t			cur_nportgids;
62287c478bd9Sstevel@tonic-gate 
62297c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ibdm.ibdm_mutex));
62307c478bd9Sstevel@tonic-gate 
62317c478bd9Sstevel@tonic-gate 	ioc->ioc_info_updated.ib_prop_updated = 0;
62327c478bd9Sstevel@tonic-gate 
62337c478bd9Sstevel@tonic-gate 
62347c478bd9Sstevel@tonic-gate 	/* Current GID list in gid_info only */
62357c478bd9Sstevel@tonic-gate 	cur_gid_list = gidinfo->gl_gid;
62367c478bd9Sstevel@tonic-gate 	cur_nportgids = gidinfo->gl_ngids;
62377c478bd9Sstevel@tonic-gate 
6238add2b70bSpramodbg 	if (ioc->ioc_prev_serv_cnt !=
6239add2b70bSpramodbg 	    ioc->ioc_profile.ioc_service_entries ||
6240add2b70bSpramodbg 	    ibdm_serv_cmp(&ioc->ioc_serv[0], &ioc->ioc_prev_serv[0],
6241add2b70bSpramodbg 	    ioc->ioc_prev_serv_cnt))
62427c478bd9Sstevel@tonic-gate 		ioc->ioc_info_updated.ib_srv_prop_updated = 1;
62437c478bd9Sstevel@tonic-gate 
62447c478bd9Sstevel@tonic-gate 	if (ioc->ioc_prev_nportgids != cur_nportgids ||
62457c478bd9Sstevel@tonic-gate 	    ioc->ioc_prev_gid_list == NULL || cur_gid_list == NULL) {
62467c478bd9Sstevel@tonic-gate 		ioc->ioc_info_updated.ib_gid_prop_updated = 1;
62477c478bd9Sstevel@tonic-gate 	} else if (ibdm_cmp_gid_list(ioc->ioc_prev_gid_list, cur_gid_list)) {
62487c478bd9Sstevel@tonic-gate 		ioc->ioc_info_updated.ib_gid_prop_updated = 1;
62497c478bd9Sstevel@tonic-gate 	}
62507c478bd9Sstevel@tonic-gate 
62517c478bd9Sstevel@tonic-gate 	/* Zero out previous entries */
62527c478bd9Sstevel@tonic-gate 	ibdm_free_gid_list(ioc->ioc_prev_gid_list);
62537c478bd9Sstevel@tonic-gate 	if (ioc->ioc_prev_serv)
62547c478bd9Sstevel@tonic-gate 		kmem_free(ioc->ioc_prev_serv, ioc->ioc_prev_serv_cnt *
62557c478bd9Sstevel@tonic-gate 		    sizeof (ibdm_srvents_info_t));
62567c478bd9Sstevel@tonic-gate 	ioc->ioc_prev_serv_cnt = 0;
62577c478bd9Sstevel@tonic-gate 	ioc->ioc_prev_nportgids = 0;
62587c478bd9Sstevel@tonic-gate 	ioc->ioc_prev_serv = NULL;
62597c478bd9Sstevel@tonic-gate 	ioc->ioc_prev_gid_list = NULL;
62607c478bd9Sstevel@tonic-gate }
62617c478bd9Sstevel@tonic-gate 
62627c478bd9Sstevel@tonic-gate /*
62637c478bd9Sstevel@tonic-gate  * Handle GID removal. This returns gid_info of an GID for the same
62647c478bd9Sstevel@tonic-gate  * node GUID, if found.  For an GID with IOU information, the same
62657c478bd9Sstevel@tonic-gate  * gid_info is returned if no gid_info with same node_guid is found.
62667c478bd9Sstevel@tonic-gate  */
62677c478bd9Sstevel@tonic-gate static ibdm_dp_gidinfo_t *
ibdm_handle_gid_rm(ibdm_dp_gidinfo_t * rm_gid)62687c478bd9Sstevel@tonic-gate ibdm_handle_gid_rm(ibdm_dp_gidinfo_t *rm_gid)
62697c478bd9Sstevel@tonic-gate {
62707c478bd9Sstevel@tonic-gate 	ibdm_dp_gidinfo_t	*gid_list;
62717c478bd9Sstevel@tonic-gate 
62727c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\thandle_gid_rm(0x%p)", rm_gid);
62737c478bd9Sstevel@tonic-gate 
62747c478bd9Sstevel@tonic-gate 	if (rm_gid->gl_iou == NULL) {
62757c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibdm", "\thandle_gid_rm NO iou");
62767c478bd9Sstevel@tonic-gate 		/*
62777c478bd9Sstevel@tonic-gate 		 * Search for a GID with same node_guid and
62787c478bd9Sstevel@tonic-gate 		 * gl_iou != NULL
62797c478bd9Sstevel@tonic-gate 		 */
62807c478bd9Sstevel@tonic-gate 		for (gid_list = ibdm.ibdm_dp_gidlist_head; gid_list;
62817c478bd9Sstevel@tonic-gate 		    gid_list = gid_list->gl_next) {
62827c478bd9Sstevel@tonic-gate 			if (gid_list->gl_iou != NULL && (gid_list->gl_nodeguid
62837c478bd9Sstevel@tonic-gate 			    == rm_gid->gl_nodeguid))
62847c478bd9Sstevel@tonic-gate 				break;
62857c478bd9Sstevel@tonic-gate 		}
62867c478bd9Sstevel@tonic-gate 
62877c478bd9Sstevel@tonic-gate 		if (gid_list)
62887c478bd9Sstevel@tonic-gate 			ibdm_rmfrom_glgid_list(gid_list, rm_gid);
62897c478bd9Sstevel@tonic-gate 
62907c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibdm", "\thandle_gid_rm ret %p", gid_list);
62917c478bd9Sstevel@tonic-gate 		return (gid_list);
62927c478bd9Sstevel@tonic-gate 	} else {
62937c478bd9Sstevel@tonic-gate 		/*
62947c478bd9Sstevel@tonic-gate 		 * Search for a GID with same node_guid and
62957c478bd9Sstevel@tonic-gate 		 * gl_iou == NULL
62967c478bd9Sstevel@tonic-gate 		 */
62977c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibdm", "\thandle_gid_rm with iou");
62987c478bd9Sstevel@tonic-gate 		for (gid_list = ibdm.ibdm_dp_gidlist_head; gid_list;
62997c478bd9Sstevel@tonic-gate 		    gid_list = gid_list->gl_next) {
63007c478bd9Sstevel@tonic-gate 			if (gid_list->gl_iou == NULL && (gid_list->gl_nodeguid
63017c478bd9Sstevel@tonic-gate 			    == rm_gid->gl_nodeguid))
63027c478bd9Sstevel@tonic-gate 				break;
63037c478bd9Sstevel@tonic-gate 		}
63047c478bd9Sstevel@tonic-gate 
63057c478bd9Sstevel@tonic-gate 		if (gid_list) {
63067c478bd9Sstevel@tonic-gate 			/*
63077c478bd9Sstevel@tonic-gate 			 * Copy the following fields from rm_gid :
63087c478bd9Sstevel@tonic-gate 			 *	1. gl_state
63097c478bd9Sstevel@tonic-gate 			 *	2. gl_iou
63107c478bd9Sstevel@tonic-gate 			 *	3. gl_gid & gl_ngids
63117c478bd9Sstevel@tonic-gate 			 *
63127c478bd9Sstevel@tonic-gate 			 * Note :	Function is synchronized by
63137c478bd9Sstevel@tonic-gate 			 *			ibdm_busy flag.
63147c478bd9Sstevel@tonic-gate 			 *
63157c478bd9Sstevel@tonic-gate 			 * Note :	Redirect info is initialized if
63167c478bd9Sstevel@tonic-gate 			 *			any MADs for the GID fail
63177c478bd9Sstevel@tonic-gate 			 */
63187c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibdm", "\thandle_gid_rm "
63197c478bd9Sstevel@tonic-gate 			    "copying info to GID with gl_iou != NULl");
63207c478bd9Sstevel@tonic-gate 			gid_list->gl_state = rm_gid->gl_state;
63217c478bd9Sstevel@tonic-gate 			gid_list->gl_iou = rm_gid->gl_iou;
63227c478bd9Sstevel@tonic-gate 			gid_list->gl_gid = rm_gid->gl_gid;
63237c478bd9Sstevel@tonic-gate 			gid_list->gl_ngids = rm_gid->gl_ngids;
63247c478bd9Sstevel@tonic-gate 
63257c478bd9Sstevel@tonic-gate 			/* Remove the GID from gl_gid list */
63267c478bd9Sstevel@tonic-gate 			ibdm_rmfrom_glgid_list(gid_list, rm_gid);
63277c478bd9Sstevel@tonic-gate 		} else {
63287c478bd9Sstevel@tonic-gate 			/*
63297c478bd9Sstevel@tonic-gate 			 * Handle a case where all GIDs to the IOU have
63307c478bd9Sstevel@tonic-gate 			 * been removed.
63317c478bd9Sstevel@tonic-gate 			 */
63327c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibdm", "\thandle_gid_rm 0 GID "
63337c478bd9Sstevel@tonic-gate 			    "to IOU");
63347c478bd9Sstevel@tonic-gate 
63357c478bd9Sstevel@tonic-gate 			ibdm_rmfrom_glgid_list(rm_gid, rm_gid);
63367c478bd9Sstevel@tonic-gate 			return (rm_gid);
63377c478bd9Sstevel@tonic-gate 		}
63387c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibdm", "\thandle_gid_rm ret %p", gid_list);
63397c478bd9Sstevel@tonic-gate 		return (gid_list);
63407c478bd9Sstevel@tonic-gate 	}
63417c478bd9Sstevel@tonic-gate }
63427c478bd9Sstevel@tonic-gate 
63437c478bd9Sstevel@tonic-gate static void
ibdm_rmfrom_glgid_list(ibdm_dp_gidinfo_t * gid_info,ibdm_dp_gidinfo_t * rm_gid)63447c478bd9Sstevel@tonic-gate ibdm_rmfrom_glgid_list(ibdm_dp_gidinfo_t *gid_info,
63457c478bd9Sstevel@tonic-gate     ibdm_dp_gidinfo_t *rm_gid)
63467c478bd9Sstevel@tonic-gate {
63477c478bd9Sstevel@tonic-gate 	ibdm_gid_t 		*tmp, *prev;
63487c478bd9Sstevel@tonic-gate 
63497c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\trmfrom_glgid (%p, %p)",
63507c478bd9Sstevel@tonic-gate 	    gid_info, rm_gid);
63517c478bd9Sstevel@tonic-gate 
63527c478bd9Sstevel@tonic-gate 	for (tmp = gid_info->gl_gid, prev = NULL; tmp; ) {
63537c478bd9Sstevel@tonic-gate 		if (tmp->gid_dgid_hi == rm_gid->gl_dgid_hi &&
63547c478bd9Sstevel@tonic-gate 		    tmp->gid_dgid_lo == rm_gid->gl_dgid_lo) {
63557c478bd9Sstevel@tonic-gate 			if (prev == NULL)
63567c478bd9Sstevel@tonic-gate 				gid_info->gl_gid = tmp->gid_next;
63577c478bd9Sstevel@tonic-gate 			else
63587c478bd9Sstevel@tonic-gate 				prev->gid_next = tmp->gid_next;
63597c478bd9Sstevel@tonic-gate 
63607c478bd9Sstevel@tonic-gate 			kmem_free(tmp, sizeof (ibdm_gid_t));
63617c478bd9Sstevel@tonic-gate 			gid_info->gl_ngids--;
63627c478bd9Sstevel@tonic-gate 			break;
63637c478bd9Sstevel@tonic-gate 		} else {
63647c478bd9Sstevel@tonic-gate 			prev = tmp;
63657c478bd9Sstevel@tonic-gate 			tmp = tmp->gid_next;
63667c478bd9Sstevel@tonic-gate 		}
63677c478bd9Sstevel@tonic-gate 	}
63687c478bd9Sstevel@tonic-gate }
63697c478bd9Sstevel@tonic-gate 
63707c478bd9Sstevel@tonic-gate static void
ibdm_addto_gidlist(ibdm_gid_t ** src_ptr,ibdm_gid_t * dest)63717c478bd9Sstevel@tonic-gate ibdm_addto_gidlist(ibdm_gid_t **src_ptr, ibdm_gid_t *dest)
63727c478bd9Sstevel@tonic-gate {
63737c478bd9Sstevel@tonic-gate 	ibdm_gid_t *head = NULL, *new, *tail;
63747c478bd9Sstevel@tonic-gate 
63757c478bd9Sstevel@tonic-gate 	/* First copy the destination */
63767c478bd9Sstevel@tonic-gate 	for (; dest; dest = dest->gid_next) {
63777c478bd9Sstevel@tonic-gate 		new = kmem_zalloc(sizeof (ibdm_gid_t), KM_SLEEP);
63787c478bd9Sstevel@tonic-gate 		new->gid_dgid_hi = dest->gid_dgid_hi;
63797c478bd9Sstevel@tonic-gate 		new->gid_dgid_lo = dest->gid_dgid_lo;
63807c478bd9Sstevel@tonic-gate 		new->gid_next = head;
63817c478bd9Sstevel@tonic-gate 		head = new;
63827c478bd9Sstevel@tonic-gate 	}
63837c478bd9Sstevel@tonic-gate 
63847c478bd9Sstevel@tonic-gate 	/* Insert this to the source */
63857c478bd9Sstevel@tonic-gate 	if (*src_ptr == NULL)
63867c478bd9Sstevel@tonic-gate 		*src_ptr = head;
63877c478bd9Sstevel@tonic-gate 	else {
63887c478bd9Sstevel@tonic-gate 		for (tail = *src_ptr; tail->gid_next != NULL;
63897c478bd9Sstevel@tonic-gate 		    tail = tail->gid_next)
63907c478bd9Sstevel@tonic-gate 			;
63917c478bd9Sstevel@tonic-gate 
63927c478bd9Sstevel@tonic-gate 		tail->gid_next = head;
63937c478bd9Sstevel@tonic-gate 	}
63947c478bd9Sstevel@tonic-gate }
63957c478bd9Sstevel@tonic-gate 
63967c478bd9Sstevel@tonic-gate static void
ibdm_free_gid_list(ibdm_gid_t * head)63977c478bd9Sstevel@tonic-gate ibdm_free_gid_list(ibdm_gid_t	*head)
63987c478bd9Sstevel@tonic-gate {
63997c478bd9Sstevel@tonic-gate 	ibdm_gid_t	*delete;
64007c478bd9Sstevel@tonic-gate 
64017c478bd9Sstevel@tonic-gate 	for (delete = head; delete; ) {
64027c478bd9Sstevel@tonic-gate 		head = delete->gid_next;
64037c478bd9Sstevel@tonic-gate 		kmem_free(delete, sizeof (ibdm_gid_t));
64047c478bd9Sstevel@tonic-gate 		delete = head;
64057c478bd9Sstevel@tonic-gate 	}
64067c478bd9Sstevel@tonic-gate }
64077c478bd9Sstevel@tonic-gate 
64087c478bd9Sstevel@tonic-gate /*
64097c478bd9Sstevel@tonic-gate  * This function rescans the DM capable GIDs (gl_state is
64107c478bd9Sstevel@tonic-gate  * GID_PROBE_COMPLETE or IBDM_GID_PROBING_SKIPPED.This
64117c478bd9Sstevel@tonic-gate  * basically checks if the DM capable GID is reachable. If
64127c478bd9Sstevel@tonic-gate  * not this is handled the same way as GID_UNAVAILABLE,
64137c478bd9Sstevel@tonic-gate  * except that notifications are not send to IBnexus.
64147c478bd9Sstevel@tonic-gate  *
64157c478bd9Sstevel@tonic-gate  * This function also initializes the ioc_prev_list for
64167c478bd9Sstevel@tonic-gate  * a particular IOC (when called from probe_ioc, with
64177c478bd9Sstevel@tonic-gate  * ioc_guidp != NULL) or all IOCs for the gid (called from
64187c478bd9Sstevel@tonic-gate  * sweep_fabric, ioc_guidp == NULL).
64197c478bd9Sstevel@tonic-gate  */
64207c478bd9Sstevel@tonic-gate static void
ibdm_rescan_gidlist(ib_guid_t * ioc_guidp)64217c478bd9Sstevel@tonic-gate ibdm_rescan_gidlist(ib_guid_t *ioc_guidp)
64227c478bd9Sstevel@tonic-gate {
64237c478bd9Sstevel@tonic-gate 	ibdm_dp_gidinfo_t	*gid_info, *tmp;
64247c478bd9Sstevel@tonic-gate 	int ii, niocs, found;
64257c478bd9Sstevel@tonic-gate 	ibdm_hca_list_t *hca_list = NULL;
64267c478bd9Sstevel@tonic-gate 	ibdm_port_attr_t *port = NULL;
64277c478bd9Sstevel@tonic-gate 	ibdm_ioc_info_t *ioc_list;
64287c478bd9Sstevel@tonic-gate 
64297c478bd9Sstevel@tonic-gate 	for (gid_info = ibdm.ibdm_dp_gidlist_head; gid_info; ) {
64307c478bd9Sstevel@tonic-gate 		found = 0;
64317c478bd9Sstevel@tonic-gate 		if (gid_info->gl_state != IBDM_GID_PROBING_SKIPPED &&
64327c478bd9Sstevel@tonic-gate 		    gid_info->gl_state != IBDM_GID_PROBING_COMPLETE) {
64337c478bd9Sstevel@tonic-gate 			gid_info = gid_info->gl_next;
64347c478bd9Sstevel@tonic-gate 			continue;
64357c478bd9Sstevel@tonic-gate 		}
64367c478bd9Sstevel@tonic-gate 
64377c478bd9Sstevel@tonic-gate 		/*
64387c478bd9Sstevel@tonic-gate 		 * Check if the GID is visible to any HCA ports.
64397c478bd9Sstevel@tonic-gate 		 * Return if so.
64407c478bd9Sstevel@tonic-gate 		 */
64417c478bd9Sstevel@tonic-gate 		mutex_enter(&ibdm.ibdm_hl_mutex);
64427c478bd9Sstevel@tonic-gate 		for (ibdm_get_next_port(&hca_list, &port, 1); port;
64437c478bd9Sstevel@tonic-gate 		    ibdm_get_next_port(&hca_list, &port, 1)) {
64447c478bd9Sstevel@tonic-gate 			if (ibdm_port_reachable(port->pa_sa_hdl,
644553c1b7a3Seota 			    gid_info->gl_dgid_lo) == B_TRUE) {
64467c478bd9Sstevel@tonic-gate 				found = 1;
64477c478bd9Sstevel@tonic-gate 				break;
64487c478bd9Sstevel@tonic-gate 			}
64497c478bd9Sstevel@tonic-gate 		}
64507c478bd9Sstevel@tonic-gate 		mutex_exit(&ibdm.ibdm_hl_mutex);
64517c478bd9Sstevel@tonic-gate 
64527c478bd9Sstevel@tonic-gate 		if (found) {
64537c478bd9Sstevel@tonic-gate 			if (gid_info->gl_iou == NULL) {
64547c478bd9Sstevel@tonic-gate 				gid_info = gid_info->gl_next;
64557c478bd9Sstevel@tonic-gate 				continue;
64567c478bd9Sstevel@tonic-gate 			}
64577c478bd9Sstevel@tonic-gate 
64587c478bd9Sstevel@tonic-gate 			/* Intialize the ioc_prev_gid_list */
64597c478bd9Sstevel@tonic-gate 			niocs =
64607c478bd9Sstevel@tonic-gate 			    gid_info->gl_iou->iou_info.iou_num_ctrl_slots;
64617c478bd9Sstevel@tonic-gate 			for (ii = 0; ii < niocs; ii++) {
64627c478bd9Sstevel@tonic-gate 				ioc_list = IBDM_GIDINFO2IOCINFO(gid_info, ii);
64637c478bd9Sstevel@tonic-gate 
64647c478bd9Sstevel@tonic-gate 				if (ioc_guidp == NULL || (*ioc_guidp ==
64657c478bd9Sstevel@tonic-gate 				    ioc_list->ioc_profile.ioc_guid)) {
64667c478bd9Sstevel@tonic-gate 					/* Add info of GIDs in gid_info also */
64677c478bd9Sstevel@tonic-gate 					ibdm_addto_gidlist(
64687c478bd9Sstevel@tonic-gate 					    &ioc_list->ioc_prev_gid_list,
64697c478bd9Sstevel@tonic-gate 					    gid_info->gl_gid);
64707c478bd9Sstevel@tonic-gate 					ioc_list->ioc_prev_nportgids =
64717c478bd9Sstevel@tonic-gate 					    gid_info->gl_ngids;
64727c478bd9Sstevel@tonic-gate 				}
64737c478bd9Sstevel@tonic-gate 			}
64747c478bd9Sstevel@tonic-gate 			gid_info = gid_info->gl_next;
64757c478bd9Sstevel@tonic-gate 			continue;
64767c478bd9Sstevel@tonic-gate 		}
64777c478bd9Sstevel@tonic-gate 
64787c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibdm", "\trescan_gidlist "
64797c478bd9Sstevel@tonic-gate 		    "deleted port GUID %llx",
64807c478bd9Sstevel@tonic-gate 		    gid_info->gl_dgid_lo);
64817c478bd9Sstevel@tonic-gate 
64827c478bd9Sstevel@tonic-gate 		/*
64837c478bd9Sstevel@tonic-gate 		 * Update GID list in all IOCs affected by this
64847c478bd9Sstevel@tonic-gate 		 */
64857c478bd9Sstevel@tonic-gate 		ioc_list = ibdm_update_ioc_gidlist(gid_info, 0);
64867c478bd9Sstevel@tonic-gate 
64877c478bd9Sstevel@tonic-gate 		/*
64887c478bd9Sstevel@tonic-gate 		 * Remove GID from the global GID list
64897c478bd9Sstevel@tonic-gate 		 * Handle the case where all port GIDs for an
64907c478bd9Sstevel@tonic-gate 		 * IOU have been hot-removed.
64917c478bd9Sstevel@tonic-gate 		 */
64927c478bd9Sstevel@tonic-gate 		mutex_enter(&ibdm.ibdm_mutex);
64937c478bd9Sstevel@tonic-gate 		if (gid_info->gl_iou != NULL && gid_info->gl_ngids == 0) {
64947c478bd9Sstevel@tonic-gate 			mutex_enter(&gid_info->gl_mutex);
6495add2b70bSpramodbg 			(void) ibdm_free_iou_info(gid_info, &gid_info->gl_iou);
64967c478bd9Sstevel@tonic-gate 			mutex_exit(&gid_info->gl_mutex);
64977c478bd9Sstevel@tonic-gate 		}
649853c1b7a3Seota 
64997c478bd9Sstevel@tonic-gate 		tmp = gid_info->gl_next;
65007c478bd9Sstevel@tonic-gate 		if (gid_info->gl_prev != NULL)
65017c478bd9Sstevel@tonic-gate 			gid_info->gl_prev->gl_next = gid_info->gl_next;
65027c478bd9Sstevel@tonic-gate 		if (gid_info->gl_next != NULL)
65037c478bd9Sstevel@tonic-gate 			gid_info->gl_next->gl_prev = gid_info->gl_prev;
65047c478bd9Sstevel@tonic-gate 
65057c478bd9Sstevel@tonic-gate 		if (gid_info == ibdm.ibdm_dp_gidlist_head)
65067c478bd9Sstevel@tonic-gate 			ibdm.ibdm_dp_gidlist_head = gid_info->gl_next;
65077c478bd9Sstevel@tonic-gate 		if (gid_info == ibdm.ibdm_dp_gidlist_tail)
65087c478bd9Sstevel@tonic-gate 			ibdm.ibdm_dp_gidlist_tail = gid_info->gl_prev;
65097c478bd9Sstevel@tonic-gate 		ibdm.ibdm_ngids--;
651053c1b7a3Seota 		mutex_exit(&ibdm.ibdm_mutex);
651153c1b7a3Seota 
651253c1b7a3Seota 		/* free the hca_list on this gid_info */
651353c1b7a3Seota 		ibdm_delete_glhca_list(gid_info);
65147c478bd9Sstevel@tonic-gate 
65157c478bd9Sstevel@tonic-gate 		mutex_destroy(&gid_info->gl_mutex);
65167c478bd9Sstevel@tonic-gate 		kmem_free(gid_info, sizeof (ibdm_dp_gidinfo_t));
65177c478bd9Sstevel@tonic-gate 
651853c1b7a3Seota 		gid_info = tmp;
65197c478bd9Sstevel@tonic-gate 
65207c478bd9Sstevel@tonic-gate 		/*
65217c478bd9Sstevel@tonic-gate 		 * Pass on the IOCs with updated GIDs to IBnexus
65227c478bd9Sstevel@tonic-gate 		 */
65237c478bd9Sstevel@tonic-gate 		if (ioc_list) {
65247c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibdm", "\trescan_gidlist "
65257c478bd9Sstevel@tonic-gate 			    "IOC_PROP_UPDATE for %p\n", ioc_list);
65267c478bd9Sstevel@tonic-gate 			mutex_enter(&ibdm.ibdm_ibnex_mutex);
65277c478bd9Sstevel@tonic-gate 			if (ibdm.ibdm_ibnex_callback != NULL) {
65287c478bd9Sstevel@tonic-gate 				(*ibdm.ibdm_ibnex_callback)((void *)
65297c478bd9Sstevel@tonic-gate 				    ioc_list, IBDM_EVENT_IOC_PROP_UPDATE);
65307c478bd9Sstevel@tonic-gate 			}
65317c478bd9Sstevel@tonic-gate 			mutex_exit(&ibdm.ibdm_ibnex_mutex);
65327c478bd9Sstevel@tonic-gate 		}
65337c478bd9Sstevel@tonic-gate 	}
65347c478bd9Sstevel@tonic-gate }
65357c478bd9Sstevel@tonic-gate 
65367c478bd9Sstevel@tonic-gate /*
65377c478bd9Sstevel@tonic-gate  * This function notifies IBnex of IOCs on this GID.
65387c478bd9Sstevel@tonic-gate  * Notification is for GIDs with gl_reprobe_flag set.
65397c478bd9Sstevel@tonic-gate  * The flag is set when IOC probe / fabric sweep
65407c478bd9Sstevel@tonic-gate  * probes a GID starting from CLASS port info.
65417c478bd9Sstevel@tonic-gate  *
65427c478bd9Sstevel@tonic-gate  * IBnexus will have information of a reconnected IOC
65437c478bd9Sstevel@tonic-gate  * if it had probed it before. If this is a new IOC,
65447c478bd9Sstevel@tonic-gate  * IBnexus ignores the notification.
65457c478bd9Sstevel@tonic-gate  *
65467c478bd9Sstevel@tonic-gate  * This function should be called with no locks held.
65477c478bd9Sstevel@tonic-gate  */
65487c478bd9Sstevel@tonic-gate static void
ibdm_notify_newgid_iocs(ibdm_dp_gidinfo_t * gid_info)65497c478bd9Sstevel@tonic-gate ibdm_notify_newgid_iocs(ibdm_dp_gidinfo_t *gid_info)
65507c478bd9Sstevel@tonic-gate {
65517c478bd9Sstevel@tonic-gate 	ibdm_ioc_info_t	*ioc_list;
65527c478bd9Sstevel@tonic-gate 
65537c478bd9Sstevel@tonic-gate 	if (gid_info->gl_reprobe_flag == 0 ||
65547c478bd9Sstevel@tonic-gate 	    gid_info->gl_iou == NULL)
65557c478bd9Sstevel@tonic-gate 		return;
65567c478bd9Sstevel@tonic-gate 
65577c478bd9Sstevel@tonic-gate 	ioc_list = ibdm_update_ioc_gidlist(gid_info, -1);
65587c478bd9Sstevel@tonic-gate 
65597c478bd9Sstevel@tonic-gate 	/*
65607c478bd9Sstevel@tonic-gate 	 * Pass on the IOCs with updated GIDs to IBnexus
65617c478bd9Sstevel@tonic-gate 	 */
65627c478bd9Sstevel@tonic-gate 	if (ioc_list) {
65637c478bd9Sstevel@tonic-gate 		mutex_enter(&ibdm.ibdm_ibnex_mutex);
65647c478bd9Sstevel@tonic-gate 		if (ibdm.ibdm_ibnex_callback != NULL) {
65657c478bd9Sstevel@tonic-gate 			(*ibdm.ibdm_ibnex_callback)((void *)ioc_list,
65667c478bd9Sstevel@tonic-gate 			    IBDM_EVENT_IOC_PROP_UPDATE);
65677c478bd9Sstevel@tonic-gate 		}
65687c478bd9Sstevel@tonic-gate 		mutex_exit(&ibdm.ibdm_ibnex_mutex);
65697c478bd9Sstevel@tonic-gate 	}
65707c478bd9Sstevel@tonic-gate }
65717c478bd9Sstevel@tonic-gate 
65727c478bd9Sstevel@tonic-gate 
65737c478bd9Sstevel@tonic-gate static void
ibdm_free_saa_event_arg(ibdm_saa_event_arg_t * arg)65747c478bd9Sstevel@tonic-gate ibdm_free_saa_event_arg(ibdm_saa_event_arg_t *arg)
65757c478bd9Sstevel@tonic-gate {
65767c478bd9Sstevel@tonic-gate 	if (arg != NULL)
65777c478bd9Sstevel@tonic-gate 		kmem_free(arg, sizeof (ibdm_saa_event_arg_t));
65787c478bd9Sstevel@tonic-gate }
65797c478bd9Sstevel@tonic-gate 
65807c478bd9Sstevel@tonic-gate /*
65817c478bd9Sstevel@tonic-gate  * This function parses the list of HCAs and HCA ports
65827c478bd9Sstevel@tonic-gate  * to return the port_attr of the next HCA port. A port
65837c478bd9Sstevel@tonic-gate  * connected to IB fabric (port_state active) is returned,
65847c478bd9Sstevel@tonic-gate  * if connected_flag is set.
65857c478bd9Sstevel@tonic-gate  */
65867c478bd9Sstevel@tonic-gate static void
ibdm_get_next_port(ibdm_hca_list_t ** inp_hcap,ibdm_port_attr_t ** inp_portp,int connect_flag)65877c478bd9Sstevel@tonic-gate ibdm_get_next_port(ibdm_hca_list_t **inp_hcap,
65887c478bd9Sstevel@tonic-gate     ibdm_port_attr_t **inp_portp, int connect_flag)
65897c478bd9Sstevel@tonic-gate {
65907c478bd9Sstevel@tonic-gate 	int ii;
65917c478bd9Sstevel@tonic-gate 	ibdm_port_attr_t *port, *next_port = NULL;
65927c478bd9Sstevel@tonic-gate 	ibdm_port_attr_t *inp_port;
65937c478bd9Sstevel@tonic-gate 	ibdm_hca_list_t	 *hca_list;
65947c478bd9Sstevel@tonic-gate 	int found = 0;
65957c478bd9Sstevel@tonic-gate 
65967c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ibdm.ibdm_hl_mutex));
65977c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4(ibdm_string, "\tget_next_port(%p, %p, %x)",
65987c478bd9Sstevel@tonic-gate 	    inp_hcap, inp_portp, connect_flag);
65997c478bd9Sstevel@tonic-gate 
66007c478bd9Sstevel@tonic-gate 	hca_list = *inp_hcap;
66017c478bd9Sstevel@tonic-gate 	inp_port = *inp_portp;
66027c478bd9Sstevel@tonic-gate 
66037c478bd9Sstevel@tonic-gate 	if (hca_list == NULL)
66047c478bd9Sstevel@tonic-gate 		hca_list = ibdm.ibdm_hca_list_head;
66057c478bd9Sstevel@tonic-gate 
66067c478bd9Sstevel@tonic-gate 	for (; hca_list; hca_list = hca_list->hl_next) {
66077c478bd9Sstevel@tonic-gate 		for (ii = 0; ii < hca_list->hl_nports; ii++) {
66087c478bd9Sstevel@tonic-gate 			port = &hca_list->hl_port_attr[ii];
66097c478bd9Sstevel@tonic-gate 
66107c478bd9Sstevel@tonic-gate 			/*
66117c478bd9Sstevel@tonic-gate 			 * inp_port != NULL;
66127c478bd9Sstevel@tonic-gate 			 * 	Skip till we find the matching port
66137c478bd9Sstevel@tonic-gate 			 */
66147c478bd9Sstevel@tonic-gate 			if (inp_port && !found) {
66157c478bd9Sstevel@tonic-gate 				if (inp_port == port)
66167c478bd9Sstevel@tonic-gate 					found = 1;
66177c478bd9Sstevel@tonic-gate 				continue;
66187c478bd9Sstevel@tonic-gate 			}
66197c478bd9Sstevel@tonic-gate 
66207c478bd9Sstevel@tonic-gate 			if (!connect_flag) {
66217c478bd9Sstevel@tonic-gate 				next_port = port;
66227c478bd9Sstevel@tonic-gate 				break;
66237c478bd9Sstevel@tonic-gate 			}
66247c478bd9Sstevel@tonic-gate 
66257c478bd9Sstevel@tonic-gate 			if (port->pa_sa_hdl == NULL)
66267c478bd9Sstevel@tonic-gate 				ibdm_initialize_port(port);
66277c478bd9Sstevel@tonic-gate 			if (port->pa_sa_hdl == NULL)
66287c478bd9Sstevel@tonic-gate 				(void) ibdm_fini_port(port);
66297c478bd9Sstevel@tonic-gate 			else if (next_port == NULL &&
66307c478bd9Sstevel@tonic-gate 			    port->pa_sa_hdl != NULL &&
66317c478bd9Sstevel@tonic-gate 			    port->pa_state == IBT_PORT_ACTIVE) {
66327c478bd9Sstevel@tonic-gate 				next_port = port;
66337c478bd9Sstevel@tonic-gate 				break;
66347c478bd9Sstevel@tonic-gate 			}
66357c478bd9Sstevel@tonic-gate 		}
66367c478bd9Sstevel@tonic-gate 
66377c478bd9Sstevel@tonic-gate 		if (next_port)
66387c478bd9Sstevel@tonic-gate 			break;
66397c478bd9Sstevel@tonic-gate 	}
66407c478bd9Sstevel@tonic-gate 
66417c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4(ibdm_string, "\tget_next_port : "
66427c478bd9Sstevel@tonic-gate 	    "returns hca_list %p port %p", hca_list, next_port);
66437c478bd9Sstevel@tonic-gate 	*inp_hcap = hca_list;
66447c478bd9Sstevel@tonic-gate 	*inp_portp = next_port;
66457c478bd9Sstevel@tonic-gate }
66467c478bd9Sstevel@tonic-gate 
66477c478bd9Sstevel@tonic-gate static void
ibdm_add_to_gl_gid(ibdm_dp_gidinfo_t * nodegid,ibdm_dp_gidinfo_t * addgid)66487c478bd9Sstevel@tonic-gate ibdm_add_to_gl_gid(ibdm_dp_gidinfo_t *nodegid, ibdm_dp_gidinfo_t *addgid)
66497c478bd9Sstevel@tonic-gate {
66507c478bd9Sstevel@tonic-gate 	ibdm_gid_t	*tmp;
66517c478bd9Sstevel@tonic-gate 
66527c478bd9Sstevel@tonic-gate 	tmp = kmem_zalloc(sizeof (ibdm_gid_t), KM_SLEEP);
66537c478bd9Sstevel@tonic-gate 	tmp->gid_dgid_hi = addgid->gl_dgid_hi;
66547c478bd9Sstevel@tonic-gate 	tmp->gid_dgid_lo = addgid->gl_dgid_lo;
66557c478bd9Sstevel@tonic-gate 
66567c478bd9Sstevel@tonic-gate 	mutex_enter(&nodegid->gl_mutex);
66577c478bd9Sstevel@tonic-gate 	tmp->gid_next = nodegid->gl_gid;
66587c478bd9Sstevel@tonic-gate 	nodegid->gl_gid = tmp;
66597c478bd9Sstevel@tonic-gate 	nodegid->gl_ngids++;
66607c478bd9Sstevel@tonic-gate 	mutex_exit(&nodegid->gl_mutex);
66617c478bd9Sstevel@tonic-gate }
66627c478bd9Sstevel@tonic-gate 
66637c478bd9Sstevel@tonic-gate static void
ibdm_addto_glhcalist(ibdm_dp_gidinfo_t * gid_info,ibdm_hca_list_t * hca)66647c478bd9Sstevel@tonic-gate ibdm_addto_glhcalist(ibdm_dp_gidinfo_t *gid_info,
66657c478bd9Sstevel@tonic-gate     ibdm_hca_list_t *hca)
66667c478bd9Sstevel@tonic-gate {
66677c478bd9Sstevel@tonic-gate 	ibdm_hca_list_t		*head, *prev = NULL, *temp;
66687c478bd9Sstevel@tonic-gate 
66697c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4(ibdm_string, "\taddto_glhcalist(%p, %p) "
66707c478bd9Sstevel@tonic-gate 	    ": gl_hca_list %p", gid_info, hca, gid_info->gl_hca_list);
66717c478bd9Sstevel@tonic-gate 	ASSERT(!MUTEX_HELD(&gid_info->gl_mutex));
667253c1b7a3Seota 
66737c478bd9Sstevel@tonic-gate 	mutex_enter(&gid_info->gl_mutex);
66747c478bd9Sstevel@tonic-gate 	head = gid_info->gl_hca_list;
66757c478bd9Sstevel@tonic-gate 	if (head == NULL) {
66767c478bd9Sstevel@tonic-gate 		head = ibdm_dup_hca_attr(hca);
66777c478bd9Sstevel@tonic-gate 		head->hl_next = NULL;
66787c478bd9Sstevel@tonic-gate 		gid_info->gl_hca_list = head;
66797c478bd9Sstevel@tonic-gate 		mutex_exit(&gid_info->gl_mutex);
66807c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4(ibdm_string, "\tadd_to_glhcalist: "
66817c478bd9Sstevel@tonic-gate 		    "gid %p, gl_hca_list %p", gid_info,
66827c478bd9Sstevel@tonic-gate 		    gid_info->gl_hca_list);
66837c478bd9Sstevel@tonic-gate 		return;
66847c478bd9Sstevel@tonic-gate 	}
66857c478bd9Sstevel@tonic-gate 
66867c478bd9Sstevel@tonic-gate 	/* Check if already in the list */
66877c478bd9Sstevel@tonic-gate 	while (head) {
66887c478bd9Sstevel@tonic-gate 		if (head->hl_hca_guid == hca->hl_hca_guid) {
66897c478bd9Sstevel@tonic-gate 			mutex_exit(&gid_info->gl_mutex);
66907c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L4(ibdm_string,
6691a1e3386eShiremath 			    "\taddto_glhcalist : gid %p hca %p dup",
66927c478bd9Sstevel@tonic-gate 			    gid_info, hca);
66937c478bd9Sstevel@tonic-gate 			return;
66947c478bd9Sstevel@tonic-gate 		}
66957c478bd9Sstevel@tonic-gate 		prev = head;
66967c478bd9Sstevel@tonic-gate 		head = head->hl_next;
66977c478bd9Sstevel@tonic-gate 	}
66987c478bd9Sstevel@tonic-gate 
66997c478bd9Sstevel@tonic-gate 	/* Add this HCA to gl_hca_list */
67007c478bd9Sstevel@tonic-gate 	temp =  ibdm_dup_hca_attr(hca);
67017c478bd9Sstevel@tonic-gate 	temp->hl_next = NULL;
67027c478bd9Sstevel@tonic-gate 	prev->hl_next = temp;
67037c478bd9Sstevel@tonic-gate 	mutex_exit(&gid_info->gl_mutex);
67047c478bd9Sstevel@tonic-gate 
67057c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4(ibdm_string, "\tadd_to_glhcalist: "
67067c478bd9Sstevel@tonic-gate 	    "gid %p, gl_hca_list %p", gid_info, gid_info->gl_hca_list);
67077c478bd9Sstevel@tonic-gate }
67087c478bd9Sstevel@tonic-gate 
67097c478bd9Sstevel@tonic-gate static void
ibdm_delete_glhca_list(ibdm_dp_gidinfo_t * gid_info)67107c478bd9Sstevel@tonic-gate ibdm_delete_glhca_list(ibdm_dp_gidinfo_t *gid_info)
67117c478bd9Sstevel@tonic-gate {
67127c478bd9Sstevel@tonic-gate 	ASSERT(!MUTEX_HELD(&gid_info->gl_mutex));
67137c478bd9Sstevel@tonic-gate 	ASSERT(!MUTEX_HELD(&ibdm.ibdm_mutex));
67147c478bd9Sstevel@tonic-gate 
67157c478bd9Sstevel@tonic-gate 	mutex_enter(&gid_info->gl_mutex);
67167c478bd9Sstevel@tonic-gate 	if (gid_info->gl_hca_list)
67177c478bd9Sstevel@tonic-gate 		ibdm_ibnex_free_hca_list(gid_info->gl_hca_list);
67187c478bd9Sstevel@tonic-gate 	gid_info->gl_hca_list = NULL;
67197c478bd9Sstevel@tonic-gate 	mutex_exit(&gid_info->gl_mutex);
67207c478bd9Sstevel@tonic-gate }
67217c478bd9Sstevel@tonic-gate 
67227c478bd9Sstevel@tonic-gate 
67237c478bd9Sstevel@tonic-gate static void
ibdm_reset_all_dgids(ibmf_saa_handle_t port_sa_hdl)67247c478bd9Sstevel@tonic-gate ibdm_reset_all_dgids(ibmf_saa_handle_t port_sa_hdl)
67257c478bd9Sstevel@tonic-gate {
67267c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4(ibdm_string, "\treset_all_dgids(%X)",
67277c478bd9Sstevel@tonic-gate 	    port_sa_hdl);
67287c478bd9Sstevel@tonic-gate 
6729c44ec8d2SRamaswamy Tummala 	if (ibdm_enumerate_iocs == 0)
6730c44ec8d2SRamaswamy Tummala 		return;
6731c44ec8d2SRamaswamy Tummala 
67327c478bd9Sstevel@tonic-gate 	ASSERT(!MUTEX_HELD(&ibdm.ibdm_mutex));
67337c478bd9Sstevel@tonic-gate 	ASSERT(!MUTEX_HELD(&ibdm.ibdm_hl_mutex));
67347c478bd9Sstevel@tonic-gate 
67357c478bd9Sstevel@tonic-gate 	/* Check : Not busy in another probe / sweep */
67367c478bd9Sstevel@tonic-gate 	mutex_enter(&ibdm.ibdm_mutex);
67377c478bd9Sstevel@tonic-gate 	if ((ibdm.ibdm_busy & IBDM_BUSY) == 0) {
67387c478bd9Sstevel@tonic-gate 		ibdm_dp_gidinfo_t	*gid_info;
67397c478bd9Sstevel@tonic-gate 
67407c478bd9Sstevel@tonic-gate 		ibdm.ibdm_busy |= IBDM_BUSY;
67417c478bd9Sstevel@tonic-gate 		mutex_exit(&ibdm.ibdm_mutex);
67427c478bd9Sstevel@tonic-gate 
67437c478bd9Sstevel@tonic-gate 		/*
67447c478bd9Sstevel@tonic-gate 		 * Check if any GID is using the SA & IBMF handle
67457c478bd9Sstevel@tonic-gate 		 * of HCA port going down. Reset ibdm_dp_gidinfo_t
67467c478bd9Sstevel@tonic-gate 		 * using another HCA port which can reach the GID.
67477c478bd9Sstevel@tonic-gate 		 * This is for DM capable GIDs only, no need to do
67487c478bd9Sstevel@tonic-gate 		 * this for others
67497c478bd9Sstevel@tonic-gate 		 *
67507c478bd9Sstevel@tonic-gate 		 * Delete the GID if no alternate HCA port to reach
67517c478bd9Sstevel@tonic-gate 		 * it is found.
67527c478bd9Sstevel@tonic-gate 		 */
67537c478bd9Sstevel@tonic-gate 		for (gid_info = ibdm.ibdm_dp_gidlist_head; gid_info; ) {
67547c478bd9Sstevel@tonic-gate 			ibdm_dp_gidinfo_t *tmp;
67557c478bd9Sstevel@tonic-gate 
67567c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L4(ibdm_string, "\tevent_hdlr "
67577c478bd9Sstevel@tonic-gate 			    "checking gidinfo %p", gid_info);
67587c478bd9Sstevel@tonic-gate 
67594f1d42a6Spramodbg 			if (gid_info->gl_sa_hdl == port_sa_hdl) {
67607c478bd9Sstevel@tonic-gate 				IBTF_DPRINTF_L3(ibdm_string,
67617c478bd9Sstevel@tonic-gate 				    "\tevent_hdlr: down HCA port hdl "
67627c478bd9Sstevel@tonic-gate 				    "matches gid %p", gid_info);
67637c478bd9Sstevel@tonic-gate 
67644f1d42a6Spramodbg 				/*
67654f1d42a6Spramodbg 				 * The non-DM GIDs can come back
67664f1d42a6Spramodbg 				 * with a new subnet prefix, when
67674f1d42a6Spramodbg 				 * the HCA port commes up again. To
67684f1d42a6Spramodbg 				 * avoid issues, delete non-DM
67694f1d42a6Spramodbg 				 * capable GIDs, if the gid was
67704f1d42a6Spramodbg 				 * discovered using the HCA port
67714f1d42a6Spramodbg 				 * going down. This is ensured by
67724f1d42a6Spramodbg 				 * setting gl_disconnected to 1.
67734f1d42a6Spramodbg 				 */
67748e55d263SRajkumar Sivaprakasam 				if (gid_info->gl_is_dm_capable == B_FALSE)
67754f1d42a6Spramodbg 					gid_info->gl_disconnected = 1;
67764f1d42a6Spramodbg 				else
67774f1d42a6Spramodbg 					ibdm_reset_gidinfo(gid_info);
67784f1d42a6Spramodbg 
67797c478bd9Sstevel@tonic-gate 				if (gid_info->gl_disconnected) {
67807c478bd9Sstevel@tonic-gate 					IBTF_DPRINTF_L3(ibdm_string,
67817c478bd9Sstevel@tonic-gate 					    "\tevent_hdlr: deleting"
67827c478bd9Sstevel@tonic-gate 					    " gid %p", gid_info);
67837c478bd9Sstevel@tonic-gate 					tmp = gid_info;
67847c478bd9Sstevel@tonic-gate 					gid_info = gid_info->gl_next;
67857c478bd9Sstevel@tonic-gate 					ibdm_delete_gidinfo(tmp);
67867c478bd9Sstevel@tonic-gate 				} else
67877c478bd9Sstevel@tonic-gate 					gid_info = gid_info->gl_next;
67887c478bd9Sstevel@tonic-gate 			} else
67897c478bd9Sstevel@tonic-gate 				gid_info = gid_info->gl_next;
67907c478bd9Sstevel@tonic-gate 		}
67917c478bd9Sstevel@tonic-gate 
67927c478bd9Sstevel@tonic-gate 		mutex_enter(&ibdm.ibdm_mutex);
67937c478bd9Sstevel@tonic-gate 		ibdm.ibdm_busy &= ~IBDM_BUSY;
67947c478bd9Sstevel@tonic-gate 		cv_signal(&ibdm.ibdm_busy_cv);
67957c478bd9Sstevel@tonic-gate 	}
67967c478bd9Sstevel@tonic-gate 	mutex_exit(&ibdm.ibdm_mutex);
67977c478bd9Sstevel@tonic-gate }
67987c478bd9Sstevel@tonic-gate 
67997c478bd9Sstevel@tonic-gate static void
ibdm_reset_gidinfo(ibdm_dp_gidinfo_t * gidinfo)68007c478bd9Sstevel@tonic-gate ibdm_reset_gidinfo(ibdm_dp_gidinfo_t *gidinfo)
68017c478bd9Sstevel@tonic-gate {
68027c478bd9Sstevel@tonic-gate 	ibdm_hca_list_t	*hca_list = NULL;
68037c478bd9Sstevel@tonic-gate 	ibdm_port_attr_t	*port = NULL;
68047c478bd9Sstevel@tonic-gate 	int	gid_reinited = 0;
68057c478bd9Sstevel@tonic-gate 	sa_node_record_t	*nr, *tmp;
68067c478bd9Sstevel@tonic-gate 	sa_portinfo_record_t	*pi;
68077c478bd9Sstevel@tonic-gate 	size_t	nr_len = 0, pi_len = 0;
68087c478bd9Sstevel@tonic-gate 	size_t	path_len;
68097c478bd9Sstevel@tonic-gate 	ib_gid_t	sgid, dgid;
68107c478bd9Sstevel@tonic-gate 	int	ret, ii, nrecords;
68117c478bd9Sstevel@tonic-gate 	sa_path_record_t	*path;
68127c478bd9Sstevel@tonic-gate 	uint8_t	npaths = 1;
6813a1e3386eShiremath 	ibdm_pkey_tbl_t		*pkey_tbl;
68147c478bd9Sstevel@tonic-gate 
68157c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4(ibdm_string, "\treset_gidinfo(%p)", gidinfo);
68167c478bd9Sstevel@tonic-gate 
68177c478bd9Sstevel@tonic-gate 	/*
68187c478bd9Sstevel@tonic-gate 	 * Get list of all the ports reachable from the local known HCA
68197c478bd9Sstevel@tonic-gate 	 * ports which are active
68207c478bd9Sstevel@tonic-gate 	 */
68217c478bd9Sstevel@tonic-gate 	mutex_enter(&ibdm.ibdm_hl_mutex);
68227c478bd9Sstevel@tonic-gate 	for (ibdm_get_next_port(&hca_list, &port, 1); port;
68237c478bd9Sstevel@tonic-gate 	    ibdm_get_next_port(&hca_list, &port, 1)) {
68247c478bd9Sstevel@tonic-gate 
68257c478bd9Sstevel@tonic-gate 
68267c478bd9Sstevel@tonic-gate 		/*
68277c478bd9Sstevel@tonic-gate 		 * Get the path and re-populate the gidinfo.
68287c478bd9Sstevel@tonic-gate 		 * Getting the path is the same probe_ioc
68297c478bd9Sstevel@tonic-gate 		 * Init the gid info as in ibdm_create_gidinfo()
68307c478bd9Sstevel@tonic-gate 		 */
68317c478bd9Sstevel@tonic-gate 		nr = ibdm_get_node_records(port->pa_sa_hdl, &nr_len,
68327c478bd9Sstevel@tonic-gate 		    gidinfo->gl_nodeguid);
68337c478bd9Sstevel@tonic-gate 		if (nr == NULL) {
68347c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L4(ibdm_string,
68357c478bd9Sstevel@tonic-gate 			    "\treset_gidinfo : no records");
68367c478bd9Sstevel@tonic-gate 			continue;
68377c478bd9Sstevel@tonic-gate 		}
68387c478bd9Sstevel@tonic-gate 
68397c478bd9Sstevel@tonic-gate 		nrecords = (nr_len / sizeof (sa_node_record_t));
68407c478bd9Sstevel@tonic-gate 		for (tmp = nr, ii = 0;  (ii < nrecords); ii++, tmp++) {
68417c478bd9Sstevel@tonic-gate 			if (tmp->NodeInfo.PortGUID == gidinfo->gl_portguid)
68427c478bd9Sstevel@tonic-gate 				break;
68437c478bd9Sstevel@tonic-gate 		}
68447c478bd9Sstevel@tonic-gate 
68457c478bd9Sstevel@tonic-gate 		if (ii == nrecords) {
68467c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L4(ibdm_string,
68477c478bd9Sstevel@tonic-gate 			    "\treset_gidinfo : no record for portguid");
68487c478bd9Sstevel@tonic-gate 			kmem_free(nr, nr_len);
68497c478bd9Sstevel@tonic-gate 			continue;
68507c478bd9Sstevel@tonic-gate 		}
68517c478bd9Sstevel@tonic-gate 
68527c478bd9Sstevel@tonic-gate 		pi = ibdm_get_portinfo(port->pa_sa_hdl, &pi_len, tmp->LID);
68537c478bd9Sstevel@tonic-gate 		if (pi == NULL) {
68547c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L4(ibdm_string,
68557c478bd9Sstevel@tonic-gate 			    "\treset_gidinfo : no portinfo");
68567c478bd9Sstevel@tonic-gate 			kmem_free(nr, nr_len);
68577c478bd9Sstevel@tonic-gate 			continue;
68587c478bd9Sstevel@tonic-gate 		}
68597c478bd9Sstevel@tonic-gate 
68607c478bd9Sstevel@tonic-gate 		sgid.gid_prefix = port->pa_sn_prefix;
68617c478bd9Sstevel@tonic-gate 		sgid.gid_guid = port->pa_port_guid;
68627c478bd9Sstevel@tonic-gate 		dgid.gid_prefix = pi->PortInfo.GidPrefix;
68637c478bd9Sstevel@tonic-gate 		dgid.gid_guid = tmp->NodeInfo.PortGUID;
68647c478bd9Sstevel@tonic-gate 
68657c478bd9Sstevel@tonic-gate 		ret = ibmf_saa_gid_to_pathrecords(port->pa_sa_hdl, sgid, dgid,
68667c478bd9Sstevel@tonic-gate 		    IBMF_SAA_PKEY_WC, 0, B_TRUE, &npaths, 0, &path_len, &path);
68677c478bd9Sstevel@tonic-gate 
6868e4ac07a3Shiremath 		if ((ret != IBMF_SUCCESS) || path == NULL) {
68697c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L4(ibdm_string,
68707c478bd9Sstevel@tonic-gate 			    "\treset_gidinfo : no paths");
68717c478bd9Sstevel@tonic-gate 			kmem_free(pi, pi_len);
68727c478bd9Sstevel@tonic-gate 			kmem_free(nr, nr_len);
68737c478bd9Sstevel@tonic-gate 			continue;
68747c478bd9Sstevel@tonic-gate 		}
68757c478bd9Sstevel@tonic-gate 
68767c478bd9Sstevel@tonic-gate 		gidinfo->gl_dgid_hi	= path->DGID.gid_prefix;
68777c478bd9Sstevel@tonic-gate 		gidinfo->gl_dgid_lo	= path->DGID.gid_guid;
68787c478bd9Sstevel@tonic-gate 		gidinfo->gl_sgid_hi	= path->SGID.gid_prefix;
68797c478bd9Sstevel@tonic-gate 		gidinfo->gl_sgid_lo	= path->SGID.gid_guid;
6880a1e3386eShiremath 		gidinfo->gl_p_key	= path->P_Key;
6881a1e3386eShiremath 		gidinfo->gl_sa_hdl	= port->pa_sa_hdl;
68827c478bd9Sstevel@tonic-gate 		gidinfo->gl_ibmf_hdl	= port->pa_ibmf_hdl;
6883a1e3386eShiremath 		gidinfo->gl_slid	= path->SLID;
6884a1e3386eShiremath 		gidinfo->gl_dlid	= path->DLID;
68857c478bd9Sstevel@tonic-gate 		/* Reset redirect info, next MAD will set if redirected */
688618edb70cSeota 		gidinfo->gl_redirected	= 0;
688718edb70cSeota 		gidinfo->gl_devid	= (*tmp).NodeInfo.DeviceID;
688818edb70cSeota 		gidinfo->gl_SL		= path->SL;
68897c478bd9Sstevel@tonic-gate 
6890a1e3386eShiremath 		gidinfo->gl_qp_hdl = IBMF_QP_HANDLE_DEFAULT;
6891a1e3386eShiremath 		for (ii = 0; ii < port->pa_npkeys; ii++) {
6892a1e3386eShiremath 			if (port->pa_pkey_tbl == NULL)
6893a1e3386eShiremath 				break;
6894a1e3386eShiremath 
6895a1e3386eShiremath 			pkey_tbl = &port->pa_pkey_tbl[ii];
6896a1e3386eShiremath 			if ((gidinfo->gl_p_key == pkey_tbl->pt_pkey) &&
6897a1e3386eShiremath 			    (pkey_tbl->pt_qp_hdl != NULL)) {
6898a1e3386eShiremath 				gidinfo->gl_qp_hdl = pkey_tbl->pt_qp_hdl;
6899a1e3386eShiremath 				break;
6900a1e3386eShiremath 			}
6901a1e3386eShiremath 		}
6902a1e3386eShiremath 
6903a1e3386eShiremath 		if (gidinfo->gl_qp_hdl == NULL)
6904a1e3386eShiremath 			IBTF_DPRINTF_L2(ibdm_string,
6905a1e3386eShiremath 			    "\treset_gid_info: No matching Pkey");
6906a1e3386eShiremath 		else
6907a1e3386eShiremath 			gid_reinited = 1;
69087c478bd9Sstevel@tonic-gate 
69097c478bd9Sstevel@tonic-gate 		kmem_free(path, path_len);
69107c478bd9Sstevel@tonic-gate 		kmem_free(pi, pi_len);
69117c478bd9Sstevel@tonic-gate 		kmem_free(nr, nr_len);
69127c478bd9Sstevel@tonic-gate 		break;
69137c478bd9Sstevel@tonic-gate 	}
69147c478bd9Sstevel@tonic-gate 	mutex_exit(&ibdm.ibdm_hl_mutex);
69157c478bd9Sstevel@tonic-gate 
69167c478bd9Sstevel@tonic-gate 	if (!gid_reinited)
69177c478bd9Sstevel@tonic-gate 		gidinfo->gl_disconnected = 1;
69187c478bd9Sstevel@tonic-gate }
69197c478bd9Sstevel@tonic-gate 
69207c478bd9Sstevel@tonic-gate static void
ibdm_delete_gidinfo(ibdm_dp_gidinfo_t * gidinfo)69217c478bd9Sstevel@tonic-gate ibdm_delete_gidinfo(ibdm_dp_gidinfo_t *gidinfo)
69227c478bd9Sstevel@tonic-gate {
69237c478bd9Sstevel@tonic-gate 	ibdm_ioc_info_t *ioc_list;
6924cd7e9b9fSpramodbg 	int	in_gidlist = 0;
6925cd7e9b9fSpramodbg 
6926cd7e9b9fSpramodbg 	/*
6927cd7e9b9fSpramodbg 	 * Check if gidinfo has been inserted into the
6928cd7e9b9fSpramodbg 	 * ibdm_dp_gidlist_head list. gl_next or gl_prev
6929cd7e9b9fSpramodbg 	 * != NULL, if gidinfo is the list.
6930cd7e9b9fSpramodbg 	 */
6931cd7e9b9fSpramodbg 	if (gidinfo->gl_prev != NULL ||
69324f1d42a6Spramodbg 	    gidinfo->gl_next != NULL ||
69334f1d42a6Spramodbg 	    ibdm.ibdm_dp_gidlist_head == gidinfo)
6934cd7e9b9fSpramodbg 		in_gidlist = 1;
69357c478bd9Sstevel@tonic-gate 
69367c478bd9Sstevel@tonic-gate 	ioc_list = ibdm_update_ioc_gidlist(gidinfo, 0);
69377c478bd9Sstevel@tonic-gate 
69387c478bd9Sstevel@tonic-gate 	/*
69397c478bd9Sstevel@tonic-gate 	 * Remove GID from the global GID list
69407c478bd9Sstevel@tonic-gate 	 * Handle the case where all port GIDs for an
69417c478bd9Sstevel@tonic-gate 	 * IOU have been hot-removed.
69427c478bd9Sstevel@tonic-gate 	 */
69437c478bd9Sstevel@tonic-gate 	mutex_enter(&ibdm.ibdm_mutex);
69447c478bd9Sstevel@tonic-gate 	if (gidinfo->gl_iou != NULL && gidinfo->gl_ngids == 0) {
69457c478bd9Sstevel@tonic-gate 		mutex_enter(&gidinfo->gl_mutex);
6946add2b70bSpramodbg 		(void) ibdm_free_iou_info(gidinfo, &gidinfo->gl_iou);
69477c478bd9Sstevel@tonic-gate 		mutex_exit(&gidinfo->gl_mutex);
69487c478bd9Sstevel@tonic-gate 	}
69497c478bd9Sstevel@tonic-gate 
69504f1d42a6Spramodbg 	/* Delete gl_hca_list */
69514f1d42a6Spramodbg 	mutex_exit(&ibdm.ibdm_mutex);
69524f1d42a6Spramodbg 	ibdm_delete_glhca_list(gidinfo);
69534f1d42a6Spramodbg 	mutex_enter(&ibdm.ibdm_mutex);
69544f1d42a6Spramodbg 
6955cd7e9b9fSpramodbg 	if (in_gidlist) {
6956cd7e9b9fSpramodbg 		if (gidinfo->gl_prev != NULL)
6957cd7e9b9fSpramodbg 			gidinfo->gl_prev->gl_next = gidinfo->gl_next;
6958cd7e9b9fSpramodbg 		if (gidinfo->gl_next != NULL)
6959cd7e9b9fSpramodbg 			gidinfo->gl_next->gl_prev = gidinfo->gl_prev;
6960cd7e9b9fSpramodbg 
6961cd7e9b9fSpramodbg 		if (gidinfo == ibdm.ibdm_dp_gidlist_head)
6962cd7e9b9fSpramodbg 			ibdm.ibdm_dp_gidlist_head = gidinfo->gl_next;
6963cd7e9b9fSpramodbg 		if (gidinfo == ibdm.ibdm_dp_gidlist_tail)
6964cd7e9b9fSpramodbg 			ibdm.ibdm_dp_gidlist_tail = gidinfo->gl_prev;
6965cd7e9b9fSpramodbg 		ibdm.ibdm_ngids--;
6966cd7e9b9fSpramodbg 	}
69677c478bd9Sstevel@tonic-gate 	mutex_exit(&ibdm.ibdm_mutex);
69687c478bd9Sstevel@tonic-gate 
69697c478bd9Sstevel@tonic-gate 	mutex_destroy(&gidinfo->gl_mutex);
697053c1b7a3Seota 	cv_destroy(&gidinfo->gl_probe_cv);
69717c478bd9Sstevel@tonic-gate 	kmem_free(gidinfo, sizeof (ibdm_dp_gidinfo_t));
69727c478bd9Sstevel@tonic-gate 
69737c478bd9Sstevel@tonic-gate 	/*
69747c478bd9Sstevel@tonic-gate 	 * Pass on the IOCs with updated GIDs to IBnexus
69757c478bd9Sstevel@tonic-gate 	 */
69767c478bd9Sstevel@tonic-gate 	if (ioc_list) {
69777c478bd9Sstevel@tonic-gate 		IBTF_DPRINTF_L4("ibdm", "\tdelete_gidinfo "
69787c478bd9Sstevel@tonic-gate 		    "IOC_PROP_UPDATE for %p\n", ioc_list);
69797c478bd9Sstevel@tonic-gate 		mutex_enter(&ibdm.ibdm_ibnex_mutex);
69807c478bd9Sstevel@tonic-gate 		if (ibdm.ibdm_ibnex_callback != NULL) {
69817c478bd9Sstevel@tonic-gate 			(*ibdm.ibdm_ibnex_callback)((void *)
69827c478bd9Sstevel@tonic-gate 			    ioc_list, IBDM_EVENT_IOC_PROP_UPDATE);
69837c478bd9Sstevel@tonic-gate 		}
69847c478bd9Sstevel@tonic-gate 		mutex_exit(&ibdm.ibdm_ibnex_mutex);
69857c478bd9Sstevel@tonic-gate 	}
69867c478bd9Sstevel@tonic-gate }
69877c478bd9Sstevel@tonic-gate 
69889d3d2ed0Shiremath 
69899d3d2ed0Shiremath static void
ibdm_fill_srv_attr_mod(ib_mad_hdr_t * hdr,ibdm_timeout_cb_args_t * cb_args)69909d3d2ed0Shiremath ibdm_fill_srv_attr_mod(ib_mad_hdr_t *hdr, ibdm_timeout_cb_args_t *cb_args)
69919d3d2ed0Shiremath {
69929d3d2ed0Shiremath 	uint32_t	attr_mod;
69939d3d2ed0Shiremath 
69949d3d2ed0Shiremath 	attr_mod = (cb_args->cb_ioc_num + 1) << 16;
69959d3d2ed0Shiremath 	attr_mod |= cb_args->cb_srvents_start;
69969d3d2ed0Shiremath 	attr_mod |= (cb_args->cb_srvents_end) << 8;
69979d3d2ed0Shiremath 	hdr->AttributeModifier = h2b32(attr_mod);
69989d3d2ed0Shiremath }
69999d3d2ed0Shiremath 
70009d3d2ed0Shiremath static void
ibdm_bump_transactionID(ibdm_dp_gidinfo_t * gid_info)70019d3d2ed0Shiremath ibdm_bump_transactionID(ibdm_dp_gidinfo_t *gid_info)
70029d3d2ed0Shiremath {
70039d3d2ed0Shiremath 	ASSERT(MUTEX_HELD(&gid_info->gl_mutex));
70049d3d2ed0Shiremath 	gid_info->gl_transactionID++;
70059d3d2ed0Shiremath 	if (gid_info->gl_transactionID == gid_info->gl_max_transactionID) {
70069d3d2ed0Shiremath 		IBTF_DPRINTF_L4(ibdm_string,
70079d3d2ed0Shiremath 		    "\tbump_transactionID(%p), wrapup", gid_info);
70089d3d2ed0Shiremath 		gid_info->gl_transactionID = gid_info->gl_min_transactionID;
70099d3d2ed0Shiremath 	}
70109d3d2ed0Shiremath }
70119d3d2ed0Shiremath 
7012add2b70bSpramodbg /*
7013add2b70bSpramodbg  * gl_prev_iou is set for *non-reprobe* sweeep requests, which
7014add2b70bSpramodbg  * detected that ChangeID in IOU info has changed. The service
7015add2b70bSpramodbg  * entry also may have changed. Check if service entry in IOC
7016add2b70bSpramodbg  * has changed wrt the prev iou, if so notify to IB Nexus.
7017add2b70bSpramodbg  */
7018add2b70bSpramodbg static ibdm_ioc_info_t *
ibdm_handle_prev_iou()7019add2b70bSpramodbg ibdm_handle_prev_iou()
7020add2b70bSpramodbg {
7021add2b70bSpramodbg 	ibdm_dp_gidinfo_t *gid_info;
7022add2b70bSpramodbg 	ibdm_ioc_info_t	*ioc_list_head = NULL, *ioc_list;
7023add2b70bSpramodbg 	ibdm_ioc_info_t	*prev_ioc, *ioc;
7024add2b70bSpramodbg 	int		ii, jj, niocs, prev_niocs;
7025add2b70bSpramodbg 
7026add2b70bSpramodbg 	ASSERT(MUTEX_HELD(&ibdm.ibdm_mutex));
7027add2b70bSpramodbg 
7028add2b70bSpramodbg 	IBTF_DPRINTF_L4(ibdm_string, "\thandle_prev_iou enter");
7029add2b70bSpramodbg 	for (gid_info = ibdm.ibdm_dp_gidlist_head; gid_info;
7030add2b70bSpramodbg 	    gid_info = gid_info->gl_next) {
7031add2b70bSpramodbg 		if (gid_info->gl_prev_iou == NULL)
7032add2b70bSpramodbg 			continue;
7033add2b70bSpramodbg 
7034add2b70bSpramodbg 		IBTF_DPRINTF_L4(ibdm_string, "\thandle_prev_iou gid %p",
7035add2b70bSpramodbg 		    gid_info);
7036add2b70bSpramodbg 		niocs = gid_info->gl_iou->iou_info.iou_num_ctrl_slots;
7037add2b70bSpramodbg 		prev_niocs =
7038add2b70bSpramodbg 		    gid_info->gl_prev_iou->iou_info.iou_num_ctrl_slots;
7039add2b70bSpramodbg 		for (ii = 0; ii < niocs; ii++) {
7040add2b70bSpramodbg 			ioc = IBDM_GIDINFO2IOCINFO(gid_info, ii);
7041add2b70bSpramodbg 
7042add2b70bSpramodbg 			/* Find matching IOC */
7043add2b70bSpramodbg 			for (jj = 0; jj < prev_niocs; jj++) {
7044add2b70bSpramodbg 				prev_ioc = (ibdm_ioc_info_t *)
7045add2b70bSpramodbg 				    &gid_info->gl_prev_iou->iou_ioc_info[jj];
7046add2b70bSpramodbg 				if (prev_ioc->ioc_profile.ioc_guid ==
7047add2b70bSpramodbg 				    ioc->ioc_profile.ioc_guid)
7048add2b70bSpramodbg 					break;
7049add2b70bSpramodbg 			}
7050add2b70bSpramodbg 			if (jj == prev_niocs)
7051add2b70bSpramodbg 				prev_ioc = NULL;
7052add2b70bSpramodbg 			if (ioc == NULL || prev_ioc == NULL)
7053add2b70bSpramodbg 				continue;
7054add2b70bSpramodbg 			if ((ioc->ioc_profile.ioc_service_entries !=
7055add2b70bSpramodbg 			    prev_ioc->ioc_profile.ioc_service_entries) ||
7056add2b70bSpramodbg 			    ibdm_serv_cmp(&ioc->ioc_serv[0],
7057add2b70bSpramodbg 			    &prev_ioc->ioc_serv[0],
7058add2b70bSpramodbg 			    ioc->ioc_profile.ioc_service_entries) != 0) {
7059add2b70bSpramodbg 				IBTF_DPRINTF_L4(ibdm_string,
7060add2b70bSpramodbg 				    "/thandle_prev_iou modified IOC: "
7061add2b70bSpramodbg 				    "current ioc %p, old ioc %p",
7062add2b70bSpramodbg 				    ioc, prev_ioc);
706353c1b7a3Seota 				mutex_enter(&gid_info->gl_mutex);
7064add2b70bSpramodbg 				ioc_list = ibdm_dup_ioc_info(ioc, gid_info);
706553c1b7a3Seota 				mutex_exit(&gid_info->gl_mutex);
7066add2b70bSpramodbg 				ioc_list->ioc_info_updated.ib_prop_updated
7067add2b70bSpramodbg 				    = 0;
7068add2b70bSpramodbg 				ioc_list->ioc_info_updated.ib_srv_prop_updated
7069add2b70bSpramodbg 				    = 1;
7070add2b70bSpramodbg 
7071add2b70bSpramodbg 				if (ioc_list_head == NULL)
7072add2b70bSpramodbg 					ioc_list_head = ioc_list;
7073add2b70bSpramodbg 				else {
7074add2b70bSpramodbg 					ioc_list_head->ioc_next = ioc_list;
7075add2b70bSpramodbg 					ioc_list_head = ioc_list;
7076add2b70bSpramodbg 				}
7077add2b70bSpramodbg 			}
7078add2b70bSpramodbg 		}
7079add2b70bSpramodbg 
7080add2b70bSpramodbg 		mutex_enter(&gid_info->gl_mutex);
7081add2b70bSpramodbg 		(void) ibdm_free_iou_info(gid_info, &gid_info->gl_prev_iou);
7082add2b70bSpramodbg 		mutex_exit(&gid_info->gl_mutex);
7083add2b70bSpramodbg 	}
7084add2b70bSpramodbg 	IBTF_DPRINTF_L4(ibdm_string, "\thandle_prev_iouret %p",
7085add2b70bSpramodbg 	    ioc_list_head);
7086add2b70bSpramodbg 	return (ioc_list_head);
7087add2b70bSpramodbg }
7088add2b70bSpramodbg 
7089add2b70bSpramodbg /*
7090add2b70bSpramodbg  * Compares two service entries lists, returns 0 if same, returns 1
7091add2b70bSpramodbg  * if no match.
7092add2b70bSpramodbg  */
7093add2b70bSpramodbg static int
ibdm_serv_cmp(ibdm_srvents_info_t * serv1,ibdm_srvents_info_t * serv2,int nserv)7094add2b70bSpramodbg ibdm_serv_cmp(ibdm_srvents_info_t *serv1, ibdm_srvents_info_t *serv2,
7095add2b70bSpramodbg     int nserv)
7096add2b70bSpramodbg {
7097add2b70bSpramodbg 	int	ii;
7098add2b70bSpramodbg 
7099add2b70bSpramodbg 	IBTF_DPRINTF_L4(ibdm_string, "\tserv_cmp: enter");
7100add2b70bSpramodbg 	for (ii = 0; ii < nserv; ii++, serv1++, serv2++) {
7101add2b70bSpramodbg 		if (serv1->se_attr.srv_id != serv2->se_attr.srv_id ||
710253c1b7a3Seota 		    bcmp(serv1->se_attr.srv_name,
710353c1b7a3Seota 		    serv2->se_attr.srv_name,
710453c1b7a3Seota 		    IB_DM_MAX_SVC_NAME_LEN) != 0) {
7105add2b70bSpramodbg 			IBTF_DPRINTF_L4(ibdm_string, "\tserv_cmp: ret 1");
7106add2b70bSpramodbg 			return (1);
7107add2b70bSpramodbg 		}
7108add2b70bSpramodbg 	}
7109add2b70bSpramodbg 	IBTF_DPRINTF_L4(ibdm_string, "\tserv_cmp: ret 0");
7110add2b70bSpramodbg 	return (0);
7111add2b70bSpramodbg }
7112add2b70bSpramodbg 
71137c478bd9Sstevel@tonic-gate /* For debugging purpose only */
71147c478bd9Sstevel@tonic-gate #ifdef	DEBUG
711553c1b7a3Seota void
ibdm_dump_mad_hdr(ib_mad_hdr_t * mad_hdr)711653c1b7a3Seota ibdm_dump_mad_hdr(ib_mad_hdr_t	*mad_hdr)
711753c1b7a3Seota {
711853c1b7a3Seota 	IBTF_DPRINTF_L4("ibdm", "\t\t MAD Header info");
711953c1b7a3Seota 	IBTF_DPRINTF_L4("ibdm", "\t\t ---------------");
712053c1b7a3Seota 
712153c1b7a3Seota 	IBTF_DPRINTF_L4("ibdm", "\tBase version  : 0x%x"
712253c1b7a3Seota 	    "\tMgmt Class : 0x%x", mad_hdr->BaseVersion, mad_hdr->MgmtClass);
712353c1b7a3Seota 	IBTF_DPRINTF_L4("ibdm", "\tClass version : 0x%x"
712453c1b7a3Seota 	    "\tR Method           : 0x%x",
712553c1b7a3Seota 	    mad_hdr->ClassVersion, mad_hdr->R_Method);
712653c1b7a3Seota 	IBTF_DPRINTF_L4("ibdm", "\tMAD  Status   : 0x%x"
712753c1b7a3Seota 	    "\tTransaction ID     : 0x%llx",
712853c1b7a3Seota 	    b2h16(mad_hdr->Status), b2h64(mad_hdr->TransactionID));
712953c1b7a3Seota 	IBTF_DPRINTF_L4("ibdm", "\t Attribute ID  : 0x%x"
713053c1b7a3Seota 	    "\tAttribute Modified : 0x%lx",
713153c1b7a3Seota 	    b2h16(mad_hdr->AttributeID), b2h32(mad_hdr->AttributeModifier));
713253c1b7a3Seota }
713353c1b7a3Seota 
713453c1b7a3Seota 
71357c478bd9Sstevel@tonic-gate void
ibdm_dump_ibmf_msg(ibmf_msg_t * ibmf_msg,int flag)71367c478bd9Sstevel@tonic-gate ibdm_dump_ibmf_msg(ibmf_msg_t *ibmf_msg, int flag)
71377c478bd9Sstevel@tonic-gate {
71387c478bd9Sstevel@tonic-gate 	ib_mad_hdr_t	*mad_hdr;
71397c478bd9Sstevel@tonic-gate 
71407c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\t\t(IBMF_PKT): Local address info");
71417c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\t\t            ------------------");
71427c478bd9Sstevel@tonic-gate 
71437c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tLocal Lid  : 0x%x\tRemote Lid : 0x%x"
71447c478bd9Sstevel@tonic-gate 	    " Remote Qp  : 0x%x", ibmf_msg->im_local_addr.ia_local_lid,
71457c478bd9Sstevel@tonic-gate 	    ibmf_msg->im_local_addr.ia_remote_lid,
71467c478bd9Sstevel@tonic-gate 	    ibmf_msg->im_local_addr.ia_remote_qno);
714718edb70cSeota 	IBTF_DPRINTF_L4("ibdm", "\tP_key      : 0x%x\tQ_key      : 0x%x"
714818edb70cSeota 	    " SL  : 0x%x", ibmf_msg->im_local_addr.ia_p_key,
714918edb70cSeota 	    ibmf_msg->im_local_addr.ia_q_key,
715018edb70cSeota 	    ibmf_msg->im_local_addr.ia_service_level);
71517c478bd9Sstevel@tonic-gate 
71527c478bd9Sstevel@tonic-gate 	if (flag)
71537c478bd9Sstevel@tonic-gate 		mad_hdr = (ib_mad_hdr_t *)IBDM_OUT_IBMFMSG_MADHDR(ibmf_msg);
71547c478bd9Sstevel@tonic-gate 	else
71557c478bd9Sstevel@tonic-gate 		mad_hdr = IBDM_IN_IBMFMSG_MADHDR(ibmf_msg);
71567c478bd9Sstevel@tonic-gate 
715753c1b7a3Seota 	ibdm_dump_mad_hdr(mad_hdr);
71587c478bd9Sstevel@tonic-gate }
71597c478bd9Sstevel@tonic-gate 
716018edb70cSeota 
71617c478bd9Sstevel@tonic-gate void
ibdm_dump_path_info(sa_path_record_t * path)71627c478bd9Sstevel@tonic-gate ibdm_dump_path_info(sa_path_record_t *path)
71637c478bd9Sstevel@tonic-gate {
71647c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\t\t Path information");
71657c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\t\t ----------------");
71667c478bd9Sstevel@tonic-gate 
71677c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\t DGID hi  : %llx\tDGID lo  : %llx",
71687c478bd9Sstevel@tonic-gate 	    path->DGID.gid_prefix, path->DGID.gid_guid);
71697c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\t SGID hi  : %llx\tSGID lo  : %llx",
71707c478bd9Sstevel@tonic-gate 	    path->SGID.gid_prefix, path->SGID.gid_guid);
717118edb70cSeota 	IBTF_DPRINTF_L4("ibdm", "\t SLID     : %x\t\tDlID     : %x",
71727c478bd9Sstevel@tonic-gate 	    path->SLID, path->DLID);
717318edb70cSeota 	IBTF_DPRINTF_L4("ibdm", "\t P Key    : %x\t\tSL       : %x",
717418edb70cSeota 	    path->P_Key, path->SL);
71757c478bd9Sstevel@tonic-gate }
71767c478bd9Sstevel@tonic-gate 
71777c478bd9Sstevel@tonic-gate 
71787c478bd9Sstevel@tonic-gate void
ibdm_dump_classportinfo(ib_mad_classportinfo_t * classportinfo)717953c1b7a3Seota ibdm_dump_classportinfo(ib_mad_classportinfo_t *classportinfo)
71807c478bd9Sstevel@tonic-gate {
71817c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\t\t CLASSPORT INFO");
71827c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\t\t --------------");
71837c478bd9Sstevel@tonic-gate 
71847c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\t Response Time Value : 0x%x",
71857c478bd9Sstevel@tonic-gate 	    ((b2h32(classportinfo->RespTimeValue)) & 0x1F));
71867c478bd9Sstevel@tonic-gate 
718753c1b7a3Seota 	IBTF_DPRINTF_L4("ibdm", "\t Redirected GID hi   : 0x%llx",
71887c478bd9Sstevel@tonic-gate 	    b2h64(classportinfo->RedirectGID_hi));
718953c1b7a3Seota 	IBTF_DPRINTF_L4("ibdm", "\t Redirected GID lo   : 0x%llx",
71907c478bd9Sstevel@tonic-gate 	    b2h64(classportinfo->RedirectGID_lo));
719118edb70cSeota 	IBTF_DPRINTF_L4("ibdm", "\t Redirected TC       : 0x%x",
719218edb70cSeota 	    classportinfo->RedirectTC);
719318edb70cSeota 	IBTF_DPRINTF_L4("ibdm", "\t Redirected SL       : 0x%x",
719418edb70cSeota 	    classportinfo->RedirectSL);
719518edb70cSeota 	IBTF_DPRINTF_L4("ibdm", "\t Redirected FL       : 0x%x",
719618edb70cSeota 	    classportinfo->RedirectFL);
719718edb70cSeota 	IBTF_DPRINTF_L4("ibdm", "\t Redirected LID      : 0x%x",
719818edb70cSeota 	    b2h16(classportinfo->RedirectLID));
719918edb70cSeota 	IBTF_DPRINTF_L4("ibdm", "\t Redirected P KEY    : 0x%x",
720018edb70cSeota 	    b2h16(classportinfo->RedirectP_Key));
720118edb70cSeota 	IBTF_DPRINTF_L4("ibdm", "\t Redirected QP       : 0x%x",
720218edb70cSeota 	    classportinfo->RedirectQP);
720318edb70cSeota 	IBTF_DPRINTF_L4("ibdm", "\t Redirected Q KEY    : 0x%x",
720418edb70cSeota 	    b2h32(classportinfo->RedirectQ_Key));
720518edb70cSeota 	IBTF_DPRINTF_L4("ibdm", "\t Trap GID hi         : 0x%llx",
720653c1b7a3Seota 	    b2h64(classportinfo->TrapGID_hi));
720718edb70cSeota 	IBTF_DPRINTF_L4("ibdm", "\t Trap GID lo         : 0x%llx",
720853c1b7a3Seota 	    b2h64(classportinfo->TrapGID_lo));
720918edb70cSeota 	IBTF_DPRINTF_L4("ibdm", "\t Trap TC             : 0x%x",
721018edb70cSeota 	    classportinfo->TrapTC);
721118edb70cSeota 	IBTF_DPRINTF_L4("ibdm", "\t Trap SL             : 0x%x",
721218edb70cSeota 	    classportinfo->TrapSL);
721318edb70cSeota 	IBTF_DPRINTF_L4("ibdm", "\t Trap FL             : 0x%x",
721418edb70cSeota 	    classportinfo->TrapFL);
721518edb70cSeota 	IBTF_DPRINTF_L4("ibdm", "\t Trap LID            : 0x%x",
721653c1b7a3Seota 	    b2h16(classportinfo->TrapLID));
721718edb70cSeota 	IBTF_DPRINTF_L4("ibdm", "\t Trap P_Key          : 0x%x",
721853c1b7a3Seota 	    b2h16(classportinfo->TrapP_Key));
721918edb70cSeota 	IBTF_DPRINTF_L4("ibdm", "\t Trap HL             : 0x%x",
722018edb70cSeota 	    classportinfo->TrapHL);
722118edb70cSeota 	IBTF_DPRINTF_L4("ibdm", "\t Trap QP             : 0x%x",
722218edb70cSeota 	    classportinfo->TrapQP);
722318edb70cSeota 	IBTF_DPRINTF_L4("ibdm", "\t Trap Q_Key          : 0x%x",
722453c1b7a3Seota 	    b2h32(classportinfo->TrapQ_Key));
72257c478bd9Sstevel@tonic-gate }
72267c478bd9Sstevel@tonic-gate 
72277c478bd9Sstevel@tonic-gate 
72287c478bd9Sstevel@tonic-gate void
ibdm_dump_iounitinfo(ib_dm_io_unitinfo_t * iou_info)72297c478bd9Sstevel@tonic-gate ibdm_dump_iounitinfo(ib_dm_io_unitinfo_t *iou_info)
72307c478bd9Sstevel@tonic-gate {
72317c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\t\t I/O UnitInfo");
72327c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\t\t ------------");
72337c478bd9Sstevel@tonic-gate 
72347c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tChange ID            : 0x%x",
72357c478bd9Sstevel@tonic-gate 	    b2h16(iou_info->iou_changeid));
72367c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\t#of ctrl slots       : %d",
72377c478bd9Sstevel@tonic-gate 	    iou_info->iou_num_ctrl_slots);
72387c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tIOU flag             : 0x%x",
72397c478bd9Sstevel@tonic-gate 	    iou_info->iou_flag);
72407c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tContrl list byte 0   : 0x%x",
72417c478bd9Sstevel@tonic-gate 	    iou_info->iou_ctrl_list[0]);
72427c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tContrl list byte 1   : 0x%x",
72437c478bd9Sstevel@tonic-gate 	    iou_info->iou_ctrl_list[1]);
72447c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tContrl list byte 2   : 0x%x",
72457c478bd9Sstevel@tonic-gate 	    iou_info->iou_ctrl_list[2]);
72467c478bd9Sstevel@tonic-gate }
72477c478bd9Sstevel@tonic-gate 
72487c478bd9Sstevel@tonic-gate 
72497c478bd9Sstevel@tonic-gate void
ibdm_dump_ioc_profile(ib_dm_ioc_ctrl_profile_t * ioc)72507c478bd9Sstevel@tonic-gate ibdm_dump_ioc_profile(ib_dm_ioc_ctrl_profile_t *ioc)
72517c478bd9Sstevel@tonic-gate {
72527c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\t\t IOC Controller Profile");
72537c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\t\t ----------------------");
72547c478bd9Sstevel@tonic-gate 
72557c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tIOC Guid    : %llx", ioc->ioc_guid);
72567c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tVendorID    : 0x%x", ioc->ioc_vendorid);
72577c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tDevice Id   : 0x%x", ioc->ioc_deviceid);
72587c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tDevice Ver  : 0x%x", ioc->ioc_device_ver);
72597c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tSubsys ID   : 0x%x", ioc->ioc_subsys_id);
72607c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tIO class    : 0x%x", ioc->ioc_io_class);
72617c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tIO subclass : 0x%x", ioc->ioc_io_subclass);
72627c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tProtocol    : 0x%x", ioc->ioc_protocol);
72637c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tProtocolV   : 0x%x", ioc->ioc_protocol_ver);
72647c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tmsg qdepth  : %d", ioc->ioc_send_msg_qdepth);
72657c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\trdma qdepth : %d",
726653c1b7a3Seota 	    ioc->ioc_rdma_read_qdepth);
72677c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tsndmsg sz   : %d", ioc->ioc_send_msg_sz);
72687c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\trdma xfersz : %d", ioc->ioc_rdma_xfer_sz);
72697c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\topcal mask  : 0x%x",
727053c1b7a3Seota 	    ioc->ioc_ctrl_opcap_mask);
72717c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\tsrventries  : %x", ioc->ioc_service_entries);
72727c478bd9Sstevel@tonic-gate }
72737c478bd9Sstevel@tonic-gate 
72747c478bd9Sstevel@tonic-gate 
72757c478bd9Sstevel@tonic-gate void
ibdm_dump_service_entries(ib_dm_srv_t * srv_ents)72767c478bd9Sstevel@tonic-gate ibdm_dump_service_entries(ib_dm_srv_t *srv_ents)
72777c478bd9Sstevel@tonic-gate {
72787c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm",
72797c478bd9Sstevel@tonic-gate 	    "\thandle_srventry_mad: service id : %llx", srv_ents->srv_id);
72807c478bd9Sstevel@tonic-gate 
72817c478bd9Sstevel@tonic-gate 	IBTF_DPRINTF_L4("ibdm", "\thandle_srventry_mad: "
72827c478bd9Sstevel@tonic-gate 	    "Service Name : %s", srv_ents->srv_name);
72837c478bd9Sstevel@tonic-gate }
72847c478bd9Sstevel@tonic-gate 
72857c478bd9Sstevel@tonic-gate int ibdm_allow_sweep_fabric_timestamp = 1;
72867c478bd9Sstevel@tonic-gate 
72877c478bd9Sstevel@tonic-gate void
ibdm_dump_sweep_fabric_timestamp(int flag)72887c478bd9Sstevel@tonic-gate ibdm_dump_sweep_fabric_timestamp(int flag)
72897c478bd9Sstevel@tonic-gate {
72907c478bd9Sstevel@tonic-gate 	static hrtime_t x;
72917c478bd9Sstevel@tonic-gate 	if (flag) {
72927c478bd9Sstevel@tonic-gate 		if (ibdm_allow_sweep_fabric_timestamp) {
72937c478bd9Sstevel@tonic-gate 			IBTF_DPRINTF_L4("ibdm", "\tTime taken to complete "
72947c478bd9Sstevel@tonic-gate 			    "sweep %lld ms", ((gethrtime() - x)/ 1000000));
72957c478bd9Sstevel@tonic-gate 		}
72967c478bd9Sstevel@tonic-gate 		x = 0;
72977c478bd9Sstevel@tonic-gate 	} else
72987c478bd9Sstevel@tonic-gate 		x = gethrtime();
72997c478bd9Sstevel@tonic-gate }
73007c478bd9Sstevel@tonic-gate #endif
7301