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