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