1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate /* 28*0Sstevel@tonic-gate * The InfiniBand Nexus driver (IB nexus) is a bus nexus driver for IB bus. 29*0Sstevel@tonic-gate * It supports Port nodes, Virtual Physical Point of Attachment nodes (VPPA) 30*0Sstevel@tonic-gate * for HCAs registered with IBTL and IOC nodes for all the IOCs present in 31*0Sstevel@tonic-gate * the IB fabric (that are accessible to the host). It also supports Pseudo 32*0Sstevel@tonic-gate * device children to be enumerated using their .conf file(s). All Port nodes 33*0Sstevel@tonic-gate * and VPPA nodes are children of HCA drivers. All the IOC nodes and the Pseudo 34*0Sstevel@tonic-gate * device nodes are children of the IB nexus driver. 35*0Sstevel@tonic-gate * 36*0Sstevel@tonic-gate * IB nexus driver provides bus nexus entry points to all the HCA drivers. 37*0Sstevel@tonic-gate * 38*0Sstevel@tonic-gate * IB nexus driver registers with InfiniBand Device Manager (IBDM) to get 39*0Sstevel@tonic-gate * information about all the HCA ports and I/O Controllers (IOCs) connected 40*0Sstevel@tonic-gate * to the IB fabric. Based on that information, IB nexus will create all the 41*0Sstevel@tonic-gate * device tree nodes. 42*0Sstevel@tonic-gate */ 43*0Sstevel@tonic-gate 44*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 45*0Sstevel@tonic-gate 46*0Sstevel@tonic-gate 47*0Sstevel@tonic-gate #include <sys/conf.h> 48*0Sstevel@tonic-gate #include <sys/stat.h> 49*0Sstevel@tonic-gate #include <sys/modctl.h> 50*0Sstevel@tonic-gate #include <sys/taskq.h> 51*0Sstevel@tonic-gate #include <sys/mdi_impldefs.h> 52*0Sstevel@tonic-gate #include <sys/sunmdi.h> 53*0Sstevel@tonic-gate #include <sys/sunpm.h> 54*0Sstevel@tonic-gate #include <sys/ib/mgt/ibdm/ibdm_impl.h> 55*0Sstevel@tonic-gate #include <sys/ib/ibnex/ibnex.h> 56*0Sstevel@tonic-gate #include <sys/ib/ibnex/ibnex_devctl.h> 57*0Sstevel@tonic-gate #include <sys/ib/ibtl/ibti.h> 58*0Sstevel@tonic-gate #include <sys/ib/ibtl/impl/ibtl_ibnex.h> 59*0Sstevel@tonic-gate #include <sys/file.h> 60*0Sstevel@tonic-gate #include <sys/hwconf.h> 61*0Sstevel@tonic-gate 62*0Sstevel@tonic-gate /* Function prototypes */ 63*0Sstevel@tonic-gate static int ibnex_attach(dev_info_t *, ddi_attach_cmd_t); 64*0Sstevel@tonic-gate static int ibnex_getinfo(dev_info_t *, ddi_info_cmd_t, 65*0Sstevel@tonic-gate void *, void **); 66*0Sstevel@tonic-gate static int ibnex_detach(dev_info_t *, ddi_detach_cmd_t); 67*0Sstevel@tonic-gate static int ibnex_busctl(dev_info_t *, 68*0Sstevel@tonic-gate dev_info_t *, ddi_ctl_enum_t, void *, void *); 69*0Sstevel@tonic-gate static int ibnex_map_fault(dev_info_t *, 70*0Sstevel@tonic-gate dev_info_t *, struct hat *, struct seg *, 71*0Sstevel@tonic-gate caddr_t, struct devpage *, pfn_t, uint_t, uint_t); 72*0Sstevel@tonic-gate static int ibnex_init_child(dev_info_t *); 73*0Sstevel@tonic-gate static ibnex_rval_t ibnex_comm_svc_init(char *, ibnex_node_type_t); 74*0Sstevel@tonic-gate static void ibnex_comm_svc_fini(); 75*0Sstevel@tonic-gate dev_info_t *ibnex_commsvc_initnode(dev_info_t *, 76*0Sstevel@tonic-gate ibdm_port_attr_t *, int, int, ib_pkey_t, int *, 77*0Sstevel@tonic-gate int); 78*0Sstevel@tonic-gate static void ibnex_delete_port_node_data(ibnex_node_data_t *); 79*0Sstevel@tonic-gate int ibnex_get_dip_from_guid(ib_guid_t, int, 80*0Sstevel@tonic-gate ib_pkey_t, dev_info_t **); 81*0Sstevel@tonic-gate static ibnex_node_data_t *ibnex_is_node_data_present(ibnex_node_type_t, 82*0Sstevel@tonic-gate void *, int, ib_pkey_t); 83*0Sstevel@tonic-gate static ibnex_node_data_t *ibnex_init_child_nodedata(ibnex_node_type_t, void *, 84*0Sstevel@tonic-gate int, ib_pkey_t); 85*0Sstevel@tonic-gate static int ibnex_create_port_node_prop(ibdm_port_attr_t *, 86*0Sstevel@tonic-gate dev_info_t *, char *, ib_pkey_t); 87*0Sstevel@tonic-gate void ibnex_dm_callback(void *, ibdm_events_t); 88*0Sstevel@tonic-gate static int ibnex_create_port_compatible_prop(dev_info_t *, 89*0Sstevel@tonic-gate char *, ibdm_port_attr_t *); 90*0Sstevel@tonic-gate static int ibnex_create_ioc_srv_props( 91*0Sstevel@tonic-gate dev_info_t *, ibdm_ioc_info_t *); 92*0Sstevel@tonic-gate static int ibnex_get_eventcookie(dev_info_t *, 93*0Sstevel@tonic-gate dev_info_t *, char *, ddi_eventcookie_t *); 94*0Sstevel@tonic-gate static int ibnex_add_eventcall(dev_info_t *, dev_info_t *, 95*0Sstevel@tonic-gate ddi_eventcookie_t, void (*)(dev_info_t *, 96*0Sstevel@tonic-gate ddi_eventcookie_t, void *, void *), 97*0Sstevel@tonic-gate void *arg, ddi_callback_id_t *cb_id); 98*0Sstevel@tonic-gate static int ibnex_remove_eventcall(dev_info_t *, 99*0Sstevel@tonic-gate ddi_callback_id_t); 100*0Sstevel@tonic-gate static int ibnex_post_event(dev_info_t *, dev_info_t *, 101*0Sstevel@tonic-gate ddi_eventcookie_t, void *); 102*0Sstevel@tonic-gate static int ibnex_bus_config(dev_info_t *, uint_t, 103*0Sstevel@tonic-gate ddi_bus_config_op_t, void *, dev_info_t **); 104*0Sstevel@tonic-gate static int ibnex_bus_unconfig(dev_info_t *, 105*0Sstevel@tonic-gate uint_t, ddi_bus_config_op_t, void *); 106*0Sstevel@tonic-gate static dev_info_t *ibnex_config_port_node(dev_info_t *, char *); 107*0Sstevel@tonic-gate static dev_info_t *ibnex_config_obp_args(dev_info_t *, char *); 108*0Sstevel@tonic-gate static int ibnex_get_pkey_commsvc_index_portnum( 109*0Sstevel@tonic-gate char *, int *, ib_pkey_t *, uint8_t *); 110*0Sstevel@tonic-gate static void ibnex_config_all_children(dev_info_t *); 111*0Sstevel@tonic-gate static int ibnex_devname_to_portnum(char *, uint8_t *); 112*0Sstevel@tonic-gate static void ibnex_create_vppa_nodes( 113*0Sstevel@tonic-gate dev_info_t *, ibdm_port_attr_t *); 114*0Sstevel@tonic-gate static void ibnex_create_port_nodes( 115*0Sstevel@tonic-gate dev_info_t *, ibdm_port_attr_t *); 116*0Sstevel@tonic-gate static void ibnex_create_hcasvc_nodes( 117*0Sstevel@tonic-gate dev_info_t *, ibdm_port_attr_t *); 118*0Sstevel@tonic-gate static int ibnex_config_root_iocnode(dev_info_t *, char *); 119*0Sstevel@tonic-gate static int ibnex_devname2port(char *, int *); 120*0Sstevel@tonic-gate static int ibnex_config_ioc_node(char *); 121*0Sstevel@tonic-gate static int ibnex_devname_to_node_n_ioc_guids( 122*0Sstevel@tonic-gate char *, ib_guid_t *, ib_guid_t *); 123*0Sstevel@tonic-gate static int ibnex_is_ioc_present(ib_guid_t); 124*0Sstevel@tonic-gate static void ibnex_ioc_node_cleanup(); 125*0Sstevel@tonic-gate static void ibnex_delete_ioc_node_data(ibnex_node_data_t *); 126*0Sstevel@tonic-gate int ibnex_ioc_initnode(ibdm_ioc_info_t *, int); 127*0Sstevel@tonic-gate static int ibnex_create_ioc_node_prop( 128*0Sstevel@tonic-gate ibdm_ioc_info_t *, dev_info_t *); 129*0Sstevel@tonic-gate static int ibnex_create_ioc_compatible_prop( 130*0Sstevel@tonic-gate dev_info_t *, ib_dm_ioc_ctrl_profile_t *); 131*0Sstevel@tonic-gate uint64_t ibnex_str2hex(char *, int, int *); 132*0Sstevel@tonic-gate static int ibnex_str2int(char *, int, int *); 133*0Sstevel@tonic-gate static int ibnex_create_ioc_portgid_prop( 134*0Sstevel@tonic-gate dev_info_t *, ibdm_ioc_info_t *); 135*0Sstevel@tonic-gate static void ibnex_wakeup_reprobe_ioc(ibnex_node_data_t *, int); 136*0Sstevel@tonic-gate static void ibnex_wakeup_reprobe_all(); 137*0Sstevel@tonic-gate ibt_status_t ibnex_ibtl_callback(ibtl_ibnex_cb_args_t *); 138*0Sstevel@tonic-gate static int ibnex_prom_devname_to_pkey_n_portnum( 139*0Sstevel@tonic-gate char *, ib_pkey_t *, uint8_t *); 140*0Sstevel@tonic-gate void ibnex_pseudo_initnodes(void); 141*0Sstevel@tonic-gate static char *ibnex_lookup_unit_address_prop(ddi_prop_t *); 142*0Sstevel@tonic-gate static void ibnex_pseudo_node_cleanup(void); 143*0Sstevel@tonic-gate static int ibnex_name_child(dev_info_t *, char *, int); 144*0Sstevel@tonic-gate static int ibnex_name_pseudo_child(dev_info_t *, char *); 145*0Sstevel@tonic-gate 146*0Sstevel@tonic-gate void ibnex_reprobe_ioc_dev(void *); 147*0Sstevel@tonic-gate void ibnex_reprobe_ioc_all(); 148*0Sstevel@tonic-gate static void ibnex_update_prop(ibnex_node_data_t *, 149*0Sstevel@tonic-gate ibdm_ioc_info_t *); 150*0Sstevel@tonic-gate static ibnex_rval_t ibnex_unique_svcname(char *); 151*0Sstevel@tonic-gate static void ibnex_handle_reprobe_dev(void *arg); 152*0Sstevel@tonic-gate 153*0Sstevel@tonic-gate extern int ibnex_open(dev_t *, int, int, cred_t *); 154*0Sstevel@tonic-gate extern int ibnex_close(dev_t, int, int, cred_t *); 155*0Sstevel@tonic-gate extern int ibnex_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); 156*0Sstevel@tonic-gate extern int ibnex_offline_childdip(dev_info_t *); 157*0Sstevel@tonic-gate 158*0Sstevel@tonic-gate static int ibnex_ioc_create_pi( 159*0Sstevel@tonic-gate ibdm_ioc_info_t *, ibnex_node_data_t *); 160*0Sstevel@tonic-gate static int ibnex_bus_power(dev_info_t *, void *, 161*0Sstevel@tonic-gate pm_bus_power_op_t, void *, void *); 162*0Sstevel@tonic-gate int ibnex_pseudo_create_pi(ibnex_node_data_t *); 163*0Sstevel@tonic-gate int ibnex_pseudo_config_one( 164*0Sstevel@tonic-gate ibnex_node_data_t *, char *, char *); 165*0Sstevel@tonic-gate static void ibnex_config_pseudo_all(void); 166*0Sstevel@tonic-gate /* 167*0Sstevel@tonic-gate * The bus_ops structure defines the capabilities of HCA nexus driver. 168*0Sstevel@tonic-gate */ 169*0Sstevel@tonic-gate struct bus_ops ibnex_ci_busops = { 170*0Sstevel@tonic-gate BUSO_REV, 171*0Sstevel@tonic-gate nullbusmap, /* bus_map */ 172*0Sstevel@tonic-gate NULL, /* bus_get_intrspec */ 173*0Sstevel@tonic-gate NULL, /* bus_add_intrspec */ 174*0Sstevel@tonic-gate NULL, /* bus_remove_intrspec */ 175*0Sstevel@tonic-gate ibnex_map_fault, /* Map Fault */ 176*0Sstevel@tonic-gate ddi_no_dma_map, /* DMA related entry points */ 177*0Sstevel@tonic-gate NULL, 178*0Sstevel@tonic-gate NULL, 179*0Sstevel@tonic-gate NULL, 180*0Sstevel@tonic-gate NULL, 181*0Sstevel@tonic-gate NULL, 182*0Sstevel@tonic-gate NULL, 183*0Sstevel@tonic-gate NULL, 184*0Sstevel@tonic-gate ibnex_busctl, /* bus_ctl */ 185*0Sstevel@tonic-gate ddi_bus_prop_op, /* bus_prop_op */ 186*0Sstevel@tonic-gate NULL, /* bus_get_eventcookie */ 187*0Sstevel@tonic-gate NULL, /* bus_add_eventcall */ 188*0Sstevel@tonic-gate NULL, /* bus_remove_eventcall */ 189*0Sstevel@tonic-gate NULL, /* bus_post_event */ 190*0Sstevel@tonic-gate NULL, 191*0Sstevel@tonic-gate ibnex_bus_config, /* bus config */ 192*0Sstevel@tonic-gate ibnex_bus_unconfig /* bus unconfig */ 193*0Sstevel@tonic-gate }; 194*0Sstevel@tonic-gate 195*0Sstevel@tonic-gate 196*0Sstevel@tonic-gate /* 197*0Sstevel@tonic-gate * Prototype declarations for the VHCI options 198*0Sstevel@tonic-gate */ 199*0Sstevel@tonic-gate /* 200*0Sstevel@tonic-gate * Functions registered with the mpxio framework 201*0Sstevel@tonic-gate */ 202*0Sstevel@tonic-gate static int ib_vhci_pi_init(dev_info_t *, mdi_pathinfo_t *, int); 203*0Sstevel@tonic-gate static int ib_vhci_pi_uninit(dev_info_t *, mdi_pathinfo_t *, int); 204*0Sstevel@tonic-gate static int ib_vhci_pi_state_change(dev_info_t *, mdi_pathinfo_t *, 205*0Sstevel@tonic-gate mdi_pathinfo_state_t, uint32_t, int); 206*0Sstevel@tonic-gate static int ib_vhci_failover(dev_info_t *, dev_info_t *, int); 207*0Sstevel@tonic-gate 208*0Sstevel@tonic-gate 209*0Sstevel@tonic-gate static mdi_vhci_ops_t ibnex_vhci_ops = { 210*0Sstevel@tonic-gate MDI_VHCI_OPS_REV, 211*0Sstevel@tonic-gate ib_vhci_pi_init, 212*0Sstevel@tonic-gate ib_vhci_pi_uninit, 213*0Sstevel@tonic-gate ib_vhci_pi_state_change, 214*0Sstevel@tonic-gate ib_vhci_failover 215*0Sstevel@tonic-gate }; 216*0Sstevel@tonic-gate 217*0Sstevel@tonic-gate 218*0Sstevel@tonic-gate /* 219*0Sstevel@tonic-gate * The bus_ops structure defines the capabilities of IB nexus driver. 220*0Sstevel@tonic-gate * IB nexus drivers does not support any DMA operations for its children 221*0Sstevel@tonic-gate * as there is no such concept in Infiniband. All the memory operations 222*0Sstevel@tonic-gate * and DMA operations required by the child drivers can be performed using 223*0Sstevel@tonic-gate * the IBTF API. 224*0Sstevel@tonic-gate */ 225*0Sstevel@tonic-gate struct bus_ops ibnex_bus_ops = { 226*0Sstevel@tonic-gate BUSO_REV, 227*0Sstevel@tonic-gate nullbusmap, /* bus_map */ 228*0Sstevel@tonic-gate NULL, /* bus_get_intrspec */ 229*0Sstevel@tonic-gate NULL, /* bus_add_intrspec */ 230*0Sstevel@tonic-gate NULL, /* bus_remove_intrspec */ 231*0Sstevel@tonic-gate ibnex_map_fault, /* Map Fault */ 232*0Sstevel@tonic-gate ddi_no_dma_map, /* DMA related entry points */ 233*0Sstevel@tonic-gate ddi_no_dma_allochdl, 234*0Sstevel@tonic-gate NULL, 235*0Sstevel@tonic-gate NULL, 236*0Sstevel@tonic-gate NULL, 237*0Sstevel@tonic-gate NULL, 238*0Sstevel@tonic-gate NULL, 239*0Sstevel@tonic-gate NULL, 240*0Sstevel@tonic-gate ibnex_busctl, /* bus_ctl */ 241*0Sstevel@tonic-gate ddi_bus_prop_op, /* bus_prop_op */ 242*0Sstevel@tonic-gate ibnex_get_eventcookie, /* bus_get_eventcookie */ 243*0Sstevel@tonic-gate ibnex_add_eventcall, /* bus_add_eventcall */ 244*0Sstevel@tonic-gate ibnex_remove_eventcall, /* bus_remove_eventcall */ 245*0Sstevel@tonic-gate ibnex_post_event, /* bus_post_event */ 246*0Sstevel@tonic-gate NULL, 247*0Sstevel@tonic-gate ibnex_bus_config, /* bus config */ 248*0Sstevel@tonic-gate ibnex_bus_unconfig, /* bus unconfig */ 249*0Sstevel@tonic-gate NULL, /* bus fm init */ 250*0Sstevel@tonic-gate NULL, /* bus fm fini */ 251*0Sstevel@tonic-gate NULL, /* bus fm access enter */ 252*0Sstevel@tonic-gate NULL, /* bus fm access exit */ 253*0Sstevel@tonic-gate ibnex_bus_power /* bus power */ 254*0Sstevel@tonic-gate }; 255*0Sstevel@tonic-gate 256*0Sstevel@tonic-gate 257*0Sstevel@tonic-gate /* ibnex cb_ops */ 258*0Sstevel@tonic-gate static struct cb_ops ibnex_cbops = { 259*0Sstevel@tonic-gate ibnex_open, /* open */ 260*0Sstevel@tonic-gate ibnex_close, /* close */ 261*0Sstevel@tonic-gate nodev, /* strategy */ 262*0Sstevel@tonic-gate nodev, /* print */ 263*0Sstevel@tonic-gate nodev, /* dump */ 264*0Sstevel@tonic-gate nodev, /* read */ 265*0Sstevel@tonic-gate nodev, /* write */ 266*0Sstevel@tonic-gate ibnex_ioctl, /* ioctl */ 267*0Sstevel@tonic-gate nodev, /* devmap */ 268*0Sstevel@tonic-gate nodev, /* mmap */ 269*0Sstevel@tonic-gate nodev, /* segmap */ 270*0Sstevel@tonic-gate nochpoll, /* poll */ 271*0Sstevel@tonic-gate ddi_prop_op, /* prop_op */ 272*0Sstevel@tonic-gate NULL, /* stream */ 273*0Sstevel@tonic-gate D_MP, /* cb_flag */ 274*0Sstevel@tonic-gate CB_REV, /* rev */ 275*0Sstevel@tonic-gate nodev, /* int (*cb_aread)() */ 276*0Sstevel@tonic-gate nodev /* int (*cb_awrite)() */ 277*0Sstevel@tonic-gate }; 278*0Sstevel@tonic-gate 279*0Sstevel@tonic-gate /* 280*0Sstevel@tonic-gate * Device options 281*0Sstevel@tonic-gate * Note: ddi_no_info needs to change during devfs time frame. The drivers 282*0Sstevel@tonic-gate * with 1 to 1 mapping between minor node and instance should use 283*0Sstevel@tonic-gate * ddi_1to1_info. (See bug id 4424752) 284*0Sstevel@tonic-gate */ 285*0Sstevel@tonic-gate static struct dev_ops ibnex_ops = { 286*0Sstevel@tonic-gate DEVO_REV, /* devo_rev, */ 287*0Sstevel@tonic-gate 0, /* refcnt */ 288*0Sstevel@tonic-gate ibnex_getinfo, /* info */ 289*0Sstevel@tonic-gate nulldev, /* identify */ 290*0Sstevel@tonic-gate nulldev, /* probe */ 291*0Sstevel@tonic-gate ibnex_attach, /* attach */ 292*0Sstevel@tonic-gate ibnex_detach, /* detach */ 293*0Sstevel@tonic-gate nodev, /* reset */ 294*0Sstevel@tonic-gate &ibnex_cbops, /* driver ops - devctl interfaces */ 295*0Sstevel@tonic-gate &ibnex_bus_ops, /* bus operations */ 296*0Sstevel@tonic-gate nulldev /* power */ 297*0Sstevel@tonic-gate }; 298*0Sstevel@tonic-gate 299*0Sstevel@tonic-gate /* Module linkage information for the kernel. */ 300*0Sstevel@tonic-gate static struct modldrv modldrv = { 301*0Sstevel@tonic-gate &mod_driverops, /* Driver module */ 302*0Sstevel@tonic-gate "IB nexus %I%", /* Driver name and version */ 303*0Sstevel@tonic-gate &ibnex_ops, /* driver ops */ 304*0Sstevel@tonic-gate }; 305*0Sstevel@tonic-gate 306*0Sstevel@tonic-gate static struct modlinkage modlinkage = { 307*0Sstevel@tonic-gate MODREV_1, (void *)&modldrv, NULL 308*0Sstevel@tonic-gate }; 309*0Sstevel@tonic-gate 310*0Sstevel@tonic-gate /* 311*0Sstevel@tonic-gate * Global per-instance IB Nexus data. 312*0Sstevel@tonic-gate * There is only one instance of IB Nexus supported. 313*0Sstevel@tonic-gate */ 314*0Sstevel@tonic-gate ibnex_t ibnex; 315*0Sstevel@tonic-gate #ifdef __lock_lint 316*0Sstevel@tonic-gate extern ibdm_t ibdm; 317*0Sstevel@tonic-gate #endif 318*0Sstevel@tonic-gate _NOTE(MUTEX_PROTECTS_DATA(ibnex.ibnex_mutex, ibnex_s)) 319*0Sstevel@tonic-gate _NOTE(DATA_READABLE_WITHOUT_LOCK(ibnex.ibnex_num_comm_svcs 320*0Sstevel@tonic-gate ibnex.ibnex_comm_svc_names ibnex.ibnex_nvppa_comm_svcs 321*0Sstevel@tonic-gate ibnex.ibnex_vppa_comm_svc_names ibnex.ibnex_nhcasvc_comm_svcs 322*0Sstevel@tonic-gate ibnex.ibnex_hcasvc_comm_svc_names)) 323*0Sstevel@tonic-gate _NOTE(MUTEX_PROTECTS_DATA(ibnex.ibnex_mutex, ibnex_node_data_s)) 324*0Sstevel@tonic-gate _NOTE(LOCK_ORDER(ibdm.ibdm_hl_mutex ibnex.ibnex_mutex)) 325*0Sstevel@tonic-gate 326*0Sstevel@tonic-gate /* The port settling time in seconds */ 327*0Sstevel@tonic-gate int ibnex_port_settling_time = 8; 328*0Sstevel@tonic-gate 329*0Sstevel@tonic-gate /* create an array of properties supported, easier to add new ones here */ 330*0Sstevel@tonic-gate static struct ibnex_property { 331*0Sstevel@tonic-gate char *name; 332*0Sstevel@tonic-gate ibnex_node_type_t type; 333*0Sstevel@tonic-gate } ibnex_properties[] = { 334*0Sstevel@tonic-gate { "port-svc-list", IBNEX_PORT_COMMSVC_NODE}, 335*0Sstevel@tonic-gate { "vppa-svc-list", IBNEX_VPPA_COMMSVC_NODE}, 336*0Sstevel@tonic-gate { "hca-svc-list", IBNEX_HCASVC_COMMSVC_NODE} 337*0Sstevel@tonic-gate }; 338*0Sstevel@tonic-gate 339*0Sstevel@tonic-gate #define N_IBNEX_PROPS (sizeof (ibnex_properties))/ \ 340*0Sstevel@tonic-gate (sizeof (struct ibnex_property)) 341*0Sstevel@tonic-gate 342*0Sstevel@tonic-gate /* 343*0Sstevel@tonic-gate * Event Definition 344*0Sstevel@tonic-gate * Single event, event name defined in ibti_common.h. 345*0Sstevel@tonic-gate * Event posted to specific child handler. Event posted 346*0Sstevel@tonic-gate * at kernel priority. 347*0Sstevel@tonic-gate */ 348*0Sstevel@tonic-gate static ndi_event_definition_t ibnex_ndi_event_defs[] = { 349*0Sstevel@tonic-gate {IB_EVENT_TAG_PROP_UPDATE, IB_PROP_UPDATE_EVENT, EPL_KERNEL, 350*0Sstevel@tonic-gate NDI_EVENT_POST_TO_TGT} 351*0Sstevel@tonic-gate }; 352*0Sstevel@tonic-gate 353*0Sstevel@tonic-gate #define IB_N_NDI_EVENTS \ 354*0Sstevel@tonic-gate (sizeof (ibnex_ndi_event_defs) / sizeof (ndi_event_definition_t)) 355*0Sstevel@tonic-gate 356*0Sstevel@tonic-gate static ndi_event_set_t ib_ndi_events = { 357*0Sstevel@tonic-gate NDI_EVENTS_REV1, IB_N_NDI_EVENTS, ibnex_ndi_event_defs}; 358*0Sstevel@tonic-gate 359*0Sstevel@tonic-gate 360*0Sstevel@tonic-gate /* 361*0Sstevel@tonic-gate * _init 362*0Sstevel@tonic-gate * Loadable module init, called before any other module. 363*0Sstevel@tonic-gate */ 364*0Sstevel@tonic-gate int 365*0Sstevel@tonic-gate _init(void) 366*0Sstevel@tonic-gate { 367*0Sstevel@tonic-gate int error; 368*0Sstevel@tonic-gate 369*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\t_init"); 370*0Sstevel@tonic-gate mutex_init(&ibnex.ibnex_mutex, NULL, MUTEX_DRIVER, NULL); 371*0Sstevel@tonic-gate cv_init(&ibnex.ibnex_reprobe_cv, NULL, CV_DRIVER, NULL); 372*0Sstevel@tonic-gate if ((error = mod_install(&modlinkage)) != 0) { 373*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", "\t_init: mod_install failed"); 374*0Sstevel@tonic-gate mutex_destroy(&ibnex.ibnex_mutex); 375*0Sstevel@tonic-gate cv_destroy(&ibnex.ibnex_reprobe_cv); 376*0Sstevel@tonic-gate } else { 377*0Sstevel@tonic-gate ibdm_ibnex_register_callback(ibnex_dm_callback); 378*0Sstevel@tonic-gate ibtl_ibnex_register_callback(ibnex_ibtl_callback); 379*0Sstevel@tonic-gate } 380*0Sstevel@tonic-gate return (error); 381*0Sstevel@tonic-gate } 382*0Sstevel@tonic-gate 383*0Sstevel@tonic-gate 384*0Sstevel@tonic-gate /* 385*0Sstevel@tonic-gate * _fini 386*0Sstevel@tonic-gate * Prepares a module for unloading. 387*0Sstevel@tonic-gate */ 388*0Sstevel@tonic-gate int 389*0Sstevel@tonic-gate _fini(void) 390*0Sstevel@tonic-gate { 391*0Sstevel@tonic-gate int error; 392*0Sstevel@tonic-gate 393*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\t_fini"); 394*0Sstevel@tonic-gate if ((error = mod_remove(&modlinkage)) != 0) { 395*0Sstevel@tonic-gate return (error); 396*0Sstevel@tonic-gate } 397*0Sstevel@tonic-gate ibdm_ibnex_unregister_callback(); 398*0Sstevel@tonic-gate ibtl_ibnex_unregister_callback(); 399*0Sstevel@tonic-gate mutex_destroy(&ibnex.ibnex_mutex); 400*0Sstevel@tonic-gate cv_destroy(&ibnex.ibnex_reprobe_cv); 401*0Sstevel@tonic-gate return (0); 402*0Sstevel@tonic-gate } 403*0Sstevel@tonic-gate 404*0Sstevel@tonic-gate 405*0Sstevel@tonic-gate /* 406*0Sstevel@tonic-gate * _info 407*0Sstevel@tonic-gate * Returns information about loadable module. 408*0Sstevel@tonic-gate */ 409*0Sstevel@tonic-gate int 410*0Sstevel@tonic-gate _info(struct modinfo *modinfop) 411*0Sstevel@tonic-gate { 412*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\t_info"); 413*0Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 414*0Sstevel@tonic-gate } 415*0Sstevel@tonic-gate 416*0Sstevel@tonic-gate 417*0Sstevel@tonic-gate /* 418*0Sstevel@tonic-gate * ibnex_attach 419*0Sstevel@tonic-gate * Configure and attach an instance of the IB Nexus driver 420*0Sstevel@tonic-gate * Only one instance of IB Nexus is supported 421*0Sstevel@tonic-gate * Create a minor node for cfgadm purpose 422*0Sstevel@tonic-gate * Initialize communication services 423*0Sstevel@tonic-gate * Register callback with IBDM 424*0Sstevel@tonic-gate * Register callback with IBTL 425*0Sstevel@tonic-gate */ 426*0Sstevel@tonic-gate static int 427*0Sstevel@tonic-gate ibnex_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 428*0Sstevel@tonic-gate { 429*0Sstevel@tonic-gate int i; 430*0Sstevel@tonic-gate int instance = ddi_get_instance(dip); 431*0Sstevel@tonic-gate 432*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tattach: device = %p cmd = %x)", dip, cmd); 433*0Sstevel@tonic-gate 434*0Sstevel@tonic-gate switch (cmd) { 435*0Sstevel@tonic-gate case DDI_ATTACH: 436*0Sstevel@tonic-gate break; 437*0Sstevel@tonic-gate case DDI_RESUME: 438*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tattach: RESUME"); 439*0Sstevel@tonic-gate return (DDI_SUCCESS); 440*0Sstevel@tonic-gate default: 441*0Sstevel@tonic-gate return (DDI_FAILURE); 442*0Sstevel@tonic-gate } 443*0Sstevel@tonic-gate 444*0Sstevel@tonic-gate /* Fail attach for more than one instance */ 445*0Sstevel@tonic-gate mutex_enter(&ibnex.ibnex_mutex); 446*0Sstevel@tonic-gate if (ibnex.ibnex_dip != NULL) { 447*0Sstevel@tonic-gate mutex_exit(&ibnex.ibnex_mutex); 448*0Sstevel@tonic-gate return (DDI_FAILURE); 449*0Sstevel@tonic-gate } 450*0Sstevel@tonic-gate mutex_exit(&ibnex.ibnex_mutex); 451*0Sstevel@tonic-gate 452*0Sstevel@tonic-gate /* Register with MPxIO framework */ 453*0Sstevel@tonic-gate 454*0Sstevel@tonic-gate if (mdi_vhci_register(MDI_HCI_CLASS_IB, dip, &ibnex_vhci_ops, 0) 455*0Sstevel@tonic-gate != MDI_SUCCESS) { 456*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", 457*0Sstevel@tonic-gate "\tattach: mdi_vhci_register() failed"); 458*0Sstevel@tonic-gate return (DDI_FAILURE); 459*0Sstevel@tonic-gate } 460*0Sstevel@tonic-gate 461*0Sstevel@tonic-gate 462*0Sstevel@tonic-gate /* 463*0Sstevel@tonic-gate * Create the "fabric" devctl minor-node for IB DR support. 464*0Sstevel@tonic-gate * The minor number for the "devctl" node is in the same format 465*0Sstevel@tonic-gate * as the AP minor nodes. 466*0Sstevel@tonic-gate */ 467*0Sstevel@tonic-gate if (ddi_create_minor_node(dip, IBNEX_FABRIC, S_IFCHR, instance, 468*0Sstevel@tonic-gate DDI_NT_IB_ATTACHMENT_POINT, 0) != DDI_SUCCESS) { 469*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", 470*0Sstevel@tonic-gate "\tattach: failed to create fabric minornode"); 471*0Sstevel@tonic-gate (void) mdi_vhci_unregister(dip, 0); 472*0Sstevel@tonic-gate return (DDI_FAILURE); 473*0Sstevel@tonic-gate } 474*0Sstevel@tonic-gate 475*0Sstevel@tonic-gate 476*0Sstevel@tonic-gate /* 477*0Sstevel@tonic-gate * Set pm-want-child-notification property for 478*0Sstevel@tonic-gate * power management of the phci and client 479*0Sstevel@tonic-gate */ 480*0Sstevel@tonic-gate if (ddi_prop_create(DDI_DEV_T_NONE, dip, DDI_PROP_CANSLEEP, 481*0Sstevel@tonic-gate "pm-want-child-notification?", NULL, NULL) != DDI_PROP_SUCCESS) { 482*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", 483*0Sstevel@tonic-gate "_attach: create pm-want-child-notification failed"); 484*0Sstevel@tonic-gate (void) ddi_remove_minor_node(dip, NULL); 485*0Sstevel@tonic-gate (void) mdi_vhci_unregister(dip, 0); 486*0Sstevel@tonic-gate return (DDI_FAILURE); 487*0Sstevel@tonic-gate } 488*0Sstevel@tonic-gate 489*0Sstevel@tonic-gate mutex_enter(&ibnex.ibnex_mutex); 490*0Sstevel@tonic-gate ibnex.ibnex_dip = dip; 491*0Sstevel@tonic-gate mutex_exit(&ibnex.ibnex_mutex); 492*0Sstevel@tonic-gate 493*0Sstevel@tonic-gate /* 494*0Sstevel@tonic-gate * Event Handling: Definition and Binding. 495*0Sstevel@tonic-gate */ 496*0Sstevel@tonic-gate if (ndi_event_alloc_hdl(dip, 0, &ibnex.ibnex_ndi_event_hdl, 497*0Sstevel@tonic-gate NDI_SLEEP) != NDI_SUCCESS) { 498*0Sstevel@tonic-gate (void) ddi_remove_minor_node(dip, NULL); 499*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", 500*0Sstevel@tonic-gate "_attach: ndi_event_alloc_hdl failed"); 501*0Sstevel@tonic-gate (void) mdi_vhci_unregister(dip, 0); 502*0Sstevel@tonic-gate return (DDI_FAILURE); 503*0Sstevel@tonic-gate } 504*0Sstevel@tonic-gate if (ndi_event_bind_set(ibnex.ibnex_ndi_event_hdl, &ib_ndi_events, 505*0Sstevel@tonic-gate NDI_SLEEP) != NDI_SUCCESS) { 506*0Sstevel@tonic-gate (void) ddi_remove_minor_node(dip, NULL); 507*0Sstevel@tonic-gate (void) ndi_event_free_hdl(ibnex.ibnex_ndi_event_hdl); 508*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", 509*0Sstevel@tonic-gate "_attach: ndi_event_bind_set failed"); 510*0Sstevel@tonic-gate (void) mdi_vhci_unregister(dip, 0); 511*0Sstevel@tonic-gate return (DDI_FAILURE); 512*0Sstevel@tonic-gate } 513*0Sstevel@tonic-gate 514*0Sstevel@tonic-gate for (i = 0; i < N_IBNEX_PROPS; i++) { 515*0Sstevel@tonic-gate if (ibnex_comm_svc_init(ibnex_properties[i].name, 516*0Sstevel@tonic-gate ibnex_properties[i].type) != IBNEX_SUCCESS) { 517*0Sstevel@tonic-gate ibnex_comm_svc_fini(); 518*0Sstevel@tonic-gate (void) ndi_event_unbind_set(ibnex.ibnex_ndi_event_hdl, 519*0Sstevel@tonic-gate &ib_ndi_events, NDI_SLEEP); 520*0Sstevel@tonic-gate (void) ddi_remove_minor_node(dip, NULL); 521*0Sstevel@tonic-gate (void) ndi_event_free_hdl( 522*0Sstevel@tonic-gate ibnex.ibnex_ndi_event_hdl); 523*0Sstevel@tonic-gate ibnex.ibnex_ndi_event_hdl = NULL; 524*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", "_attach: ibnex_comm_svc_init" 525*0Sstevel@tonic-gate " failed %s", ibnex_properties[i].name); 526*0Sstevel@tonic-gate (void) mdi_vhci_unregister(dip, 0); 527*0Sstevel@tonic-gate return (DDI_FAILURE); 528*0Sstevel@tonic-gate } 529*0Sstevel@tonic-gate } 530*0Sstevel@tonic-gate 531*0Sstevel@tonic-gate /* 532*0Sstevel@tonic-gate * before anything else comes up: 533*0Sstevel@tonic-gate * Initialize the internal list of pseudo device nodes by 534*0Sstevel@tonic-gate * getting all pseudo children of "ib" and processing them. 535*0Sstevel@tonic-gate */ 536*0Sstevel@tonic-gate ibnex_pseudo_initnodes(); 537*0Sstevel@tonic-gate 538*0Sstevel@tonic-gate return (DDI_SUCCESS); 539*0Sstevel@tonic-gate } 540*0Sstevel@tonic-gate 541*0Sstevel@tonic-gate 542*0Sstevel@tonic-gate /* 543*0Sstevel@tonic-gate * ibnex_getinfo() 544*0Sstevel@tonic-gate * Given the device number, return the devinfo pointer or the 545*0Sstevel@tonic-gate * instance number. 546*0Sstevel@tonic-gate * Note: always succeed DDI_INFO_DEVT2INSTANCE, even before attach. 547*0Sstevel@tonic-gate */ 548*0Sstevel@tonic-gate 549*0Sstevel@tonic-gate /*ARGSUSED*/ 550*0Sstevel@tonic-gate static int 551*0Sstevel@tonic-gate ibnex_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result) 552*0Sstevel@tonic-gate { 553*0Sstevel@tonic-gate int ret = DDI_SUCCESS; 554*0Sstevel@tonic-gate 555*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tgetinfo: Begin"); 556*0Sstevel@tonic-gate switch (cmd) { 557*0Sstevel@tonic-gate case DDI_INFO_DEVT2DEVINFO: 558*0Sstevel@tonic-gate if (ibnex.ibnex_dip != NULL) 559*0Sstevel@tonic-gate *result = ibnex.ibnex_dip; 560*0Sstevel@tonic-gate else { 561*0Sstevel@tonic-gate *result = NULL; 562*0Sstevel@tonic-gate ret = DDI_FAILURE; 563*0Sstevel@tonic-gate } 564*0Sstevel@tonic-gate break; 565*0Sstevel@tonic-gate 566*0Sstevel@tonic-gate case DDI_INFO_DEVT2INSTANCE: 567*0Sstevel@tonic-gate *result = 0; 568*0Sstevel@tonic-gate break; 569*0Sstevel@tonic-gate 570*0Sstevel@tonic-gate default: 571*0Sstevel@tonic-gate ret = DDI_FAILURE; 572*0Sstevel@tonic-gate } 573*0Sstevel@tonic-gate return (ret); 574*0Sstevel@tonic-gate } 575*0Sstevel@tonic-gate 576*0Sstevel@tonic-gate 577*0Sstevel@tonic-gate /* 578*0Sstevel@tonic-gate * ibnex_detach 579*0Sstevel@tonic-gate * Unregister callback with the IBDM 580*0Sstevel@tonic-gate * Unregister callback with the IBTL 581*0Sstevel@tonic-gate * Uninitialize the communication entries 582*0Sstevel@tonic-gate * Remove all the minor nodes created by this instance 583*0Sstevel@tonic-gate */ 584*0Sstevel@tonic-gate static int 585*0Sstevel@tonic-gate ibnex_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 586*0Sstevel@tonic-gate { 587*0Sstevel@tonic-gate 588*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tdetach: dip = %p cmd = %x)", dip, cmd); 589*0Sstevel@tonic-gate 590*0Sstevel@tonic-gate switch (cmd) { 591*0Sstevel@tonic-gate 592*0Sstevel@tonic-gate case DDI_DETACH: 593*0Sstevel@tonic-gate break; 594*0Sstevel@tonic-gate case DDI_SUSPEND: 595*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\t_detach: Suspend"); 596*0Sstevel@tonic-gate return (DDI_SUCCESS); 597*0Sstevel@tonic-gate default: 598*0Sstevel@tonic-gate return (DDI_FAILURE); 599*0Sstevel@tonic-gate } 600*0Sstevel@tonic-gate 601*0Sstevel@tonic-gate mutex_enter(&ibnex.ibnex_mutex); 602*0Sstevel@tonic-gate if (ibt_hw_is_present()) { 603*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", 604*0Sstevel@tonic-gate "\tdetach: IB HW is present "); 605*0Sstevel@tonic-gate mutex_exit(&ibnex.ibnex_mutex); 606*0Sstevel@tonic-gate return (DDI_FAILURE); 607*0Sstevel@tonic-gate } 608*0Sstevel@tonic-gate if (ndi_event_free_hdl(ibnex.ibnex_ndi_event_hdl)) { 609*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", 610*0Sstevel@tonic-gate "\tdetach: ndi_event_free_hdl() failed"); 611*0Sstevel@tonic-gate mutex_exit(&ibnex.ibnex_mutex); 612*0Sstevel@tonic-gate return (DDI_FAILURE); 613*0Sstevel@tonic-gate } 614*0Sstevel@tonic-gate ibnex.ibnex_ndi_event_hdl = NULL; 615*0Sstevel@tonic-gate ibnex.ibnex_prop_update_evt_cookie = NULL; 616*0Sstevel@tonic-gate 617*0Sstevel@tonic-gate ibnex_pseudo_node_cleanup(); 618*0Sstevel@tonic-gate ibnex_comm_svc_fini(); 619*0Sstevel@tonic-gate ibnex_ioc_node_cleanup(); 620*0Sstevel@tonic-gate 621*0Sstevel@tonic-gate (void) ddi_remove_minor_node(dip, NULL); 622*0Sstevel@tonic-gate ibnex.ibnex_dip = NULL; 623*0Sstevel@tonic-gate mutex_exit(&ibnex.ibnex_mutex); 624*0Sstevel@tonic-gate (void) mdi_vhci_unregister(dip, 0); 625*0Sstevel@tonic-gate return (DDI_SUCCESS); 626*0Sstevel@tonic-gate } 627*0Sstevel@tonic-gate 628*0Sstevel@tonic-gate 629*0Sstevel@tonic-gate /* 630*0Sstevel@tonic-gate * ibnex_pseudo_node_cleanup() 631*0Sstevel@tonic-gate * This checks if all the "dips" have been deallocated (implying 632*0Sstevel@tonic-gate * that all the children have been unconfigured) first. 633*0Sstevel@tonic-gate * If not, it just returns. 634*0Sstevel@tonic-gate * If yes, then it frees up memory allocated for devi_name, 635*0Sstevel@tonic-gate * node_addr, and property list. 636*0Sstevel@tonic-gate */ 637*0Sstevel@tonic-gate static void 638*0Sstevel@tonic-gate ibnex_pseudo_node_cleanup(void) 639*0Sstevel@tonic-gate { 640*0Sstevel@tonic-gate ibnex_node_data_t *nodep = ibnex.ibnex_pseudo_node_head; 641*0Sstevel@tonic-gate ibnex_pseudo_node_t *pseudo; 642*0Sstevel@tonic-gate 643*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tpseudo_node_cleanup:"); 644*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&ibnex.ibnex_mutex)); 645*0Sstevel@tonic-gate 646*0Sstevel@tonic-gate for (; nodep; nodep = nodep->node_next) 647*0Sstevel@tonic-gate if (nodep->node_dip) 648*0Sstevel@tonic-gate return; 649*0Sstevel@tonic-gate 650*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tpseudo_node_cleanup: freeing up memory"); 651*0Sstevel@tonic-gate for (nodep = ibnex.ibnex_pseudo_node_head; nodep; 652*0Sstevel@tonic-gate nodep = nodep->node_next) { 653*0Sstevel@tonic-gate 654*0Sstevel@tonic-gate pseudo = &nodep->node_data.pseudo_node; 655*0Sstevel@tonic-gate if (pseudo->pseudo_node_addr) { 656*0Sstevel@tonic-gate kmem_free(pseudo->pseudo_node_addr, 657*0Sstevel@tonic-gate strlen(pseudo-> pseudo_node_addr) + 1); 658*0Sstevel@tonic-gate pseudo->pseudo_node_addr = NULL; 659*0Sstevel@tonic-gate } 660*0Sstevel@tonic-gate 661*0Sstevel@tonic-gate if (pseudo->pseudo_devi_name) { 662*0Sstevel@tonic-gate kmem_free(pseudo->pseudo_devi_name, 663*0Sstevel@tonic-gate strlen(pseudo-> pseudo_devi_name) + 1); 664*0Sstevel@tonic-gate pseudo->pseudo_devi_name = NULL; 665*0Sstevel@tonic-gate } 666*0Sstevel@tonic-gate 667*0Sstevel@tonic-gate if (pseudo->pseudo_unit_addr) { 668*0Sstevel@tonic-gate kmem_free(pseudo->pseudo_unit_addr, 669*0Sstevel@tonic-gate pseudo->pseudo_unit_addr_len); 670*0Sstevel@tonic-gate } 671*0Sstevel@tonic-gate } 672*0Sstevel@tonic-gate } 673*0Sstevel@tonic-gate 674*0Sstevel@tonic-gate 675*0Sstevel@tonic-gate /* 676*0Sstevel@tonic-gate * This functions wakes up any reprobe requests waiting for completion 677*0Sstevel@tonic-gate * of reprobe of this IOC. It also send an NDI event, if : 678*0Sstevel@tonic-gate * 679*0Sstevel@tonic-gate * notify_flag is set. This is set if : 680*0Sstevel@tonic-gate * ibt_reprobe_ioc has returned with SUCCESS 681*0Sstevel@tonic-gate * IBTF client has not been notified for this node. 682*0Sstevel@tonic-gate * node_data->node_dip != NULL 683*0Sstevel@tonic-gate * node_state has IBNEX_NODE_REPROBE_NOTIFY_ALWAYS set 684*0Sstevel@tonic-gate * An NDI event cookie has been registered. 685*0Sstevel@tonic-gate */ 686*0Sstevel@tonic-gate static void 687*0Sstevel@tonic-gate ibnex_wakeup_reprobe_ioc(ibnex_node_data_t *node_data, int notify_flag) 688*0Sstevel@tonic-gate { 689*0Sstevel@tonic-gate ddi_eventcookie_t evt_cookie; 690*0Sstevel@tonic-gate 691*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&ibnex.ibnex_mutex)); 692*0Sstevel@tonic-gate evt_cookie = ibnex.ibnex_prop_update_evt_cookie; 693*0Sstevel@tonic-gate 694*0Sstevel@tonic-gate if ((ibnex.ibnex_reprobe_state == IBNEX_REPROBE_IOC_WAIT) || 695*0Sstevel@tonic-gate (node_data->node_reprobe_state != 0)) { 696*0Sstevel@tonic-gate if (notify_flag && (node_data->node_dip != NULL) && 697*0Sstevel@tonic-gate (node_data->node_state & 698*0Sstevel@tonic-gate IBNEX_NODE_REPROBE_NOTIFY_ALWAYS) && 699*0Sstevel@tonic-gate (evt_cookie != NULL)) { 700*0Sstevel@tonic-gate ibt_prop_update_payload_t evt_data; 701*0Sstevel@tonic-gate 702*0Sstevel@tonic-gate mutex_exit(&ibnex.ibnex_mutex); 703*0Sstevel@tonic-gate 704*0Sstevel@tonic-gate bzero(&evt_data, sizeof (evt_data)); 705*0Sstevel@tonic-gate if (ndi_post_event(ibnex.ibnex_dip, 706*0Sstevel@tonic-gate node_data->node_dip, 707*0Sstevel@tonic-gate evt_cookie, &evt_data) != NDI_SUCCESS) 708*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", 709*0Sstevel@tonic-gate "\tndi_post_event failed\n"); 710*0Sstevel@tonic-gate 711*0Sstevel@tonic-gate mutex_enter(&ibnex.ibnex_mutex); 712*0Sstevel@tonic-gate } 713*0Sstevel@tonic-gate 714*0Sstevel@tonic-gate node_data->node_reprobe_state = 0; 715*0Sstevel@tonic-gate cv_broadcast(&ibnex.ibnex_reprobe_cv); 716*0Sstevel@tonic-gate } 717*0Sstevel@tonic-gate node_data->node_reprobe_state = 0; 718*0Sstevel@tonic-gate } 719*0Sstevel@tonic-gate 720*0Sstevel@tonic-gate /* 721*0Sstevel@tonic-gate * This function wakes up any reprobe request waiting for completion 722*0Sstevel@tonic-gate * of reprobe of all IOCs. 723*0Sstevel@tonic-gate */ 724*0Sstevel@tonic-gate static void 725*0Sstevel@tonic-gate ibnex_wakeup_reprobe_all() 726*0Sstevel@tonic-gate { 727*0Sstevel@tonic-gate ibnex_node_data_t *ioc_node; 728*0Sstevel@tonic-gate 729*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&ibnex.ibnex_mutex)); 730*0Sstevel@tonic-gate 731*0Sstevel@tonic-gate /* Notify if another reprobe_all is pending */ 732*0Sstevel@tonic-gate if (ibnex.ibnex_reprobe_state == IBNEX_REPROBE_ALL_WAIT) { 733*0Sstevel@tonic-gate ibnex.ibnex_reprobe_state = 0; 734*0Sstevel@tonic-gate cv_broadcast(&ibnex.ibnex_reprobe_cv); 735*0Sstevel@tonic-gate } 736*0Sstevel@tonic-gate ibnex.ibnex_reprobe_state = 0; 737*0Sstevel@tonic-gate 738*0Sstevel@tonic-gate /* 739*0Sstevel@tonic-gate * The IOC may be hot-removed after the reprobe request. 740*0Sstevel@tonic-gate * Reset the reprobe states for such IOCs. 741*0Sstevel@tonic-gate */ 742*0Sstevel@tonic-gate for (ioc_node = ibnex.ibnex_ioc_node_head; ioc_node; 743*0Sstevel@tonic-gate ioc_node = ioc_node->node_next) { 744*0Sstevel@tonic-gate if (ioc_node->node_reprobe_state != 0) { 745*0Sstevel@tonic-gate ibnex_wakeup_reprobe_ioc(ioc_node, 1); 746*0Sstevel@tonic-gate } 747*0Sstevel@tonic-gate } 748*0Sstevel@tonic-gate } 749*0Sstevel@tonic-gate 750*0Sstevel@tonic-gate /* 751*0Sstevel@tonic-gate * ibnex_ibnex_callback: 752*0Sstevel@tonic-gate * IBTL_IBNEX_IBC_INIT: 753*0Sstevel@tonic-gate * Called from ibc_init() which is called from 754*0Sstevel@tonic-gate * HCA driver _init entry point 755*0Sstevel@tonic-gate * Initializes the HCA dev_ops structure with default 756*0Sstevel@tonic-gate * IB nexus structure. 757*0Sstevel@tonic-gate * IBTL_IBNEX_IBC_FINI: 758*0Sstevel@tonic-gate * Called from ibc_fini() which is called from 759*0Sstevel@tonic-gate * HCA driver _fini entry point 760*0Sstevel@tonic-gate * Un-Initializes the HCA dev_ops structure with default 761*0Sstevel@tonic-gate * IB nexus strucuture. 762*0Sstevel@tonic-gate * Returns IBT_SUCCESS 763*0Sstevel@tonic-gate */ 764*0Sstevel@tonic-gate ibt_status_t 765*0Sstevel@tonic-gate ibnex_ibtl_callback(ibtl_ibnex_cb_args_t *cb_args) 766*0Sstevel@tonic-gate { 767*0Sstevel@tonic-gate int retval = IBT_SUCCESS; 768*0Sstevel@tonic-gate struct dev_ops *hca_dev_ops; 769*0Sstevel@tonic-gate dev_info_t *clnt_dip; 770*0Sstevel@tonic-gate ibnex_node_data_t *node_data; 771*0Sstevel@tonic-gate 772*0Sstevel@tonic-gate IBTF_DPRINTF_L5("ibnex", "\tibtl_callback"); 773*0Sstevel@tonic-gate 774*0Sstevel@tonic-gate switch (cb_args->cb_flag) { 775*0Sstevel@tonic-gate case IBTL_IBNEX_IBC_INIT: 776*0Sstevel@tonic-gate /* 777*0Sstevel@tonic-gate * Get the devops structure of the HCA, 778*0Sstevel@tonic-gate * and put IB nexus default busops vector in its place. 779*0Sstevel@tonic-gate */ 780*0Sstevel@tonic-gate hca_dev_ops = ((struct modldrv *) 781*0Sstevel@tonic-gate (cb_args->cb_modlp->ml_linkage[0]))->drv_dev_ops; 782*0Sstevel@tonic-gate ASSERT((hca_dev_ops) && (hca_dev_ops->devo_bus_ops == NULL)); 783*0Sstevel@tonic-gate hca_dev_ops->devo_bus_ops = &ibnex_ci_busops; 784*0Sstevel@tonic-gate break; 785*0Sstevel@tonic-gate 786*0Sstevel@tonic-gate case IBTL_IBNEX_IBC_FINI: 787*0Sstevel@tonic-gate hca_dev_ops = ((struct modldrv *) 788*0Sstevel@tonic-gate (cb_args->cb_modlp->ml_linkage[0]))->drv_dev_ops; 789*0Sstevel@tonic-gate hca_dev_ops->devo_bus_ops = NULL; 790*0Sstevel@tonic-gate break; 791*0Sstevel@tonic-gate 792*0Sstevel@tonic-gate case IBTL_IBNEX_REPROBE_DEV_REQ: 793*0Sstevel@tonic-gate /* IBTL pass down request for ibt_reprobe_dev */ 794*0Sstevel@tonic-gate clnt_dip = cb_args->cb_dip; 795*0Sstevel@tonic-gate ASSERT(clnt_dip); 796*0Sstevel@tonic-gate 797*0Sstevel@tonic-gate node_data = ddi_get_parent_data(clnt_dip); 798*0Sstevel@tonic-gate ASSERT(node_data); 799*0Sstevel@tonic-gate 800*0Sstevel@tonic-gate /* Reprobe for IOC nodes only */ 801*0Sstevel@tonic-gate ASSERT(node_data->node_type == IBNEX_IOC_NODE); 802*0Sstevel@tonic-gate 803*0Sstevel@tonic-gate /* 804*0Sstevel@tonic-gate * Start the reprobe. This could sleep as it is not 805*0Sstevel@tonic-gate * from interrupt context. 806*0Sstevel@tonic-gate */ 807*0Sstevel@tonic-gate if (taskq_dispatch(system_taskq, ibnex_handle_reprobe_dev, 808*0Sstevel@tonic-gate clnt_dip, TQ_SLEEP) == 0) { 809*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", 810*0Sstevel@tonic-gate "ibnex_ibtl_callback: taskq_dispatch failed"); 811*0Sstevel@tonic-gate mutex_enter(&ibnex.ibnex_mutex); 812*0Sstevel@tonic-gate ibnex_wakeup_reprobe_ioc(node_data, 0); 813*0Sstevel@tonic-gate mutex_exit(&ibnex.ibnex_mutex); 814*0Sstevel@tonic-gate return (IBT_INSUFF_KERNEL_RESOURCE); 815*0Sstevel@tonic-gate } 816*0Sstevel@tonic-gate return (IBT_SUCCESS); 817*0Sstevel@tonic-gate } 818*0Sstevel@tonic-gate 819*0Sstevel@tonic-gate return (retval); 820*0Sstevel@tonic-gate } 821*0Sstevel@tonic-gate 822*0Sstevel@tonic-gate 823*0Sstevel@tonic-gate /* 824*0Sstevel@tonic-gate * Bus-ops entry points 825*0Sstevel@tonic-gate */ 826*0Sstevel@tonic-gate 827*0Sstevel@tonic-gate /* 828*0Sstevel@tonic-gate * ibnex_map_fault 829*0Sstevel@tonic-gate * IOC drivers need not map memory. Return failure to fail any 830*0Sstevel@tonic-gate * such calls. 831*0Sstevel@tonic-gate */ 832*0Sstevel@tonic-gate /*ARGSUSED*/ 833*0Sstevel@tonic-gate static int 834*0Sstevel@tonic-gate ibnex_map_fault(dev_info_t *dip, dev_info_t *rdip, struct hat *hat, 835*0Sstevel@tonic-gate struct seg *seg, caddr_t addr, struct devpage *dp, pfn_t pfn, 836*0Sstevel@tonic-gate uint_t prot, uint_t lock) 837*0Sstevel@tonic-gate { 838*0Sstevel@tonic-gate return (DDI_FAILURE); 839*0Sstevel@tonic-gate } 840*0Sstevel@tonic-gate 841*0Sstevel@tonic-gate 842*0Sstevel@tonic-gate /* 843*0Sstevel@tonic-gate * ibnex_busctl 844*0Sstevel@tonic-gate * bus_ctl bus_ops entry point 845*0Sstevel@tonic-gate */ 846*0Sstevel@tonic-gate /*ARGSUSED*/ 847*0Sstevel@tonic-gate static int 848*0Sstevel@tonic-gate ibnex_busctl(dev_info_t *dip, dev_info_t *rdip, 849*0Sstevel@tonic-gate ddi_ctl_enum_t ctlop, void *arg, void *result) 850*0Sstevel@tonic-gate { 851*0Sstevel@tonic-gate dev_info_t *child_dip; 852*0Sstevel@tonic-gate 853*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", 854*0Sstevel@tonic-gate "\tbusctl: dip = %p, rdip = %p, ctlop = %x,", dip, rdip, ctlop); 855*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tbusctl: targ = %p, result %p", arg, result); 856*0Sstevel@tonic-gate 857*0Sstevel@tonic-gate switch (ctlop) { 858*0Sstevel@tonic-gate case DDI_CTLOPS_REPORTDEV: 859*0Sstevel@tonic-gate if (rdip == NULL) { 860*0Sstevel@tonic-gate return (DDI_FAILURE); 861*0Sstevel@tonic-gate } 862*0Sstevel@tonic-gate 863*0Sstevel@tonic-gate /* Log the relevant details of dip to sysbuf */ 864*0Sstevel@tonic-gate cmn_err(CE_CONT, "?IB device: %s@%s, %s%d\n", 865*0Sstevel@tonic-gate ddi_node_name(rdip), ddi_get_name_addr(rdip), 866*0Sstevel@tonic-gate ddi_driver_name(rdip), ddi_get_instance(rdip)); 867*0Sstevel@tonic-gate 868*0Sstevel@tonic-gate return (DDI_SUCCESS); 869*0Sstevel@tonic-gate 870*0Sstevel@tonic-gate case DDI_CTLOPS_INITCHILD: 871*0Sstevel@tonic-gate child_dip = (dev_info_t *)arg; 872*0Sstevel@tonic-gate return (ibnex_init_child(child_dip)); 873*0Sstevel@tonic-gate 874*0Sstevel@tonic-gate case DDI_CTLOPS_UNINITCHILD: 875*0Sstevel@tonic-gate child_dip = (dev_info_t *)arg; 876*0Sstevel@tonic-gate ddi_set_name_addr(child_dip, NULL); 877*0Sstevel@tonic-gate return (DDI_SUCCESS); 878*0Sstevel@tonic-gate 879*0Sstevel@tonic-gate case DDI_CTLOPS_ATTACH: 880*0Sstevel@tonic-gate case DDI_CTLOPS_DETACH: 881*0Sstevel@tonic-gate case DDI_CTLOPS_POWER : 882*0Sstevel@tonic-gate return (DDI_SUCCESS); 883*0Sstevel@tonic-gate 884*0Sstevel@tonic-gate case DDI_CTLOPS_SIDDEV: 885*0Sstevel@tonic-gate /* 886*0Sstevel@tonic-gate * Return DDI_SUCCESS for IOC/PORT/VPPA nodes and 887*0Sstevel@tonic-gate * DDI_FAILURE for the nodes enumerated by a Pseudo file. 888*0Sstevel@tonic-gate */ 889*0Sstevel@tonic-gate return (ndi_dev_is_persistent_node(rdip) ? 890*0Sstevel@tonic-gate DDI_SUCCESS : DDI_FAILURE); 891*0Sstevel@tonic-gate 892*0Sstevel@tonic-gate 893*0Sstevel@tonic-gate case DDI_CTLOPS_IOMIN: 894*0Sstevel@tonic-gate /* 895*0Sstevel@tonic-gate * Return DDI_SUCCESS, so that consistent buf alloc 896*0Sstevel@tonic-gate * gets the default DMA IO minimum for the platform 897*0Sstevel@tonic-gate */ 898*0Sstevel@tonic-gate return (DDI_SUCCESS); 899*0Sstevel@tonic-gate 900*0Sstevel@tonic-gate /* 901*0Sstevel@tonic-gate * These ops correspond to functions that "shouldn't" be 902*0Sstevel@tonic-gate * called by IB Nexus driver. 903*0Sstevel@tonic-gate */ 904*0Sstevel@tonic-gate case DDI_CTLOPS_DMAPMAPC: 905*0Sstevel@tonic-gate case DDI_CTLOPS_REPORTINT: 906*0Sstevel@tonic-gate case DDI_CTLOPS_REGSIZE: 907*0Sstevel@tonic-gate case DDI_CTLOPS_NREGS: 908*0Sstevel@tonic-gate case DDI_CTLOPS_NINTRS: 909*0Sstevel@tonic-gate case DDI_CTLOPS_SLAVEONLY: 910*0Sstevel@tonic-gate case DDI_CTLOPS_AFFINITY: 911*0Sstevel@tonic-gate case DDI_CTLOPS_INTR_HILEVEL: 912*0Sstevel@tonic-gate case DDI_CTLOPS_XLATE_INTRS: 913*0Sstevel@tonic-gate case DDI_CTLOPS_POKE: 914*0Sstevel@tonic-gate case DDI_CTLOPS_PEEK: 915*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", 916*0Sstevel@tonic-gate "%s%d: invalid op (%d) from %s inst%d", 917*0Sstevel@tonic-gate ddi_get_name(dip), ddi_get_instance(dip), 918*0Sstevel@tonic-gate ctlop, ddi_get_name(rdip), ddi_get_instance(rdip)); 919*0Sstevel@tonic-gate return (DDI_FAILURE); 920*0Sstevel@tonic-gate 921*0Sstevel@tonic-gate /* 922*0Sstevel@tonic-gate * Everything else (PTOB/BTOP/BTOPR/DVMAPAGESIZE requests) we 923*0Sstevel@tonic-gate * pass up 924*0Sstevel@tonic-gate */ 925*0Sstevel@tonic-gate default: 926*0Sstevel@tonic-gate return (ddi_ctlops(dip, rdip, ctlop, arg, result)); 927*0Sstevel@tonic-gate } 928*0Sstevel@tonic-gate } 929*0Sstevel@tonic-gate 930*0Sstevel@tonic-gate 931*0Sstevel@tonic-gate /* 932*0Sstevel@tonic-gate * ibnex_init_child() 933*0Sstevel@tonic-gate * 934*0Sstevel@tonic-gate * Initialize a child device node. This is called for the DDI_CTLOPS_INITCHILD 935*0Sstevel@tonic-gate * entry. Function returns DDI_SUCCESS, DDI_FAILURE or DDI_NOT_WELL_FORMED. 936*0Sstevel@tonic-gate */ 937*0Sstevel@tonic-gate static int 938*0Sstevel@tonic-gate ibnex_init_child(dev_info_t *child) 939*0Sstevel@tonic-gate { 940*0Sstevel@tonic-gate int ret; 941*0Sstevel@tonic-gate char name[MAXNAMELEN]; 942*0Sstevel@tonic-gate 943*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tinit_child: child = %p", child); 944*0Sstevel@tonic-gate 945*0Sstevel@tonic-gate /* Handle Pseudo nodes of client children */ 946*0Sstevel@tonic-gate if (ndi_dev_is_persistent_node(child) == 0) { 947*0Sstevel@tonic-gate if (ibnex_name_pseudo_child(child, name) != DDI_SUCCESS) 948*0Sstevel@tonic-gate return (DDI_FAILURE); 949*0Sstevel@tonic-gate 950*0Sstevel@tonic-gate ddi_set_name_addr(child, name); 951*0Sstevel@tonic-gate /* 952*0Sstevel@tonic-gate * Merge the .conf node 953*0Sstevel@tonic-gate */ 954*0Sstevel@tonic-gate if (ndi_merge_node(child, 955*0Sstevel@tonic-gate ibnex_name_child) == DDI_SUCCESS) { 956*0Sstevel@tonic-gate ddi_set_name_addr(child, NULL); 957*0Sstevel@tonic-gate return (DDI_FAILURE); 958*0Sstevel@tonic-gate } 959*0Sstevel@tonic-gate return (DDI_NOT_WELL_FORMED); 960*0Sstevel@tonic-gate 961*0Sstevel@tonic-gate } 962*0Sstevel@tonic-gate 963*0Sstevel@tonic-gate if ((ret = ibnex_name_child(child, name, 0)) != DDI_SUCCESS) 964*0Sstevel@tonic-gate return (ret); 965*0Sstevel@tonic-gate 966*0Sstevel@tonic-gate ddi_set_name_addr(child, name); 967*0Sstevel@tonic-gate 968*0Sstevel@tonic-gate return (DDI_SUCCESS); 969*0Sstevel@tonic-gate } 970*0Sstevel@tonic-gate 971*0Sstevel@tonic-gate 972*0Sstevel@tonic-gate int 973*0Sstevel@tonic-gate ibnex_name_pseudo_child(dev_info_t *child, char *name) 974*0Sstevel@tonic-gate { 975*0Sstevel@tonic-gate char **unit_addr; 976*0Sstevel@tonic-gate uint_t n; 977*0Sstevel@tonic-gate if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, child, 978*0Sstevel@tonic-gate DDI_PROP_DONTPASS, "unit-address", &unit_addr, &n) != 979*0Sstevel@tonic-gate DDI_PROP_SUCCESS) { 980*0Sstevel@tonic-gate cmn_err(CE_WARN, 981*0Sstevel@tonic-gate "cannot find unit-address in %s.conf", 982*0Sstevel@tonic-gate ddi_get_name(child)); 983*0Sstevel@tonic-gate return (DDI_FAILURE); 984*0Sstevel@tonic-gate } 985*0Sstevel@tonic-gate if (n != 1 || *unit_addr == NULL || **unit_addr == 0) { 986*0Sstevel@tonic-gate cmn_err(CE_WARN, "unit-address property in %s.conf" 987*0Sstevel@tonic-gate " not well-formed", ddi_get_name(child)); 988*0Sstevel@tonic-gate ddi_prop_free(unit_addr); 989*0Sstevel@tonic-gate return (DDI_FAILURE); 990*0Sstevel@tonic-gate } 991*0Sstevel@tonic-gate (void) snprintf(name, MAXNAMELEN, "%s", *unit_addr); 992*0Sstevel@tonic-gate ddi_prop_free(unit_addr); 993*0Sstevel@tonic-gate return (DDI_SUCCESS); 994*0Sstevel@tonic-gate } 995*0Sstevel@tonic-gate 996*0Sstevel@tonic-gate 997*0Sstevel@tonic-gate /*ARGSUSED*/ 998*0Sstevel@tonic-gate int 999*0Sstevel@tonic-gate ibnex_name_child(dev_info_t *child, char *name, int flag) 1000*0Sstevel@tonic-gate { 1001*0Sstevel@tonic-gate ibnex_pseudo_node_t *pseudo; 1002*0Sstevel@tonic-gate ibnex_node_data_t *node_datap; 1003*0Sstevel@tonic-gate ibnex_port_node_t *port_node; 1004*0Sstevel@tonic-gate ibnex_ioc_node_t *ioc; 1005*0Sstevel@tonic-gate 1006*0Sstevel@tonic-gate node_datap = ddi_get_parent_data(child); 1007*0Sstevel@tonic-gate if (node_datap == NULL) { 1008*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", "\tname_child: Node data is NULL"); 1009*0Sstevel@tonic-gate return (DDI_NOT_WELL_FORMED); 1010*0Sstevel@tonic-gate } 1011*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tname_sid_child: Node data %p" 1012*0Sstevel@tonic-gate "Node type %x", node_datap, node_datap->node_type); 1013*0Sstevel@tonic-gate switch (node_datap->node_type) { 1014*0Sstevel@tonic-gate case IBNEX_PORT_COMMSVC_NODE: 1015*0Sstevel@tonic-gate port_node = &node_datap->node_data.port_node; 1016*0Sstevel@tonic-gate (void) snprintf(name, IBNEX_MAX_NODEADDR_SZ, "%x,0,%s", 1017*0Sstevel@tonic-gate port_node->port_num, 1018*0Sstevel@tonic-gate ibnex.ibnex_comm_svc_names[port_node->port_commsvc_idx]); 1019*0Sstevel@tonic-gate break; 1020*0Sstevel@tonic-gate case IBNEX_VPPA_COMMSVC_NODE: 1021*0Sstevel@tonic-gate port_node = &node_datap->node_data.port_node; 1022*0Sstevel@tonic-gate (void) snprintf(name, IBNEX_MAX_NODEADDR_SZ, "%x,%x,%s", 1023*0Sstevel@tonic-gate port_node->port_num, port_node->port_pkey, ibnex. 1024*0Sstevel@tonic-gate ibnex_vppa_comm_svc_names[port_node->port_commsvc_idx]); 1025*0Sstevel@tonic-gate break; 1026*0Sstevel@tonic-gate case IBNEX_HCASVC_COMMSVC_NODE: 1027*0Sstevel@tonic-gate port_node = &node_datap->node_data.port_node; 1028*0Sstevel@tonic-gate (void) snprintf(name, IBNEX_MAX_NODEADDR_SZ, "%x,0,%s", 1029*0Sstevel@tonic-gate port_node->port_num, 1030*0Sstevel@tonic-gate ibnex.ibnex_hcasvc_comm_svc_names[port_node-> 1031*0Sstevel@tonic-gate port_commsvc_idx]); 1032*0Sstevel@tonic-gate break; 1033*0Sstevel@tonic-gate case IBNEX_IOC_NODE: 1034*0Sstevel@tonic-gate ioc = &node_datap->node_data.ioc_node; 1035*0Sstevel@tonic-gate (void) snprintf(name, IBNEX_MAX_NODEADDR_SZ, "%llX,%llX", 1036*0Sstevel@tonic-gate (longlong_t)ioc->ioc_guid, (longlong_t)ioc->iou_guid); 1037*0Sstevel@tonic-gate break; 1038*0Sstevel@tonic-gate case IBNEX_PSEUDO_NODE: 1039*0Sstevel@tonic-gate pseudo = &node_datap->node_data.pseudo_node; 1040*0Sstevel@tonic-gate (void) snprintf(name, 1041*0Sstevel@tonic-gate IBNEX_MAX_NODEADDR_SZ, pseudo->pseudo_unit_addr); 1042*0Sstevel@tonic-gate break; 1043*0Sstevel@tonic-gate default: 1044*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", "\name_child: Not well formed"); 1045*0Sstevel@tonic-gate return (DDI_NOT_WELL_FORMED); 1046*0Sstevel@tonic-gate } 1047*0Sstevel@tonic-gate 1048*0Sstevel@tonic-gate return (DDI_SUCCESS); 1049*0Sstevel@tonic-gate } 1050*0Sstevel@tonic-gate 1051*0Sstevel@tonic-gate 1052*0Sstevel@tonic-gate /* 1053*0Sstevel@tonic-gate * ibnex_bus_config() 1054*0Sstevel@tonic-gate * 1055*0Sstevel@tonic-gate * BUS_CONFIG_ONE: 1056*0Sstevel@tonic-gate * Enumerate the exact instance of the driver. Use the device node name 1057*0Sstevel@tonic-gate * to locate the exact instance. 1058*0Sstevel@tonic-gate * Query IBDM to find whether the hardware exits for the instance of the 1059*0Sstevel@tonic-gate * driver. If exists, create a device node and return NDI_SUCCESS. 1060*0Sstevel@tonic-gate * 1061*0Sstevel@tonic-gate * BUS_CONFIG_ALL: 1062*0Sstevel@tonic-gate * Enumerate all the instances of all the possible children (seen before 1063*0Sstevel@tonic-gate * and never seen before). 1064*0Sstevel@tonic-gate * 1065*0Sstevel@tonic-gate * BUS_CONFIG_DRIVER: 1066*0Sstevel@tonic-gate * Enumerate all the instances of a particular driver. 1067*0Sstevel@tonic-gate */ 1068*0Sstevel@tonic-gate static int 1069*0Sstevel@tonic-gate ibnex_bus_config(dev_info_t *parent, uint_t flag, 1070*0Sstevel@tonic-gate ddi_bus_config_op_t op, void *devname, dev_info_t **child) 1071*0Sstevel@tonic-gate { 1072*0Sstevel@tonic-gate int ret = IBNEX_SUCCESS, len, circ; 1073*0Sstevel@tonic-gate char *device_name, *cname = NULL, *caddr = NULL; 1074*0Sstevel@tonic-gate char *srvname, nameaddr[MAXNAMELEN]; 1075*0Sstevel@tonic-gate dev_info_t *cdip, *pdip = NULL; 1076*0Sstevel@tonic-gate ibnex_node_data_t *node_data; 1077*0Sstevel@tonic-gate ibnex_port_node_t *port_node; 1078*0Sstevel@tonic-gate 1079*0Sstevel@tonic-gate ndi_devi_enter(parent, &circ); 1080*0Sstevel@tonic-gate 1081*0Sstevel@tonic-gate switch (op) { 1082*0Sstevel@tonic-gate case BUS_CONFIG_ONE: 1083*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tbus_config: CONFIG_ONE"); 1084*0Sstevel@tonic-gate 1085*0Sstevel@tonic-gate len = strlen((char *)devname) + 1; 1086*0Sstevel@tonic-gate device_name = i_ddi_strdup(devname, KM_SLEEP); 1087*0Sstevel@tonic-gate i_ddi_parse_name(device_name, &cname, &caddr, NULL); 1088*0Sstevel@tonic-gate 1089*0Sstevel@tonic-gate if (caddr == NULL || (strlen(caddr) == 0)) { 1090*0Sstevel@tonic-gate kmem_free(device_name, len); 1091*0Sstevel@tonic-gate ndi_devi_exit(parent, circ); 1092*0Sstevel@tonic-gate return (NDI_FAILURE); 1093*0Sstevel@tonic-gate } 1094*0Sstevel@tonic-gate 1095*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", 1096*0Sstevel@tonic-gate "\tbus_config: cname %s addr %s", cname, caddr); 1097*0Sstevel@tonic-gate 1098*0Sstevel@tonic-gate cdip = ndi_devi_findchild(parent, device_name); 1099*0Sstevel@tonic-gate if (cdip == NULL) { 1100*0Sstevel@tonic-gate /* Node is not present */ 1101*0Sstevel@tonic-gate if (strncmp(cname, IBNEX_IOC_CNAME, 3) == 0) { 1102*0Sstevel@tonic-gate if (parent == ibnex.ibnex_dip) 1103*0Sstevel@tonic-gate ret = ibnex_config_ioc_node(devname); 1104*0Sstevel@tonic-gate else { 1105*0Sstevel@tonic-gate ret = ibnex_config_root_iocnode( 1106*0Sstevel@tonic-gate parent, devname); 1107*0Sstevel@tonic-gate if (ibnex.ibnex_dip) 1108*0Sstevel@tonic-gate pdip = ibnex.ibnex_dip; 1109*0Sstevel@tonic-gate else 1110*0Sstevel@tonic-gate ret = IBNEX_FAILURE; 1111*0Sstevel@tonic-gate } 1112*0Sstevel@tonic-gate } else if ((strncmp(cname, 1113*0Sstevel@tonic-gate IBNEX_IBPORT_CNAME, 6) == 0) && 1114*0Sstevel@tonic-gate (parent != ibnex.ibnex_dip)) { /* parent is HCA */ 1115*0Sstevel@tonic-gate cdip = ibnex_config_port_node(parent, devname); 1116*0Sstevel@tonic-gate if (cdip) 1117*0Sstevel@tonic-gate ret = IBNEX_SUCCESS; 1118*0Sstevel@tonic-gate else 1119*0Sstevel@tonic-gate ret = IBNEX_FAILURE; 1120*0Sstevel@tonic-gate /* Allows enumeration under PHCI */ 1121*0Sstevel@tonic-gate flag |= NDI_MDI_FALLBACK; 1122*0Sstevel@tonic-gate } else if (parent == ibnex.ibnex_dip) { 1123*0Sstevel@tonic-gate /* 1124*0Sstevel@tonic-gate * if not IOC or PORT device then always 1125*0Sstevel@tonic-gate * assume a Pseudo child 1126*0Sstevel@tonic-gate */ 1127*0Sstevel@tonic-gate ret = IBNEX_SUCCESS; 1128*0Sstevel@tonic-gate ibnex_pseudo_initnodes(); 1129*0Sstevel@tonic-gate mutex_enter(&ibnex.ibnex_mutex); 1130*0Sstevel@tonic-gate ret = ibnex_pseudo_config_one( 1131*0Sstevel@tonic-gate NULL, cname, caddr); 1132*0Sstevel@tonic-gate mutex_exit(&ibnex.ibnex_mutex); 1133*0Sstevel@tonic-gate } else 1134*0Sstevel@tonic-gate ret = IBNEX_FAILURE; 1135*0Sstevel@tonic-gate } 1136*0Sstevel@tonic-gate kmem_free(device_name, len); 1137*0Sstevel@tonic-gate break; 1138*0Sstevel@tonic-gate 1139*0Sstevel@tonic-gate case BUS_CONFIG_OBP_ARGS: 1140*0Sstevel@tonic-gate cdip = ibnex_config_obp_args(parent, devname); 1141*0Sstevel@tonic-gate if (cdip) { 1142*0Sstevel@tonic-gate /* 1143*0Sstevel@tonic-gate * Boot case. 1144*0Sstevel@tonic-gate * Special handling because the "devname" 1145*0Sstevel@tonic-gate * format for the enumerated device is 1146*0Sstevel@tonic-gate * different. 1147*0Sstevel@tonic-gate */ 1148*0Sstevel@tonic-gate node_data = ddi_get_parent_data(cdip); 1149*0Sstevel@tonic-gate port_node = &node_data->node_data.port_node; 1150*0Sstevel@tonic-gate if (node_data->node_type == 1151*0Sstevel@tonic-gate IBNEX_VPPA_COMMSVC_NODE) { 1152*0Sstevel@tonic-gate srvname = 1153*0Sstevel@tonic-gate ibnex.ibnex_vppa_comm_svc_names[ 1154*0Sstevel@tonic-gate port_node->port_commsvc_idx]; 1155*0Sstevel@tonic-gate (void) snprintf(nameaddr, MAXNAMELEN, 1156*0Sstevel@tonic-gate "ibport@%x,%x,%s", 1157*0Sstevel@tonic-gate port_node->port_num, 1158*0Sstevel@tonic-gate port_node->port_pkey, srvname); 1159*0Sstevel@tonic-gate } 1160*0Sstevel@tonic-gate devname = (void *)nameaddr; 1161*0Sstevel@tonic-gate } else { 1162*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", 1163*0Sstevel@tonic-gate "\tbus_config: CONFIG_OBP_ARGS : invalid state!!"); 1164*0Sstevel@tonic-gate 1165*0Sstevel@tonic-gate ret = IBNEX_FAILURE; 1166*0Sstevel@tonic-gate } 1167*0Sstevel@tonic-gate break; 1168*0Sstevel@tonic-gate case BUS_CONFIG_ALL: 1169*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tbus_config: CONFIG_ALL"); 1170*0Sstevel@tonic-gate ibnex_config_all_children(parent); 1171*0Sstevel@tonic-gate break; 1172*0Sstevel@tonic-gate 1173*0Sstevel@tonic-gate case BUS_CONFIG_DRIVER: 1174*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tbus_config: CONFIG_DRIVER"); 1175*0Sstevel@tonic-gate ibnex_config_all_children(parent); 1176*0Sstevel@tonic-gate break; 1177*0Sstevel@tonic-gate 1178*0Sstevel@tonic-gate default: 1179*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tbus_config: error"); 1180*0Sstevel@tonic-gate ret = IBNEX_FAILURE; 1181*0Sstevel@tonic-gate break; 1182*0Sstevel@tonic-gate } 1183*0Sstevel@tonic-gate ndi_devi_exit(parent, circ); 1184*0Sstevel@tonic-gate if (ret == IBNEX_SUCCESS) { 1185*0Sstevel@tonic-gate if (op == BUS_CONFIG_OBP_ARGS) 1186*0Sstevel@tonic-gate op = BUS_CONFIG_ONE; 1187*0Sstevel@tonic-gate 1188*0Sstevel@tonic-gate if (pdip == NULL) 1189*0Sstevel@tonic-gate pdip = parent; 1190*0Sstevel@tonic-gate 1191*0Sstevel@tonic-gate ret = ndi_busop_bus_config( 1192*0Sstevel@tonic-gate pdip, flag, op, devname, child, 0); 1193*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tbus_config:" 1194*0Sstevel@tonic-gate "ndi_busop_bus_config : retval %d", ret); 1195*0Sstevel@tonic-gate return (ret); 1196*0Sstevel@tonic-gate } 1197*0Sstevel@tonic-gate 1198*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", "\tbus_config: Failure End"); 1199*0Sstevel@tonic-gate return (NDI_FAILURE); 1200*0Sstevel@tonic-gate } 1201*0Sstevel@tonic-gate 1202*0Sstevel@tonic-gate 1203*0Sstevel@tonic-gate /* 1204*0Sstevel@tonic-gate * ibnex_config_root_iocnode() 1205*0Sstevel@tonic-gate * Configures one particular instance of the IOC driver. 1206*0Sstevel@tonic-gate * Returns IBNEX_SUCCESS/IBNEX_FAILURE 1207*0Sstevel@tonic-gate */ 1208*0Sstevel@tonic-gate static int 1209*0Sstevel@tonic-gate ibnex_config_root_iocnode(dev_info_t *parent, char *device_name) 1210*0Sstevel@tonic-gate { 1211*0Sstevel@tonic-gate int ret, port = 0, iter = 0; 1212*0Sstevel@tonic-gate boolean_t displayed = B_FALSE; 1213*0Sstevel@tonic-gate char *portstr; 1214*0Sstevel@tonic-gate ib_guid_t hca_guid, iou_guid, ioc_guid; 1215*0Sstevel@tonic-gate ibdm_ioc_info_t *ioc_info; 1216*0Sstevel@tonic-gate ibdm_port_attr_t *port_attr; 1217*0Sstevel@tonic-gate 1218*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", 1219*0Sstevel@tonic-gate "\tconfig_root_iocnode: name %s", device_name); 1220*0Sstevel@tonic-gate 1221*0Sstevel@tonic-gate portstr = strstr(device_name, ":port="); 1222*0Sstevel@tonic-gate if (portstr == NULL) { 1223*0Sstevel@tonic-gate return (IBNEX_FAILURE); 1224*0Sstevel@tonic-gate } 1225*0Sstevel@tonic-gate 1226*0Sstevel@tonic-gate portstr[0] = 0; portstr++; 1227*0Sstevel@tonic-gate if (ibnex_devname2port(portstr, &port)) { 1228*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tconfig_root_iocnode: invalid port"); 1229*0Sstevel@tonic-gate return (IBNEX_FAILURE); 1230*0Sstevel@tonic-gate } 1231*0Sstevel@tonic-gate 1232*0Sstevel@tonic-gate if (ibnex_devname_to_node_n_ioc_guids( 1233*0Sstevel@tonic-gate device_name, &iou_guid, &ioc_guid) != IBNEX_SUCCESS) { 1234*0Sstevel@tonic-gate return (IBNEX_FAILURE); 1235*0Sstevel@tonic-gate } 1236*0Sstevel@tonic-gate 1237*0Sstevel@tonic-gate (void) snprintf(device_name, (IBNEX_MAX_NODEADDR_SZ + 4), 1238*0Sstevel@tonic-gate "ioc@%llX,%llX", (longlong_t)ioc_guid, (longlong_t)iou_guid); 1239*0Sstevel@tonic-gate 1240*0Sstevel@tonic-gate hca_guid = ibtl_ibnex_hcadip2guid(parent); 1241*0Sstevel@tonic-gate if ((port_attr = ibdm_ibnex_probe_hcaport(hca_guid, port)) == NULL) { 1242*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", 1243*0Sstevel@tonic-gate "\tconfig_root_iocnode: Port does not exist"); 1244*0Sstevel@tonic-gate return (IBNEX_FAILURE); 1245*0Sstevel@tonic-gate } 1246*0Sstevel@tonic-gate 1247*0Sstevel@tonic-gate /* Wait until "port is up" */ 1248*0Sstevel@tonic-gate while (port_attr->pa_state != IBT_PORT_ACTIVE) { 1249*0Sstevel@tonic-gate ibdm_ibnex_free_port_attr(port_attr); 1250*0Sstevel@tonic-gate delay(drv_usectohz(10000)); 1251*0Sstevel@tonic-gate if ((port_attr = ibdm_ibnex_probe_hcaport( 1252*0Sstevel@tonic-gate hca_guid, port)) == NULL) { 1253*0Sstevel@tonic-gate return (IBNEX_FAILURE); 1254*0Sstevel@tonic-gate } 1255*0Sstevel@tonic-gate 1256*0Sstevel@tonic-gate if (iter++ == 400) { 1257*0Sstevel@tonic-gate if (displayed == B_FALSE) { 1258*0Sstevel@tonic-gate cmn_err(CE_NOTE, "\tWaiting for Port %d " 1259*0Sstevel@tonic-gate "initialization", port_attr->pa_port_num); 1260*0Sstevel@tonic-gate displayed = B_TRUE; 1261*0Sstevel@tonic-gate } 1262*0Sstevel@tonic-gate } 1263*0Sstevel@tonic-gate } 1264*0Sstevel@tonic-gate ibdm_ibnex_free_port_attr(port_attr); 1265*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tconfig_rootioc_node:" 1266*0Sstevel@tonic-gate "Port is initialized"); 1267*0Sstevel@tonic-gate 1268*0Sstevel@tonic-gate if ((ioc_info = ibdm_ibnex_probe_ioc(iou_guid, ioc_guid, 0)) == NULL) { 1269*0Sstevel@tonic-gate ibdm_ibnex_free_ioc_list(ioc_info); 1270*0Sstevel@tonic-gate return (IBNEX_FAILURE); 1271*0Sstevel@tonic-gate } 1272*0Sstevel@tonic-gate mutex_enter(&ibnex.ibnex_mutex); 1273*0Sstevel@tonic-gate if (ibnex_is_ioc_present(ioc_guid) == IBNEX_SUCCESS) { 1274*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tconfig_root_iocnode: IOC present"); 1275*0Sstevel@tonic-gate ret = IBNEX_SUCCESS; 1276*0Sstevel@tonic-gate } else 1277*0Sstevel@tonic-gate ret = ibnex_ioc_initnode(ioc_info, IBNEX_DEVFS_ENUMERATE); 1278*0Sstevel@tonic-gate mutex_exit(&ibnex.ibnex_mutex); 1279*0Sstevel@tonic-gate ibdm_ibnex_free_ioc_list(ioc_info); 1280*0Sstevel@tonic-gate return (ret); 1281*0Sstevel@tonic-gate } 1282*0Sstevel@tonic-gate 1283*0Sstevel@tonic-gate 1284*0Sstevel@tonic-gate static int 1285*0Sstevel@tonic-gate ibnex_devname2port(char *portstr, int *port) 1286*0Sstevel@tonic-gate { 1287*0Sstevel@tonic-gate char *temp; 1288*0Sstevel@tonic-gate int ret = IBNEX_FAILURE; 1289*0Sstevel@tonic-gate 1290*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tdevname2port: Begin"); 1291*0Sstevel@tonic-gate 1292*0Sstevel@tonic-gate temp = strchr(portstr, '='); 1293*0Sstevel@tonic-gate if (temp != NULL) { 1294*0Sstevel@tonic-gate temp++; 1295*0Sstevel@tonic-gate *port = ibnex_str2int(temp, strlen(temp), &ret); 1296*0Sstevel@tonic-gate } 1297*0Sstevel@tonic-gate return (ret); 1298*0Sstevel@tonic-gate } 1299*0Sstevel@tonic-gate 1300*0Sstevel@tonic-gate 1301*0Sstevel@tonic-gate /* 1302*0Sstevel@tonic-gate * ibnex_config_all_children() 1303*0Sstevel@tonic-gate * Wait for lata SM initialization case before enumerating the nodes 1304*0Sstevel@tonic-gate * Get list of HCA's and HCA port information 1305*0Sstevel@tonic-gate * Create device device nodes and its node properties 1306*0Sstevel@tonic-gate * for port nodes and VPPA nodes 1307*0Sstevel@tonic-gate * Get list of all the IOC node information 1308*0Sstevel@tonic-gate * Create device nodes and its properties for all the IOCs 1309*0Sstevel@tonic-gate * if not created already 1310*0Sstevel@tonic-gate * Bind drivers for all the newly created device nodes 1311*0Sstevel@tonic-gate * Support Pseudo nodes enumerated using their .conf file 1312*0Sstevel@tonic-gate */ 1313*0Sstevel@tonic-gate static void 1314*0Sstevel@tonic-gate ibnex_config_all_children(dev_info_t *parent) 1315*0Sstevel@tonic-gate { 1316*0Sstevel@tonic-gate int ii; 1317*0Sstevel@tonic-gate time_t wait_time; 1318*0Sstevel@tonic-gate ibdm_ioc_info_t *ioc_list, *ioc; 1319*0Sstevel@tonic-gate ibdm_hca_list_t *hca_list; 1320*0Sstevel@tonic-gate ib_guid_t hca_guid; 1321*0Sstevel@tonic-gate 1322*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tconfig_all_children: Begin"); 1323*0Sstevel@tonic-gate 1324*0Sstevel@tonic-gate if (parent != ibnex.ibnex_dip) { 1325*0Sstevel@tonic-gate /* 1326*0Sstevel@tonic-gate * Parent is a HCA node. Enumerate only children of 1327*0Sstevel@tonic-gate * this HCA, port nodes, VPPA & HCA_SVC nodes 1328*0Sstevel@tonic-gate */ 1329*0Sstevel@tonic-gate hca_guid = ibtl_ibnex_hcadip2guid(parent); 1330*0Sstevel@tonic-gate wait_time = ibdm_ibnex_get_waittime( 1331*0Sstevel@tonic-gate hca_guid, &ibnex_port_settling_time); 1332*0Sstevel@tonic-gate if (wait_time) { 1333*0Sstevel@tonic-gate delay(drv_usectohz(wait_time * 1000000)); 1334*0Sstevel@tonic-gate } 1335*0Sstevel@tonic-gate hca_list = ibdm_ibnex_get_hca_info_by_guid(hca_guid); 1336*0Sstevel@tonic-gate if (hca_list == NULL) 1337*0Sstevel@tonic-gate return; 1338*0Sstevel@tonic-gate ibnex_create_hcasvc_nodes(parent, hca_list->hl_hca_port_attr); 1339*0Sstevel@tonic-gate for (ii = 0; ii < hca_list->hl_nports; ii++) { 1340*0Sstevel@tonic-gate ibnex_create_port_nodes( 1341*0Sstevel@tonic-gate parent, &hca_list->hl_port_attr[ii]); 1342*0Sstevel@tonic-gate ibnex_create_vppa_nodes( 1343*0Sstevel@tonic-gate parent, &hca_list->hl_port_attr[ii]); 1344*0Sstevel@tonic-gate } 1345*0Sstevel@tonic-gate ibdm_ibnex_free_hca_list(hca_list); 1346*0Sstevel@tonic-gate } else { 1347*0Sstevel@tonic-gate 1348*0Sstevel@tonic-gate ibnex_pseudo_initnodes(); 1349*0Sstevel@tonic-gate 1350*0Sstevel@tonic-gate /* Parent is a IB nexus. Enumerate all the IOC's */ 1351*0Sstevel@tonic-gate wait_time = ibdm_ibnex_get_waittime( 1352*0Sstevel@tonic-gate 0, &ibnex_port_settling_time); 1353*0Sstevel@tonic-gate if (wait_time) 1354*0Sstevel@tonic-gate delay(drv_usectohz(wait_time * 1000000)); 1355*0Sstevel@tonic-gate 1356*0Sstevel@tonic-gate 1357*0Sstevel@tonic-gate ioc_list = ibdm_ibnex_get_ioc_list(IBDM_IBNEX_NORMAL_PROBE); 1358*0Sstevel@tonic-gate ioc = ioc_list; 1359*0Sstevel@tonic-gate 1360*0Sstevel@tonic-gate mutex_enter(&ibnex.ibnex_mutex); 1361*0Sstevel@tonic-gate 1362*0Sstevel@tonic-gate while (ioc_list) { 1363*0Sstevel@tonic-gate if (ibnex_is_ioc_present( 1364*0Sstevel@tonic-gate ioc_list->ioc_profile.ioc_guid) != IBNEX_SUCCESS) { 1365*0Sstevel@tonic-gate (void) ibnex_ioc_initnode(ioc_list, 1366*0Sstevel@tonic-gate IBNEX_DEVFS_ENUMERATE); 1367*0Sstevel@tonic-gate } 1368*0Sstevel@tonic-gate ioc_list = ioc_list->ioc_next; 1369*0Sstevel@tonic-gate } 1370*0Sstevel@tonic-gate ibnex_config_pseudo_all(); 1371*0Sstevel@tonic-gate mutex_exit(&ibnex.ibnex_mutex); 1372*0Sstevel@tonic-gate ibdm_ibnex_free_ioc_list(ioc); 1373*0Sstevel@tonic-gate } 1374*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tconfig_all_children: End"); 1375*0Sstevel@tonic-gate } 1376*0Sstevel@tonic-gate 1377*0Sstevel@tonic-gate 1378*0Sstevel@tonic-gate /* 1379*0Sstevel@tonic-gate * ibnex_create_port_nodes: 1380*0Sstevel@tonic-gate * Creates a device node per each communication service defined 1381*0Sstevel@tonic-gate * in the "port-commsvc-list" property per HCA port 1382*0Sstevel@tonic-gate */ 1383*0Sstevel@tonic-gate static void 1384*0Sstevel@tonic-gate ibnex_create_port_nodes(dev_info_t *parent, ibdm_port_attr_t *port_attr) 1385*0Sstevel@tonic-gate { 1386*0Sstevel@tonic-gate int idx; 1387*0Sstevel@tonic-gate dev_info_t *dip; 1388*0Sstevel@tonic-gate int rval; 1389*0Sstevel@tonic-gate 1390*0Sstevel@tonic-gate mutex_enter(&ibnex.ibnex_mutex); 1391*0Sstevel@tonic-gate for (idx = 0; idx < ibnex.ibnex_num_comm_svcs; idx++) { 1392*0Sstevel@tonic-gate rval = ibnex_get_dip_from_guid(port_attr->pa_port_guid, 1393*0Sstevel@tonic-gate idx, 0, &dip); 1394*0Sstevel@tonic-gate if (rval != IBNEX_SUCCESS) { 1395*0Sstevel@tonic-gate (void) ibnex_commsvc_initnode(parent, port_attr, idx, 1396*0Sstevel@tonic-gate IBNEX_PORT_COMMSVC_NODE, 0, &rval, 1397*0Sstevel@tonic-gate IBNEX_DEVFS_ENUMERATE); 1398*0Sstevel@tonic-gate } 1399*0Sstevel@tonic-gate } 1400*0Sstevel@tonic-gate mutex_exit(&ibnex.ibnex_mutex); 1401*0Sstevel@tonic-gate } 1402*0Sstevel@tonic-gate 1403*0Sstevel@tonic-gate 1404*0Sstevel@tonic-gate /* 1405*0Sstevel@tonic-gate * ibnex_create_vppa_nodes: 1406*0Sstevel@tonic-gate * Creates a device node per each communication service defined 1407*0Sstevel@tonic-gate * in the "vppa-commsvc-list" property and per each PKEY that 1408*0Sstevel@tonic-gate * this particular port supports and per HCA port 1409*0Sstevel@tonic-gate */ 1410*0Sstevel@tonic-gate static void 1411*0Sstevel@tonic-gate ibnex_create_vppa_nodes(dev_info_t *parent, ibdm_port_attr_t *port_attr) 1412*0Sstevel@tonic-gate { 1413*0Sstevel@tonic-gate int idx, ii; 1414*0Sstevel@tonic-gate int rval; 1415*0Sstevel@tonic-gate ib_pkey_t pkey; 1416*0Sstevel@tonic-gate dev_info_t *dip; 1417*0Sstevel@tonic-gate 1418*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tcreate_vppa_nodes: Begin"); 1419*0Sstevel@tonic-gate 1420*0Sstevel@tonic-gate mutex_enter(&ibnex.ibnex_mutex); 1421*0Sstevel@tonic-gate if (port_attr->pa_state != IBT_PORT_ACTIVE) { 1422*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tcreate_vppa_nodes: " 1423*0Sstevel@tonic-gate "Port %d is down", port_attr->pa_port_num); 1424*0Sstevel@tonic-gate mutex_exit(&ibnex.ibnex_mutex); 1425*0Sstevel@tonic-gate return; 1426*0Sstevel@tonic-gate } 1427*0Sstevel@tonic-gate for (idx = 0; idx < ibnex.ibnex_nvppa_comm_svcs; idx++) { 1428*0Sstevel@tonic-gate for (ii = 0; ii < port_attr->pa_npkeys; ii++) { 1429*0Sstevel@tonic-gate pkey = port_attr->pa_pkey_tbl[ii].pt_pkey; 1430*0Sstevel@tonic-gate 1431*0Sstevel@tonic-gate if (IBNEX_INVALID_PKEY(pkey)) { 1432*0Sstevel@tonic-gate continue; 1433*0Sstevel@tonic-gate } 1434*0Sstevel@tonic-gate rval = ibnex_get_dip_from_guid( 1435*0Sstevel@tonic-gate port_attr->pa_port_guid, idx, pkey, &dip); 1436*0Sstevel@tonic-gate if (rval != IBNEX_SUCCESS) { 1437*0Sstevel@tonic-gate (void) ibnex_commsvc_initnode(parent, port_attr, 1438*0Sstevel@tonic-gate idx, IBNEX_VPPA_COMMSVC_NODE, 1439*0Sstevel@tonic-gate pkey, &rval, IBNEX_CFGADM_ENUMERATE); 1440*0Sstevel@tonic-gate IBTF_DPRINTF_L5("ibnex", "\tcreate_vppa_nodes: " 1441*0Sstevel@tonic-gate "commsvc_initnode failed rval %x", rval); 1442*0Sstevel@tonic-gate } 1443*0Sstevel@tonic-gate } 1444*0Sstevel@tonic-gate } 1445*0Sstevel@tonic-gate mutex_exit(&ibnex.ibnex_mutex); 1446*0Sstevel@tonic-gate } 1447*0Sstevel@tonic-gate 1448*0Sstevel@tonic-gate 1449*0Sstevel@tonic-gate /* 1450*0Sstevel@tonic-gate * ibnex_create_hcasvc_nodes: 1451*0Sstevel@tonic-gate * Creates a device node per each communication service defined 1452*0Sstevel@tonic-gate * in the "port-commsvc-list" property per HCA port 1453*0Sstevel@tonic-gate */ 1454*0Sstevel@tonic-gate static void 1455*0Sstevel@tonic-gate ibnex_create_hcasvc_nodes(dev_info_t *parent, ibdm_port_attr_t *port_attr) 1456*0Sstevel@tonic-gate { 1457*0Sstevel@tonic-gate int idx; 1458*0Sstevel@tonic-gate dev_info_t *dip; 1459*0Sstevel@tonic-gate int rval; 1460*0Sstevel@tonic-gate 1461*0Sstevel@tonic-gate mutex_enter(&ibnex.ibnex_mutex); 1462*0Sstevel@tonic-gate for (idx = 0; idx < ibnex.ibnex_nhcasvc_comm_svcs; idx++) { 1463*0Sstevel@tonic-gate rval = ibnex_get_dip_from_guid(port_attr->pa_port_guid, 1464*0Sstevel@tonic-gate idx, 0, &dip); 1465*0Sstevel@tonic-gate if (rval != IBNEX_SUCCESS) { 1466*0Sstevel@tonic-gate (void) ibnex_commsvc_initnode(parent, port_attr, idx, 1467*0Sstevel@tonic-gate IBNEX_HCASVC_COMMSVC_NODE, 0, &rval, 1468*0Sstevel@tonic-gate IBNEX_DEVFS_ENUMERATE); 1469*0Sstevel@tonic-gate IBTF_DPRINTF_L5("ibnex", "create_hcasvc_nodes: " 1470*0Sstevel@tonic-gate "commsvc_initnode failed, rval %x", rval); 1471*0Sstevel@tonic-gate } 1472*0Sstevel@tonic-gate } 1473*0Sstevel@tonic-gate mutex_exit(&ibnex.ibnex_mutex); 1474*0Sstevel@tonic-gate } 1475*0Sstevel@tonic-gate 1476*0Sstevel@tonic-gate /* 1477*0Sstevel@tonic-gate * ibnex_is_ioc_present() 1478*0Sstevel@tonic-gate * Returns IBNEX_SUCCESS if an entry found in the global linked list 1479*0Sstevel@tonic-gate * Returns IBNEX_FAILURE, if no match found 1480*0Sstevel@tonic-gate */ 1481*0Sstevel@tonic-gate static int 1482*0Sstevel@tonic-gate ibnex_is_ioc_present(ib_guid_t ioc_guid) 1483*0Sstevel@tonic-gate { 1484*0Sstevel@tonic-gate ibnex_node_data_t *head; 1485*0Sstevel@tonic-gate ibnex_ioc_node_t *ioc; 1486*0Sstevel@tonic-gate int ret = IBNEX_FAILURE; 1487*0Sstevel@tonic-gate 1488*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tis_ioc_present: Begin"); 1489*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&ibnex.ibnex_mutex)); 1490*0Sstevel@tonic-gate 1491*0Sstevel@tonic-gate head = ibnex.ibnex_ioc_node_head; 1492*0Sstevel@tonic-gate while (head) { 1493*0Sstevel@tonic-gate ioc = &head->node_data.ioc_node; 1494*0Sstevel@tonic-gate if (ioc->ioc_guid == ioc_guid) 1495*0Sstevel@tonic-gate break; 1496*0Sstevel@tonic-gate head = head->node_next; 1497*0Sstevel@tonic-gate } 1498*0Sstevel@tonic-gate if (head) 1499*0Sstevel@tonic-gate ret = IBNEX_SUCCESS; 1500*0Sstevel@tonic-gate 1501*0Sstevel@tonic-gate return (ret); 1502*0Sstevel@tonic-gate } 1503*0Sstevel@tonic-gate 1504*0Sstevel@tonic-gate 1505*0Sstevel@tonic-gate /* 1506*0Sstevel@tonic-gate * ibnex_bus_unconfig() 1507*0Sstevel@tonic-gate * 1508*0Sstevel@tonic-gate * Unconfigure a particular device node or all instance of a device 1509*0Sstevel@tonic-gate * driver device or all children of IBnex 1510*0Sstevel@tonic-gate */ 1511*0Sstevel@tonic-gate static int 1512*0Sstevel@tonic-gate ibnex_bus_unconfig(dev_info_t *parent, 1513*0Sstevel@tonic-gate uint_t flag, ddi_bus_config_op_t op, void *device_name) 1514*0Sstevel@tonic-gate { 1515*0Sstevel@tonic-gate return (ndi_busop_bus_unconfig(parent, flag, op, device_name)); 1516*0Sstevel@tonic-gate } 1517*0Sstevel@tonic-gate 1518*0Sstevel@tonic-gate 1519*0Sstevel@tonic-gate /* 1520*0Sstevel@tonic-gate * ibnex_config_port_node() 1521*0Sstevel@tonic-gate * 1522*0Sstevel@tonic-gate * Configures a particular port / HCA node for a particular 1523*0Sstevel@tonic-gate * communication service. 1524*0Sstevel@tonic-gate * The format of the device_name is 1525*0Sstevel@tonic-gate * ibport@<Port#>,<pkey>,<service name> 1526*0Sstevel@tonic-gate * where pkey = 0 for port communication service nodes 1527*0Sstevel@tonic-gate * Port# = 0 for HCA_SVC communication service nodes 1528*0Sstevel@tonic-gate * Returns "dev_info_t" of the "child" node just created 1529*0Sstevel@tonic-gate * NULL when failed to enumerate the child node 1530*0Sstevel@tonic-gate */ 1531*0Sstevel@tonic-gate static dev_info_t * 1532*0Sstevel@tonic-gate ibnex_config_port_node(dev_info_t *parent, char *devname) 1533*0Sstevel@tonic-gate { 1534*0Sstevel@tonic-gate int ii, index; 1535*0Sstevel@tonic-gate int rval; 1536*0Sstevel@tonic-gate time_t wait_time; 1537*0Sstevel@tonic-gate uint8_t port_num; 1538*0Sstevel@tonic-gate ib_guid_t hca_guid, port_guid; 1539*0Sstevel@tonic-gate ib_pkey_t pkey; 1540*0Sstevel@tonic-gate dev_info_t *cdip; 1541*0Sstevel@tonic-gate ibdm_port_attr_t *port_attr; 1542*0Sstevel@tonic-gate ibdm_hca_list_t *hca_list; 1543*0Sstevel@tonic-gate 1544*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tconfig_port_node: %s", devname); 1545*0Sstevel@tonic-gate 1546*0Sstevel@tonic-gate if (ibnex_get_pkey_commsvc_index_portnum(devname, 1547*0Sstevel@tonic-gate &index, &pkey, &port_num) != IBNEX_SUCCESS) { 1548*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", 1549*0Sstevel@tonic-gate "\tconfig_port_node: Invalid Service Name"); 1550*0Sstevel@tonic-gate return (NULL); 1551*0Sstevel@tonic-gate } 1552*0Sstevel@tonic-gate 1553*0Sstevel@tonic-gate hca_guid = ibtl_ibnex_hcadip2guid(parent); 1554*0Sstevel@tonic-gate if (port_num == 0) { 1555*0Sstevel@tonic-gate /* 1556*0Sstevel@tonic-gate * Use the dummy port attribute for HCA node in hca_list 1557*0Sstevel@tonic-gate * Note : pa_state is always IBT_PORT_ACTIVE. 1558*0Sstevel@tonic-gate */ 1559*0Sstevel@tonic-gate hca_list = ibdm_ibnex_get_hca_info_by_guid(hca_guid); 1560*0Sstevel@tonic-gate ASSERT(hca_list != NULL); 1561*0Sstevel@tonic-gate port_attr = hca_list->hl_hca_port_attr; 1562*0Sstevel@tonic-gate } else { 1563*0Sstevel@tonic-gate if ((port_attr = ibdm_ibnex_probe_hcaport( 1564*0Sstevel@tonic-gate hca_guid, port_num)) == NULL) { 1565*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", 1566*0Sstevel@tonic-gate "\tconfig_port_node: Port does not exist"); 1567*0Sstevel@tonic-gate return (NULL); 1568*0Sstevel@tonic-gate } 1569*0Sstevel@tonic-gate 1570*0Sstevel@tonic-gate if (port_attr->pa_state != IBT_PORT_ACTIVE) { 1571*0Sstevel@tonic-gate wait_time = ibdm_ibnex_get_waittime( 1572*0Sstevel@tonic-gate hca_guid, &ibnex_port_settling_time); 1573*0Sstevel@tonic-gate if (wait_time) { 1574*0Sstevel@tonic-gate delay(drv_usectohz(wait_time * 1000000)); 1575*0Sstevel@tonic-gate } 1576*0Sstevel@tonic-gate ibdm_ibnex_free_port_attr(port_attr); 1577*0Sstevel@tonic-gate if ((port_attr = ibdm_ibnex_probe_hcaport( 1578*0Sstevel@tonic-gate hca_guid, port_num)) == NULL) { 1579*0Sstevel@tonic-gate return (NULL); 1580*0Sstevel@tonic-gate } 1581*0Sstevel@tonic-gate } 1582*0Sstevel@tonic-gate } 1583*0Sstevel@tonic-gate 1584*0Sstevel@tonic-gate port_guid = port_attr->pa_port_guid; 1585*0Sstevel@tonic-gate mutex_enter(&ibnex.ibnex_mutex); 1586*0Sstevel@tonic-gate if ((rval = ibnex_get_dip_from_guid(port_guid, index, pkey, 1587*0Sstevel@tonic-gate &cdip)) == IBNEX_SUCCESS) { 1588*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tconfig_port_node: Node exists"); 1589*0Sstevel@tonic-gate mutex_exit(&ibnex.ibnex_mutex); 1590*0Sstevel@tonic-gate if (port_num != 0) 1591*0Sstevel@tonic-gate ibdm_ibnex_free_port_attr(port_attr); 1592*0Sstevel@tonic-gate else 1593*0Sstevel@tonic-gate ibdm_ibnex_free_hca_list(hca_list); 1594*0Sstevel@tonic-gate return (cdip); 1595*0Sstevel@tonic-gate } 1596*0Sstevel@tonic-gate 1597*0Sstevel@tonic-gate if (pkey == 0 && port_num != 0) { 1598*0Sstevel@tonic-gate cdip = ibnex_commsvc_initnode(parent, 1599*0Sstevel@tonic-gate port_attr, index, IBNEX_PORT_COMMSVC_NODE, pkey, &rval, 1600*0Sstevel@tonic-gate IBNEX_DEVFS_ENUMERATE); 1601*0Sstevel@tonic-gate IBTF_DPRINTF_L5("ibnex", 1602*0Sstevel@tonic-gate "\t ibnex_commsvc_initnode rval %x", rval); 1603*0Sstevel@tonic-gate } else if (pkey == 0 && port_num == 0) { 1604*0Sstevel@tonic-gate cdip = ibnex_commsvc_initnode(parent, 1605*0Sstevel@tonic-gate port_attr, index, IBNEX_HCASVC_COMMSVC_NODE, pkey, &rval, 1606*0Sstevel@tonic-gate IBNEX_DEVFS_ENUMERATE); 1607*0Sstevel@tonic-gate IBTF_DPRINTF_L5("ibnex", 1608*0Sstevel@tonic-gate "\t ibnex_commsvc_initnode rval %x", rval); 1609*0Sstevel@tonic-gate } else { 1610*0Sstevel@tonic-gate if (port_attr->pa_state != IBT_PORT_ACTIVE) { 1611*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tconfig_port_nodes: " 1612*0Sstevel@tonic-gate "Port %d is down", port_attr->pa_port_num); 1613*0Sstevel@tonic-gate ibdm_ibnex_free_port_attr(port_attr); 1614*0Sstevel@tonic-gate mutex_exit(&ibnex.ibnex_mutex); 1615*0Sstevel@tonic-gate return (NULL); 1616*0Sstevel@tonic-gate } 1617*0Sstevel@tonic-gate for (ii = 0; ii < port_attr->pa_npkeys; ii++) { 1618*0Sstevel@tonic-gate if (pkey == port_attr->pa_pkey_tbl[ii].pt_pkey) { 1619*0Sstevel@tonic-gate cdip = ibnex_commsvc_initnode(parent, port_attr, 1620*0Sstevel@tonic-gate index, IBNEX_VPPA_COMMSVC_NODE, 1621*0Sstevel@tonic-gate pkey, &rval, IBNEX_CFGADM_ENUMERATE); 1622*0Sstevel@tonic-gate IBTF_DPRINTF_L5("ibnex", 1623*0Sstevel@tonic-gate "\t ibnex_commsvc_initnode rval %x", rval); 1624*0Sstevel@tonic-gate break; 1625*0Sstevel@tonic-gate } 1626*0Sstevel@tonic-gate } 1627*0Sstevel@tonic-gate } 1628*0Sstevel@tonic-gate mutex_exit(&ibnex.ibnex_mutex); 1629*0Sstevel@tonic-gate if (port_num != 0) 1630*0Sstevel@tonic-gate ibdm_ibnex_free_port_attr(port_attr); 1631*0Sstevel@tonic-gate else 1632*0Sstevel@tonic-gate ibdm_ibnex_free_hca_list(hca_list); 1633*0Sstevel@tonic-gate return (cdip); 1634*0Sstevel@tonic-gate } 1635*0Sstevel@tonic-gate 1636*0Sstevel@tonic-gate 1637*0Sstevel@tonic-gate /* 1638*0Sstevel@tonic-gate * ibnex_config_obp_args() 1639*0Sstevel@tonic-gate * Configures a particular port node for a IP over IB communication 1640*0Sstevel@tonic-gate * service. 1641*0Sstevel@tonic-gate * The format of the input string "devname" is 1642*0Sstevel@tonic-gate * port=x,pkey=y,protocol=ip,<wanboot options> 1643*0Sstevel@tonic-gate * Thr format of the node name created here is 1644*0Sstevel@tonic-gate * ibport@<Port#>,<pkey>,<service name> 1645*0Sstevel@tonic-gate * where pkey = 0 for port communication service nodes 1646*0Sstevel@tonic-gate * Returns "dev_info_t" of the "child" node just created 1647*0Sstevel@tonic-gate * NULL when failed to enumerate the child node 1648*0Sstevel@tonic-gate * 1649*0Sstevel@tonic-gate */ 1650*0Sstevel@tonic-gate static dev_info_t * 1651*0Sstevel@tonic-gate ibnex_config_obp_args(dev_info_t *parent, char *devname) 1652*0Sstevel@tonic-gate { 1653*0Sstevel@tonic-gate int ii, index; 1654*0Sstevel@tonic-gate int rval, iter = 0; 1655*0Sstevel@tonic-gate char *temp; 1656*0Sstevel@tonic-gate uint8_t port_num; 1657*0Sstevel@tonic-gate ib_guid_t hca_guid, port_guid; 1658*0Sstevel@tonic-gate ib_pkey_t pkey; 1659*0Sstevel@tonic-gate dev_info_t *cdip; 1660*0Sstevel@tonic-gate boolean_t displayed = B_FALSE; 1661*0Sstevel@tonic-gate ibdm_port_attr_t *port_attr; 1662*0Sstevel@tonic-gate 1663*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tconfig_obp_args: %s", devname); 1664*0Sstevel@tonic-gate 1665*0Sstevel@tonic-gate /* Is this OBP node for IPoIB ? */ 1666*0Sstevel@tonic-gate temp = devname; 1667*0Sstevel@tonic-gate do { 1668*0Sstevel@tonic-gate temp = strstr(temp, ",protocol=ip"); 1669*0Sstevel@tonic-gate if (temp == NULL) 1670*0Sstevel@tonic-gate break; 1671*0Sstevel@tonic-gate 1672*0Sstevel@tonic-gate if (strlen(devname) > (int)((temp - devname) + 12)) { 1673*0Sstevel@tonic-gate if (temp[12] == ',') 1674*0Sstevel@tonic-gate break; 1675*0Sstevel@tonic-gate } else { 1676*0Sstevel@tonic-gate break; 1677*0Sstevel@tonic-gate } 1678*0Sstevel@tonic-gate temp++; 1679*0Sstevel@tonic-gate } while (temp); 1680*0Sstevel@tonic-gate 1681*0Sstevel@tonic-gate if (temp == NULL) 1682*0Sstevel@tonic-gate return (NULL); 1683*0Sstevel@tonic-gate if (ibnex_prom_devname_to_pkey_n_portnum( 1684*0Sstevel@tonic-gate devname, &pkey, &port_num) != IBNEX_SUCCESS) { 1685*0Sstevel@tonic-gate return (NULL); 1686*0Sstevel@tonic-gate } 1687*0Sstevel@tonic-gate for (index = 0; index < ibnex.ibnex_nvppa_comm_svcs; index++) { 1688*0Sstevel@tonic-gate if (strcmp(ibnex.ibnex_vppa_comm_svc_names[index], 1689*0Sstevel@tonic-gate "ipib") == 0) { 1690*0Sstevel@tonic-gate break; 1691*0Sstevel@tonic-gate } 1692*0Sstevel@tonic-gate } 1693*0Sstevel@tonic-gate 1694*0Sstevel@tonic-gate hca_guid = ibtl_ibnex_hcadip2guid(parent); 1695*0Sstevel@tonic-gate if ((port_attr = ibdm_ibnex_probe_hcaport( 1696*0Sstevel@tonic-gate hca_guid, port_num)) == NULL) { 1697*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", 1698*0Sstevel@tonic-gate "\tconfig_port_node: Port does not exist"); 1699*0Sstevel@tonic-gate return (NULL); 1700*0Sstevel@tonic-gate } 1701*0Sstevel@tonic-gate 1702*0Sstevel@tonic-gate /* Wait until "port is up" */ 1703*0Sstevel@tonic-gate while (port_attr->pa_state != IBT_PORT_ACTIVE) { 1704*0Sstevel@tonic-gate ibdm_ibnex_free_port_attr(port_attr); 1705*0Sstevel@tonic-gate delay(drv_usectohz(10000)); 1706*0Sstevel@tonic-gate if ((port_attr = ibdm_ibnex_probe_hcaport( 1707*0Sstevel@tonic-gate hca_guid, port_num)) == NULL) { 1708*0Sstevel@tonic-gate return (NULL); 1709*0Sstevel@tonic-gate } 1710*0Sstevel@tonic-gate if (iter++ == 400) { 1711*0Sstevel@tonic-gate if (displayed == B_FALSE) { 1712*0Sstevel@tonic-gate cmn_err(CE_NOTE, "\tWaiting for Port %d " 1713*0Sstevel@tonic-gate "initialization", port_attr->pa_port_num); 1714*0Sstevel@tonic-gate displayed = B_TRUE; 1715*0Sstevel@tonic-gate } 1716*0Sstevel@tonic-gate } 1717*0Sstevel@tonic-gate } 1718*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tPort is initialized"); 1719*0Sstevel@tonic-gate 1720*0Sstevel@tonic-gate mutex_enter(&ibnex.ibnex_mutex); 1721*0Sstevel@tonic-gate port_guid = port_attr->pa_port_guid; 1722*0Sstevel@tonic-gate if ((rval = ibnex_get_dip_from_guid(port_guid, index, pkey, 1723*0Sstevel@tonic-gate &cdip)) == IBNEX_SUCCESS) { 1724*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tconfig_port_node: Node exists"); 1725*0Sstevel@tonic-gate mutex_exit(&ibnex.ibnex_mutex); 1726*0Sstevel@tonic-gate ibdm_ibnex_free_port_attr(port_attr); 1727*0Sstevel@tonic-gate return (cdip); 1728*0Sstevel@tonic-gate } 1729*0Sstevel@tonic-gate for (ii = 0; ii < port_attr->pa_npkeys; ii++) { 1730*0Sstevel@tonic-gate if (pkey == port_attr->pa_pkey_tbl[ii].pt_pkey) { 1731*0Sstevel@tonic-gate cdip = ibnex_commsvc_initnode(parent, port_attr, 1732*0Sstevel@tonic-gate index, IBNEX_VPPA_COMMSVC_NODE, pkey, &rval, 1733*0Sstevel@tonic-gate IBNEX_CFGADM_ENUMERATE); 1734*0Sstevel@tonic-gate IBTF_DPRINTF_L5("ibnex", 1735*0Sstevel@tonic-gate "\t ibnex_commsvc_initnode rval %x", rval); 1736*0Sstevel@tonic-gate break; 1737*0Sstevel@tonic-gate } 1738*0Sstevel@tonic-gate } 1739*0Sstevel@tonic-gate mutex_exit(&ibnex.ibnex_mutex); 1740*0Sstevel@tonic-gate 1741*0Sstevel@tonic-gate ibdm_ibnex_free_port_attr(port_attr); 1742*0Sstevel@tonic-gate return (cdip); 1743*0Sstevel@tonic-gate } 1744*0Sstevel@tonic-gate 1745*0Sstevel@tonic-gate 1746*0Sstevel@tonic-gate /* 1747*0Sstevel@tonic-gate * ibnex_prom_devname_to_pkey_n_portnum() 1748*0Sstevel@tonic-gate * Parses the device node name and extracts "PKEY" and "port#" 1749*0Sstevel@tonic-gate * Returns IBNEX_SUCCESS/IBNEX_FAILURE 1750*0Sstevel@tonic-gate */ 1751*0Sstevel@tonic-gate static int 1752*0Sstevel@tonic-gate ibnex_prom_devname_to_pkey_n_portnum( 1753*0Sstevel@tonic-gate char *devname, ib_pkey_t *pkey, uint8_t *port) 1754*0Sstevel@tonic-gate { 1755*0Sstevel@tonic-gate int ret = IBNEX_SUCCESS; 1756*0Sstevel@tonic-gate char *tmp, *tmp1; 1757*0Sstevel@tonic-gate 1758*0Sstevel@tonic-gate if ((tmp = strstr(devname, "port=")) != NULL) { 1759*0Sstevel@tonic-gate if ((tmp = strchr(++tmp, '=')) != NULL) 1760*0Sstevel@tonic-gate if ((tmp1 = strchr(++tmp, ',')) != NULL) 1761*0Sstevel@tonic-gate *port = ibnex_str2int(tmp, (tmp1 - tmp), &ret); 1762*0Sstevel@tonic-gate } else 1763*0Sstevel@tonic-gate ret = IBNEX_FAILURE; 1764*0Sstevel@tonic-gate 1765*0Sstevel@tonic-gate if ((ret == IBNEX_SUCCESS) && 1766*0Sstevel@tonic-gate (tmp = strstr(devname, "pkey=")) != NULL) { 1767*0Sstevel@tonic-gate if ((tmp = strchr(++tmp, '=')) != NULL) 1768*0Sstevel@tonic-gate if ((tmp1 = strchr(++tmp, ',')) != NULL) 1769*0Sstevel@tonic-gate *pkey = ibnex_str2hex(tmp, (tmp1 - tmp), &ret); 1770*0Sstevel@tonic-gate } else 1771*0Sstevel@tonic-gate ret = IBNEX_FAILURE; 1772*0Sstevel@tonic-gate 1773*0Sstevel@tonic-gate return (ret); 1774*0Sstevel@tonic-gate } 1775*0Sstevel@tonic-gate 1776*0Sstevel@tonic-gate 1777*0Sstevel@tonic-gate /* 1778*0Sstevel@tonic-gate * ibnex_get_pkey_commsvc_index_portnum() 1779*0Sstevel@tonic-gate * Parses the device node name and extracts PKEY, communication 1780*0Sstevel@tonic-gate * service index & Port #. 1781*0Sstevel@tonic-gate * Returns IBNEX_SUCCESS/IBNEX_FAILURE 1782*0Sstevel@tonic-gate */ 1783*0Sstevel@tonic-gate static int 1784*0Sstevel@tonic-gate ibnex_get_pkey_commsvc_index_portnum(char *device_name, int *index, 1785*0Sstevel@tonic-gate ib_pkey_t *pkey, uint8_t *port_num) 1786*0Sstevel@tonic-gate { 1787*0Sstevel@tonic-gate char *srv, **service_name, *temp; 1788*0Sstevel@tonic-gate int ii, ncommsvcs, ret; 1789*0Sstevel@tonic-gate 1790*0Sstevel@tonic-gate if (ibnex_devname_to_portnum(device_name, port_num) != 1791*0Sstevel@tonic-gate IBNEX_SUCCESS) { 1792*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", 1793*0Sstevel@tonic-gate "\tget_pkey_commsvc_index_portnum: Invalid PortGuid"); 1794*0Sstevel@tonic-gate return (NULL); 1795*0Sstevel@tonic-gate } 1796*0Sstevel@tonic-gate srv = strchr(device_name, ','); 1797*0Sstevel@tonic-gate if (srv == 0) 1798*0Sstevel@tonic-gate return (IBNEX_FAILURE); 1799*0Sstevel@tonic-gate 1800*0Sstevel@tonic-gate srv++; 1801*0Sstevel@tonic-gate temp = strchr(srv, ','); 1802*0Sstevel@tonic-gate if (temp == 0) 1803*0Sstevel@tonic-gate return (IBNEX_FAILURE); 1804*0Sstevel@tonic-gate temp++; 1805*0Sstevel@tonic-gate *pkey = ibnex_str2hex(srv, (temp - srv - 1), &ret); 1806*0Sstevel@tonic-gate if (ret != IBNEX_SUCCESS) 1807*0Sstevel@tonic-gate return (ret); 1808*0Sstevel@tonic-gate 1809*0Sstevel@tonic-gate if (*pkey == 0 && *port_num != 0) { 1810*0Sstevel@tonic-gate service_name = ibnex.ibnex_comm_svc_names; 1811*0Sstevel@tonic-gate ncommsvcs = ibnex.ibnex_num_comm_svcs; 1812*0Sstevel@tonic-gate } else if (*pkey == 0 && *port_num == 0) { 1813*0Sstevel@tonic-gate service_name = ibnex.ibnex_hcasvc_comm_svc_names; 1814*0Sstevel@tonic-gate ncommsvcs = ibnex.ibnex_nhcasvc_comm_svcs; 1815*0Sstevel@tonic-gate } else { 1816*0Sstevel@tonic-gate service_name = ibnex.ibnex_vppa_comm_svc_names; 1817*0Sstevel@tonic-gate ncommsvcs = ibnex.ibnex_nvppa_comm_svcs; 1818*0Sstevel@tonic-gate } 1819*0Sstevel@tonic-gate 1820*0Sstevel@tonic-gate for (ii = 0; ii < ncommsvcs; ii++) { 1821*0Sstevel@tonic-gate if (strcmp(service_name[ii], temp) == 0) { 1822*0Sstevel@tonic-gate break; 1823*0Sstevel@tonic-gate } 1824*0Sstevel@tonic-gate } 1825*0Sstevel@tonic-gate if (ii == ncommsvcs) 1826*0Sstevel@tonic-gate return (IBNEX_FAILURE); 1827*0Sstevel@tonic-gate 1828*0Sstevel@tonic-gate *index = ii; 1829*0Sstevel@tonic-gate return (IBNEX_SUCCESS); 1830*0Sstevel@tonic-gate } 1831*0Sstevel@tonic-gate 1832*0Sstevel@tonic-gate 1833*0Sstevel@tonic-gate /* 1834*0Sstevel@tonic-gate * ibnex_devname_to_portnum() 1835*0Sstevel@tonic-gate * Get portguid from device name 1836*0Sstevel@tonic-gate * Returns IBNEX_SUCCESS/IBNEX_FAILURE 1837*0Sstevel@tonic-gate */ 1838*0Sstevel@tonic-gate static int 1839*0Sstevel@tonic-gate ibnex_devname_to_portnum(char *device_name, uint8_t *portnum) 1840*0Sstevel@tonic-gate { 1841*0Sstevel@tonic-gate int ret; 1842*0Sstevel@tonic-gate char *temp1, *temp2; 1843*0Sstevel@tonic-gate 1844*0Sstevel@tonic-gate temp1 = strchr(device_name, '@'); 1845*0Sstevel@tonic-gate if (temp1 == NULL) { 1846*0Sstevel@tonic-gate return (IBNEX_FAILURE); 1847*0Sstevel@tonic-gate } 1848*0Sstevel@tonic-gate temp2 = strchr(temp1, ','); 1849*0Sstevel@tonic-gate if (temp2 == NULL) 1850*0Sstevel@tonic-gate return (IBNEX_FAILURE); 1851*0Sstevel@tonic-gate temp1++; 1852*0Sstevel@tonic-gate *portnum = ibnex_str2hex(temp1, (temp2 - temp1), &ret); 1853*0Sstevel@tonic-gate return (ret); 1854*0Sstevel@tonic-gate } 1855*0Sstevel@tonic-gate 1856*0Sstevel@tonic-gate 1857*0Sstevel@tonic-gate /* 1858*0Sstevel@tonic-gate * ibnex_config_ioc_node() 1859*0Sstevel@tonic-gate * Configures one particular instance of the IOC driver. 1860*0Sstevel@tonic-gate * Returns IBNEX_SUCCESS/IBNEX_FAILURE 1861*0Sstevel@tonic-gate */ 1862*0Sstevel@tonic-gate static int 1863*0Sstevel@tonic-gate ibnex_config_ioc_node(char *device_name) 1864*0Sstevel@tonic-gate { 1865*0Sstevel@tonic-gate int ret; 1866*0Sstevel@tonic-gate time_t wait_time; 1867*0Sstevel@tonic-gate ib_guid_t iou_guid, ioc_guid; 1868*0Sstevel@tonic-gate ibdm_ioc_info_t *ioc_info; 1869*0Sstevel@tonic-gate 1870*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tconfig_ioc_node: Begin"); 1871*0Sstevel@tonic-gate 1872*0Sstevel@tonic-gate if (ibnex_devname_to_node_n_ioc_guids( 1873*0Sstevel@tonic-gate device_name, &iou_guid, &ioc_guid) != IBNEX_SUCCESS) { 1874*0Sstevel@tonic-gate return (IBNEX_FAILURE); 1875*0Sstevel@tonic-gate } 1876*0Sstevel@tonic-gate 1877*0Sstevel@tonic-gate wait_time = ibdm_ibnex_get_waittime(0, &ibnex_port_settling_time); 1878*0Sstevel@tonic-gate if (wait_time) 1879*0Sstevel@tonic-gate delay(drv_usectohz(wait_time * 1000000)); 1880*0Sstevel@tonic-gate 1881*0Sstevel@tonic-gate if ((ioc_info = ibdm_ibnex_probe_ioc(iou_guid, ioc_guid, 0)) == 1882*0Sstevel@tonic-gate NULL) { 1883*0Sstevel@tonic-gate ibdm_ibnex_free_ioc_list(ioc_info); 1884*0Sstevel@tonic-gate return (IBNEX_FAILURE); 1885*0Sstevel@tonic-gate } 1886*0Sstevel@tonic-gate mutex_enter(&ibnex.ibnex_mutex); 1887*0Sstevel@tonic-gate if (ibnex_is_ioc_present(ioc_guid) == IBNEX_SUCCESS) { 1888*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tconfig_ioc_node: IOC present"); 1889*0Sstevel@tonic-gate ret = IBNEX_SUCCESS; 1890*0Sstevel@tonic-gate } else 1891*0Sstevel@tonic-gate ret = ibnex_ioc_initnode(ioc_info, IBNEX_DEVFS_ENUMERATE); 1892*0Sstevel@tonic-gate mutex_exit(&ibnex.ibnex_mutex); 1893*0Sstevel@tonic-gate ibdm_ibnex_free_ioc_list(ioc_info); 1894*0Sstevel@tonic-gate return (ret); 1895*0Sstevel@tonic-gate } 1896*0Sstevel@tonic-gate 1897*0Sstevel@tonic-gate 1898*0Sstevel@tonic-gate /* 1899*0Sstevel@tonic-gate * ibnex_devname_to_node_n_ioc_guids() 1900*0Sstevel@tonic-gate * Get node guid and ioc guid from the device name 1901*0Sstevel@tonic-gate * Format of the device node name is: 1902*0Sstevel@tonic-gate * ioc@<IOC GUID>,<IOU GUID> 1903*0Sstevel@tonic-gate * Returns IBNEX_SUCCESS/IBNEX_FAILURE 1904*0Sstevel@tonic-gate */ 1905*0Sstevel@tonic-gate static int 1906*0Sstevel@tonic-gate ibnex_devname_to_node_n_ioc_guids( 1907*0Sstevel@tonic-gate char *device_name, ib_guid_t *iou_guid, ib_guid_t *ioc_guid) 1908*0Sstevel@tonic-gate { 1909*0Sstevel@tonic-gate char *temp1, *temp; 1910*0Sstevel@tonic-gate int len, ret; 1911*0Sstevel@tonic-gate 1912*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tdevname_to_node_n_ioc_guids:" 1913*0Sstevel@tonic-gate "Device Name %s", device_name); 1914*0Sstevel@tonic-gate 1915*0Sstevel@tonic-gate if ((temp = strchr(device_name, '@')) == NULL) { 1916*0Sstevel@tonic-gate return (IBNEX_FAILURE); 1917*0Sstevel@tonic-gate } 1918*0Sstevel@tonic-gate if ((temp1 = strchr(++temp, ',')) == NULL) { 1919*0Sstevel@tonic-gate return (IBNEX_FAILURE); 1920*0Sstevel@tonic-gate } 1921*0Sstevel@tonic-gate *ioc_guid = ibnex_str2hex(temp, (temp1 - temp), &ret); 1922*0Sstevel@tonic-gate if (ret == IBNEX_SUCCESS) { 1923*0Sstevel@tonic-gate len = device_name + strlen(device_name) - ++temp1; 1924*0Sstevel@tonic-gate *iou_guid = ibnex_str2hex(temp1, len, &ret); 1925*0Sstevel@tonic-gate } 1926*0Sstevel@tonic-gate return (ret); 1927*0Sstevel@tonic-gate } 1928*0Sstevel@tonic-gate 1929*0Sstevel@tonic-gate 1930*0Sstevel@tonic-gate /*ARGSUSED*/ 1931*0Sstevel@tonic-gate /* 1932*0Sstevel@tonic-gate * ibnex_ioc_initnode() 1933*0Sstevel@tonic-gate * Allocate a pathinfo node for the IOC 1934*0Sstevel@tonic-gate * Initialize the device node 1935*0Sstevel@tonic-gate * Bind driver to the node 1936*0Sstevel@tonic-gate * Update IBnex global data 1937*0Sstevel@tonic-gate * Returns IBNEX_SUCCESS/IBNEX_FAILURE/IBNEX_BUSY 1938*0Sstevel@tonic-gate */ 1939*0Sstevel@tonic-gate int 1940*0Sstevel@tonic-gate ibnex_ioc_initnode(ibdm_ioc_info_t *ioc_info, int flag) 1941*0Sstevel@tonic-gate { 1942*0Sstevel@tonic-gate int rval; 1943*0Sstevel@tonic-gate ibnex_node_data_t *node_data; 1944*0Sstevel@tonic-gate 1945*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&ibnex.ibnex_mutex)); 1946*0Sstevel@tonic-gate 1947*0Sstevel@tonic-gate node_data = ibnex_is_node_data_present(IBNEX_IOC_NODE, 1948*0Sstevel@tonic-gate (void *)ioc_info, 0, 0); 1949*0Sstevel@tonic-gate 1950*0Sstevel@tonic-gate /* 1951*0Sstevel@tonic-gate * prevent any races 1952*0Sstevel@tonic-gate * we have seen this node_data and it has been initialized 1953*0Sstevel@tonic-gate * Note that node_dip is already NULL if unconfigure is in 1954*0Sstevel@tonic-gate * progress. 1955*0Sstevel@tonic-gate */ 1956*0Sstevel@tonic-gate if (node_data && node_data->node_dip) { 1957*0Sstevel@tonic-gate return ((node_data->node_state == IBNEX_CFGADM_CONFIGURING) ? 1958*0Sstevel@tonic-gate IBNEX_BUSY : IBNEX_SUCCESS); 1959*0Sstevel@tonic-gate } else if (node_data == NULL) { 1960*0Sstevel@tonic-gate node_data = ibnex_init_child_nodedata(IBNEX_IOC_NODE, 1961*0Sstevel@tonic-gate ioc_info, 0, 0); 1962*0Sstevel@tonic-gate } 1963*0Sstevel@tonic-gate 1964*0Sstevel@tonic-gate /* 1965*0Sstevel@tonic-gate * Return EBUSY if another configure/unconfigure 1966*0Sstevel@tonic-gate * operation is in progress 1967*0Sstevel@tonic-gate */ 1968*0Sstevel@tonic-gate if (node_data->node_state == IBNEX_CFGADM_UNCONFIGURING) { 1969*0Sstevel@tonic-gate return (IBNEX_BUSY); 1970*0Sstevel@tonic-gate } 1971*0Sstevel@tonic-gate 1972*0Sstevel@tonic-gate ASSERT(node_data->node_state != IBNEX_CFGADM_CONFIGURED); 1973*0Sstevel@tonic-gate node_data->node_state = IBNEX_CFGADM_CONFIGURING; 1974*0Sstevel@tonic-gate 1975*0Sstevel@tonic-gate 1976*0Sstevel@tonic-gate mutex_exit(&ibnex.ibnex_mutex); 1977*0Sstevel@tonic-gate 1978*0Sstevel@tonic-gate rval = ibnex_ioc_create_pi(ioc_info, node_data); 1979*0Sstevel@tonic-gate 1980*0Sstevel@tonic-gate mutex_enter(&ibnex.ibnex_mutex); 1981*0Sstevel@tonic-gate if (rval == IBNEX_SUCCESS) 1982*0Sstevel@tonic-gate node_data->node_state = IBNEX_CFGADM_CONFIGURED; 1983*0Sstevel@tonic-gate 1984*0Sstevel@tonic-gate return (rval); 1985*0Sstevel@tonic-gate } 1986*0Sstevel@tonic-gate 1987*0Sstevel@tonic-gate 1988*0Sstevel@tonic-gate /* 1989*0Sstevel@tonic-gate * ibnex_config_pseudo_all() 1990*0Sstevel@tonic-gate * Configure all the pseudo nodes 1991*0Sstevel@tonic-gate */ 1992*0Sstevel@tonic-gate static void 1993*0Sstevel@tonic-gate ibnex_config_pseudo_all(void) 1994*0Sstevel@tonic-gate { 1995*0Sstevel@tonic-gate ibnex_node_data_t *nodep; 1996*0Sstevel@tonic-gate 1997*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&ibnex.ibnex_mutex)); 1998*0Sstevel@tonic-gate 1999*0Sstevel@tonic-gate for (nodep = ibnex.ibnex_pseudo_node_head; 2000*0Sstevel@tonic-gate nodep; nodep = nodep->node_next) { 2001*0Sstevel@tonic-gate (void) ibnex_pseudo_config_one(nodep, NULL, NULL); 2002*0Sstevel@tonic-gate } 2003*0Sstevel@tonic-gate } 2004*0Sstevel@tonic-gate 2005*0Sstevel@tonic-gate 2006*0Sstevel@tonic-gate /* 2007*0Sstevel@tonic-gate * ibnex_pseudo_config_one() 2008*0Sstevel@tonic-gate */ 2009*0Sstevel@tonic-gate int 2010*0Sstevel@tonic-gate ibnex_pseudo_config_one(ibnex_node_data_t *node_data, char *cname, char *caddr) 2011*0Sstevel@tonic-gate { 2012*0Sstevel@tonic-gate int rval, len; 2013*0Sstevel@tonic-gate char *node_addr; 2014*0Sstevel@tonic-gate 2015*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tpseudo_config_one:Begin"); 2016*0Sstevel@tonic-gate 2017*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&ibnex.ibnex_mutex)); 2018*0Sstevel@tonic-gate 2019*0Sstevel@tonic-gate if (node_data == NULL) { 2020*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tpseudo_config_one:" 2021*0Sstevel@tonic-gate "cname = %s caddr = %s", cname, caddr); 2022*0Sstevel@tonic-gate 2023*0Sstevel@tonic-gate len = strlen(cname) + strlen(caddr) + 2; 2024*0Sstevel@tonic-gate node_addr = (char *)kmem_alloc(len, KM_SLEEP); 2025*0Sstevel@tonic-gate 2026*0Sstevel@tonic-gate (void) snprintf(node_addr, len, "%s,%s", cname, caddr); 2027*0Sstevel@tonic-gate node_data = ibnex_is_node_data_present(IBNEX_PSEUDO_NODE, 2028*0Sstevel@tonic-gate (void *)node_addr, 0, 0); 2029*0Sstevel@tonic-gate kmem_free(node_addr, len); 2030*0Sstevel@tonic-gate } 2031*0Sstevel@tonic-gate 2032*0Sstevel@tonic-gate /* 2033*0Sstevel@tonic-gate * prevent any races 2034*0Sstevel@tonic-gate * we have seen this node_data and it has been initialized 2035*0Sstevel@tonic-gate * Note that node_dip is already NULL if unconfigure is in 2036*0Sstevel@tonic-gate * progress. 2037*0Sstevel@tonic-gate */ 2038*0Sstevel@tonic-gate if (node_data && node_data->node_dip) { 2039*0Sstevel@tonic-gate return ((node_data->node_state == IBNEX_CFGADM_CONFIGURING) ? 2040*0Sstevel@tonic-gate IBNEX_BUSY : IBNEX_SUCCESS); 2041*0Sstevel@tonic-gate } else if (node_data == NULL) { 2042*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", "\tpseudo_config_one: Invalid node"); 2043*0Sstevel@tonic-gate return (IBNEX_FAILURE); 2044*0Sstevel@tonic-gate } 2045*0Sstevel@tonic-gate 2046*0Sstevel@tonic-gate /* 2047*0Sstevel@tonic-gate * Return EBUSY if another configure/unconfigure 2048*0Sstevel@tonic-gate * operation is in progress 2049*0Sstevel@tonic-gate */ 2050*0Sstevel@tonic-gate if (node_data->node_state == IBNEX_CFGADM_UNCONFIGURING) { 2051*0Sstevel@tonic-gate return (IBNEX_BUSY); 2052*0Sstevel@tonic-gate } 2053*0Sstevel@tonic-gate 2054*0Sstevel@tonic-gate if (node_data->node_state == IBNEX_CFGADM_CONFIGURED) 2055*0Sstevel@tonic-gate return (IBNEX_SUCCESS); 2056*0Sstevel@tonic-gate 2057*0Sstevel@tonic-gate /* 2058*0Sstevel@tonic-gate * Prevent configuring pseudo nodes specifically unconfigured 2059*0Sstevel@tonic-gate * by cfgadm. This is done by checking if this is a newly 2060*0Sstevel@tonic-gate * created node, not yet configured by BUS_CONFIG or cfgadm 2061*0Sstevel@tonic-gate */ 2062*0Sstevel@tonic-gate if (node_data->node_data.pseudo_node.pseudo_new_node != 1) 2063*0Sstevel@tonic-gate return (IBNEX_FAILURE); 2064*0Sstevel@tonic-gate node_data->node_data.pseudo_node.pseudo_new_node = 0; 2065*0Sstevel@tonic-gate 2066*0Sstevel@tonic-gate node_data->node_state = IBNEX_CFGADM_CONFIGURING; 2067*0Sstevel@tonic-gate 2068*0Sstevel@tonic-gate mutex_exit(&ibnex.ibnex_mutex); 2069*0Sstevel@tonic-gate rval = ibnex_pseudo_create_pi(node_data); 2070*0Sstevel@tonic-gate mutex_enter(&ibnex.ibnex_mutex); 2071*0Sstevel@tonic-gate 2072*0Sstevel@tonic-gate if (rval == IBNEX_SUCCESS) 2073*0Sstevel@tonic-gate node_data->node_state = IBNEX_CFGADM_CONFIGURED; 2074*0Sstevel@tonic-gate else { 2075*0Sstevel@tonic-gate node_data->node_dip = NULL; 2076*0Sstevel@tonic-gate node_data->node_state = IBNEX_CFGADM_UNCONFIGURED; 2077*0Sstevel@tonic-gate node_data->node_data.pseudo_node.pseudo_new_node = 1; 2078*0Sstevel@tonic-gate } 2079*0Sstevel@tonic-gate 2080*0Sstevel@tonic-gate return (rval); 2081*0Sstevel@tonic-gate } 2082*0Sstevel@tonic-gate 2083*0Sstevel@tonic-gate 2084*0Sstevel@tonic-gate /* 2085*0Sstevel@tonic-gate * ibnex_pseudo_create_pi() 2086*0Sstevel@tonic-gate * Create a path info node for each pseudo entry 2087*0Sstevel@tonic-gate */ 2088*0Sstevel@tonic-gate int 2089*0Sstevel@tonic-gate ibnex_pseudo_create_pi(ibnex_node_data_t *nodep) 2090*0Sstevel@tonic-gate { 2091*0Sstevel@tonic-gate mdi_pathinfo_t *pip; 2092*0Sstevel@tonic-gate int rval, hcacnt; 2093*0Sstevel@tonic-gate dev_info_t *hca_dip, *cdip = NULL; 2094*0Sstevel@tonic-gate ibdm_hca_list_t *hca_list, *head; 2095*0Sstevel@tonic-gate ibnex_pseudo_node_t *pseudo; 2096*0Sstevel@tonic-gate 2097*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tibnex_pseudo_create_pi: %p", nodep); 2098*0Sstevel@tonic-gate 2099*0Sstevel@tonic-gate pseudo = &nodep->node_data.pseudo_node; 2100*0Sstevel@tonic-gate 2101*0Sstevel@tonic-gate ibdm_ibnex_get_hca_list(&hca_list, &hcacnt); 2102*0Sstevel@tonic-gate 2103*0Sstevel@tonic-gate head = hca_list; 2104*0Sstevel@tonic-gate 2105*0Sstevel@tonic-gate for (; hca_list != NULL; hca_list = hca_list->hl_next) { 2106*0Sstevel@tonic-gate 2107*0Sstevel@tonic-gate hca_dip = ibtl_ibnex_hcaguid2dip(hca_list->hl_hca_guid); 2108*0Sstevel@tonic-gate 2109*0Sstevel@tonic-gate rval = mdi_pi_alloc(hca_dip, 2110*0Sstevel@tonic-gate pseudo->pseudo_devi_name, pseudo->pseudo_node_addr, 2111*0Sstevel@tonic-gate pseudo->pseudo_node_addr, 0, &pip); 2112*0Sstevel@tonic-gate 2113*0Sstevel@tonic-gate if (rval != MDI_SUCCESS) { 2114*0Sstevel@tonic-gate (void) ibnex_offline_childdip(cdip); 2115*0Sstevel@tonic-gate return (IBNEX_FAILURE); 2116*0Sstevel@tonic-gate } 2117*0Sstevel@tonic-gate cdip = mdi_pi_get_client(pip); 2118*0Sstevel@tonic-gate 2119*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", 2120*0Sstevel@tonic-gate "\tpseudo_create_pi: New dip %p", cdip); 2121*0Sstevel@tonic-gate 2122*0Sstevel@tonic-gate nodep->node_dip = cdip; 2123*0Sstevel@tonic-gate ddi_set_parent_data(cdip, nodep); 2124*0Sstevel@tonic-gate 2125*0Sstevel@tonic-gate rval = mdi_pi_online(pip, 0); 2126*0Sstevel@tonic-gate 2127*0Sstevel@tonic-gate if (rval != MDI_SUCCESS) { 2128*0Sstevel@tonic-gate ddi_set_parent_data(cdip, NULL); 2129*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", "\tpseudo_create_pi:" 2130*0Sstevel@tonic-gate "mdi_pi_online: failed for pseudo dip %p," 2131*0Sstevel@tonic-gate " rval %d", cdip, rval); 2132*0Sstevel@tonic-gate (void) ibnex_offline_childdip(cdip); 2133*0Sstevel@tonic-gate rval = IBNEX_FAILURE; 2134*0Sstevel@tonic-gate break; 2135*0Sstevel@tonic-gate } else 2136*0Sstevel@tonic-gate rval = IBNEX_SUCCESS; 2137*0Sstevel@tonic-gate } 2138*0Sstevel@tonic-gate if (head) 2139*0Sstevel@tonic-gate ibdm_ibnex_free_hca_list(head); 2140*0Sstevel@tonic-gate return (rval); 2141*0Sstevel@tonic-gate } 2142*0Sstevel@tonic-gate 2143*0Sstevel@tonic-gate 2144*0Sstevel@tonic-gate /* 2145*0Sstevel@tonic-gate * ibnex_ioc_create_pi() 2146*0Sstevel@tonic-gate * Create a pathinfo node for the ioc node 2147*0Sstevel@tonic-gate */ 2148*0Sstevel@tonic-gate static int 2149*0Sstevel@tonic-gate ibnex_ioc_create_pi(ibdm_ioc_info_t *ioc_info, ibnex_node_data_t *node_data) 2150*0Sstevel@tonic-gate { 2151*0Sstevel@tonic-gate char ioc_guid[33], iou_guid[33]; 2152*0Sstevel@tonic-gate mdi_pathinfo_t *pip; 2153*0Sstevel@tonic-gate int rval; 2154*0Sstevel@tonic-gate dev_info_t *hca_dip, *cdip = NULL; 2155*0Sstevel@tonic-gate int flag = 1; 2156*0Sstevel@tonic-gate ibdm_hca_list_t *hca_list; 2157*0Sstevel@tonic-gate 2158*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tibnex_ioc_create_pi Begin"); 2159*0Sstevel@tonic-gate 2160*0Sstevel@tonic-gate (void) snprintf(ioc_guid, 33, "%llx", 2161*0Sstevel@tonic-gate (longlong_t)ioc_info->ioc_profile.ioc_guid); 2162*0Sstevel@tonic-gate (void) snprintf(iou_guid, 33, "%llx", 2163*0Sstevel@tonic-gate (longlong_t)ioc_info->ioc_iou_guid); 2164*0Sstevel@tonic-gate 2165*0Sstevel@tonic-gate hca_list = ioc_info->ioc_hca_list; 2166*0Sstevel@tonic-gate 2167*0Sstevel@tonic-gate for (; hca_list != NULL; hca_list = hca_list->hl_next) { 2168*0Sstevel@tonic-gate 2169*0Sstevel@tonic-gate hca_dip = ibtl_ibnex_hcaguid2dip(hca_list->hl_hca_guid); 2170*0Sstevel@tonic-gate 2171*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tioc_create_pi " 2172*0Sstevel@tonic-gate "hca guid %llx", hca_list->hl_hca_guid); 2173*0Sstevel@tonic-gate 2174*0Sstevel@tonic-gate rval = mdi_pi_alloc(hca_dip, 2175*0Sstevel@tonic-gate IBNEX_IOC_CNAME, ioc_guid, iou_guid, 0, &pip); 2176*0Sstevel@tonic-gate if (rval != MDI_SUCCESS) { 2177*0Sstevel@tonic-gate (void) ibnex_offline_childdip(cdip); 2178*0Sstevel@tonic-gate return (IBNEX_FAILURE); 2179*0Sstevel@tonic-gate } 2180*0Sstevel@tonic-gate cdip = mdi_pi_get_client(pip); 2181*0Sstevel@tonic-gate 2182*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", 2183*0Sstevel@tonic-gate "\tioc_create_pi: New IOC dip %p", cdip); 2184*0Sstevel@tonic-gate 2185*0Sstevel@tonic-gate node_data->node_dip = cdip; 2186*0Sstevel@tonic-gate ddi_set_parent_data(cdip, node_data); 2187*0Sstevel@tonic-gate 2188*0Sstevel@tonic-gate if (flag) { 2189*0Sstevel@tonic-gate if ((rval = ibnex_create_ioc_node_prop( 2190*0Sstevel@tonic-gate ioc_info, cdip)) != IBNEX_SUCCESS) { 2191*0Sstevel@tonic-gate ibnex_delete_ioc_node_data(node_data); 2192*0Sstevel@tonic-gate ddi_prop_remove_all(cdip); 2193*0Sstevel@tonic-gate ddi_set_parent_data(cdip, NULL); 2194*0Sstevel@tonic-gate 2195*0Sstevel@tonic-gate (void) ibnex_offline_childdip(cdip); 2196*0Sstevel@tonic-gate return (IBNEX_FAILURE); 2197*0Sstevel@tonic-gate } 2198*0Sstevel@tonic-gate flag = 0; 2199*0Sstevel@tonic-gate } 2200*0Sstevel@tonic-gate 2201*0Sstevel@tonic-gate rval = mdi_pi_online(pip, 0); 2202*0Sstevel@tonic-gate 2203*0Sstevel@tonic-gate if (rval != MDI_SUCCESS) { 2204*0Sstevel@tonic-gate ibnex_delete_ioc_node_data(node_data); 2205*0Sstevel@tonic-gate ddi_prop_remove_all(cdip); 2206*0Sstevel@tonic-gate ddi_set_parent_data(cdip, NULL); 2207*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", "\tioc_create_pi: " 2208*0Sstevel@tonic-gate "mdi_pi_online() failed ioc dip %p, rval %d", 2209*0Sstevel@tonic-gate cdip, rval); 2210*0Sstevel@tonic-gate (void) ibnex_offline_childdip(cdip); 2211*0Sstevel@tonic-gate rval = IBNEX_FAILURE; 2212*0Sstevel@tonic-gate break; 2213*0Sstevel@tonic-gate } else 2214*0Sstevel@tonic-gate rval = IBNEX_SUCCESS; 2215*0Sstevel@tonic-gate } 2216*0Sstevel@tonic-gate return (rval); 2217*0Sstevel@tonic-gate } 2218*0Sstevel@tonic-gate 2219*0Sstevel@tonic-gate 2220*0Sstevel@tonic-gate /* 2221*0Sstevel@tonic-gate * ibnex_create_ioc_node_prop() 2222*0Sstevel@tonic-gate * Create IOC device node properties 2223*0Sstevel@tonic-gate * Returns IBNEX_SUCCESS/IBNEX_FAILURE 2224*0Sstevel@tonic-gate */ 2225*0Sstevel@tonic-gate static int 2226*0Sstevel@tonic-gate ibnex_create_ioc_node_prop(ibdm_ioc_info_t *ioc_info, dev_info_t *cdip) 2227*0Sstevel@tonic-gate { 2228*0Sstevel@tonic-gate uint16_t capabilities; 2229*0Sstevel@tonic-gate ib_dm_ioc_ctrl_profile_t *ioc_profile = &ioc_info->ioc_profile; 2230*0Sstevel@tonic-gate 2231*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tcreate_ioc_node_prop"); 2232*0Sstevel@tonic-gate 2233*0Sstevel@tonic-gate if (ibnex_create_ioc_compatible_prop(cdip, 2234*0Sstevel@tonic-gate ioc_profile) != IBNEX_SUCCESS) { 2235*0Sstevel@tonic-gate return (IBNEX_FAILURE); 2236*0Sstevel@tonic-gate } 2237*0Sstevel@tonic-gate if ((ioc_info->ioc_iou_dc_valid) && 2238*0Sstevel@tonic-gate (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, "iou-diagcode", 2239*0Sstevel@tonic-gate ioc_info->ioc_iou_diagcode)) != DDI_PROP_SUCCESS) { 2240*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", 2241*0Sstevel@tonic-gate "\tcreate_ioc_node_prop: iou-diagcode create failed"); 2242*0Sstevel@tonic-gate return (IBNEX_FAILURE); 2243*0Sstevel@tonic-gate } 2244*0Sstevel@tonic-gate if ((ioc_info->ioc_diagdeviceid) && (ioc_info->ioc_dc_valid)) { 2245*0Sstevel@tonic-gate if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, "ioc-diagcode", 2246*0Sstevel@tonic-gate ioc_info->ioc_diagcode) != DDI_PROP_SUCCESS) { 2247*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", "\tcreate_ioc_node_prop: " 2248*0Sstevel@tonic-gate "ioc-diagcode create failed"); 2249*0Sstevel@tonic-gate return (IBNEX_FAILURE); 2250*0Sstevel@tonic-gate } 2251*0Sstevel@tonic-gate } 2252*0Sstevel@tonic-gate if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, "rdma-queue-depth", 2253*0Sstevel@tonic-gate ioc_profile->ioc_rdma_read_qdepth) != DDI_PROP_SUCCESS) { 2254*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", 2255*0Sstevel@tonic-gate "\tcreate_ioc_node_prop: rdma-queue-depth create failed"); 2256*0Sstevel@tonic-gate return (IBNEX_FAILURE); 2257*0Sstevel@tonic-gate } 2258*0Sstevel@tonic-gate if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, "rdma-transfer-size", 2259*0Sstevel@tonic-gate ioc_profile->ioc_rdma_xfer_sz) != DDI_PROP_SUCCESS) { 2260*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", "\tcreate_ioc_node_prop: " 2261*0Sstevel@tonic-gate "rdma-transfer-size create failed"); 2262*0Sstevel@tonic-gate return (IBNEX_FAILURE); 2263*0Sstevel@tonic-gate } 2264*0Sstevel@tonic-gate if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, "send-message-size", 2265*0Sstevel@tonic-gate ioc_profile->ioc_send_msg_sz) != DDI_PROP_SUCCESS) { 2266*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", 2267*0Sstevel@tonic-gate "\tcreate_ioc_node_prop: send-message-size create failed"); 2268*0Sstevel@tonic-gate return (IBNEX_FAILURE); 2269*0Sstevel@tonic-gate } 2270*0Sstevel@tonic-gate if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, "send-queue-depth", 2271*0Sstevel@tonic-gate ioc_profile->ioc_send_msg_qdepth) != DDI_PROP_SUCCESS) { 2272*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", 2273*0Sstevel@tonic-gate "\tcreate_ioc_node_prop: send-queue-depth create failed"); 2274*0Sstevel@tonic-gate return (IBNEX_FAILURE); 2275*0Sstevel@tonic-gate } 2276*0Sstevel@tonic-gate 2277*0Sstevel@tonic-gate capabilities = (ioc_profile->ioc_ctrl_opcap_mask << 8); 2278*0Sstevel@tonic-gate if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, 2279*0Sstevel@tonic-gate "capabilities", capabilities) != DDI_PROP_SUCCESS) { 2280*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", 2281*0Sstevel@tonic-gate "\tcreate_ioc_node_prop: capabilities create failed"); 2282*0Sstevel@tonic-gate return (IBNEX_FAILURE); 2283*0Sstevel@tonic-gate } 2284*0Sstevel@tonic-gate if (ndi_prop_update_string(DDI_DEV_T_NONE, cdip, "id-string", 2285*0Sstevel@tonic-gate (char *)ioc_profile->ioc_id_string) != DDI_PROP_SUCCESS) { 2286*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", 2287*0Sstevel@tonic-gate "\tcreate_ioc_node_prop: id-string failed"); 2288*0Sstevel@tonic-gate return (IBNEX_FAILURE); 2289*0Sstevel@tonic-gate } 2290*0Sstevel@tonic-gate 2291*0Sstevel@tonic-gate /* 2292*0Sstevel@tonic-gate * Create properties to represent all the service entries supported 2293*0Sstevel@tonic-gate * by the IOC. Each service entry consists of 1) Service ID (64 bits) 2294*0Sstevel@tonic-gate * and 2) Service name (40 bytes). The service entry table is 2295*0Sstevel@tonic-gate * represented by two properties, service-ids and service-names. The 2296*0Sstevel@tonic-gate * service-id property is a array of int64's and service names is 2297*0Sstevel@tonic-gate * array of strings. The first element in the "service-ids" property 2298*0Sstevel@tonic-gate * corresponds to first string in the "service-names" and so on. 2299*0Sstevel@tonic-gate */ 2300*0Sstevel@tonic-gate if ((ioc_profile->ioc_service_entries != 0) && 2301*0Sstevel@tonic-gate (ibnex_create_ioc_srv_props(cdip, ioc_info) != IBNEX_SUCCESS)) 2302*0Sstevel@tonic-gate return (IBNEX_FAILURE); 2303*0Sstevel@tonic-gate 2304*0Sstevel@tonic-gate /* Create destination port GID properties */ 2305*0Sstevel@tonic-gate if (ibnex_create_ioc_portgid_prop(cdip, ioc_info) != IBNEX_SUCCESS) 2306*0Sstevel@tonic-gate return (IBNEX_FAILURE); 2307*0Sstevel@tonic-gate 2308*0Sstevel@tonic-gate if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, "protocol-version", 2309*0Sstevel@tonic-gate ioc_profile->ioc_protocol_ver) != DDI_PROP_SUCCESS) { 2310*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", 2311*0Sstevel@tonic-gate "\tcreate_ioc_node_prop: protocol-version create failed"); 2312*0Sstevel@tonic-gate return (IBNEX_FAILURE); 2313*0Sstevel@tonic-gate } 2314*0Sstevel@tonic-gate if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, "protocol", 2315*0Sstevel@tonic-gate ioc_profile->ioc_protocol) != DDI_PROP_SUCCESS) { 2316*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", 2317*0Sstevel@tonic-gate "\tcreate_ioc_node_prop: protocol create failed"); 2318*0Sstevel@tonic-gate return (IBNEX_FAILURE); 2319*0Sstevel@tonic-gate } 2320*0Sstevel@tonic-gate if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, "io-subclass", 2321*0Sstevel@tonic-gate ioc_profile->ioc_io_subclass) != DDI_PROP_SUCCESS) { 2322*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", 2323*0Sstevel@tonic-gate "\tcreate_ioc_node_prop: subclass create failed"); 2324*0Sstevel@tonic-gate return (IBNEX_FAILURE); 2325*0Sstevel@tonic-gate } 2326*0Sstevel@tonic-gate if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, "io-class", 2327*0Sstevel@tonic-gate ioc_profile->ioc_io_class) != DDI_PROP_SUCCESS) { 2328*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", 2329*0Sstevel@tonic-gate "\tcreate_ioc_node_prop: class prop create failed"); 2330*0Sstevel@tonic-gate return (IBNEX_FAILURE); 2331*0Sstevel@tonic-gate } 2332*0Sstevel@tonic-gate if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, "subsystem-id", 2333*0Sstevel@tonic-gate ioc_profile->ioc_subsys_id) != DDI_PROP_SUCCESS) { 2334*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", 2335*0Sstevel@tonic-gate "\tcreate_ioc_node_prop: subsys_id create failed"); 2336*0Sstevel@tonic-gate return (IBNEX_FAILURE); 2337*0Sstevel@tonic-gate } 2338*0Sstevel@tonic-gate if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, "subsystem-vendor-id", 2339*0Sstevel@tonic-gate ioc_profile->ioc_subsys_vendorid) != DDI_PROP_SUCCESS) { 2340*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", 2341*0Sstevel@tonic-gate "\tcreate_ioc_node_prop: subsystem vendor create failed"); 2342*0Sstevel@tonic-gate return (IBNEX_FAILURE); 2343*0Sstevel@tonic-gate } 2344*0Sstevel@tonic-gate if (ndi_prop_update_int64(DDI_DEV_T_NONE, cdip, "ioc-guid", 2345*0Sstevel@tonic-gate ioc_profile->ioc_guid) != DDI_PROP_SUCCESS) { 2346*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", 2347*0Sstevel@tonic-gate "\tcreate_ioc_node_prop: protocol create failed"); 2348*0Sstevel@tonic-gate return (IBNEX_FAILURE); 2349*0Sstevel@tonic-gate } 2350*0Sstevel@tonic-gate if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, "device-version", 2351*0Sstevel@tonic-gate ioc_profile->ioc_device_ver) != DDI_PROP_SUCCESS) { 2352*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", 2353*0Sstevel@tonic-gate "\tcreate_ioc_node_prop: product-id create failed"); 2354*0Sstevel@tonic-gate return (IBNEX_FAILURE); 2355*0Sstevel@tonic-gate } 2356*0Sstevel@tonic-gate if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, "device-id", 2357*0Sstevel@tonic-gate ioc_profile->ioc_deviceid) != DDI_PROP_SUCCESS) { 2358*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", 2359*0Sstevel@tonic-gate "\tcreate_ioc_node_prop: product-id create failed"); 2360*0Sstevel@tonic-gate return (IBNEX_FAILURE); 2361*0Sstevel@tonic-gate } 2362*0Sstevel@tonic-gate if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, "vendor-id", 2363*0Sstevel@tonic-gate ioc_profile->ioc_vendorid) != DDI_PROP_SUCCESS) { 2364*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", 2365*0Sstevel@tonic-gate "\tcreate_ioc_node_prop: vendor-id create failed"); 2366*0Sstevel@tonic-gate return (IBNEX_FAILURE); 2367*0Sstevel@tonic-gate } 2368*0Sstevel@tonic-gate return (IBNEX_SUCCESS); 2369*0Sstevel@tonic-gate } 2370*0Sstevel@tonic-gate 2371*0Sstevel@tonic-gate 2372*0Sstevel@tonic-gate /* 2373*0Sstevel@tonic-gate * ibnex_create_ioc_portgid_prop() 2374*0Sstevel@tonic-gate * Creates "port-entries", "port-list" properties 2375*0Sstevel@tonic-gate * Returns IBNEX_SUCCESS/IBNEX_FAILURE 2376*0Sstevel@tonic-gate */ 2377*0Sstevel@tonic-gate static int 2378*0Sstevel@tonic-gate ibnex_create_ioc_portgid_prop( 2379*0Sstevel@tonic-gate dev_info_t *cdip, ibdm_ioc_info_t *ioc_info) 2380*0Sstevel@tonic-gate { 2381*0Sstevel@tonic-gate uint64_t *port_gids; 2382*0Sstevel@tonic-gate int length, ii, jj; 2383*0Sstevel@tonic-gate int prop_len; 2384*0Sstevel@tonic-gate ibnex_node_data_t *node_data; 2385*0Sstevel@tonic-gate 2386*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tcreate_ioc_portgid_prop"); 2387*0Sstevel@tonic-gate 2388*0Sstevel@tonic-gate node_data = ddi_get_parent_data(cdip); 2389*0Sstevel@tonic-gate ASSERT(node_data); 2390*0Sstevel@tonic-gate 2391*0Sstevel@tonic-gate prop_len = (ioc_info->ioc_nportgids != 0) ? 2392*0Sstevel@tonic-gate (2 * ioc_info->ioc_nportgids) : 1; 2393*0Sstevel@tonic-gate length = sizeof (uint64_t) * prop_len; 2394*0Sstevel@tonic-gate port_gids = kmem_zalloc(length, KM_SLEEP); 2395*0Sstevel@tonic-gate 2396*0Sstevel@tonic-gate for (ii = 0, jj = 0; ii < ioc_info->ioc_nportgids; ii++) { 2397*0Sstevel@tonic-gate port_gids[jj++] = ioc_info->ioc_gid_list[ii].gid_dgid_hi; 2398*0Sstevel@tonic-gate port_gids[jj++] = ioc_info->ioc_gid_list[ii].gid_dgid_lo; 2399*0Sstevel@tonic-gate } 2400*0Sstevel@tonic-gate if (ndi_prop_update_int64_array(DDI_DEV_T_NONE, cdip, "port-list", 2401*0Sstevel@tonic-gate (int64_t *)port_gids, prop_len) != DDI_PROP_SUCCESS) { 2402*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", 2403*0Sstevel@tonic-gate "\tcreate_ioc_portgid_prop: port-list create failed"); 2404*0Sstevel@tonic-gate kmem_free(port_gids, length); 2405*0Sstevel@tonic-gate return (IBNEX_FAILURE); 2406*0Sstevel@tonic-gate } 2407*0Sstevel@tonic-gate if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, "port-entries", 2408*0Sstevel@tonic-gate ioc_info->ioc_nportgids) != DDI_PROP_SUCCESS) { 2409*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", 2410*0Sstevel@tonic-gate "\tcreate_ioc_portgid_prop: port-entries create failed"); 2411*0Sstevel@tonic-gate kmem_free(port_gids, length); 2412*0Sstevel@tonic-gate return (IBNEX_FAILURE); 2413*0Sstevel@tonic-gate } 2414*0Sstevel@tonic-gate 2415*0Sstevel@tonic-gate kmem_free(port_gids, length); 2416*0Sstevel@tonic-gate return (IBNEX_SUCCESS); 2417*0Sstevel@tonic-gate } 2418*0Sstevel@tonic-gate 2419*0Sstevel@tonic-gate 2420*0Sstevel@tonic-gate /* 2421*0Sstevel@tonic-gate * ibnex_create_ioc_srv_props() 2422*0Sstevel@tonic-gate * Creates "service-name" and "service-id" properties 2423*0Sstevel@tonic-gate * Returns IBNEX_SUCCESS/IBNEX_FAILURE 2424*0Sstevel@tonic-gate */ 2425*0Sstevel@tonic-gate static int 2426*0Sstevel@tonic-gate ibnex_create_ioc_srv_props( 2427*0Sstevel@tonic-gate dev_info_t *cdip, ibdm_ioc_info_t *ioc_info) 2428*0Sstevel@tonic-gate { 2429*0Sstevel@tonic-gate int length, ii; 2430*0Sstevel@tonic-gate uint64_t *srv_id; 2431*0Sstevel@tonic-gate char *temp, *srv_names[IB_DM_MAX_IOCS_IN_IOU]; 2432*0Sstevel@tonic-gate ib_dm_ioc_ctrl_profile_t *profile = &ioc_info->ioc_profile; 2433*0Sstevel@tonic-gate ibdm_srvents_info_t *srvents = ioc_info->ioc_serv; 2434*0Sstevel@tonic-gate 2435*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tcreate_ioc_srv_props"); 2436*0Sstevel@tonic-gate 2437*0Sstevel@tonic-gate length = profile->ioc_service_entries * sizeof (ib_dm_srv_t); 2438*0Sstevel@tonic-gate srv_id = kmem_zalloc(length, KM_SLEEP); 2439*0Sstevel@tonic-gate temp = (char *)((char *)srv_id + (8 * profile->ioc_service_entries)); 2440*0Sstevel@tonic-gate for (ii = 0; ii < profile->ioc_service_entries; ii++) { 2441*0Sstevel@tonic-gate srv_names[ii] = (char *)temp + (ii * IB_DM_MAX_SVC_NAME_LEN); 2442*0Sstevel@tonic-gate } 2443*0Sstevel@tonic-gate 2444*0Sstevel@tonic-gate for (ii = 0; ii < profile->ioc_service_entries; ii++) { 2445*0Sstevel@tonic-gate srv_id[ii] = srvents[ii].se_attr.srv_id; 2446*0Sstevel@tonic-gate bcopy(srvents[ii].se_attr.srv_name, 2447*0Sstevel@tonic-gate srv_names[ii], (IB_DM_MAX_SVC_NAME_LEN - 1)); 2448*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tcreate_ioc_srv_props " 2449*0Sstevel@tonic-gate "Service Names : %s", srv_names[ii]); 2450*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tcreate_ioc_srv_props " 2451*0Sstevel@tonic-gate "Service ID : %llx", srv_id[ii]); 2452*0Sstevel@tonic-gate } 2453*0Sstevel@tonic-gate 2454*0Sstevel@tonic-gate if (ndi_prop_update_int64_array(DDI_DEV_T_NONE, cdip, 2455*0Sstevel@tonic-gate "service-id", (int64_t *)srv_id, 2456*0Sstevel@tonic-gate profile->ioc_service_entries) != DDI_PROP_SUCCESS) { 2457*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", 2458*0Sstevel@tonic-gate "\tcreate_ioc_srv_props: service-id create failed"); 2459*0Sstevel@tonic-gate kmem_free(srv_id, length); 2460*0Sstevel@tonic-gate return (IBNEX_FAILURE); 2461*0Sstevel@tonic-gate } 2462*0Sstevel@tonic-gate 2463*0Sstevel@tonic-gate if (ndi_prop_update_string_array(DDI_DEV_T_NONE, cdip, 2464*0Sstevel@tonic-gate "service-name", (char **)srv_names, 2465*0Sstevel@tonic-gate profile->ioc_service_entries) != DDI_PROP_SUCCESS) { 2466*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", 2467*0Sstevel@tonic-gate "\tcreate_ioc_srv_props: service-name create failed"); 2468*0Sstevel@tonic-gate kmem_free(srv_id, length); 2469*0Sstevel@tonic-gate return (IBNEX_FAILURE); 2470*0Sstevel@tonic-gate } 2471*0Sstevel@tonic-gate kmem_free(srv_id, length); 2472*0Sstevel@tonic-gate return (IBNEX_SUCCESS); 2473*0Sstevel@tonic-gate } 2474*0Sstevel@tonic-gate 2475*0Sstevel@tonic-gate 2476*0Sstevel@tonic-gate /* 2477*0Sstevel@tonic-gate * ibnex_create_ioc_compatible_prop() 2478*0Sstevel@tonic-gate * Creates "compatible" property values 2479*0Sstevel@tonic-gate * Returns IBNEX_SUCCESS/IBNEX_FAILURE 2480*0Sstevel@tonic-gate */ 2481*0Sstevel@tonic-gate static int 2482*0Sstevel@tonic-gate ibnex_create_ioc_compatible_prop( 2483*0Sstevel@tonic-gate dev_info_t *cdip, ib_dm_ioc_ctrl_profile_t *ioc_profile) 2484*0Sstevel@tonic-gate { 2485*0Sstevel@tonic-gate char *temp; 2486*0Sstevel@tonic-gate int rval, ii; 2487*0Sstevel@tonic-gate char *compatible[IBNEX_MAX_COMPAT_NAMES]; 2488*0Sstevel@tonic-gate 2489*0Sstevel@tonic-gate /* 2490*0Sstevel@tonic-gate * Initialize the "compatible" property string as below: 2491*0Sstevel@tonic-gate * Compatible Strings : 2492*0Sstevel@tonic-gate * 1. ib.V<vid>P<pid>S<subsys vid>s<subsys id>v<ver> 2493*0Sstevel@tonic-gate * 2. ib.V<vid>P<pid>S<subsys vid>s<subsys id> 2494*0Sstevel@tonic-gate * 3. ib.V<vid>P<pid>v<ver> 2495*0Sstevel@tonic-gate * 4. ib.V<vid>P<pid> 2496*0Sstevel@tonic-gate * 5. ib.C<Class>c<Subclass>p<protocol>r<protocol ver> 2497*0Sstevel@tonic-gate * 6. ib.C<Class>c<Subclass>p<protocol> 2498*0Sstevel@tonic-gate * 2499*0Sstevel@tonic-gate * Note: 2500*0Sstevel@tonic-gate * All leading zeros must be present 2501*0Sstevel@tonic-gate * All numeric values must specified in hex without prefix "0x" 2502*0Sstevel@tonic-gate */ 2503*0Sstevel@tonic-gate 2504*0Sstevel@tonic-gate temp = kmem_alloc(IBNEX_MAX_COMPAT_PROP_SZ, KM_SLEEP); 2505*0Sstevel@tonic-gate for (ii = 0; ii < IBNEX_MAX_COMPAT_NAMES; ii++) 2506*0Sstevel@tonic-gate compatible[ii] = temp + (ii * IBNEX_MAX_COMPAT_LEN); 2507*0Sstevel@tonic-gate 2508*0Sstevel@tonic-gate (void) snprintf(compatible[0], IBNEX_MAX_COMPAT_LEN, 2509*0Sstevel@tonic-gate "ib.V%06xP%08xS%06xs%08xv%04x", 2510*0Sstevel@tonic-gate ioc_profile->ioc_vendorid, ioc_profile->ioc_deviceid, 2511*0Sstevel@tonic-gate ioc_profile->ioc_subsys_vendorid, ioc_profile->ioc_subsys_id, 2512*0Sstevel@tonic-gate ioc_profile->ioc_device_ver); 2513*0Sstevel@tonic-gate 2514*0Sstevel@tonic-gate (void) snprintf(compatible[1], IBNEX_MAX_COMPAT_LEN, 2515*0Sstevel@tonic-gate "ib.V%06xP%08xS%06xs%08x", 2516*0Sstevel@tonic-gate ioc_profile->ioc_vendorid, ioc_profile->ioc_deviceid, 2517*0Sstevel@tonic-gate ioc_profile->ioc_subsys_vendorid, ioc_profile->ioc_subsys_id); 2518*0Sstevel@tonic-gate 2519*0Sstevel@tonic-gate (void) snprintf(compatible[2], IBNEX_MAX_COMPAT_LEN, 2520*0Sstevel@tonic-gate "ib.V%06xP%08xv%04x", 2521*0Sstevel@tonic-gate ioc_profile->ioc_vendorid, ioc_profile->ioc_deviceid, 2522*0Sstevel@tonic-gate ioc_profile->ioc_device_ver); 2523*0Sstevel@tonic-gate 2524*0Sstevel@tonic-gate (void) snprintf(compatible[3], IBNEX_MAX_COMPAT_LEN, 2525*0Sstevel@tonic-gate "ib.V%06xP%08x", 2526*0Sstevel@tonic-gate ioc_profile->ioc_vendorid, ioc_profile->ioc_deviceid); 2527*0Sstevel@tonic-gate 2528*0Sstevel@tonic-gate (void) snprintf(compatible[4], IBNEX_MAX_COMPAT_LEN, 2529*0Sstevel@tonic-gate "ib.C%04xc%04xp%04xr%04x", 2530*0Sstevel@tonic-gate ioc_profile->ioc_io_class, ioc_profile->ioc_io_subclass, 2531*0Sstevel@tonic-gate ioc_profile->ioc_protocol, ioc_profile->ioc_protocol_ver); 2532*0Sstevel@tonic-gate 2533*0Sstevel@tonic-gate (void) snprintf(compatible[5], IBNEX_MAX_COMPAT_LEN, 2534*0Sstevel@tonic-gate "ib.C%04xc%04xp%04x", 2535*0Sstevel@tonic-gate ioc_profile->ioc_io_class, ioc_profile->ioc_io_subclass, 2536*0Sstevel@tonic-gate ioc_profile->ioc_protocol); 2537*0Sstevel@tonic-gate for (ii = 0; ii < IBNEX_MAX_COMPAT_NAMES; ii++) 2538*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tcompatible: %s", compatible[ii]); 2539*0Sstevel@tonic-gate 2540*0Sstevel@tonic-gate /* Create the compatible property for child cdip */ 2541*0Sstevel@tonic-gate rval = ndi_prop_update_string_array(DDI_DEV_T_NONE, cdip, 2542*0Sstevel@tonic-gate "compatible", (char **)compatible, IBNEX_MAX_COMPAT_NAMES); 2543*0Sstevel@tonic-gate 2544*0Sstevel@tonic-gate if (rval != DDI_PROP_SUCCESS) { 2545*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", "\tcompatible prop_create failed"); 2546*0Sstevel@tonic-gate kmem_free(temp, IBNEX_MAX_COMPAT_PROP_SZ); 2547*0Sstevel@tonic-gate return (IBNEX_FAILURE); 2548*0Sstevel@tonic-gate } 2549*0Sstevel@tonic-gate 2550*0Sstevel@tonic-gate kmem_free(temp, IBNEX_MAX_COMPAT_PROP_SZ); 2551*0Sstevel@tonic-gate return (IBNEX_SUCCESS); 2552*0Sstevel@tonic-gate } 2553*0Sstevel@tonic-gate 2554*0Sstevel@tonic-gate 2555*0Sstevel@tonic-gate static void 2556*0Sstevel@tonic-gate ibnex_ioc_node_cleanup() 2557*0Sstevel@tonic-gate { 2558*0Sstevel@tonic-gate ibnex_node_data_t *node, *delete; 2559*0Sstevel@tonic-gate 2560*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&ibnex.ibnex_mutex)); 2561*0Sstevel@tonic-gate for (node = ibnex.ibnex_ioc_node_head; node; ) { 2562*0Sstevel@tonic-gate delete = node; 2563*0Sstevel@tonic-gate node = node->node_next; 2564*0Sstevel@tonic-gate mutex_exit(&ibnex.ibnex_mutex); 2565*0Sstevel@tonic-gate ibnex_delete_ioc_node_data(delete); 2566*0Sstevel@tonic-gate mutex_enter(&ibnex.ibnex_mutex); 2567*0Sstevel@tonic-gate } 2568*0Sstevel@tonic-gate } 2569*0Sstevel@tonic-gate 2570*0Sstevel@tonic-gate /* 2571*0Sstevel@tonic-gate * ibnex_delete_ioc_node_data() 2572*0Sstevel@tonic-gate * Delete IOC node from the list 2573*0Sstevel@tonic-gate */ 2574*0Sstevel@tonic-gate static void 2575*0Sstevel@tonic-gate ibnex_delete_ioc_node_data(ibnex_node_data_t *node) 2576*0Sstevel@tonic-gate { 2577*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tdelete_ioc_node_data:"); 2578*0Sstevel@tonic-gate 2579*0Sstevel@tonic-gate mutex_enter(&ibnex.ibnex_mutex); 2580*0Sstevel@tonic-gate if ((node->node_next == NULL) && (node->node_prev == NULL)) { 2581*0Sstevel@tonic-gate ASSERT(ibnex.ibnex_ioc_node_head == node); 2582*0Sstevel@tonic-gate ibnex.ibnex_ioc_node_head = NULL; 2583*0Sstevel@tonic-gate } else if (node->node_next == NULL) 2584*0Sstevel@tonic-gate node->node_prev->node_next = NULL; 2585*0Sstevel@tonic-gate else if (node->node_prev == NULL) { 2586*0Sstevel@tonic-gate node->node_next->node_prev = NULL; 2587*0Sstevel@tonic-gate ibnex.ibnex_ioc_node_head = node->node_next; 2588*0Sstevel@tonic-gate } else { 2589*0Sstevel@tonic-gate node->node_prev->node_next = node->node_next; 2590*0Sstevel@tonic-gate node->node_next->node_prev = node->node_prev; 2591*0Sstevel@tonic-gate } 2592*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tdelete_ioc_node_data: head %p", 2593*0Sstevel@tonic-gate ibnex.ibnex_ioc_node_head); 2594*0Sstevel@tonic-gate mutex_exit(&ibnex.ibnex_mutex); 2595*0Sstevel@tonic-gate kmem_free(node, sizeof (ibnex_node_data_t)); 2596*0Sstevel@tonic-gate } 2597*0Sstevel@tonic-gate 2598*0Sstevel@tonic-gate 2599*0Sstevel@tonic-gate /* 2600*0Sstevel@tonic-gate * ibnex_dm_callback() 2601*0Sstevel@tonic-gate * 2602*0Sstevel@tonic-gate * This routine is registered with the IBDM during IB nexus attach. It 2603*0Sstevel@tonic-gate * is called by the IBDM module when it discovers 2604*0Sstevel@tonic-gate * New HCA port 2605*0Sstevel@tonic-gate * HCA port removal 2606*0Sstevel@tonic-gate * New HCA added 2607*0Sstevel@tonic-gate * HCA removed 2608*0Sstevel@tonic-gate */ 2609*0Sstevel@tonic-gate void 2610*0Sstevel@tonic-gate ibnex_dm_callback(void *arg, ibdm_events_t flag) 2611*0Sstevel@tonic-gate { 2612*0Sstevel@tonic-gate char hca_guid[IBNEX_HCAGUID_STRSZ]; 2613*0Sstevel@tonic-gate ibdm_ioc_info_t *ioc_list, *ioc; 2614*0Sstevel@tonic-gate ibnex_node_data_t *node_data; 2615*0Sstevel@tonic-gate 2616*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tdm_callback: attr %p event %x", arg, flag); 2617*0Sstevel@tonic-gate 2618*0Sstevel@tonic-gate switch (flag) { 2619*0Sstevel@tonic-gate case IBDM_EVENT_HCA_ADDED: 2620*0Sstevel@tonic-gate (void) snprintf(hca_guid, IBNEX_HCAGUID_STRSZ, "%llX", 2621*0Sstevel@tonic-gate (*(longlong_t *)arg)); 2622*0Sstevel@tonic-gate /* Create a devctl minor node for the HCA's port */ 2623*0Sstevel@tonic-gate if (ddi_create_minor_node(ibnex.ibnex_dip, hca_guid, S_IFCHR, 2624*0Sstevel@tonic-gate ddi_get_instance(ibnex.ibnex_dip), 2625*0Sstevel@tonic-gate DDI_NT_IB_ATTACHMENT_POINT, 0) != DDI_SUCCESS) { 2626*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tdm_callback: failed to " 2627*0Sstevel@tonic-gate "create minor node for port w/ guid %s", hca_guid); 2628*0Sstevel@tonic-gate } 2629*0Sstevel@tonic-gate 2630*0Sstevel@tonic-gate break; 2631*0Sstevel@tonic-gate 2632*0Sstevel@tonic-gate case IBDM_EVENT_HCA_REMOVED: 2633*0Sstevel@tonic-gate (void) snprintf(hca_guid, IBNEX_HCAGUID_STRSZ, "%llX", 2634*0Sstevel@tonic-gate (*(longlong_t *)arg)); 2635*0Sstevel@tonic-gate ddi_remove_minor_node(ibnex.ibnex_dip, hca_guid); 2636*0Sstevel@tonic-gate break; 2637*0Sstevel@tonic-gate 2638*0Sstevel@tonic-gate case IBDM_EVENT_IOC_PROP_UPDATE: 2639*0Sstevel@tonic-gate ioc = ioc_list = (ibdm_ioc_info_t *)arg; 2640*0Sstevel@tonic-gate if (ioc_list == NULL) 2641*0Sstevel@tonic-gate break; 2642*0Sstevel@tonic-gate 2643*0Sstevel@tonic-gate mutex_enter(&ibnex.ibnex_mutex); 2644*0Sstevel@tonic-gate while (ioc_list) { 2645*0Sstevel@tonic-gate if ((node_data = ibnex_is_node_data_present( 2646*0Sstevel@tonic-gate IBNEX_IOC_NODE, ioc_list, 0, 0)) != NULL && 2647*0Sstevel@tonic-gate node_data->node_dip != NULL) { 2648*0Sstevel@tonic-gate ibnex_update_prop(node_data, ioc_list); 2649*0Sstevel@tonic-gate } 2650*0Sstevel@tonic-gate ioc_list = ioc_list->ioc_next; 2651*0Sstevel@tonic-gate } 2652*0Sstevel@tonic-gate mutex_exit(&ibnex.ibnex_mutex); 2653*0Sstevel@tonic-gate ibdm_ibnex_free_ioc_list(ioc); 2654*0Sstevel@tonic-gate } 2655*0Sstevel@tonic-gate } 2656*0Sstevel@tonic-gate 2657*0Sstevel@tonic-gate 2658*0Sstevel@tonic-gate /* 2659*0Sstevel@tonic-gate * ibnex_get_dip_from_guid() 2660*0Sstevel@tonic-gate * 2661*0Sstevel@tonic-gate * Searches the linked list of the port nodes and returns the dip for 2662*0Sstevel@tonic-gate * the of the Port / Node guid requested. 2663*0Sstevel@tonic-gate * Returns NULL if not found 2664*0Sstevel@tonic-gate */ 2665*0Sstevel@tonic-gate int 2666*0Sstevel@tonic-gate ibnex_get_dip_from_guid(ib_guid_t guid, int index, ib_pkey_t pkey, 2667*0Sstevel@tonic-gate dev_info_t **dip) 2668*0Sstevel@tonic-gate { 2669*0Sstevel@tonic-gate int node_index; 2670*0Sstevel@tonic-gate ib_guid_t node_guid; 2671*0Sstevel@tonic-gate ib_pkey_t node_pkey; 2672*0Sstevel@tonic-gate ibnex_node_data_t *node_data; 2673*0Sstevel@tonic-gate 2674*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", 2675*0Sstevel@tonic-gate "\tget_dip_from_guid: guid = %llx", guid); 2676*0Sstevel@tonic-gate 2677*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&ibnex.ibnex_mutex)); 2678*0Sstevel@tonic-gate /* Search for a matching entry in internal lists */ 2679*0Sstevel@tonic-gate node_data = ibnex.ibnex_port_node_head; 2680*0Sstevel@tonic-gate while (node_data) { 2681*0Sstevel@tonic-gate node_guid = node_data->node_data.port_node.port_guid; 2682*0Sstevel@tonic-gate node_index = node_data->node_data.port_node.port_commsvc_idx; 2683*0Sstevel@tonic-gate node_pkey = node_data->node_data.port_node.port_pkey; 2684*0Sstevel@tonic-gate if ((node_guid == guid) && (index == node_index) && 2685*0Sstevel@tonic-gate (node_pkey == pkey)) { 2686*0Sstevel@tonic-gate break; 2687*0Sstevel@tonic-gate } 2688*0Sstevel@tonic-gate node_data = node_data->node_next; 2689*0Sstevel@tonic-gate } 2690*0Sstevel@tonic-gate 2691*0Sstevel@tonic-gate /* matching found with a valid dip */ 2692*0Sstevel@tonic-gate if (node_data && node_data->node_dip) { 2693*0Sstevel@tonic-gate *dip = node_data->node_dip; 2694*0Sstevel@tonic-gate return (IBNEX_SUCCESS); 2695*0Sstevel@tonic-gate } else if (node_data && !node_data->node_dip) { /* dip is invalid */ 2696*0Sstevel@tonic-gate *dip = NULL; 2697*0Sstevel@tonic-gate return (IBNEX_SUCCESS); 2698*0Sstevel@tonic-gate } 2699*0Sstevel@tonic-gate 2700*0Sstevel@tonic-gate /* no match found */ 2701*0Sstevel@tonic-gate *dip = NULL; 2702*0Sstevel@tonic-gate return (IBNEX_FAILURE); 2703*0Sstevel@tonic-gate } 2704*0Sstevel@tonic-gate 2705*0Sstevel@tonic-gate 2706*0Sstevel@tonic-gate /* 2707*0Sstevel@tonic-gate * ibnex_comm_svc_init() 2708*0Sstevel@tonic-gate * Read the property and cache the values in the global 2709*0Sstevel@tonic-gate * structure. 2710*0Sstevel@tonic-gate * Check for max allowed length (4 bytes) of service name 2711*0Sstevel@tonic-gate * (each element of the property) 2712*0Sstevel@tonic-gate * Returns IBNEX_SUCCESS/IBNEX_FAILURE 2713*0Sstevel@tonic-gate */ 2714*0Sstevel@tonic-gate static ibnex_rval_t 2715*0Sstevel@tonic-gate ibnex_comm_svc_init(char *property, ibnex_node_type_t type) 2716*0Sstevel@tonic-gate { 2717*0Sstevel@tonic-gate int i, len, count; 2718*0Sstevel@tonic-gate int ncomm_svcs; 2719*0Sstevel@tonic-gate char **comm_svcp; 2720*0Sstevel@tonic-gate char **servicep = NULL; 2721*0Sstevel@tonic-gate uint_t nservices = 0; 2722*0Sstevel@tonic-gate int *valid = NULL; 2723*0Sstevel@tonic-gate 2724*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tcomm_svc_init : %s property, type = %x", 2725*0Sstevel@tonic-gate property, type); 2726*0Sstevel@tonic-gate 2727*0Sstevel@tonic-gate /* lookup the string array property */ 2728*0Sstevel@tonic-gate if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, ibnex.ibnex_dip, 2729*0Sstevel@tonic-gate DDI_PROP_DONTPASS, property, &servicep, &nservices) != 2730*0Sstevel@tonic-gate DDI_PROP_SUCCESS) { 2731*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", "\t%s property undefined", property); 2732*0Sstevel@tonic-gate return (IBNEX_SUCCESS); 2733*0Sstevel@tonic-gate } 2734*0Sstevel@tonic-gate 2735*0Sstevel@tonic-gate if (nservices) 2736*0Sstevel@tonic-gate valid = kmem_zalloc(nservices * sizeof (int), KM_SLEEP); 2737*0Sstevel@tonic-gate 2738*0Sstevel@tonic-gate 2739*0Sstevel@tonic-gate /* first read the file to get a count of valid service entries */ 2740*0Sstevel@tonic-gate for (ncomm_svcs = 0, count = 0; count < nservices; count++) { 2741*0Sstevel@tonic-gate int j; 2742*0Sstevel@tonic-gate 2743*0Sstevel@tonic-gate len = strlen(servicep[count]); 2744*0Sstevel@tonic-gate if (len == 0 || len > 4) { 2745*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", "\tcomm_svc_init : " 2746*0Sstevel@tonic-gate "Service name %s invalid : length %d", 2747*0Sstevel@tonic-gate servicep[count], len); 2748*0Sstevel@tonic-gate continue; 2749*0Sstevel@tonic-gate } 2750*0Sstevel@tonic-gate if (ibnex_unique_svcname(servicep[count]) != IBNEX_SUCCESS) { 2751*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", "\tcomm_svc_init : " 2752*0Sstevel@tonic-gate "Service name %s invalid : Not unique", 2753*0Sstevel@tonic-gate servicep[count]); 2754*0Sstevel@tonic-gate continue; 2755*0Sstevel@tonic-gate } 2756*0Sstevel@tonic-gate 2757*0Sstevel@tonic-gate /* 2758*0Sstevel@tonic-gate * ibnex_unique_svcname checks for uniqueness in service names 2759*0Sstevel@tonic-gate * communication services fully initialized. Check uniqueness 2760*0Sstevel@tonic-gate * in service names currently initialized. 2761*0Sstevel@tonic-gate */ 2762*0Sstevel@tonic-gate for (j = 0; j < count; j++) 2763*0Sstevel@tonic-gate if (valid[j] && strncmp(servicep[count], 2764*0Sstevel@tonic-gate servicep[j], 4) == 0) { 2765*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", "\tcomm_svc_init : " 2766*0Sstevel@tonic-gate "Service name %s invalid : Not unique", 2767*0Sstevel@tonic-gate servicep[count]); 2768*0Sstevel@tonic-gate continue; 2769*0Sstevel@tonic-gate } 2770*0Sstevel@tonic-gate 2771*0Sstevel@tonic-gate valid[count] = 1; 2772*0Sstevel@tonic-gate ncomm_svcs++; 2773*0Sstevel@tonic-gate } 2774*0Sstevel@tonic-gate 2775*0Sstevel@tonic-gate /* if no valid entries found, bailout */ 2776*0Sstevel@tonic-gate if (nservices == 0 || ncomm_svcs == 0) { 2777*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tNo %s entries found", property); 2778*0Sstevel@tonic-gate ddi_prop_free(servicep); /* free the property */ 2779*0Sstevel@tonic-gate if (valid) 2780*0Sstevel@tonic-gate kmem_free(valid, nservices * sizeof (int)); 2781*0Sstevel@tonic-gate return (IBNEX_SUCCESS); 2782*0Sstevel@tonic-gate } 2783*0Sstevel@tonic-gate 2784*0Sstevel@tonic-gate comm_svcp = kmem_zalloc((ncomm_svcs * sizeof (char *)), KM_SLEEP); 2785*0Sstevel@tonic-gate if (type == IBNEX_PORT_COMMSVC_NODE) { 2786*0Sstevel@tonic-gate ibnex.ibnex_comm_svc_names = comm_svcp; 2787*0Sstevel@tonic-gate ibnex.ibnex_num_comm_svcs = ncomm_svcs; 2788*0Sstevel@tonic-gate } else if (type == IBNEX_VPPA_COMMSVC_NODE) { 2789*0Sstevel@tonic-gate ibnex.ibnex_vppa_comm_svc_names = comm_svcp; 2790*0Sstevel@tonic-gate ibnex.ibnex_nvppa_comm_svcs = ncomm_svcs; 2791*0Sstevel@tonic-gate } else if (type == IBNEX_HCASVC_COMMSVC_NODE) { 2792*0Sstevel@tonic-gate ibnex.ibnex_hcasvc_comm_svc_names = comm_svcp; 2793*0Sstevel@tonic-gate ibnex.ibnex_nhcasvc_comm_svcs = ncomm_svcs; 2794*0Sstevel@tonic-gate } 2795*0Sstevel@tonic-gate 2796*0Sstevel@tonic-gate /* copy the services into an array of strings */ 2797*0Sstevel@tonic-gate for (i = 0, count = 0; count < nservices; count++) { 2798*0Sstevel@tonic-gate if (valid[count] == 0) /* Skip invalid ones */ 2799*0Sstevel@tonic-gate continue; 2800*0Sstevel@tonic-gate comm_svcp[i] = kmem_alloc(len + 1, KM_SLEEP); 2801*0Sstevel@tonic-gate (void) strcpy(comm_svcp[i], servicep[count]); 2802*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", 2803*0Sstevel@tonic-gate "\t\tService [%d]: %s", i, comm_svcp[i]); 2804*0Sstevel@tonic-gate ++i; 2805*0Sstevel@tonic-gate } 2806*0Sstevel@tonic-gate ddi_prop_free(servicep); 2807*0Sstevel@tonic-gate kmem_free(valid, nservices * sizeof (int)); 2808*0Sstevel@tonic-gate return (IBNEX_SUCCESS); 2809*0Sstevel@tonic-gate } 2810*0Sstevel@tonic-gate 2811*0Sstevel@tonic-gate 2812*0Sstevel@tonic-gate /* 2813*0Sstevel@tonic-gate * ibnex_comm_svc_fini() 2814*0Sstevel@tonic-gate * Deallocate all the memory allocated for the communication 2815*0Sstevel@tonic-gate * service arrays. 2816*0Sstevel@tonic-gate */ 2817*0Sstevel@tonic-gate static void 2818*0Sstevel@tonic-gate ibnex_comm_svc_fini() 2819*0Sstevel@tonic-gate { 2820*0Sstevel@tonic-gate int index; 2821*0Sstevel@tonic-gate 2822*0Sstevel@tonic-gate for (index = 0; index < ibnex.ibnex_num_comm_svcs; index++) { 2823*0Sstevel@tonic-gate kmem_free(ibnex.ibnex_comm_svc_names[index], 2824*0Sstevel@tonic-gate (strlen(ibnex.ibnex_comm_svc_names[index]) + 1)); 2825*0Sstevel@tonic-gate } 2826*0Sstevel@tonic-gate if (ibnex.ibnex_comm_svc_names) { 2827*0Sstevel@tonic-gate kmem_free(ibnex.ibnex_comm_svc_names, 2828*0Sstevel@tonic-gate ibnex.ibnex_num_comm_svcs * sizeof (char *)); 2829*0Sstevel@tonic-gate } 2830*0Sstevel@tonic-gate for (index = 0; index < ibnex.ibnex_nvppa_comm_svcs; index++) { 2831*0Sstevel@tonic-gate kmem_free(ibnex.ibnex_vppa_comm_svc_names[index], 2832*0Sstevel@tonic-gate strlen(ibnex.ibnex_vppa_comm_svc_names[index]) +1); 2833*0Sstevel@tonic-gate } 2834*0Sstevel@tonic-gate if (ibnex.ibnex_vppa_comm_svc_names) { 2835*0Sstevel@tonic-gate kmem_free(ibnex.ibnex_vppa_comm_svc_names, 2836*0Sstevel@tonic-gate ibnex.ibnex_nvppa_comm_svcs * sizeof (char *)); 2837*0Sstevel@tonic-gate } 2838*0Sstevel@tonic-gate for (index = 0; index < ibnex.ibnex_nhcasvc_comm_svcs; index++) { 2839*0Sstevel@tonic-gate kmem_free(ibnex.ibnex_hcasvc_comm_svc_names[index], 2840*0Sstevel@tonic-gate strlen(ibnex.ibnex_hcasvc_comm_svc_names[index]) +1); 2841*0Sstevel@tonic-gate } 2842*0Sstevel@tonic-gate if (ibnex.ibnex_hcasvc_comm_svc_names) { 2843*0Sstevel@tonic-gate kmem_free(ibnex.ibnex_hcasvc_comm_svc_names, 2844*0Sstevel@tonic-gate ibnex.ibnex_nhcasvc_comm_svcs * sizeof (char *)); 2845*0Sstevel@tonic-gate } 2846*0Sstevel@tonic-gate ibnex.ibnex_comm_svc_names = NULL; 2847*0Sstevel@tonic-gate ibnex.ibnex_num_comm_svcs = 0; 2848*0Sstevel@tonic-gate ibnex.ibnex_vppa_comm_svc_names = NULL; 2849*0Sstevel@tonic-gate ibnex.ibnex_nvppa_comm_svcs = 0; 2850*0Sstevel@tonic-gate ibnex.ibnex_hcasvc_comm_svc_names = NULL; 2851*0Sstevel@tonic-gate ibnex.ibnex_nhcasvc_comm_svcs = 0; 2852*0Sstevel@tonic-gate } 2853*0Sstevel@tonic-gate 2854*0Sstevel@tonic-gate 2855*0Sstevel@tonic-gate /* 2856*0Sstevel@tonic-gate * ibnex_commsvc_initnode() 2857*0Sstevel@tonic-gate * This routine is specific to port/VPPA node creation 2858*0Sstevel@tonic-gate * Creates a device node for the comm service specified by commsvc_index 2859*0Sstevel@tonic-gate * Creates all the device node properties 2860*0Sstevel@tonic-gate * Allocates and initializes the node specific data 2861*0Sstevel@tonic-gate * Binds the device driver of the device node 2862*0Sstevel@tonic-gate * Returns "dev_info_t" of the child node or NULL in case of failure 2863*0Sstevel@tonic-gate * Sets IBNEX_SUCCESS/IBNEX_FAILURE/IBNEX_BUSY in "rval" to reflect 2864*0Sstevel@tonic-gate * if the operation was successful, failed or was not performed. 2865*0Sstevel@tonic-gate */ 2866*0Sstevel@tonic-gate dev_info_t * 2867*0Sstevel@tonic-gate ibnex_commsvc_initnode(dev_info_t *parent, ibdm_port_attr_t *port_attr, 2868*0Sstevel@tonic-gate int index, int node_type, ib_pkey_t pkey, int *rval, int flag) 2869*0Sstevel@tonic-gate { 2870*0Sstevel@tonic-gate int ret; 2871*0Sstevel@tonic-gate char *svcname; 2872*0Sstevel@tonic-gate dev_info_t *cdip; 2873*0Sstevel@tonic-gate ibnex_node_data_t *node_data; 2874*0Sstevel@tonic-gate 2875*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&ibnex.ibnex_mutex)); 2876*0Sstevel@tonic-gate 2877*0Sstevel@tonic-gate *rval = IBNEX_SUCCESS; 2878*0Sstevel@tonic-gate 2879*0Sstevel@tonic-gate /* 2880*0Sstevel@tonic-gate * prevent any races 2881*0Sstevel@tonic-gate * we have seen this node_data and it has been initialized 2882*0Sstevel@tonic-gate * Note that node_dip is already NULL if unconfigure is in 2883*0Sstevel@tonic-gate * progress. 2884*0Sstevel@tonic-gate */ 2885*0Sstevel@tonic-gate node_data = ibnex_is_node_data_present(node_type, (void *)port_attr, 2886*0Sstevel@tonic-gate index, pkey); 2887*0Sstevel@tonic-gate if (node_data && node_data->node_dip) { 2888*0Sstevel@tonic-gate /* 2889*0Sstevel@tonic-gate * Return NULL if another configure 2890*0Sstevel@tonic-gate * operation is in progress 2891*0Sstevel@tonic-gate */ 2892*0Sstevel@tonic-gate if (node_data->node_state == IBNEX_CFGADM_CONFIGURING) { 2893*0Sstevel@tonic-gate *rval = IBNEX_BUSY; 2894*0Sstevel@tonic-gate return (NULL); 2895*0Sstevel@tonic-gate } else { 2896*0Sstevel@tonic-gate return (node_data->node_dip); 2897*0Sstevel@tonic-gate } 2898*0Sstevel@tonic-gate } else if (node_data == NULL) { 2899*0Sstevel@tonic-gate /* allocate a new ibnex_node_data_t */ 2900*0Sstevel@tonic-gate node_data = ibnex_init_child_nodedata(node_type, port_attr, 2901*0Sstevel@tonic-gate index, pkey); 2902*0Sstevel@tonic-gate } 2903*0Sstevel@tonic-gate 2904*0Sstevel@tonic-gate /* 2905*0Sstevel@tonic-gate * Return NULL if another unconfigure operation is in progress 2906*0Sstevel@tonic-gate */ 2907*0Sstevel@tonic-gate if (node_data->node_state == IBNEX_CFGADM_UNCONFIGURING) { 2908*0Sstevel@tonic-gate *rval = IBNEX_BUSY; 2909*0Sstevel@tonic-gate return (NULL); 2910*0Sstevel@tonic-gate } 2911*0Sstevel@tonic-gate 2912*0Sstevel@tonic-gate ASSERT(node_data->node_state != IBNEX_CFGADM_CONFIGURED); 2913*0Sstevel@tonic-gate node_data->node_state = IBNEX_CFGADM_CONFIGURING; 2914*0Sstevel@tonic-gate 2915*0Sstevel@tonic-gate ndi_devi_alloc_sleep(parent, 2916*0Sstevel@tonic-gate IBNEX_IBPORT_CNAME, (dnode_t)DEVI_SID_NODEID, &cdip); 2917*0Sstevel@tonic-gate 2918*0Sstevel@tonic-gate node_data->node_dip = cdip; 2919*0Sstevel@tonic-gate ddi_set_parent_data(cdip, node_data); 2920*0Sstevel@tonic-gate mutex_exit(&ibnex.ibnex_mutex); 2921*0Sstevel@tonic-gate 2922*0Sstevel@tonic-gate switch (node_type) { 2923*0Sstevel@tonic-gate case IBNEX_VPPA_COMMSVC_NODE : 2924*0Sstevel@tonic-gate svcname = ibnex.ibnex_vppa_comm_svc_names[index]; 2925*0Sstevel@tonic-gate break; 2926*0Sstevel@tonic-gate case IBNEX_HCASVC_COMMSVC_NODE : 2927*0Sstevel@tonic-gate svcname = ibnex.ibnex_hcasvc_comm_svc_names[index]; 2928*0Sstevel@tonic-gate break; 2929*0Sstevel@tonic-gate case IBNEX_PORT_COMMSVC_NODE : 2930*0Sstevel@tonic-gate svcname = ibnex.ibnex_comm_svc_names[index]; 2931*0Sstevel@tonic-gate break; 2932*0Sstevel@tonic-gate default : 2933*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", "\tcommsvc_initnode:" 2934*0Sstevel@tonic-gate "\tInvalid Node type"); 2935*0Sstevel@tonic-gate *rval = IBNEX_FAILURE; 2936*0Sstevel@tonic-gate ibnex_delete_port_node_data(node_data); 2937*0Sstevel@tonic-gate ddi_prop_remove_all(cdip); 2938*0Sstevel@tonic-gate ddi_set_parent_data(cdip, NULL); 2939*0Sstevel@tonic-gate (void) ndi_devi_free(cdip); 2940*0Sstevel@tonic-gate mutex_enter(&ibnex.ibnex_mutex); 2941*0Sstevel@tonic-gate return (NULL); 2942*0Sstevel@tonic-gate } 2943*0Sstevel@tonic-gate 2944*0Sstevel@tonic-gate if (ibnex_create_port_node_prop(port_attr, cdip, svcname, pkey) == 2945*0Sstevel@tonic-gate IBNEX_SUCCESS) { 2946*0Sstevel@tonic-gate if (flag == IBNEX_DEVFS_ENUMERATE) 2947*0Sstevel@tonic-gate ret = ndi_devi_bind_driver(cdip, 0); 2948*0Sstevel@tonic-gate else 2949*0Sstevel@tonic-gate ret = ndi_devi_online(cdip, 0); 2950*0Sstevel@tonic-gate if (ret == NDI_SUCCESS) { 2951*0Sstevel@tonic-gate mutex_enter(&ibnex.ibnex_mutex); 2952*0Sstevel@tonic-gate node_data->node_state = IBNEX_CFGADM_CONFIGURED; 2953*0Sstevel@tonic-gate return (cdip); 2954*0Sstevel@tonic-gate } 2955*0Sstevel@tonic-gate } 2956*0Sstevel@tonic-gate *rval = IBNEX_FAILURE; 2957*0Sstevel@tonic-gate ibnex_delete_port_node_data(node_data); 2958*0Sstevel@tonic-gate ddi_prop_remove_all(cdip); 2959*0Sstevel@tonic-gate ddi_set_parent_data(cdip, NULL); 2960*0Sstevel@tonic-gate (void) ndi_devi_free(cdip); 2961*0Sstevel@tonic-gate mutex_enter(&ibnex.ibnex_mutex); 2962*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tcommsvc_initnode: failure exit"); 2963*0Sstevel@tonic-gate return (NULL); 2964*0Sstevel@tonic-gate } 2965*0Sstevel@tonic-gate 2966*0Sstevel@tonic-gate 2967*0Sstevel@tonic-gate /* 2968*0Sstevel@tonic-gate * ibnex_create_port_node_prop() 2969*0Sstevel@tonic-gate * Returns IBNEX_SUCCESS/IBNEX_FAILURE 2970*0Sstevel@tonic-gate */ 2971*0Sstevel@tonic-gate static int 2972*0Sstevel@tonic-gate ibnex_create_port_node_prop(ibdm_port_attr_t *port_attr, 2973*0Sstevel@tonic-gate dev_info_t *child_dip, char *srvname, ib_pkey_t pkey) 2974*0Sstevel@tonic-gate { 2975*0Sstevel@tonic-gate if (ibnex_create_port_compatible_prop(child_dip, 2976*0Sstevel@tonic-gate srvname, port_attr) != DDI_PROP_SUCCESS) { 2977*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", 2978*0Sstevel@tonic-gate "\tcreate_port_node_prop: compatible update failed"); 2979*0Sstevel@tonic-gate return (IBNEX_FAILURE); 2980*0Sstevel@tonic-gate } 2981*0Sstevel@tonic-gate if ((pkey != 0) && (ndi_prop_update_int(DDI_DEV_T_NONE, child_dip, 2982*0Sstevel@tonic-gate "port-pkey", pkey) != DDI_PROP_SUCCESS)) { 2983*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", 2984*0Sstevel@tonic-gate "\tcreate_port_node_prop: port-num update failed"); 2985*0Sstevel@tonic-gate return (IBNEX_FAILURE); 2986*0Sstevel@tonic-gate } 2987*0Sstevel@tonic-gate 2988*0Sstevel@tonic-gate /* 2989*0Sstevel@tonic-gate * For HCA_SVC device nodes, port_num will be 0. 2990*0Sstevel@tonic-gate * Do not create the "port-number" & "port-guid" properties. 2991*0Sstevel@tonic-gate */ 2992*0Sstevel@tonic-gate if (port_attr->pa_port_num != 0) { 2993*0Sstevel@tonic-gate if (ndi_prop_update_int(DDI_DEV_T_NONE, child_dip, 2994*0Sstevel@tonic-gate "port-number", port_attr->pa_port_num) != 2995*0Sstevel@tonic-gate DDI_PROP_SUCCESS) { 2996*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", 2997*0Sstevel@tonic-gate "\tcreate_port_node_prop: port-num update failed"); 2998*0Sstevel@tonic-gate return (IBNEX_FAILURE); 2999*0Sstevel@tonic-gate } 3000*0Sstevel@tonic-gate if (ndi_prop_update_int64(DDI_DEV_T_NONE, child_dip, 3001*0Sstevel@tonic-gate "port-guid", port_attr->pa_port_guid) != 3002*0Sstevel@tonic-gate DDI_PROP_SUCCESS) { 3003*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", 3004*0Sstevel@tonic-gate "\tcreate_port_node_prop: port-guid update failed"); 3005*0Sstevel@tonic-gate return (IBNEX_FAILURE); 3006*0Sstevel@tonic-gate } 3007*0Sstevel@tonic-gate } else { 3008*0Sstevel@tonic-gate ibdm_hca_list_t *hca_list; 3009*0Sstevel@tonic-gate 3010*0Sstevel@tonic-gate /* 3011*0Sstevel@tonic-gate * HCA_SVC nodes require "num-ports" & "port-guids" 3012*0Sstevel@tonic-gate * properties. 3013*0Sstevel@tonic-gate * 3014*0Sstevel@tonic-gate * To create the num-ports & port-guids attribute : 3015*0Sstevel@tonic-gate * 1. Get HCA list (ibdm_ibnex_get_hca_info_by_guid) 3016*0Sstevel@tonic-gate * 2. Form the array of port GUIDs. 3017*0Sstevel@tonic-gate */ 3018*0Sstevel@tonic-gate if ((hca_list = ibdm_ibnex_get_hca_info_by_guid( 3019*0Sstevel@tonic-gate port_attr->pa_hca_guid)) == NULL) { 3020*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", 3021*0Sstevel@tonic-gate "\tcreate_port_node_prop: hca_info_by_guid failed"); 3022*0Sstevel@tonic-gate return (IBNEX_FAILURE); 3023*0Sstevel@tonic-gate } 3024*0Sstevel@tonic-gate 3025*0Sstevel@tonic-gate if (hca_list->hl_nports != 0) { 3026*0Sstevel@tonic-gate ib_guid_t *port_guids; 3027*0Sstevel@tonic-gate uint8_t portnum; 3028*0Sstevel@tonic-gate 3029*0Sstevel@tonic-gate ASSERT(hca_list->hl_port_attr != NULL); 3030*0Sstevel@tonic-gate 3031*0Sstevel@tonic-gate port_guids = kmem_zalloc( 3032*0Sstevel@tonic-gate hca_list->hl_nports * sizeof (ib_guid_t), 3033*0Sstevel@tonic-gate KM_SLEEP); 3034*0Sstevel@tonic-gate 3035*0Sstevel@tonic-gate for (portnum = 0; portnum < hca_list->hl_nports; 3036*0Sstevel@tonic-gate portnum++) { 3037*0Sstevel@tonic-gate port_guids[portnum] = (hca_list-> 3038*0Sstevel@tonic-gate hl_port_attr[portnum]).pa_port_guid; 3039*0Sstevel@tonic-gate } 3040*0Sstevel@tonic-gate 3041*0Sstevel@tonic-gate if (ndi_prop_update_int64_array(DDI_DEV_T_NONE, 3042*0Sstevel@tonic-gate child_dip, "port-guids", (int64_t *)port_guids, 3043*0Sstevel@tonic-gate hca_list->hl_nports) != DDI_PROP_SUCCESS) { 3044*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", 3045*0Sstevel@tonic-gate "\tcreate_port_node_prop: port-guids " 3046*0Sstevel@tonic-gate "create failed"); 3047*0Sstevel@tonic-gate kmem_free(port_guids, hca_list->hl_nports * 3048*0Sstevel@tonic-gate sizeof (ib_guid_t)); 3049*0Sstevel@tonic-gate ibdm_ibnex_free_hca_list(hca_list); 3050*0Sstevel@tonic-gate return (IBNEX_FAILURE); 3051*0Sstevel@tonic-gate } 3052*0Sstevel@tonic-gate kmem_free(port_guids, hca_list->hl_nports * 3053*0Sstevel@tonic-gate sizeof (ib_guid_t)); 3054*0Sstevel@tonic-gate } 3055*0Sstevel@tonic-gate 3056*0Sstevel@tonic-gate if (ndi_prop_update_int(DDI_DEV_T_NONE, child_dip, 3057*0Sstevel@tonic-gate "num-ports", hca_list->hl_nports) != DDI_PROP_SUCCESS) { 3058*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", 3059*0Sstevel@tonic-gate "\tcreate_port_node_prop: num-ports update failed"); 3060*0Sstevel@tonic-gate ibdm_ibnex_free_hca_list(hca_list); 3061*0Sstevel@tonic-gate return (IBNEX_FAILURE); 3062*0Sstevel@tonic-gate } 3063*0Sstevel@tonic-gate ibdm_ibnex_free_hca_list(hca_list); 3064*0Sstevel@tonic-gate } 3065*0Sstevel@tonic-gate 3066*0Sstevel@tonic-gate if (ndi_prop_update_int64(DDI_DEV_T_NONE, child_dip, 3067*0Sstevel@tonic-gate "hca-guid", port_attr->pa_hca_guid) != DDI_PROP_SUCCESS) { 3068*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", 3069*0Sstevel@tonic-gate "\tcreate_port_node_prop: hca-guid update failed"); 3070*0Sstevel@tonic-gate return (IBNEX_FAILURE); 3071*0Sstevel@tonic-gate } 3072*0Sstevel@tonic-gate if (ndi_prop_update_int(DDI_DEV_T_NONE, child_dip, 3073*0Sstevel@tonic-gate "product-id", port_attr->pa_productid) != DDI_PROP_SUCCESS) { 3074*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", 3075*0Sstevel@tonic-gate "\tcreate_port_node_prop: product-id update failed"); 3076*0Sstevel@tonic-gate return (IBNEX_FAILURE); 3077*0Sstevel@tonic-gate } 3078*0Sstevel@tonic-gate if (ndi_prop_update_int(DDI_DEV_T_NONE, child_dip, 3079*0Sstevel@tonic-gate "vendor-id", port_attr->pa_vendorid) != DDI_PROP_SUCCESS) { 3080*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", 3081*0Sstevel@tonic-gate "\tcreate_port_node_prop: vendor-id update failed"); 3082*0Sstevel@tonic-gate return (IBNEX_FAILURE); 3083*0Sstevel@tonic-gate } 3084*0Sstevel@tonic-gate if (ndi_prop_update_int(DDI_DEV_T_NONE, child_dip, "device-version", 3085*0Sstevel@tonic-gate port_attr->pa_dev_version) != DDI_PROP_SUCCESS) { 3086*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", 3087*0Sstevel@tonic-gate "\tcreate_port_node_prop: device-version update failed"); 3088*0Sstevel@tonic-gate return (IBNEX_FAILURE); 3089*0Sstevel@tonic-gate } 3090*0Sstevel@tonic-gate return (IBNEX_SUCCESS); 3091*0Sstevel@tonic-gate } 3092*0Sstevel@tonic-gate 3093*0Sstevel@tonic-gate 3094*0Sstevel@tonic-gate /* 3095*0Sstevel@tonic-gate * ibnex_str2int() 3096*0Sstevel@tonic-gate * Utility function that converts a string of length "len" to 3097*0Sstevel@tonic-gate * integer. 3098*0Sstevel@tonic-gate * Returns IBNEX_SUCCESS/IBNEX_FAILURE 3099*0Sstevel@tonic-gate */ 3100*0Sstevel@tonic-gate static int 3101*0Sstevel@tonic-gate ibnex_str2int(char *c, int len, int *ret) 3102*0Sstevel@tonic-gate { 3103*0Sstevel@tonic-gate int intval = 0, ii; 3104*0Sstevel@tonic-gate 3105*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tstr2int: Int string %s..", c); 3106*0Sstevel@tonic-gate *ret = IBNEX_SUCCESS; 3107*0Sstevel@tonic-gate for (ii = 0; ii < len; ii ++) { 3108*0Sstevel@tonic-gate if ((c[ii] >= '0') && (c[ii] <= '9')) 3109*0Sstevel@tonic-gate intval = intval * 10 +c[ii] - '0'; 3110*0Sstevel@tonic-gate else { 3111*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", 3112*0Sstevel@tonic-gate "\tstr2int: Invalid integer string %s..", c); 3113*0Sstevel@tonic-gate *ret = IBNEX_FAILURE; 3114*0Sstevel@tonic-gate break; 3115*0Sstevel@tonic-gate } 3116*0Sstevel@tonic-gate } 3117*0Sstevel@tonic-gate 3118*0Sstevel@tonic-gate return (intval); 3119*0Sstevel@tonic-gate } 3120*0Sstevel@tonic-gate 3121*0Sstevel@tonic-gate 3122*0Sstevel@tonic-gate /* 3123*0Sstevel@tonic-gate * ibnex_str2hex() 3124*0Sstevel@tonic-gate * Utility functions that converts a string of length "len" to 3125*0Sstevel@tonic-gate * hex value. Note. This function does not handle strings which 3126*0Sstevel@tonic-gate * string length more than 8 bytes. 3127*0Sstevel@tonic-gate * 3128*0Sstevel@tonic-gate */ 3129*0Sstevel@tonic-gate uint64_t 3130*0Sstevel@tonic-gate ibnex_str2hex(char *c, int len, int *ret) 3131*0Sstevel@tonic-gate { 3132*0Sstevel@tonic-gate uint64_t hex = 0, ii; 3133*0Sstevel@tonic-gate 3134*0Sstevel@tonic-gate *ret = IBNEX_SUCCESS; 3135*0Sstevel@tonic-gate for (ii = 0; ii < len; ii ++) { 3136*0Sstevel@tonic-gate hex = (ii == 0) ? hex : (hex << 4); 3137*0Sstevel@tonic-gate if ((c[ii] >= '0') && (c[ii] <= '9')) 3138*0Sstevel@tonic-gate hex |= c[ii] - '0'; 3139*0Sstevel@tonic-gate else if ((c[ii] >= 'a') && (c[ii] <= 'f')) 3140*0Sstevel@tonic-gate hex |= c[ii] - 'a' + 10; 3141*0Sstevel@tonic-gate else if ((c[ii] >= 'A') && (c[ii] <= 'F')) 3142*0Sstevel@tonic-gate hex |= c[ii] - 'A' + 10; 3143*0Sstevel@tonic-gate else { 3144*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", 3145*0Sstevel@tonic-gate "\tstr2hex: Invalid integer string"); 3146*0Sstevel@tonic-gate *ret = IBNEX_FAILURE; 3147*0Sstevel@tonic-gate break; 3148*0Sstevel@tonic-gate } 3149*0Sstevel@tonic-gate } 3150*0Sstevel@tonic-gate 3151*0Sstevel@tonic-gate return (hex); 3152*0Sstevel@tonic-gate } 3153*0Sstevel@tonic-gate 3154*0Sstevel@tonic-gate 3155*0Sstevel@tonic-gate /* 3156*0Sstevel@tonic-gate * ibnex_create_port_compatible_prop() 3157*0Sstevel@tonic-gate * Creates 'Compatibility' property for port / HCA_SVC device nodes 3158*0Sstevel@tonic-gate * Returns IBNEX_SUCCESS/IBNEX_FAILURE 3159*0Sstevel@tonic-gate */ 3160*0Sstevel@tonic-gate static int 3161*0Sstevel@tonic-gate ibnex_create_port_compatible_prop(dev_info_t *child_dip, 3162*0Sstevel@tonic-gate char *comm_svcp, ibdm_port_attr_t *port_attr) 3163*0Sstevel@tonic-gate { 3164*0Sstevel@tonic-gate int rval, i; 3165*0Sstevel@tonic-gate char *temp; 3166*0Sstevel@tonic-gate char *compatible[IBNEX_MAX_IBPORT_COMPAT_NAMES]; 3167*0Sstevel@tonic-gate 3168*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tcreate_port_compatible_prop: Begin"); 3169*0Sstevel@tonic-gate /* 3170*0Sstevel@tonic-gate * Initialize the "compatible" property string as below: 3171*0Sstevel@tonic-gate * Compatible Strings : 3172*0Sstevel@tonic-gate * 1. ib.V<vid>P<pid>v<revision>.<service name>. 3173*0Sstevel@tonic-gate * 2. ib.V<vid>P<pid>.<service name>. 3174*0Sstevel@tonic-gate * 3. ib.<service name> 3175*0Sstevel@tonic-gate * Leading zeros must be present 3176*0Sstevel@tonic-gate */ 3177*0Sstevel@tonic-gate temp = kmem_alloc(IBNEX_MAX_IBPORT_COMPAT_PROP_SZ, KM_SLEEP); 3178*0Sstevel@tonic-gate for (i = 0; i < IBNEX_MAX_IBPORT_COMPAT_NAMES; i++) { 3179*0Sstevel@tonic-gate compatible[i] = temp + (i * IBNEX_MAX_COMPAT_LEN); 3180*0Sstevel@tonic-gate } 3181*0Sstevel@tonic-gate 3182*0Sstevel@tonic-gate (void) snprintf(compatible[0], IBNEX_MAX_COMPAT_LEN, 3183*0Sstevel@tonic-gate "ib.V%06xP%08xv%04x.%s", 3184*0Sstevel@tonic-gate port_attr->pa_vendorid, port_attr->pa_productid, 3185*0Sstevel@tonic-gate port_attr->pa_dev_version, comm_svcp); 3186*0Sstevel@tonic-gate (void) snprintf(compatible[1], IBNEX_MAX_COMPAT_LEN, 3187*0Sstevel@tonic-gate "ib.V%06xP%08x.%s", 3188*0Sstevel@tonic-gate port_attr->pa_vendorid, port_attr->pa_productid, 3189*0Sstevel@tonic-gate comm_svcp); 3190*0Sstevel@tonic-gate (void) snprintf(compatible[2], IBNEX_MAX_COMPAT_LEN, 3191*0Sstevel@tonic-gate "ib.%s", comm_svcp); 3192*0Sstevel@tonic-gate 3193*0Sstevel@tonic-gate for (i = 0; i < IBNEX_MAX_IBPORT_COMPAT_NAMES; i++) 3194*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tcompatible: %s", compatible[i]); 3195*0Sstevel@tonic-gate 3196*0Sstevel@tonic-gate rval = ndi_prop_update_string_array(DDI_DEV_T_NONE, child_dip, 3197*0Sstevel@tonic-gate "compatible", (char **)compatible, IBNEX_MAX_IBPORT_COMPAT_NAMES); 3198*0Sstevel@tonic-gate 3199*0Sstevel@tonic-gate if (rval != DDI_PROP_SUCCESS) { 3200*0Sstevel@tonic-gate kmem_free(temp, IBNEX_MAX_IBPORT_COMPAT_PROP_SZ); 3201*0Sstevel@tonic-gate return (IBNEX_FAILURE); 3202*0Sstevel@tonic-gate } 3203*0Sstevel@tonic-gate kmem_free(temp, IBNEX_MAX_IBPORT_COMPAT_PROP_SZ); 3204*0Sstevel@tonic-gate return (IBNEX_SUCCESS); 3205*0Sstevel@tonic-gate } 3206*0Sstevel@tonic-gate 3207*0Sstevel@tonic-gate 3208*0Sstevel@tonic-gate /* 3209*0Sstevel@tonic-gate * ibnex_delete_port_node_data() 3210*0Sstevel@tonic-gate * Delete the parent private node data from the linked list 3211*0Sstevel@tonic-gate * Deallocate the memory of the port/ioc attributes 3212*0Sstevel@tonic-gate * Deallocate the memory of the node data 3213*0Sstevel@tonic-gate */ 3214*0Sstevel@tonic-gate static void 3215*0Sstevel@tonic-gate ibnex_delete_port_node_data(ibnex_node_data_t *node) 3216*0Sstevel@tonic-gate { 3217*0Sstevel@tonic-gate mutex_enter(&ibnex.ibnex_mutex); 3218*0Sstevel@tonic-gate if ((node->node_next == NULL) && (node->node_prev == NULL)) 3219*0Sstevel@tonic-gate ibnex.ibnex_port_node_head = NULL; 3220*0Sstevel@tonic-gate else if (node->node_next == NULL) 3221*0Sstevel@tonic-gate node->node_prev->node_next = NULL; 3222*0Sstevel@tonic-gate else if (node->node_prev == NULL) { 3223*0Sstevel@tonic-gate node->node_next->node_prev = NULL; 3224*0Sstevel@tonic-gate ibnex.ibnex_port_node_head = node->node_next; 3225*0Sstevel@tonic-gate } else { 3226*0Sstevel@tonic-gate node->node_prev->node_next = node->node_next; 3227*0Sstevel@tonic-gate node->node_next->node_prev = node->node_prev; 3228*0Sstevel@tonic-gate } 3229*0Sstevel@tonic-gate mutex_exit(&ibnex.ibnex_mutex); 3230*0Sstevel@tonic-gate kmem_free(node, sizeof (ibnex_node_data_t)); 3231*0Sstevel@tonic-gate } 3232*0Sstevel@tonic-gate 3233*0Sstevel@tonic-gate 3234*0Sstevel@tonic-gate /* 3235*0Sstevel@tonic-gate * ibnex_is_node_data_present() 3236*0Sstevel@tonic-gate * Checks whether ibnex_node_t is created already 3237*0Sstevel@tonic-gate * Returns ibnex_node_data_t if found, otherwise NULL 3238*0Sstevel@tonic-gate */ 3239*0Sstevel@tonic-gate static ibnex_node_data_t * 3240*0Sstevel@tonic-gate ibnex_is_node_data_present(ibnex_node_type_t node_type, void *attr, 3241*0Sstevel@tonic-gate int index, ib_pkey_t pkey) 3242*0Sstevel@tonic-gate { 3243*0Sstevel@tonic-gate ibnex_node_data_t *nodep; 3244*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&ibnex.ibnex_mutex)); 3245*0Sstevel@tonic-gate if (node_type == IBNEX_IOC_NODE) { 3246*0Sstevel@tonic-gate ibdm_ioc_info_t *ioc_infop = (ibdm_ioc_info_t *)attr; 3247*0Sstevel@tonic-gate 3248*0Sstevel@tonic-gate for (nodep = ibnex.ibnex_ioc_node_head; nodep != NULL; 3249*0Sstevel@tonic-gate nodep = nodep->node_next) { 3250*0Sstevel@tonic-gate if (nodep->node_data.ioc_node.ioc_guid == 3251*0Sstevel@tonic-gate ioc_infop->ioc_profile.ioc_guid) { 3252*0Sstevel@tonic-gate return (nodep); 3253*0Sstevel@tonic-gate } 3254*0Sstevel@tonic-gate } 3255*0Sstevel@tonic-gate 3256*0Sstevel@tonic-gate } else if (node_type == IBNEX_PSEUDO_NODE) { 3257*0Sstevel@tonic-gate for (nodep = ibnex.ibnex_pseudo_node_head; nodep; 3258*0Sstevel@tonic-gate nodep = nodep->node_next) 3259*0Sstevel@tonic-gate if (strcmp(nodep->node_data.pseudo_node. 3260*0Sstevel@tonic-gate pseudo_node_addr, (char *)attr) == 0) 3261*0Sstevel@tonic-gate return (nodep); 3262*0Sstevel@tonic-gate 3263*0Sstevel@tonic-gate } else { 3264*0Sstevel@tonic-gate ibdm_port_attr_t *pattrp = (ibdm_port_attr_t *)attr; 3265*0Sstevel@tonic-gate 3266*0Sstevel@tonic-gate for (nodep = ibnex.ibnex_port_node_head; nodep != NULL; 3267*0Sstevel@tonic-gate nodep = nodep->node_next) { 3268*0Sstevel@tonic-gate if ((nodep->node_data.port_node.port_guid == 3269*0Sstevel@tonic-gate pattrp->pa_port_guid) && 3270*0Sstevel@tonic-gate (nodep->node_data.port_node.port_commsvc_idx == 3271*0Sstevel@tonic-gate index) && 3272*0Sstevel@tonic-gate (nodep->node_data.port_node.port_pkey == pkey)) { 3273*0Sstevel@tonic-gate return (nodep); 3274*0Sstevel@tonic-gate } 3275*0Sstevel@tonic-gate } 3276*0Sstevel@tonic-gate } 3277*0Sstevel@tonic-gate return (NULL); 3278*0Sstevel@tonic-gate } 3279*0Sstevel@tonic-gate 3280*0Sstevel@tonic-gate /* 3281*0Sstevel@tonic-gate * ibnex_lookup_unit_address_prop: 3282*0Sstevel@tonic-gate * 3283*0Sstevel@tonic-gate * If "unit-address" property is found, return its value 3284*0Sstevel@tonic-gate * otherwise return NULL. 3285*0Sstevel@tonic-gate */ 3286*0Sstevel@tonic-gate static char * 3287*0Sstevel@tonic-gate ibnex_lookup_unit_address_prop(ddi_prop_t *head) 3288*0Sstevel@tonic-gate { 3289*0Sstevel@tonic-gate ddi_prop_t *propp; 3290*0Sstevel@tonic-gate 3291*0Sstevel@tonic-gate /* Search the list of properties for "unit-address" */ 3292*0Sstevel@tonic-gate for (propp = head; propp != NULL; propp = propp->prop_next) { 3293*0Sstevel@tonic-gate if (strcmp(propp->prop_name, "unit-address") != 0) 3294*0Sstevel@tonic-gate continue; 3295*0Sstevel@tonic-gate /* "unit-address" property should be valid and have a value */ 3296*0Sstevel@tonic-gate if (propp->prop_len <= 1) 3297*0Sstevel@tonic-gate break; 3298*0Sstevel@tonic-gate return ((char *)propp->prop_val); 3299*0Sstevel@tonic-gate } 3300*0Sstevel@tonic-gate 3301*0Sstevel@tonic-gate return ((char *)0); 3302*0Sstevel@tonic-gate } 3303*0Sstevel@tonic-gate 3304*0Sstevel@tonic-gate 3305*0Sstevel@tonic-gate /* 3306*0Sstevel@tonic-gate * ibnex_pseudo_initnodes() 3307*0Sstevel@tonic-gate * This routine is specific to pseudo node information handling 3308*0Sstevel@tonic-gate * Creates a ibnex_node_data_t all pseudo nodes children of ibnex 3309*0Sstevel@tonic-gate */ 3310*0Sstevel@tonic-gate void 3311*0Sstevel@tonic-gate ibnex_pseudo_initnodes() 3312*0Sstevel@tonic-gate { 3313*0Sstevel@tonic-gate int pnam_len, len; 3314*0Sstevel@tonic-gate ibnex_node_data_t *nodep; 3315*0Sstevel@tonic-gate struct hwc_spec *list, *spec; 3316*0Sstevel@tonic-gate char *node_addr, *temp, *unit_addr; 3317*0Sstevel@tonic-gate 3318*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tpseudo_initnodes"); 3319*0Sstevel@tonic-gate 3320*0Sstevel@tonic-gate mutex_enter(&ibnex.ibnex_mutex); 3321*0Sstevel@tonic-gate /* 3322*0Sstevel@tonic-gate * get a list of all "pseudo" children of "ib". 3323*0Sstevel@tonic-gate * for these children initialize/allocate an internal 3324*0Sstevel@tonic-gate * ibnex_node_data_t. 3325*0Sstevel@tonic-gate */ 3326*0Sstevel@tonic-gate list = hwc_get_child_spec(ibnex.ibnex_dip, (major_t)-1); 3327*0Sstevel@tonic-gate for (spec = list; spec != NULL; spec = spec->hwc_next) { 3328*0Sstevel@tonic-gate if (spec->hwc_devi_sys_prop_ptr == NULL) 3329*0Sstevel@tonic-gate continue; 3330*0Sstevel@tonic-gate 3331*0Sstevel@tonic-gate /* "unit-address" property should be present */ 3332*0Sstevel@tonic-gate temp = ibnex_lookup_unit_address_prop( 3333*0Sstevel@tonic-gate spec->hwc_devi_sys_prop_ptr); 3334*0Sstevel@tonic-gate if (temp == NULL) 3335*0Sstevel@tonic-gate continue; 3336*0Sstevel@tonic-gate 3337*0Sstevel@tonic-gate pnam_len = strlen(spec->hwc_devi_name) + strlen(temp) + 2; 3338*0Sstevel@tonic-gate 3339*0Sstevel@tonic-gate node_addr = kmem_zalloc(pnam_len, KM_SLEEP); 3340*0Sstevel@tonic-gate 3341*0Sstevel@tonic-gate (void) snprintf(node_addr, 3342*0Sstevel@tonic-gate pnam_len, "%s,%s", spec->hwc_devi_name, temp); 3343*0Sstevel@tonic-gate 3344*0Sstevel@tonic-gate nodep = ibnex_is_node_data_present( 3345*0Sstevel@tonic-gate IBNEX_PSEUDO_NODE, (void *)node_addr, 0, 0); 3346*0Sstevel@tonic-gate 3347*0Sstevel@tonic-gate if (nodep) { 3348*0Sstevel@tonic-gate kmem_free(node_addr, pnam_len); 3349*0Sstevel@tonic-gate continue; 3350*0Sstevel@tonic-gate } 3351*0Sstevel@tonic-gate 3352*0Sstevel@tonic-gate nodep = ibnex_init_child_nodedata(IBNEX_PSEUDO_NODE, 3353*0Sstevel@tonic-gate (void *)spec->hwc_devi_name, 0, 0); 3354*0Sstevel@tonic-gate 3355*0Sstevel@tonic-gate nodep->node_data.pseudo_node.pseudo_node_addr = node_addr; 3356*0Sstevel@tonic-gate (void) snprintf(nodep->node_data. 3357*0Sstevel@tonic-gate pseudo_node.pseudo_node_addr, pnam_len, "%s", node_addr); 3358*0Sstevel@tonic-gate 3359*0Sstevel@tonic-gate len = strlen(temp) + 1; 3360*0Sstevel@tonic-gate unit_addr = (char *)kmem_alloc(len, KM_SLEEP); 3361*0Sstevel@tonic-gate nodep->node_data.pseudo_node.pseudo_unit_addr = unit_addr; 3362*0Sstevel@tonic-gate (void) snprintf(unit_addr, len, "%s", temp); 3363*0Sstevel@tonic-gate nodep->node_data.pseudo_node.pseudo_unit_addr_len = len; 3364*0Sstevel@tonic-gate 3365*0Sstevel@tonic-gate /* Mark this as a new psuedo node */ 3366*0Sstevel@tonic-gate nodep->node_data.pseudo_node.pseudo_new_node = 1; 3367*0Sstevel@tonic-gate 3368*0Sstevel@tonic-gate IBTF_DPRINTF_L3("ibnex", "\tpseudo_initnodes: unit addr = %s" 3369*0Sstevel@tonic-gate " : drv name = %s", unit_addr, spec->hwc_devi_name); 3370*0Sstevel@tonic-gate } 3371*0Sstevel@tonic-gate hwc_free_spec_list(list); 3372*0Sstevel@tonic-gate mutex_exit(&ibnex.ibnex_mutex); 3373*0Sstevel@tonic-gate } 3374*0Sstevel@tonic-gate 3375*0Sstevel@tonic-gate 3376*0Sstevel@tonic-gate /* 3377*0Sstevel@tonic-gate * ibnex_init_child_nodedata() 3378*0Sstevel@tonic-gate * 3379*0Sstevel@tonic-gate * Allocate memory for the parent private data for device node 3380*0Sstevel@tonic-gate * Initializes the parent private child device node data. 3381*0Sstevel@tonic-gate * Returns pointer to the parent private data 3382*0Sstevel@tonic-gate */ 3383*0Sstevel@tonic-gate static ibnex_node_data_t * 3384*0Sstevel@tonic-gate ibnex_init_child_nodedata(ibnex_node_type_t node_type, void *attr, int index, 3385*0Sstevel@tonic-gate ib_pkey_t pkey) 3386*0Sstevel@tonic-gate { 3387*0Sstevel@tonic-gate char *devi_name; 3388*0Sstevel@tonic-gate ibdm_ioc_info_t *ioc_info; 3389*0Sstevel@tonic-gate ibnex_ioc_node_t *ioc_node; 3390*0Sstevel@tonic-gate ibnex_node_data_t *node_data; 3391*0Sstevel@tonic-gate ib_dm_ioc_ctrl_profile_t *ioc_profile; 3392*0Sstevel@tonic-gate 3393*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&ibnex.ibnex_mutex)); 3394*0Sstevel@tonic-gate 3395*0Sstevel@tonic-gate node_data = kmem_zalloc(sizeof (ibnex_node_data_t), KM_SLEEP); 3396*0Sstevel@tonic-gate node_data->node_state = IBNEX_CFGADM_CONFIGURING; 3397*0Sstevel@tonic-gate node_data->node_type = node_type; 3398*0Sstevel@tonic-gate 3399*0Sstevel@tonic-gate if (node_type == IBNEX_IOC_NODE) { 3400*0Sstevel@tonic-gate ioc_info = (ibdm_ioc_info_t *)attr; 3401*0Sstevel@tonic-gate ioc_profile = &ioc_info->ioc_profile; 3402*0Sstevel@tonic-gate ioc_node = &node_data->node_data.ioc_node; 3403*0Sstevel@tonic-gate 3404*0Sstevel@tonic-gate ioc_node->iou_guid = ioc_info->ioc_iou_guid; 3405*0Sstevel@tonic-gate ioc_node->ioc_guid = ioc_profile->ioc_guid; 3406*0Sstevel@tonic-gate (void) strncpy(ioc_node->ioc_id_string, 3407*0Sstevel@tonic-gate (char *)ioc_profile->ioc_id_string, 3408*0Sstevel@tonic-gate IB_DM_IOC_ID_STRING_LEN); 3409*0Sstevel@tonic-gate ioc_node->ioc_ngids = ioc_info->ioc_nportgids; 3410*0Sstevel@tonic-gate 3411*0Sstevel@tonic-gate node_data->node_next = ibnex.ibnex_ioc_node_head; 3412*0Sstevel@tonic-gate node_data->node_prev = NULL; 3413*0Sstevel@tonic-gate if (ibnex.ibnex_ioc_node_head) 3414*0Sstevel@tonic-gate ibnex.ibnex_ioc_node_head->node_prev = node_data; 3415*0Sstevel@tonic-gate ibnex.ibnex_ioc_node_head = node_data; 3416*0Sstevel@tonic-gate } else if (node_type == IBNEX_PSEUDO_NODE) { 3417*0Sstevel@tonic-gate devi_name = (char *)attr; 3418*0Sstevel@tonic-gate node_data->node_data.pseudo_node.pseudo_devi_name = 3419*0Sstevel@tonic-gate kmem_zalloc(strlen(devi_name) + 1, KM_SLEEP); 3420*0Sstevel@tonic-gate (void) strncpy(node_data->node_data.pseudo_node. 3421*0Sstevel@tonic-gate pseudo_devi_name, devi_name, strlen(devi_name)); 3422*0Sstevel@tonic-gate node_data->node_next = ibnex.ibnex_pseudo_node_head; 3423*0Sstevel@tonic-gate node_data->node_prev = NULL; 3424*0Sstevel@tonic-gate if (ibnex.ibnex_pseudo_node_head) 3425*0Sstevel@tonic-gate ibnex.ibnex_pseudo_node_head->node_prev = node_data; 3426*0Sstevel@tonic-gate ibnex.ibnex_pseudo_node_head = node_data; 3427*0Sstevel@tonic-gate } else { 3428*0Sstevel@tonic-gate node_data->node_data.port_node.port_hcaguid = 3429*0Sstevel@tonic-gate ((ibdm_port_attr_t *)attr)->pa_hca_guid; 3430*0Sstevel@tonic-gate node_data->node_data.port_node.port_guid = 3431*0Sstevel@tonic-gate ((ibdm_port_attr_t *)attr)->pa_port_guid; 3432*0Sstevel@tonic-gate node_data->node_data.port_node.port_num = 3433*0Sstevel@tonic-gate ((ibdm_port_attr_t *)attr)->pa_port_num; 3434*0Sstevel@tonic-gate node_data->node_data.port_node.port_commsvc_idx = index; 3435*0Sstevel@tonic-gate node_data->node_data.port_node.port_pkey = pkey; 3436*0Sstevel@tonic-gate 3437*0Sstevel@tonic-gate node_data->node_next = ibnex.ibnex_port_node_head; 3438*0Sstevel@tonic-gate node_data->node_prev = NULL; 3439*0Sstevel@tonic-gate if (ibnex.ibnex_port_node_head) 3440*0Sstevel@tonic-gate ibnex.ibnex_port_node_head->node_prev = node_data; 3441*0Sstevel@tonic-gate ibnex.ibnex_port_node_head = node_data; 3442*0Sstevel@tonic-gate } 3443*0Sstevel@tonic-gate return (node_data); 3444*0Sstevel@tonic-gate } 3445*0Sstevel@tonic-gate 3446*0Sstevel@tonic-gate static int 3447*0Sstevel@tonic-gate ibnex_get_eventcookie(dev_info_t *dip, dev_info_t *rdip, 3448*0Sstevel@tonic-gate char *eventname, ddi_eventcookie_t *cookie) 3449*0Sstevel@tonic-gate { 3450*0Sstevel@tonic-gate int rc; 3451*0Sstevel@tonic-gate 3452*0Sstevel@tonic-gate 3453*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "ibnex_get_eventcookie(%p, %p, %s, 0x%X)", 3454*0Sstevel@tonic-gate dip, rdip, eventname, cookie); 3455*0Sstevel@tonic-gate 3456*0Sstevel@tonic-gate rc = ndi_event_retrieve_cookie(ibnex.ibnex_ndi_event_hdl, 3457*0Sstevel@tonic-gate rdip, eventname, cookie, NDI_EVENT_NOPASS); 3458*0Sstevel@tonic-gate if (rc == NDI_SUCCESS) { 3459*0Sstevel@tonic-gate mutex_enter(&ibnex.ibnex_mutex); 3460*0Sstevel@tonic-gate ibnex.ibnex_prop_update_evt_cookie = *cookie; 3461*0Sstevel@tonic-gate mutex_exit(&ibnex.ibnex_mutex); 3462*0Sstevel@tonic-gate } 3463*0Sstevel@tonic-gate 3464*0Sstevel@tonic-gate return (rc); 3465*0Sstevel@tonic-gate } 3466*0Sstevel@tonic-gate 3467*0Sstevel@tonic-gate static int 3468*0Sstevel@tonic-gate ibnex_add_eventcall(dev_info_t *dip, dev_info_t *rdip, 3469*0Sstevel@tonic-gate ddi_eventcookie_t cookie, void (*callback)(dev_info_t *dip, 3470*0Sstevel@tonic-gate ddi_eventcookie_t cookie, void *arg, void *bus_impldata), 3471*0Sstevel@tonic-gate void *arg, ddi_callback_id_t *cb_id) 3472*0Sstevel@tonic-gate { 3473*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", 3474*0Sstevel@tonic-gate "ibnex_add_eventcall(%p, %p, 0x%X, %p, %p, %p)", 3475*0Sstevel@tonic-gate dip, rdip, cookie, callback, arg, cb_id); 3476*0Sstevel@tonic-gate 3477*0Sstevel@tonic-gate return (ndi_event_add_callback(ibnex.ibnex_ndi_event_hdl, 3478*0Sstevel@tonic-gate rdip, cookie, callback, arg, NDI_SLEEP, cb_id)); 3479*0Sstevel@tonic-gate } 3480*0Sstevel@tonic-gate 3481*0Sstevel@tonic-gate static int 3482*0Sstevel@tonic-gate ibnex_remove_eventcall(dev_info_t *dip, ddi_callback_id_t cb_id) 3483*0Sstevel@tonic-gate { 3484*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "ibnex_remove_eventcall(%p, 0x%X)", 3485*0Sstevel@tonic-gate dip, cb_id); 3486*0Sstevel@tonic-gate 3487*0Sstevel@tonic-gate return (ndi_event_remove_callback(ibnex.ibnex_ndi_event_hdl, 3488*0Sstevel@tonic-gate cb_id)); 3489*0Sstevel@tonic-gate } 3490*0Sstevel@tonic-gate 3491*0Sstevel@tonic-gate static int 3492*0Sstevel@tonic-gate ibnex_post_event(dev_info_t *dip, dev_info_t *rdip, 3493*0Sstevel@tonic-gate ddi_eventcookie_t cookie, void *bus_impldata) 3494*0Sstevel@tonic-gate { 3495*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "ibnex_post_event(%p, %p, 0x%X, %p)", 3496*0Sstevel@tonic-gate dip, rdip, cookie, bus_impldata); 3497*0Sstevel@tonic-gate 3498*0Sstevel@tonic-gate return (ndi_event_run_callbacks(ibnex.ibnex_ndi_event_hdl, rdip, 3499*0Sstevel@tonic-gate cookie, bus_impldata)); 3500*0Sstevel@tonic-gate } 3501*0Sstevel@tonic-gate 3502*0Sstevel@tonic-gate /* 3503*0Sstevel@tonic-gate * ibnex_reprobe_ioc_dev() 3504*0Sstevel@tonic-gate * 3505*0Sstevel@tonic-gate * This could be called as a result of ibt_reprobe_dev request or 3506*0Sstevel@tonic-gate * cfgadm command. The function is called from a taskq in case of 3507*0Sstevel@tonic-gate * ibt_reprobe_dev and from user context for cfgadm command. 3508*0Sstevel@tonic-gate * 3509*0Sstevel@tonic-gate * This function reprobes the properties for one IOC dip. 3510*0Sstevel@tonic-gate * 3511*0Sstevel@tonic-gate * node_reprobe_state should be set before calling this function. 3512*0Sstevel@tonic-gate */ 3513*0Sstevel@tonic-gate void 3514*0Sstevel@tonic-gate ibnex_reprobe_ioc_dev(void *arg) 3515*0Sstevel@tonic-gate { 3516*0Sstevel@tonic-gate dev_info_t *dip = (dev_info_t *)arg; 3517*0Sstevel@tonic-gate ibnex_node_data_t *node_data; 3518*0Sstevel@tonic-gate ibnex_ioc_node_t *ioc_data; 3519*0Sstevel@tonic-gate ibdm_ioc_info_t *ioc_info; 3520*0Sstevel@tonic-gate 3521*0Sstevel@tonic-gate /* ASSERT(NO_LOCKS_HELD); */ 3522*0Sstevel@tonic-gate ASSERT(dip != NULL); 3523*0Sstevel@tonic-gate 3524*0Sstevel@tonic-gate node_data = ddi_get_parent_data(dip); 3525*0Sstevel@tonic-gate ASSERT(node_data); 3526*0Sstevel@tonic-gate 3527*0Sstevel@tonic-gate if (node_data->node_dip == NULL) { 3528*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "reprobe for unconfigured dip"); 3529*0Sstevel@tonic-gate mutex_enter(&ibnex.ibnex_mutex); 3530*0Sstevel@tonic-gate ibnex_wakeup_reprobe_ioc(node_data, 0); 3531*0Sstevel@tonic-gate mutex_exit(&ibnex.ibnex_mutex); 3532*0Sstevel@tonic-gate return; 3533*0Sstevel@tonic-gate } 3534*0Sstevel@tonic-gate ioc_data = &(node_data->node_data.ioc_node); 3535*0Sstevel@tonic-gate 3536*0Sstevel@tonic-gate /* Reprobe the IOC */ 3537*0Sstevel@tonic-gate ioc_info = ibdm_ibnex_probe_ioc(ioc_data->iou_guid, ioc_data->ioc_guid, 3538*0Sstevel@tonic-gate 1); 3539*0Sstevel@tonic-gate if (ioc_info == NULL) { 3540*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", "Null ioc_info from reprobe"); 3541*0Sstevel@tonic-gate mutex_enter(&ibnex.ibnex_mutex); 3542*0Sstevel@tonic-gate ibnex_wakeup_reprobe_ioc(node_data, 1); 3543*0Sstevel@tonic-gate mutex_exit(&ibnex.ibnex_mutex); 3544*0Sstevel@tonic-gate return; 3545*0Sstevel@tonic-gate } 3546*0Sstevel@tonic-gate 3547*0Sstevel@tonic-gate mutex_enter(&ibnex.ibnex_mutex); 3548*0Sstevel@tonic-gate if (node_data->node_dip) 3549*0Sstevel@tonic-gate ibnex_update_prop(node_data, ioc_info); 3550*0Sstevel@tonic-gate ibnex_wakeup_reprobe_ioc(node_data, 0); 3551*0Sstevel@tonic-gate mutex_exit(&ibnex.ibnex_mutex); 3552*0Sstevel@tonic-gate 3553*0Sstevel@tonic-gate ibdm_ibnex_free_ioc_list(ioc_info); 3554*0Sstevel@tonic-gate } 3555*0Sstevel@tonic-gate 3556*0Sstevel@tonic-gate /* 3557*0Sstevel@tonic-gate * ibnex_reprobe_all() 3558*0Sstevel@tonic-gate * 3559*0Sstevel@tonic-gate * This could be called as a result of cfgadm command. The function 3560*0Sstevel@tonic-gate * is called from user context. 3561*0Sstevel@tonic-gate * 3562*0Sstevel@tonic-gate * This function reprobes the properties for all IOC dips. 3563*0Sstevel@tonic-gate * 3564*0Sstevel@tonic-gate * ibnex_reprobe_state should be set before calling this function. 3565*0Sstevel@tonic-gate */ 3566*0Sstevel@tonic-gate void 3567*0Sstevel@tonic-gate ibnex_reprobe_ioc_all() 3568*0Sstevel@tonic-gate { 3569*0Sstevel@tonic-gate ibnex_node_data_t *node_data; 3570*0Sstevel@tonic-gate ibdm_ioc_info_t *ioc_info_list, *ioc; 3571*0Sstevel@tonic-gate 3572*0Sstevel@tonic-gate /* ASSERT(NO_LOCKS_HELD); */ 3573*0Sstevel@tonic-gate 3574*0Sstevel@tonic-gate /* Sweep the fabric */ 3575*0Sstevel@tonic-gate ioc = ioc_info_list = ibdm_ibnex_get_ioc_list( 3576*0Sstevel@tonic-gate IBDM_IBNEX_REPROBE_ALL); 3577*0Sstevel@tonic-gate if (ioc_info_list == NULL) { 3578*0Sstevel@tonic-gate mutex_enter(&ibnex.ibnex_mutex); 3579*0Sstevel@tonic-gate ibnex_wakeup_reprobe_all(); 3580*0Sstevel@tonic-gate mutex_exit(&ibnex.ibnex_mutex); 3581*0Sstevel@tonic-gate return; 3582*0Sstevel@tonic-gate } 3583*0Sstevel@tonic-gate 3584*0Sstevel@tonic-gate mutex_enter(&ibnex.ibnex_mutex); 3585*0Sstevel@tonic-gate while (ioc_info_list) { 3586*0Sstevel@tonic-gate if ((node_data = ibnex_is_node_data_present(IBNEX_IOC_NODE, 3587*0Sstevel@tonic-gate ioc_info_list, 0, 0)) != NULL && 3588*0Sstevel@tonic-gate node_data->node_dip != NULL) { 3589*0Sstevel@tonic-gate ibnex_update_prop(node_data, ioc_info_list); 3590*0Sstevel@tonic-gate } 3591*0Sstevel@tonic-gate ioc_info_list = ioc_info_list->ioc_next; 3592*0Sstevel@tonic-gate } 3593*0Sstevel@tonic-gate ibnex_wakeup_reprobe_all(); 3594*0Sstevel@tonic-gate mutex_exit(&ibnex.ibnex_mutex); 3595*0Sstevel@tonic-gate 3596*0Sstevel@tonic-gate ibdm_ibnex_free_ioc_list(ioc); 3597*0Sstevel@tonic-gate } 3598*0Sstevel@tonic-gate 3599*0Sstevel@tonic-gate /* 3600*0Sstevel@tonic-gate * Update the properties, if it has modified and notify IBTF client. 3601*0Sstevel@tonic-gate */ 3602*0Sstevel@tonic-gate static void 3603*0Sstevel@tonic-gate ibnex_update_prop(ibnex_node_data_t *node_data, ibdm_ioc_info_t *ioc_info) 3604*0Sstevel@tonic-gate { 3605*0Sstevel@tonic-gate ibt_prop_update_payload_t evt_data; 3606*0Sstevel@tonic-gate dev_info_t *dip = node_data->node_dip; 3607*0Sstevel@tonic-gate ddi_eventcookie_t evt_cookie; 3608*0Sstevel@tonic-gate ibnex_ioc_node_t *ioc; 3609*0Sstevel@tonic-gate 3610*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&ibnex.ibnex_mutex)); 3611*0Sstevel@tonic-gate 3612*0Sstevel@tonic-gate ASSERT(dip != NULL); 3613*0Sstevel@tonic-gate 3614*0Sstevel@tonic-gate ioc = &node_data->node_data.ioc_node; 3615*0Sstevel@tonic-gate 3616*0Sstevel@tonic-gate evt_data = ioc_info->ioc_info_updated; 3617*0Sstevel@tonic-gate evt_cookie = ibnex.ibnex_prop_update_evt_cookie; 3618*0Sstevel@tonic-gate 3619*0Sstevel@tonic-gate /* 3620*0Sstevel@tonic-gate * For a disconnected IOC : 3621*0Sstevel@tonic-gate * Store the ioc_profile for supplying cfgadm info 3622*0Sstevel@tonic-gate * ibdm maintains no info of disconnected IOC 3623*0Sstevel@tonic-gate * 3624*0Sstevel@tonic-gate * For reconnected IOC : 3625*0Sstevel@tonic-gate * ibdm has info of previous service entries 3626*0Sstevel@tonic-gate * ioc_profile maintained by ibnexus is used to 3627*0Sstevel@tonic-gate * update ib_srv_prop_updated. 3628*0Sstevel@tonic-gate * Free the ibnex maintained ioc_profile 3629*0Sstevel@tonic-gate */ 3630*0Sstevel@tonic-gate if (ioc_info->ioc_nportgids == 0) { 3631*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", 3632*0Sstevel@tonic-gate "\tupdate_prop: IOC disconnected"); 3633*0Sstevel@tonic-gate ioc->ioc_profile = (ib_dm_ioc_ctrl_profile_t *)kmem_zalloc( 3634*0Sstevel@tonic-gate sizeof (ib_dm_ioc_ctrl_profile_t), KM_SLEEP); 3635*0Sstevel@tonic-gate bcopy(&ioc_info->ioc_profile, ioc->ioc_profile, 3636*0Sstevel@tonic-gate sizeof (ib_dm_ioc_ctrl_profile_t)); 3637*0Sstevel@tonic-gate 3638*0Sstevel@tonic-gate ibnex.ibnex_num_disconnect_iocs++; 3639*0Sstevel@tonic-gate } else if (ioc_info->ioc_nportgids != 0 && ioc->ioc_ngids == 0 && 3640*0Sstevel@tonic-gate ioc->ioc_profile != NULL) { 3641*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", 3642*0Sstevel@tonic-gate "\tupdate_prop: IOC reconnected"); 3643*0Sstevel@tonic-gate if (ioc->ioc_profile->ioc_service_entries != 3644*0Sstevel@tonic-gate ioc_info->ioc_profile.ioc_service_entries) 3645*0Sstevel@tonic-gate evt_data.ib_srv_prop_updated = 1; 3646*0Sstevel@tonic-gate 3647*0Sstevel@tonic-gate ibnex.ibnex_num_disconnect_iocs--; 3648*0Sstevel@tonic-gate kmem_free(ioc->ioc_profile, sizeof (ib_dm_ioc_ctrl_profile_t)); 3649*0Sstevel@tonic-gate ioc->ioc_profile = NULL; 3650*0Sstevel@tonic-gate } 3651*0Sstevel@tonic-gate 3652*0Sstevel@tonic-gate /* Update the properties that have changed */ 3653*0Sstevel@tonic-gate mutex_exit(&ibnex.ibnex_mutex); 3654*0Sstevel@tonic-gate if (evt_data.ib_gid_prop_updated) { 3655*0Sstevel@tonic-gate if (ibnex_create_ioc_portgid_prop(dip, ioc_info) != 3656*0Sstevel@tonic-gate IBNEX_SUCCESS) { 3657*0Sstevel@tonic-gate mutex_enter(&ibnex.ibnex_mutex); 3658*0Sstevel@tonic-gate return; 3659*0Sstevel@tonic-gate } 3660*0Sstevel@tonic-gate } 3661*0Sstevel@tonic-gate if (evt_data.ib_srv_prop_updated) { 3662*0Sstevel@tonic-gate if (ioc_info->ioc_profile.ioc_service_entries != 0 && 3663*0Sstevel@tonic-gate (ibnex_create_ioc_srv_props(dip, ioc_info) != 3664*0Sstevel@tonic-gate IBNEX_SUCCESS)) { 3665*0Sstevel@tonic-gate mutex_enter(&ibnex.ibnex_mutex); 3666*0Sstevel@tonic-gate return; 3667*0Sstevel@tonic-gate } else if (ioc_info->ioc_profile.ioc_service_entries == 0) { 3668*0Sstevel@tonic-gate (void) ndi_prop_remove(DDI_DEV_T_NONE, dip, 3669*0Sstevel@tonic-gate "service-id"); 3670*0Sstevel@tonic-gate (void) ndi_prop_remove(DDI_DEV_T_NONE, dip, 3671*0Sstevel@tonic-gate "service-name"); 3672*0Sstevel@tonic-gate } 3673*0Sstevel@tonic-gate } 3674*0Sstevel@tonic-gate mutex_enter(&ibnex.ibnex_mutex); 3675*0Sstevel@tonic-gate ioc->ioc_ngids = ioc_info->ioc_nportgids; 3676*0Sstevel@tonic-gate 3677*0Sstevel@tonic-gate /* 3678*0Sstevel@tonic-gate * Post an event if : 3679*0Sstevel@tonic-gate * 1. Properites have changed or NOTIFY_ALWAYS is set. 3680*0Sstevel@tonic-gate * 2. child dip is configured and a valid cookie for 3681*0Sstevel@tonic-gate * IB_PROP_UPDATE_EVENT. 3682*0Sstevel@tonic-gate */ 3683*0Sstevel@tonic-gate if ((evt_data.ib_prop_updated != 0 || 3684*0Sstevel@tonic-gate (node_data->node_reprobe_state & 3685*0Sstevel@tonic-gate IBNEX_NODE_REPROBE_NOTIFY_ALWAYS)) && 3686*0Sstevel@tonic-gate ((node_data->node_state == IBNEX_CFGADM_CONFIGURED) && 3687*0Sstevel@tonic-gate (evt_cookie != NULL))) { 3688*0Sstevel@tonic-gate mutex_exit(&ibnex.ibnex_mutex); 3689*0Sstevel@tonic-gate 3690*0Sstevel@tonic-gate if (ndi_post_event(ibnex.ibnex_dip, dip, 3691*0Sstevel@tonic-gate evt_cookie, &evt_data) != NDI_SUCCESS) 3692*0Sstevel@tonic-gate IBTF_DPRINTF_L2("ibnex", 3693*0Sstevel@tonic-gate "\tndi_post_event failed\n"); 3694*0Sstevel@tonic-gate 3695*0Sstevel@tonic-gate mutex_enter(&ibnex.ibnex_mutex); 3696*0Sstevel@tonic-gate } 3697*0Sstevel@tonic-gate 3698*0Sstevel@tonic-gate /* 3699*0Sstevel@tonic-gate * Cleanup node_reprobe_state, for ibt_reprobe_dev 3700*0Sstevel@tonic-gate * requests, when reprobe all / node reprobe is in 3701*0Sstevel@tonic-gate * progress. ibnex_reprobe_ioc_dev is not called 3702*0Sstevel@tonic-gate * in this case. 3703*0Sstevel@tonic-gate */ 3704*0Sstevel@tonic-gate if (node_data->node_reprobe_state == 3705*0Sstevel@tonic-gate IBNEX_NODE_REPROBE_NOTIFY_ALWAYS) 3706*0Sstevel@tonic-gate ibnex_wakeup_reprobe_ioc(node_data, 0); 3707*0Sstevel@tonic-gate } 3708*0Sstevel@tonic-gate 3709*0Sstevel@tonic-gate static ibnex_rval_t 3710*0Sstevel@tonic-gate ibnex_unique_svcname(char *svcname) 3711*0Sstevel@tonic-gate { 3712*0Sstevel@tonic-gate int i; 3713*0Sstevel@tonic-gate 3714*0Sstevel@tonic-gate /* Check Port Services */ 3715*0Sstevel@tonic-gate for (i = 0; i < ibnex.ibnex_num_comm_svcs; i++) 3716*0Sstevel@tonic-gate if (ibnex.ibnex_comm_svc_names[i] && strncmp(svcname, 3717*0Sstevel@tonic-gate ibnex.ibnex_comm_svc_names[i], 4) == 0) 3718*0Sstevel@tonic-gate return (IBNEX_FAILURE); 3719*0Sstevel@tonic-gate 3720*0Sstevel@tonic-gate /* Check VPPA Services */ 3721*0Sstevel@tonic-gate for (i = 0; i < ibnex.ibnex_nvppa_comm_svcs; i++) 3722*0Sstevel@tonic-gate if (ibnex.ibnex_vppa_comm_svc_names[i] && strncmp(svcname, 3723*0Sstevel@tonic-gate ibnex.ibnex_vppa_comm_svc_names[i], 4) == 0) 3724*0Sstevel@tonic-gate return (IBNEX_FAILURE); 3725*0Sstevel@tonic-gate 3726*0Sstevel@tonic-gate /* Check HCA_SVC Services */ 3727*0Sstevel@tonic-gate for (i = 0; i < ibnex.ibnex_nhcasvc_comm_svcs; i++) 3728*0Sstevel@tonic-gate if (ibnex.ibnex_hcasvc_comm_svc_names[i] && strncmp(svcname, 3729*0Sstevel@tonic-gate ibnex.ibnex_hcasvc_comm_svc_names[i], 4) == 0) 3730*0Sstevel@tonic-gate return (IBNEX_FAILURE); 3731*0Sstevel@tonic-gate 3732*0Sstevel@tonic-gate return (IBNEX_SUCCESS); 3733*0Sstevel@tonic-gate } 3734*0Sstevel@tonic-gate 3735*0Sstevel@tonic-gate static void 3736*0Sstevel@tonic-gate ibnex_handle_reprobe_dev(void *arg) 3737*0Sstevel@tonic-gate { 3738*0Sstevel@tonic-gate dev_info_t *dip = (dev_info_t *)arg; 3739*0Sstevel@tonic-gate ibnex_node_data_t *node_data; 3740*0Sstevel@tonic-gate 3741*0Sstevel@tonic-gate ASSERT(dip != NULL); 3742*0Sstevel@tonic-gate node_data = ddi_get_parent_data(dip); 3743*0Sstevel@tonic-gate ASSERT(node_data); 3744*0Sstevel@tonic-gate 3745*0Sstevel@tonic-gate /* 3746*0Sstevel@tonic-gate * Return success if: 3747*0Sstevel@tonic-gate * 1. Reprobe for all nodes are in progress 3748*0Sstevel@tonic-gate * 2. Reprobe for this node is in progress. 3749*0Sstevel@tonic-gate * The reprobe in progress will complete eventually and 3750*0Sstevel@tonic-gate * update the properties, if required. 3751*0Sstevel@tonic-gate */ 3752*0Sstevel@tonic-gate mutex_enter(&ibnex.ibnex_mutex); 3753*0Sstevel@tonic-gate if (ibnex.ibnex_reprobe_state != 0 || 3754*0Sstevel@tonic-gate node_data->node_reprobe_state != 0) { 3755*0Sstevel@tonic-gate /* 3756*0Sstevel@tonic-gate * Setting NOTIFY_ALWAYS to ensure that 3757*0Sstevel@tonic-gate * DDI event is delivered always for 3758*0Sstevel@tonic-gate * ibt_reprobe_dev 3759*0Sstevel@tonic-gate */ 3760*0Sstevel@tonic-gate node_data->node_reprobe_state |= 3761*0Sstevel@tonic-gate IBNEX_NODE_REPROBE_NOTIFY_ALWAYS; 3762*0Sstevel@tonic-gate mutex_exit(&ibnex.ibnex_mutex); 3763*0Sstevel@tonic-gate return; 3764*0Sstevel@tonic-gate } 3765*0Sstevel@tonic-gate node_data->node_reprobe_state = 3766*0Sstevel@tonic-gate IBNEX_NODE_REPROBE_NOTIFY_ALWAYS; 3767*0Sstevel@tonic-gate mutex_exit(&ibnex.ibnex_mutex); 3768*0Sstevel@tonic-gate ibnex_reprobe_ioc_dev(arg); 3769*0Sstevel@tonic-gate } 3770*0Sstevel@tonic-gate 3771*0Sstevel@tonic-gate 3772*0Sstevel@tonic-gate /* 3773*0Sstevel@tonic-gate * MPxIO pathmangement routines. Currently IB nexus does not support 3774*0Sstevel@tonic-gate * any kind of pathmangement. So, just return success to make MPxIO 3775*0Sstevel@tonic-gate * framework happy. 3776*0Sstevel@tonic-gate */ 3777*0Sstevel@tonic-gate /*ARGSUSED*/ 3778*0Sstevel@tonic-gate static int 3779*0Sstevel@tonic-gate ib_vhci_pi_init(dev_info_t *dip, mdi_pathinfo_t *pip, int flag) 3780*0Sstevel@tonic-gate { 3781*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tpi_init: dip %p pip %p", dip, pip); 3782*0Sstevel@tonic-gate return (MDI_SUCCESS); 3783*0Sstevel@tonic-gate } 3784*0Sstevel@tonic-gate 3785*0Sstevel@tonic-gate 3786*0Sstevel@tonic-gate /*ARGSUSED*/ 3787*0Sstevel@tonic-gate static int 3788*0Sstevel@tonic-gate ib_vhci_pi_uninit(dev_info_t *dip, mdi_pathinfo_t *pip, int flag) 3789*0Sstevel@tonic-gate { 3790*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tpi_uninit: dip %p pip %p", dip, pip); 3791*0Sstevel@tonic-gate return (MDI_SUCCESS); 3792*0Sstevel@tonic-gate } 3793*0Sstevel@tonic-gate 3794*0Sstevel@tonic-gate 3795*0Sstevel@tonic-gate /*ARGSUSED*/ 3796*0Sstevel@tonic-gate static int 3797*0Sstevel@tonic-gate ib_vhci_pi_state_change(dev_info_t *dip, mdi_pathinfo_t *pip, 3798*0Sstevel@tonic-gate mdi_pathinfo_state_t state, uint32_t arg1, int arg2) 3799*0Sstevel@tonic-gate { 3800*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", 3801*0Sstevel@tonic-gate "\tpi_state_change: dip %p pip %p state %x", dip, pip, state); 3802*0Sstevel@tonic-gate return (MDI_SUCCESS); 3803*0Sstevel@tonic-gate } 3804*0Sstevel@tonic-gate 3805*0Sstevel@tonic-gate 3806*0Sstevel@tonic-gate /*ARGSUSED*/ 3807*0Sstevel@tonic-gate static int 3808*0Sstevel@tonic-gate ib_vhci_failover(dev_info_t *dip1, dev_info_t *dip2, int arg) 3809*0Sstevel@tonic-gate { 3810*0Sstevel@tonic-gate return (MDI_SUCCESS); 3811*0Sstevel@tonic-gate } 3812*0Sstevel@tonic-gate 3813*0Sstevel@tonic-gate 3814*0Sstevel@tonic-gate static int 3815*0Sstevel@tonic-gate ibnex_bus_power(dev_info_t *parent, void *impl_arg, 3816*0Sstevel@tonic-gate pm_bus_power_op_t op, void *arg, void *result) 3817*0Sstevel@tonic-gate { 3818*0Sstevel@tonic-gate 3819*0Sstevel@tonic-gate int ret = DDI_SUCCESS; 3820*0Sstevel@tonic-gate 3821*0Sstevel@tonic-gate IBTF_DPRINTF_L4("ibnex", "\tbus_power: begin: op = %d", op); 3822*0Sstevel@tonic-gate 3823*0Sstevel@tonic-gate /* 3824*0Sstevel@tonic-gate * Generic processing in MPxIO framework 3825*0Sstevel@tonic-gate */ 3826*0Sstevel@tonic-gate ret = mdi_bus_power(parent, impl_arg, op, arg, result); 3827*0Sstevel@tonic-gate 3828*0Sstevel@tonic-gate switch (ret) { 3829*0Sstevel@tonic-gate case MDI_SUCCESS: 3830*0Sstevel@tonic-gate ret = DDI_SUCCESS; 3831*0Sstevel@tonic-gate break; 3832*0Sstevel@tonic-gate case MDI_FAILURE: 3833*0Sstevel@tonic-gate ret = DDI_FAILURE; 3834*0Sstevel@tonic-gate break; 3835*0Sstevel@tonic-gate default: 3836*0Sstevel@tonic-gate break; 3837*0Sstevel@tonic-gate } 3838*0Sstevel@tonic-gate 3839*0Sstevel@tonic-gate return (ret); 3840*0Sstevel@tonic-gate } 3841