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