1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 #include <sys/systm.h>
27 #include <sys/sunndi.h>
28 #include <sys/sunmdi.h>
29 #include <sys/ib/ibtl/impl/ibtl.h>
30 #include <sys/ib/ibtl/impl/ibtl_ibnex.h>
31
32 /*
33 * ibtl_ibnex.c
34 * These routines tie the Device Manager into IBTL.
35 *
36 * ibt_reprobe_dev which can be called by IBTF clients.
37 * This results in calls to IBnexus callback.
38 */
39
40 /*
41 * Globals.
42 */
43 static char ibtl_ibnex[] = "ibtl_ibnex";
44 ibtl_ibnex_callback_t ibtl_ibnex_callback_routine = NULL;
45
46 /*
47 * Function:
48 * ibtl_ibnex_get_hca_info
49 * Input:
50 * hca_guid - The HCA's node GUID.
51 * flag - Tells what to do
52 * IBTL_IBNEX_LIST_CLNTS_FLAG - Build a NVLIST containing
53 * client's names, their AP_IDs and
54 * alternate_HCA information.
55 * (-x list_clients option)
56 * IBTL_IBNEX_UNCFG_CLNTS_FLAG - Build a NVLIST containing
57 * clients' devpaths and their
58 * AP_IDs. (-x unconfig_clients)
59 * callback - Callback function to get ap_id from ib(7d)
60 * Output:
61 * buffer - The information is returned in this buffer
62 * bufsiz - The size of the information buffer
63 * Returns:
64 * IBT_SUCCESS/IBT_HCA_INVALID/IBT_INVALID_PARAM
65 * Description:
66 * For a given HCA node GUID it figures out the registered clients
67 * (ie. ones who called ibt_open_hca(9f) on this GUID) and creates
68 * a NVL packed buffer (of client names/ap_ids or devpaths) and returns
69 * it. If flag is not specified, then an error is returned.
70 */
71 ibt_status_t
ibtl_ibnex_get_hca_info(ib_guid_t hca_guid,int flag,char ** buffer,size_t * bufsiz,void (* callback)(dev_info_t *,char **))72 ibtl_ibnex_get_hca_info(ib_guid_t hca_guid, int flag, char **buffer,
73 size_t *bufsiz, void (*callback)(dev_info_t *, char **))
74 {
75 char *node_name;
76 char *ret_apid;
77 nvlist_t *nvl;
78 ibtl_hca_t *ibt_hca;
79 ibtl_clnt_t *clntp;
80 dev_info_t *child;
81 dev_info_t *parent;
82 ibtl_hca_devinfo_t *hca_devp;
83
84 IBTF_DPRINTF_L3(ibtl_ibnex, "ibtl_ibnex_get_hca_info: "
85 "GUID 0x%llX, flag = 0x%x", hca_guid, flag);
86
87 *buffer = NULL;
88 *bufsiz = 0;
89
90 /* verify that valid "flag" is passed */
91 if (flag != IBTL_IBNEX_LIST_CLNTS_FLAG &&
92 flag != IBTL_IBNEX_UNCFG_CLNTS_FLAG) {
93 return (IBT_INVALID_PARAM);
94 }
95
96 mutex_enter(&ibtl_clnt_list_mutex);
97
98 if ((hca_devp = ibtl_get_hcadevinfo(hca_guid)) == NULL) {
99 mutex_exit(&ibtl_clnt_list_mutex);
100
101 /*
102 * If we are here, then the requested HCA device is not
103 * present. Return the status as Invalid HCA GUID.
104 */
105 IBTF_DPRINTF_L2(ibtl_ibnex, "ibtl_ibnex_get_hca_info: "
106 "HCA Not Found, Invalid HCA GUID 0x%llX", hca_guid);
107 return (IBT_HCA_INVALID);
108 }
109
110 /* Walk the client list */
111 ibt_hca = hca_devp->hd_clnt_list;
112 (void) nvlist_alloc(&nvl, 0, KM_SLEEP);
113
114 /* Allocate memory for ret_apid, instead of using stack */
115 ret_apid = kmem_alloc(IBTL_IBNEX_APID_LEN, KM_SLEEP);
116
117 while (ibt_hca != NULL) {
118 clntp = ibt_hca->ha_clnt_devp;
119 child = clntp->clnt_dip;
120 IBTF_DPRINTF_L4(ibtl_ibnex, "ibtl_ibnex_get_hca_info: "
121 "Client = %s", clntp->clnt_modinfop->mi_clnt_name);
122
123 if (flag == IBTL_IBNEX_LIST_CLNTS_FLAG) {
124 (void) nvlist_add_string(nvl, "Client",
125 clntp->clnt_modinfop->mi_clnt_name);
126
127 /*
128 * Always check, first, if this client exists
129 * under this HCA anymore? If not, continue.
130 */
131 if (clntp->clnt_hca_list == NULL) {
132 (void) nvlist_add_string(nvl, "Alt_HCA", "no");
133 (void) nvlist_add_string(nvl, "ApID", "-");
134 ibt_hca = ibt_hca->ha_clnt_link;
135 continue;
136 }
137
138 /* Check if this client has more than one HCAs */
139 if (clntp->clnt_hca_list->ha_hca_link == NULL)
140 (void) nvlist_add_string(nvl, "Alt_HCA", "no");
141 else
142 (void) nvlist_add_string(nvl, "Alt_HCA", "yes");
143
144 if (child == NULL) {
145 (void) nvlist_add_string(nvl, "ApID", "-");
146 ibt_hca = ibt_hca->ha_clnt_link;
147 continue;
148 }
149
150 /*
151 * All IB clients (IOC, VPPA, Port, Pseudo etc.)
152 * need to be looked at. The parent of IOC nodes
153 * is "ib" nexus and node-name is "ioc". "VPPA/Port"s
154 * should have HCA as parent and node-name is "ibport".
155 * HCA validity is checked by looking at parent's "dip"
156 * and the dip saved in the ibtl_hca_devinfo_t.
157 * NOTE: We only want to list this HCA's IB clients.
158 * All others clients are ignored.
159 */
160 parent = ddi_get_parent(child);
161 if (parent == NULL || /* No parent? */
162 ddi_get_parent_data(child) == NULL) {
163 (void) nvlist_add_string(nvl, "ApID", "-");
164 ibt_hca = ibt_hca->ha_clnt_link;
165 continue;
166 }
167
168 node_name = ddi_node_name(child);
169 if ((strcmp(ddi_node_name(parent), "ib") == 0) ||
170 ((hca_devp->hd_hca_dip == parent) &&
171 (strncmp(node_name, IBNEX_IBPORT_CNAME, 6) == 0))) {
172 ASSERT(callback != NULL);
173 /*
174 * Callback is invoked to figure out the
175 * ap_id string.
176 */
177 callback(child, &ret_apid);
178 (void) nvlist_add_string(nvl, "ApID", ret_apid);
179 } else {
180 (void) nvlist_add_string(nvl, "ApID", "-");
181 }
182
183 } else if (flag == IBTL_IBNEX_UNCFG_CLNTS_FLAG) {
184 char path[MAXPATHLEN];
185
186 if (child == NULL) {
187 IBTF_DPRINTF_L4(ibtl_ibnex,
188 "ibtl_ibnex_get_hca_info: No dip exists");
189 ibt_hca = ibt_hca->ha_clnt_link;
190 continue;
191 }
192
193 /*
194 * if the child has a alternate HCA then skip it
195 */
196 if (clntp->clnt_hca_list->ha_hca_link) {
197 IBTF_DPRINTF_L4(ibtl_ibnex,
198 "ibtl_ibnex_get_hca_info: Alt HCA exists");
199 ibt_hca = ibt_hca->ha_clnt_link;
200 continue;
201 }
202
203 /*
204 * See earlier comments on how to check if a client
205 * is IOC, VPPA, Port or a Pseudo node.
206 */
207 parent = ddi_get_parent(child);
208 if (parent == NULL || /* No parent? */
209 ddi_get_parent_data(child) == NULL) {
210 IBTF_DPRINTF_L4(ibtl_ibnex,
211 "ibtl_ibnex_get_hca_info: no parent");
212 ibt_hca = ibt_hca->ha_clnt_link;
213 continue;
214 }
215
216 node_name = ddi_node_name(child);
217 if ((strcmp(ddi_node_name(parent), "ib") == 0) ||
218 ((hca_devp->hd_hca_dip == parent) &&
219 (strncmp(node_name, IBNEX_IBPORT_CNAME, 6) == 0))) {
220 ASSERT(callback != NULL);
221 /*
222 * Callback is invoked to figure out the
223 * ap_id string.
224 */
225 callback(child, &ret_apid);
226 (void) nvlist_add_string(nvl, "ApID", ret_apid);
227
228 /*
229 * ddi_pathname() doesn't supply /devices,
230 * so we do
231 */
232 (void) strcpy(path, "/devices");
233 (void) ddi_pathname(child, path + strlen(path));
234 IBTF_DPRINTF_L4(ibtl_ibnex,
235 "ibtl_ibnex_get_hca_info: "
236 "device path = %s", path);
237
238 if (nvlist_add_string(nvl, "devpath", path)) {
239 IBTF_DPRINTF_L2(ibtl_ibnex,
240 "ibtl_ibnex_get_hca_info: "
241 "failed to fill in path %s", path);
242 mutex_exit(&ibtl_clnt_list_mutex);
243 nvlist_free(nvl);
244 kmem_free(ret_apid,
245 IBTL_IBNEX_APID_LEN);
246 return (ibt_get_module_failure(
247 IBT_FAILURE_IBTL, 0));
248 }
249 } /* end of if */
250 } /* end of while */
251
252 ibt_hca = ibt_hca->ha_clnt_link;
253 } /* End of while */
254 mutex_exit(&ibtl_clnt_list_mutex);
255
256 kmem_free(ret_apid, IBTL_IBNEX_APID_LEN);
257
258 /* Pack all data into "buffer" */
259 if (nvlist_pack(nvl, buffer, bufsiz, NV_ENCODE_NATIVE, KM_SLEEP)) {
260 IBTF_DPRINTF_L2(ibtl_ibnex, "ibtl_ibnex_get_hca_info: "
261 "nvlist_pack failed");
262 nvlist_free(nvl);
263 return (ibt_get_module_failure(IBT_FAILURE_IBTL, 0));
264 }
265
266 IBTF_DPRINTF_L4(ibtl_ibnex, "ibtl_ibnex_get_hca_info: size = %x",
267 *bufsiz);
268 nvlist_free(nvl);
269 return (IBT_SUCCESS);
270 }
271
272
273 /*
274 * Function:
275 * ibtl_ibnex_register_callback()
276 * Input:
277 * ibnex_cb - IB nexus driver callback routine
278 * Output:
279 * none
280 * Returns:
281 * none
282 * Description:
283 * Register a callback routine for IB nexus driver
284 */
285 void
ibtl_ibnex_register_callback(ibtl_ibnex_callback_t ibnex_cb)286 ibtl_ibnex_register_callback(ibtl_ibnex_callback_t ibnex_cb)
287 {
288 IBTF_DPRINTF_L5(ibtl_ibnex, "ibtl_ibnex_register_callback:");
289
290 mutex_enter(&ibtl_clnt_list_mutex);
291 ibtl_ibnex_callback_routine = ibnex_cb;
292 mutex_exit(&ibtl_clnt_list_mutex);
293 }
294
295 /*
296 * Function:
297 * ibtl_ibnex_unregister_callback()
298 * Input:
299 * none
300 * Output:
301 * none
302 * Returns:
303 * none
304 * Description:
305 * Un-register a callback routine for IB nexus driver
306 */
307 void
ibtl_ibnex_unregister_callback()308 ibtl_ibnex_unregister_callback()
309 {
310 IBTF_DPRINTF_L5(ibtl_ibnex, "ibtl_ibnex_unregister_callback: ibnex cb");
311
312 mutex_enter(&ibtl_clnt_list_mutex);
313 ibtl_ibnex_callback_routine = NULL;
314 mutex_exit(&ibtl_clnt_list_mutex);
315 }
316
317
318 /*
319 * Function:
320 * ibtl_ibnex_hcadip2guid
321 * Input:
322 * dev_info_t - The "dip" of this HCA
323 * Output:
324 * hca_guid - The HCA's node GUID.
325 * Returns:
326 * "HCA GUID" on SUCCESS, NULL on FAILURE
327 * Description:
328 * For a given HCA node GUID it figures out the HCA GUID
329 * and returns it. If not found, NULL is returned.
330 */
331 ib_guid_t
ibtl_ibnex_hcadip2guid(dev_info_t * hca_dip)332 ibtl_ibnex_hcadip2guid(dev_info_t *hca_dip)
333 {
334 ib_guid_t hca_guid = 0LL;
335 ibtl_hca_devinfo_t *hca_devp;
336
337 mutex_enter(&ibtl_clnt_list_mutex);
338 hca_devp = ibtl_hca_list;
339
340 while (hca_devp) {
341 if (hca_devp->hd_hca_dip == hca_dip) {
342 hca_guid = hca_devp->hd_hca_attr->hca_node_guid;
343 break;
344 }
345 hca_devp = hca_devp->hd_hca_dev_link;
346 }
347 mutex_exit(&ibtl_clnt_list_mutex);
348 IBTF_DPRINTF_L4(ibtl_ibnex, "ibtl_ibnex_hcadip_guid: hca_guid 0x%llX",
349 hca_guid);
350 return (hca_guid);
351 }
352
353
354 /*
355 * Function:
356 * ibtl_ibnex_hcaguid2dip
357 * Input:
358 * hca_guid - The HCA's node GUID.
359 * Output:
360 * dev_info_t - The "dip" of this HCA
361 * Returns:
362 * "dip" on SUCCESS, NULL on FAILURE
363 * Description:
364 * For a given HCA node GUID it figures out the "dip"
365 * and returns it. If not found, NULL is returned.
366 */
367 dev_info_t *
ibtl_ibnex_hcaguid2dip(ib_guid_t hca_guid)368 ibtl_ibnex_hcaguid2dip(ib_guid_t hca_guid)
369 {
370 dev_info_t *dip = NULL;
371 ibtl_hca_devinfo_t *hca_devp;
372
373 IBTF_DPRINTF_L4(ibtl_ibnex, "ibtl_ibnex_hcaguid2dip:");
374
375 mutex_enter(&ibtl_clnt_list_mutex);
376 hca_devp = ibtl_hca_list;
377
378 while (hca_devp) {
379 if (hca_devp->hd_hca_attr->hca_node_guid == hca_guid) {
380 dip = hca_devp->hd_hca_dip;
381 break;
382 }
383 hca_devp = hca_devp->hd_hca_dev_link;
384 }
385 mutex_exit(&ibtl_clnt_list_mutex);
386 return (dip);
387 }
388
389
390 /*
391 * Function:
392 * ibtl_ibnex_get_hca_verbose_data
393 * Input:
394 * hca_guid - The HCA's node GUID.
395 * Output:
396 * buffer - The information is returned in this buffer
397 * bufsiz - The size of the information buffer
398 * Returns:
399 * IBT_SUCCESS/IBT_HCA_INVALID
400 * Description:
401 * For a given HCA node GUID it figures out the verbose listing display.
402 */
403 ibt_status_t
ibtl_ibnex_get_hca_verbose_data(ib_guid_t hca_guid,char ** buffer,size_t * bufsiz)404 ibtl_ibnex_get_hca_verbose_data(ib_guid_t hca_guid, char **buffer,
405 size_t *bufsiz)
406 {
407 char path[IBTL_IBNEX_STR_LEN];
408 char tmp[MAXPATHLEN];
409 uint_t ii;
410 ibt_hca_portinfo_t *pinfop;
411 ibtl_hca_devinfo_t *hca_devp;
412
413 IBTF_DPRINTF_L3(ibtl_ibnex, "ibtl_ibnex_get_hca_verbose_data: "
414 "HCA GUID 0x%llX", hca_guid);
415
416 *buffer = NULL;
417 *bufsiz = 0;
418
419 mutex_enter(&ibtl_clnt_list_mutex);
420 if ((hca_devp = ibtl_get_hcadevinfo(hca_guid)) == NULL) {
421 mutex_exit(&ibtl_clnt_list_mutex);
422
423 /*
424 * If we are here, then the requested HCA device is not
425 * present. Return the status as Invalid HCA GUID.
426 */
427 IBTF_DPRINTF_L2(ibtl_ibnex, "ibtl_ibnex_get_hca_verbose_data: "
428 "HCA Not Found, Invalid HCA GUID");
429 return (IBT_HCA_INVALID);
430 }
431
432 (void) snprintf(tmp, MAXPATHLEN, "VID: 0x%x, PID: 0x%x, #ports: 0x%x",
433 hca_devp->hd_hca_attr->hca_vendor_id,
434 hca_devp->hd_hca_attr->hca_device_id,
435 hca_devp->hd_hca_attr->hca_nports);
436
437 pinfop = hca_devp->hd_portinfop;
438 for (ii = 0; ii < hca_devp->hd_hca_attr->hca_nports; ii++) {
439 (void) snprintf(path, IBTL_IBNEX_STR_LEN,
440 ", port%d GUID: 0x%llX", ii + 1,
441 (longlong_t)pinfop[ii].p_sgid_tbl->gid_guid);
442 (void) strcat(tmp, path);
443 }
444 mutex_exit(&ibtl_clnt_list_mutex);
445
446 *bufsiz = strlen(tmp);
447 *buffer = kmem_alloc(*bufsiz, KM_SLEEP);
448 (void) strncpy(*buffer, tmp, *bufsiz);
449
450 IBTF_DPRINTF_L4(ibtl_ibnex, "ibtl_ibnex_get_hca_verbose_data: "
451 "data = %s, size = 0x%x", *buffer, *bufsiz);
452 return (IBT_SUCCESS);
453 }
454
455 /*
456 * Function:
457 * ibt_reprobe_dev()
458 * Input:
459 * dev_info_t *dip
460 * Output:
461 * none
462 * Returns:
463 * Return value from IBnexus callback handler
464 * IBT_ILLEGAL_OP if IBnexus callback is not installed.
465 * Description:
466 * This function passes the IBTF client's "reprobe device
467 * properties" request to IBnexus. See ibt_reprobe_dev(9f)
468 * for details.
469 */
470 ibt_status_t
ibt_reprobe_dev(dev_info_t * dip)471 ibt_reprobe_dev(dev_info_t *dip)
472 {
473 ibt_status_t rv;
474 ibtl_ibnex_cb_args_t cb_args;
475
476 if (dip == NULL)
477 return (IBT_NOT_SUPPORTED);
478
479 /*
480 * Restricting the reprobe request to the children of
481 * ibnexus. Note the IB_CONF_UPDATE_EVENT DDI event can
482 * be subscribed by any device on the IBnexus device tree.
483 */
484 if (strcmp(ddi_node_name(ddi_get_parent(dip)), "ib") != 0)
485 return (IBT_NOT_SUPPORTED);
486
487 /* Reprobe for IOC nodes only */
488 if (strncmp(ddi_node_name(dip), IBNEX_IBPORT_CNAME, 6) == 0)
489 return (IBT_NOT_SUPPORTED);
490
491 cb_args.cb_flag = IBTL_IBNEX_REPROBE_DEV_REQ;
492 cb_args.cb_dip = dip;
493 mutex_enter(&ibtl_clnt_list_mutex);
494 if (ibtl_ibnex_callback_routine) {
495 rv = (*ibtl_ibnex_callback_routine)(&cb_args);
496 mutex_exit(&ibtl_clnt_list_mutex);
497 return (rv);
498 }
499 mutex_exit(&ibtl_clnt_list_mutex);
500
501 /* Should -not- come here */
502 IBTF_DPRINTF_L2("ibtl", "ibt_reprobe_dev: ibnex not registered!!");
503 return (IBT_ILLEGAL_OP);
504 }
505
506
507 /*
508 * Function:
509 * ibtl_ibnex_valid_hca_parent
510 * Input:
511 * pdip - The parent dip from client's child dev_info_t
512 * Output:
513 * NONE
514 * Returns:
515 * IBT_SUCCESS/IBT_NO_HCAS_AVAILABLE
516 * Description:
517 * For a given pdip, of Port/VPPA devices, match it against all the
518 * registered HCAs's dip. If match found return IBT_SUCCESS,
519 * else IBT_NO_HCAS_AVAILABLE.
520 *
521 * For IOC/Pseudo devices check if the given pdip is that of
522 * the ib(7d) nexus or that of the eoib(7d) nexus. If yes
523 * return IBT_SUCCESS, else IBT_NO_HCAS_AVAILABLE.
524 */
525 ibt_status_t
ibtl_ibnex_valid_hca_parent(dev_info_t * pdip)526 ibtl_ibnex_valid_hca_parent(dev_info_t *pdip)
527 {
528 ibtl_hca_devinfo_t *hca_devp;
529
530 IBTF_DPRINTF_L4(ibtl_ibnex, "ibtl_ibnex_valid_hca_parent: pdip %p",
531 pdip);
532
533 /* For Pseudo devices and IOCs */
534 if (strncmp(ddi_node_name(pdip), "ib", 2) == 0 ||
535 strncmp(ddi_node_name(pdip), "eibnx", 5) == 0) {
536 return (IBT_SUCCESS);
537 } else {
538 /* For Port devices and VPPAs */
539 mutex_enter(&ibtl_clnt_list_mutex);
540 hca_devp = ibtl_hca_list;
541 while (hca_devp) {
542 if (hca_devp->hd_hca_dip == pdip) {
543 mutex_exit(&ibtl_clnt_list_mutex);
544 return (IBT_SUCCESS);
545 }
546 hca_devp = hca_devp->hd_hca_dev_link;
547 }
548 mutex_exit(&ibtl_clnt_list_mutex);
549 return (IBT_NO_HCAS_AVAILABLE);
550 }
551 }
552
553 /*
554 * Function:
555 * ibtl_ibnex_phci_register
556 * Input:
557 * hca_dip - The HCA dip
558 * Output:
559 * NONE
560 * Returns:
561 * IBT_SUCCESS/IBT_FAILURE
562 * Description:
563 * Register the HCA dip as the MPxIO PCHI.
564 */
565 ibt_status_t
ibtl_ibnex_phci_register(dev_info_t * hca_dip)566 ibtl_ibnex_phci_register(dev_info_t *hca_dip)
567 {
568 /* Register the with MPxIO as PHCI */
569 if (mdi_phci_register(MDI_HCI_CLASS_IB, hca_dip, 0) !=
570 MDI_SUCCESS) {
571 return (IBT_FAILURE);
572 }
573 return (IBT_SUCCESS);
574 }
575
576 /*
577 * Function:
578 * ibtl_ibnex_phci_unregister
579 * Input:
580 * hca_dip - The HCA dip
581 * Output:
582 * NONE
583 * Returns:
584 * IBT_SUCCESS/IBT_FAILURE
585 * Description:
586 * Free up any pending MPxIO Pathinfos and unregister the HCA dip as the
587 * MPxIO PCHI.
588 */
589 ibt_status_t
ibtl_ibnex_phci_unregister(dev_info_t * hca_dip)590 ibtl_ibnex_phci_unregister(dev_info_t *hca_dip)
591 {
592 mdi_pathinfo_t *pip = NULL;
593 dev_info_t *vdip = 0;
594 int circ = 0, circ1 = 0;
595
596 /*
597 * Should free all the Pathinfos associated with the HCA pdip before
598 * unregistering the PHCI.
599 *
600 * mdi_pi_free will call ib_vhci_pi_uninit() callbackfor each PI where
601 * the ibnex internal datastructures (ibnex_node_data) will have to be
602 * cleaned up if needed.
603 */
604 vdip = mdi_devi_get_vdip(hca_dip);
605 ndi_devi_enter(vdip, &circ1);
606 ndi_devi_enter(hca_dip, &circ);
607 while (pip = mdi_get_next_client_path(hca_dip, NULL)) {
608 if (mdi_pi_free(pip, 0) == MDI_SUCCESS) {
609 continue;
610 }
611 ndi_devi_exit(hca_dip, circ);
612 ndi_devi_exit(vdip, circ1);
613 IBTF_DPRINTF_L1(ibtl_ibnex, "ibtl_ibnex_phci_unregister: "
614 "mdi_pi_free failed");
615 return (IBT_FAILURE);
616 }
617 ndi_devi_exit(hca_dip, circ);
618 ndi_devi_exit(vdip, circ1);
619
620 if (mdi_phci_unregister(hca_dip, 0) != MDI_SUCCESS) {
621 IBTF_DPRINTF_L1(ibtl_ibnex, "ibtl_ibnex_phci_unregister: PHCI "
622 "unregister failed");
623 return (IBT_FAILURE);
624 }
625 return (IBT_SUCCESS);
626 }
627
628 /*
629 * Function:
630 * ibtl_ibnex_query_hca_byguid
631 * Input:
632 * hca_guid - The HCA's node GUID.
633 * driver_name_size- size of the caller allocated driver_name buffer
634 * Output:
635 * hca_attrs - caller allocated buffer which will contain
636 * HCA attributes upon success
637 * driver_name - caller allocated buffer which will contain
638 * HCA driver name upon success
639 * driver_instance - HCA driver instance
640 * hca_device_path - caller allocated buffer of size MAXPATHLEN which
641 * will contain hca device path upon success.
642 * Returns:
643 * IBT_SUCCESS/IBT_FAILURE
644 * Description:
645 * Get the HCA attributes, driver name and instance number of the
646 * specified HCA.
647 */
648 ibt_status_t
ibtl_ibnex_query_hca_byguid(ib_guid_t hca_guid,ibt_hca_attr_t * hca_attrs,char * driver_name,size_t driver_name_size,int * driver_instance,char * hca_device_path)649 ibtl_ibnex_query_hca_byguid(ib_guid_t hca_guid, ibt_hca_attr_t *hca_attrs,
650 char *driver_name, size_t driver_name_size, int *driver_instance,
651 char *hca_device_path)
652 {
653 ibtl_hca_devinfo_t *hca_devp;
654
655 IBTF_DPRINTF_L4(ibtl_ibnex, "ibtl_ibnex_query_hca_byguid("
656 "hca_guid = 0x%llx, hca_attrs = 0x%p, driver_name = 0x%p, "
657 "driver_name_size = 0x%d, driver_instancep = 0x%p)", hca_guid,
658 hca_attrs, driver_name, (int)driver_name_size, driver_instance);
659
660 mutex_enter(&ibtl_clnt_list_mutex);
661
662 hca_devp = ibtl_get_hcadevinfo(hca_guid);
663 if (hca_devp == NULL) {
664 mutex_exit(&ibtl_clnt_list_mutex);
665 return (IBT_HCA_INVALID);
666 }
667
668 if (strlcpy(driver_name,
669 ddi_driver_name(hca_devp->hd_hca_dip), driver_name_size) >=
670 driver_name_size) {
671 mutex_exit(&ibtl_clnt_list_mutex);
672 return (IBT_INSUFF_KERNEL_RESOURCE);
673 }
674
675 (void) ddi_pathname(hca_devp->hd_hca_dip, hca_device_path);
676 *driver_instance = ddi_get_instance(hca_devp->hd_hca_dip);
677 bcopy(hca_devp->hd_hca_attr, hca_attrs, sizeof (ibt_hca_attr_t));
678
679 mutex_exit(&ibtl_clnt_list_mutex);
680 return (IBT_SUCCESS);
681 }
682