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.
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.
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]
22 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
26 * Copyright (c) 2018, Joyent, Inc.
30 * The InfiniBand Nexus driver (IB nexus) is a bus nexus driver for IB bus.
31 * It supports Port nodes, Virtual Physical Point of Attachment nodes (VPPA)
32 * for HCAs registered with IBTL and IOC nodes for all the IOCs present in
33 * the IB fabric (that are accessible to the host). It also supports Pseudo
34 * device children to be enumerated using their .conf file(s). All Port nodes
35 * and VPPA nodes are children of HCA drivers. All the IOC nodes and the Pseudo
36 * device nodes are children of the IB nexus driver.
38 * IB nexus driver provides bus nexus entry points to all the HCA drivers.
40 * IB nexus driver registers with InfiniBand Device Manager (IBDM) to get
41 * information about all the HCA ports and I/O Controllers (IOCs) connected
42 * to the IB fabric. Based on that information, IB nexus will create all the
48 #include <sys/modctl.h>
49 #include <sys/taskq.h>
50 #include <sys/mdi_impldefs.h>
51 #include <sys/sunmdi.h>
52 #include <sys/sunpm.h>
53 #include <sys/ib/mgt/ibdm/ibdm_impl.h>
54 #include <sys/ib/ibnex/ibnex.h>
55 #include <sys/ib/ibnex/ibnex_devctl.h>
56 #include <sys/ib/ibtl/ibti.h>
57 #include <sys/ib/ibtl/impl/ibtl_ibnex.h>
59 #include <sys/hwconf.h>
60 #include <sys/fs/dv_node.h>
62 /* Function prototypes */
63 static int ibnex_attach(dev_info_t
*, ddi_attach_cmd_t
);
64 static int ibnex_getinfo(dev_info_t
*, ddi_info_cmd_t
,
66 static int ibnex_detach(dev_info_t
*, ddi_detach_cmd_t
);
67 int ibnex_busctl(dev_info_t
*,
68 dev_info_t
*, ddi_ctl_enum_t
, void *, void *);
69 int ibnex_map_fault(dev_info_t
*,
70 dev_info_t
*, struct hat
*, struct seg
*,
71 caddr_t
, struct devpage
*, pfn_t
, uint_t
, uint_t
);
72 static int ibnex_init_child(dev_info_t
*);
73 static ibnex_rval_t
ibnex_comm_svc_init(char *, ibnex_node_type_t
);
74 static void ibnex_comm_svc_fini();
75 dev_info_t
*ibnex_commsvc_initnode(dev_info_t
*,
76 ibdm_port_attr_t
*, int, int, ib_pkey_t
, int *,
78 static void ibnex_delete_port_node_data(ibnex_node_data_t
*);
79 int ibnex_get_dip_from_guid(ib_guid_t
, int,
80 ib_pkey_t
, dev_info_t
**);
81 int ibnex_get_node_and_dip_from_guid(ib_guid_t
, int,
82 ib_pkey_t
, ibnex_node_data_t
**, dev_info_t
**);
83 static ibnex_node_data_t
*ibnex_is_node_data_present(ibnex_node_type_t
,
84 void *, int, ib_pkey_t
);
85 static ibnex_node_data_t
*ibnex_init_child_nodedata(ibnex_node_type_t
, void *,
87 static int ibnex_create_port_node_prop(ibdm_port_attr_t
*,
88 dev_info_t
*, char *, ib_pkey_t
);
89 void ibnex_dm_callback(void *, ibdm_events_t
);
90 static int ibnex_create_port_compatible_prop(dev_info_t
*,
91 char *, ibdm_port_attr_t
*);
92 static int ibnex_create_ioc_srv_props(
93 dev_info_t
*, ibdm_ioc_info_t
*);
94 static int ibnex_get_eventcookie(dev_info_t
*,
95 dev_info_t
*, char *, ddi_eventcookie_t
*);
96 static int ibnex_add_eventcall(dev_info_t
*, dev_info_t
*,
97 ddi_eventcookie_t
, void (*)(dev_info_t
*,
98 ddi_eventcookie_t
, void *, void *),
99 void *arg
, ddi_callback_id_t
*cb_id
);
100 static int ibnex_remove_eventcall(dev_info_t
*,
102 static int ibnex_post_event(dev_info_t
*, dev_info_t
*,
103 ddi_eventcookie_t
, void *);
104 static int ibnex_bus_config(dev_info_t
*, uint_t
,
105 ddi_bus_config_op_t
, void *, dev_info_t
**);
106 static int ibnex_bus_unconfig(dev_info_t
*,
107 uint_t
, ddi_bus_config_op_t
, void *);
108 dev_info_t
*ibnex_config_port_node(dev_info_t
*, char *);
109 int ibnex_get_pkey_commsvc_index_portnum(
110 char *, int *, ib_pkey_t
*, uint8_t *);
111 void ibnex_config_all_children(dev_info_t
*);
112 static int ibnex_devname_to_portnum(char *, uint8_t *);
113 void ibnex_create_vppa_nodes(dev_info_t
*, ibdm_port_attr_t
*);
114 void ibnex_create_port_nodes(
115 dev_info_t
*, ibdm_port_attr_t
*);
116 void ibnex_create_hcasvc_nodes(
117 dev_info_t
*, ibdm_port_attr_t
*);
118 static int ibnex_config_root_iocnode(dev_info_t
*, char *);
119 static int ibnex_devname2port(char *, int *);
120 static int ibnex_config_ioc_node(char *, dev_info_t
*);
121 static int ibnex_devname_to_node_n_ioc_guids(
122 char *, ib_guid_t
*, ib_guid_t
*, char **);
123 static void ibnex_ioc_node_cleanup();
124 static void ibnex_delete_ioc_node_data(ibnex_node_data_t
*);
125 int ibnex_ioc_initnode_all_pi(ibdm_ioc_info_t
*);
126 static int ibnex_ioc_initnode_pdip(ibnex_node_data_t
*,
127 ibdm_ioc_info_t
*, dev_info_t
*);
128 static int ibnex_create_ioc_node_prop(
129 ibdm_ioc_info_t
*, dev_info_t
*);
130 static int ibnex_create_ioc_compatible_prop(
131 dev_info_t
*, ib_dm_ioc_ctrl_profile_t
*);
132 uint64_t ibnex_str2hex(char *, int, int *);
133 int ibnex_str2int(char *, int, int *);
134 static int ibnex_create_ioc_portgid_prop(
135 dev_info_t
*, ibdm_ioc_info_t
*);
136 static void ibnex_wakeup_reprobe_ioc(ibnex_node_data_t
*, int);
137 static void ibnex_wakeup_reprobe_all();
138 ibt_status_t
ibnex_ibtl_callback(ibtl_ibnex_cb_args_t
*);
139 void ibnex_pseudo_initnodes(void);
140 static char *ibnex_lookup_named_prop(ddi_prop_t
*, char *);
141 static void ibnex_pseudo_node_cleanup(void);
142 static int ibnex_name_child(dev_info_t
*, char *, int);
143 static int ibnex_name_pseudo_child(dev_info_t
*, char *);
145 void ibnex_reprobe_ioc_dev(void *);
146 void ibnex_reprobe_ioc_all();
147 static void ibnex_update_prop(ibnex_node_data_t
*,
149 static ibnex_rval_t
ibnex_unique_svcname(char *);
150 static void ibnex_handle_reprobe_dev(void *arg
);
152 extern int ibnex_open(dev_t
*, int, int, cred_t
*);
153 extern int ibnex_close(dev_t
, int, int, cred_t
*);
154 extern int ibnex_ioctl(dev_t
, int, intptr_t, int, cred_t
*, int *);
155 extern int ibnex_offline_childdip(dev_info_t
*);
157 static int ibnex_ioc_create_pi(
158 ibdm_ioc_info_t
*, ibnex_node_data_t
*,
159 dev_info_t
*, int *);
160 static int ibnex_bus_power(dev_info_t
*, void *,
161 pm_bus_power_op_t
, void *, void *);
162 int ibnex_pseudo_create_all_pi(ibnex_node_data_t
*);
163 static int ibnex_pseudo_create_pi_pdip(ibnex_node_data_t
*,
165 int ibnex_pseudo_config_one(
166 ibnex_node_data_t
*, char *, dev_info_t
*);
167 int ibnex_pseudo_mdi_config_one(int, void *, dev_info_t
**,
169 static void ibnex_config_pseudo_all(dev_info_t
*);
170 int ibnex_ioc_bus_config_one(dev_info_t
**, uint_t
,
171 ddi_bus_config_op_t
, void *, dev_info_t
**, int *);
172 static int ibnex_is_merge_node(dev_info_t
*);
173 static void ibnex_hw_in_dev_tree(char *);
174 static int ibnex_ioc_config_from_pdip(ibdm_ioc_info_t
*,
176 static int ibnex_ioc_pi_exists(ibnex_node_data_t
*, dev_info_t
*);
177 static int ibnex_ioc_pi_reachable(ibdm_ioc_info_t
*,
180 extern void ibnex_handle_hca_attach(void *);
182 extern struct bus_ops ibnex_ci_busops
;
184 * Prototype declarations for the VHCI options
187 * Functions registered with the mpxio framework
189 static int ib_vhci_pi_init(dev_info_t
*, mdi_pathinfo_t
*, int);
190 static int ib_vhci_pi_uninit(dev_info_t
*, mdi_pathinfo_t
*, int);
191 static int ib_vhci_pi_state_change(dev_info_t
*, mdi_pathinfo_t
*,
192 mdi_pathinfo_state_t
, uint32_t, int);
193 static int ib_vhci_failover(dev_info_t
*, dev_info_t
*, int);
196 static mdi_vhci_ops_t ibnex_vhci_ops
= {
200 ib_vhci_pi_state_change
,
206 * The bus_ops structure defines the capabilities of IB nexus driver.
207 * IB nexus drivers does not support any DMA operations for its children
208 * as there is no such concept in Infiniband. All the memory operations
209 * and DMA operations required by the child drivers can be performed using
212 struct bus_ops ibnex_bus_ops
= {
214 nullbusmap
, /* bus_map */
215 NULL
, /* bus_get_intrspec */
216 NULL
, /* bus_add_intrspec */
217 NULL
, /* bus_remove_intrspec */
218 ibnex_map_fault
, /* Map Fault */
219 ddi_no_dma_map
, /* DMA related entry points */
227 ibnex_busctl
, /* bus_ctl */
228 ddi_bus_prop_op
, /* bus_prop_op */
229 ibnex_get_eventcookie
, /* bus_get_eventcookie */
230 ibnex_add_eventcall
, /* bus_add_eventcall */
231 ibnex_remove_eventcall
, /* bus_remove_eventcall */
232 ibnex_post_event
, /* bus_post_event */
234 ibnex_bus_config
, /* bus config */
235 ibnex_bus_unconfig
, /* bus unconfig */
236 NULL
, /* bus fm init */
237 NULL
, /* bus fm fini */
238 NULL
, /* bus fm access enter */
239 NULL
, /* bus fm access exit */
240 ibnex_bus_power
/* bus power */
244 static struct cb_ops ibnex_cbops
= {
245 ibnex_open
, /* open */
246 ibnex_close
, /* close */
247 nodev
, /* strategy */
252 ibnex_ioctl
, /* ioctl */
257 ddi_prop_op
, /* prop_op */
261 nodev
, /* int (*cb_aread)() */
262 nodev
/* int (*cb_awrite)() */
267 * Note: ddi_no_info needs to change during devfs time frame. The drivers
268 * with 1 to 1 mapping between minor node and instance should use
269 * ddi_1to1_info. (See bug id 4424752)
271 static struct dev_ops ibnex_ops
= {
272 DEVO_REV
, /* devo_rev, */
274 ibnex_getinfo
, /* info */
275 nulldev
, /* identify */
277 ibnex_attach
, /* attach */
278 ibnex_detach
, /* detach */
280 &ibnex_cbops
, /* driver ops - devctl interfaces */
281 &ibnex_bus_ops
, /* bus operations */
283 ddi_quiesce_not_needed
, /* quiesce */
286 /* Module linkage information for the kernel. */
287 static struct modldrv modldrv
= {
288 &mod_driverops
, /* Driver module */
289 "IB nexus", /* Driver name and version */
290 &ibnex_ops
, /* driver ops */
293 static struct modlinkage modlinkage
= {
294 MODREV_1
, (void *)&modldrv
, NULL
298 * Global per-instance IB Nexus data.
299 * There is only one instance of IB Nexus supported.
305 _NOTE(MUTEX_PROTECTS_DATA(ibnex
.ibnex_mutex
, ibnex_s
))
306 _NOTE(DATA_READABLE_WITHOUT_LOCK(ibnex
.ibnex_num_comm_svcs
307 ibnex
.ibnex_comm_svc_names ibnex
.ibnex_nvppa_comm_svcs
308 ibnex
.ibnex_vppa_comm_svc_names ibnex
.ibnex_nhcasvc_comm_svcs
309 ibnex
.ibnex_hcasvc_comm_svc_names ibnex
.ibnex_ioc_list
))
310 _NOTE(MUTEX_PROTECTS_DATA(ibnex
.ibnex_mutex
, ibnex_node_data_s
))
311 _NOTE(LOCK_ORDER(ibdm
.ibdm_hl_mutex ibnex
.ibnex_mutex
))
313 /* The port settling time in seconds */
314 int ibnex_port_settling_time
= 8;
316 /* create an array of properties supported, easier to add new ones here */
317 static struct ibnex_property
{
319 ibnex_node_type_t type
;
320 } ibnex_properties
[] = {
321 { "port-svc-list", IBNEX_PORT_COMMSVC_NODE
},
322 { "vppa-svc-list", IBNEX_VPPA_COMMSVC_NODE
},
323 { "hca-svc-list", IBNEX_HCASVC_COMMSVC_NODE
}
326 #define N_IBNEX_PROPS (sizeof (ibnex_properties))/ \
327 (sizeof (struct ibnex_property))
331 * Single event, event name defined in ibti_common.h.
332 * Event posted to specific child handler. Event posted
333 * at kernel priority.
335 static ndi_event_definition_t ibnex_ndi_event_defs
[] = {
336 {IB_EVENT_TAG_PROP_UPDATE
, IB_PROP_UPDATE_EVENT
, EPL_KERNEL
,
337 NDI_EVENT_POST_TO_TGT
}
340 #define IB_N_NDI_EVENTS \
341 (sizeof (ibnex_ndi_event_defs) / sizeof (ndi_event_definition_t))
343 static ndi_event_set_t ib_ndi_events
= {
344 NDI_EVENTS_REV1
, IB_N_NDI_EVENTS
, ibnex_ndi_event_defs
};
345 static int ibnex_hw_status
= IBNEX_DEVTREE_NOT_CHECKED
;
350 * Loadable module init, called before any other module.
356 char **hca_driver_list
;
359 if (ibnex_hw_status
== IBNEX_DEVTREE_NOT_CHECKED
) {
360 ibnex_hw_status
= IBNEX_HW_NOT_IN_DEVTREE
;
361 hca_driver_list
= mdi_get_phci_driver_list("ib", &ndrivers
);
362 for (i
= 0; i
< ndrivers
; i
++) {
363 ibnex_hw_in_dev_tree(hca_driver_list
[i
]);
364 if (ibnex_hw_status
== IBNEX_HW_IN_DEVTREE
)
367 mdi_free_phci_driver_list(hca_driver_list
, ndrivers
);
371 * IB Nexus _init can be called while force attaching
372 * IB Nexus driver or when a HCA is hotplugged.
374 * If IB HW is not in device tree or if no HCA driver
375 * has been attached, fail IB Nexus _init().
377 if (ibnex_hw_status
== IBNEX_HW_NOT_IN_DEVTREE
&&
378 ibt_hw_is_present() == 0) {
379 IBTF_DPRINTF_L4("ibnex", "\t_init: NO IB HW");
380 return (DDI_FAILURE
);
383 IBTF_DPRINTF_L4("ibnex", "\t_init");
384 mutex_init(&ibnex
.ibnex_mutex
, NULL
, MUTEX_DRIVER
, NULL
);
385 cv_init(&ibnex
.ibnex_reprobe_cv
, NULL
, CV_DRIVER
, NULL
);
386 cv_init(&ibnex
.ibnex_ioc_list_cv
, NULL
, CV_DRIVER
, NULL
);
387 if ((error
= mod_install(&modlinkage
)) != 0) {
388 IBTF_DPRINTF_L2("ibnex", "\t_init: mod_install failed");
389 mutex_destroy(&ibnex
.ibnex_mutex
);
390 cv_destroy(&ibnex
.ibnex_reprobe_cv
);
391 cv_destroy(&ibnex
.ibnex_ioc_list_cv
);
393 ibdm_ibnex_register_callback(ibnex_dm_callback
);
394 ibtl_ibnex_register_callback(ibnex_ibtl_callback
);
402 * Prepares a module for unloading.
409 IBTF_DPRINTF_L4("ibnex", "\t_fini");
410 if ((error
= mod_remove(&modlinkage
)) != 0) {
413 ibdm_ibnex_unregister_callback();
414 ibtl_ibnex_unregister_callback();
415 mutex_destroy(&ibnex
.ibnex_mutex
);
416 cv_destroy(&ibnex
.ibnex_reprobe_cv
);
417 cv_destroy(&ibnex
.ibnex_ioc_list_cv
);
424 * Returns information about loadable module.
427 _info(struct modinfo
*modinfop
)
429 IBTF_DPRINTF_L4("ibnex", "\t_info");
430 return (mod_info(&modlinkage
, modinfop
));
436 * Configure and attach an instance of the IB Nexus driver
437 * Only one instance of IB Nexus is supported
438 * Create a minor node for cfgadm purpose
439 * Initialize communication services
440 * Register callback with IBDM
441 * Register callback with IBTL
444 ibnex_attach(dev_info_t
*dip
, ddi_attach_cmd_t cmd
)
447 int instance
= ddi_get_instance(dip
);
449 IBTF_DPRINTF_L4("ibnex", "\tattach: device = %p cmd = %x)", dip
, cmd
);
455 IBTF_DPRINTF_L4("ibnex", "\tattach: RESUME");
456 return (DDI_SUCCESS
);
458 return (DDI_FAILURE
);
461 /* Fail attach for more than one instance */
462 mutex_enter(&ibnex
.ibnex_mutex
);
463 if (ibnex
.ibnex_dip
!= NULL
) {
464 mutex_exit(&ibnex
.ibnex_mutex
);
465 return (DDI_FAILURE
);
467 mutex_exit(&ibnex
.ibnex_mutex
);
470 * Create a IB nexus taskq
473 ibnex
.ibnex_taskq_id
= ddi_taskq_create(dip
,
474 "ibnex-enum-taskq", 1, TASKQ_DEFAULTPRI
, 0);
475 if (ibnex
.ibnex_taskq_id
== NULL
) {
476 IBTF_DPRINTF_L2("ibnex",
477 "\tattach: ddi_taskq_create() failed");
478 return (DDI_FAILURE
);
482 /* Register with MPxIO framework */
484 if (mdi_vhci_register(MDI_HCI_CLASS_IB
, dip
, &ibnex_vhci_ops
, 0)
486 IBTF_DPRINTF_L2("ibnex",
487 "\tattach: mdi_vhci_register() failed");
488 (void) ddi_taskq_destroy(ibnex
.ibnex_taskq_id
);
489 ibnex
.ibnex_taskq_id
= NULL
;
490 return (DDI_FAILURE
);
495 * Create the "fabric" devctl minor-node for IB DR support.
496 * The minor number for the "devctl" node is in the same format
497 * as the AP minor nodes.
499 if (ddi_create_minor_node(dip
, IBNEX_FABRIC
, S_IFCHR
, instance
,
500 DDI_NT_IB_ATTACHMENT_POINT
, 0) != DDI_SUCCESS
) {
501 IBTF_DPRINTF_L2("ibnex",
502 "\tattach: failed to create fabric minornode");
503 (void) ddi_taskq_destroy(ibnex
.ibnex_taskq_id
);
504 ibnex
.ibnex_taskq_id
= NULL
;
505 (void) mdi_vhci_unregister(dip
, 0);
506 return (DDI_FAILURE
);
510 * Create "devctl" minor node for general ioctl interface to the
513 if (ddi_create_minor_node(dip
, "devctl", S_IFCHR
, instance
,
514 DDI_NT_IB_NEXUS
, 0) != DDI_SUCCESS
) {
515 IBTF_DPRINTF_L2("ibnex",
516 "\tattach: failed to create devctl minornode");
517 (void) ddi_remove_minor_node(dip
, NULL
);
518 (void) ddi_taskq_destroy(ibnex
.ibnex_taskq_id
);
519 ibnex
.ibnex_taskq_id
= NULL
;
520 (void) mdi_vhci_unregister(dip
, 0);
521 return (DDI_FAILURE
);
525 * Set pm-want-child-notification property for
526 * power management of the phci and client
528 if (ddi_prop_create(DDI_DEV_T_NONE
, dip
, DDI_PROP_CANSLEEP
,
529 "pm-want-child-notification?", NULL
, 0) != DDI_PROP_SUCCESS
) {
530 IBTF_DPRINTF_L2("ibnex",
531 "_attach: create pm-want-child-notification failed");
532 (void) ddi_remove_minor_node(dip
, NULL
);
533 (void) ddi_taskq_destroy(ibnex
.ibnex_taskq_id
);
534 ibnex
.ibnex_taskq_id
= NULL
;
535 (void) mdi_vhci_unregister(dip
, 0);
536 return (DDI_FAILURE
);
539 mutex_enter(&ibnex
.ibnex_mutex
);
540 ibnex
.ibnex_dip
= dip
;
541 mutex_exit(&ibnex
.ibnex_mutex
);
544 * Event Handling: Definition and Binding.
546 if (ndi_event_alloc_hdl(dip
, 0, &ibnex
.ibnex_ndi_event_hdl
,
547 NDI_SLEEP
) != NDI_SUCCESS
) {
548 IBTF_DPRINTF_L2("ibnex",
549 "_attach: ndi_event_alloc_hdl failed");
550 (void) ddi_remove_minor_node(dip
, NULL
);
551 (void) ddi_taskq_destroy(ibnex
.ibnex_taskq_id
);
552 ibnex
.ibnex_taskq_id
= NULL
;
553 (void) mdi_vhci_unregister(dip
, 0);
554 return (DDI_FAILURE
);
556 if (ndi_event_bind_set(ibnex
.ibnex_ndi_event_hdl
, &ib_ndi_events
,
557 NDI_SLEEP
) != NDI_SUCCESS
) {
558 (void) ddi_remove_minor_node(dip
, NULL
);
559 (void) ndi_event_free_hdl(ibnex
.ibnex_ndi_event_hdl
);
560 IBTF_DPRINTF_L2("ibnex",
561 "_attach: ndi_event_bind_set failed");
562 (void) ddi_taskq_destroy(ibnex
.ibnex_taskq_id
);
563 ibnex
.ibnex_taskq_id
= NULL
;
564 (void) mdi_vhci_unregister(dip
, 0);
565 return (DDI_FAILURE
);
568 for (i
= 0; i
< N_IBNEX_PROPS
; i
++) {
569 if (ibnex_comm_svc_init(ibnex_properties
[i
].name
,
570 ibnex_properties
[i
].type
) != IBNEX_SUCCESS
) {
571 ibnex_comm_svc_fini();
572 (void) ndi_event_unbind_set(ibnex
.ibnex_ndi_event_hdl
,
573 &ib_ndi_events
, NDI_SLEEP
);
574 (void) ddi_remove_minor_node(dip
, NULL
);
575 (void) ndi_event_free_hdl(
576 ibnex
.ibnex_ndi_event_hdl
);
577 ibnex
.ibnex_ndi_event_hdl
= NULL
;
578 IBTF_DPRINTF_L2("ibnex", "_attach: ibnex_comm_svc_init"
579 " failed %s", ibnex_properties
[i
].name
);
580 (void) ddi_taskq_destroy(ibnex
.ibnex_taskq_id
);
581 ibnex
.ibnex_taskq_id
= NULL
;
582 (void) mdi_vhci_unregister(dip
, 0);
583 return (DDI_FAILURE
);
588 * before anything else comes up:
589 * Initialize the internal list of pseudo device nodes by
590 * getting all pseudo children of "ib" and processing them.
592 ibnex_pseudo_initnodes();
594 return (DDI_SUCCESS
);
600 * Given the device number, return the devinfo pointer or the
602 * Note: always succeed DDI_INFO_DEVT2INSTANCE, even before attach.
607 ibnex_getinfo(dev_info_t
*dip
, ddi_info_cmd_t cmd
, void *arg
, void **result
)
609 int ret
= DDI_SUCCESS
;
611 IBTF_DPRINTF_L4("ibnex", "\tgetinfo: Begin");
613 case DDI_INFO_DEVT2DEVINFO
:
614 if (ibnex
.ibnex_dip
!= NULL
)
615 *result
= ibnex
.ibnex_dip
;
622 case DDI_INFO_DEVT2INSTANCE
:
635 * Unregister callback with the IBDM
636 * Unregister callback with the IBTL
637 * Uninitialize the communication entries
638 * Remove all the minor nodes created by this instance
641 ibnex_detach(dev_info_t
*dip
, ddi_detach_cmd_t cmd
)
644 IBTF_DPRINTF_L4("ibnex", "\tdetach: dip = %p cmd = %x)", dip
, cmd
);
651 IBTF_DPRINTF_L4("ibnex", "\t_detach: Suspend");
652 return (DDI_SUCCESS
);
654 return (DDI_FAILURE
);
657 mutex_enter(&ibnex
.ibnex_mutex
);
658 if (ibt_hw_is_present()) {
659 IBTF_DPRINTF_L2("ibnex",
660 "\tdetach: IB HW is present ");
661 mutex_exit(&ibnex
.ibnex_mutex
);
662 return (DDI_FAILURE
);
664 if (ndi_event_free_hdl(ibnex
.ibnex_ndi_event_hdl
)) {
665 IBTF_DPRINTF_L2("ibnex",
666 "\tdetach: ndi_event_free_hdl() failed");
667 mutex_exit(&ibnex
.ibnex_mutex
);
668 return (DDI_FAILURE
);
670 ibnex
.ibnex_ndi_event_hdl
= NULL
;
671 ibnex
.ibnex_prop_update_evt_cookie
= NULL
;
673 ibnex_pseudo_node_cleanup();
674 ibnex_comm_svc_fini();
675 ibnex_ioc_node_cleanup();
677 (void) ddi_remove_minor_node(dip
, NULL
);
678 ibnex
.ibnex_dip
= NULL
;
679 mutex_exit(&ibnex
.ibnex_mutex
);
680 (void) mdi_vhci_unregister(dip
, 0);
682 if (ibnex
.ibnex_taskq_id
!= NULL
) {
683 ddi_taskq_destroy(ibnex
.ibnex_taskq_id
);
684 ibnex
.ibnex_taskq_id
= NULL
;
687 return (DDI_SUCCESS
);
692 * ibnex_pseudo_node_cleanup()
693 * This checks if all the "dips" have been deallocated (implying
694 * that all the children have been unconfigured) first.
695 * If not, it just returns.
696 * If yes, then it frees up memory allocated for devi_name,
697 * node_addr, and property list.
700 ibnex_pseudo_node_cleanup(void)
702 ibnex_node_data_t
*nodep
= ibnex
.ibnex_pseudo_node_head
;
703 ibnex_pseudo_node_t
*pseudo
;
705 IBTF_DPRINTF_L4("ibnex", "\tpseudo_node_cleanup:");
706 ASSERT(MUTEX_HELD(&ibnex
.ibnex_mutex
));
708 for (; nodep
; nodep
= nodep
->node_next
)
712 IBTF_DPRINTF_L4("ibnex", "\tpseudo_node_cleanup: freeing up memory");
713 for (nodep
= ibnex
.ibnex_pseudo_node_head
; nodep
;
714 nodep
= nodep
->node_next
) {
716 pseudo
= &nodep
->node_data
.pseudo_node
;
717 if (pseudo
->pseudo_node_addr
) {
718 kmem_free(pseudo
->pseudo_node_addr
,
719 strlen(pseudo
-> pseudo_node_addr
) + 1);
720 pseudo
->pseudo_node_addr
= NULL
;
723 if (pseudo
->pseudo_devi_name
) {
724 kmem_free(pseudo
->pseudo_devi_name
,
725 strlen(pseudo
-> pseudo_devi_name
) + 1);
726 pseudo
->pseudo_devi_name
= NULL
;
729 if (pseudo
->pseudo_unit_addr
) {
730 kmem_free(pseudo
->pseudo_unit_addr
,
731 pseudo
->pseudo_unit_addr_len
);
738 * This functions wakes up any reprobe requests waiting for completion
739 * of reprobe of this IOC. It also send an NDI event, if :
741 * notify_flag is set. This is set if :
742 * ibt_reprobe_ioc has returned with SUCCESS
743 * IBTF client has not been notified for this node.
744 * node_data->node_dip != NULL
745 * node_state has IBNEX_NODE_REPROBE_NOTIFY_ALWAYS set
746 * An NDI event cookie has been registered.
749 ibnex_wakeup_reprobe_ioc(ibnex_node_data_t
*node_data
, int notify_flag
)
751 ddi_eventcookie_t evt_cookie
;
753 ASSERT(MUTEX_HELD(&ibnex
.ibnex_mutex
));
754 evt_cookie
= ibnex
.ibnex_prop_update_evt_cookie
;
756 if ((ibnex
.ibnex_reprobe_state
== IBNEX_REPROBE_IOC_WAIT
) ||
757 (node_data
->node_reprobe_state
!= 0)) {
758 if (notify_flag
&& (node_data
->node_dip
!= NULL
) &&
759 (node_data
->node_state
&
760 IBNEX_NODE_REPROBE_NOTIFY_ALWAYS
) &&
761 (evt_cookie
!= NULL
)) {
762 ibt_prop_update_payload_t evt_data
;
764 mutex_exit(&ibnex
.ibnex_mutex
);
766 bzero(&evt_data
, sizeof (evt_data
));
767 if (ndi_post_event(ibnex
.ibnex_dip
,
769 evt_cookie
, &evt_data
) != NDI_SUCCESS
)
770 IBTF_DPRINTF_L2("ibnex",
771 "\tndi_post_event failed\n");
773 mutex_enter(&ibnex
.ibnex_mutex
);
776 node_data
->node_reprobe_state
= 0;
777 cv_broadcast(&ibnex
.ibnex_reprobe_cv
);
779 node_data
->node_reprobe_state
= 0;
783 * This function wakes up any reprobe request waiting for completion
784 * of reprobe of all IOCs.
787 ibnex_wakeup_reprobe_all()
789 ibnex_node_data_t
*ioc_node
;
791 ASSERT(MUTEX_HELD(&ibnex
.ibnex_mutex
));
793 /* Notify if another reprobe_all is pending */
794 if (ibnex
.ibnex_reprobe_state
== IBNEX_REPROBE_ALL_WAIT
) {
795 ibnex
.ibnex_reprobe_state
= 0;
796 cv_broadcast(&ibnex
.ibnex_reprobe_cv
);
798 ibnex
.ibnex_reprobe_state
= 0;
801 * The IOC may be hot-removed after the reprobe request.
802 * Reset the reprobe states for such IOCs.
804 for (ioc_node
= ibnex
.ibnex_ioc_node_head
; ioc_node
;
805 ioc_node
= ioc_node
->node_next
) {
806 if (ioc_node
->node_reprobe_state
!= 0) {
807 ibnex_wakeup_reprobe_ioc(ioc_node
, 1);
813 * ibnex_ibnex_callback:
814 * IBTL_IBNEX_IBC_INIT:
815 * Called from ibc_init() which is called from
816 * HCA driver _init entry point
817 * Initializes the HCA dev_ops structure with default
818 * IB nexus structure.
819 * IBTL_IBNEX_IBC_FINI:
820 * Called from ibc_fini() which is called from
821 * HCA driver _fini entry point
822 * Un-Initializes the HCA dev_ops structure with default
823 * IB nexus strucuture.
824 * Returns IBT_SUCCESS
827 ibnex_ibtl_callback(ibtl_ibnex_cb_args_t
*cb_args
)
829 int retval
= IBT_SUCCESS
;
830 struct dev_ops
*hca_dev_ops
;
831 dev_info_t
*clnt_dip
;
832 ibnex_node_data_t
*node_data
;
834 IBTF_DPRINTF_L5("ibnex", "\tibtl_callback");
836 switch (cb_args
->cb_flag
) {
837 case IBTL_IBNEX_IBC_INIT
:
839 * Get the devops structure of the HCA,
840 * and put IB nexus default busops vector in its place.
842 hca_dev_ops
= ((struct modldrv
*)
843 (cb_args
->cb_modlp
->ml_linkage
[0]))->drv_dev_ops
;
844 ASSERT((hca_dev_ops
) && (hca_dev_ops
->devo_bus_ops
== NULL
));
845 hca_dev_ops
->devo_bus_ops
= &ibnex_ci_busops
;
848 case IBTL_IBNEX_IBC_FINI
:
849 hca_dev_ops
= ((struct modldrv
*)
850 (cb_args
->cb_modlp
->ml_linkage
[0]))->drv_dev_ops
;
851 hca_dev_ops
->devo_bus_ops
= NULL
;
854 case IBTL_IBNEX_REPROBE_DEV_REQ
:
855 /* IBTL pass down request for ibt_reprobe_dev */
856 clnt_dip
= cb_args
->cb_dip
;
859 node_data
= ddi_get_parent_data(clnt_dip
);
862 /* Reprobe for IOC nodes only */
863 ASSERT(node_data
->node_type
== IBNEX_IOC_NODE
);
866 * Start the reprobe. This could sleep as it is not
867 * from interrupt context.
869 if (taskq_dispatch(system_taskq
, ibnex_handle_reprobe_dev
,
870 clnt_dip
, TQ_SLEEP
) == 0) {
871 IBTF_DPRINTF_L2("ibnex",
872 "ibnex_ibtl_callback: taskq_dispatch failed");
873 mutex_enter(&ibnex
.ibnex_mutex
);
874 ibnex_wakeup_reprobe_ioc(node_data
, 0);
875 mutex_exit(&ibnex
.ibnex_mutex
);
876 return (IBT_INSUFF_KERNEL_RESOURCE
);
878 return (IBT_SUCCESS
);
886 * Bus-ops entry points
891 * IOC drivers need not map memory. Return failure to fail any
896 ibnex_map_fault(dev_info_t
*dip
, dev_info_t
*rdip
, struct hat
*hat
,
897 struct seg
*seg
, caddr_t addr
, struct devpage
*dp
, pfn_t pfn
,
898 uint_t prot
, uint_t lock
)
900 return (DDI_FAILURE
);
906 * bus_ctl bus_ops entry point
910 ibnex_busctl(dev_info_t
*dip
, dev_info_t
*rdip
,
911 ddi_ctl_enum_t ctlop
, void *arg
, void *result
)
913 dev_info_t
*child_dip
;
915 IBTF_DPRINTF_L4("ibnex",
916 "\tbusctl: dip = %p, rdip = %p, ctlop = %x,", dip
, rdip
, ctlop
);
917 IBTF_DPRINTF_L4("ibnex", "\tbusctl: targ = %p, result %p", arg
, result
);
920 case DDI_CTLOPS_REPORTDEV
:
922 return (DDI_FAILURE
);
925 /* Log the relevant details of dip to sysbuf */
926 cmn_err(CE_CONT
, "?IB device: %s@%s, %s%d\n",
927 ddi_node_name(rdip
), ddi_get_name_addr(rdip
),
928 ddi_driver_name(rdip
), ddi_get_instance(rdip
));
930 return (DDI_SUCCESS
);
932 case DDI_CTLOPS_INITCHILD
:
933 child_dip
= (dev_info_t
*)arg
;
934 return (ibnex_init_child(child_dip
));
936 case DDI_CTLOPS_UNINITCHILD
:
937 child_dip
= (dev_info_t
*)arg
;
938 ddi_set_name_addr(child_dip
, NULL
);
939 return (DDI_SUCCESS
);
941 case DDI_CTLOPS_ATTACH
:
942 case DDI_CTLOPS_DETACH
:
943 case DDI_CTLOPS_POWER
:
944 return (DDI_SUCCESS
);
946 case DDI_CTLOPS_SIDDEV
:
948 * Return DDI_SUCCESS for IOC/PORT/VPPA nodes and
949 * DDI_FAILURE for the nodes enumerated by a Pseudo file.
951 return (ndi_dev_is_persistent_node(rdip
) ?
952 DDI_SUCCESS
: DDI_FAILURE
);
955 case DDI_CTLOPS_IOMIN
:
957 * Return DDI_SUCCESS, so that consistent buf alloc
958 * gets the default DMA IO minimum for the platform
960 return (DDI_SUCCESS
);
963 * These ops correspond to functions that "shouldn't" be
964 * called by IB Nexus driver.
966 case DDI_CTLOPS_DMAPMAPC
:
967 case DDI_CTLOPS_REPORTINT
:
968 case DDI_CTLOPS_REGSIZE
:
969 case DDI_CTLOPS_NREGS
:
970 case DDI_CTLOPS_SLAVEONLY
:
971 case DDI_CTLOPS_AFFINITY
:
972 case DDI_CTLOPS_POKE
:
973 case DDI_CTLOPS_PEEK
:
974 IBTF_DPRINTF_L2("ibnex",
975 "%s%d: invalid op (%d) from %s inst%d",
976 ddi_get_name(dip
), ddi_get_instance(dip
),
977 ctlop
, ddi_get_name(rdip
), ddi_get_instance(rdip
));
978 return (DDI_FAILURE
);
981 * Everything else (PTOB/BTOP/BTOPR/DVMAPAGESIZE requests) we
985 return (ddi_ctlops(dip
, rdip
, ctlop
, arg
, result
));
993 * Initialize a child device node. This is called for the DDI_CTLOPS_INITCHILD
994 * entry. Function returns DDI_SUCCESS, DDI_FAILURE or DDI_NOT_WELL_FORMED.
997 ibnex_init_child(dev_info_t
*child
)
1000 char name
[MAXNAMELEN
];
1002 IBTF_DPRINTF_L4("ibnex", "\tinit_child: child = %p", child
);
1004 /* Handle Pseudo nodes of client children */
1005 if (ndi_dev_is_persistent_node(child
) == 0) {
1006 /* Skip nodes without ib-node-type="merge" */
1007 if (ibnex_is_merge_node(child
) != IBNEX_SUCCESS
)
1008 return (DDI_FAILURE
);
1010 if (ibnex_name_pseudo_child(child
, name
) != DDI_SUCCESS
)
1011 return (DDI_FAILURE
);
1013 ddi_set_name_addr(child
, name
);
1015 * Merge the .conf node
1017 if (ndi_merge_node(child
,
1018 ibnex_name_child
) == DDI_SUCCESS
) {
1019 ddi_set_name_addr(child
, NULL
);
1020 return (DDI_FAILURE
);
1022 return (DDI_NOT_WELL_FORMED
);
1026 if ((ret
= ibnex_name_child(child
, name
, 0)) != DDI_SUCCESS
)
1029 ddi_set_name_addr(child
, name
);
1031 return (DDI_SUCCESS
);
1036 ibnex_name_pseudo_child(dev_info_t
*child
, char *name
)
1040 if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY
, child
,
1041 DDI_PROP_DONTPASS
, "unit-address", &unit_addr
, &n
) !=
1043 IBTF_DPRINTF_L4("ibnex",
1044 "\tname_pseudo_child: cannot find unit-address in %s.conf",
1045 ddi_get_name(child
));
1046 return (DDI_FAILURE
);
1048 if (n
!= 1 || *unit_addr
== NULL
|| **unit_addr
== 0) {
1049 cmn_err(CE_WARN
, "unit-address property in %s.conf"
1050 " not well-formed", ddi_get_name(child
));
1051 ddi_prop_free(unit_addr
);
1052 return (DDI_FAILURE
);
1054 (void) snprintf(name
, MAXNAMELEN
, "%s", *unit_addr
);
1055 ddi_prop_free(unit_addr
);
1056 return (DDI_SUCCESS
);
1062 ibnex_name_child(dev_info_t
*child
, char *name
, int flag
)
1064 ibnex_pseudo_node_t
*pseudo
;
1065 ibnex_node_data_t
*node_datap
;
1066 ibnex_port_node_t
*port_node
;
1067 ibnex_ioc_node_t
*ioc
;
1069 node_datap
= ddi_get_parent_data(child
);
1070 if (node_datap
== NULL
) {
1071 IBTF_DPRINTF_L2("ibnex", "\tname_child: Node data is NULL");
1072 return (DDI_NOT_WELL_FORMED
);
1074 IBTF_DPRINTF_L4("ibnex", "\tname_sid_child: Node data %p"
1075 "Node type %x", node_datap
, node_datap
->node_type
);
1076 switch (node_datap
->node_type
) {
1077 case IBNEX_PORT_COMMSVC_NODE
:
1078 port_node
= &node_datap
->node_data
.port_node
;
1079 (void) snprintf(name
, IBNEX_MAX_NODEADDR_SZ
, "%x,0,%s",
1080 port_node
->port_num
,
1081 ibnex
.ibnex_comm_svc_names
[port_node
->port_commsvc_idx
]);
1083 case IBNEX_VPPA_COMMSVC_NODE
:
1084 port_node
= &node_datap
->node_data
.port_node
;
1085 (void) snprintf(name
, IBNEX_MAX_NODEADDR_SZ
, "%x,%x,%s",
1086 port_node
->port_num
, port_node
->port_pkey
, ibnex
.
1087 ibnex_vppa_comm_svc_names
[port_node
->port_commsvc_idx
]);
1089 case IBNEX_HCASVC_COMMSVC_NODE
:
1090 port_node
= &node_datap
->node_data
.port_node
;
1091 (void) snprintf(name
, IBNEX_MAX_NODEADDR_SZ
, "%x,0,%s",
1092 port_node
->port_num
,
1093 ibnex
.ibnex_hcasvc_comm_svc_names
[port_node
->
1096 case IBNEX_IOC_NODE
:
1097 ioc
= &node_datap
->node_data
.ioc_node
;
1098 (void) snprintf(name
, IBNEX_MAX_NODEADDR_SZ
, "%llX,%llX",
1099 (longlong_t
)ioc
->ioc_guid
, (longlong_t
)ioc
->iou_guid
);
1101 case IBNEX_PSEUDO_NODE
:
1102 pseudo
= &node_datap
->node_data
.pseudo_node
;
1103 (void) snprintf(name
,
1104 IBNEX_MAX_NODEADDR_SZ
, pseudo
->pseudo_unit_addr
);
1107 IBTF_DPRINTF_L2("ibnex", "\name_child: Not well formed");
1108 return (DDI_NOT_WELL_FORMED
);
1111 return (DDI_SUCCESS
);
1116 * ibnex_bus_config()
1119 * Enumerate the exact instance of the driver. Use the device node name
1120 * to locate the exact instance.
1121 * Query IBDM to find whether the hardware exits for the instance of the
1122 * driver. If exists, create a device node and return NDI_SUCCESS.
1125 * Enumerate all the instances of all the possible children (seen before
1126 * and never seen before).
1128 * BUS_CONFIG_DRIVER:
1129 * Enumerate all the instances of a particular driver.
1133 ibnex_bus_config(dev_info_t
*parent
, uint_t flag
,
1134 ddi_bus_config_op_t op
, void *devname
, dev_info_t
**child
)
1136 int ret
= IBNEX_SUCCESS
, len
, circ
, need_bus_config
;
1137 char *device_name
, *cname
= NULL
, *caddr
= NULL
;
1139 ibnex_node_data_t
*node_data
;
1142 case BUS_CONFIG_ONE
:
1143 IBTF_DPRINTF_L4("ibnex", "\tbus_config: CONFIG_ONE, "
1144 "parent %p", parent
);
1146 ndi_devi_enter(parent
, &circ
);
1148 len
= strlen((char *)devname
) + 1;
1149 device_name
= i_ddi_strdup(devname
, KM_SLEEP
);
1150 i_ddi_parse_name(device_name
, &cname
, &caddr
, NULL
);
1152 if (caddr
== NULL
|| (strlen(caddr
) == 0)) {
1153 kmem_free(device_name
, len
);
1154 ndi_devi_exit(parent
, circ
);
1155 return (NDI_FAILURE
);
1158 cdip
= ndi_devi_findchild(parent
, devname
);
1160 node_data
= ddi_get_parent_data(cdip
);
1162 ndi_devi_exit(parent
, circ
);
1164 if (cdip
== NULL
|| (node_data
!= NULL
&&
1165 node_data
->node_dip
== NULL
)) {
1166 /* Node is not present */
1167 if (strncmp(cname
, IBNEX_IOC_CNAME
, 3) == 0) {
1168 ret
= ibnex_ioc_bus_config_one(&parent
, flag
,
1169 op
, devname
, child
, &need_bus_config
);
1170 if (!need_bus_config
) {
1171 kmem_free(device_name
, len
);
1176 * if IB Nexus is the parent, call MDI. Bus
1177 * config with HCA as the parent would have
1178 * enumerated the Pseudo node.
1180 ret
= IBNEX_SUCCESS
;
1181 ibnex_pseudo_initnodes();
1182 mutex_enter(&ibnex
.ibnex_mutex
);
1183 ret
= ibnex_pseudo_mdi_config_one(flag
, devname
,
1184 child
, cname
, caddr
);
1185 mutex_exit(&ibnex
.ibnex_mutex
);
1186 kmem_free(device_name
, len
);
1190 kmem_free(device_name
, len
);
1193 case BUS_CONFIG_ALL
:
1195 case BUS_CONFIG_DRIVER
:
1196 if (op
== BUS_CONFIG_ALL
)
1197 IBTF_DPRINTF_L4("ibnex", "\tbus_config: CONFIG_ALL, "
1198 "parent %p", parent
);
1200 IBTF_DPRINTF_L4("ibnex", "\tbus_config: CONFIG_DRIVER"
1201 ", parent %p", parent
);
1204 * Drive CONFIG requests for IB Nexus parent through
1205 * MDI. This is needed to load the HCA drivers in x86 SRP
1208 * CONFIG Requests with HCA parent will probe devices using
1209 * ibdm and configure all children.
1211 ibdm_ioc_info_t
*ioc_list
, *new_ioc_list
;
1213 mutex_enter(&ibnex
.ibnex_mutex
);
1214 while (ibnex
.ibnex_ioc_list_state
!=
1215 IBNEX_IOC_LIST_READY
) {
1216 cv_wait(&ibnex
.ibnex_ioc_list_cv
,
1217 &ibnex
.ibnex_mutex
);
1219 ibnex
.ibnex_ioc_list_state
= IBNEX_IOC_LIST_RENEW
;
1220 mutex_exit(&ibnex
.ibnex_mutex
);
1221 /* Enumerate all the IOC's */
1222 ibdm_ibnex_port_settle_wait(0, ibnex_port_settling_time
);
1224 new_ioc_list
= ibdm_ibnex_get_ioc_list(
1225 IBDM_IBNEX_NORMAL_PROBE
);
1226 IBTF_DPRINTF_L4("ibnex",
1227 "\tbus_config: alloc ioc_list %p", new_ioc_list
);
1229 * Optimize the calls for each BUS_CONFIG_ALL request
1230 * to the IB Nexus dip. This is currently done for
1233 mutex_enter(&ibnex
.ibnex_mutex
);
1234 ioc_list
= ibnex
.ibnex_ioc_list
;
1235 ibnex
.ibnex_ioc_list
= new_ioc_list
;
1236 ibnex
.ibnex_ioc_list_state
= IBNEX_IOC_LIST_READY
;
1237 cv_broadcast(&ibnex
.ibnex_ioc_list_cv
);
1238 mutex_exit(&ibnex
.ibnex_mutex
);
1241 IBTF_DPRINTF_L4("ibnex",
1242 "\tbus_config: freeing ioc_list %p",
1244 ibdm_ibnex_free_ioc_list(ioc_list
);
1248 ret
= mdi_vhci_bus_config(parent
,
1249 flag
, op
, devname
, child
, NULL
);
1252 IBTF_DPRINTF_L4("ibnex", "\tbus_config: error");
1253 ret
= IBNEX_FAILURE
;
1257 if (ret
== IBNEX_SUCCESS
) {
1258 ret
= ndi_busop_bus_config(
1259 parent
, flag
, op
, devname
, child
, 0);
1260 IBTF_DPRINTF_L4("ibnex", "\tbus_config:"
1261 "ndi_busop_bus_config : retval %d", ret
);
1265 return (NDI_FAILURE
);
1270 * ibnex_config_root_iocnode()
1271 * Configures one particular instance of the IOC driver.
1272 * Returns IBNEX_SUCCESS/IBNEX_FAILURE
1275 ibnex_config_root_iocnode(dev_info_t
*parent
, char *device_name
)
1277 int ret
, port
= 0, iter
= 0;
1278 boolean_t displayed
= B_FALSE
;
1280 ib_guid_t hca_guid
, iou_guid
, ioc_guid
;
1281 ibdm_ioc_info_t
*ioc_info
;
1282 ibdm_port_attr_t
*port_attr
;
1284 IBTF_DPRINTF_L4("ibnex",
1285 "\tconfig_root_iocnode: name %s", device_name
);
1287 portstr
= strstr(device_name
, ":port=");
1288 if (portstr
== NULL
) {
1289 return (IBNEX_FAILURE
);
1292 portstr
[0] = 0; portstr
++;
1293 if (ibnex_devname2port(portstr
, &port
)) {
1294 IBTF_DPRINTF_L4("ibnex", "\tconfig_root_iocnode: invalid port");
1295 return (IBNEX_FAILURE
);
1298 if (ibnex_devname_to_node_n_ioc_guids(
1299 device_name
, &iou_guid
, &ioc_guid
, NULL
) != IBNEX_SUCCESS
) {
1300 return (IBNEX_FAILURE
);
1303 (void) snprintf(device_name
, (IBNEX_MAX_NODEADDR_SZ
+ 4),
1304 "ioc@%llX,%llX", (longlong_t
)ioc_guid
, (longlong_t
)iou_guid
);
1306 hca_guid
= ibtl_ibnex_hcadip2guid(parent
);
1307 if ((port_attr
= ibdm_ibnex_probe_hcaport(hca_guid
, port
)) == NULL
) {
1308 IBTF_DPRINTF_L2("ibnex",
1309 "\tconfig_root_iocnode: Port does not exist");
1310 return (IBNEX_FAILURE
);
1313 /* Wait until "port is up" */
1314 while (port_attr
->pa_state
!= IBT_PORT_ACTIVE
) {
1315 ibdm_ibnex_free_port_attr(port_attr
);
1316 delay(drv_usectohz(10000));
1317 if ((port_attr
= ibdm_ibnex_probe_hcaport(
1318 hca_guid
, port
)) == NULL
) {
1319 return (IBNEX_FAILURE
);
1322 if (iter
++ == 400) {
1323 if (displayed
== B_FALSE
) {
1324 cmn_err(CE_NOTE
, "\tWaiting for Port %d "
1325 "initialization", port_attr
->pa_port_num
);
1330 ibdm_ibnex_free_port_attr(port_attr
);
1331 IBTF_DPRINTF_L4("ibnex", "\tconfig_rootioc_node:"
1332 "Port is initialized");
1334 if ((ioc_info
= ibdm_ibnex_probe_ioc(iou_guid
, ioc_guid
, 0)) == NULL
) {
1335 ibdm_ibnex_free_ioc_list(ioc_info
);
1336 return (IBNEX_FAILURE
);
1338 mutex_enter(&ibnex
.ibnex_mutex
);
1339 if ((ret
= ibnex_ioc_config_from_pdip(ioc_info
, parent
, 0)) !=
1341 IBTF_DPRINTF_L2("ibnex",
1342 "\tconfig_root_ioc_node failed for pdip %p", parent
);
1344 mutex_exit(&ibnex
.ibnex_mutex
);
1345 ibdm_ibnex_free_ioc_list(ioc_info
);
1351 ibnex_devname2port(char *portstr
, int *port
)
1354 int ret
= IBNEX_FAILURE
;
1356 IBTF_DPRINTF_L4("ibnex", "\tdevname2port: Begin");
1358 temp
= strchr(portstr
, '=');
1361 *port
= ibnex_str2int(temp
, strlen(temp
), &ret
);
1368 * ibnex_config_all_children()
1369 * Wait for lata SM initialization case before enumerating the nodes
1370 * Get list of HCA's and HCA port information
1371 * Create device device nodes and its node properties
1372 * for port nodes and VPPA nodes
1373 * Get list of all the IOC node information
1374 * Create device nodes and its properties for all the IOCs
1375 * if not created already
1376 * Bind drivers for all the newly created device nodes
1377 * Support Pseudo nodes enumerated using their .conf file
1380 ibnex_config_all_children(dev_info_t
*parent
)
1383 ibdm_ioc_info_t
*ioc_list
;
1384 ibdm_hca_list_t
*hca_list
;
1388 IBTF_DPRINTF_L4("ibnex", "\tconfig_all_children: Begin");
1392 * Enumerate children of this HCA, port nodes,
1393 * VPPA & HCA_SVC nodes. Use ndi_devi_enter() for
1394 * locking. IB Nexus is enumerating the children
1395 * of HCA, not MPXIO clients.
1397 ndi_devi_enter(parent
, &circ
);
1398 hca_guid
= ibtl_ibnex_hcadip2guid(parent
);
1399 ibdm_ibnex_port_settle_wait(hca_guid
, ibnex_port_settling_time
);
1400 hca_list
= ibdm_ibnex_get_hca_info_by_guid(hca_guid
);
1401 if (hca_list
== NULL
) {
1402 ndi_devi_exit(parent
, circ
);
1405 ibnex_create_hcasvc_nodes(parent
, hca_list
->hl_hca_port_attr
);
1406 for (ii
= 0; ii
< hca_list
->hl_nports
; ii
++) {
1407 ibnex_create_port_nodes(
1408 parent
, &hca_list
->hl_port_attr
[ii
]);
1409 ibnex_create_vppa_nodes(parent
, &hca_list
->hl_port_attr
[ii
]);
1411 ibdm_ibnex_free_hca_list(hca_list
);
1412 ndi_devi_exit(parent
, circ
);
1415 * Use mdi_devi_enter() for locking. IB Nexus is
1416 * enumerating MPxIO clients.
1418 mdi_devi_enter(parent
, &circ
);
1420 ibnex_pseudo_initnodes();
1422 mutex_enter(&ibnex
.ibnex_mutex
);
1423 while (ibnex
.ibnex_ioc_list_state
!= IBNEX_IOC_LIST_READY
) {
1424 cv_wait(&ibnex
.ibnex_ioc_list_cv
, &ibnex
.ibnex_mutex
);
1426 ibnex
.ibnex_ioc_list_state
= IBNEX_IOC_LIST_ACCESS
;
1427 ioc_list
= ibnex
.ibnex_ioc_list
;
1429 (void) ibnex_ioc_config_from_pdip(ioc_list
, parent
, 0);
1430 ioc_list
= ioc_list
->ioc_next
;
1432 ibnex
.ibnex_ioc_list_state
= IBNEX_IOC_LIST_READY
;
1433 cv_broadcast(&ibnex
.ibnex_ioc_list_cv
);
1435 /* Config IBTF Pseudo clients */
1436 ibnex_config_pseudo_all(parent
);
1438 mutex_exit(&ibnex
.ibnex_mutex
);
1439 mdi_devi_exit(parent
, circ
);
1441 IBTF_DPRINTF_L4("ibnex", "\tconfig_all_children: End");
1446 * ibnex_create_port_nodes:
1447 * Creates a device node per each communication service defined
1448 * in the "port-commsvc-list" property per HCA port
1451 ibnex_create_port_nodes(dev_info_t
*parent
, ibdm_port_attr_t
*port_attr
)
1457 mutex_enter(&ibnex
.ibnex_mutex
);
1458 for (idx
= 0; idx
< ibnex
.ibnex_num_comm_svcs
; idx
++) {
1459 rval
= ibnex_get_dip_from_guid(port_attr
->pa_port_guid
,
1461 if (rval
!= IBNEX_SUCCESS
|| dip
== NULL
) {
1462 (void) ibnex_commsvc_initnode(parent
, port_attr
, idx
,
1463 IBNEX_PORT_COMMSVC_NODE
, 0, &rval
,
1464 IBNEX_DEVFS_ENUMERATE
);
1467 mutex_exit(&ibnex
.ibnex_mutex
);
1472 * ibnex_create_vppa_nodes:
1473 * Creates a device node per each communication service defined
1474 * in the "vppa-commsvc-list" property and per each PKEY that
1475 * this particular port supports and per HCA port
1478 ibnex_create_vppa_nodes(
1479 dev_info_t
*parent
, ibdm_port_attr_t
*port_attr
)
1486 IBTF_DPRINTF_L4("ibnex", "\tcreate_vppa_nodes: Begin");
1488 mutex_enter(&ibnex
.ibnex_mutex
);
1489 if (port_attr
->pa_state
!= IBT_PORT_ACTIVE
) {
1490 IBTF_DPRINTF_L4("ibnex", "\tcreate_vppa_nodes: "
1491 "Port %d is down", port_attr
->pa_port_num
);
1492 mutex_exit(&ibnex
.ibnex_mutex
);
1495 for (idx
= 0; idx
< ibnex
.ibnex_nvppa_comm_svcs
; idx
++) {
1496 if (strcmp("ipib", ibnex
.ibnex_vppa_comm_svc_names
[idx
]) == 0) {
1497 IBTF_DPRINTF_L2("ibnex", "Skipping IBD devices...");
1500 for (ii
= 0; ii
< port_attr
->pa_npkeys
; ii
++) {
1501 pkey
= port_attr
->pa_pkey_tbl
[ii
].pt_pkey
;
1503 if (IBNEX_INVALID_PKEY(pkey
)) {
1506 rval
= ibnex_get_dip_from_guid(
1507 port_attr
->pa_port_guid
, idx
, pkey
, &dip
);
1508 if ((rval
!= IBNEX_SUCCESS
) || (dip
== NULL
)) {
1509 (void) ibnex_commsvc_initnode(parent
, port_attr
,
1510 idx
, IBNEX_VPPA_COMMSVC_NODE
,
1511 pkey
, &rval
, IBNEX_CFGADM_ENUMERATE
);
1515 mutex_exit(&ibnex
.ibnex_mutex
);
1520 * ibnex_create_hcasvc_nodes:
1521 * Creates a device node per each communication service defined
1522 * in the "port-commsvc-list" property per HCA port
1525 ibnex_create_hcasvc_nodes(dev_info_t
*parent
, ibdm_port_attr_t
*port_attr
)
1531 mutex_enter(&ibnex
.ibnex_mutex
);
1532 for (idx
= 0; idx
< ibnex
.ibnex_nhcasvc_comm_svcs
; idx
++) {
1533 rval
= ibnex_get_dip_from_guid(port_attr
->pa_port_guid
,
1535 if (rval
!= IBNEX_SUCCESS
|| dip
== NULL
) {
1536 (void) ibnex_commsvc_initnode(parent
, port_attr
, idx
,
1537 IBNEX_HCASVC_COMMSVC_NODE
, 0, &rval
,
1538 IBNEX_DEVFS_ENUMERATE
);
1539 IBTF_DPRINTF_L5("ibnex", "create_hcasvc_nodes: "
1540 "commsvc_initnode failed, rval %x", rval
);
1543 mutex_exit(&ibnex
.ibnex_mutex
);
1548 * ibnex_bus_unconfig()
1550 * Unconfigure a particular device node or all instance of a device
1551 * driver device or all children of IBnex
1554 ibnex_bus_unconfig(dev_info_t
*parent
,
1555 uint_t flag
, ddi_bus_config_op_t op
, void *device_name
)
1557 ibnex_node_data_t
*ndp
;
1558 major_t major
= (major_t
)(uintptr_t)device_name
;
1559 dev_info_t
*dip
= NULL
;
1561 if (ndi_busop_bus_unconfig(parent
, flag
, op
, device_name
) !=
1563 return (DDI_FAILURE
);
1565 if ((op
== BUS_UNCONFIG_ALL
|| op
== BUS_UNCONFIG_DRIVER
) &&
1566 (flag
& (NDI_UNCONFIG
| NDI_DETACH_DRIVER
))) {
1567 mutex_enter(&ibnex
.ibnex_mutex
);
1569 * IB dip. here we handle IOC and pseudo nodes which
1570 * are the children of IB nexus. Cleanup only the nodes
1571 * with matching major number. We also need to cleanup
1572 * the PathInfo links to the PHCI here.
1574 for (ndp
= ibnex
.ibnex_ioc_node_head
;
1575 ndp
; ndp
= ndp
->node_next
) {
1576 dip
= ndp
->node_dip
;
1577 if (dip
&& (ddi_driver_major(dip
) == major
)) {
1578 (void) ibnex_offline_childdip(dip
);
1581 for (ndp
= ibnex
.ibnex_pseudo_node_head
;
1582 ndp
; ndp
= ndp
->node_next
) {
1583 dip
= ndp
->node_dip
;
1584 if (dip
&& (ddi_driver_major(dip
) == major
)) {
1585 (void) ibnex_offline_childdip(dip
);
1588 mutex_exit(&ibnex
.ibnex_mutex
);
1590 return (DDI_SUCCESS
);
1595 * ibnex_config_port_node()
1597 * Configures a particular port / HCA node for a particular
1598 * communication service.
1599 * The format of the device_name is
1600 * ibport@<Port#>,<pkey>,<service name>
1601 * where pkey = 0 for port communication service nodes
1602 * Port# = 0 for HCA_SVC communication service nodes
1603 * Returns "dev_info_t" of the "child" node just created
1604 * NULL when failed to enumerate the child node
1607 ibnex_config_port_node(dev_info_t
*parent
, char *devname
)
1612 ib_guid_t hca_guid
, port_guid
;
1615 ibdm_port_attr_t
*port_attr
;
1616 ibdm_hca_list_t
*hca_list
;
1618 IBTF_DPRINTF_L4("ibnex", "\tconfig_port_node: %s", devname
);
1620 if (ibnex_get_pkey_commsvc_index_portnum(devname
,
1621 &index
, &pkey
, &port_num
) != IBNEX_SUCCESS
) {
1622 IBTF_DPRINTF_L2("ibnex",
1623 "\tconfig_port_node: Invalid Service Name");
1627 hca_guid
= ibtl_ibnex_hcadip2guid(parent
);
1628 if (port_num
== 0) {
1630 * Use the dummy port attribute for HCA node in hca_list
1631 * Note : pa_state is always IBT_PORT_ACTIVE.
1633 hca_list
= ibdm_ibnex_get_hca_info_by_guid(hca_guid
);
1634 ASSERT(hca_list
!= NULL
);
1635 port_attr
= hca_list
->hl_hca_port_attr
;
1637 if ((port_attr
= ibdm_ibnex_probe_hcaport(
1638 hca_guid
, port_num
)) == NULL
) {
1639 IBTF_DPRINTF_L2("ibnex",
1640 "\tconfig_port_node: Port does not exist");
1644 if (port_attr
->pa_state
!= IBT_PORT_ACTIVE
) {
1645 ibdm_ibnex_port_settle_wait(
1646 hca_guid
, ibnex_port_settling_time
);
1647 ibdm_ibnex_free_port_attr(port_attr
);
1648 if ((port_attr
= ibdm_ibnex_probe_hcaport(
1649 hca_guid
, port_num
)) == NULL
) {
1655 port_guid
= port_attr
->pa_port_guid
;
1656 mutex_enter(&ibnex
.ibnex_mutex
);
1657 rval
= ibnex_get_dip_from_guid(port_guid
, index
, pkey
, &cdip
);
1658 if ((rval
== IBNEX_SUCCESS
) && cdip
!= NULL
) {
1659 IBTF_DPRINTF_L4("ibnex", "\tconfig_port_node: Node exists");
1660 mutex_exit(&ibnex
.ibnex_mutex
);
1662 ibdm_ibnex_free_port_attr(port_attr
);
1664 ibdm_ibnex_free_hca_list(hca_list
);
1668 if (pkey
== 0 && port_num
!= 0) {
1669 cdip
= ibnex_commsvc_initnode(parent
,
1670 port_attr
, index
, IBNEX_PORT_COMMSVC_NODE
, pkey
, &rval
,
1671 IBNEX_DEVFS_ENUMERATE
);
1672 IBTF_DPRINTF_L5("ibnex",
1673 "\t ibnex_commsvc_initnode rval %x", rval
);
1674 } else if (pkey
== 0 && port_num
== 0) {
1675 cdip
= ibnex_commsvc_initnode(parent
,
1676 port_attr
, index
, IBNEX_HCASVC_COMMSVC_NODE
, pkey
, &rval
,
1677 IBNEX_DEVFS_ENUMERATE
);
1678 IBTF_DPRINTF_L5("ibnex",
1679 "\t ibnex_commsvc_initnode rval %x", rval
);
1681 if (port_attr
->pa_state
!= IBT_PORT_ACTIVE
) {
1682 IBTF_DPRINTF_L4("ibnex", "\tconfig_port_nodes: "
1683 "Port %d is down", port_attr
->pa_port_num
);
1684 ibdm_ibnex_free_port_attr(port_attr
);
1685 mutex_exit(&ibnex
.ibnex_mutex
);
1688 for (ii
= 0; ii
< port_attr
->pa_npkeys
; ii
++) {
1689 if (pkey
== port_attr
->pa_pkey_tbl
[ii
].pt_pkey
) {
1690 cdip
= ibnex_commsvc_initnode(parent
, port_attr
,
1691 index
, IBNEX_VPPA_COMMSVC_NODE
,
1692 pkey
, &rval
, IBNEX_CFGADM_ENUMERATE
);
1693 IBTF_DPRINTF_L5("ibnex",
1694 "\t ibnex_commsvc_initnode rval %x", rval
);
1699 mutex_exit(&ibnex
.ibnex_mutex
);
1701 ibdm_ibnex_free_port_attr(port_attr
);
1703 ibdm_ibnex_free_hca_list(hca_list
);
1709 * ibnex_get_pkey_commsvc_index_portnum()
1710 * Parses the device node name and extracts PKEY, communication
1711 * service index & Port #.
1712 * Returns IBNEX_SUCCESS/IBNEX_FAILURE
1715 ibnex_get_pkey_commsvc_index_portnum(char *device_name
, int *index
,
1716 ib_pkey_t
*pkey
, uint8_t *port_num
)
1718 char *srv
, **service_name
, *temp
;
1719 int ii
, ncommsvcs
, ret
;
1721 if (ibnex_devname_to_portnum(device_name
, port_num
) !=
1723 IBTF_DPRINTF_L2("ibnex",
1724 "\tget_pkey_commsvc_index_portnum: Invalid Service Name");
1725 return (IBNEX_FAILURE
);
1727 srv
= strchr(device_name
, ',');
1729 return (IBNEX_FAILURE
);
1732 temp
= strchr(srv
, ',');
1734 return (IBNEX_FAILURE
);
1736 *pkey
= ibnex_str2hex(srv
, (temp
- srv
- 1), &ret
);
1737 if (ret
!= IBNEX_SUCCESS
)
1740 if (*pkey
== 0 && *port_num
!= 0) {
1741 service_name
= ibnex
.ibnex_comm_svc_names
;
1742 ncommsvcs
= ibnex
.ibnex_num_comm_svcs
;
1743 } else if (*pkey
== 0 && *port_num
== 0) {
1744 service_name
= ibnex
.ibnex_hcasvc_comm_svc_names
;
1745 ncommsvcs
= ibnex
.ibnex_nhcasvc_comm_svcs
;
1747 service_name
= ibnex
.ibnex_vppa_comm_svc_names
;
1748 ncommsvcs
= ibnex
.ibnex_nvppa_comm_svcs
;
1751 for (ii
= 0; ii
< ncommsvcs
; ii
++) {
1752 if (strcmp(service_name
[ii
], temp
) == 0) {
1756 if (ii
== ncommsvcs
)
1757 return (IBNEX_FAILURE
);
1760 return (IBNEX_SUCCESS
);
1765 * ibnex_devname_to_portnum()
1766 * Get portguid from device name
1767 * Returns IBNEX_SUCCESS/IBNEX_FAILURE
1770 ibnex_devname_to_portnum(char *device_name
, uint8_t *portnum
)
1773 char *temp1
, *temp2
;
1775 temp1
= strchr(device_name
, '@');
1776 if (temp1
== NULL
) {
1777 return (IBNEX_FAILURE
);
1779 temp2
= strchr(temp1
, ',');
1781 return (IBNEX_FAILURE
);
1783 *portnum
= ibnex_str2hex(temp1
, (temp2
- temp1
), &ret
);
1789 * ibnex_config_ioc_node()
1790 * Configures one particular instance of the IOC driver.
1791 * Returns IBNEX_SUCCESS/IBNEX_FAILURE
1794 ibnex_config_ioc_node(char *device_name
, dev_info_t
*pdip
)
1797 ib_guid_t iou_guid
, ioc_guid
;
1798 ibdm_ioc_info_t
*ioc_info
;
1800 IBTF_DPRINTF_L4("ibnex", "\tconfig_ioc_node: Begin");
1802 if (ibnex_devname_to_node_n_ioc_guids(
1803 device_name
, &iou_guid
, &ioc_guid
, NULL
) != IBNEX_SUCCESS
) {
1804 return (IBNEX_FAILURE
);
1807 ibdm_ibnex_port_settle_wait(0, ibnex_port_settling_time
);
1809 if ((ioc_info
= ibdm_ibnex_probe_ioc(iou_guid
, ioc_guid
, 0)) ==
1811 ibdm_ibnex_free_ioc_list(ioc_info
);
1812 return (IBNEX_FAILURE
);
1814 mutex_enter(&ibnex
.ibnex_mutex
);
1815 ret
= ibnex_ioc_config_from_pdip(ioc_info
, pdip
, 0);
1816 mutex_exit(&ibnex
.ibnex_mutex
);
1817 ibdm_ibnex_free_ioc_list(ioc_info
);
1818 IBTF_DPRINTF_L4("ibnex", "\tconfig_ioc_node: ret %x",
1825 * ibnex_devname_to_node_n_ioc_guids()
1826 * Get node guid and ioc guid from the device name
1827 * Format of the device node name is:
1828 * ioc@<IOC GUID>,<IOU GUID>
1829 * Returns IBNEX_SUCCESS/IBNEX_FAILURE
1832 ibnex_devname_to_node_n_ioc_guids(
1833 char *device_name
, ib_guid_t
*iou_guid
, ib_guid_t
*ioc_guid
,
1834 char **ioc_guid_strp
)
1840 IBTF_DPRINTF_L4("ibnex", "\tdevname_to_node_n_ioc_guids:"
1841 "Device Name %s", device_name
);
1843 if ((temp
= strchr(device_name
, '@')) == NULL
) {
1844 return (IBNEX_FAILURE
);
1846 if ((temp1
= strchr(++temp
, ',')) == NULL
) {
1847 return (IBNEX_FAILURE
);
1849 *ioc_guid
= ibnex_str2hex(temp
, (temp1
- temp
), &ret
);
1850 if (ret
== IBNEX_SUCCESS
) {
1851 if (ioc_guid_strp
) {
1852 ioc_guid_str
= *ioc_guid_strp
= kmem_zalloc((temp1
1853 - temp
) + 1, KM_SLEEP
);
1854 (void) strncpy(ioc_guid_str
, temp
, temp1
- temp
+ 1);
1855 ioc_guid_str
[temp1
- temp
] = '\0';
1857 len
= device_name
+ strlen(device_name
) - ++temp1
;
1858 *iou_guid
= ibnex_str2hex(temp1
, len
, &ret
);
1865 * ibnex_ioc_initnode()
1866 * Allocate a pathinfo node for the IOC
1867 * Initialize the device node
1868 * Bind driver to the node
1869 * Update IBnex global data
1870 * Returns IBNEX_SUCCESS/IBNEX_FAILURE/IBNEX_BUSY
1873 ibnex_ioc_initnode_pdip(ibnex_node_data_t
*node_data
,
1874 ibdm_ioc_info_t
*ioc_info
, dev_info_t
*pdip
)
1876 int rval
, node_valid
;
1877 ibnex_node_state_t prev_state
;
1879 ASSERT(MUTEX_HELD(&ibnex
.ibnex_mutex
));
1884 * Return EBUSY if another configure/unconfigure
1885 * operation is in progress
1887 if (node_data
->node_state
== IBNEX_CFGADM_UNCONFIGURING
) {
1888 IBTF_DPRINTF_L4("ibnex",
1889 "\tioc_initnode_pdip : BUSY");
1890 return (IBNEX_BUSY
);
1893 prev_state
= node_data
->node_state
;
1894 node_data
->node_state
= IBNEX_CFGADM_CONFIGURING
;
1895 mutex_exit(&ibnex
.ibnex_mutex
);
1897 rval
= ibnex_ioc_create_pi(ioc_info
, node_data
, pdip
, &node_valid
);
1899 mutex_enter(&ibnex
.ibnex_mutex
);
1900 if (rval
== IBNEX_SUCCESS
)
1901 node_data
->node_state
= IBNEX_CFGADM_CONFIGURED
;
1902 else if (node_valid
)
1903 node_data
->node_state
= prev_state
;
1909 * ibnex_config_pseudo_all()
1910 * Configure all the pseudo nodes
1913 ibnex_config_pseudo_all(dev_info_t
*pdip
)
1915 ibnex_node_data_t
*nodep
;
1917 ASSERT(MUTEX_HELD(&ibnex
.ibnex_mutex
));
1919 for (nodep
= ibnex
.ibnex_pseudo_node_head
;
1920 nodep
; nodep
= nodep
->node_next
) {
1921 (void) ibnex_pseudo_config_one(nodep
, NULL
, pdip
);
1927 * ibnex_pseudo_config_one()
1930 ibnex_pseudo_config_one(ibnex_node_data_t
*node_data
, char *caddr
,
1934 ibnex_pseudo_node_t
*pseudo
;
1935 ibnex_node_state_t prev_state
;
1937 IBTF_DPRINTF_L4("ibnex", "\tpseudo_config_one(%p, %p, %p)",
1938 node_data
, caddr
, pdip
);
1940 ASSERT(MUTEX_HELD(&ibnex
.ibnex_mutex
));
1942 if (node_data
== NULL
) {
1943 IBTF_DPRINTF_L4("ibnex",
1944 "\tpseudo_config_one: caddr = %s", caddr
);
1947 * This function is now called with PHCI / HCA driver
1948 * as parent. The format of devicename is :
1949 * <driver_name>@<driver_name>,<unit_address>
1950 * The "caddr" part of the devicename matches the
1951 * format of pseudo_node_addr.
1953 * Use "caddr" to find a matching Pseudo node entry.
1955 node_data
= ibnex_is_node_data_present(IBNEX_PSEUDO_NODE
,
1956 (void *)caddr
, 0, 0);
1959 if (node_data
== NULL
) {
1960 IBTF_DPRINTF_L2("ibnex",
1961 "\tpseudo_config_one: Invalid node");
1962 return (IBNEX_FAILURE
);
1965 if (node_data
->node_ap_state
== IBNEX_NODE_AP_UNCONFIGURED
) {
1966 IBTF_DPRINTF_L4("ibnex",
1967 "\tpseudo_config_one: Unconfigured node");
1968 return (IBNEX_FAILURE
);
1971 pseudo
= &node_data
->node_data
.pseudo_node
;
1974 * Do not enumerate nodes with ib-node-type set as "merge"
1976 if (pseudo
->pseudo_merge_node
== 1) {
1977 IBTF_DPRINTF_L4("ibnex",
1978 "\tpseudo_config_one: merge_node");
1979 return (IBNEX_FAILURE
);
1983 * Check if a PI has already been created for the PDIP.
1984 * If so, return SUCCESS.
1986 if (node_data
->node_dip
!= NULL
&& mdi_pi_find(pdip
,
1987 pseudo
->pseudo_node_addr
, pseudo
->pseudo_node_addr
) != NULL
) {
1988 IBTF_DPRINTF_L4("ibnex",
1989 "\tpseudo_config_one: PI created,"
1990 " pdip %p, addr %s", pdip
, pseudo
->pseudo_node_addr
);
1991 return (IBNEX_SUCCESS
);
1995 * Return EBUSY if another unconfigure
1996 * operation is in progress
1998 if (node_data
->node_state
== IBNEX_CFGADM_UNCONFIGURING
) {
1999 IBTF_DPRINTF_L4("ibnex",
2000 "\tpseudo_config_one: BUSY");
2001 return (IBNEX_BUSY
);
2005 prev_state
= node_data
->node_state
;
2006 node_data
->node_state
= IBNEX_CFGADM_CONFIGURING
;
2008 mutex_exit(&ibnex
.ibnex_mutex
);
2009 rval
= ibnex_pseudo_create_pi_pdip(node_data
, pdip
);
2010 mutex_enter(&ibnex
.ibnex_mutex
);
2012 if (rval
== IBNEX_SUCCESS
) {
2013 node_data
->node_state
= IBNEX_CFGADM_CONFIGURED
;
2015 node_data
->node_state
= prev_state
;
2018 IBTF_DPRINTF_L4("ibnex", "\tpseudo_config_one: ret %x",
2025 * ibnex_pseudo_mdi_config_one()
2026 * This is similar to ibnex_pseudo_config_one. Few
2028 * 1. parent device lock not held(no ndi_devi_enter)
2029 * 2. Called for IB Nexus as parent, not IB HCA as
2031 * 3. Calls mdi_vhci_bus_config()
2032 * This function skips checks for node_state, initializing
2033 * node_state, node_dip, etc. These checks and initializations
2034 * are done when BUS_CONFIG is called with PHCI as the parent.
2037 ibnex_pseudo_mdi_config_one(int flag
, void *devname
, dev_info_t
**child
,
2038 char *cname
, char *caddr
)
2042 ibnex_node_data_t
*node_data
;
2044 IBTF_DPRINTF_L4("ibnex", "\tpseudo_mdi_config_one:"
2045 "cname = %s caddr = %s", cname
, caddr
);
2047 ASSERT(MUTEX_HELD(&ibnex
.ibnex_mutex
));
2049 len
= strlen(cname
) + strlen(caddr
) + 2;
2050 node_addr
= kmem_alloc(len
, KM_SLEEP
);
2052 (void) snprintf(node_addr
, len
, "%s,%s", cname
, caddr
);
2053 node_data
= ibnex_is_node_data_present(IBNEX_PSEUDO_NODE
,
2054 (void *)node_addr
, 0, 0);
2055 kmem_free(node_addr
, len
);
2057 if (node_data
== NULL
) {
2058 IBTF_DPRINTF_L2("ibnex",
2059 "\tpseudo_mdi_config_one: Invalid node");
2060 return (IBNEX_FAILURE
);
2063 mutex_exit(&ibnex
.ibnex_mutex
);
2064 rval
= mdi_vhci_bus_config(ibnex
.ibnex_dip
, flag
, BUS_CONFIG_ONE
,
2065 devname
, child
, node_data
->node_data
.pseudo_node
.pseudo_node_addr
);
2066 mutex_enter(&ibnex
.ibnex_mutex
);
2073 * ibnex_pseudo_create_all_pi()
2074 * Create all path infos node for a pseudo entry
2077 ibnex_pseudo_create_all_pi(ibnex_node_data_t
*nodep
)
2081 dev_info_t
*hca_dip
;
2082 ibdm_hca_list_t
*hca_list
, *head
;
2084 IBTF_DPRINTF_L4("ibnex", "\tpseudo_create_all_pi(%p)",
2086 ibdm_ibnex_get_hca_list(&hca_list
, &hcacnt
);
2091 * We return failure even if we fail for all HCAs.
2093 for (; hca_list
!= NULL
; hca_list
= hca_list
->hl_next
) {
2094 hca_dip
= ibtl_ibnex_hcaguid2dip(hca_list
->hl_hca_guid
);
2095 rc
= ibnex_pseudo_create_pi_pdip(nodep
, hca_dip
);
2096 if (rc
!= IBNEX_SUCCESS
)
2100 ibdm_ibnex_free_hca_list(head
);
2102 if (hcafailcnt
== hcacnt
)
2107 IBTF_DPRINTF_L4("ibnex", "\tpseudo_create_all_pi rc %x",
2113 ibnex_pseudo_create_pi_pdip(ibnex_node_data_t
*nodep
, dev_info_t
*hca_dip
)
2115 mdi_pathinfo_t
*pip
;
2117 dev_info_t
*cdip
= NULL
;
2118 ibnex_pseudo_node_t
*pseudo
;
2121 IBTF_DPRINTF_L4("ibnex", "\tpseudo_create_pi_pdip: %p, %p",
2124 pseudo
= &nodep
->node_data
.pseudo_node
;
2126 rval
= mdi_pi_alloc(hca_dip
,
2127 pseudo
->pseudo_devi_name
, pseudo
->pseudo_node_addr
,
2128 pseudo
->pseudo_node_addr
, 0, &pip
);
2130 if (rval
!= MDI_SUCCESS
) {
2131 IBTF_DPRINTF_L2("ibnex", "\tpseudo_create_pi_pdip:"
2132 " mdi_pi_alloc failed");
2133 return (IBNEX_FAILURE
);
2135 cdip
= mdi_pi_get_client(pip
);
2137 if (nodep
->node_dip
== NULL
) {
2138 IBTF_DPRINTF_L4("ibnex",
2139 "\tpseudo_create_pi: New dip %p", cdip
);
2142 nodep
->node_dip
= cdip
;
2143 ddi_set_parent_data(cdip
, nodep
);
2146 rval
= mdi_pi_online(pip
, 0);
2148 if (rval
!= MDI_SUCCESS
) {
2149 IBTF_DPRINTF_L2("ibnex",
2150 "\tpseudo_create_pi: "
2151 "mdi_pi_online: failed for pseudo dip %p,"
2152 " rval %d", cdip
, rval
);
2153 rval
= IBNEX_FAILURE
;
2154 if (first_pi
== 1) {
2155 ddi_set_parent_data(cdip
, NULL
);
2156 (void) ibnex_offline_childdip(cdip
);
2157 nodep
->node_dip
= NULL
;
2159 (void) mdi_pi_free(pip
, 0);
2161 rval
= IBNEX_SUCCESS
;
2166 * ibnex_ioc_create_pi()
2167 * Create a pathinfo node for the ioc node
2170 ibnex_ioc_create_pi(ibdm_ioc_info_t
*ioc_info
, ibnex_node_data_t
*node_data
,
2171 dev_info_t
*pdip
, int *node_valid
)
2173 mdi_pathinfo_t
*pip
;
2174 int rval
= DDI_FAILURE
;
2175 dev_info_t
*cdip
= NULL
;
2176 int create_prop
= 0;
2177 ibnex_ioc_node_t
*ioc
= &node_data
->node_data
.ioc_node
;
2179 IBTF_DPRINTF_L4("ibnex",
2180 "\tibnex_ioc_create_pi(%p, %p, %p)", ioc_info
, node_data
, pdip
);
2184 * For CONFIG_ONE requests through HCA dip, alloc
2185 * for HCA dip driving BUS_CONFIG request.
2187 rval
= mdi_pi_alloc(pdip
, IBNEX_IOC_CNAME
, ioc
->ioc_guid_str
,
2188 ioc
->ioc_phci_guid
, 0, &pip
);
2189 if (rval
!= MDI_SUCCESS
) {
2190 IBTF_DPRINTF_L2("ibnex",
2191 "\tioc_create_pi: mdi_pi_alloc(%p, %s. %s) failed",
2192 pdip
, ioc
->ioc_guid_str
, ioc
->ioc_phci_guid
);
2193 return (IBNEX_FAILURE
);
2195 cdip
= mdi_pi_get_client(pip
);
2197 IBTF_DPRINTF_L4("ibnex", "\tioc_create_pi: IOC dip %p",
2200 if (node_data
->node_dip
== NULL
) {
2201 node_data
->node_dip
= cdip
;
2202 ddi_set_parent_data(cdip
, node_data
);
2204 IBTF_DPRINTF_L4("ibnex",
2205 "\tioc_create_pi: creating prop");
2206 if ((rval
= ibnex_create_ioc_node_prop(
2207 ioc_info
, cdip
)) != IBNEX_SUCCESS
) {
2208 IBTF_DPRINTF_L4("ibnex",
2209 "\tioc_create_pi: creating prop failed");
2210 ibnex_delete_ioc_node_data(node_data
);
2212 ddi_prop_remove_all(cdip
);
2213 ddi_set_parent_data(cdip
, NULL
);
2215 (void) ibnex_offline_childdip(cdip
);
2216 return (IBNEX_FAILURE
);
2220 rval
= mdi_pi_online(pip
, 0);
2222 if (rval
!= MDI_SUCCESS
) {
2223 IBTF_DPRINTF_L2("ibnex", "\tioc_create_pi: "
2224 "mdi_pi_online() failed ioc dip %p, rval %d",
2226 rval
= IBNEX_FAILURE
;
2228 ddi_set_parent_data(cdip
, NULL
);
2229 ddi_prop_remove_all(cdip
);
2230 ibnex_delete_ioc_node_data(node_data
);
2232 (void) ibnex_offline_childdip(cdip
);
2234 (void) mdi_pi_free(pip
, 0);
2236 rval
= IBNEX_SUCCESS
;
2238 IBTF_DPRINTF_L4("ibnex", "\tioc_create_pi ret %x", rval
);
2244 * ibnex_create_ioc_node_prop()
2245 * Create IOC device node properties
2246 * Returns IBNEX_SUCCESS/IBNEX_FAILURE
2249 ibnex_create_ioc_node_prop(ibdm_ioc_info_t
*ioc_info
, dev_info_t
*cdip
)
2251 uint16_t capabilities
;
2252 ib_dm_ioc_ctrl_profile_t
*ioc_profile
= &ioc_info
->ioc_profile
;
2254 IBTF_DPRINTF_L4("ibnex", "\tcreate_ioc_node_prop");
2256 if (ibnex_create_ioc_compatible_prop(cdip
,
2257 ioc_profile
) != IBNEX_SUCCESS
) {
2258 return (IBNEX_FAILURE
);
2260 if ((ioc_info
->ioc_iou_dc_valid
) &&
2261 (ndi_prop_update_int(DDI_DEV_T_NONE
, cdip
, "iou-diagcode",
2262 ioc_info
->ioc_iou_diagcode
)) != DDI_PROP_SUCCESS
) {
2263 IBTF_DPRINTF_L2("ibnex",
2264 "\tcreate_ioc_node_prop: iou-diagcode create failed");
2265 return (IBNEX_FAILURE
);
2267 if ((ioc_info
->ioc_diagdeviceid
) && (ioc_info
->ioc_dc_valid
)) {
2268 if (ndi_prop_update_int(DDI_DEV_T_NONE
, cdip
, "ioc-diagcode",
2269 ioc_info
->ioc_diagcode
) != DDI_PROP_SUCCESS
) {
2270 IBTF_DPRINTF_L2("ibnex", "\tcreate_ioc_node_prop: "
2271 "ioc-diagcode create failed");
2272 return (IBNEX_FAILURE
);
2275 if (ndi_prop_update_int(DDI_DEV_T_NONE
, cdip
, "rdma-queue-depth",
2276 ioc_profile
->ioc_rdma_read_qdepth
) != DDI_PROP_SUCCESS
) {
2277 IBTF_DPRINTF_L2("ibnex",
2278 "\tcreate_ioc_node_prop: rdma-queue-depth create failed");
2279 return (IBNEX_FAILURE
);
2281 if (ndi_prop_update_int(DDI_DEV_T_NONE
, cdip
, "rdma-transfer-size",
2282 ioc_profile
->ioc_rdma_xfer_sz
) != DDI_PROP_SUCCESS
) {
2283 IBTF_DPRINTF_L2("ibnex", "\tcreate_ioc_node_prop: "
2284 "rdma-transfer-size create failed");
2285 return (IBNEX_FAILURE
);
2287 if (ndi_prop_update_int(DDI_DEV_T_NONE
, cdip
, "send-message-size",
2288 ioc_profile
->ioc_send_msg_sz
) != DDI_PROP_SUCCESS
) {
2289 IBTF_DPRINTF_L2("ibnex",
2290 "\tcreate_ioc_node_prop: send-message-size create failed");
2291 return (IBNEX_FAILURE
);
2293 if (ndi_prop_update_int(DDI_DEV_T_NONE
, cdip
, "send-queue-depth",
2294 ioc_profile
->ioc_send_msg_qdepth
) != DDI_PROP_SUCCESS
) {
2295 IBTF_DPRINTF_L2("ibnex",
2296 "\tcreate_ioc_node_prop: send-queue-depth create failed");
2297 return (IBNEX_FAILURE
);
2300 capabilities
= (ioc_profile
->ioc_ctrl_opcap_mask
<< 8);
2301 if (ndi_prop_update_int(DDI_DEV_T_NONE
, cdip
,
2302 "capabilities", capabilities
) != DDI_PROP_SUCCESS
) {
2303 IBTF_DPRINTF_L2("ibnex",
2304 "\tcreate_ioc_node_prop: capabilities create failed");
2305 return (IBNEX_FAILURE
);
2307 if (ndi_prop_update_string(DDI_DEV_T_NONE
, cdip
, "id-string",
2308 (char *)ioc_profile
->ioc_id_string
) != DDI_PROP_SUCCESS
) {
2309 IBTF_DPRINTF_L2("ibnex",
2310 "\tcreate_ioc_node_prop: id-string failed");
2311 return (IBNEX_FAILURE
);
2315 * Create properties to represent all the service entries supported
2316 * by the IOC. Each service entry consists of 1) Service ID (64 bits)
2317 * and 2) Service name (40 bytes). The service entry table is
2318 * represented by two properties, service-ids and service-names. The
2319 * service-id property is a array of int64's and service names is
2320 * array of strings. The first element in the "service-ids" property
2321 * corresponds to first string in the "service-names" and so on.
2323 if ((ioc_profile
->ioc_service_entries
!= 0) &&
2324 (ibnex_create_ioc_srv_props(cdip
, ioc_info
) != IBNEX_SUCCESS
))
2325 return (IBNEX_FAILURE
);
2327 /* Create destination port GID properties */
2328 if (ibnex_create_ioc_portgid_prop(cdip
, ioc_info
) != IBNEX_SUCCESS
)
2329 return (IBNEX_FAILURE
);
2331 if (ndi_prop_update_int(DDI_DEV_T_NONE
, cdip
, "protocol-version",
2332 ioc_profile
->ioc_protocol_ver
) != DDI_PROP_SUCCESS
) {
2333 IBTF_DPRINTF_L2("ibnex",
2334 "\tcreate_ioc_node_prop: protocol-version create failed");
2335 return (IBNEX_FAILURE
);
2337 if (ndi_prop_update_int(DDI_DEV_T_NONE
, cdip
, "protocol",
2338 ioc_profile
->ioc_protocol
) != DDI_PROP_SUCCESS
) {
2339 IBTF_DPRINTF_L2("ibnex",
2340 "\tcreate_ioc_node_prop: protocol create failed");
2341 return (IBNEX_FAILURE
);
2343 if (ndi_prop_update_int(DDI_DEV_T_NONE
, cdip
, "io-subclass",
2344 ioc_profile
->ioc_io_subclass
) != DDI_PROP_SUCCESS
) {
2345 IBTF_DPRINTF_L2("ibnex",
2346 "\tcreate_ioc_node_prop: subclass create failed");
2347 return (IBNEX_FAILURE
);
2349 if (ndi_prop_update_int(DDI_DEV_T_NONE
, cdip
, "io-class",
2350 ioc_profile
->ioc_io_class
) != DDI_PROP_SUCCESS
) {
2351 IBTF_DPRINTF_L2("ibnex",
2352 "\tcreate_ioc_node_prop: class prop create failed");
2353 return (IBNEX_FAILURE
);
2355 if (ndi_prop_update_int(DDI_DEV_T_NONE
, cdip
, "subsystem-id",
2356 ioc_profile
->ioc_subsys_id
) != DDI_PROP_SUCCESS
) {
2357 IBTF_DPRINTF_L2("ibnex",
2358 "\tcreate_ioc_node_prop: subsys_id create failed");
2359 return (IBNEX_FAILURE
);
2361 if (ndi_prop_update_int(DDI_DEV_T_NONE
, cdip
, "subsystem-vendor-id",
2362 ioc_profile
->ioc_subsys_vendorid
) != DDI_PROP_SUCCESS
) {
2363 IBTF_DPRINTF_L2("ibnex",
2364 "\tcreate_ioc_node_prop: subsystem vendor create failed");
2365 return (IBNEX_FAILURE
);
2367 if (ndi_prop_update_int64(DDI_DEV_T_NONE
, cdip
, "ioc-guid",
2368 ioc_profile
->ioc_guid
) != DDI_PROP_SUCCESS
) {
2369 IBTF_DPRINTF_L2("ibnex",
2370 "\tcreate_ioc_node_prop: protocol create failed");
2371 return (IBNEX_FAILURE
);
2373 if (ndi_prop_update_int(DDI_DEV_T_NONE
, cdip
, "device-version",
2374 ioc_profile
->ioc_device_ver
) != DDI_PROP_SUCCESS
) {
2375 IBTF_DPRINTF_L2("ibnex",
2376 "\tcreate_ioc_node_prop: product-id create failed");
2377 return (IBNEX_FAILURE
);
2379 if (ndi_prop_update_int(DDI_DEV_T_NONE
, cdip
, "device-id",
2380 ioc_profile
->ioc_deviceid
) != DDI_PROP_SUCCESS
) {
2381 IBTF_DPRINTF_L2("ibnex",
2382 "\tcreate_ioc_node_prop: product-id create failed");
2383 return (IBNEX_FAILURE
);
2385 if (ndi_prop_update_int(DDI_DEV_T_NONE
, cdip
, "vendor-id",
2386 ioc_profile
->ioc_vendorid
) != DDI_PROP_SUCCESS
) {
2387 IBTF_DPRINTF_L2("ibnex",
2388 "\tcreate_ioc_node_prop: vendor-id create failed");
2389 return (IBNEX_FAILURE
);
2391 return (IBNEX_SUCCESS
);
2396 * ibnex_create_ioc_portgid_prop()
2397 * Creates "port-entries", "port-list" properties
2398 * Returns IBNEX_SUCCESS/IBNEX_FAILURE
2401 ibnex_create_ioc_portgid_prop(
2402 dev_info_t
*cdip
, ibdm_ioc_info_t
*ioc_info
)
2404 uint64_t *port_gids
;
2407 ibnex_node_data_t
*node_data
;
2409 IBTF_DPRINTF_L4("ibnex", "\tcreate_ioc_portgid_prop");
2411 node_data
= ddi_get_parent_data(cdip
);
2414 prop_len
= (ioc_info
->ioc_nportgids
!= 0) ?
2415 (2 * ioc_info
->ioc_nportgids
) : 1;
2416 length
= sizeof (uint64_t) * prop_len
;
2417 port_gids
= kmem_zalloc(length
, KM_SLEEP
);
2419 for (ii
= 0, jj
= 0; ii
< ioc_info
->ioc_nportgids
; ii
++) {
2420 port_gids
[jj
++] = ioc_info
->ioc_gid_list
[ii
].gid_dgid_hi
;
2421 port_gids
[jj
++] = ioc_info
->ioc_gid_list
[ii
].gid_dgid_lo
;
2423 if (ndi_prop_update_int64_array(DDI_DEV_T_NONE
, cdip
, "port-list",
2424 (int64_t *)port_gids
, prop_len
) != DDI_PROP_SUCCESS
) {
2425 IBTF_DPRINTF_L2("ibnex",
2426 "\tcreate_ioc_portgid_prop: port-list create failed");
2427 kmem_free(port_gids
, length
);
2428 return (IBNEX_FAILURE
);
2430 if (ndi_prop_update_int(DDI_DEV_T_NONE
, cdip
, "port-entries",
2431 ioc_info
->ioc_nportgids
) != DDI_PROP_SUCCESS
) {
2432 IBTF_DPRINTF_L2("ibnex",
2433 "\tcreate_ioc_portgid_prop: port-entries create failed");
2434 kmem_free(port_gids
, length
);
2435 return (IBNEX_FAILURE
);
2438 kmem_free(port_gids
, length
);
2439 return (IBNEX_SUCCESS
);
2444 * ibnex_create_ioc_srv_props()
2445 * Creates "service-name" and "service-id" properties
2446 * Returns IBNEX_SUCCESS/IBNEX_FAILURE
2449 ibnex_create_ioc_srv_props(
2450 dev_info_t
*cdip
, ibdm_ioc_info_t
*ioc_info
)
2454 char *temp
, *srv_names
[IB_DM_MAX_IOCS_IN_IOU
];
2455 ib_dm_ioc_ctrl_profile_t
*profile
= &ioc_info
->ioc_profile
;
2456 ibdm_srvents_info_t
*srvents
= ioc_info
->ioc_serv
;
2458 IBTF_DPRINTF_L4("ibnex", "\tcreate_ioc_srv_props");
2460 length
= profile
->ioc_service_entries
* sizeof (ib_dm_srv_t
);
2461 srv_id
= kmem_zalloc(length
, KM_SLEEP
);
2462 temp
= (char *)((char *)srv_id
+ (8 * profile
->ioc_service_entries
));
2463 for (ii
= 0; ii
< profile
->ioc_service_entries
; ii
++) {
2464 srv_names
[ii
] = (char *)temp
+ (ii
* IB_DM_MAX_SVC_NAME_LEN
);
2467 for (ii
= 0; ii
< profile
->ioc_service_entries
; ii
++) {
2468 srv_id
[ii
] = srvents
[ii
].se_attr
.srv_id
;
2469 bcopy(srvents
[ii
].se_attr
.srv_name
,
2470 srv_names
[ii
], (IB_DM_MAX_SVC_NAME_LEN
- 1));
2471 IBTF_DPRINTF_L4("ibnex", "\tcreate_ioc_srv_props "
2472 "Service Names : %s", srv_names
[ii
]);
2473 IBTF_DPRINTF_L4("ibnex", "\tcreate_ioc_srv_props "
2474 "Service ID : %llX", srv_id
[ii
]);
2477 if (ndi_prop_update_int64_array(DDI_DEV_T_NONE
, cdip
,
2478 "service-id", (int64_t *)srv_id
,
2479 profile
->ioc_service_entries
) != DDI_PROP_SUCCESS
) {
2480 IBTF_DPRINTF_L2("ibnex",
2481 "\tcreate_ioc_srv_props: service-id create failed");
2482 kmem_free(srv_id
, length
);
2483 return (IBNEX_FAILURE
);
2486 if (ndi_prop_update_string_array(DDI_DEV_T_NONE
, cdip
,
2487 "service-name", (char **)srv_names
,
2488 profile
->ioc_service_entries
) != DDI_PROP_SUCCESS
) {
2489 IBTF_DPRINTF_L2("ibnex",
2490 "\tcreate_ioc_srv_props: service-name create failed");
2491 kmem_free(srv_id
, length
);
2492 return (IBNEX_FAILURE
);
2494 kmem_free(srv_id
, length
);
2495 return (IBNEX_SUCCESS
);
2500 * ibnex_create_ioc_compatible_prop()
2501 * Creates "compatible" property values
2502 * Returns IBNEX_SUCCESS/IBNEX_FAILURE
2505 ibnex_create_ioc_compatible_prop(
2506 dev_info_t
*cdip
, ib_dm_ioc_ctrl_profile_t
*ioc_profile
)
2510 char *compatible
[IBNEX_MAX_COMPAT_NAMES
];
2513 * Initialize the "compatible" property string as below:
2514 * Compatible Strings :
2515 * 1. ib.V<vid>P<pid>S<subsys vid>s<subsys id>v<ver>
2516 * 2. ib.V<vid>P<pid>S<subsys vid>s<subsys id>
2517 * 3. ib.V<vid>P<pid>v<ver>
2518 * 4. ib.V<vid>P<pid>
2519 * 5. ib.C<Class>c<Subclass>p<protocol>r<protocol ver>
2520 * 6. ib.C<Class>c<Subclass>p<protocol>
2523 * All leading zeros must be present
2524 * All numeric values must specified in hex without prefix "0x"
2527 temp
= kmem_alloc(IBNEX_MAX_COMPAT_PROP_SZ
, KM_SLEEP
);
2528 for (ii
= 0; ii
< IBNEX_MAX_COMPAT_NAMES
; ii
++)
2529 compatible
[ii
] = temp
+ (ii
* IBNEX_MAX_COMPAT_LEN
);
2531 (void) snprintf(compatible
[0], IBNEX_MAX_COMPAT_LEN
,
2532 "ib.V%06xP%08xS%06xs%08xv%04x",
2533 ioc_profile
->ioc_vendorid
, ioc_profile
->ioc_deviceid
,
2534 ioc_profile
->ioc_subsys_vendorid
, ioc_profile
->ioc_subsys_id
,
2535 ioc_profile
->ioc_device_ver
);
2537 (void) snprintf(compatible
[1], IBNEX_MAX_COMPAT_LEN
,
2538 "ib.V%06xP%08xS%06xs%08x",
2539 ioc_profile
->ioc_vendorid
, ioc_profile
->ioc_deviceid
,
2540 ioc_profile
->ioc_subsys_vendorid
, ioc_profile
->ioc_subsys_id
);
2542 (void) snprintf(compatible
[2], IBNEX_MAX_COMPAT_LEN
,
2543 "ib.V%06xP%08xv%04x",
2544 ioc_profile
->ioc_vendorid
, ioc_profile
->ioc_deviceid
,
2545 ioc_profile
->ioc_device_ver
);
2547 (void) snprintf(compatible
[3], IBNEX_MAX_COMPAT_LEN
,
2549 ioc_profile
->ioc_vendorid
, ioc_profile
->ioc_deviceid
);
2551 (void) snprintf(compatible
[4], IBNEX_MAX_COMPAT_LEN
,
2552 "ib.C%04xc%04xp%04xr%04x",
2553 ioc_profile
->ioc_io_class
, ioc_profile
->ioc_io_subclass
,
2554 ioc_profile
->ioc_protocol
, ioc_profile
->ioc_protocol_ver
);
2556 (void) snprintf(compatible
[5], IBNEX_MAX_COMPAT_LEN
,
2557 "ib.C%04xc%04xp%04x",
2558 ioc_profile
->ioc_io_class
, ioc_profile
->ioc_io_subclass
,
2559 ioc_profile
->ioc_protocol
);
2560 for (ii
= 0; ii
< IBNEX_MAX_COMPAT_NAMES
; ii
++)
2561 IBTF_DPRINTF_L4("ibnex", "\tcompatible: %s", compatible
[ii
]);
2563 /* Create the compatible property for child cdip */
2564 rval
= ndi_prop_update_string_array(DDI_DEV_T_NONE
, cdip
,
2565 "compatible", (char **)compatible
, IBNEX_MAX_COMPAT_NAMES
);
2567 if (rval
!= DDI_PROP_SUCCESS
) {
2568 IBTF_DPRINTF_L2("ibnex", "\tcompatible prop_create failed");
2569 kmem_free(temp
, IBNEX_MAX_COMPAT_PROP_SZ
);
2570 return (IBNEX_FAILURE
);
2573 kmem_free(temp
, IBNEX_MAX_COMPAT_PROP_SZ
);
2574 return (IBNEX_SUCCESS
);
2579 ibnex_ioc_node_cleanup()
2581 ibnex_node_data_t
*node
, *delete;
2583 ASSERT(MUTEX_HELD(&ibnex
.ibnex_mutex
));
2584 for (node
= ibnex
.ibnex_ioc_node_head
; node
; ) {
2586 node
= node
->node_next
;
2587 mutex_exit(&ibnex
.ibnex_mutex
);
2588 ibnex_delete_ioc_node_data(delete);
2589 mutex_enter(&ibnex
.ibnex_mutex
);
2594 * ibnex_delete_ioc_node_data()
2595 * Delete IOC node from the list
2598 ibnex_delete_ioc_node_data(ibnex_node_data_t
*node
)
2600 IBTF_DPRINTF_L4("ibnex", "\tdelete_ioc_node_data:");
2602 mutex_enter(&ibnex
.ibnex_mutex
);
2603 if ((node
->node_next
== NULL
) && (node
->node_prev
== NULL
)) {
2604 ASSERT(ibnex
.ibnex_ioc_node_head
== node
);
2605 ibnex
.ibnex_ioc_node_head
= NULL
;
2606 } else if (node
->node_next
== NULL
)
2607 node
->node_prev
->node_next
= NULL
;
2608 else if (node
->node_prev
== NULL
) {
2609 node
->node_next
->node_prev
= NULL
;
2610 ibnex
.ibnex_ioc_node_head
= node
->node_next
;
2612 node
->node_prev
->node_next
= node
->node_next
;
2613 node
->node_next
->node_prev
= node
->node_prev
;
2615 IBTF_DPRINTF_L4("ibnex", "\tdelete_ioc_node_data: head %p",
2616 ibnex
.ibnex_ioc_node_head
);
2617 mutex_exit(&ibnex
.ibnex_mutex
);
2618 kmem_free(node
, sizeof (ibnex_node_data_t
));
2623 * ibnex_dm_callback()
2625 * This routine is registered with the IBDM during IB nexus attach. It
2626 * is called by the IBDM module when it discovers
2633 ibnex_dm_callback(void *arg
, ibdm_events_t flag
)
2635 char hca_guid
[IBNEX_HCAGUID_STRSZ
];
2636 ibdm_ioc_info_t
*ioc_list
, *ioc
;
2637 ibnex_node_data_t
*node_data
;
2641 IBTF_DPRINTF_L4("ibnex", "\tdm_callback: attr %p event %x", arg
, flag
);
2644 case IBDM_EVENT_HCA_ADDED
:
2645 (void) snprintf(hca_guid
, IBNEX_HCAGUID_STRSZ
, "%llX",
2646 (*(longlong_t
*)arg
));
2647 /* Create a devctl minor node for the HCA's port */
2648 if (ddi_create_minor_node(ibnex
.ibnex_dip
, hca_guid
, S_IFCHR
,
2649 ddi_get_instance(ibnex
.ibnex_dip
),
2650 DDI_NT_IB_ATTACHMENT_POINT
, 0) != DDI_SUCCESS
) {
2651 IBTF_DPRINTF_L4("ibnex", "\tdm_callback: failed to "
2652 "create minor node for port w/ guid %s", hca_guid
);
2655 guid
= kmem_alloc(sizeof (ib_guid_t
), KM_SLEEP
);
2656 *guid
= *(ib_guid_t
*)arg
;
2657 if (ddi_taskq_dispatch(ibnex
.ibnex_taskq_id
,
2658 ibnex_handle_hca_attach
, guid
, DDI_NOSLEEP
)
2660 kmem_free(guid
, sizeof (ib_guid_t
));
2661 IBTF_DPRINTF_L4("ibnex", "\tdm_callback: failed to "
2662 "dispatch HCA add event for guid %s", hca_guid
);
2667 case IBDM_EVENT_HCA_REMOVED
:
2668 (void) snprintf(hca_guid
, IBNEX_HCAGUID_STRSZ
, "%llX",
2669 (*(longlong_t
*)arg
));
2670 ddi_remove_minor_node(ibnex
.ibnex_dip
, hca_guid
);
2673 case IBDM_EVENT_IOC_PROP_UPDATE
:
2674 ioc
= ioc_list
= (ibdm_ioc_info_t
*)arg
;
2675 if (ioc_list
== NULL
)
2678 mutex_enter(&ibnex
.ibnex_mutex
);
2680 if ((node_data
= ibnex_is_node_data_present(
2681 IBNEX_IOC_NODE
, ioc_list
, 0, 0)) != NULL
&&
2682 node_data
->node_dip
!= NULL
) {
2683 ibnex_update_prop(node_data
, ioc_list
);
2685 ioc_list
= ioc_list
->ioc_next
;
2687 mutex_exit(&ibnex
.ibnex_mutex
);
2688 ibdm_ibnex_free_ioc_list(ioc
);
2691 case IBDM_EVENT_PORT_UP
:
2692 case IBDM_EVENT_PORT_PKEY_CHANGE
:
2693 phci
= ibtl_ibnex_hcaguid2dip(*(longlong_t
*)arg
);
2694 (void) devfs_clean(phci
, NULL
, 0);
2704 * ibnex_get_node_and_dip_from_guid()
2706 * Searches the linked list of the port nodes and returns the dip for
2707 * the of the Port / Node guid requested.
2708 * Returns NULL if not found
2711 ibnex_get_node_and_dip_from_guid(ib_guid_t guid
, int index
, ib_pkey_t pkey
,
2712 ibnex_node_data_t
**nodep
, dev_info_t
**dip
)
2715 ib_guid_t node_guid
;
2716 ib_pkey_t node_pkey
;
2717 ibnex_node_data_t
*node_data
;
2719 IBTF_DPRINTF_L4("ibnex",
2720 "\tget_node_and_dip_from_guid: guid = %llX", guid
);
2722 ASSERT(MUTEX_HELD(&ibnex
.ibnex_mutex
));
2723 /* Search for a matching entry in internal lists */
2724 node_data
= ibnex
.ibnex_port_node_head
;
2726 node_guid
= node_data
->node_data
.port_node
.port_guid
;
2727 node_index
= node_data
->node_data
.port_node
.port_commsvc_idx
;
2728 node_pkey
= node_data
->node_data
.port_node
.port_pkey
;
2729 if ((node_guid
== guid
) && (index
== node_index
) &&
2730 (node_pkey
== pkey
)) {
2733 node_data
= node_data
->node_next
;
2736 /* matching found with a valid dip */
2737 if (node_data
&& node_data
->node_dip
) {
2739 *dip
= node_data
->node_dip
;
2740 return (IBNEX_SUCCESS
);
2741 } else if (node_data
&& !node_data
->node_dip
) { /* dip is invalid */
2744 return (IBNEX_SUCCESS
);
2747 /* no match found */
2750 return (IBNEX_FAILURE
);
2754 * ibnex_get_dip_from_guid()
2756 * Searches the linked list of the port nodes and returns the dip for
2757 * the of the Port / Node guid requested.
2758 * Returns NULL if not found
2761 ibnex_get_dip_from_guid(ib_guid_t guid
, int index
, ib_pkey_t pkey
,
2765 ib_guid_t node_guid
;
2766 ib_pkey_t node_pkey
;
2767 ibnex_node_data_t
*node_data
;
2769 IBTF_DPRINTF_L4("ibnex",
2770 "\tget_dip_from_guid: guid = %llX", guid
);
2772 ASSERT(MUTEX_HELD(&ibnex
.ibnex_mutex
));
2773 /* Search for a matching entry in internal lists */
2774 node_data
= ibnex
.ibnex_port_node_head
;
2776 node_guid
= node_data
->node_data
.port_node
.port_guid
;
2777 node_index
= node_data
->node_data
.port_node
.port_commsvc_idx
;
2778 node_pkey
= node_data
->node_data
.port_node
.port_pkey
;
2779 if ((node_guid
== guid
) && (index
== node_index
) &&
2780 (node_pkey
== pkey
)) {
2783 node_data
= node_data
->node_next
;
2786 /* matching found with a valid dip */
2787 if (node_data
&& node_data
->node_dip
) {
2788 *dip
= node_data
->node_dip
;
2789 return (IBNEX_SUCCESS
);
2790 } else if (node_data
&& !node_data
->node_dip
) { /* dip is invalid */
2792 return (IBNEX_SUCCESS
);
2795 /* no match found */
2797 return (IBNEX_FAILURE
);
2802 * ibnex_comm_svc_init()
2803 * Read the property and cache the values in the global
2805 * Check for max allowed length (4 bytes) of service name
2806 * (each element of the property)
2807 * Returns IBNEX_SUCCESS/IBNEX_FAILURE
2810 ibnex_comm_svc_init(char *property
, ibnex_node_type_t type
)
2815 char **servicep
= NULL
;
2816 uint_t nservices
= 0;
2819 IBTF_DPRINTF_L4("ibnex", "\tcomm_svc_init : %s property, type = %x",
2822 /* lookup the string array property */
2823 if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY
, ibnex
.ibnex_dip
,
2824 DDI_PROP_DONTPASS
, property
, &servicep
, &nservices
) !=
2826 IBTF_DPRINTF_L2("ibnex", "\t%s property undefined", property
);
2827 return (IBNEX_SUCCESS
);
2831 valid
= kmem_zalloc(nservices
* sizeof (int), KM_SLEEP
);
2834 /* first read the file to get a count of valid service entries */
2835 for (ncomm_svcs
= 0, count
= 0; count
< nservices
; count
++) {
2838 len
= strlen(servicep
[count
]);
2840 * ib.conf has NULL strings for port-svc-list &
2841 * hca-svc-list, by default. Do not have L2 message
2844 if (len
== 1 || len
> 4) {
2845 IBTF_DPRINTF_L2("ibnex", "\tcomm_svc_init : "
2846 "Service name %s for property %s invalid : "
2847 "length %d", servicep
[count
], property
, len
);
2849 } else if (len
== 0) {
2852 if (ibnex_unique_svcname(servicep
[count
]) != IBNEX_SUCCESS
) {
2853 IBTF_DPRINTF_L2("ibnex", "\tcomm_svc_init : "
2854 "Service name %s invalid : Not unique",
2860 * ibnex_unique_svcname checks for uniqueness in service names
2861 * communication services fully initialized. Check uniqueness
2862 * in service names currently initialized.
2864 for (j
= 0; j
< count
; j
++)
2865 if (valid
[j
] && strncmp(servicep
[count
],
2866 servicep
[j
], 4) == 0) {
2867 IBTF_DPRINTF_L2("ibnex", "\tcomm_svc_init : "
2868 "Service name %s invalid : Not unique",
2877 /* if no valid entries found, bailout */
2878 if (nservices
== 0 || ncomm_svcs
== 0) {
2879 IBTF_DPRINTF_L4("ibnex", "\tNo %s entries found", property
);
2880 ddi_prop_free(servicep
); /* free the property */
2882 kmem_free(valid
, nservices
* sizeof (int));
2883 return (IBNEX_SUCCESS
);
2886 comm_svcp
= kmem_zalloc((ncomm_svcs
* sizeof (char *)), KM_SLEEP
);
2887 if (type
== IBNEX_PORT_COMMSVC_NODE
) {
2888 ibnex
.ibnex_comm_svc_names
= comm_svcp
;
2889 ibnex
.ibnex_num_comm_svcs
= ncomm_svcs
;
2890 } else if (type
== IBNEX_VPPA_COMMSVC_NODE
) {
2891 ibnex
.ibnex_vppa_comm_svc_names
= comm_svcp
;
2892 ibnex
.ibnex_nvppa_comm_svcs
= ncomm_svcs
;
2893 } else if (type
== IBNEX_HCASVC_COMMSVC_NODE
) {
2894 ibnex
.ibnex_hcasvc_comm_svc_names
= comm_svcp
;
2895 ibnex
.ibnex_nhcasvc_comm_svcs
= ncomm_svcs
;
2898 /* copy the services into an array of strings */
2899 for (i
= 0, count
= 0; count
< nservices
; count
++) {
2900 if (valid
[count
] == 0) /* Skip invalid ones */
2902 comm_svcp
[i
] = kmem_alloc(len
+ 1, KM_SLEEP
);
2903 (void) strcpy(comm_svcp
[i
], servicep
[count
]);
2904 IBTF_DPRINTF_L4("ibnex",
2905 "\t\tService [%d]: %s", i
, comm_svcp
[i
]);
2908 ddi_prop_free(servicep
);
2909 kmem_free(valid
, nservices
* sizeof (int));
2910 return (IBNEX_SUCCESS
);
2915 * ibnex_comm_svc_fini()
2916 * Deallocate all the memory allocated for the communication
2920 ibnex_comm_svc_fini()
2924 for (index
= 0; index
< ibnex
.ibnex_num_comm_svcs
; index
++) {
2925 kmem_free(ibnex
.ibnex_comm_svc_names
[index
],
2926 (strlen(ibnex
.ibnex_comm_svc_names
[index
]) + 1));
2928 if (ibnex
.ibnex_comm_svc_names
) {
2929 kmem_free(ibnex
.ibnex_comm_svc_names
,
2930 ibnex
.ibnex_num_comm_svcs
* sizeof (char *));
2932 for (index
= 0; index
< ibnex
.ibnex_nvppa_comm_svcs
; index
++) {
2933 kmem_free(ibnex
.ibnex_vppa_comm_svc_names
[index
],
2934 strlen(ibnex
.ibnex_vppa_comm_svc_names
[index
]) +1);
2936 if (ibnex
.ibnex_vppa_comm_svc_names
) {
2937 kmem_free(ibnex
.ibnex_vppa_comm_svc_names
,
2938 ibnex
.ibnex_nvppa_comm_svcs
* sizeof (char *));
2940 for (index
= 0; index
< ibnex
.ibnex_nhcasvc_comm_svcs
; index
++) {
2941 kmem_free(ibnex
.ibnex_hcasvc_comm_svc_names
[index
],
2942 strlen(ibnex
.ibnex_hcasvc_comm_svc_names
[index
]) +1);
2944 if (ibnex
.ibnex_hcasvc_comm_svc_names
) {
2945 kmem_free(ibnex
.ibnex_hcasvc_comm_svc_names
,
2946 ibnex
.ibnex_nhcasvc_comm_svcs
* sizeof (char *));
2948 ibnex
.ibnex_comm_svc_names
= NULL
;
2949 ibnex
.ibnex_num_comm_svcs
= 0;
2950 ibnex
.ibnex_vppa_comm_svc_names
= NULL
;
2951 ibnex
.ibnex_nvppa_comm_svcs
= 0;
2952 ibnex
.ibnex_hcasvc_comm_svc_names
= NULL
;
2953 ibnex
.ibnex_nhcasvc_comm_svcs
= 0;
2958 * ibnex_commsvc_initnode()
2959 * This routine is specific to port/VPPA node creation
2960 * Creates a device node for the comm service specified by commsvc_index
2961 * Creates all the device node properties
2962 * Allocates and initializes the node specific data
2963 * Binds the device driver of the device node
2964 * Returns "dev_info_t" of the child node or NULL in case of failure
2965 * Sets IBNEX_SUCCESS/IBNEX_FAILURE/IBNEX_BUSY in "rval" to reflect
2966 * if the operation was successful, failed or was not performed.
2969 ibnex_commsvc_initnode(dev_info_t
*parent
, ibdm_port_attr_t
*port_attr
,
2970 int index
, int node_type
, ib_pkey_t pkey
, int *rval
, int flag
)
2975 ibnex_node_data_t
*node_data
;
2976 ibnex_port_node_t
*port_node
;
2977 char devname
[MAXNAMELEN
];
2978 int cdip_allocated
= 0;
2980 ASSERT(MUTEX_HELD(&ibnex
.ibnex_mutex
));
2982 *rval
= IBNEX_SUCCESS
;
2986 * we have seen this node_data and it has been initialized
2987 * Note that node_dip is already NULL if unconfigure is in
2990 node_data
= ibnex_is_node_data_present(node_type
, (void *)port_attr
,
2994 * If this node has been explicity unconfigured by cfgadm, then it can
2995 * be configured back again only by cfgadm configure.
2997 if (node_data
&& (node_data
->node_ap_state
==
2998 IBNEX_NODE_AP_UNCONFIGURED
)) {
2999 *rval
= IBNEX_FAILURE
;
3003 if (node_data
&& node_data
->node_dip
) {
3005 * Return NULL if another configure
3006 * operation is in progress
3008 if (node_data
->node_state
== IBNEX_CFGADM_CONFIGURING
) {
3012 return (node_data
->node_dip
);
3014 } else if (node_data
== NULL
) {
3015 /* allocate a new ibnex_node_data_t */
3016 node_data
= ibnex_init_child_nodedata(node_type
, port_attr
,
3018 node_data
->node_data
.port_node
.port_pdip
= parent
;
3022 * Return NULL if another unconfigure operation is in progress
3024 if (node_data
->node_state
== IBNEX_CFGADM_UNCONFIGURING
) {
3029 ASSERT(node_data
->node_state
!= IBNEX_CFGADM_CONFIGURED
);
3030 node_data
->node_state
= IBNEX_CFGADM_CONFIGURING
;
3032 switch (node_type
) {
3033 case IBNEX_VPPA_COMMSVC_NODE
:
3034 svcname
= ibnex
.ibnex_vppa_comm_svc_names
[index
];
3035 port_node
= &node_data
->node_data
.port_node
;
3036 (void) snprintf(devname
, MAXNAMELEN
, "%s@%x,%x,%s",
3037 IBNEX_IBPORT_CNAME
, port_node
->port_num
,
3038 port_node
->port_pkey
, svcname
);
3040 case IBNEX_HCASVC_COMMSVC_NODE
:
3041 svcname
= ibnex
.ibnex_hcasvc_comm_svc_names
[index
];
3042 port_node
= &node_data
->node_data
.port_node
;
3043 (void) snprintf(devname
, MAXNAMELEN
, "%s@%x,0,%s",
3044 IBNEX_IBPORT_CNAME
, port_node
->port_num
, svcname
);
3046 case IBNEX_PORT_COMMSVC_NODE
:
3047 svcname
= ibnex
.ibnex_comm_svc_names
[index
];
3048 port_node
= &node_data
->node_data
.port_node
;
3049 (void) snprintf(devname
, MAXNAMELEN
, "%s@%x,0,%s",
3050 IBNEX_IBPORT_CNAME
, port_node
->port_num
, svcname
);
3053 IBTF_DPRINTF_L2("ibnex", "\tcommsvc_initnode:"
3054 "\tInvalid Node type");
3055 *rval
= IBNEX_FAILURE
;
3056 ibnex_delete_port_node_data(node_data
);
3060 if ((cdip
= ndi_devi_findchild(parent
, devname
)) != NULL
) {
3061 if (i_ddi_devi_attached(cdip
)) {
3062 node_data
->node_dip
= cdip
;
3063 node_data
->node_data
.port_node
.port_pdip
= parent
;
3064 node_data
->node_state
= IBNEX_CFGADM_CONFIGURED
;
3065 ddi_set_parent_data(cdip
, node_data
);
3066 IBTF_DPRINTF_L4("ibnex", "\tcommsvc_initnode: found "
3067 "attached cdip 0x%p for devname %s", cdip
, devname
);
3071 ndi_devi_alloc_sleep(parent
,
3072 IBNEX_IBPORT_CNAME
, (pnode_t
)DEVI_SID_NODEID
, &cdip
);
3076 node_data
->node_dip
= cdip
;
3077 ddi_set_parent_data(cdip
, node_data
);
3078 mutex_exit(&ibnex
.ibnex_mutex
);
3081 if (ibnex_create_port_node_prop(port_attr
, cdip
, svcname
, pkey
) ==
3083 if (flag
== IBNEX_DEVFS_ENUMERATE
)
3084 ret
= ndi_devi_bind_driver(cdip
, 0);
3086 ret
= ndi_devi_online(cdip
, 0);
3087 if (ret
== NDI_SUCCESS
) {
3088 mutex_enter(&ibnex
.ibnex_mutex
);
3089 node_data
->node_state
= IBNEX_CFGADM_CONFIGURED
;
3090 node_data
->node_data
.port_node
.port_pdip
= parent
;
3093 IBTF_DPRINTF_L4("ibnex", "\tcommsvc_initnode: BIND/ONLINE "
3094 "of cdip 0x%p for devname %s and flag %d failed", cdip
,
3098 *rval
= IBNEX_FAILURE
;
3099 node_data
->node_dip
= NULL
;
3100 ddi_set_parent_data(cdip
, NULL
);
3102 (void) ndi_devi_free(cdip
);
3103 mutex_enter(&ibnex
.ibnex_mutex
);
3104 IBTF_DPRINTF_L4("ibnex", "\tcommsvc_initnode: failure exit");
3110 * ibnex_create_port_node_prop()
3111 * Returns IBNEX_SUCCESS/IBNEX_FAILURE
3114 ibnex_create_port_node_prop(ibdm_port_attr_t
*port_attr
,
3115 dev_info_t
*child_dip
, char *srvname
, ib_pkey_t pkey
)
3117 if (ibnex_create_port_compatible_prop(child_dip
,
3118 srvname
, port_attr
) != DDI_PROP_SUCCESS
) {
3119 IBTF_DPRINTF_L2("ibnex",
3120 "\tcreate_port_node_prop: compatible update failed");
3121 return (IBNEX_FAILURE
);
3123 if ((pkey
!= 0) && (ndi_prop_update_int(DDI_DEV_T_NONE
, child_dip
,
3124 "port-pkey", pkey
) != DDI_PROP_SUCCESS
)) {
3125 IBTF_DPRINTF_L2("ibnex",
3126 "\tcreate_port_node_prop: port-num update failed");
3127 return (IBNEX_FAILURE
);
3131 * For HCA_SVC device nodes, port_num will be 0.
3132 * Do not create the "port-number" & "port-guid" properties.
3134 if (port_attr
->pa_port_num
!= 0) {
3135 if (ndi_prop_update_int(DDI_DEV_T_NONE
, child_dip
,
3136 "port-number", port_attr
->pa_port_num
) !=
3138 IBTF_DPRINTF_L2("ibnex",
3139 "\tcreate_port_node_prop: port-num update failed");
3140 return (IBNEX_FAILURE
);
3142 if (ndi_prop_update_int64(DDI_DEV_T_NONE
, child_dip
,
3143 "port-guid", port_attr
->pa_port_guid
) !=
3145 IBTF_DPRINTF_L2("ibnex",
3146 "\tcreate_port_node_prop: port-guid update failed");
3147 return (IBNEX_FAILURE
);
3150 ibdm_hca_list_t
*hca_list
;
3153 * HCA_SVC nodes require "num-ports" & "port-guids"
3156 * To create the num-ports & port-guids attribute :
3157 * 1. Get HCA list (ibdm_ibnex_get_hca_info_by_guid)
3158 * 2. Form the array of port GUIDs.
3160 if ((hca_list
= ibdm_ibnex_get_hca_info_by_guid(
3161 port_attr
->pa_hca_guid
)) == NULL
) {
3162 IBTF_DPRINTF_L2("ibnex",
3163 "\tcreate_port_node_prop: hca_info_by_guid failed");
3164 return (IBNEX_FAILURE
);
3167 if (hca_list
->hl_nports
!= 0) {
3168 ib_guid_t
*port_guids
;
3171 ASSERT(hca_list
->hl_port_attr
!= NULL
);
3173 port_guids
= kmem_zalloc(
3174 hca_list
->hl_nports
* sizeof (ib_guid_t
),
3177 for (portnum
= 0; portnum
< hca_list
->hl_nports
;
3179 port_guids
[portnum
] = (hca_list
->
3180 hl_port_attr
[portnum
]).pa_port_guid
;
3183 if (ndi_prop_update_int64_array(DDI_DEV_T_NONE
,
3184 child_dip
, "port-guids", (int64_t *)port_guids
,
3185 hca_list
->hl_nports
) != DDI_PROP_SUCCESS
) {
3186 IBTF_DPRINTF_L2("ibnex",
3187 "\tcreate_port_node_prop: port-guids "
3189 kmem_free(port_guids
, hca_list
->hl_nports
*
3190 sizeof (ib_guid_t
));
3191 ibdm_ibnex_free_hca_list(hca_list
);
3192 return (IBNEX_FAILURE
);
3194 kmem_free(port_guids
, hca_list
->hl_nports
*
3195 sizeof (ib_guid_t
));
3198 if (ndi_prop_update_int(DDI_DEV_T_NONE
, child_dip
,
3199 "num-ports", hca_list
->hl_nports
) != DDI_PROP_SUCCESS
) {
3200 IBTF_DPRINTF_L2("ibnex",
3201 "\tcreate_port_node_prop: num-ports update failed");
3202 ibdm_ibnex_free_hca_list(hca_list
);
3203 return (IBNEX_FAILURE
);
3205 ibdm_ibnex_free_hca_list(hca_list
);
3208 if (ndi_prop_update_int64(DDI_DEV_T_NONE
, child_dip
,
3209 "hca-guid", port_attr
->pa_hca_guid
) != DDI_PROP_SUCCESS
) {
3210 IBTF_DPRINTF_L2("ibnex",
3211 "\tcreate_port_node_prop: hca-guid update failed");
3212 return (IBNEX_FAILURE
);
3214 if (ndi_prop_update_int(DDI_DEV_T_NONE
, child_dip
,
3215 "product-id", port_attr
->pa_productid
) != DDI_PROP_SUCCESS
) {
3216 IBTF_DPRINTF_L2("ibnex",
3217 "\tcreate_port_node_prop: product-id update failed");
3218 return (IBNEX_FAILURE
);
3220 if (ndi_prop_update_int(DDI_DEV_T_NONE
, child_dip
,
3221 "vendor-id", port_attr
->pa_vendorid
) != DDI_PROP_SUCCESS
) {
3222 IBTF_DPRINTF_L2("ibnex",
3223 "\tcreate_port_node_prop: vendor-id update failed");
3224 return (IBNEX_FAILURE
);
3226 if (ndi_prop_update_int(DDI_DEV_T_NONE
, child_dip
, "device-version",
3227 port_attr
->pa_dev_version
) != DDI_PROP_SUCCESS
) {
3228 IBTF_DPRINTF_L2("ibnex",
3229 "\tcreate_port_node_prop: device-version update failed");
3230 return (IBNEX_FAILURE
);
3232 return (IBNEX_SUCCESS
);
3238 * Utility function that converts a string of length "len" to
3240 * Returns IBNEX_SUCCESS/IBNEX_FAILURE
3243 ibnex_str2int(char *c
, int len
, int *ret
)
3247 IBTF_DPRINTF_L4("ibnex", "\tstr2int: Int string %s..", c
);
3248 *ret
= IBNEX_SUCCESS
;
3249 for (ii
= 0; ii
< len
; ii
++) {
3250 if ((c
[ii
] >= '0') && (c
[ii
] <= '9'))
3251 intval
= intval
* 10 +c
[ii
] - '0';
3253 IBTF_DPRINTF_L2("ibnex",
3254 "\tstr2int: Invalid integer string %s..", c
);
3255 *ret
= IBNEX_FAILURE
;
3266 * Utility functions that converts a string of length "len" to
3267 * hex value. Note. This function does not handle strings which
3268 * string length more than 8 bytes.
3272 ibnex_str2hex(char *c
, int len
, int *ret
)
3274 uint64_t hex
= 0, ii
;
3276 *ret
= IBNEX_SUCCESS
;
3277 for (ii
= 0; ii
< len
; ii
++) {
3278 hex
= (ii
== 0) ? hex
: (hex
<< 4);
3279 if ((c
[ii
] >= '0') && (c
[ii
] <= '9'))
3281 else if ((c
[ii
] >= 'a') && (c
[ii
] <= 'f'))
3282 hex
|= c
[ii
] - 'a' + 10;
3283 else if ((c
[ii
] >= 'A') && (c
[ii
] <= 'F'))
3284 hex
|= c
[ii
] - 'A' + 10;
3286 IBTF_DPRINTF_L2("ibnex",
3287 "\tstr2hex: Invalid integer string");
3288 *ret
= IBNEX_FAILURE
;
3298 * ibnex_create_port_compatible_prop()
3299 * Creates 'Compatibility' property for port / HCA_SVC device nodes
3300 * Returns IBNEX_SUCCESS/IBNEX_FAILURE
3303 ibnex_create_port_compatible_prop(dev_info_t
*child_dip
,
3304 char *comm_svcp
, ibdm_port_attr_t
*port_attr
)
3308 char *compatible
[IBNEX_MAX_IBPORT_COMPAT_NAMES
];
3310 IBTF_DPRINTF_L4("ibnex", "\tcreate_port_compatible_prop: Begin");
3312 * Initialize the "compatible" property string as below:
3313 * Compatible Strings :
3314 * 1. ib.V<vid>P<pid>v<revision>.<service name>.
3315 * 2. ib.V<vid>P<pid>.<service name>.
3316 * 3. ib.<service name>
3317 * Leading zeros must be present
3319 temp
= kmem_alloc(IBNEX_MAX_IBPORT_COMPAT_PROP_SZ
, KM_SLEEP
);
3320 for (i
= 0; i
< IBNEX_MAX_IBPORT_COMPAT_NAMES
; i
++) {
3321 compatible
[i
] = temp
+ (i
* IBNEX_MAX_COMPAT_LEN
);
3324 (void) snprintf(compatible
[0], IBNEX_MAX_COMPAT_LEN
,
3325 "ib.V%06xP%08xv%04x.%s",
3326 port_attr
->pa_vendorid
, port_attr
->pa_productid
,
3327 port_attr
->pa_dev_version
, comm_svcp
);
3328 (void) snprintf(compatible
[1], IBNEX_MAX_COMPAT_LEN
,
3330 port_attr
->pa_vendorid
, port_attr
->pa_productid
,
3332 (void) snprintf(compatible
[2], IBNEX_MAX_COMPAT_LEN
,
3333 "ib.%s", comm_svcp
);
3335 for (i
= 0; i
< IBNEX_MAX_IBPORT_COMPAT_NAMES
; i
++)
3336 IBTF_DPRINTF_L4("ibnex", "\tcompatible: %s", compatible
[i
]);
3338 rval
= ndi_prop_update_string_array(DDI_DEV_T_NONE
, child_dip
,
3339 "compatible", (char **)compatible
, IBNEX_MAX_IBPORT_COMPAT_NAMES
);
3341 if (rval
!= DDI_PROP_SUCCESS
) {
3342 kmem_free(temp
, IBNEX_MAX_IBPORT_COMPAT_PROP_SZ
);
3343 return (IBNEX_FAILURE
);
3345 kmem_free(temp
, IBNEX_MAX_IBPORT_COMPAT_PROP_SZ
);
3346 return (IBNEX_SUCCESS
);
3351 * ibnex_delete_port_node_data()
3352 * Delete the parent private node data from the linked list
3353 * Deallocate the memory of the port/ioc attributes
3354 * Deallocate the memory of the node data
3357 ibnex_delete_port_node_data(ibnex_node_data_t
*node
)
3359 if ((node
->node_next
== NULL
) && (node
->node_prev
== NULL
))
3360 ibnex
.ibnex_port_node_head
= NULL
;
3361 else if (node
->node_next
== NULL
)
3362 node
->node_prev
->node_next
= NULL
;
3363 else if (node
->node_prev
== NULL
) {
3364 node
->node_next
->node_prev
= NULL
;
3365 ibnex
.ibnex_port_node_head
= node
->node_next
;
3367 node
->node_prev
->node_next
= node
->node_next
;
3368 node
->node_next
->node_prev
= node
->node_prev
;
3370 kmem_free(node
, sizeof (ibnex_node_data_t
));
3375 * ibnex_is_node_data_present()
3376 * Checks whether ibnex_node_t is created already
3377 * Returns ibnex_node_data_t if found, otherwise NULL
3379 static ibnex_node_data_t
*
3380 ibnex_is_node_data_present(ibnex_node_type_t node_type
, void *attr
,
3381 int index
, ib_pkey_t pkey
)
3383 ibnex_node_data_t
*nodep
;
3384 ASSERT(MUTEX_HELD(&ibnex
.ibnex_mutex
));
3385 if (node_type
== IBNEX_IOC_NODE
) {
3386 ibdm_ioc_info_t
*ioc_infop
= (ibdm_ioc_info_t
*)attr
;
3388 for (nodep
= ibnex
.ibnex_ioc_node_head
; nodep
!= NULL
;
3389 nodep
= nodep
->node_next
) {
3390 if (nodep
->node_data
.ioc_node
.ioc_guid
==
3391 ioc_infop
->ioc_profile
.ioc_guid
) {
3396 } else if (node_type
== IBNEX_PSEUDO_NODE
) {
3397 for (nodep
= ibnex
.ibnex_pseudo_node_head
; nodep
;
3398 nodep
= nodep
->node_next
)
3399 if (strcmp(nodep
->node_data
.pseudo_node
.
3400 pseudo_node_addr
, (char *)attr
) == 0)
3404 ibdm_port_attr_t
*pattrp
= (ibdm_port_attr_t
*)attr
;
3406 for (nodep
= ibnex
.ibnex_port_node_head
; nodep
!= NULL
;
3407 nodep
= nodep
->node_next
) {
3408 if ((nodep
->node_data
.port_node
.port_guid
==
3409 pattrp
->pa_port_guid
) &&
3410 (nodep
->node_data
.port_node
.port_commsvc_idx
==
3412 (nodep
->node_data
.port_node
.port_pkey
== pkey
)) {
3421 * ibnex_lookup_unit_address_prop:
3423 * If property with name is found, return its value
3424 * otherwise return NULL.
3427 ibnex_lookup_named_prop(ddi_prop_t
*head
, char *name
)
3431 /* Search the list of properties for name */
3432 for (propp
= head
; propp
!= NULL
; propp
= propp
->prop_next
) {
3433 if (strcmp(propp
->prop_name
, name
) != 0)
3435 /* named property should be valid and have a value */
3436 if (propp
->prop_len
<= 1)
3438 return ((char *)propp
->prop_val
);
3446 * ibnex_pseudo_initnodes()
3447 * This routine is specific to pseudo node information handling
3448 * Creates a ibnex_node_data_t all pseudo nodes children of ibnex
3451 ibnex_pseudo_initnodes()
3454 ibnex_node_data_t
*nodep
;
3455 struct hwc_spec
*list
, *spec
;
3456 char *node_addr
, *temp
, *unit_addr
;
3459 IBTF_DPRINTF_L4("ibnex", "\tpseudo_initnodes");
3461 mutex_enter(&ibnex
.ibnex_mutex
);
3463 * get a list of all "pseudo" children of "ib".
3464 * for these children initialize/allocate an internal
3465 * ibnex_node_data_t.
3467 list
= hwc_get_child_spec(ibnex
.ibnex_dip
, (major_t
)-1);
3468 for (spec
= list
; spec
!= NULL
; spec
= spec
->hwc_next
) {
3469 if (spec
->hwc_devi_sys_prop_ptr
== NULL
)
3472 /* Check "ib-node-type" property for IOC .conf */
3473 node_type
= ibnex_lookup_named_prop(
3474 spec
->hwc_devi_sys_prop_ptr
, "ib-node-type");
3476 /* "unit-address" property should be present */
3477 temp
= ibnex_lookup_named_prop(
3478 spec
->hwc_devi_sys_prop_ptr
, "unit-address");
3482 pnam_len
= strlen(spec
->hwc_devi_name
) + strlen(temp
) + 2;
3484 node_addr
= kmem_zalloc(pnam_len
, KM_SLEEP
);
3486 (void) snprintf(node_addr
,
3487 pnam_len
, "%s,%s", spec
->hwc_devi_name
, temp
);
3489 nodep
= ibnex_is_node_data_present(
3490 IBNEX_PSEUDO_NODE
, (void *)node_addr
, 0, 0);
3493 kmem_free(node_addr
, pnam_len
);
3497 nodep
= ibnex_init_child_nodedata(IBNEX_PSEUDO_NODE
,
3498 (void *)spec
->hwc_devi_name
, 0, 0);
3500 nodep
->node_data
.pseudo_node
.pseudo_node_addr
= node_addr
;
3501 (void) snprintf(nodep
->node_data
.
3502 pseudo_node
.pseudo_node_addr
, pnam_len
, "%s", node_addr
);
3504 len
= strlen(temp
) + 1;
3505 unit_addr
= kmem_alloc(len
, KM_SLEEP
);
3506 nodep
->node_data
.pseudo_node
.pseudo_unit_addr
= unit_addr
;
3507 (void) snprintf(unit_addr
, len
, "%s", temp
);
3508 nodep
->node_data
.pseudo_node
.pseudo_unit_addr_len
= len
;
3510 if (node_type
&& strcmp(node_type
, "merge") == 0)
3511 nodep
->node_data
.pseudo_node
.pseudo_merge_node
= 1;
3513 IBTF_DPRINTF_L3("ibnex", "\tpseudo_initnodes: unit addr = %s"
3514 " : drv name = %s", unit_addr
, spec
->hwc_devi_name
);
3516 hwc_free_spec_list(list
);
3517 mutex_exit(&ibnex
.ibnex_mutex
);
3522 * ibnex_init_child_nodedata()
3524 * Allocate memory for the parent private data for device node
3525 * Initializes the parent private child device node data.
3526 * Returns pointer to the parent private data
3528 static ibnex_node_data_t
*
3529 ibnex_init_child_nodedata(ibnex_node_type_t node_type
, void *attr
, int index
,
3533 ibdm_ioc_info_t
*ioc_info
;
3534 ibnex_ioc_node_t
*ioc_node
;
3535 ibnex_node_data_t
*node_data
;
3536 ib_dm_ioc_ctrl_profile_t
*ioc_profile
;
3538 ASSERT(MUTEX_HELD(&ibnex
.ibnex_mutex
));
3540 node_data
= kmem_zalloc(sizeof (ibnex_node_data_t
), KM_SLEEP
);
3541 node_data
->node_ap_state
= IBNEX_NODE_AP_CONFIGURED
;
3542 node_data
->node_state
= IBNEX_CFGADM_CONFIGURING
;
3543 node_data
->node_type
= node_type
;
3545 if (node_type
== IBNEX_IOC_NODE
) {
3546 ioc_info
= (ibdm_ioc_info_t
*)attr
;
3547 ioc_profile
= &ioc_info
->ioc_profile
;
3548 ioc_node
= &node_data
->node_data
.ioc_node
;
3550 ioc_node
->iou_guid
= ioc_info
->ioc_iou_guid
;
3551 ioc_node
->ioc_guid
= ioc_profile
->ioc_guid
;
3552 (void) strncpy(ioc_node
->ioc_id_string
,
3553 (char *)ioc_profile
->ioc_id_string
,
3554 IB_DM_IOC_ID_STRING_LEN
);
3555 ioc_node
->ioc_ngids
= ioc_info
->ioc_nportgids
;
3557 node_data
->node_next
= ibnex
.ibnex_ioc_node_head
;
3558 node_data
->node_prev
= NULL
;
3559 if (ibnex
.ibnex_ioc_node_head
)
3560 ibnex
.ibnex_ioc_node_head
->node_prev
= node_data
;
3561 ibnex
.ibnex_ioc_node_head
= node_data
;
3562 } else if (node_type
== IBNEX_PSEUDO_NODE
) {
3563 devi_name
= (char *)attr
;
3564 node_data
->node_data
.pseudo_node
.pseudo_devi_name
=
3565 kmem_zalloc(strlen(devi_name
) + 1, KM_SLEEP
);
3566 (void) strncpy(node_data
->node_data
.pseudo_node
.
3567 pseudo_devi_name
, devi_name
, strlen(devi_name
));
3568 node_data
->node_next
= ibnex
.ibnex_pseudo_node_head
;
3569 node_data
->node_prev
= NULL
;
3570 if (ibnex
.ibnex_pseudo_node_head
)
3571 ibnex
.ibnex_pseudo_node_head
->node_prev
= node_data
;
3572 ibnex
.ibnex_pseudo_node_head
= node_data
;
3574 node_data
->node_data
.port_node
.port_hcaguid
=
3575 ((ibdm_port_attr_t
*)attr
)->pa_hca_guid
;
3576 node_data
->node_data
.port_node
.port_guid
=
3577 ((ibdm_port_attr_t
*)attr
)->pa_port_guid
;
3578 node_data
->node_data
.port_node
.port_num
=
3579 ((ibdm_port_attr_t
*)attr
)->pa_port_num
;
3580 node_data
->node_data
.port_node
.port_commsvc_idx
= index
;
3581 node_data
->node_data
.port_node
.port_pkey
= pkey
;
3583 node_data
->node_next
= ibnex
.ibnex_port_node_head
;
3584 node_data
->node_prev
= NULL
;
3585 if (ibnex
.ibnex_port_node_head
)
3586 ibnex
.ibnex_port_node_head
->node_prev
= node_data
;
3587 ibnex
.ibnex_port_node_head
= node_data
;
3593 ibnex_get_eventcookie(dev_info_t
*dip
, dev_info_t
*rdip
,
3594 char *eventname
, ddi_eventcookie_t
*cookie
)
3599 IBTF_DPRINTF_L4("ibnex", "ibnex_get_eventcookie(%p, %p, %s, 0x%X)",
3600 dip
, rdip
, eventname
, cookie
);
3602 rc
= ndi_event_retrieve_cookie(ibnex
.ibnex_ndi_event_hdl
,
3603 rdip
, eventname
, cookie
, NDI_EVENT_NOPASS
);
3604 if (rc
== NDI_SUCCESS
) {
3605 mutex_enter(&ibnex
.ibnex_mutex
);
3606 ibnex
.ibnex_prop_update_evt_cookie
= *cookie
;
3607 mutex_exit(&ibnex
.ibnex_mutex
);
3614 ibnex_add_eventcall(dev_info_t
*dip
, dev_info_t
*rdip
,
3615 ddi_eventcookie_t cookie
, void (*callback
)(dev_info_t
*dip
,
3616 ddi_eventcookie_t cookie
, void *arg
, void *bus_impldata
),
3617 void *arg
, ddi_callback_id_t
*cb_id
)
3619 IBTF_DPRINTF_L4("ibnex",
3620 "ibnex_add_eventcall(%p, %p, 0x%X, %p, %p, %p)",
3621 dip
, rdip
, cookie
, callback
, arg
, cb_id
);
3623 return (ndi_event_add_callback(ibnex
.ibnex_ndi_event_hdl
,
3624 rdip
, cookie
, callback
, arg
, NDI_SLEEP
, cb_id
));
3628 ibnex_remove_eventcall(dev_info_t
*dip
, ddi_callback_id_t cb_id
)
3630 IBTF_DPRINTF_L4("ibnex", "ibnex_remove_eventcall(%p, 0x%X)",
3633 return (ndi_event_remove_callback(ibnex
.ibnex_ndi_event_hdl
,
3638 ibnex_post_event(dev_info_t
*dip
, dev_info_t
*rdip
,
3639 ddi_eventcookie_t cookie
, void *bus_impldata
)
3641 IBTF_DPRINTF_L4("ibnex", "ibnex_post_event(%p, %p, 0x%X, %p)",
3642 dip
, rdip
, cookie
, bus_impldata
);
3644 return (ndi_event_run_callbacks(ibnex
.ibnex_ndi_event_hdl
, rdip
,
3645 cookie
, bus_impldata
));
3649 * ibnex_reprobe_ioc_dev()
3651 * This could be called as a result of ibt_reprobe_dev request or
3652 * cfgadm command. The function is called from a taskq in case of
3653 * ibt_reprobe_dev and from user context for cfgadm command.
3655 * This function reprobes the properties for one IOC dip.
3657 * node_reprobe_state should be set before calling this function.
3660 ibnex_reprobe_ioc_dev(void *arg
)
3662 dev_info_t
*dip
= (dev_info_t
*)arg
;
3663 ibnex_node_data_t
*node_data
;
3664 ibnex_ioc_node_t
*ioc_data
;
3665 ibdm_ioc_info_t
*ioc_info
;
3667 /* ASSERT(NO_LOCKS_HELD); */
3668 ASSERT(dip
!= NULL
);
3670 node_data
= ddi_get_parent_data(dip
);
3673 if (node_data
->node_dip
== NULL
) {
3674 IBTF_DPRINTF_L4("ibnex", "reprobe for unconfigured dip");
3675 mutex_enter(&ibnex
.ibnex_mutex
);
3676 ibnex_wakeup_reprobe_ioc(node_data
, 0);
3677 mutex_exit(&ibnex
.ibnex_mutex
);
3680 ioc_data
= &(node_data
->node_data
.ioc_node
);
3682 /* Reprobe the IOC */
3683 ioc_info
= ibdm_ibnex_probe_ioc(ioc_data
->iou_guid
, ioc_data
->ioc_guid
,
3685 if (ioc_info
== NULL
) {
3686 IBTF_DPRINTF_L2("ibnex", "Null ioc_info from reprobe");
3687 mutex_enter(&ibnex
.ibnex_mutex
);
3688 ibnex_wakeup_reprobe_ioc(node_data
, 1);
3689 mutex_exit(&ibnex
.ibnex_mutex
);
3693 mutex_enter(&ibnex
.ibnex_mutex
);
3694 if (node_data
->node_dip
)
3695 ibnex_update_prop(node_data
, ioc_info
);
3696 ibnex_wakeup_reprobe_ioc(node_data
, 0);
3697 mutex_exit(&ibnex
.ibnex_mutex
);
3699 ibdm_ibnex_free_ioc_list(ioc_info
);
3703 * ibnex_reprobe_all()
3705 * This could be called as a result of cfgadm command. The function
3706 * is called from user context.
3708 * This function reprobes the properties for all IOC dips.
3710 * ibnex_reprobe_state should be set before calling this function.
3713 ibnex_reprobe_ioc_all()
3715 ibnex_node_data_t
*node_data
;
3716 ibdm_ioc_info_t
*ioc_info_list
, *ioc
;
3718 /* ASSERT(NO_LOCKS_HELD); */
3720 /* Sweep the fabric */
3721 ioc
= ioc_info_list
= ibdm_ibnex_get_ioc_list(
3722 IBDM_IBNEX_REPROBE_ALL
);
3723 if (ioc_info_list
== NULL
) {
3724 mutex_enter(&ibnex
.ibnex_mutex
);
3725 ibnex_wakeup_reprobe_all();
3726 mutex_exit(&ibnex
.ibnex_mutex
);
3730 mutex_enter(&ibnex
.ibnex_mutex
);
3731 while (ioc_info_list
) {
3732 if ((node_data
= ibnex_is_node_data_present(IBNEX_IOC_NODE
,
3733 ioc_info_list
, 0, 0)) != NULL
&&
3734 node_data
->node_dip
!= NULL
) {
3735 ibnex_update_prop(node_data
, ioc_info_list
);
3737 ioc_info_list
= ioc_info_list
->ioc_next
;
3739 ibnex_wakeup_reprobe_all();
3740 mutex_exit(&ibnex
.ibnex_mutex
);
3742 ibdm_ibnex_free_ioc_list(ioc
);
3746 * Update the properties, if it has modified and notify IBTF client.
3749 ibnex_update_prop(ibnex_node_data_t
*node_data
, ibdm_ioc_info_t
*ioc_info
)
3751 ibt_prop_update_payload_t evt_data
;
3752 dev_info_t
*dip
= node_data
->node_dip
;
3753 ddi_eventcookie_t evt_cookie
;
3754 ibnex_ioc_node_t
*ioc
;
3756 ASSERT(MUTEX_HELD(&ibnex
.ibnex_mutex
));
3758 ASSERT(dip
!= NULL
);
3760 ioc
= &node_data
->node_data
.ioc_node
;
3762 evt_data
= ioc_info
->ioc_info_updated
;
3763 evt_cookie
= ibnex
.ibnex_prop_update_evt_cookie
;
3766 * For a disconnected IOC :
3767 * Store the ioc_profile for supplying cfgadm info
3768 * ibdm maintains no info of disconnected IOC
3770 * For reconnected IOC :
3771 * ibdm has info of previous service entries
3772 * ioc_profile maintained by ibnexus is used to
3773 * update ib_srv_prop_updated.
3774 * Free the ibnex maintained ioc_profile
3776 if (ioc_info
->ioc_nportgids
== 0) {
3777 IBTF_DPRINTF_L4("ibnex",
3778 "\tupdate_prop: IOC disconnected");
3779 ioc
->ioc_profile
= (ib_dm_ioc_ctrl_profile_t
*)kmem_zalloc(
3780 sizeof (ib_dm_ioc_ctrl_profile_t
), KM_SLEEP
);
3781 bcopy(&ioc_info
->ioc_profile
, ioc
->ioc_profile
,
3782 sizeof (ib_dm_ioc_ctrl_profile_t
));
3784 ibnex
.ibnex_num_disconnect_iocs
++;
3785 } else if (ioc_info
->ioc_nportgids
!= 0 && ioc
->ioc_ngids
== 0 &&
3786 ioc
->ioc_profile
!= NULL
) {
3787 IBTF_DPRINTF_L4("ibnex",
3788 "\tupdate_prop: IOC reconnected");
3789 if (ioc
->ioc_profile
->ioc_service_entries
!=
3790 ioc_info
->ioc_profile
.ioc_service_entries
)
3791 evt_data
.ib_srv_prop_updated
= 1;
3793 ibnex
.ibnex_num_disconnect_iocs
--;
3794 kmem_free(ioc
->ioc_profile
, sizeof (ib_dm_ioc_ctrl_profile_t
));
3795 ioc
->ioc_profile
= NULL
;
3798 /* Update the properties that have changed */
3799 mutex_exit(&ibnex
.ibnex_mutex
);
3800 if (evt_data
.ib_gid_prop_updated
) {
3801 if (ibnex_create_ioc_portgid_prop(dip
, ioc_info
) !=
3803 mutex_enter(&ibnex
.ibnex_mutex
);
3807 if (evt_data
.ib_srv_prop_updated
) {
3808 if (ioc_info
->ioc_profile
.ioc_service_entries
!= 0 &&
3809 (ibnex_create_ioc_srv_props(dip
, ioc_info
) !=
3811 mutex_enter(&ibnex
.ibnex_mutex
);
3813 } else if (ioc_info
->ioc_profile
.ioc_service_entries
== 0) {
3814 (void) ndi_prop_remove(DDI_DEV_T_NONE
, dip
,
3816 (void) ndi_prop_remove(DDI_DEV_T_NONE
, dip
,
3820 mutex_enter(&ibnex
.ibnex_mutex
);
3821 ioc
->ioc_ngids
= ioc_info
->ioc_nportgids
;
3824 * Post an event if :
3825 * 1. Properites have changed or NOTIFY_ALWAYS is set.
3826 * 2. child dip is configured and a valid cookie for
3827 * IB_PROP_UPDATE_EVENT.
3829 if ((evt_data
.ib_prop_updated
!= 0 ||
3830 (node_data
->node_reprobe_state
&
3831 IBNEX_NODE_REPROBE_NOTIFY_ALWAYS
)) &&
3832 ((node_data
->node_state
== IBNEX_CFGADM_CONFIGURED
) &&
3833 (evt_cookie
!= NULL
))) {
3834 mutex_exit(&ibnex
.ibnex_mutex
);
3836 if (ndi_post_event(ibnex
.ibnex_dip
, dip
,
3837 evt_cookie
, &evt_data
) != NDI_SUCCESS
)
3838 IBTF_DPRINTF_L2("ibnex",
3839 "\tndi_post_event failed\n");
3841 mutex_enter(&ibnex
.ibnex_mutex
);
3845 * Cleanup node_reprobe_state, for ibt_reprobe_dev
3846 * requests, when reprobe all / node reprobe is in
3847 * progress. ibnex_reprobe_ioc_dev is not called
3850 if (node_data
->node_reprobe_state
==
3851 IBNEX_NODE_REPROBE_NOTIFY_ALWAYS
)
3852 ibnex_wakeup_reprobe_ioc(node_data
, 0);
3856 ibnex_unique_svcname(char *svcname
)
3860 /* Check Port Services */
3861 for (i
= 0; i
< ibnex
.ibnex_num_comm_svcs
; i
++)
3862 if (ibnex
.ibnex_comm_svc_names
[i
] && strncmp(svcname
,
3863 ibnex
.ibnex_comm_svc_names
[i
], 4) == 0)
3864 return (IBNEX_FAILURE
);
3866 /* Check VPPA Services */
3867 for (i
= 0; i
< ibnex
.ibnex_nvppa_comm_svcs
; i
++)
3868 if (ibnex
.ibnex_vppa_comm_svc_names
[i
] && strncmp(svcname
,
3869 ibnex
.ibnex_vppa_comm_svc_names
[i
], 4) == 0)
3870 return (IBNEX_FAILURE
);
3872 /* Check HCA_SVC Services */
3873 for (i
= 0; i
< ibnex
.ibnex_nhcasvc_comm_svcs
; i
++)
3874 if (ibnex
.ibnex_hcasvc_comm_svc_names
[i
] && strncmp(svcname
,
3875 ibnex
.ibnex_hcasvc_comm_svc_names
[i
], 4) == 0)
3876 return (IBNEX_FAILURE
);
3878 return (IBNEX_SUCCESS
);
3882 ibnex_handle_reprobe_dev(void *arg
)
3884 dev_info_t
*dip
= (dev_info_t
*)arg
;
3885 ibnex_node_data_t
*node_data
;
3887 ASSERT(dip
!= NULL
);
3888 node_data
= ddi_get_parent_data(dip
);
3892 * Return success if:
3893 * 1. Reprobe for all nodes are in progress
3894 * 2. Reprobe for this node is in progress.
3895 * The reprobe in progress will complete eventually and
3896 * update the properties, if required.
3898 mutex_enter(&ibnex
.ibnex_mutex
);
3899 if (ibnex
.ibnex_reprobe_state
!= 0 ||
3900 node_data
->node_reprobe_state
!= 0) {
3902 * Setting NOTIFY_ALWAYS to ensure that
3903 * DDI event is delivered always for
3906 node_data
->node_reprobe_state
|=
3907 IBNEX_NODE_REPROBE_NOTIFY_ALWAYS
;
3908 mutex_exit(&ibnex
.ibnex_mutex
);
3911 node_data
->node_reprobe_state
=
3912 IBNEX_NODE_REPROBE_NOTIFY_ALWAYS
;
3913 mutex_exit(&ibnex
.ibnex_mutex
);
3914 ibnex_reprobe_ioc_dev(arg
);
3919 * MPxIO pathmangement routines. Currently IB nexus does not support
3920 * any kind of pathmangement. So, just return success to make MPxIO
3925 ib_vhci_pi_init(dev_info_t
*vdip
, mdi_pathinfo_t
*pip
, int flag
)
3927 IBTF_DPRINTF_L4("ibnex", "\tpi_init: dip %p pip %p", vdip
, pip
);
3928 return (MDI_SUCCESS
);
3934 ib_vhci_pi_uninit(dev_info_t
*vdip
, mdi_pathinfo_t
*pip
, int flag
)
3937 ibnex_node_data_t
*node_data
;
3939 IBTF_DPRINTF_L4("ibnex", "\tpi_uninit: dip %p pip %p", vdip
, pip
);
3942 return (MDI_FAILURE
);
3944 * Get the Client dev_info from the pathinfo.
3946 cdip
= mdi_pi_get_client(pip
);
3948 return (MDI_FAILURE
);
3951 * How many PIs do we have from this cdip ?
3953 clnt_num_pi
= mdi_client_get_path_count(cdip
);
3956 * If this is the last PI that is being free'd ( called from
3957 * mdi_pi_free) we have to clean up the node data for the cdip since
3958 * the client would have been detached by mdi_devi_offline.
3960 if (clnt_num_pi
== 1) {
3961 node_data
= ddi_get_parent_data(cdip
);
3962 if (node_data
== NULL
)
3963 return (MDI_SUCCESS
);
3964 if (node_data
->node_dip
== cdip
) {
3965 node_data
->node_dip
= NULL
;
3966 node_data
->node_state
= IBNEX_CFGADM_UNCONFIGURED
;
3967 return (MDI_SUCCESS
);
3970 return (MDI_SUCCESS
);
3976 ib_vhci_pi_state_change(dev_info_t
*vdip
, mdi_pathinfo_t
*pip
,
3977 mdi_pathinfo_state_t state
, uint32_t arg1
, int arg2
)
3979 IBTF_DPRINTF_L4("ibnex",
3980 "\tpi_state_change: dip %p pip %p state %x", vdip
, pip
, state
);
3981 return (MDI_SUCCESS
);
3987 ib_vhci_failover(dev_info_t
*dip1
, dev_info_t
*dip2
, int arg
)
3989 return (MDI_SUCCESS
);
3994 ibnex_bus_power(dev_info_t
*parent
, void *impl_arg
,
3995 pm_bus_power_op_t op
, void *arg
, void *result
)
3998 int ret
= DDI_SUCCESS
;
4000 IBTF_DPRINTF_L4("ibnex", "\tbus_power: begin: op = %d", op
);
4003 * Generic processing in MPxIO framework
4005 ret
= mdi_bus_power(parent
, impl_arg
, op
, arg
, result
);
4023 * If enumerated as a child of IB Nexus / VHCI, call mdi_vhci_bus_config.
4024 * ndi_devi_enter is not held during this call. mdi_vhci_bus_config()
4025 * will have called ndi_busop_bus_config(), no need for the caller to call
4026 * ndi_busop_bus_config() again.
4028 * If enumerated as a child of HCA device, this could be a case for
4029 * Sparc boot or device enumeration from PHCI, driven by MDI.
4030 * Hold parent lock (ndi_devi_enter). The caller will have to call
4031 * ndi_busop_bus_config() if this function returns SUCCESS.
4033 * if the device name contains ":port", then it is the Sparc boot case.
4034 * Handle this as before.
4036 * If the device name does *not* contain the ":port", then :
4037 * 1. ibdm to probe IOC
4038 * 2. Create a pathinfo only if the IOC is reachable from the parent dip.
4041 ibnex_ioc_bus_config_one(dev_info_t
**pdipp
, uint_t flag
,
4042 ddi_bus_config_op_t op
, void *devname
, dev_info_t
**child
,
4043 int *need_bus_config
)
4045 int ret
= DDI_FAILURE
, circ
;
4046 dev_info_t
*pdip
= *pdipp
;
4047 ib_guid_t iou_guid
, ioc_guid
;
4051 *need_bus_config
= 1;
4053 if (pdip
== ibnex
.ibnex_dip
) {
4054 if (ibnex_devname_to_node_n_ioc_guids(
4055 (char *)devname
, &iou_guid
, &ioc_guid
,
4056 &ioc_guid_str
) != IBNEX_SUCCESS
) {
4059 ret
= mdi_vhci_bus_config(pdip
, flag
, op
, devname
, child
,
4061 kmem_free(ioc_guid_str
, strlen(ioc_guid_str
) + 1);
4062 if (ret
== MDI_SUCCESS
)
4063 *need_bus_config
= 0;
4065 mdi_devi_enter(pdip
, &circ
);
4066 if (strstr((char *)devname
, ":port=") != NULL
) {
4067 ret
= ibnex_config_root_iocnode(pdip
, devname
);
4068 ASSERT(ibnex
.ibnex_dip
== NULL
);
4069 *pdipp
= ibnex
.ibnex_dip
;
4071 ret
= ibnex_config_ioc_node(devname
, pdip
);
4073 mdi_devi_exit(pdip
, circ
);
4079 ibnex_is_merge_node(dev_info_t
*child
)
4082 int ret
= IBNEX_INVALID_NODE
;
4084 if (ddi_prop_lookup_string(DDI_DEV_T_ANY
, child
,
4085 DDI_PROP_DONTPASS
, "ib-node-type", &node
) !=
4087 return (IBNEX_FAILURE
);
4090 if (node
!= NULL
&& *node
!= 0) {
4091 if (strcmp(node
, "merge") == 0)
4092 ret
= IBNEX_SUCCESS
;
4094 IBTF_DPRINTF_L4("ibnex",
4095 "\tis_merge_node: ib-node-type = %s", node
);
4099 ddi_prop_free(node
);
4104 * Checks if the dn_head for the driver has already
4105 * initialized by the prom tree.
4108 ibnex_hw_in_dev_tree(char *driver_name
)
4112 IBTF_DPRINTF_L4("ibnex", "\thw_in_dev_tree(%s)", driver_name
);
4114 if (devnamesp
== NULL
)
4117 major
= ddi_name_to_major(driver_name
);
4121 if (devnamesp
[major
].dn_head
!= (dev_info_t
*)NULL
)
4122 ibnex_hw_status
= IBNEX_HW_IN_DEVTREE
;
4126 ibnex_ioc_initnode_all_pi(ibdm_ioc_info_t
*ioc_info
)
4128 ibdm_hca_list_t
*hca_list
;
4129 dev_info_t
*hca_dip
;
4130 int rc
= IBNEX_FAILURE
;
4132 ASSERT(MUTEX_HELD(&ibnex
.ibnex_mutex
));
4134 * We return failure even if we fail for all HCAs
4136 for (hca_list
= ioc_info
->ioc_hca_list
; hca_list
;
4137 hca_list
= hca_list
->hl_next
) {
4138 hca_dip
= ibtl_ibnex_hcaguid2dip(hca_list
->hl_hca_guid
);
4139 if (ibnex_ioc_config_from_pdip(ioc_info
, hca_dip
, 1) ==
4147 ibnex_ioc_config_from_pdip(ibdm_ioc_info_t
*ioc_info
, dev_info_t
*pdip
,
4148 int pdip_reachable_checked
)
4150 ibnex_node_data_t
*node_data
;
4151 int create_pdip
= 0;
4152 int rc
= IBNEX_SUCCESS
;
4155 ASSERT(MUTEX_HELD(&ibnex
.ibnex_mutex
));
4156 IBTF_DPRINTF_L4("ibnex",
4157 "/tioc_config_from_pdip(%p, %p, %d)", ioc_info
, pdip
,
4158 pdip_reachable_checked
);
4160 if (pdip_reachable_checked
== 0) {
4161 if (ibnex_ioc_pi_reachable(ioc_info
, pdip
) == IBNEX_FAILURE
) {
4162 IBTF_DPRINTF_L4("ibnex",
4163 "/tioc_config_from_pdip: ioc %p not reachable"
4164 "from %p", ioc_info
, pdip
);
4165 return (IBNEX_FAILURE
);
4169 node_data
= ibnex_is_node_data_present(IBNEX_IOC_NODE
,
4170 (void *)ioc_info
, 0, 0);
4172 if (node_data
&& node_data
->node_ap_state
==
4173 IBNEX_NODE_AP_UNCONFIGURED
) {
4174 IBTF_DPRINTF_L4("ibnex",
4175 "\tioc_config_from_pdip: Unconfigured node");
4176 return (IBNEX_FAILURE
);
4180 if (node_data
== NULL
) {
4181 ibnex_ioc_node_t
*ioc
;
4185 node_data
= ibnex_init_child_nodedata(IBNEX_IOC_NODE
,
4188 ioc
= &node_data
->node_data
.ioc_node
;
4189 (void) snprintf(ioc
->ioc_guid_str
, IBNEX_IOC_GUID_LEN
,
4191 (longlong_t
)ioc_info
->ioc_profile
.ioc_guid
);
4192 (void) snprintf(ioc
->ioc_phci_guid
, IBNEX_PHCI_GUID_LEN
,
4194 (longlong_t
)ioc_info
->ioc_profile
.ioc_guid
,
4195 (longlong_t
)ioc_info
->ioc_iou_guid
);
4196 } else if (ibnex_ioc_pi_exists(node_data
, pdip
) == IBNEX_FAILURE
) {
4201 rc
= ibnex_ioc_initnode_pdip(node_data
, ioc_info
, pdip
);
4204 IBTF_DPRINTF_L4("ibnex", "\tioc_config_from_pdip ret %x",
4210 * This function checks if a pathinfo has already been created
4211 * for the HCA parent. The function returns SUCCESS if a pathinfo
4212 * has already been created, FAILURE if not.
4215 ibnex_ioc_pi_exists(ibnex_node_data_t
*node_data
, dev_info_t
*parent
)
4218 ibnex_ioc_node_t
*ioc
;
4220 ioc
= &node_data
->node_data
.ioc_node
;
4221 if (mdi_pi_find(parent
, (char *)ioc
->ioc_guid_str
,
4222 (char *)ioc
->ioc_phci_guid
) != NULL
)
4227 IBTF_DPRINTF_L4("ibnex", "\tioc_pi_created- client_guid %s, "
4228 "phci_guid %s, parent %p, rc %x",
4229 ioc
->ioc_guid_str
, ioc
->ioc_phci_guid
, parent
, rc
);
4234 ibnex_ioc_pi_reachable(ibdm_ioc_info_t
*ioc_info
, dev_info_t
*pdip
)
4236 ibdm_hca_list_t
*hca_list
;
4237 dev_info_t
*hca_dip
;
4239 IBTF_DPRINTF_L4("ibnex", "\tioc_pi_reachable(%p, %p)",
4241 for (hca_list
= ioc_info
->ioc_hca_list
; hca_list
;
4242 hca_list
= hca_list
->hl_next
) {
4243 hca_dip
= ibtl_ibnex_hcaguid2dip(hca_list
->hl_hca_guid
);
4244 if (hca_dip
== pdip
) {
4245 IBTF_DPRINTF_L4("ibnex",
4246 "\tioc_pi_reachable FAILURE");
4247 return (IBNEX_SUCCESS
);
4251 IBTF_DPRINTF_L4("ibnex", "\tioc_pi_reachable FAILURE");
4252 return (IBNEX_FAILURE
);