4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
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>
34 * These routines tie the Device Manager into IBTL.
36 * ibt_reprobe_dev which can be called by IBTF clients.
37 * This results in calls to IBnexus callback.
43 static char ibtl_ibnex
[] = "ibtl_ibnex";
44 ibtl_ibnex_callback_t ibtl_ibnex_callback_routine
= NULL
;
48 * ibtl_ibnex_get_hca_info
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)
61 * buffer - The information is returned in this buffer
62 * bufsiz - The size of the information buffer
64 * IBT_SUCCESS/IBT_HCA_INVALID/IBT_INVALID_PARAM
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.
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 **))
82 ibtl_hca_devinfo_t
*hca_devp
;
84 IBTF_DPRINTF_L3(ibtl_ibnex
, "ibtl_ibnex_get_hca_info: "
85 "GUID 0x%llX, flag = 0x%x", hca_guid
, flag
);
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
);
96 mutex_enter(&ibtl_clnt_list_mutex
);
98 if ((hca_devp
= ibtl_get_hcadevinfo(hca_guid
)) == NULL
) {
99 mutex_exit(&ibtl_clnt_list_mutex
);
102 * If we are here, then the requested HCA device is not
103 * present. Return the status as Invalid HCA GUID.
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
);
110 /* Walk the client list */
111 ibt_hca
= hca_devp
->hd_clnt_list
;
112 (void) nvlist_alloc(&nvl
, 0, KM_SLEEP
);
114 /* Allocate memory for ret_apid, instead of using stack */
115 ret_apid
= kmem_alloc(IBTL_IBNEX_APID_LEN
, KM_SLEEP
);
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
);
123 if (flag
== IBTL_IBNEX_LIST_CLNTS_FLAG
) {
124 (void) nvlist_add_string(nvl
, "Client",
125 clntp
->clnt_modinfop
->mi_clnt_name
);
128 * Always check, first, if this client exists
129 * under this HCA anymore? If not, continue.
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
;
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");
142 (void) nvlist_add_string(nvl
, "Alt_HCA", "yes");
145 (void) nvlist_add_string(nvl
, "ApID", "-");
146 ibt_hca
= ibt_hca
->ha_clnt_link
;
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.
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
;
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
);
174 * Callback is invoked to figure out the
177 callback(child
, &ret_apid
);
178 (void) nvlist_add_string(nvl
, "ApID", ret_apid
);
180 (void) nvlist_add_string(nvl
, "ApID", "-");
183 } else if (flag
== IBTL_IBNEX_UNCFG_CLNTS_FLAG
) {
184 char path
[MAXPATHLEN
];
187 IBTF_DPRINTF_L4(ibtl_ibnex
,
188 "ibtl_ibnex_get_hca_info: No dip exists");
189 ibt_hca
= ibt_hca
->ha_clnt_link
;
194 * if the child has a alternate HCA then skip it
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
;
204 * See earlier comments on how to check if a client
205 * is IOC, VPPA, Port or a Pseudo node.
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
;
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
);
222 * Callback is invoked to figure out the
225 callback(child
, &ret_apid
);
226 (void) nvlist_add_string(nvl
, "ApID", ret_apid
);
229 * ddi_pathname() doesn't supply /devices,
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
);
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
);
245 IBTL_IBNEX_APID_LEN
);
246 return (ibt_get_module_failure(
247 IBT_FAILURE_IBTL
, 0));
252 ibt_hca
= ibt_hca
->ha_clnt_link
;
254 mutex_exit(&ibtl_clnt_list_mutex
);
256 kmem_free(ret_apid
, IBTL_IBNEX_APID_LEN
);
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");
263 return (ibt_get_module_failure(IBT_FAILURE_IBTL
, 0));
266 IBTF_DPRINTF_L4(ibtl_ibnex
, "ibtl_ibnex_get_hca_info: size = %x",
269 return (IBT_SUCCESS
);
275 * ibtl_ibnex_register_callback()
277 * ibnex_cb - IB nexus driver callback routine
283 * Register a callback routine for IB nexus driver
286 ibtl_ibnex_register_callback(ibtl_ibnex_callback_t ibnex_cb
)
288 IBTF_DPRINTF_L5(ibtl_ibnex
, "ibtl_ibnex_register_callback:");
290 mutex_enter(&ibtl_clnt_list_mutex
);
291 ibtl_ibnex_callback_routine
= ibnex_cb
;
292 mutex_exit(&ibtl_clnt_list_mutex
);
297 * ibtl_ibnex_unregister_callback()
305 * Un-register a callback routine for IB nexus driver
308 ibtl_ibnex_unregister_callback()
310 IBTF_DPRINTF_L5(ibtl_ibnex
, "ibtl_ibnex_unregister_callback: ibnex cb");
312 mutex_enter(&ibtl_clnt_list_mutex
);
313 ibtl_ibnex_callback_routine
= NULL
;
314 mutex_exit(&ibtl_clnt_list_mutex
);
320 * ibtl_ibnex_hcadip2guid
322 * dev_info_t - The "dip" of this HCA
324 * hca_guid - The HCA's node GUID.
326 * "HCA GUID" on SUCCESS, NULL on FAILURE
328 * For a given HCA node GUID it figures out the HCA GUID
329 * and returns it. If not found, NULL is returned.
332 ibtl_ibnex_hcadip2guid(dev_info_t
*hca_dip
)
334 ib_guid_t hca_guid
= 0LL;
335 ibtl_hca_devinfo_t
*hca_devp
;
337 mutex_enter(&ibtl_clnt_list_mutex
);
338 hca_devp
= ibtl_hca_list
;
341 if (hca_devp
->hd_hca_dip
== hca_dip
) {
342 hca_guid
= hca_devp
->hd_hca_attr
->hca_node_guid
;
345 hca_devp
= hca_devp
->hd_hca_dev_link
;
347 mutex_exit(&ibtl_clnt_list_mutex
);
348 IBTF_DPRINTF_L4(ibtl_ibnex
, "ibtl_ibnex_hcadip_guid: hca_guid 0x%llX",
356 * ibtl_ibnex_hcaguid2dip
358 * hca_guid - The HCA's node GUID.
360 * dev_info_t - The "dip" of this HCA
362 * "dip" on SUCCESS, NULL on FAILURE
364 * For a given HCA node GUID it figures out the "dip"
365 * and returns it. If not found, NULL is returned.
368 ibtl_ibnex_hcaguid2dip(ib_guid_t hca_guid
)
370 dev_info_t
*dip
= NULL
;
371 ibtl_hca_devinfo_t
*hca_devp
;
373 IBTF_DPRINTF_L4(ibtl_ibnex
, "ibtl_ibnex_hcaguid2dip:");
375 mutex_enter(&ibtl_clnt_list_mutex
);
376 hca_devp
= ibtl_hca_list
;
379 if (hca_devp
->hd_hca_attr
->hca_node_guid
== hca_guid
) {
380 dip
= hca_devp
->hd_hca_dip
;
383 hca_devp
= hca_devp
->hd_hca_dev_link
;
385 mutex_exit(&ibtl_clnt_list_mutex
);
392 * ibtl_ibnex_get_hca_verbose_data
394 * hca_guid - The HCA's node GUID.
396 * buffer - The information is returned in this buffer
397 * bufsiz - The size of the information buffer
399 * IBT_SUCCESS/IBT_HCA_INVALID
401 * For a given HCA node GUID it figures out the verbose listing display.
404 ibtl_ibnex_get_hca_verbose_data(ib_guid_t hca_guid
, char **buffer
,
407 char path
[IBTL_IBNEX_STR_LEN
];
408 char tmp
[MAXPATHLEN
];
410 ibt_hca_portinfo_t
*pinfop
;
411 ibtl_hca_devinfo_t
*hca_devp
;
413 IBTF_DPRINTF_L3(ibtl_ibnex
, "ibtl_ibnex_get_hca_verbose_data: "
414 "HCA GUID 0x%llX", hca_guid
);
419 mutex_enter(&ibtl_clnt_list_mutex
);
420 if ((hca_devp
= ibtl_get_hcadevinfo(hca_guid
)) == NULL
) {
421 mutex_exit(&ibtl_clnt_list_mutex
);
424 * If we are here, then the requested HCA device is not
425 * present. Return the status as Invalid HCA GUID.
427 IBTF_DPRINTF_L2(ibtl_ibnex
, "ibtl_ibnex_get_hca_verbose_data: "
428 "HCA Not Found, Invalid HCA GUID");
429 return (IBT_HCA_INVALID
);
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
);
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
);
444 mutex_exit(&ibtl_clnt_list_mutex
);
446 *bufsiz
= strlen(tmp
);
447 *buffer
= kmem_alloc(*bufsiz
, KM_SLEEP
);
448 (void) strncpy(*buffer
, tmp
, *bufsiz
);
450 IBTF_DPRINTF_L4(ibtl_ibnex
, "ibtl_ibnex_get_hca_verbose_data: "
451 "data = %s, size = 0x%x", *buffer
, *bufsiz
);
452 return (IBT_SUCCESS
);
463 * Return value from IBnexus callback handler
464 * IBT_ILLEGAL_OP if IBnexus callback is not installed.
466 * This function passes the IBTF client's "reprobe device
467 * properties" request to IBnexus. See ibt_reprobe_dev(9f)
471 ibt_reprobe_dev(dev_info_t
*dip
)
474 ibtl_ibnex_cb_args_t cb_args
;
477 return (IBT_NOT_SUPPORTED
);
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.
484 if (strcmp(ddi_node_name(ddi_get_parent(dip
)), "ib") != 0)
485 return (IBT_NOT_SUPPORTED
);
487 /* Reprobe for IOC nodes only */
488 if (strncmp(ddi_node_name(dip
), IBNEX_IBPORT_CNAME
, 6) == 0)
489 return (IBT_NOT_SUPPORTED
);
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
);
499 mutex_exit(&ibtl_clnt_list_mutex
);
501 /* Should -not- come here */
502 IBTF_DPRINTF_L2("ibtl", "ibt_reprobe_dev: ibnex not registered!!");
503 return (IBT_ILLEGAL_OP
);
509 * ibtl_ibnex_valid_hca_parent
511 * pdip - The parent dip from client's child dev_info_t
515 * IBT_SUCCESS/IBT_NO_HCAS_AVAILABLE
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.
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.
526 ibtl_ibnex_valid_hca_parent(dev_info_t
*pdip
)
528 ibtl_hca_devinfo_t
*hca_devp
;
530 IBTF_DPRINTF_L4(ibtl_ibnex
, "ibtl_ibnex_valid_hca_parent: pdip %p",
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
);
538 /* For Port devices and VPPAs */
539 mutex_enter(&ibtl_clnt_list_mutex
);
540 hca_devp
= ibtl_hca_list
;
542 if (hca_devp
->hd_hca_dip
== pdip
) {
543 mutex_exit(&ibtl_clnt_list_mutex
);
544 return (IBT_SUCCESS
);
546 hca_devp
= hca_devp
->hd_hca_dev_link
;
548 mutex_exit(&ibtl_clnt_list_mutex
);
549 return (IBT_NO_HCAS_AVAILABLE
);
555 * ibtl_ibnex_phci_register
557 * hca_dip - The HCA dip
561 * IBT_SUCCESS/IBT_FAILURE
563 * Register the HCA dip as the MPxIO PCHI.
566 ibtl_ibnex_phci_register(dev_info_t
*hca_dip
)
568 /* Register the with MPxIO as PHCI */
569 if (mdi_phci_register(MDI_HCI_CLASS_IB
, hca_dip
, 0) !=
571 return (IBT_FAILURE
);
573 return (IBT_SUCCESS
);
578 * ibtl_ibnex_phci_unregister
580 * hca_dip - The HCA dip
584 * IBT_SUCCESS/IBT_FAILURE
586 * Free up any pending MPxIO Pathinfos and unregister the HCA dip as the
590 ibtl_ibnex_phci_unregister(dev_info_t
*hca_dip
)
592 mdi_pathinfo_t
*pip
= NULL
;
593 dev_info_t
*vdip
= 0;
594 int circ
= 0, circ1
= 0;
597 * Should free all the Pathinfos associated with the HCA pdip before
598 * unregistering the PHCI.
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.
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
) {
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
);
617 ndi_devi_exit(hca_dip
, circ
);
618 ndi_devi_exit(vdip
, circ1
);
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
);
625 return (IBT_SUCCESS
);
630 * ibtl_ibnex_query_hca_byguid
632 * hca_guid - The HCA's node GUID.
633 * driver_name_size- size of the caller allocated driver_name buffer
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.
643 * IBT_SUCCESS/IBT_FAILURE
645 * Get the HCA attributes, driver name and instance number of the
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
)
653 ibtl_hca_devinfo_t
*hca_devp
;
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
);
660 mutex_enter(&ibtl_clnt_list_mutex
);
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
);
668 if (strlcpy(driver_name
,
669 ddi_driver_name(hca_devp
->hd_hca_dip
), driver_name_size
) >=
671 mutex_exit(&ibtl_clnt_list_mutex
);
672 return (IBT_INSUFF_KERNEL_RESOURCE
);
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
));
679 mutex_exit(&ibtl_clnt_list_mutex
);
680 return (IBT_SUCCESS
);