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