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