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 2007 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 } else { 1188 /* 1189 * if not IOC or PORT device then always 1190 * assume a Pseudo child 1191 * 1192 * if IB Nexus is the parent, call MDI. 1193 * else if HCA is the parent, enumerate 1194 * the Pseudo node. 1195 */ 1196 ret = IBNEX_SUCCESS; 1197 ibnex_pseudo_initnodes(); 1198 if (parent == ibnex.ibnex_dip) { 1199 if (use_mdi_devi_locking) 1200 mdi_devi_exit(parent, circ); 1201 else 1202 ndi_devi_exit(parent, circ); 1203 1204 mutex_enter(&ibnex.ibnex_mutex); 1205 ret = ibnex_pseudo_mdi_config_one( 1206 flag, devname, child, cname, 1207 caddr); 1208 mutex_exit(&ibnex.ibnex_mutex); 1209 kmem_free(device_name, len); 1210 return (ret); 1211 } 1212 mutex_enter(&ibnex.ibnex_mutex); 1213 ret = ibnex_pseudo_config_one(NULL, 1214 caddr, parent); 1215 mutex_exit(&ibnex.ibnex_mutex); 1216 } 1217 } 1218 1219 if (strncmp(cname, IBNEX_IBPORT_CNAME, 6) == 0) { 1220 /* Allows enumeration under PHCI */ 1221 flag |= NDI_MDI_FALLBACK; 1222 } 1223 kmem_free(device_name, len); 1224 break; 1225 1226 case BUS_CONFIG_OBP_ARGS: 1227 cdip = ibnex_config_obp_args(parent, devname); 1228 if (cdip) { 1229 /* 1230 * Boot case. 1231 * Special handling because the "devname" 1232 * format for the enumerated device is 1233 * different. 1234 */ 1235 node_data = ddi_get_parent_data(cdip); 1236 port_node = &node_data->node_data.port_node; 1237 if (node_data->node_type == 1238 IBNEX_VPPA_COMMSVC_NODE) { 1239 srvname = 1240 ibnex.ibnex_vppa_comm_svc_names[ 1241 port_node->port_commsvc_idx]; 1242 (void) snprintf(nameaddr, MAXNAMELEN, 1243 "ibport@%x,%x,%s", 1244 port_node->port_num, 1245 port_node->port_pkey, srvname); 1246 } 1247 devname = (void *)nameaddr; 1248 } else { 1249 IBTF_DPRINTF_L2("ibnex", 1250 "\tbus_config: CONFIG_OBP_ARGS : invalid state!!"); 1251 1252 ret = IBNEX_FAILURE; 1253 } 1254 break; 1255 case BUS_CONFIG_ALL: 1256 /*FALLTHRU*/ 1257 case BUS_CONFIG_DRIVER: 1258 if (op == BUS_CONFIG_ALL) 1259 IBTF_DPRINTF_L4("ibnex", "\tbus_config: CONFIG_ALL, " 1260 "parent %p", parent); 1261 else 1262 IBTF_DPRINTF_L4("ibnex", "\tbus_config: CONFIG_DRIVER" 1263 ", parent %p", parent); 1264 1265 /* 1266 * No locks to be held while calling mdi_vhci_bus_config() 1267 * ibnex_config_all_children() holds appropriate locks. 1268 */ 1269 if (use_mdi_devi_locking) 1270 mdi_devi_exit(parent, circ); 1271 else 1272 ndi_devi_exit(parent, circ); 1273 1274 /* 1275 * Drive CONFIG requests for IB Nexus parent through 1276 * MDI. This is needed to load the HCA drivers in x86 SRP 1277 * boot case. 1278 * 1279 * CONFIG Requests with HCA parent will probe devices using 1280 * ibdm and configure all children. 1281 */ 1282 if (parent == ibnex.ibnex_dip) { 1283 ret = mdi_vhci_bus_config(parent, 1284 flag, op, devname, child, NULL); 1285 return (ret); 1286 } else { 1287 ibnex_config_all_children(parent); 1288 1289 if (use_mdi_devi_locking) 1290 mdi_devi_enter(parent, &circ); 1291 else 1292 ndi_devi_enter(parent, &circ); 1293 } 1294 break; 1295 default: 1296 IBTF_DPRINTF_L4("ibnex", "\tbus_config: error"); 1297 ret = IBNEX_FAILURE; 1298 break; 1299 } 1300 1301 if (use_mdi_devi_locking) 1302 mdi_devi_exit(parent, circ); 1303 else 1304 ndi_devi_exit(parent, circ); 1305 1306 if (ret == IBNEX_SUCCESS) { 1307 if (op == BUS_CONFIG_OBP_ARGS) 1308 op = BUS_CONFIG_ONE; 1309 1310 if (pdip == NULL) 1311 pdip = parent; 1312 1313 ret = ndi_busop_bus_config( 1314 pdip, flag, op, devname, child, 0); 1315 IBTF_DPRINTF_L4("ibnex", "\tbus_config:" 1316 "ndi_busop_bus_config : retval %d", ret); 1317 return (ret); 1318 } 1319 1320 IBTF_DPRINTF_L2("ibnex", "\tbus_config: Failure End"); 1321 return (NDI_FAILURE); 1322 } 1323 1324 1325 /* 1326 * ibnex_config_root_iocnode() 1327 * Configures one particular instance of the IOC driver. 1328 * Returns IBNEX_SUCCESS/IBNEX_FAILURE 1329 */ 1330 static int 1331 ibnex_config_root_iocnode(dev_info_t *parent, char *device_name) 1332 { 1333 int ret, port = 0, iter = 0; 1334 boolean_t displayed = B_FALSE; 1335 char *portstr; 1336 ib_guid_t hca_guid, iou_guid, ioc_guid; 1337 ibdm_ioc_info_t *ioc_info; 1338 ibdm_port_attr_t *port_attr; 1339 1340 IBTF_DPRINTF_L4("ibnex", 1341 "\tconfig_root_iocnode: name %s", device_name); 1342 1343 portstr = strstr(device_name, ":port="); 1344 if (portstr == NULL) { 1345 return (IBNEX_FAILURE); 1346 } 1347 1348 portstr[0] = 0; portstr++; 1349 if (ibnex_devname2port(portstr, &port)) { 1350 IBTF_DPRINTF_L4("ibnex", "\tconfig_root_iocnode: invalid port"); 1351 return (IBNEX_FAILURE); 1352 } 1353 1354 if (ibnex_devname_to_node_n_ioc_guids( 1355 device_name, &iou_guid, &ioc_guid, NULL) != IBNEX_SUCCESS) { 1356 return (IBNEX_FAILURE); 1357 } 1358 1359 (void) snprintf(device_name, (IBNEX_MAX_NODEADDR_SZ + 4), 1360 "ioc@%llX,%llX", (longlong_t)ioc_guid, (longlong_t)iou_guid); 1361 1362 hca_guid = ibtl_ibnex_hcadip2guid(parent); 1363 if ((port_attr = ibdm_ibnex_probe_hcaport(hca_guid, port)) == NULL) { 1364 IBTF_DPRINTF_L2("ibnex", 1365 "\tconfig_root_iocnode: Port does not exist"); 1366 return (IBNEX_FAILURE); 1367 } 1368 1369 /* Wait until "port is up" */ 1370 while (port_attr->pa_state != IBT_PORT_ACTIVE) { 1371 ibdm_ibnex_free_port_attr(port_attr); 1372 delay(drv_usectohz(10000)); 1373 if ((port_attr = ibdm_ibnex_probe_hcaport( 1374 hca_guid, port)) == NULL) { 1375 return (IBNEX_FAILURE); 1376 } 1377 1378 if (iter++ == 400) { 1379 if (displayed == B_FALSE) { 1380 cmn_err(CE_NOTE, "\tWaiting for Port %d " 1381 "initialization", port_attr->pa_port_num); 1382 displayed = B_TRUE; 1383 } 1384 } 1385 } 1386 ibdm_ibnex_free_port_attr(port_attr); 1387 IBTF_DPRINTF_L4("ibnex", "\tconfig_rootioc_node:" 1388 "Port is initialized"); 1389 1390 if ((ioc_info = ibdm_ibnex_probe_ioc(iou_guid, ioc_guid, 0)) == NULL) { 1391 ibdm_ibnex_free_ioc_list(ioc_info); 1392 return (IBNEX_FAILURE); 1393 } 1394 mutex_enter(&ibnex.ibnex_mutex); 1395 if (ibnex_is_ioc_present(ioc_guid) == IBNEX_SUCCESS) { 1396 IBTF_DPRINTF_L4("ibnex", "\tconfig_root_iocnode: IOC present"); 1397 ret = IBNEX_SUCCESS; 1398 } else 1399 ret = ibnex_ioc_initnode(ioc_info, IBNEX_DEVFS_ENUMERATE, 1400 parent); 1401 mutex_exit(&ibnex.ibnex_mutex); 1402 ibdm_ibnex_free_ioc_list(ioc_info); 1403 return (ret); 1404 } 1405 1406 1407 static int 1408 ibnex_devname2port(char *portstr, int *port) 1409 { 1410 char *temp; 1411 int ret = IBNEX_FAILURE; 1412 1413 IBTF_DPRINTF_L4("ibnex", "\tdevname2port: Begin"); 1414 1415 temp = strchr(portstr, '='); 1416 if (temp != NULL) { 1417 temp++; 1418 *port = ibnex_str2int(temp, strlen(temp), &ret); 1419 } 1420 return (ret); 1421 } 1422 1423 1424 /* 1425 * ibnex_config_all_children() 1426 * Wait for lata SM initialization case before enumerating the nodes 1427 * Get list of HCA's and HCA port information 1428 * Create device device nodes and its node properties 1429 * for port nodes and VPPA nodes 1430 * Get list of all the IOC node information 1431 * Create device nodes and its properties for all the IOCs 1432 * if not created already 1433 * Bind drivers for all the newly created device nodes 1434 * Support Pseudo nodes enumerated using their .conf file 1435 */ 1436 static void 1437 ibnex_config_all_children(dev_info_t *parent) 1438 { 1439 int ii; 1440 time_t wait_time; 1441 ibdm_ioc_info_t *ioc_list, *ioc; 1442 ibdm_hca_list_t *hca_list; 1443 ib_guid_t hca_guid; 1444 int circ; 1445 1446 IBTF_DPRINTF_L4("ibnex", "\tconfig_all_children: Begin"); 1447 1448 /* 1449 * Enumerate children of this HCA, port nodes, 1450 * VPPA & HCA_SVC nodes. Use ndi_devi_enter() for 1451 * locking. IB Nexus is enumerating the children 1452 * of HCA, not MPXIO clients. 1453 */ 1454 ndi_devi_enter(parent, &circ); 1455 hca_guid = ibtl_ibnex_hcadip2guid(parent); 1456 wait_time = ibdm_ibnex_get_waittime( 1457 hca_guid, &ibnex_port_settling_time); 1458 if (wait_time) { 1459 delay(drv_usectohz(wait_time * 1000000)); 1460 } 1461 hca_list = ibdm_ibnex_get_hca_info_by_guid(hca_guid); 1462 if (hca_list == NULL) 1463 return; 1464 ibnex_create_hcasvc_nodes(parent, hca_list->hl_hca_port_attr); 1465 for (ii = 0; ii < hca_list->hl_nports; ii++) { 1466 ibnex_create_port_nodes( 1467 parent, &hca_list->hl_port_attr[ii]); 1468 ibnex_create_vppa_nodes( 1469 parent, &hca_list->hl_port_attr[ii]); 1470 } 1471 ibdm_ibnex_free_hca_list(hca_list); 1472 ndi_devi_exit(parent, circ); 1473 1474 /* 1475 * Use mdi_devi_enter() for locking. IB Nexus is 1476 * enumerating MPXIO clients. 1477 */ 1478 mdi_devi_enter(parent, &circ); 1479 1480 ibnex_pseudo_initnodes(); 1481 1482 /* Enumerate all the IOC's */ 1483 wait_time = ibdm_ibnex_get_waittime( 1484 0, &ibnex_port_settling_time); 1485 if (wait_time) 1486 delay(drv_usectohz(wait_time * 1000000)); 1487 1488 ioc_list = ibdm_ibnex_get_ioc_list(IBDM_IBNEX_NORMAL_PROBE); 1489 ioc = ioc_list; 1490 1491 mutex_enter(&ibnex.ibnex_mutex); 1492 1493 while (ioc_list) { 1494 if (ibnex_is_ioc_present( 1495 ioc_list->ioc_profile.ioc_guid) != IBNEX_SUCCESS) { 1496 (void) ibnex_ioc_initnode(ioc_list, 1497 IBNEX_DEVFS_ENUMERATE, parent); 1498 } 1499 ioc_list = ioc_list->ioc_next; 1500 } 1501 1502 /* Config IBTF Pseudo clients */ 1503 ibnex_config_pseudo_all(parent); 1504 1505 mutex_exit(&ibnex.ibnex_mutex); 1506 ibdm_ibnex_free_ioc_list(ioc); 1507 mdi_devi_exit(parent, circ); 1508 1509 IBTF_DPRINTF_L4("ibnex", "\tconfig_all_children: End"); 1510 } 1511 1512 1513 /* 1514 * ibnex_create_port_nodes: 1515 * Creates a device node per each communication service defined 1516 * in the "port-commsvc-list" property per HCA port 1517 */ 1518 static void 1519 ibnex_create_port_nodes(dev_info_t *parent, ibdm_port_attr_t *port_attr) 1520 { 1521 int idx; 1522 dev_info_t *dip; 1523 int rval; 1524 1525 mutex_enter(&ibnex.ibnex_mutex); 1526 for (idx = 0; idx < ibnex.ibnex_num_comm_svcs; idx++) { 1527 rval = ibnex_get_dip_from_guid(port_attr->pa_port_guid, 1528 idx, 0, &dip); 1529 if (rval != IBNEX_SUCCESS) { 1530 (void) ibnex_commsvc_initnode(parent, port_attr, idx, 1531 IBNEX_PORT_COMMSVC_NODE, 0, &rval, 1532 IBNEX_DEVFS_ENUMERATE); 1533 } 1534 } 1535 mutex_exit(&ibnex.ibnex_mutex); 1536 } 1537 1538 1539 /* 1540 * ibnex_create_vppa_nodes: 1541 * Creates a device node per each communication service defined 1542 * in the "vppa-commsvc-list" property and per each PKEY that 1543 * this particular port supports and per HCA port 1544 */ 1545 static void 1546 ibnex_create_vppa_nodes(dev_info_t *parent, ibdm_port_attr_t *port_attr) 1547 { 1548 int idx, ii; 1549 int rval; 1550 ib_pkey_t pkey; 1551 dev_info_t *dip; 1552 1553 IBTF_DPRINTF_L4("ibnex", "\tcreate_vppa_nodes: Begin"); 1554 1555 mutex_enter(&ibnex.ibnex_mutex); 1556 if (port_attr->pa_state != IBT_PORT_ACTIVE) { 1557 IBTF_DPRINTF_L4("ibnex", "\tcreate_vppa_nodes: " 1558 "Port %d is down", port_attr->pa_port_num); 1559 mutex_exit(&ibnex.ibnex_mutex); 1560 return; 1561 } 1562 for (idx = 0; idx < ibnex.ibnex_nvppa_comm_svcs; idx++) { 1563 for (ii = 0; ii < port_attr->pa_npkeys; ii++) { 1564 pkey = port_attr->pa_pkey_tbl[ii].pt_pkey; 1565 1566 if (IBNEX_INVALID_PKEY(pkey)) { 1567 continue; 1568 } 1569 rval = ibnex_get_dip_from_guid( 1570 port_attr->pa_port_guid, idx, pkey, &dip); 1571 if (rval != IBNEX_SUCCESS) { 1572 (void) ibnex_commsvc_initnode(parent, port_attr, 1573 idx, IBNEX_VPPA_COMMSVC_NODE, 1574 pkey, &rval, IBNEX_CFGADM_ENUMERATE); 1575 IBTF_DPRINTF_L5("ibnex", "\tcreate_vppa_nodes: " 1576 "commsvc_initnode failed rval %x", rval); 1577 } 1578 } 1579 } 1580 mutex_exit(&ibnex.ibnex_mutex); 1581 } 1582 1583 1584 /* 1585 * ibnex_create_hcasvc_nodes: 1586 * Creates a device node per each communication service defined 1587 * in the "port-commsvc-list" property per HCA port 1588 */ 1589 static void 1590 ibnex_create_hcasvc_nodes(dev_info_t *parent, ibdm_port_attr_t *port_attr) 1591 { 1592 int idx; 1593 dev_info_t *dip; 1594 int rval; 1595 1596 mutex_enter(&ibnex.ibnex_mutex); 1597 for (idx = 0; idx < ibnex.ibnex_nhcasvc_comm_svcs; idx++) { 1598 rval = ibnex_get_dip_from_guid(port_attr->pa_port_guid, 1599 idx, 0, &dip); 1600 if (rval != IBNEX_SUCCESS) { 1601 (void) ibnex_commsvc_initnode(parent, port_attr, idx, 1602 IBNEX_HCASVC_COMMSVC_NODE, 0, &rval, 1603 IBNEX_DEVFS_ENUMERATE); 1604 IBTF_DPRINTF_L5("ibnex", "create_hcasvc_nodes: " 1605 "commsvc_initnode failed, rval %x", rval); 1606 } 1607 } 1608 mutex_exit(&ibnex.ibnex_mutex); 1609 } 1610 1611 /* 1612 * ibnex_is_ioc_present() 1613 * Returns IBNEX_SUCCESS if an entry found in the global linked list 1614 * Returns IBNEX_FAILURE, if no match found 1615 */ 1616 static int 1617 ibnex_is_ioc_present(ib_guid_t ioc_guid) 1618 { 1619 ibnex_node_data_t *head; 1620 ibnex_ioc_node_t *ioc; 1621 int ret = IBNEX_FAILURE; 1622 1623 IBTF_DPRINTF_L4("ibnex", "\tis_ioc_present: Begin"); 1624 ASSERT(MUTEX_HELD(&ibnex.ibnex_mutex)); 1625 1626 head = ibnex.ibnex_ioc_node_head; 1627 while (head) { 1628 ioc = &head->node_data.ioc_node; 1629 if (ioc->ioc_guid == ioc_guid) 1630 break; 1631 head = head->node_next; 1632 } 1633 if (head) 1634 ret = IBNEX_SUCCESS; 1635 1636 return (ret); 1637 } 1638 1639 1640 /* 1641 * ibnex_bus_unconfig() 1642 * 1643 * Unconfigure a particular device node or all instance of a device 1644 * driver device or all children of IBnex 1645 */ 1646 static int 1647 ibnex_bus_unconfig(dev_info_t *parent, 1648 uint_t flag, ddi_bus_config_op_t op, void *device_name) 1649 { 1650 return (ndi_busop_bus_unconfig(parent, flag, op, device_name)); 1651 } 1652 1653 1654 /* 1655 * ibnex_config_port_node() 1656 * 1657 * Configures a particular port / HCA node for a particular 1658 * communication service. 1659 * The format of the device_name is 1660 * ibport@<Port#>,<pkey>,<service name> 1661 * where pkey = 0 for port communication service nodes 1662 * Port# = 0 for HCA_SVC communication service nodes 1663 * Returns "dev_info_t" of the "child" node just created 1664 * NULL when failed to enumerate the child node 1665 */ 1666 static dev_info_t * 1667 ibnex_config_port_node(dev_info_t *parent, char *devname) 1668 { 1669 int ii, index; 1670 int rval; 1671 time_t wait_time; 1672 uint8_t port_num; 1673 ib_guid_t hca_guid, port_guid; 1674 ib_pkey_t pkey; 1675 dev_info_t *cdip; 1676 ibdm_port_attr_t *port_attr; 1677 ibdm_hca_list_t *hca_list; 1678 1679 IBTF_DPRINTF_L4("ibnex", "\tconfig_port_node: %s", devname); 1680 1681 if (ibnex_get_pkey_commsvc_index_portnum(devname, 1682 &index, &pkey, &port_num) != IBNEX_SUCCESS) { 1683 IBTF_DPRINTF_L2("ibnex", 1684 "\tconfig_port_node: Invalid Service Name"); 1685 return (NULL); 1686 } 1687 1688 hca_guid = ibtl_ibnex_hcadip2guid(parent); 1689 if (port_num == 0) { 1690 /* 1691 * Use the dummy port attribute for HCA node in hca_list 1692 * Note : pa_state is always IBT_PORT_ACTIVE. 1693 */ 1694 hca_list = ibdm_ibnex_get_hca_info_by_guid(hca_guid); 1695 ASSERT(hca_list != NULL); 1696 port_attr = hca_list->hl_hca_port_attr; 1697 } else { 1698 if ((port_attr = ibdm_ibnex_probe_hcaport( 1699 hca_guid, port_num)) == NULL) { 1700 IBTF_DPRINTF_L2("ibnex", 1701 "\tconfig_port_node: Port does not exist"); 1702 return (NULL); 1703 } 1704 1705 if (port_attr->pa_state != IBT_PORT_ACTIVE) { 1706 wait_time = ibdm_ibnex_get_waittime( 1707 hca_guid, &ibnex_port_settling_time); 1708 if (wait_time) { 1709 delay(drv_usectohz(wait_time * 1000000)); 1710 } 1711 ibdm_ibnex_free_port_attr(port_attr); 1712 if ((port_attr = ibdm_ibnex_probe_hcaport( 1713 hca_guid, port_num)) == NULL) { 1714 return (NULL); 1715 } 1716 } 1717 } 1718 1719 port_guid = port_attr->pa_port_guid; 1720 mutex_enter(&ibnex.ibnex_mutex); 1721 if ((rval = ibnex_get_dip_from_guid(port_guid, index, pkey, 1722 &cdip)) == IBNEX_SUCCESS) { 1723 IBTF_DPRINTF_L4("ibnex", "\tconfig_port_node: Node exists"); 1724 mutex_exit(&ibnex.ibnex_mutex); 1725 if (port_num != 0) 1726 ibdm_ibnex_free_port_attr(port_attr); 1727 else 1728 ibdm_ibnex_free_hca_list(hca_list); 1729 return (cdip); 1730 } 1731 1732 if (pkey == 0 && port_num != 0) { 1733 cdip = ibnex_commsvc_initnode(parent, 1734 port_attr, index, IBNEX_PORT_COMMSVC_NODE, pkey, &rval, 1735 IBNEX_DEVFS_ENUMERATE); 1736 IBTF_DPRINTF_L5("ibnex", 1737 "\t ibnex_commsvc_initnode rval %x", rval); 1738 } else if (pkey == 0 && port_num == 0) { 1739 cdip = ibnex_commsvc_initnode(parent, 1740 port_attr, index, IBNEX_HCASVC_COMMSVC_NODE, pkey, &rval, 1741 IBNEX_DEVFS_ENUMERATE); 1742 IBTF_DPRINTF_L5("ibnex", 1743 "\t ibnex_commsvc_initnode rval %x", rval); 1744 } else { 1745 if (port_attr->pa_state != IBT_PORT_ACTIVE) { 1746 IBTF_DPRINTF_L4("ibnex", "\tconfig_port_nodes: " 1747 "Port %d is down", port_attr->pa_port_num); 1748 ibdm_ibnex_free_port_attr(port_attr); 1749 mutex_exit(&ibnex.ibnex_mutex); 1750 return (NULL); 1751 } 1752 for (ii = 0; ii < port_attr->pa_npkeys; ii++) { 1753 if (pkey == port_attr->pa_pkey_tbl[ii].pt_pkey) { 1754 cdip = ibnex_commsvc_initnode(parent, port_attr, 1755 index, IBNEX_VPPA_COMMSVC_NODE, 1756 pkey, &rval, IBNEX_CFGADM_ENUMERATE); 1757 IBTF_DPRINTF_L5("ibnex", 1758 "\t ibnex_commsvc_initnode rval %x", rval); 1759 break; 1760 } 1761 } 1762 } 1763 mutex_exit(&ibnex.ibnex_mutex); 1764 if (port_num != 0) 1765 ibdm_ibnex_free_port_attr(port_attr); 1766 else 1767 ibdm_ibnex_free_hca_list(hca_list); 1768 return (cdip); 1769 } 1770 1771 1772 /* 1773 * ibnex_config_obp_args() 1774 * Configures a particular port node for a IP over IB communication 1775 * service. 1776 * The format of the input string "devname" is 1777 * port=x,pkey=y,protocol=ip,<wanboot options> 1778 * Thr format of the node name created here is 1779 * ibport@<Port#>,<pkey>,<service name> 1780 * where pkey = 0 for port communication service nodes 1781 * Returns "dev_info_t" of the "child" node just created 1782 * NULL when failed to enumerate the child node 1783 * 1784 */ 1785 static dev_info_t * 1786 ibnex_config_obp_args(dev_info_t *parent, char *devname) 1787 { 1788 int ii, index; 1789 int rval, iter = 0; 1790 char *temp; 1791 uint8_t port_num; 1792 ib_guid_t hca_guid, port_guid; 1793 ib_pkey_t pkey; 1794 dev_info_t *cdip; 1795 boolean_t displayed = B_FALSE; 1796 ibdm_port_attr_t *port_attr; 1797 1798 IBTF_DPRINTF_L4("ibnex", "\tconfig_obp_args: %s", devname); 1799 1800 /* Is this OBP node for IPoIB ? */ 1801 temp = devname; 1802 do { 1803 temp = strstr(temp, ",protocol=ip"); 1804 if (temp == NULL) 1805 break; 1806 1807 if (strlen(devname) > (int)((temp - devname) + 12)) { 1808 if (temp[12] == ',') 1809 break; 1810 } else { 1811 break; 1812 } 1813 temp++; 1814 } while (temp); 1815 1816 if (temp == NULL) 1817 return (NULL); 1818 if (ibnex_prom_devname_to_pkey_n_portnum( 1819 devname, &pkey, &port_num) != IBNEX_SUCCESS) { 1820 return (NULL); 1821 } 1822 for (index = 0; index < ibnex.ibnex_nvppa_comm_svcs; index++) { 1823 if (strcmp(ibnex.ibnex_vppa_comm_svc_names[index], 1824 "ipib") == 0) { 1825 break; 1826 } 1827 } 1828 1829 hca_guid = ibtl_ibnex_hcadip2guid(parent); 1830 if ((port_attr = ibdm_ibnex_probe_hcaport( 1831 hca_guid, port_num)) == NULL) { 1832 IBTF_DPRINTF_L2("ibnex", 1833 "\tconfig_port_node: Port does not exist"); 1834 return (NULL); 1835 } 1836 1837 /* Wait until "port is up" */ 1838 while (port_attr->pa_state != IBT_PORT_ACTIVE) { 1839 ibdm_ibnex_free_port_attr(port_attr); 1840 delay(drv_usectohz(10000)); 1841 if ((port_attr = ibdm_ibnex_probe_hcaport( 1842 hca_guid, port_num)) == NULL) { 1843 return (NULL); 1844 } 1845 if (iter++ == 400) { 1846 if (displayed == B_FALSE) { 1847 cmn_err(CE_NOTE, "\tWaiting for Port %d " 1848 "initialization", port_attr->pa_port_num); 1849 displayed = B_TRUE; 1850 } 1851 } 1852 } 1853 IBTF_DPRINTF_L4("ibnex", "\tPort is initialized"); 1854 1855 mutex_enter(&ibnex.ibnex_mutex); 1856 port_guid = port_attr->pa_port_guid; 1857 if ((rval = ibnex_get_dip_from_guid(port_guid, index, pkey, 1858 &cdip)) == IBNEX_SUCCESS) { 1859 IBTF_DPRINTF_L4("ibnex", "\tconfig_port_node: Node exists"); 1860 mutex_exit(&ibnex.ibnex_mutex); 1861 ibdm_ibnex_free_port_attr(port_attr); 1862 return (cdip); 1863 } 1864 for (ii = 0; ii < port_attr->pa_npkeys; ii++) { 1865 if (pkey == port_attr->pa_pkey_tbl[ii].pt_pkey) { 1866 cdip = ibnex_commsvc_initnode(parent, port_attr, 1867 index, IBNEX_VPPA_COMMSVC_NODE, pkey, &rval, 1868 IBNEX_CFGADM_ENUMERATE); 1869 IBTF_DPRINTF_L5("ibnex", 1870 "\t ibnex_commsvc_initnode rval %x", rval); 1871 break; 1872 } 1873 } 1874 mutex_exit(&ibnex.ibnex_mutex); 1875 1876 ibdm_ibnex_free_port_attr(port_attr); 1877 return (cdip); 1878 } 1879 1880 1881 /* 1882 * ibnex_prom_devname_to_pkey_n_portnum() 1883 * Parses the device node name and extracts "PKEY" and "port#" 1884 * Returns IBNEX_SUCCESS/IBNEX_FAILURE 1885 */ 1886 static int 1887 ibnex_prom_devname_to_pkey_n_portnum( 1888 char *devname, ib_pkey_t *pkey, uint8_t *port) 1889 { 1890 int ret = IBNEX_SUCCESS; 1891 char *tmp, *tmp1; 1892 1893 if ((tmp = strstr(devname, "port=")) != NULL) { 1894 if ((tmp = strchr(++tmp, '=')) != NULL) 1895 if ((tmp1 = strchr(++tmp, ',')) != NULL) 1896 *port = ibnex_str2int(tmp, (tmp1 - tmp), &ret); 1897 } else 1898 ret = IBNEX_FAILURE; 1899 1900 if ((ret == IBNEX_SUCCESS) && 1901 (tmp = strstr(devname, "pkey=")) != NULL) { 1902 if ((tmp = strchr(++tmp, '=')) != NULL) 1903 if ((tmp1 = strchr(++tmp, ',')) != NULL) 1904 *pkey = ibnex_str2hex(tmp, (tmp1 - tmp), &ret); 1905 } else 1906 ret = IBNEX_FAILURE; 1907 1908 return (ret); 1909 } 1910 1911 1912 /* 1913 * ibnex_get_pkey_commsvc_index_portnum() 1914 * Parses the device node name and extracts PKEY, communication 1915 * service index & Port #. 1916 * Returns IBNEX_SUCCESS/IBNEX_FAILURE 1917 */ 1918 static int 1919 ibnex_get_pkey_commsvc_index_portnum(char *device_name, int *index, 1920 ib_pkey_t *pkey, uint8_t *port_num) 1921 { 1922 char *srv, **service_name, *temp; 1923 int ii, ncommsvcs, ret; 1924 1925 if (ibnex_devname_to_portnum(device_name, port_num) != 1926 IBNEX_SUCCESS) { 1927 IBTF_DPRINTF_L2("ibnex", 1928 "\tget_pkey_commsvc_index_portnum: Invalid PortGuid"); 1929 return (NULL); 1930 } 1931 srv = strchr(device_name, ','); 1932 if (srv == 0) 1933 return (IBNEX_FAILURE); 1934 1935 srv++; 1936 temp = strchr(srv, ','); 1937 if (temp == 0) 1938 return (IBNEX_FAILURE); 1939 temp++; 1940 *pkey = ibnex_str2hex(srv, (temp - srv - 1), &ret); 1941 if (ret != IBNEX_SUCCESS) 1942 return (ret); 1943 1944 if (*pkey == 0 && *port_num != 0) { 1945 service_name = ibnex.ibnex_comm_svc_names; 1946 ncommsvcs = ibnex.ibnex_num_comm_svcs; 1947 } else if (*pkey == 0 && *port_num == 0) { 1948 service_name = ibnex.ibnex_hcasvc_comm_svc_names; 1949 ncommsvcs = ibnex.ibnex_nhcasvc_comm_svcs; 1950 } else { 1951 service_name = ibnex.ibnex_vppa_comm_svc_names; 1952 ncommsvcs = ibnex.ibnex_nvppa_comm_svcs; 1953 } 1954 1955 for (ii = 0; ii < ncommsvcs; ii++) { 1956 if (strcmp(service_name[ii], temp) == 0) { 1957 break; 1958 } 1959 } 1960 if (ii == ncommsvcs) 1961 return (IBNEX_FAILURE); 1962 1963 *index = ii; 1964 return (IBNEX_SUCCESS); 1965 } 1966 1967 1968 /* 1969 * ibnex_devname_to_portnum() 1970 * Get portguid from device name 1971 * Returns IBNEX_SUCCESS/IBNEX_FAILURE 1972 */ 1973 static int 1974 ibnex_devname_to_portnum(char *device_name, uint8_t *portnum) 1975 { 1976 int ret; 1977 char *temp1, *temp2; 1978 1979 temp1 = strchr(device_name, '@'); 1980 if (temp1 == NULL) { 1981 return (IBNEX_FAILURE); 1982 } 1983 temp2 = strchr(temp1, ','); 1984 if (temp2 == NULL) 1985 return (IBNEX_FAILURE); 1986 temp1++; 1987 *portnum = ibnex_str2hex(temp1, (temp2 - temp1), &ret); 1988 return (ret); 1989 } 1990 1991 1992 /* 1993 * ibnex_config_ioc_node() 1994 * Configures one particular instance of the IOC driver. 1995 * Returns IBNEX_SUCCESS/IBNEX_FAILURE 1996 */ 1997 static int 1998 ibnex_config_ioc_node(char *device_name, dev_info_t *pdip) 1999 { 2000 int ret; 2001 time_t wait_time; 2002 ib_guid_t iou_guid, ioc_guid; 2003 ibdm_ioc_info_t *ioc_info; 2004 2005 IBTF_DPRINTF_L4("ibnex", "\tconfig_ioc_node: Begin"); 2006 2007 if (ibnex_devname_to_node_n_ioc_guids( 2008 device_name, &iou_guid, &ioc_guid, NULL) != IBNEX_SUCCESS) { 2009 return (IBNEX_FAILURE); 2010 } 2011 2012 wait_time = ibdm_ibnex_get_waittime(0, &ibnex_port_settling_time); 2013 if (wait_time) 2014 delay(drv_usectohz(wait_time * 1000000)); 2015 2016 if ((ioc_info = ibdm_ibnex_probe_ioc(iou_guid, ioc_guid, 0)) == 2017 NULL) { 2018 ibdm_ibnex_free_ioc_list(ioc_info); 2019 return (IBNEX_FAILURE); 2020 } 2021 mutex_enter(&ibnex.ibnex_mutex); 2022 if (ibnex_is_ioc_present(ioc_guid) == IBNEX_SUCCESS) { 2023 IBTF_DPRINTF_L4("ibnex", "\tconfig_ioc_node: IOC present"); 2024 ret = IBNEX_SUCCESS; 2025 } else 2026 ret = ibnex_ioc_initnode(ioc_info, IBNEX_DEVFS_ENUMERATE, 2027 pdip); 2028 mutex_exit(&ibnex.ibnex_mutex); 2029 ibdm_ibnex_free_ioc_list(ioc_info); 2030 return (ret); 2031 } 2032 2033 2034 /* 2035 * ibnex_devname_to_node_n_ioc_guids() 2036 * Get node guid and ioc guid from the device name 2037 * Format of the device node name is: 2038 * ioc@<IOC GUID>,<IOU GUID> 2039 * Returns IBNEX_SUCCESS/IBNEX_FAILURE 2040 */ 2041 static int 2042 ibnex_devname_to_node_n_ioc_guids( 2043 char *device_name, ib_guid_t *iou_guid, ib_guid_t *ioc_guid, 2044 char **ioc_guid_strp) 2045 { 2046 char *temp1, *temp; 2047 int len, ret; 2048 char *ioc_guid_str; 2049 2050 IBTF_DPRINTF_L4("ibnex", "\tdevname_to_node_n_ioc_guids:" 2051 "Device Name %s", device_name); 2052 2053 if ((temp = strchr(device_name, '@')) == NULL) { 2054 return (IBNEX_FAILURE); 2055 } 2056 if ((temp1 = strchr(++temp, ',')) == NULL) { 2057 return (IBNEX_FAILURE); 2058 } 2059 *ioc_guid = ibnex_str2hex(temp, (temp1 - temp), &ret); 2060 if (ret == IBNEX_SUCCESS) { 2061 if (ioc_guid_strp) { 2062 ioc_guid_str = *ioc_guid_strp = kmem_zalloc((temp1 2063 - temp) + 1, KM_SLEEP); 2064 (void) strncpy(ioc_guid_str, temp, temp1 - temp + 1); 2065 ioc_guid_str[temp1 - temp] = '\0'; 2066 } 2067 len = device_name + strlen(device_name) - ++temp1; 2068 *iou_guid = ibnex_str2hex(temp1, len, &ret); 2069 } 2070 return (ret); 2071 } 2072 2073 2074 /*ARGSUSED*/ 2075 /* 2076 * ibnex_ioc_initnode() 2077 * Allocate a pathinfo node for the IOC 2078 * Initialize the device node 2079 * Bind driver to the node 2080 * Update IBnex global data 2081 * Returns IBNEX_SUCCESS/IBNEX_FAILURE/IBNEX_BUSY 2082 */ 2083 int 2084 ibnex_ioc_initnode(ibdm_ioc_info_t *ioc_info, int flag, dev_info_t *pdip) 2085 { 2086 int rval; 2087 ibnex_node_data_t *node_data; 2088 2089 ASSERT(MUTEX_HELD(&ibnex.ibnex_mutex)); 2090 2091 node_data = ibnex_is_node_data_present(IBNEX_IOC_NODE, 2092 (void *)ioc_info, 0, 0); 2093 2094 /* 2095 * prevent any races 2096 * we have seen this node_data and it has been initialized 2097 * Note that node_dip is already NULL if unconfigure is in 2098 * progress. 2099 */ 2100 if (node_data && node_data->node_dip) { 2101 return ((node_data->node_state == IBNEX_CFGADM_CONFIGURING) ? 2102 IBNEX_BUSY : IBNEX_SUCCESS); 2103 } else if (node_data == NULL) { 2104 node_data = ibnex_init_child_nodedata(IBNEX_IOC_NODE, 2105 ioc_info, 0, 0); 2106 } 2107 2108 /* 2109 * Return EBUSY if another configure/unconfigure 2110 * operation is in progress 2111 */ 2112 if (node_data->node_state == IBNEX_CFGADM_UNCONFIGURING) { 2113 return (IBNEX_BUSY); 2114 } 2115 2116 ASSERT(node_data->node_state != IBNEX_CFGADM_CONFIGURED); 2117 node_data->node_state = IBNEX_CFGADM_CONFIGURING; 2118 2119 2120 mutex_exit(&ibnex.ibnex_mutex); 2121 2122 rval = ibnex_ioc_create_pi(ioc_info, node_data, pdip); 2123 2124 mutex_enter(&ibnex.ibnex_mutex); 2125 if (rval == IBNEX_SUCCESS) 2126 node_data->node_state = IBNEX_CFGADM_CONFIGURED; 2127 2128 return (rval); 2129 } 2130 2131 2132 /* 2133 * ibnex_config_pseudo_all() 2134 * Configure all the pseudo nodes 2135 */ 2136 static void 2137 ibnex_config_pseudo_all(dev_info_t *pdip) 2138 { 2139 ibnex_node_data_t *nodep; 2140 2141 ASSERT(MUTEX_HELD(&ibnex.ibnex_mutex)); 2142 2143 for (nodep = ibnex.ibnex_pseudo_node_head; 2144 nodep; nodep = nodep->node_next) { 2145 (void) ibnex_pseudo_config_one(nodep, NULL, pdip); 2146 } 2147 } 2148 2149 2150 /* 2151 * ibnex_pseudo_config_one() 2152 */ 2153 static int 2154 ibnex_pseudo_config_one(ibnex_node_data_t *node_data, char *caddr, 2155 dev_info_t *pdip) 2156 { 2157 int rval; 2158 2159 IBTF_DPRINTF_L4("ibnex", "\tpseudo_config_one(%p, %p, %p):Begin", 2160 node_data, caddr, pdip); 2161 2162 ASSERT(MUTEX_HELD(&ibnex.ibnex_mutex)); 2163 2164 if (node_data == NULL) { 2165 IBTF_DPRINTF_L4("ibnex", "\tpseudo_config_one: caddr = %s", 2166 caddr); 2167 2168 /* 2169 * This function is now called with PHCI / HCA driver 2170 * as parent. The format of devicename is : 2171 * <driver_name>@<driver_name>,<unit_address> 2172 * The "caddr" part of the devicename matches the 2173 * format of pseudo_node_addr. 2174 * 2175 * Use "caddr" to find a matching Pseudo node entry. 2176 */ 2177 node_data = ibnex_is_node_data_present(IBNEX_PSEUDO_NODE, 2178 (void *)caddr, 0, 0); 2179 } 2180 2181 /* 2182 * Do not enumerate nodes with ib-node-type set as "merge" 2183 */ 2184 if (node_data && node_data->node_data.pseudo_node.pseudo_merge_node 2185 == 1) { 2186 IBTF_DPRINTF_L4("ibnex", "\tpseudo_config_one: merge_node"); 2187 return (IBNEX_FAILURE); 2188 } 2189 2190 /* 2191 * prevent any races 2192 * we have seen this node_data and it has been initialized 2193 * Note that node_dip is already NULL if unconfigure is in 2194 * progress. 2195 */ 2196 if (node_data && node_data->node_dip) { 2197 return ((node_data->node_state == IBNEX_CFGADM_CONFIGURING) ? 2198 IBNEX_BUSY : IBNEX_SUCCESS); 2199 } else if (node_data == NULL) { 2200 IBTF_DPRINTF_L2("ibnex", "\tpseudo_config_one: Invalid node"); 2201 return (IBNEX_FAILURE); 2202 } 2203 2204 /* 2205 * Return EBUSY if another configure/unconfigure 2206 * operation is in progress 2207 */ 2208 if (node_data->node_state == IBNEX_CFGADM_UNCONFIGURING) { 2209 return (IBNEX_BUSY); 2210 } 2211 2212 if (node_data->node_state == IBNEX_CFGADM_CONFIGURED) 2213 return (IBNEX_SUCCESS); 2214 2215 /* 2216 * Prevent configuring pseudo nodes specifically unconfigured 2217 * by cfgadm. This is done by checking if this is a newly 2218 * created node, not yet configured by BUS_CONFIG or cfgadm 2219 */ 2220 if (node_data->node_data.pseudo_node.pseudo_new_node != 1) 2221 return (IBNEX_FAILURE); 2222 node_data->node_data.pseudo_node.pseudo_new_node = 0; 2223 2224 node_data->node_state = IBNEX_CFGADM_CONFIGURING; 2225 2226 mutex_exit(&ibnex.ibnex_mutex); 2227 rval = ibnex_pseudo_create_pi(node_data, pdip); 2228 mutex_enter(&ibnex.ibnex_mutex); 2229 2230 if (rval == IBNEX_SUCCESS) 2231 node_data->node_state = IBNEX_CFGADM_CONFIGURED; 2232 else { 2233 node_data->node_dip = NULL; 2234 node_data->node_state = IBNEX_CFGADM_UNCONFIGURED; 2235 node_data->node_data.pseudo_node.pseudo_new_node = 1; 2236 } 2237 2238 return (rval); 2239 } 2240 2241 2242 2243 /* 2244 * ibnex_pseudo_mdi_config_one() 2245 * This is similar to ibnex_pseudo_config_one. Few 2246 * differences : 2247 * 1. parent device lock not held(no ndi_devi_enter) 2248 * 2. Called for IB Nexus as parent, not IB HCA as 2249 * parent. 2250 * 3. Calls mdi_vhci_bus_config() 2251 * This function skips checks for node_state, initializing 2252 * node_state, node_dip, etc. These checks and initializations 2253 * are done when BUS_CONFIG is called with PHCI as the parent. 2254 */ 2255 static int 2256 ibnex_pseudo_mdi_config_one(int flag, void *devname, dev_info_t **child, 2257 char *cname, char *caddr) 2258 { 2259 int rval, len; 2260 char *node_addr; 2261 ibnex_node_data_t *node_data; 2262 2263 IBTF_DPRINTF_L4("ibnex", "\tpseudo_mdi_config_one:" 2264 "cname = %s caddr = %s", cname, caddr); 2265 2266 ASSERT(MUTEX_HELD(&ibnex.ibnex_mutex)); 2267 2268 len = strlen(cname) + strlen(caddr) + 2; 2269 node_addr = (char *)kmem_alloc(len, KM_SLEEP); 2270 2271 (void) snprintf(node_addr, len, "%s,%s", cname, caddr); 2272 node_data = ibnex_is_node_data_present(IBNEX_PSEUDO_NODE, 2273 (void *)node_addr, 0, 0); 2274 kmem_free(node_addr, len); 2275 2276 if (node_data == NULL) { 2277 IBTF_DPRINTF_L2("ibnex", 2278 "\tpseudo_mdi_config_one: Invalid node"); 2279 return (IBNEX_FAILURE); 2280 } 2281 2282 mutex_exit(&ibnex.ibnex_mutex); 2283 rval = mdi_vhci_bus_config(ibnex.ibnex_dip, flag, BUS_CONFIG_ONE, 2284 devname, child, node_data->node_data.pseudo_node.pseudo_node_addr); 2285 mutex_enter(&ibnex.ibnex_mutex); 2286 2287 return (rval); 2288 } 2289 2290 /* 2291 * ibnex_pseudo_create_pi() 2292 * Create a path info node for each pseudo entry 2293 */ 2294 int 2295 ibnex_pseudo_create_pi(ibnex_node_data_t *nodep, dev_info_t *parent) 2296 { 2297 mdi_pathinfo_t *pip; 2298 int rval, hcacnt; 2299 dev_info_t *hca_dip, *cdip = NULL; 2300 ibdm_hca_list_t *hca_list, *head; 2301 ibnex_pseudo_node_t *pseudo; 2302 2303 IBTF_DPRINTF_L4("ibnex", "\tibnex_pseudo_create_pi: %p", nodep); 2304 2305 pseudo = &nodep->node_data.pseudo_node; 2306 2307 2308 ibdm_ibnex_get_hca_list(&hca_list, &hcacnt); 2309 2310 head = hca_list; 2311 2312 for (; hca_list != NULL; hca_list = hca_list->hl_next) { 2313 2314 hca_dip = ibtl_ibnex_hcaguid2dip(hca_list->hl_hca_guid); 2315 2316 /* 2317 * For CONFIG_ONE requests through HCA dip, alloc 2318 * for HCA dip driving BUS_CONFIG request. 2319 */ 2320 if (parent != NULL && hca_dip != parent) 2321 continue; 2322 2323 rval = mdi_pi_alloc(hca_dip, 2324 pseudo->pseudo_devi_name, pseudo->pseudo_node_addr, 2325 pseudo->pseudo_node_addr, 0, &pip); 2326 2327 if (rval != MDI_SUCCESS) { 2328 (void) ibnex_offline_childdip(cdip); 2329 return (IBNEX_FAILURE); 2330 } 2331 cdip = mdi_pi_get_client(pip); 2332 2333 IBTF_DPRINTF_L4("ibnex", 2334 "\tpseudo_create_pi: New dip %p", cdip); 2335 2336 nodep->node_dip = cdip; 2337 ddi_set_parent_data(cdip, nodep); 2338 2339 rval = mdi_pi_online(pip, 0); 2340 2341 if (rval != MDI_SUCCESS) { 2342 ddi_set_parent_data(cdip, NULL); 2343 IBTF_DPRINTF_L2("ibnex", "\tpseudo_create_pi:" 2344 "mdi_pi_online: failed for pseudo dip %p," 2345 " rval %d", cdip, rval); 2346 (void) ibnex_offline_childdip(cdip); 2347 rval = IBNEX_FAILURE; 2348 break; 2349 } else 2350 rval = IBNEX_SUCCESS; 2351 2352 if (parent != NULL && hca_dip != parent) 2353 break; 2354 } 2355 if (head) 2356 ibdm_ibnex_free_hca_list(head); 2357 return (rval); 2358 } 2359 2360 2361 /* 2362 * ibnex_ioc_create_pi() 2363 * Create a pathinfo node for the ioc node 2364 */ 2365 static int 2366 ibnex_ioc_create_pi(ibdm_ioc_info_t *ioc_info, ibnex_node_data_t *node_data, 2367 dev_info_t *pdip) 2368 { 2369 char ioc_guid[33], phci_guid[66]; 2370 mdi_pathinfo_t *pip; 2371 int rval = DDI_FAILURE; 2372 dev_info_t *hca_dip, *cdip = NULL; 2373 int flag = 1; 2374 ibdm_hca_list_t *hca_list; 2375 2376 IBTF_DPRINTF_L4("ibnex", "\tibnex_ioc_create_pi Begin"); 2377 2378 (void) snprintf(ioc_guid, 33, "%llX", 2379 (longlong_t)ioc_info->ioc_profile.ioc_guid); 2380 (void) snprintf(phci_guid, 66, "%llX,%llX", 2381 (longlong_t)ioc_info->ioc_profile.ioc_guid, 2382 (longlong_t)ioc_info->ioc_iou_guid); 2383 2384 hca_list = ioc_info->ioc_hca_list; 2385 2386 for (; hca_list != NULL; hca_list = hca_list->hl_next) { 2387 2388 hca_dip = ibtl_ibnex_hcaguid2dip(hca_list->hl_hca_guid); 2389 2390 /* 2391 * For CONFIG_ONE requests through HCA dip, alloc 2392 * for HCA dip driving BUS_CONFIG request. 2393 */ 2394 if (pdip != NULL && hca_dip != pdip) 2395 continue; 2396 2397 IBTF_DPRINTF_L4("ibnex", "\tioc_create_pi " 2398 "hca guid %llX", hca_list->hl_hca_guid); 2399 2400 rval = mdi_pi_alloc(hca_dip, 2401 IBNEX_IOC_CNAME, ioc_guid, phci_guid, 0, &pip); 2402 if (rval != MDI_SUCCESS) { 2403 (void) ibnex_offline_childdip(cdip); 2404 return (IBNEX_FAILURE); 2405 } 2406 cdip = mdi_pi_get_client(pip); 2407 2408 IBTF_DPRINTF_L4("ibnex", 2409 "\tioc_create_pi: New IOC dip %p", cdip); 2410 2411 node_data->node_dip = cdip; 2412 ddi_set_parent_data(cdip, node_data); 2413 2414 if (flag) { 2415 if ((rval = ibnex_create_ioc_node_prop( 2416 ioc_info, cdip)) != IBNEX_SUCCESS) { 2417 ibnex_delete_ioc_node_data(node_data); 2418 ddi_prop_remove_all(cdip); 2419 ddi_set_parent_data(cdip, NULL); 2420 2421 (void) ibnex_offline_childdip(cdip); 2422 return (IBNEX_FAILURE); 2423 } 2424 flag = 0; 2425 } 2426 2427 rval = mdi_pi_online(pip, 0); 2428 2429 if (rval != MDI_SUCCESS) { 2430 ibnex_delete_ioc_node_data(node_data); 2431 ddi_prop_remove_all(cdip); 2432 ddi_set_parent_data(cdip, NULL); 2433 IBTF_DPRINTF_L2("ibnex", "\tioc_create_pi: " 2434 "mdi_pi_online() failed ioc dip %p, rval %d", 2435 cdip, rval); 2436 (void) ibnex_offline_childdip(cdip); 2437 rval = IBNEX_FAILURE; 2438 break; 2439 } else 2440 rval = IBNEX_SUCCESS; 2441 2442 if (pdip != NULL && hca_dip != pdip) 2443 break; 2444 } 2445 return (rval); 2446 } 2447 2448 2449 /* 2450 * ibnex_create_ioc_node_prop() 2451 * Create IOC device node properties 2452 * Returns IBNEX_SUCCESS/IBNEX_FAILURE 2453 */ 2454 static int 2455 ibnex_create_ioc_node_prop(ibdm_ioc_info_t *ioc_info, dev_info_t *cdip) 2456 { 2457 uint16_t capabilities; 2458 ib_dm_ioc_ctrl_profile_t *ioc_profile = &ioc_info->ioc_profile; 2459 2460 IBTF_DPRINTF_L4("ibnex", "\tcreate_ioc_node_prop"); 2461 2462 if (ibnex_create_ioc_compatible_prop(cdip, 2463 ioc_profile) != IBNEX_SUCCESS) { 2464 return (IBNEX_FAILURE); 2465 } 2466 if ((ioc_info->ioc_iou_dc_valid) && 2467 (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, "iou-diagcode", 2468 ioc_info->ioc_iou_diagcode)) != DDI_PROP_SUCCESS) { 2469 IBTF_DPRINTF_L2("ibnex", 2470 "\tcreate_ioc_node_prop: iou-diagcode create failed"); 2471 return (IBNEX_FAILURE); 2472 } 2473 if ((ioc_info->ioc_diagdeviceid) && (ioc_info->ioc_dc_valid)) { 2474 if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, "ioc-diagcode", 2475 ioc_info->ioc_diagcode) != DDI_PROP_SUCCESS) { 2476 IBTF_DPRINTF_L2("ibnex", "\tcreate_ioc_node_prop: " 2477 "ioc-diagcode create failed"); 2478 return (IBNEX_FAILURE); 2479 } 2480 } 2481 if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, "rdma-queue-depth", 2482 ioc_profile->ioc_rdma_read_qdepth) != DDI_PROP_SUCCESS) { 2483 IBTF_DPRINTF_L2("ibnex", 2484 "\tcreate_ioc_node_prop: rdma-queue-depth create failed"); 2485 return (IBNEX_FAILURE); 2486 } 2487 if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, "rdma-transfer-size", 2488 ioc_profile->ioc_rdma_xfer_sz) != DDI_PROP_SUCCESS) { 2489 IBTF_DPRINTF_L2("ibnex", "\tcreate_ioc_node_prop: " 2490 "rdma-transfer-size create failed"); 2491 return (IBNEX_FAILURE); 2492 } 2493 if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, "send-message-size", 2494 ioc_profile->ioc_send_msg_sz) != DDI_PROP_SUCCESS) { 2495 IBTF_DPRINTF_L2("ibnex", 2496 "\tcreate_ioc_node_prop: send-message-size create failed"); 2497 return (IBNEX_FAILURE); 2498 } 2499 if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, "send-queue-depth", 2500 ioc_profile->ioc_send_msg_qdepth) != DDI_PROP_SUCCESS) { 2501 IBTF_DPRINTF_L2("ibnex", 2502 "\tcreate_ioc_node_prop: send-queue-depth create failed"); 2503 return (IBNEX_FAILURE); 2504 } 2505 2506 capabilities = (ioc_profile->ioc_ctrl_opcap_mask << 8); 2507 if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, 2508 "capabilities", capabilities) != DDI_PROP_SUCCESS) { 2509 IBTF_DPRINTF_L2("ibnex", 2510 "\tcreate_ioc_node_prop: capabilities create failed"); 2511 return (IBNEX_FAILURE); 2512 } 2513 if (ndi_prop_update_string(DDI_DEV_T_NONE, cdip, "id-string", 2514 (char *)ioc_profile->ioc_id_string) != DDI_PROP_SUCCESS) { 2515 IBTF_DPRINTF_L2("ibnex", 2516 "\tcreate_ioc_node_prop: id-string failed"); 2517 return (IBNEX_FAILURE); 2518 } 2519 2520 /* 2521 * Create properties to represent all the service entries supported 2522 * by the IOC. Each service entry consists of 1) Service ID (64 bits) 2523 * and 2) Service name (40 bytes). The service entry table is 2524 * represented by two properties, service-ids and service-names. The 2525 * service-id property is a array of int64's and service names is 2526 * array of strings. The first element in the "service-ids" property 2527 * corresponds to first string in the "service-names" and so on. 2528 */ 2529 if ((ioc_profile->ioc_service_entries != 0) && 2530 (ibnex_create_ioc_srv_props(cdip, ioc_info) != IBNEX_SUCCESS)) 2531 return (IBNEX_FAILURE); 2532 2533 /* Create destination port GID properties */ 2534 if (ibnex_create_ioc_portgid_prop(cdip, ioc_info) != IBNEX_SUCCESS) 2535 return (IBNEX_FAILURE); 2536 2537 if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, "protocol-version", 2538 ioc_profile->ioc_protocol_ver) != DDI_PROP_SUCCESS) { 2539 IBTF_DPRINTF_L2("ibnex", 2540 "\tcreate_ioc_node_prop: protocol-version create failed"); 2541 return (IBNEX_FAILURE); 2542 } 2543 if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, "protocol", 2544 ioc_profile->ioc_protocol) != DDI_PROP_SUCCESS) { 2545 IBTF_DPRINTF_L2("ibnex", 2546 "\tcreate_ioc_node_prop: protocol create failed"); 2547 return (IBNEX_FAILURE); 2548 } 2549 if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, "io-subclass", 2550 ioc_profile->ioc_io_subclass) != DDI_PROP_SUCCESS) { 2551 IBTF_DPRINTF_L2("ibnex", 2552 "\tcreate_ioc_node_prop: subclass create failed"); 2553 return (IBNEX_FAILURE); 2554 } 2555 if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, "io-class", 2556 ioc_profile->ioc_io_class) != DDI_PROP_SUCCESS) { 2557 IBTF_DPRINTF_L2("ibnex", 2558 "\tcreate_ioc_node_prop: class prop create failed"); 2559 return (IBNEX_FAILURE); 2560 } 2561 if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, "subsystem-id", 2562 ioc_profile->ioc_subsys_id) != DDI_PROP_SUCCESS) { 2563 IBTF_DPRINTF_L2("ibnex", 2564 "\tcreate_ioc_node_prop: subsys_id create failed"); 2565 return (IBNEX_FAILURE); 2566 } 2567 if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, "subsystem-vendor-id", 2568 ioc_profile->ioc_subsys_vendorid) != DDI_PROP_SUCCESS) { 2569 IBTF_DPRINTF_L2("ibnex", 2570 "\tcreate_ioc_node_prop: subsystem vendor create failed"); 2571 return (IBNEX_FAILURE); 2572 } 2573 if (ndi_prop_update_int64(DDI_DEV_T_NONE, cdip, "ioc-guid", 2574 ioc_profile->ioc_guid) != DDI_PROP_SUCCESS) { 2575 IBTF_DPRINTF_L2("ibnex", 2576 "\tcreate_ioc_node_prop: protocol create failed"); 2577 return (IBNEX_FAILURE); 2578 } 2579 if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, "device-version", 2580 ioc_profile->ioc_device_ver) != DDI_PROP_SUCCESS) { 2581 IBTF_DPRINTF_L2("ibnex", 2582 "\tcreate_ioc_node_prop: product-id create failed"); 2583 return (IBNEX_FAILURE); 2584 } 2585 if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, "device-id", 2586 ioc_profile->ioc_deviceid) != DDI_PROP_SUCCESS) { 2587 IBTF_DPRINTF_L2("ibnex", 2588 "\tcreate_ioc_node_prop: product-id create failed"); 2589 return (IBNEX_FAILURE); 2590 } 2591 if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, "vendor-id", 2592 ioc_profile->ioc_vendorid) != DDI_PROP_SUCCESS) { 2593 IBTF_DPRINTF_L2("ibnex", 2594 "\tcreate_ioc_node_prop: vendor-id create failed"); 2595 return (IBNEX_FAILURE); 2596 } 2597 return (IBNEX_SUCCESS); 2598 } 2599 2600 2601 /* 2602 * ibnex_create_ioc_portgid_prop() 2603 * Creates "port-entries", "port-list" properties 2604 * Returns IBNEX_SUCCESS/IBNEX_FAILURE 2605 */ 2606 static int 2607 ibnex_create_ioc_portgid_prop( 2608 dev_info_t *cdip, ibdm_ioc_info_t *ioc_info) 2609 { 2610 uint64_t *port_gids; 2611 int length, ii, jj; 2612 int prop_len; 2613 ibnex_node_data_t *node_data; 2614 2615 IBTF_DPRINTF_L4("ibnex", "\tcreate_ioc_portgid_prop"); 2616 2617 node_data = ddi_get_parent_data(cdip); 2618 ASSERT(node_data); 2619 2620 prop_len = (ioc_info->ioc_nportgids != 0) ? 2621 (2 * ioc_info->ioc_nportgids) : 1; 2622 length = sizeof (uint64_t) * prop_len; 2623 port_gids = kmem_zalloc(length, KM_SLEEP); 2624 2625 for (ii = 0, jj = 0; ii < ioc_info->ioc_nportgids; ii++) { 2626 port_gids[jj++] = ioc_info->ioc_gid_list[ii].gid_dgid_hi; 2627 port_gids[jj++] = ioc_info->ioc_gid_list[ii].gid_dgid_lo; 2628 } 2629 if (ndi_prop_update_int64_array(DDI_DEV_T_NONE, cdip, "port-list", 2630 (int64_t *)port_gids, prop_len) != DDI_PROP_SUCCESS) { 2631 IBTF_DPRINTF_L2("ibnex", 2632 "\tcreate_ioc_portgid_prop: port-list create failed"); 2633 kmem_free(port_gids, length); 2634 return (IBNEX_FAILURE); 2635 } 2636 if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, "port-entries", 2637 ioc_info->ioc_nportgids) != DDI_PROP_SUCCESS) { 2638 IBTF_DPRINTF_L2("ibnex", 2639 "\tcreate_ioc_portgid_prop: port-entries create failed"); 2640 kmem_free(port_gids, length); 2641 return (IBNEX_FAILURE); 2642 } 2643 2644 kmem_free(port_gids, length); 2645 return (IBNEX_SUCCESS); 2646 } 2647 2648 2649 /* 2650 * ibnex_create_ioc_srv_props() 2651 * Creates "service-name" and "service-id" properties 2652 * Returns IBNEX_SUCCESS/IBNEX_FAILURE 2653 */ 2654 static int 2655 ibnex_create_ioc_srv_props( 2656 dev_info_t *cdip, ibdm_ioc_info_t *ioc_info) 2657 { 2658 int length, ii; 2659 uint64_t *srv_id; 2660 char *temp, *srv_names[IB_DM_MAX_IOCS_IN_IOU]; 2661 ib_dm_ioc_ctrl_profile_t *profile = &ioc_info->ioc_profile; 2662 ibdm_srvents_info_t *srvents = ioc_info->ioc_serv; 2663 2664 IBTF_DPRINTF_L4("ibnex", "\tcreate_ioc_srv_props"); 2665 2666 length = profile->ioc_service_entries * sizeof (ib_dm_srv_t); 2667 srv_id = kmem_zalloc(length, KM_SLEEP); 2668 temp = (char *)((char *)srv_id + (8 * profile->ioc_service_entries)); 2669 for (ii = 0; ii < profile->ioc_service_entries; ii++) { 2670 srv_names[ii] = (char *)temp + (ii * IB_DM_MAX_SVC_NAME_LEN); 2671 } 2672 2673 for (ii = 0; ii < profile->ioc_service_entries; ii++) { 2674 srv_id[ii] = srvents[ii].se_attr.srv_id; 2675 bcopy(srvents[ii].se_attr.srv_name, 2676 srv_names[ii], (IB_DM_MAX_SVC_NAME_LEN - 1)); 2677 IBTF_DPRINTF_L4("ibnex", "\tcreate_ioc_srv_props " 2678 "Service Names : %s", srv_names[ii]); 2679 IBTF_DPRINTF_L4("ibnex", "\tcreate_ioc_srv_props " 2680 "Service ID : %llX", srv_id[ii]); 2681 } 2682 2683 if (ndi_prop_update_int64_array(DDI_DEV_T_NONE, cdip, 2684 "service-id", (int64_t *)srv_id, 2685 profile->ioc_service_entries) != DDI_PROP_SUCCESS) { 2686 IBTF_DPRINTF_L2("ibnex", 2687 "\tcreate_ioc_srv_props: service-id create failed"); 2688 kmem_free(srv_id, length); 2689 return (IBNEX_FAILURE); 2690 } 2691 2692 if (ndi_prop_update_string_array(DDI_DEV_T_NONE, cdip, 2693 "service-name", (char **)srv_names, 2694 profile->ioc_service_entries) != DDI_PROP_SUCCESS) { 2695 IBTF_DPRINTF_L2("ibnex", 2696 "\tcreate_ioc_srv_props: service-name create failed"); 2697 kmem_free(srv_id, length); 2698 return (IBNEX_FAILURE); 2699 } 2700 kmem_free(srv_id, length); 2701 return (IBNEX_SUCCESS); 2702 } 2703 2704 2705 /* 2706 * ibnex_create_ioc_compatible_prop() 2707 * Creates "compatible" property values 2708 * Returns IBNEX_SUCCESS/IBNEX_FAILURE 2709 */ 2710 static int 2711 ibnex_create_ioc_compatible_prop( 2712 dev_info_t *cdip, ib_dm_ioc_ctrl_profile_t *ioc_profile) 2713 { 2714 char *temp; 2715 int rval, ii; 2716 char *compatible[IBNEX_MAX_COMPAT_NAMES]; 2717 2718 /* 2719 * Initialize the "compatible" property string as below: 2720 * Compatible Strings : 2721 * 1. ib.V<vid>P<pid>S<subsys vid>s<subsys id>v<ver> 2722 * 2. ib.V<vid>P<pid>S<subsys vid>s<subsys id> 2723 * 3. ib.V<vid>P<pid>v<ver> 2724 * 4. ib.V<vid>P<pid> 2725 * 5. ib.C<Class>c<Subclass>p<protocol>r<protocol ver> 2726 * 6. ib.C<Class>c<Subclass>p<protocol> 2727 * 2728 * Note: 2729 * All leading zeros must be present 2730 * All numeric values must specified in hex without prefix "0x" 2731 */ 2732 2733 temp = kmem_alloc(IBNEX_MAX_COMPAT_PROP_SZ, KM_SLEEP); 2734 for (ii = 0; ii < IBNEX_MAX_COMPAT_NAMES; ii++) 2735 compatible[ii] = temp + (ii * IBNEX_MAX_COMPAT_LEN); 2736 2737 (void) snprintf(compatible[0], IBNEX_MAX_COMPAT_LEN, 2738 "ib.V%06xP%08xS%06xs%08xv%04x", 2739 ioc_profile->ioc_vendorid, ioc_profile->ioc_deviceid, 2740 ioc_profile->ioc_subsys_vendorid, ioc_profile->ioc_subsys_id, 2741 ioc_profile->ioc_device_ver); 2742 2743 (void) snprintf(compatible[1], IBNEX_MAX_COMPAT_LEN, 2744 "ib.V%06xP%08xS%06xs%08x", 2745 ioc_profile->ioc_vendorid, ioc_profile->ioc_deviceid, 2746 ioc_profile->ioc_subsys_vendorid, ioc_profile->ioc_subsys_id); 2747 2748 (void) snprintf(compatible[2], IBNEX_MAX_COMPAT_LEN, 2749 "ib.V%06xP%08xv%04x", 2750 ioc_profile->ioc_vendorid, ioc_profile->ioc_deviceid, 2751 ioc_profile->ioc_device_ver); 2752 2753 (void) snprintf(compatible[3], IBNEX_MAX_COMPAT_LEN, 2754 "ib.V%06xP%08x", 2755 ioc_profile->ioc_vendorid, ioc_profile->ioc_deviceid); 2756 2757 (void) snprintf(compatible[4], IBNEX_MAX_COMPAT_LEN, 2758 "ib.C%04xc%04xp%04xr%04x", 2759 ioc_profile->ioc_io_class, ioc_profile->ioc_io_subclass, 2760 ioc_profile->ioc_protocol, ioc_profile->ioc_protocol_ver); 2761 2762 (void) snprintf(compatible[5], IBNEX_MAX_COMPAT_LEN, 2763 "ib.C%04xc%04xp%04x", 2764 ioc_profile->ioc_io_class, ioc_profile->ioc_io_subclass, 2765 ioc_profile->ioc_protocol); 2766 for (ii = 0; ii < IBNEX_MAX_COMPAT_NAMES; ii++) 2767 IBTF_DPRINTF_L4("ibnex", "\tcompatible: %s", compatible[ii]); 2768 2769 /* Create the compatible property for child cdip */ 2770 rval = ndi_prop_update_string_array(DDI_DEV_T_NONE, cdip, 2771 "compatible", (char **)compatible, IBNEX_MAX_COMPAT_NAMES); 2772 2773 if (rval != DDI_PROP_SUCCESS) { 2774 IBTF_DPRINTF_L2("ibnex", "\tcompatible prop_create failed"); 2775 kmem_free(temp, IBNEX_MAX_COMPAT_PROP_SZ); 2776 return (IBNEX_FAILURE); 2777 } 2778 2779 kmem_free(temp, IBNEX_MAX_COMPAT_PROP_SZ); 2780 return (IBNEX_SUCCESS); 2781 } 2782 2783 2784 static void 2785 ibnex_ioc_node_cleanup() 2786 { 2787 ibnex_node_data_t *node, *delete; 2788 2789 ASSERT(MUTEX_HELD(&ibnex.ibnex_mutex)); 2790 for (node = ibnex.ibnex_ioc_node_head; node; ) { 2791 delete = node; 2792 node = node->node_next; 2793 mutex_exit(&ibnex.ibnex_mutex); 2794 ibnex_delete_ioc_node_data(delete); 2795 mutex_enter(&ibnex.ibnex_mutex); 2796 } 2797 } 2798 2799 /* 2800 * ibnex_delete_ioc_node_data() 2801 * Delete IOC node from the list 2802 */ 2803 static void 2804 ibnex_delete_ioc_node_data(ibnex_node_data_t *node) 2805 { 2806 IBTF_DPRINTF_L4("ibnex", "\tdelete_ioc_node_data:"); 2807 2808 mutex_enter(&ibnex.ibnex_mutex); 2809 if ((node->node_next == NULL) && (node->node_prev == NULL)) { 2810 ASSERT(ibnex.ibnex_ioc_node_head == node); 2811 ibnex.ibnex_ioc_node_head = NULL; 2812 } else if (node->node_next == NULL) 2813 node->node_prev->node_next = NULL; 2814 else if (node->node_prev == NULL) { 2815 node->node_next->node_prev = NULL; 2816 ibnex.ibnex_ioc_node_head = node->node_next; 2817 } else { 2818 node->node_prev->node_next = node->node_next; 2819 node->node_next->node_prev = node->node_prev; 2820 } 2821 IBTF_DPRINTF_L4("ibnex", "\tdelete_ioc_node_data: head %p", 2822 ibnex.ibnex_ioc_node_head); 2823 mutex_exit(&ibnex.ibnex_mutex); 2824 kmem_free(node, sizeof (ibnex_node_data_t)); 2825 } 2826 2827 2828 /* 2829 * ibnex_dm_callback() 2830 * 2831 * This routine is registered with the IBDM during IB nexus attach. It 2832 * is called by the IBDM module when it discovers 2833 * New HCA port 2834 * HCA port removal 2835 * New HCA added 2836 * HCA removed 2837 */ 2838 void 2839 ibnex_dm_callback(void *arg, ibdm_events_t flag) 2840 { 2841 char hca_guid[IBNEX_HCAGUID_STRSZ]; 2842 ibdm_ioc_info_t *ioc_list, *ioc; 2843 ibnex_node_data_t *node_data; 2844 2845 IBTF_DPRINTF_L4("ibnex", "\tdm_callback: attr %p event %x", arg, flag); 2846 2847 switch (flag) { 2848 case IBDM_EVENT_HCA_ADDED: 2849 (void) snprintf(hca_guid, IBNEX_HCAGUID_STRSZ, "%llX", 2850 (*(longlong_t *)arg)); 2851 /* Create a devctl minor node for the HCA's port */ 2852 if (ddi_create_minor_node(ibnex.ibnex_dip, hca_guid, S_IFCHR, 2853 ddi_get_instance(ibnex.ibnex_dip), 2854 DDI_NT_IB_ATTACHMENT_POINT, 0) != DDI_SUCCESS) { 2855 IBTF_DPRINTF_L4("ibnex", "\tdm_callback: failed to " 2856 "create minor node for port w/ guid %s", hca_guid); 2857 } 2858 2859 break; 2860 2861 case IBDM_EVENT_HCA_REMOVED: 2862 (void) snprintf(hca_guid, IBNEX_HCAGUID_STRSZ, "%llX", 2863 (*(longlong_t *)arg)); 2864 ddi_remove_minor_node(ibnex.ibnex_dip, hca_guid); 2865 break; 2866 2867 case IBDM_EVENT_IOC_PROP_UPDATE: 2868 ioc = ioc_list = (ibdm_ioc_info_t *)arg; 2869 if (ioc_list == NULL) 2870 break; 2871 2872 mutex_enter(&ibnex.ibnex_mutex); 2873 while (ioc_list) { 2874 if ((node_data = ibnex_is_node_data_present( 2875 IBNEX_IOC_NODE, ioc_list, 0, 0)) != NULL && 2876 node_data->node_dip != NULL) { 2877 ibnex_update_prop(node_data, ioc_list); 2878 } 2879 ioc_list = ioc_list->ioc_next; 2880 } 2881 mutex_exit(&ibnex.ibnex_mutex); 2882 ibdm_ibnex_free_ioc_list(ioc); 2883 } 2884 } 2885 2886 2887 /* 2888 * ibnex_get_dip_from_guid() 2889 * 2890 * Searches the linked list of the port nodes and returns the dip for 2891 * the of the Port / Node guid requested. 2892 * Returns NULL if not found 2893 */ 2894 int 2895 ibnex_get_dip_from_guid(ib_guid_t guid, int index, ib_pkey_t pkey, 2896 dev_info_t **dip) 2897 { 2898 int node_index; 2899 ib_guid_t node_guid; 2900 ib_pkey_t node_pkey; 2901 ibnex_node_data_t *node_data; 2902 2903 IBTF_DPRINTF_L4("ibnex", 2904 "\tget_dip_from_guid: guid = %llX", guid); 2905 2906 ASSERT(MUTEX_HELD(&ibnex.ibnex_mutex)); 2907 /* Search for a matching entry in internal lists */ 2908 node_data = ibnex.ibnex_port_node_head; 2909 while (node_data) { 2910 node_guid = node_data->node_data.port_node.port_guid; 2911 node_index = node_data->node_data.port_node.port_commsvc_idx; 2912 node_pkey = node_data->node_data.port_node.port_pkey; 2913 if ((node_guid == guid) && (index == node_index) && 2914 (node_pkey == pkey)) { 2915 break; 2916 } 2917 node_data = node_data->node_next; 2918 } 2919 2920 /* matching found with a valid dip */ 2921 if (node_data && node_data->node_dip) { 2922 *dip = node_data->node_dip; 2923 return (IBNEX_SUCCESS); 2924 } else if (node_data && !node_data->node_dip) { /* dip is invalid */ 2925 *dip = NULL; 2926 return (IBNEX_SUCCESS); 2927 } 2928 2929 /* no match found */ 2930 *dip = NULL; 2931 return (IBNEX_FAILURE); 2932 } 2933 2934 2935 /* 2936 * ibnex_comm_svc_init() 2937 * Read the property and cache the values in the global 2938 * structure. 2939 * Check for max allowed length (4 bytes) of service name 2940 * (each element of the property) 2941 * Returns IBNEX_SUCCESS/IBNEX_FAILURE 2942 */ 2943 static ibnex_rval_t 2944 ibnex_comm_svc_init(char *property, ibnex_node_type_t type) 2945 { 2946 int i, len, count; 2947 int ncomm_svcs; 2948 char **comm_svcp; 2949 char **servicep = NULL; 2950 uint_t nservices = 0; 2951 int *valid = NULL; 2952 2953 IBTF_DPRINTF_L4("ibnex", "\tcomm_svc_init : %s property, type = %x", 2954 property, type); 2955 2956 /* lookup the string array property */ 2957 if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, ibnex.ibnex_dip, 2958 DDI_PROP_DONTPASS, property, &servicep, &nservices) != 2959 DDI_PROP_SUCCESS) { 2960 IBTF_DPRINTF_L2("ibnex", "\t%s property undefined", property); 2961 return (IBNEX_SUCCESS); 2962 } 2963 2964 if (nservices) 2965 valid = kmem_zalloc(nservices * sizeof (int), KM_SLEEP); 2966 2967 2968 /* first read the file to get a count of valid service entries */ 2969 for (ncomm_svcs = 0, count = 0; count < nservices; count++) { 2970 int j; 2971 2972 len = strlen(servicep[count]); 2973 if (len == 0 || len > 4) { 2974 IBTF_DPRINTF_L2("ibnex", "\tcomm_svc_init : " 2975 "Service name %s invalid : length %d", 2976 servicep[count], len); 2977 continue; 2978 } 2979 if (ibnex_unique_svcname(servicep[count]) != IBNEX_SUCCESS) { 2980 IBTF_DPRINTF_L2("ibnex", "\tcomm_svc_init : " 2981 "Service name %s invalid : Not unique", 2982 servicep[count]); 2983 continue; 2984 } 2985 2986 /* 2987 * ibnex_unique_svcname checks for uniqueness in service names 2988 * communication services fully initialized. Check uniqueness 2989 * in service names currently initialized. 2990 */ 2991 for (j = 0; j < count; j++) 2992 if (valid[j] && strncmp(servicep[count], 2993 servicep[j], 4) == 0) { 2994 IBTF_DPRINTF_L2("ibnex", "\tcomm_svc_init : " 2995 "Service name %s invalid : Not unique", 2996 servicep[count]); 2997 continue; 2998 } 2999 3000 valid[count] = 1; 3001 ncomm_svcs++; 3002 } 3003 3004 /* if no valid entries found, bailout */ 3005 if (nservices == 0 || ncomm_svcs == 0) { 3006 IBTF_DPRINTF_L4("ibnex", "\tNo %s entries found", property); 3007 ddi_prop_free(servicep); /* free the property */ 3008 if (valid) 3009 kmem_free(valid, nservices * sizeof (int)); 3010 return (IBNEX_SUCCESS); 3011 } 3012 3013 comm_svcp = kmem_zalloc((ncomm_svcs * sizeof (char *)), KM_SLEEP); 3014 if (type == IBNEX_PORT_COMMSVC_NODE) { 3015 ibnex.ibnex_comm_svc_names = comm_svcp; 3016 ibnex.ibnex_num_comm_svcs = ncomm_svcs; 3017 } else if (type == IBNEX_VPPA_COMMSVC_NODE) { 3018 ibnex.ibnex_vppa_comm_svc_names = comm_svcp; 3019 ibnex.ibnex_nvppa_comm_svcs = ncomm_svcs; 3020 } else if (type == IBNEX_HCASVC_COMMSVC_NODE) { 3021 ibnex.ibnex_hcasvc_comm_svc_names = comm_svcp; 3022 ibnex.ibnex_nhcasvc_comm_svcs = ncomm_svcs; 3023 } 3024 3025 /* copy the services into an array of strings */ 3026 for (i = 0, count = 0; count < nservices; count++) { 3027 if (valid[count] == 0) /* Skip invalid ones */ 3028 continue; 3029 comm_svcp[i] = kmem_alloc(len + 1, KM_SLEEP); 3030 (void) strcpy(comm_svcp[i], servicep[count]); 3031 IBTF_DPRINTF_L4("ibnex", 3032 "\t\tService [%d]: %s", i, comm_svcp[i]); 3033 ++i; 3034 } 3035 ddi_prop_free(servicep); 3036 kmem_free(valid, nservices * sizeof (int)); 3037 return (IBNEX_SUCCESS); 3038 } 3039 3040 3041 /* 3042 * ibnex_comm_svc_fini() 3043 * Deallocate all the memory allocated for the communication 3044 * service arrays. 3045 */ 3046 static void 3047 ibnex_comm_svc_fini() 3048 { 3049 int index; 3050 3051 for (index = 0; index < ibnex.ibnex_num_comm_svcs; index++) { 3052 kmem_free(ibnex.ibnex_comm_svc_names[index], 3053 (strlen(ibnex.ibnex_comm_svc_names[index]) + 1)); 3054 } 3055 if (ibnex.ibnex_comm_svc_names) { 3056 kmem_free(ibnex.ibnex_comm_svc_names, 3057 ibnex.ibnex_num_comm_svcs * sizeof (char *)); 3058 } 3059 for (index = 0; index < ibnex.ibnex_nvppa_comm_svcs; index++) { 3060 kmem_free(ibnex.ibnex_vppa_comm_svc_names[index], 3061 strlen(ibnex.ibnex_vppa_comm_svc_names[index]) +1); 3062 } 3063 if (ibnex.ibnex_vppa_comm_svc_names) { 3064 kmem_free(ibnex.ibnex_vppa_comm_svc_names, 3065 ibnex.ibnex_nvppa_comm_svcs * sizeof (char *)); 3066 } 3067 for (index = 0; index < ibnex.ibnex_nhcasvc_comm_svcs; index++) { 3068 kmem_free(ibnex.ibnex_hcasvc_comm_svc_names[index], 3069 strlen(ibnex.ibnex_hcasvc_comm_svc_names[index]) +1); 3070 } 3071 if (ibnex.ibnex_hcasvc_comm_svc_names) { 3072 kmem_free(ibnex.ibnex_hcasvc_comm_svc_names, 3073 ibnex.ibnex_nhcasvc_comm_svcs * sizeof (char *)); 3074 } 3075 ibnex.ibnex_comm_svc_names = NULL; 3076 ibnex.ibnex_num_comm_svcs = 0; 3077 ibnex.ibnex_vppa_comm_svc_names = NULL; 3078 ibnex.ibnex_nvppa_comm_svcs = 0; 3079 ibnex.ibnex_hcasvc_comm_svc_names = NULL; 3080 ibnex.ibnex_nhcasvc_comm_svcs = 0; 3081 } 3082 3083 3084 /* 3085 * ibnex_commsvc_initnode() 3086 * This routine is specific to port/VPPA node creation 3087 * Creates a device node for the comm service specified by commsvc_index 3088 * Creates all the device node properties 3089 * Allocates and initializes the node specific data 3090 * Binds the device driver of the device node 3091 * Returns "dev_info_t" of the child node or NULL in case of failure 3092 * Sets IBNEX_SUCCESS/IBNEX_FAILURE/IBNEX_BUSY in "rval" to reflect 3093 * if the operation was successful, failed or was not performed. 3094 */ 3095 dev_info_t * 3096 ibnex_commsvc_initnode(dev_info_t *parent, ibdm_port_attr_t *port_attr, 3097 int index, int node_type, ib_pkey_t pkey, int *rval, int flag) 3098 { 3099 int ret; 3100 char *svcname; 3101 dev_info_t *cdip; 3102 ibnex_node_data_t *node_data; 3103 3104 ASSERT(MUTEX_HELD(&ibnex.ibnex_mutex)); 3105 3106 *rval = IBNEX_SUCCESS; 3107 3108 /* 3109 * prevent any races 3110 * we have seen this node_data and it has been initialized 3111 * Note that node_dip is already NULL if unconfigure is in 3112 * progress. 3113 */ 3114 node_data = ibnex_is_node_data_present(node_type, (void *)port_attr, 3115 index, pkey); 3116 if (node_data && node_data->node_dip) { 3117 /* 3118 * Return NULL if another configure 3119 * operation is in progress 3120 */ 3121 if (node_data->node_state == IBNEX_CFGADM_CONFIGURING) { 3122 *rval = IBNEX_BUSY; 3123 return (NULL); 3124 } else { 3125 return (node_data->node_dip); 3126 } 3127 } else if (node_data == NULL) { 3128 /* allocate a new ibnex_node_data_t */ 3129 node_data = ibnex_init_child_nodedata(node_type, port_attr, 3130 index, pkey); 3131 } 3132 3133 /* 3134 * Return NULL if another unconfigure operation is in progress 3135 */ 3136 if (node_data->node_state == IBNEX_CFGADM_UNCONFIGURING) { 3137 *rval = IBNEX_BUSY; 3138 return (NULL); 3139 } 3140 3141 ASSERT(node_data->node_state != IBNEX_CFGADM_CONFIGURED); 3142 node_data->node_state = IBNEX_CFGADM_CONFIGURING; 3143 3144 ndi_devi_alloc_sleep(parent, 3145 IBNEX_IBPORT_CNAME, (pnode_t)DEVI_SID_NODEID, &cdip); 3146 3147 node_data->node_dip = cdip; 3148 ddi_set_parent_data(cdip, node_data); 3149 mutex_exit(&ibnex.ibnex_mutex); 3150 3151 switch (node_type) { 3152 case IBNEX_VPPA_COMMSVC_NODE : 3153 svcname = ibnex.ibnex_vppa_comm_svc_names[index]; 3154 break; 3155 case IBNEX_HCASVC_COMMSVC_NODE : 3156 svcname = ibnex.ibnex_hcasvc_comm_svc_names[index]; 3157 break; 3158 case IBNEX_PORT_COMMSVC_NODE : 3159 svcname = ibnex.ibnex_comm_svc_names[index]; 3160 break; 3161 default : 3162 IBTF_DPRINTF_L2("ibnex", "\tcommsvc_initnode:" 3163 "\tInvalid Node type"); 3164 *rval = IBNEX_FAILURE; 3165 ibnex_delete_port_node_data(node_data); 3166 ddi_prop_remove_all(cdip); 3167 ddi_set_parent_data(cdip, NULL); 3168 (void) ndi_devi_free(cdip); 3169 mutex_enter(&ibnex.ibnex_mutex); 3170 return (NULL); 3171 } 3172 3173 if (ibnex_create_port_node_prop(port_attr, cdip, svcname, pkey) == 3174 IBNEX_SUCCESS) { 3175 if (flag == IBNEX_DEVFS_ENUMERATE) 3176 ret = ndi_devi_bind_driver(cdip, 0); 3177 else 3178 ret = ndi_devi_online(cdip, 0); 3179 if (ret == NDI_SUCCESS) { 3180 mutex_enter(&ibnex.ibnex_mutex); 3181 node_data->node_state = IBNEX_CFGADM_CONFIGURED; 3182 return (cdip); 3183 } 3184 } 3185 *rval = IBNEX_FAILURE; 3186 ibnex_delete_port_node_data(node_data); 3187 ddi_prop_remove_all(cdip); 3188 ddi_set_parent_data(cdip, NULL); 3189 (void) ndi_devi_free(cdip); 3190 mutex_enter(&ibnex.ibnex_mutex); 3191 IBTF_DPRINTF_L4("ibnex", "\tcommsvc_initnode: failure exit"); 3192 return (NULL); 3193 } 3194 3195 3196 /* 3197 * ibnex_create_port_node_prop() 3198 * Returns IBNEX_SUCCESS/IBNEX_FAILURE 3199 */ 3200 static int 3201 ibnex_create_port_node_prop(ibdm_port_attr_t *port_attr, 3202 dev_info_t *child_dip, char *srvname, ib_pkey_t pkey) 3203 { 3204 if (ibnex_create_port_compatible_prop(child_dip, 3205 srvname, port_attr) != DDI_PROP_SUCCESS) { 3206 IBTF_DPRINTF_L2("ibnex", 3207 "\tcreate_port_node_prop: compatible update failed"); 3208 return (IBNEX_FAILURE); 3209 } 3210 if ((pkey != 0) && (ndi_prop_update_int(DDI_DEV_T_NONE, child_dip, 3211 "port-pkey", pkey) != DDI_PROP_SUCCESS)) { 3212 IBTF_DPRINTF_L2("ibnex", 3213 "\tcreate_port_node_prop: port-num update failed"); 3214 return (IBNEX_FAILURE); 3215 } 3216 3217 /* 3218 * For HCA_SVC device nodes, port_num will be 0. 3219 * Do not create the "port-number" & "port-guid" properties. 3220 */ 3221 if (port_attr->pa_port_num != 0) { 3222 if (ndi_prop_update_int(DDI_DEV_T_NONE, child_dip, 3223 "port-number", port_attr->pa_port_num) != 3224 DDI_PROP_SUCCESS) { 3225 IBTF_DPRINTF_L2("ibnex", 3226 "\tcreate_port_node_prop: port-num update failed"); 3227 return (IBNEX_FAILURE); 3228 } 3229 if (ndi_prop_update_int64(DDI_DEV_T_NONE, child_dip, 3230 "port-guid", port_attr->pa_port_guid) != 3231 DDI_PROP_SUCCESS) { 3232 IBTF_DPRINTF_L2("ibnex", 3233 "\tcreate_port_node_prop: port-guid update failed"); 3234 return (IBNEX_FAILURE); 3235 } 3236 } else { 3237 ibdm_hca_list_t *hca_list; 3238 3239 /* 3240 * HCA_SVC nodes require "num-ports" & "port-guids" 3241 * properties. 3242 * 3243 * To create the num-ports & port-guids attribute : 3244 * 1. Get HCA list (ibdm_ibnex_get_hca_info_by_guid) 3245 * 2. Form the array of port GUIDs. 3246 */ 3247 if ((hca_list = ibdm_ibnex_get_hca_info_by_guid( 3248 port_attr->pa_hca_guid)) == NULL) { 3249 IBTF_DPRINTF_L2("ibnex", 3250 "\tcreate_port_node_prop: hca_info_by_guid failed"); 3251 return (IBNEX_FAILURE); 3252 } 3253 3254 if (hca_list->hl_nports != 0) { 3255 ib_guid_t *port_guids; 3256 uint8_t portnum; 3257 3258 ASSERT(hca_list->hl_port_attr != NULL); 3259 3260 port_guids = kmem_zalloc( 3261 hca_list->hl_nports * sizeof (ib_guid_t), 3262 KM_SLEEP); 3263 3264 for (portnum = 0; portnum < hca_list->hl_nports; 3265 portnum++) { 3266 port_guids[portnum] = (hca_list-> 3267 hl_port_attr[portnum]).pa_port_guid; 3268 } 3269 3270 if (ndi_prop_update_int64_array(DDI_DEV_T_NONE, 3271 child_dip, "port-guids", (int64_t *)port_guids, 3272 hca_list->hl_nports) != DDI_PROP_SUCCESS) { 3273 IBTF_DPRINTF_L2("ibnex", 3274 "\tcreate_port_node_prop: port-guids " 3275 "create failed"); 3276 kmem_free(port_guids, hca_list->hl_nports * 3277 sizeof (ib_guid_t)); 3278 ibdm_ibnex_free_hca_list(hca_list); 3279 return (IBNEX_FAILURE); 3280 } 3281 kmem_free(port_guids, hca_list->hl_nports * 3282 sizeof (ib_guid_t)); 3283 } 3284 3285 if (ndi_prop_update_int(DDI_DEV_T_NONE, child_dip, 3286 "num-ports", hca_list->hl_nports) != DDI_PROP_SUCCESS) { 3287 IBTF_DPRINTF_L2("ibnex", 3288 "\tcreate_port_node_prop: num-ports update failed"); 3289 ibdm_ibnex_free_hca_list(hca_list); 3290 return (IBNEX_FAILURE); 3291 } 3292 ibdm_ibnex_free_hca_list(hca_list); 3293 } 3294 3295 if (ndi_prop_update_int64(DDI_DEV_T_NONE, child_dip, 3296 "hca-guid", port_attr->pa_hca_guid) != DDI_PROP_SUCCESS) { 3297 IBTF_DPRINTF_L2("ibnex", 3298 "\tcreate_port_node_prop: hca-guid update failed"); 3299 return (IBNEX_FAILURE); 3300 } 3301 if (ndi_prop_update_int(DDI_DEV_T_NONE, child_dip, 3302 "product-id", port_attr->pa_productid) != DDI_PROP_SUCCESS) { 3303 IBTF_DPRINTF_L2("ibnex", 3304 "\tcreate_port_node_prop: product-id update failed"); 3305 return (IBNEX_FAILURE); 3306 } 3307 if (ndi_prop_update_int(DDI_DEV_T_NONE, child_dip, 3308 "vendor-id", port_attr->pa_vendorid) != DDI_PROP_SUCCESS) { 3309 IBTF_DPRINTF_L2("ibnex", 3310 "\tcreate_port_node_prop: vendor-id update failed"); 3311 return (IBNEX_FAILURE); 3312 } 3313 if (ndi_prop_update_int(DDI_DEV_T_NONE, child_dip, "device-version", 3314 port_attr->pa_dev_version) != DDI_PROP_SUCCESS) { 3315 IBTF_DPRINTF_L2("ibnex", 3316 "\tcreate_port_node_prop: device-version update failed"); 3317 return (IBNEX_FAILURE); 3318 } 3319 return (IBNEX_SUCCESS); 3320 } 3321 3322 3323 /* 3324 * ibnex_str2int() 3325 * Utility function that converts a string of length "len" to 3326 * integer. 3327 * Returns IBNEX_SUCCESS/IBNEX_FAILURE 3328 */ 3329 static int 3330 ibnex_str2int(char *c, int len, int *ret) 3331 { 3332 int intval = 0, ii; 3333 3334 IBTF_DPRINTF_L4("ibnex", "\tstr2int: Int string %s..", c); 3335 *ret = IBNEX_SUCCESS; 3336 for (ii = 0; ii < len; ii ++) { 3337 if ((c[ii] >= '0') && (c[ii] <= '9')) 3338 intval = intval * 10 +c[ii] - '0'; 3339 else { 3340 IBTF_DPRINTF_L2("ibnex", 3341 "\tstr2int: Invalid integer string %s..", c); 3342 *ret = IBNEX_FAILURE; 3343 break; 3344 } 3345 } 3346 3347 return (intval); 3348 } 3349 3350 3351 /* 3352 * ibnex_str2hex() 3353 * Utility functions that converts a string of length "len" to 3354 * hex value. Note. This function does not handle strings which 3355 * string length more than 8 bytes. 3356 * 3357 */ 3358 uint64_t 3359 ibnex_str2hex(char *c, int len, int *ret) 3360 { 3361 uint64_t hex = 0, ii; 3362 3363 *ret = IBNEX_SUCCESS; 3364 for (ii = 0; ii < len; ii ++) { 3365 hex = (ii == 0) ? hex : (hex << 4); 3366 if ((c[ii] >= '0') && (c[ii] <= '9')) 3367 hex |= c[ii] - '0'; 3368 else if ((c[ii] >= 'a') && (c[ii] <= 'f')) 3369 hex |= c[ii] - 'a' + 10; 3370 else if ((c[ii] >= 'A') && (c[ii] <= 'F')) 3371 hex |= c[ii] - 'A' + 10; 3372 else { 3373 IBTF_DPRINTF_L2("ibnex", 3374 "\tstr2hex: Invalid integer string"); 3375 *ret = IBNEX_FAILURE; 3376 break; 3377 } 3378 } 3379 3380 return (hex); 3381 } 3382 3383 3384 /* 3385 * ibnex_create_port_compatible_prop() 3386 * Creates 'Compatibility' property for port / HCA_SVC device nodes 3387 * Returns IBNEX_SUCCESS/IBNEX_FAILURE 3388 */ 3389 static int 3390 ibnex_create_port_compatible_prop(dev_info_t *child_dip, 3391 char *comm_svcp, ibdm_port_attr_t *port_attr) 3392 { 3393 int rval, i; 3394 char *temp; 3395 char *compatible[IBNEX_MAX_IBPORT_COMPAT_NAMES]; 3396 3397 IBTF_DPRINTF_L4("ibnex", "\tcreate_port_compatible_prop: Begin"); 3398 /* 3399 * Initialize the "compatible" property string as below: 3400 * Compatible Strings : 3401 * 1. ib.V<vid>P<pid>v<revision>.<service name>. 3402 * 2. ib.V<vid>P<pid>.<service name>. 3403 * 3. ib.<service name> 3404 * Leading zeros must be present 3405 */ 3406 temp = kmem_alloc(IBNEX_MAX_IBPORT_COMPAT_PROP_SZ, KM_SLEEP); 3407 for (i = 0; i < IBNEX_MAX_IBPORT_COMPAT_NAMES; i++) { 3408 compatible[i] = temp + (i * IBNEX_MAX_COMPAT_LEN); 3409 } 3410 3411 (void) snprintf(compatible[0], IBNEX_MAX_COMPAT_LEN, 3412 "ib.V%06xP%08xv%04x.%s", 3413 port_attr->pa_vendorid, port_attr->pa_productid, 3414 port_attr->pa_dev_version, comm_svcp); 3415 (void) snprintf(compatible[1], IBNEX_MAX_COMPAT_LEN, 3416 "ib.V%06xP%08x.%s", 3417 port_attr->pa_vendorid, port_attr->pa_productid, 3418 comm_svcp); 3419 (void) snprintf(compatible[2], IBNEX_MAX_COMPAT_LEN, 3420 "ib.%s", comm_svcp); 3421 3422 for (i = 0; i < IBNEX_MAX_IBPORT_COMPAT_NAMES; i++) 3423 IBTF_DPRINTF_L4("ibnex", "\tcompatible: %s", compatible[i]); 3424 3425 rval = ndi_prop_update_string_array(DDI_DEV_T_NONE, child_dip, 3426 "compatible", (char **)compatible, IBNEX_MAX_IBPORT_COMPAT_NAMES); 3427 3428 if (rval != DDI_PROP_SUCCESS) { 3429 kmem_free(temp, IBNEX_MAX_IBPORT_COMPAT_PROP_SZ); 3430 return (IBNEX_FAILURE); 3431 } 3432 kmem_free(temp, IBNEX_MAX_IBPORT_COMPAT_PROP_SZ); 3433 return (IBNEX_SUCCESS); 3434 } 3435 3436 3437 /* 3438 * ibnex_delete_port_node_data() 3439 * Delete the parent private node data from the linked list 3440 * Deallocate the memory of the port/ioc attributes 3441 * Deallocate the memory of the node data 3442 */ 3443 static void 3444 ibnex_delete_port_node_data(ibnex_node_data_t *node) 3445 { 3446 mutex_enter(&ibnex.ibnex_mutex); 3447 if ((node->node_next == NULL) && (node->node_prev == NULL)) 3448 ibnex.ibnex_port_node_head = NULL; 3449 else if (node->node_next == NULL) 3450 node->node_prev->node_next = NULL; 3451 else if (node->node_prev == NULL) { 3452 node->node_next->node_prev = NULL; 3453 ibnex.ibnex_port_node_head = node->node_next; 3454 } else { 3455 node->node_prev->node_next = node->node_next; 3456 node->node_next->node_prev = node->node_prev; 3457 } 3458 mutex_exit(&ibnex.ibnex_mutex); 3459 kmem_free(node, sizeof (ibnex_node_data_t)); 3460 } 3461 3462 3463 /* 3464 * ibnex_is_node_data_present() 3465 * Checks whether ibnex_node_t is created already 3466 * Returns ibnex_node_data_t if found, otherwise NULL 3467 */ 3468 static ibnex_node_data_t * 3469 ibnex_is_node_data_present(ibnex_node_type_t node_type, void *attr, 3470 int index, ib_pkey_t pkey) 3471 { 3472 ibnex_node_data_t *nodep; 3473 ASSERT(MUTEX_HELD(&ibnex.ibnex_mutex)); 3474 if (node_type == IBNEX_IOC_NODE) { 3475 ibdm_ioc_info_t *ioc_infop = (ibdm_ioc_info_t *)attr; 3476 3477 for (nodep = ibnex.ibnex_ioc_node_head; nodep != NULL; 3478 nodep = nodep->node_next) { 3479 if (nodep->node_data.ioc_node.ioc_guid == 3480 ioc_infop->ioc_profile.ioc_guid) { 3481 return (nodep); 3482 } 3483 } 3484 3485 } else if (node_type == IBNEX_PSEUDO_NODE) { 3486 for (nodep = ibnex.ibnex_pseudo_node_head; nodep; 3487 nodep = nodep->node_next) 3488 if (strcmp(nodep->node_data.pseudo_node. 3489 pseudo_node_addr, (char *)attr) == 0) 3490 return (nodep); 3491 3492 } else { 3493 ibdm_port_attr_t *pattrp = (ibdm_port_attr_t *)attr; 3494 3495 for (nodep = ibnex.ibnex_port_node_head; nodep != NULL; 3496 nodep = nodep->node_next) { 3497 if ((nodep->node_data.port_node.port_guid == 3498 pattrp->pa_port_guid) && 3499 (nodep->node_data.port_node.port_commsvc_idx == 3500 index) && 3501 (nodep->node_data.port_node.port_pkey == pkey)) { 3502 return (nodep); 3503 } 3504 } 3505 } 3506 return (NULL); 3507 } 3508 3509 /* 3510 * ibnex_lookup_unit_address_prop: 3511 * 3512 * If property with name is found, return its value 3513 * otherwise return NULL. 3514 */ 3515 static char * 3516 ibnex_lookup_named_prop(ddi_prop_t *head, char *name) 3517 { 3518 ddi_prop_t *propp; 3519 3520 /* Search the list of properties for name */ 3521 for (propp = head; propp != NULL; propp = propp->prop_next) { 3522 if (strcmp(propp->prop_name, name) != 0) 3523 continue; 3524 /* named property should be valid and have a value */ 3525 if (propp->prop_len <= 1) 3526 break; 3527 return ((char *)propp->prop_val); 3528 } 3529 3530 return ((char *)0); 3531 } 3532 3533 3534 /* 3535 * ibnex_pseudo_initnodes() 3536 * This routine is specific to pseudo node information handling 3537 * Creates a ibnex_node_data_t all pseudo nodes children of ibnex 3538 */ 3539 void 3540 ibnex_pseudo_initnodes() 3541 { 3542 int pnam_len, len; 3543 ibnex_node_data_t *nodep; 3544 struct hwc_spec *list, *spec; 3545 char *node_addr, *temp, *unit_addr; 3546 char *node_type; 3547 3548 IBTF_DPRINTF_L4("ibnex", "\tpseudo_initnodes"); 3549 3550 mutex_enter(&ibnex.ibnex_mutex); 3551 /* 3552 * get a list of all "pseudo" children of "ib". 3553 * for these children initialize/allocate an internal 3554 * ibnex_node_data_t. 3555 */ 3556 list = hwc_get_child_spec(ibnex.ibnex_dip, (major_t)-1); 3557 for (spec = list; spec != NULL; spec = spec->hwc_next) { 3558 if (spec->hwc_devi_sys_prop_ptr == NULL) 3559 continue; 3560 3561 /* Check "ib-node-type" property for IOC .conf */ 3562 node_type = ibnex_lookup_named_prop( 3563 spec->hwc_devi_sys_prop_ptr, "ib-node-type"); 3564 3565 /* "unit-address" property should be present */ 3566 temp = ibnex_lookup_named_prop( 3567 spec->hwc_devi_sys_prop_ptr, "unit-address"); 3568 if (temp == NULL) 3569 continue; 3570 3571 pnam_len = strlen(spec->hwc_devi_name) + strlen(temp) + 2; 3572 3573 node_addr = kmem_zalloc(pnam_len, KM_SLEEP); 3574 3575 (void) snprintf(node_addr, 3576 pnam_len, "%s,%s", spec->hwc_devi_name, temp); 3577 3578 nodep = ibnex_is_node_data_present( 3579 IBNEX_PSEUDO_NODE, (void *)node_addr, 0, 0); 3580 3581 if (nodep) { 3582 kmem_free(node_addr, pnam_len); 3583 continue; 3584 } 3585 3586 nodep = ibnex_init_child_nodedata(IBNEX_PSEUDO_NODE, 3587 (void *)spec->hwc_devi_name, 0, 0); 3588 3589 nodep->node_data.pseudo_node.pseudo_node_addr = node_addr; 3590 (void) snprintf(nodep->node_data. 3591 pseudo_node.pseudo_node_addr, pnam_len, "%s", node_addr); 3592 3593 len = strlen(temp) + 1; 3594 unit_addr = (char *)kmem_alloc(len, KM_SLEEP); 3595 nodep->node_data.pseudo_node.pseudo_unit_addr = unit_addr; 3596 (void) snprintf(unit_addr, len, "%s", temp); 3597 nodep->node_data.pseudo_node.pseudo_unit_addr_len = len; 3598 3599 if (node_type && strcmp(node_type, "merge") == 0) 3600 nodep->node_data.pseudo_node.pseudo_merge_node = 1; 3601 3602 /* Mark this as a new psuedo node */ 3603 nodep->node_data.pseudo_node.pseudo_new_node = 1; 3604 3605 IBTF_DPRINTF_L3("ibnex", "\tpseudo_initnodes: unit addr = %s" 3606 " : drv name = %s", unit_addr, spec->hwc_devi_name); 3607 } 3608 hwc_free_spec_list(list); 3609 mutex_exit(&ibnex.ibnex_mutex); 3610 } 3611 3612 3613 /* 3614 * ibnex_init_child_nodedata() 3615 * 3616 * Allocate memory for the parent private data for device node 3617 * Initializes the parent private child device node data. 3618 * Returns pointer to the parent private data 3619 */ 3620 static ibnex_node_data_t * 3621 ibnex_init_child_nodedata(ibnex_node_type_t node_type, void *attr, int index, 3622 ib_pkey_t pkey) 3623 { 3624 char *devi_name; 3625 ibdm_ioc_info_t *ioc_info; 3626 ibnex_ioc_node_t *ioc_node; 3627 ibnex_node_data_t *node_data; 3628 ib_dm_ioc_ctrl_profile_t *ioc_profile; 3629 3630 ASSERT(MUTEX_HELD(&ibnex.ibnex_mutex)); 3631 3632 node_data = kmem_zalloc(sizeof (ibnex_node_data_t), KM_SLEEP); 3633 node_data->node_state = IBNEX_CFGADM_CONFIGURING; 3634 node_data->node_type = node_type; 3635 3636 if (node_type == IBNEX_IOC_NODE) { 3637 ioc_info = (ibdm_ioc_info_t *)attr; 3638 ioc_profile = &ioc_info->ioc_profile; 3639 ioc_node = &node_data->node_data.ioc_node; 3640 3641 ioc_node->iou_guid = ioc_info->ioc_iou_guid; 3642 ioc_node->ioc_guid = ioc_profile->ioc_guid; 3643 (void) strncpy(ioc_node->ioc_id_string, 3644 (char *)ioc_profile->ioc_id_string, 3645 IB_DM_IOC_ID_STRING_LEN); 3646 ioc_node->ioc_ngids = ioc_info->ioc_nportgids; 3647 3648 node_data->node_next = ibnex.ibnex_ioc_node_head; 3649 node_data->node_prev = NULL; 3650 if (ibnex.ibnex_ioc_node_head) 3651 ibnex.ibnex_ioc_node_head->node_prev = node_data; 3652 ibnex.ibnex_ioc_node_head = node_data; 3653 } else if (node_type == IBNEX_PSEUDO_NODE) { 3654 devi_name = (char *)attr; 3655 node_data->node_data.pseudo_node.pseudo_devi_name = 3656 kmem_zalloc(strlen(devi_name) + 1, KM_SLEEP); 3657 (void) strncpy(node_data->node_data.pseudo_node. 3658 pseudo_devi_name, devi_name, strlen(devi_name)); 3659 node_data->node_next = ibnex.ibnex_pseudo_node_head; 3660 node_data->node_prev = NULL; 3661 if (ibnex.ibnex_pseudo_node_head) 3662 ibnex.ibnex_pseudo_node_head->node_prev = node_data; 3663 ibnex.ibnex_pseudo_node_head = node_data; 3664 } else { 3665 node_data->node_data.port_node.port_hcaguid = 3666 ((ibdm_port_attr_t *)attr)->pa_hca_guid; 3667 node_data->node_data.port_node.port_guid = 3668 ((ibdm_port_attr_t *)attr)->pa_port_guid; 3669 node_data->node_data.port_node.port_num = 3670 ((ibdm_port_attr_t *)attr)->pa_port_num; 3671 node_data->node_data.port_node.port_commsvc_idx = index; 3672 node_data->node_data.port_node.port_pkey = pkey; 3673 3674 node_data->node_next = ibnex.ibnex_port_node_head; 3675 node_data->node_prev = NULL; 3676 if (ibnex.ibnex_port_node_head) 3677 ibnex.ibnex_port_node_head->node_prev = node_data; 3678 ibnex.ibnex_port_node_head = node_data; 3679 } 3680 return (node_data); 3681 } 3682 3683 static int 3684 ibnex_get_eventcookie(dev_info_t *dip, dev_info_t *rdip, 3685 char *eventname, ddi_eventcookie_t *cookie) 3686 { 3687 int rc; 3688 3689 3690 IBTF_DPRINTF_L4("ibnex", "ibnex_get_eventcookie(%p, %p, %s, 0x%X)", 3691 dip, rdip, eventname, cookie); 3692 3693 rc = ndi_event_retrieve_cookie(ibnex.ibnex_ndi_event_hdl, 3694 rdip, eventname, cookie, NDI_EVENT_NOPASS); 3695 if (rc == NDI_SUCCESS) { 3696 mutex_enter(&ibnex.ibnex_mutex); 3697 ibnex.ibnex_prop_update_evt_cookie = *cookie; 3698 mutex_exit(&ibnex.ibnex_mutex); 3699 } 3700 3701 return (rc); 3702 } 3703 3704 static int 3705 ibnex_add_eventcall(dev_info_t *dip, dev_info_t *rdip, 3706 ddi_eventcookie_t cookie, void (*callback)(dev_info_t *dip, 3707 ddi_eventcookie_t cookie, void *arg, void *bus_impldata), 3708 void *arg, ddi_callback_id_t *cb_id) 3709 { 3710 IBTF_DPRINTF_L4("ibnex", 3711 "ibnex_add_eventcall(%p, %p, 0x%X, %p, %p, %p)", 3712 dip, rdip, cookie, callback, arg, cb_id); 3713 3714 return (ndi_event_add_callback(ibnex.ibnex_ndi_event_hdl, 3715 rdip, cookie, callback, arg, NDI_SLEEP, cb_id)); 3716 } 3717 3718 static int 3719 ibnex_remove_eventcall(dev_info_t *dip, ddi_callback_id_t cb_id) 3720 { 3721 IBTF_DPRINTF_L4("ibnex", "ibnex_remove_eventcall(%p, 0x%X)", 3722 dip, cb_id); 3723 3724 return (ndi_event_remove_callback(ibnex.ibnex_ndi_event_hdl, 3725 cb_id)); 3726 } 3727 3728 static int 3729 ibnex_post_event(dev_info_t *dip, dev_info_t *rdip, 3730 ddi_eventcookie_t cookie, void *bus_impldata) 3731 { 3732 IBTF_DPRINTF_L4("ibnex", "ibnex_post_event(%p, %p, 0x%X, %p)", 3733 dip, rdip, cookie, bus_impldata); 3734 3735 return (ndi_event_run_callbacks(ibnex.ibnex_ndi_event_hdl, rdip, 3736 cookie, bus_impldata)); 3737 } 3738 3739 /* 3740 * ibnex_reprobe_ioc_dev() 3741 * 3742 * This could be called as a result of ibt_reprobe_dev request or 3743 * cfgadm command. The function is called from a taskq in case of 3744 * ibt_reprobe_dev and from user context for cfgadm command. 3745 * 3746 * This function reprobes the properties for one IOC dip. 3747 * 3748 * node_reprobe_state should be set before calling this function. 3749 */ 3750 void 3751 ibnex_reprobe_ioc_dev(void *arg) 3752 { 3753 dev_info_t *dip = (dev_info_t *)arg; 3754 ibnex_node_data_t *node_data; 3755 ibnex_ioc_node_t *ioc_data; 3756 ibdm_ioc_info_t *ioc_info; 3757 3758 /* ASSERT(NO_LOCKS_HELD); */ 3759 ASSERT(dip != NULL); 3760 3761 node_data = ddi_get_parent_data(dip); 3762 ASSERT(node_data); 3763 3764 if (node_data->node_dip == NULL) { 3765 IBTF_DPRINTF_L4("ibnex", "reprobe for unconfigured dip"); 3766 mutex_enter(&ibnex.ibnex_mutex); 3767 ibnex_wakeup_reprobe_ioc(node_data, 0); 3768 mutex_exit(&ibnex.ibnex_mutex); 3769 return; 3770 } 3771 ioc_data = &(node_data->node_data.ioc_node); 3772 3773 /* Reprobe the IOC */ 3774 ioc_info = ibdm_ibnex_probe_ioc(ioc_data->iou_guid, ioc_data->ioc_guid, 3775 1); 3776 if (ioc_info == NULL) { 3777 IBTF_DPRINTF_L2("ibnex", "Null ioc_info from reprobe"); 3778 mutex_enter(&ibnex.ibnex_mutex); 3779 ibnex_wakeup_reprobe_ioc(node_data, 1); 3780 mutex_exit(&ibnex.ibnex_mutex); 3781 return; 3782 } 3783 3784 mutex_enter(&ibnex.ibnex_mutex); 3785 if (node_data->node_dip) 3786 ibnex_update_prop(node_data, ioc_info); 3787 ibnex_wakeup_reprobe_ioc(node_data, 0); 3788 mutex_exit(&ibnex.ibnex_mutex); 3789 3790 ibdm_ibnex_free_ioc_list(ioc_info); 3791 } 3792 3793 /* 3794 * ibnex_reprobe_all() 3795 * 3796 * This could be called as a result of cfgadm command. The function 3797 * is called from user context. 3798 * 3799 * This function reprobes the properties for all IOC dips. 3800 * 3801 * ibnex_reprobe_state should be set before calling this function. 3802 */ 3803 void 3804 ibnex_reprobe_ioc_all() 3805 { 3806 ibnex_node_data_t *node_data; 3807 ibdm_ioc_info_t *ioc_info_list, *ioc; 3808 3809 /* ASSERT(NO_LOCKS_HELD); */ 3810 3811 /* Sweep the fabric */ 3812 ioc = ioc_info_list = ibdm_ibnex_get_ioc_list( 3813 IBDM_IBNEX_REPROBE_ALL); 3814 if (ioc_info_list == NULL) { 3815 mutex_enter(&ibnex.ibnex_mutex); 3816 ibnex_wakeup_reprobe_all(); 3817 mutex_exit(&ibnex.ibnex_mutex); 3818 return; 3819 } 3820 3821 mutex_enter(&ibnex.ibnex_mutex); 3822 while (ioc_info_list) { 3823 if ((node_data = ibnex_is_node_data_present(IBNEX_IOC_NODE, 3824 ioc_info_list, 0, 0)) != NULL && 3825 node_data->node_dip != NULL) { 3826 ibnex_update_prop(node_data, ioc_info_list); 3827 } 3828 ioc_info_list = ioc_info_list->ioc_next; 3829 } 3830 ibnex_wakeup_reprobe_all(); 3831 mutex_exit(&ibnex.ibnex_mutex); 3832 3833 ibdm_ibnex_free_ioc_list(ioc); 3834 } 3835 3836 /* 3837 * Update the properties, if it has modified and notify IBTF client. 3838 */ 3839 static void 3840 ibnex_update_prop(ibnex_node_data_t *node_data, ibdm_ioc_info_t *ioc_info) 3841 { 3842 ibt_prop_update_payload_t evt_data; 3843 dev_info_t *dip = node_data->node_dip; 3844 ddi_eventcookie_t evt_cookie; 3845 ibnex_ioc_node_t *ioc; 3846 3847 ASSERT(MUTEX_HELD(&ibnex.ibnex_mutex)); 3848 3849 ASSERT(dip != NULL); 3850 3851 ioc = &node_data->node_data.ioc_node; 3852 3853 evt_data = ioc_info->ioc_info_updated; 3854 evt_cookie = ibnex.ibnex_prop_update_evt_cookie; 3855 3856 /* 3857 * For a disconnected IOC : 3858 * Store the ioc_profile for supplying cfgadm info 3859 * ibdm maintains no info of disconnected IOC 3860 * 3861 * For reconnected IOC : 3862 * ibdm has info of previous service entries 3863 * ioc_profile maintained by ibnexus is used to 3864 * update ib_srv_prop_updated. 3865 * Free the ibnex maintained ioc_profile 3866 */ 3867 if (ioc_info->ioc_nportgids == 0) { 3868 IBTF_DPRINTF_L4("ibnex", 3869 "\tupdate_prop: IOC disconnected"); 3870 ioc->ioc_profile = (ib_dm_ioc_ctrl_profile_t *)kmem_zalloc( 3871 sizeof (ib_dm_ioc_ctrl_profile_t), KM_SLEEP); 3872 bcopy(&ioc_info->ioc_profile, ioc->ioc_profile, 3873 sizeof (ib_dm_ioc_ctrl_profile_t)); 3874 3875 ibnex.ibnex_num_disconnect_iocs++; 3876 } else if (ioc_info->ioc_nportgids != 0 && ioc->ioc_ngids == 0 && 3877 ioc->ioc_profile != NULL) { 3878 IBTF_DPRINTF_L4("ibnex", 3879 "\tupdate_prop: IOC reconnected"); 3880 if (ioc->ioc_profile->ioc_service_entries != 3881 ioc_info->ioc_profile.ioc_service_entries) 3882 evt_data.ib_srv_prop_updated = 1; 3883 3884 ibnex.ibnex_num_disconnect_iocs--; 3885 kmem_free(ioc->ioc_profile, sizeof (ib_dm_ioc_ctrl_profile_t)); 3886 ioc->ioc_profile = NULL; 3887 } 3888 3889 /* Update the properties that have changed */ 3890 mutex_exit(&ibnex.ibnex_mutex); 3891 if (evt_data.ib_gid_prop_updated) { 3892 if (ibnex_create_ioc_portgid_prop(dip, ioc_info) != 3893 IBNEX_SUCCESS) { 3894 mutex_enter(&ibnex.ibnex_mutex); 3895 return; 3896 } 3897 } 3898 if (evt_data.ib_srv_prop_updated) { 3899 if (ioc_info->ioc_profile.ioc_service_entries != 0 && 3900 (ibnex_create_ioc_srv_props(dip, ioc_info) != 3901 IBNEX_SUCCESS)) { 3902 mutex_enter(&ibnex.ibnex_mutex); 3903 return; 3904 } else if (ioc_info->ioc_profile.ioc_service_entries == 0) { 3905 (void) ndi_prop_remove(DDI_DEV_T_NONE, dip, 3906 "service-id"); 3907 (void) ndi_prop_remove(DDI_DEV_T_NONE, dip, 3908 "service-name"); 3909 } 3910 } 3911 mutex_enter(&ibnex.ibnex_mutex); 3912 ioc->ioc_ngids = ioc_info->ioc_nportgids; 3913 3914 /* 3915 * Post an event if : 3916 * 1. Properites have changed or NOTIFY_ALWAYS is set. 3917 * 2. child dip is configured and a valid cookie for 3918 * IB_PROP_UPDATE_EVENT. 3919 */ 3920 if ((evt_data.ib_prop_updated != 0 || 3921 (node_data->node_reprobe_state & 3922 IBNEX_NODE_REPROBE_NOTIFY_ALWAYS)) && 3923 ((node_data->node_state == IBNEX_CFGADM_CONFIGURED) && 3924 (evt_cookie != NULL))) { 3925 mutex_exit(&ibnex.ibnex_mutex); 3926 3927 if (ndi_post_event(ibnex.ibnex_dip, dip, 3928 evt_cookie, &evt_data) != NDI_SUCCESS) 3929 IBTF_DPRINTF_L2("ibnex", 3930 "\tndi_post_event failed\n"); 3931 3932 mutex_enter(&ibnex.ibnex_mutex); 3933 } 3934 3935 /* 3936 * Cleanup node_reprobe_state, for ibt_reprobe_dev 3937 * requests, when reprobe all / node reprobe is in 3938 * progress. ibnex_reprobe_ioc_dev is not called 3939 * in this case. 3940 */ 3941 if (node_data->node_reprobe_state == 3942 IBNEX_NODE_REPROBE_NOTIFY_ALWAYS) 3943 ibnex_wakeup_reprobe_ioc(node_data, 0); 3944 } 3945 3946 static ibnex_rval_t 3947 ibnex_unique_svcname(char *svcname) 3948 { 3949 int i; 3950 3951 /* Check Port Services */ 3952 for (i = 0; i < ibnex.ibnex_num_comm_svcs; i++) 3953 if (ibnex.ibnex_comm_svc_names[i] && strncmp(svcname, 3954 ibnex.ibnex_comm_svc_names[i], 4) == 0) 3955 return (IBNEX_FAILURE); 3956 3957 /* Check VPPA Services */ 3958 for (i = 0; i < ibnex.ibnex_nvppa_comm_svcs; i++) 3959 if (ibnex.ibnex_vppa_comm_svc_names[i] && strncmp(svcname, 3960 ibnex.ibnex_vppa_comm_svc_names[i], 4) == 0) 3961 return (IBNEX_FAILURE); 3962 3963 /* Check HCA_SVC Services */ 3964 for (i = 0; i < ibnex.ibnex_nhcasvc_comm_svcs; i++) 3965 if (ibnex.ibnex_hcasvc_comm_svc_names[i] && strncmp(svcname, 3966 ibnex.ibnex_hcasvc_comm_svc_names[i], 4) == 0) 3967 return (IBNEX_FAILURE); 3968 3969 return (IBNEX_SUCCESS); 3970 } 3971 3972 static void 3973 ibnex_handle_reprobe_dev(void *arg) 3974 { 3975 dev_info_t *dip = (dev_info_t *)arg; 3976 ibnex_node_data_t *node_data; 3977 3978 ASSERT(dip != NULL); 3979 node_data = ddi_get_parent_data(dip); 3980 ASSERT(node_data); 3981 3982 /* 3983 * Return success if: 3984 * 1. Reprobe for all nodes are in progress 3985 * 2. Reprobe for this node is in progress. 3986 * The reprobe in progress will complete eventually and 3987 * update the properties, if required. 3988 */ 3989 mutex_enter(&ibnex.ibnex_mutex); 3990 if (ibnex.ibnex_reprobe_state != 0 || 3991 node_data->node_reprobe_state != 0) { 3992 /* 3993 * Setting NOTIFY_ALWAYS to ensure that 3994 * DDI event is delivered always for 3995 * ibt_reprobe_dev 3996 */ 3997 node_data->node_reprobe_state |= 3998 IBNEX_NODE_REPROBE_NOTIFY_ALWAYS; 3999 mutex_exit(&ibnex.ibnex_mutex); 4000 return; 4001 } 4002 node_data->node_reprobe_state = 4003 IBNEX_NODE_REPROBE_NOTIFY_ALWAYS; 4004 mutex_exit(&ibnex.ibnex_mutex); 4005 ibnex_reprobe_ioc_dev(arg); 4006 } 4007 4008 4009 /* 4010 * MPxIO pathmangement routines. Currently IB nexus does not support 4011 * any kind of pathmangement. So, just return success to make MPxIO 4012 * framework happy. 4013 */ 4014 /*ARGSUSED*/ 4015 static int 4016 ib_vhci_pi_init(dev_info_t *dip, mdi_pathinfo_t *pip, int flag) 4017 { 4018 IBTF_DPRINTF_L4("ibnex", "\tpi_init: dip %p pip %p", dip, pip); 4019 return (MDI_SUCCESS); 4020 } 4021 4022 4023 /*ARGSUSED*/ 4024 static int 4025 ib_vhci_pi_uninit(dev_info_t *dip, mdi_pathinfo_t *pip, int flag) 4026 { 4027 IBTF_DPRINTF_L4("ibnex", "\tpi_uninit: dip %p pip %p", dip, pip); 4028 return (MDI_SUCCESS); 4029 } 4030 4031 4032 /*ARGSUSED*/ 4033 static int 4034 ib_vhci_pi_state_change(dev_info_t *dip, mdi_pathinfo_t *pip, 4035 mdi_pathinfo_state_t state, uint32_t arg1, int arg2) 4036 { 4037 IBTF_DPRINTF_L4("ibnex", 4038 "\tpi_state_change: dip %p pip %p state %x", dip, pip, state); 4039 return (MDI_SUCCESS); 4040 } 4041 4042 4043 /*ARGSUSED*/ 4044 static int 4045 ib_vhci_failover(dev_info_t *dip1, dev_info_t *dip2, int arg) 4046 { 4047 return (MDI_SUCCESS); 4048 } 4049 4050 4051 static int 4052 ibnex_bus_power(dev_info_t *parent, void *impl_arg, 4053 pm_bus_power_op_t op, void *arg, void *result) 4054 { 4055 4056 int ret = DDI_SUCCESS; 4057 4058 IBTF_DPRINTF_L4("ibnex", "\tbus_power: begin: op = %d", op); 4059 4060 /* 4061 * Generic processing in MPxIO framework 4062 */ 4063 ret = mdi_bus_power(parent, impl_arg, op, arg, result); 4064 4065 switch (ret) { 4066 case MDI_SUCCESS: 4067 ret = DDI_SUCCESS; 4068 break; 4069 case MDI_FAILURE: 4070 ret = DDI_FAILURE; 4071 break; 4072 default: 4073 break; 4074 } 4075 4076 return (ret); 4077 } 4078 4079 4080 /* 4081 * If enumerated as a child of IB Nexus / VHCI, call mdi_vhci_bus_config. 4082 * ndi_devi_enter is not held during this call. mdi_vhci_bus_config() 4083 * will have called ndi_busop_bus_config(), no need for the caller to call 4084 * ndi_busop_bus_config() again. 4085 * 4086 * If enumerated as a child of HCA device, this could be a case for 4087 * Sparc boot or device enumeration from PHCI, driven by MDI. 4088 * Hold parent lock (ndi_devi_enter). The caller will have to call 4089 * ndi_busop_bus_config() if this function returns SUCCESS. 4090 * 4091 * if the device name contains ":port", then it is the Sparc boot case. 4092 * Handle this as before. 4093 * 4094 * If the device name does *not* contain the ":port", then : 4095 * 1. ibdm to probe IOC 4096 * 2. Create a pathinfo only if the IOC is reachable from the parent dip. 4097 */ 4098 static int 4099 ibnex_ioc_bus_config_one(dev_info_t **pdipp, uint_t flag, 4100 ddi_bus_config_op_t op, void *devname, dev_info_t **child, 4101 int *need_bus_config) 4102 { 4103 int ret = DDI_FAILURE, circ; 4104 dev_info_t *pdip = *pdipp; 4105 ib_guid_t iou_guid, ioc_guid; 4106 char *ioc_guid_str; 4107 4108 4109 *need_bus_config = 1; 4110 4111 if (pdip == ibnex.ibnex_dip) { 4112 if (ibnex_devname_to_node_n_ioc_guids( 4113 (char *)devname, &iou_guid, &ioc_guid, 4114 &ioc_guid_str) != IBNEX_SUCCESS) { 4115 return (ret); 4116 } 4117 ret = mdi_vhci_bus_config(pdip, flag, op, devname, child, 4118 ioc_guid_str); 4119 kmem_free(ioc_guid_str, strlen(ioc_guid_str) + 1); 4120 if (ret == MDI_SUCCESS) 4121 *need_bus_config = 0; 4122 } else { 4123 mdi_devi_enter(pdip, &circ); 4124 if (strstr((char *)devname, ":port=") != NULL) { 4125 ret = ibnex_config_root_iocnode(pdip, devname); 4126 ASSERT(ibnex.ibnex_dip == NULL); 4127 *pdipp = ibnex.ibnex_dip; 4128 } else { 4129 ret = ibnex_config_ioc_node(devname, pdip); 4130 } 4131 mdi_devi_exit(pdip, circ); 4132 } 4133 return (ret); 4134 } 4135 4136 static int 4137 ibnex_is_merge_node(dev_info_t *child) 4138 { 4139 char *node; 4140 int ret = IBNEX_INVALID_NODE; 4141 4142 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, child, 4143 DDI_PROP_DONTPASS, "ib-node-type", &node) != 4144 DDI_PROP_SUCCESS) { 4145 return (IBNEX_FAILURE); 4146 } 4147 4148 if (node != NULL && *node != 0) { 4149 if (strcmp(node, "merge") == 0) 4150 ret = IBNEX_SUCCESS; 4151 else { 4152 IBTF_DPRINTF_L4("ibnex", 4153 "\tis_merge_node: ib-node-type = %s", node); 4154 } 4155 } 4156 4157 ddi_prop_free(node); 4158 return (ret); 4159 } 4160 4161 /* 4162 * Checks if the dn_head for the driver has already 4163 * initialized by the prom tree. 4164 */ 4165 void 4166 ibnex_hw_in_dev_tree(char *driver_name) 4167 { 4168 major_t major; 4169 4170 IBTF_DPRINTF_L4("ibnex", "\thw_in_dev_tree(%s)", driver_name); 4171 4172 if (devnamesp == NULL) 4173 return; 4174 4175 major = ddi_name_to_major(driver_name); 4176 if (major == -1) 4177 return; 4178 4179 if (devnamesp[major].dn_head != (dev_info_t *)NULL) 4180 ibnex_hw_status = IBNEX_HW_IN_DEVTREE; 4181 } 4182