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