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