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