19684SSusan.Gleeson@Sun.COM /*
29684SSusan.Gleeson@Sun.COM * CDDL HEADER START
39684SSusan.Gleeson@Sun.COM *
49684SSusan.Gleeson@Sun.COM * The contents of this file are subject to the terms of the
59684SSusan.Gleeson@Sun.COM * Common Development and Distribution License (the "License").
69684SSusan.Gleeson@Sun.COM * You may not use this file except in compliance with the License.
79684SSusan.Gleeson@Sun.COM *
89684SSusan.Gleeson@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
99684SSusan.Gleeson@Sun.COM * or http://www.opensolaris.org/os/licensing.
109684SSusan.Gleeson@Sun.COM * See the License for the specific language governing permissions
119684SSusan.Gleeson@Sun.COM * and limitations under the License.
129684SSusan.Gleeson@Sun.COM *
139684SSusan.Gleeson@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
149684SSusan.Gleeson@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
159684SSusan.Gleeson@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
169684SSusan.Gleeson@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
179684SSusan.Gleeson@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
189684SSusan.Gleeson@Sun.COM *
199684SSusan.Gleeson@Sun.COM * CDDL HEADER END
209684SSusan.Gleeson@Sun.COM */
219684SSusan.Gleeson@Sun.COM
229684SSusan.Gleeson@Sun.COM /*
23*12509SPeter.Cudhea@Oracle.COM * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
249684SSusan.Gleeson@Sun.COM */
259684SSusan.Gleeson@Sun.COM
269684SSusan.Gleeson@Sun.COM /*
279684SSusan.Gleeson@Sun.COM * Infiniband Device Management Agent for IB storage.
289684SSusan.Gleeson@Sun.COM */
299684SSusan.Gleeson@Sun.COM
309684SSusan.Gleeson@Sun.COM #include <sys/conf.h>
319684SSusan.Gleeson@Sun.COM #include <sys/file.h>
329684SSusan.Gleeson@Sun.COM #include <sys/ddi.h>
339684SSusan.Gleeson@Sun.COM #include <sys/sunddi.h>
349684SSusan.Gleeson@Sun.COM #include <sys/modctl.h>
359684SSusan.Gleeson@Sun.COM #include <sys/priv.h>
369684SSusan.Gleeson@Sun.COM #include <sys/sysmacros.h>
379684SSusan.Gleeson@Sun.COM
389684SSusan.Gleeson@Sun.COM #include <sys/ib/ibtl/ibti.h> /* IB public interfaces */
399684SSusan.Gleeson@Sun.COM
409684SSusan.Gleeson@Sun.COM #include <sys/ib/mgt/ibdma/ibdma.h>
419684SSusan.Gleeson@Sun.COM #include <sys/ib/mgt/ibdma/ibdma_impl.h>
429684SSusan.Gleeson@Sun.COM
439684SSusan.Gleeson@Sun.COM /*
449684SSusan.Gleeson@Sun.COM * NOTE: The IB Device Management Agent function, like other IB
459684SSusan.Gleeson@Sun.COM * managers and agents is best implemented as a kernel misc.
469684SSusan.Gleeson@Sun.COM * module.
479684SSusan.Gleeson@Sun.COM * Eventually we could modify IBT_DM_AGENT so that we don't need to
489684SSusan.Gleeson@Sun.COM * open each HCA to receive asynchronous events.
499684SSusan.Gleeson@Sun.COM */
509684SSusan.Gleeson@Sun.COM
519684SSusan.Gleeson@Sun.COM #define IBDMA_NAME_VERSION "IB Device Management Agent"
529684SSusan.Gleeson@Sun.COM
539684SSusan.Gleeson@Sun.COM extern struct mod_ops mod_miscops;
549684SSusan.Gleeson@Sun.COM
559684SSusan.Gleeson@Sun.COM static void ibdma_ibt_async_handler(void *clnt, ibt_hca_hdl_t hdl,
569684SSusan.Gleeson@Sun.COM ibt_async_code_t code, ibt_async_event_t *event);
579684SSusan.Gleeson@Sun.COM
589684SSusan.Gleeson@Sun.COM static void ibdma_mad_recv_cb(ibmf_handle_t ibmf_hdl,
599684SSusan.Gleeson@Sun.COM ibmf_msg_t *msgp, void *args);
609684SSusan.Gleeson@Sun.COM static void ibdma_create_resp_mad(ibmf_msg_t *msgp);
619684SSusan.Gleeson@Sun.COM
629684SSusan.Gleeson@Sun.COM /*
639684SSusan.Gleeson@Sun.COM * Misc. kernel module for now.
649684SSusan.Gleeson@Sun.COM */
659684SSusan.Gleeson@Sun.COM static struct modlmisc modlmisc = {
669684SSusan.Gleeson@Sun.COM &mod_miscops,
679684SSusan.Gleeson@Sun.COM IBDMA_NAME_VERSION
689684SSusan.Gleeson@Sun.COM };
699684SSusan.Gleeson@Sun.COM
709684SSusan.Gleeson@Sun.COM static struct modlinkage modlinkage = {
719684SSusan.Gleeson@Sun.COM MODREV_1, (void *)&modlmisc, NULL
729684SSusan.Gleeson@Sun.COM };
739684SSusan.Gleeson@Sun.COM
749684SSusan.Gleeson@Sun.COM static ibt_clnt_modinfo_t ibdma_ibt_modinfo = {
759684SSusan.Gleeson@Sun.COM IBTI_V_CURR,
769684SSusan.Gleeson@Sun.COM IBT_DM_AGENT,
779684SSusan.Gleeson@Sun.COM ibdma_ibt_async_handler,
789684SSusan.Gleeson@Sun.COM NULL,
799684SSusan.Gleeson@Sun.COM "ibdma"
809684SSusan.Gleeson@Sun.COM };
819684SSusan.Gleeson@Sun.COM
829684SSusan.Gleeson@Sun.COM /*
839684SSusan.Gleeson@Sun.COM * Module global state allocated at init().
849684SSusan.Gleeson@Sun.COM */
859684SSusan.Gleeson@Sun.COM static ibdma_mod_state_t *ibdma = NULL;
869684SSusan.Gleeson@Sun.COM
879684SSusan.Gleeson@Sun.COM /*
889684SSusan.Gleeson@Sun.COM * Init/Fini handlers and IBTL HCA management prototypes.
899684SSusan.Gleeson@Sun.COM */
909684SSusan.Gleeson@Sun.COM static int ibdma_init();
919684SSusan.Gleeson@Sun.COM static int ibdma_fini();
929684SSusan.Gleeson@Sun.COM static int ibdma_ibt_init();
939684SSusan.Gleeson@Sun.COM static void ibdma_ibt_fini();
949684SSusan.Gleeson@Sun.COM static ibdma_hca_t *ibdma_hca_init(ib_guid_t guid);
959684SSusan.Gleeson@Sun.COM static void ibdma_hca_fini(ibdma_hca_t *hca);
969684SSusan.Gleeson@Sun.COM static ibdma_hca_t *ibdma_find_hca(ib_guid_t guid);
979684SSusan.Gleeson@Sun.COM
989684SSusan.Gleeson@Sun.COM /*
999684SSusan.Gleeson@Sun.COM * DevMgmt Agent MAD attribute handlers prototypes.
1009684SSusan.Gleeson@Sun.COM */
1019684SSusan.Gleeson@Sun.COM static void ibdma_get_class_portinfo(ibmf_msg_t *msg);
1029684SSusan.Gleeson@Sun.COM static void ibdma_get_io_unitinfo(ibdma_hca_t *hca, ibmf_msg_t *msg);
1039684SSusan.Gleeson@Sun.COM static void ibdma_get_ioc_profile(ibdma_hca_t *hca, ibmf_msg_t *msg);
1049684SSusan.Gleeson@Sun.COM static void ibdma_get_ioc_services(ibdma_hca_t *hca, ibmf_msg_t *msg);
1059684SSusan.Gleeson@Sun.COM
1069684SSusan.Gleeson@Sun.COM /*
1079684SSusan.Gleeson@Sun.COM * _init()
1089684SSusan.Gleeson@Sun.COM */
1099684SSusan.Gleeson@Sun.COM int
_init(void)1109684SSusan.Gleeson@Sun.COM _init(void)
1119684SSusan.Gleeson@Sun.COM {
1129684SSusan.Gleeson@Sun.COM int status;
1139684SSusan.Gleeson@Sun.COM
1149684SSusan.Gleeson@Sun.COM ASSERT(ibdma == NULL);
1159684SSusan.Gleeson@Sun.COM
1169684SSusan.Gleeson@Sun.COM ibdma = kmem_zalloc(sizeof (*ibdma), KM_SLEEP);
1179684SSusan.Gleeson@Sun.COM ASSERT(ibdma != NULL);
1189684SSusan.Gleeson@Sun.COM
1199684SSusan.Gleeson@Sun.COM status = ibdma_init();
1209684SSusan.Gleeson@Sun.COM if (status != DDI_SUCCESS) {
1219684SSusan.Gleeson@Sun.COM kmem_free(ibdma, sizeof (*ibdma));
1229684SSusan.Gleeson@Sun.COM ibdma = NULL;
1239684SSusan.Gleeson@Sun.COM return (status);
1249684SSusan.Gleeson@Sun.COM }
1259684SSusan.Gleeson@Sun.COM
1269684SSusan.Gleeson@Sun.COM status = mod_install(&modlinkage);
1279684SSusan.Gleeson@Sun.COM if (status != DDI_SUCCESS) {
1289684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "_init, mod_install error (%d)", status);
1299684SSusan.Gleeson@Sun.COM (void) ibdma_fini();
1309684SSusan.Gleeson@Sun.COM kmem_free(ibdma, sizeof (*ibdma));
1319684SSusan.Gleeson@Sun.COM ibdma = NULL;
1329684SSusan.Gleeson@Sun.COM }
1339684SSusan.Gleeson@Sun.COM return (status);
1349684SSusan.Gleeson@Sun.COM }
1359684SSusan.Gleeson@Sun.COM
1369684SSusan.Gleeson@Sun.COM /*
1379684SSusan.Gleeson@Sun.COM * _info()
1389684SSusan.Gleeson@Sun.COM */
1399684SSusan.Gleeson@Sun.COM int
_info(struct modinfo * modinfop)1409684SSusan.Gleeson@Sun.COM _info(struct modinfo *modinfop)
1419684SSusan.Gleeson@Sun.COM {
1429684SSusan.Gleeson@Sun.COM return (mod_info(&modlinkage, modinfop));
1439684SSusan.Gleeson@Sun.COM }
1449684SSusan.Gleeson@Sun.COM
1459684SSusan.Gleeson@Sun.COM /*
1469684SSusan.Gleeson@Sun.COM * _fini()
1479684SSusan.Gleeson@Sun.COM */
1489684SSusan.Gleeson@Sun.COM int
_fini(void)1499684SSusan.Gleeson@Sun.COM _fini(void)
1509684SSusan.Gleeson@Sun.COM {
1519684SSusan.Gleeson@Sun.COM int status;
1529684SSusan.Gleeson@Sun.COM int slot;
1539684SSusan.Gleeson@Sun.COM ibdma_hca_t *hca;
1549684SSusan.Gleeson@Sun.COM
1559684SSusan.Gleeson@Sun.COM status = mod_remove(&modlinkage);
1569684SSusan.Gleeson@Sun.COM if (status != DDI_SUCCESS) {
1579684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "_fini, mod_remove error (%d)", status);
1589684SSusan.Gleeson@Sun.COM return (status);
1599684SSusan.Gleeson@Sun.COM }
1609684SSusan.Gleeson@Sun.COM
1619684SSusan.Gleeson@Sun.COM /*
1629684SSusan.Gleeson@Sun.COM * Sanity check to see if anyone is not cleaning
1639684SSusan.Gleeson@Sun.COM * up appropriately.
1649684SSusan.Gleeson@Sun.COM */
1659684SSusan.Gleeson@Sun.COM mutex_enter(&ibdma->ms_hca_list_lock);
1669684SSusan.Gleeson@Sun.COM hca = list_head(&ibdma->ms_hca_list);
1679684SSusan.Gleeson@Sun.COM while (hca != NULL) {
1689684SSusan.Gleeson@Sun.COM for (slot = 0; slot < IBDMA_MAX_IOC; slot++) {
1699684SSusan.Gleeson@Sun.COM if (hca->ih_ioc[slot].ii_inuse) {
1709684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "_fini, IOC %d still attached"
1719684SSusan.Gleeson@Sun.COM " for (0x%0llx)", slot+1,
1729684SSusan.Gleeson@Sun.COM (u_longlong_t)hca->ih_iou_guid);
1739684SSusan.Gleeson@Sun.COM }
1749684SSusan.Gleeson@Sun.COM }
1759684SSusan.Gleeson@Sun.COM hca = list_next(&ibdma->ms_hca_list, hca);
1769684SSusan.Gleeson@Sun.COM }
1779684SSusan.Gleeson@Sun.COM mutex_exit(&ibdma->ms_hca_list_lock);
1789684SSusan.Gleeson@Sun.COM
1799684SSusan.Gleeson@Sun.COM (void) ibdma_fini();
1809684SSusan.Gleeson@Sun.COM kmem_free(ibdma, sizeof (*ibdma));
1819684SSusan.Gleeson@Sun.COM return (status);
1829684SSusan.Gleeson@Sun.COM }
1839684SSusan.Gleeson@Sun.COM
1849684SSusan.Gleeson@Sun.COM /*
1859684SSusan.Gleeson@Sun.COM * ibdma_init()
1869684SSusan.Gleeson@Sun.COM *
1879684SSusan.Gleeson@Sun.COM * Initialize I/O Unit structure, generate initial HCA list and register
1889684SSusan.Gleeson@Sun.COM * it port with the IBMF.
1899684SSusan.Gleeson@Sun.COM */
1909684SSusan.Gleeson@Sun.COM static int
ibdma_init()1919684SSusan.Gleeson@Sun.COM ibdma_init()
1929684SSusan.Gleeson@Sun.COM {
1939684SSusan.Gleeson@Sun.COM int status;
1949684SSusan.Gleeson@Sun.COM
1959684SSusan.Gleeson@Sun.COM /*
1969684SSusan.Gleeson@Sun.COM * Global lock and I/O Unit initialization.
1979684SSusan.Gleeson@Sun.COM */
1989684SSusan.Gleeson@Sun.COM mutex_init(&ibdma->ms_hca_list_lock, NULL, MUTEX_DRIVER, NULL);
1999684SSusan.Gleeson@Sun.COM
2009684SSusan.Gleeson@Sun.COM /*
2019684SSusan.Gleeson@Sun.COM * Discover IB hardware and setup for device management agent
2029684SSusan.Gleeson@Sun.COM * support.
2039684SSusan.Gleeson@Sun.COM */
2049684SSusan.Gleeson@Sun.COM status = ibdma_ibt_init();
2059684SSusan.Gleeson@Sun.COM if (status != DDI_SUCCESS) {
2069684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "ibdma_init, ibt_attach failed (%d)",
2079684SSusan.Gleeson@Sun.COM status);
2089684SSusan.Gleeson@Sun.COM mutex_destroy(&ibdma->ms_hca_list_lock);
2099684SSusan.Gleeson@Sun.COM return (status);
2109684SSusan.Gleeson@Sun.COM }
2119684SSusan.Gleeson@Sun.COM
2129684SSusan.Gleeson@Sun.COM return (status);
2139684SSusan.Gleeson@Sun.COM }
2149684SSusan.Gleeson@Sun.COM
2159684SSusan.Gleeson@Sun.COM /*
2169684SSusan.Gleeson@Sun.COM * ibdma_fini()
2179684SSusan.Gleeson@Sun.COM *
2189684SSusan.Gleeson@Sun.COM * Release resource if we are no longer in use.
2199684SSusan.Gleeson@Sun.COM */
2209684SSusan.Gleeson@Sun.COM static int
ibdma_fini()2219684SSusan.Gleeson@Sun.COM ibdma_fini()
2229684SSusan.Gleeson@Sun.COM {
2239684SSusan.Gleeson@Sun.COM ibdma_ibt_fini();
2249684SSusan.Gleeson@Sun.COM mutex_destroy(&ibdma->ms_hca_list_lock);
2259684SSusan.Gleeson@Sun.COM return (DDI_SUCCESS);
2269684SSusan.Gleeson@Sun.COM }
2279684SSusan.Gleeson@Sun.COM
2289684SSusan.Gleeson@Sun.COM /*
2299684SSusan.Gleeson@Sun.COM * ibdma_ibt_async_handler()
2309684SSusan.Gleeson@Sun.COM */
2319684SSusan.Gleeson@Sun.COM /* ARGSUSED */
2329684SSusan.Gleeson@Sun.COM static void
ibdma_ibt_async_handler(void * clnt,ibt_hca_hdl_t hdl,ibt_async_code_t code,ibt_async_event_t * event)2339684SSusan.Gleeson@Sun.COM ibdma_ibt_async_handler(void *clnt, ibt_hca_hdl_t hdl,
2349684SSusan.Gleeson@Sun.COM ibt_async_code_t code, ibt_async_event_t *event)
2359684SSusan.Gleeson@Sun.COM {
2369684SSusan.Gleeson@Sun.COM ibdma_hca_t *hca;
2379684SSusan.Gleeson@Sun.COM
2389684SSusan.Gleeson@Sun.COM switch (code) {
2399684SSusan.Gleeson@Sun.COM
2409684SSusan.Gleeson@Sun.COM case IBT_EVENT_PORT_UP:
2419684SSusan.Gleeson@Sun.COM case IBT_ERROR_PORT_DOWN:
242*12509SPeter.Cudhea@Oracle.COM case IBT_PORT_CHANGE_EVENT:
243*12509SPeter.Cudhea@Oracle.COM case IBT_CLNT_REREG_EVENT:
2449684SSusan.Gleeson@Sun.COM break;
2459684SSusan.Gleeson@Sun.COM
2469684SSusan.Gleeson@Sun.COM case IBT_HCA_ATTACH_EVENT:
2479684SSusan.Gleeson@Sun.COM mutex_enter(&ibdma->ms_hca_list_lock);
2489684SSusan.Gleeson@Sun.COM hca = ibdma_hca_init(event->ev_hca_guid);
2499684SSusan.Gleeson@Sun.COM if (hca != NULL) {
2509684SSusan.Gleeson@Sun.COM list_insert_tail(&ibdma->ms_hca_list, hca);
2519684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "hca ibt hdl (%p)",
2529684SSusan.Gleeson@Sun.COM (void *)hca->ih_ibt_hdl);
2539684SSusan.Gleeson@Sun.COM ibdma->ms_num_hcas++;
2549684SSusan.Gleeson@Sun.COM }
2559684SSusan.Gleeson@Sun.COM mutex_exit(&ibdma->ms_hca_list_lock);
2569684SSusan.Gleeson@Sun.COM break;
2579684SSusan.Gleeson@Sun.COM
2589684SSusan.Gleeson@Sun.COM case IBT_HCA_DETACH_EVENT:
2599684SSusan.Gleeson@Sun.COM mutex_enter(&ibdma->ms_hca_list_lock);
2609684SSusan.Gleeson@Sun.COM hca = ibdma_find_hca(event->ev_hca_guid);
2619684SSusan.Gleeson@Sun.COM if (hca != NULL) {
2629684SSusan.Gleeson@Sun.COM list_remove(&ibdma->ms_hca_list, hca);
2639684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "removing hca (%p) (0x%llx)",
2649684SSusan.Gleeson@Sun.COM (void *)hca, hca ?
2659684SSusan.Gleeson@Sun.COM (u_longlong_t)hca->ih_iou_guid : 0x0ll);
2669684SSusan.Gleeson@Sun.COM ibdma_hca_fini(hca);
2679684SSusan.Gleeson@Sun.COM }
2689684SSusan.Gleeson@Sun.COM mutex_exit(&ibdma->ms_hca_list_lock);
2699684SSusan.Gleeson@Sun.COM break;
2709684SSusan.Gleeson@Sun.COM
2719684SSusan.Gleeson@Sun.COM default:
272*12509SPeter.Cudhea@Oracle.COM #ifdef DEBUG
2739684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "ibt_async_handler, unhandled event(%d)",
2749684SSusan.Gleeson@Sun.COM code);
275*12509SPeter.Cudhea@Oracle.COM #endif
2769684SSusan.Gleeson@Sun.COM break;
2779684SSusan.Gleeson@Sun.COM }
2789684SSusan.Gleeson@Sun.COM
2799684SSusan.Gleeson@Sun.COM }
2809684SSusan.Gleeson@Sun.COM
2819684SSusan.Gleeson@Sun.COM /*
2829684SSusan.Gleeson@Sun.COM * ibdma_ibt_init()
2839684SSusan.Gleeson@Sun.COM */
2849684SSusan.Gleeson@Sun.COM static int
ibdma_ibt_init()2859684SSusan.Gleeson@Sun.COM ibdma_ibt_init()
2869684SSusan.Gleeson@Sun.COM {
2879684SSusan.Gleeson@Sun.COM int status;
2889684SSusan.Gleeson@Sun.COM int hca_cnt;
2899684SSusan.Gleeson@Sun.COM int hca_ndx;
2909684SSusan.Gleeson@Sun.COM ib_guid_t *guid;
2919684SSusan.Gleeson@Sun.COM ibdma_hca_t *hca;
2929684SSusan.Gleeson@Sun.COM
2939684SSusan.Gleeson@Sun.COM /*
2949684SSusan.Gleeson@Sun.COM * Attach to IBTF and get HCA list.
2959684SSusan.Gleeson@Sun.COM */
2969684SSusan.Gleeson@Sun.COM status = ibt_attach(&ibdma_ibt_modinfo, NULL,
2979684SSusan.Gleeson@Sun.COM ibdma, &ibdma->ms_ibt_hdl);
2989684SSusan.Gleeson@Sun.COM if (status != DDI_SUCCESS) {
2999684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "ibt_init, ibt_attach failed (%d)",
3009684SSusan.Gleeson@Sun.COM status);
3019684SSusan.Gleeson@Sun.COM return (status);
3029684SSusan.Gleeson@Sun.COM }
3039684SSusan.Gleeson@Sun.COM
30411097SSusan.Gleeson@Sun.COM list_create(&ibdma->ms_hca_list, sizeof (ibdma_hca_t),
30511097SSusan.Gleeson@Sun.COM offsetof(ibdma_hca_t, ih_node));
30611097SSusan.Gleeson@Sun.COM
3079684SSusan.Gleeson@Sun.COM hca_cnt = ibt_get_hca_list(&guid);
3089684SSusan.Gleeson@Sun.COM if (hca_cnt < 1) {
3099684SSusan.Gleeson@Sun.COM #ifdef DEBUG_IBDMA
3109684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "ibt_init, no HCA(s) found");
3119684SSusan.Gleeson@Sun.COM #endif
31211097SSusan.Gleeson@Sun.COM /* not an error if no HCAs, but nothing more to do here */
31311097SSusan.Gleeson@Sun.COM return (DDI_SUCCESS);
3149684SSusan.Gleeson@Sun.COM }
3159684SSusan.Gleeson@Sun.COM
3169684SSusan.Gleeson@Sun.COM mutex_enter(&ibdma->ms_hca_list_lock);
3179684SSusan.Gleeson@Sun.COM
3189684SSusan.Gleeson@Sun.COM for (hca_ndx = 0; hca_ndx < hca_cnt; hca_ndx++) {
3199684SSusan.Gleeson@Sun.COM #ifdef DEBUG_IBDMA
3209684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "adding hca GUID(0x%llx)",
3219684SSusan.Gleeson@Sun.COM (u_longlong_t)guid[hca_ndx]);
3229684SSusan.Gleeson@Sun.COM #endif
3239684SSusan.Gleeson@Sun.COM
3249684SSusan.Gleeson@Sun.COM hca = ibdma_hca_init(guid[hca_ndx]);
3259684SSusan.Gleeson@Sun.COM if (hca == NULL) {
3269684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "ibt_init, hca_init GUID(0x%llx)"
3279684SSusan.Gleeson@Sun.COM " failed", (u_longlong_t)guid[hca_ndx]);
3289684SSusan.Gleeson@Sun.COM continue;
3299684SSusan.Gleeson@Sun.COM }
3309684SSusan.Gleeson@Sun.COM list_insert_tail(&ibdma->ms_hca_list, hca);
3319684SSusan.Gleeson@Sun.COM ibdma->ms_num_hcas++;
3329684SSusan.Gleeson@Sun.COM }
3339684SSusan.Gleeson@Sun.COM
3349684SSusan.Gleeson@Sun.COM mutex_exit(&ibdma->ms_hca_list_lock);
3359684SSusan.Gleeson@Sun.COM
3369684SSusan.Gleeson@Sun.COM ibt_free_hca_list(guid, hca_cnt);
3379684SSusan.Gleeson@Sun.COM #ifdef DEBUG_IBDMA
3389684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "Added %d HCA(s)",
3399684SSusan.Gleeson@Sun.COM ibdma->ms_num_hcas);
3409684SSusan.Gleeson@Sun.COM #endif
3419684SSusan.Gleeson@Sun.COM return (DDI_SUCCESS);
3429684SSusan.Gleeson@Sun.COM }
3439684SSusan.Gleeson@Sun.COM
3449684SSusan.Gleeson@Sun.COM /*
3459684SSusan.Gleeson@Sun.COM * ibdma_ibt_fini()
3469684SSusan.Gleeson@Sun.COM */
3479684SSusan.Gleeson@Sun.COM static void
ibdma_ibt_fini()3489684SSusan.Gleeson@Sun.COM ibdma_ibt_fini()
3499684SSusan.Gleeson@Sun.COM {
3509684SSusan.Gleeson@Sun.COM ibdma_hca_t *hca;
3519684SSusan.Gleeson@Sun.COM ibdma_hca_t *next;
3529684SSusan.Gleeson@Sun.COM
3539684SSusan.Gleeson@Sun.COM mutex_enter(&ibdma->ms_hca_list_lock);
3549684SSusan.Gleeson@Sun.COM hca = list_head(&ibdma->ms_hca_list);
3559684SSusan.Gleeson@Sun.COM while (hca != NULL) {
3569684SSusan.Gleeson@Sun.COM next = list_next(&ibdma->ms_hca_list, hca);
3579684SSusan.Gleeson@Sun.COM list_remove(&ibdma->ms_hca_list, hca);
3589684SSusan.Gleeson@Sun.COM #ifdef DEBUG_IBDMA
3599684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "removing hca (%p) (0x%llx)",
3609684SSusan.Gleeson@Sun.COM (void *)hca, hca ?
3619684SSusan.Gleeson@Sun.COM (u_longlong_t)hca->ih_iou_guid : 0x0ll);
3629684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "hca ibt hdl (%p)",
3639684SSusan.Gleeson@Sun.COM (void *)hca->ih_ibt_hdl);
3649684SSusan.Gleeson@Sun.COM #endif
3659684SSusan.Gleeson@Sun.COM ibdma_hca_fini(hca);
3669684SSusan.Gleeson@Sun.COM hca = next;
3679684SSusan.Gleeson@Sun.COM }
3689684SSusan.Gleeson@Sun.COM list_destroy(&ibdma->ms_hca_list);
3699684SSusan.Gleeson@Sun.COM
37011097SSusan.Gleeson@Sun.COM (void) ibt_detach(ibdma->ms_ibt_hdl);
3719684SSusan.Gleeson@Sun.COM ibdma->ms_ibt_hdl = NULL;
3729684SSusan.Gleeson@Sun.COM ibdma->ms_num_hcas = 0;
3739684SSusan.Gleeson@Sun.COM mutex_exit(&ibdma->ms_hca_list_lock);
3749684SSusan.Gleeson@Sun.COM }
3759684SSusan.Gleeson@Sun.COM
3769684SSusan.Gleeson@Sun.COM /*
3779684SSusan.Gleeson@Sun.COM * ibdma_find_hca()
3789684SSusan.Gleeson@Sun.COM */
3799684SSusan.Gleeson@Sun.COM static ibdma_hca_t *
ibdma_find_hca(ib_guid_t guid)3809684SSusan.Gleeson@Sun.COM ibdma_find_hca(ib_guid_t guid)
3819684SSusan.Gleeson@Sun.COM {
3829684SSusan.Gleeson@Sun.COM ibdma_hca_t *hca;
3839684SSusan.Gleeson@Sun.COM
3849684SSusan.Gleeson@Sun.COM ASSERT(mutex_owned(&ibdma->ms_hca_list_lock));
3859684SSusan.Gleeson@Sun.COM
3869684SSusan.Gleeson@Sun.COM hca = list_head(&ibdma->ms_hca_list);
3879684SSusan.Gleeson@Sun.COM while (hca != NULL) {
3889684SSusan.Gleeson@Sun.COM if (hca->ih_iou_guid == guid) {
3899684SSusan.Gleeson@Sun.COM break;
3909684SSusan.Gleeson@Sun.COM }
3919684SSusan.Gleeson@Sun.COM hca = list_next(&ibdma->ms_hca_list, hca);
3929684SSusan.Gleeson@Sun.COM }
3939684SSusan.Gleeson@Sun.COM return (hca);
3949684SSusan.Gleeson@Sun.COM }
3959684SSusan.Gleeson@Sun.COM
3969684SSusan.Gleeson@Sun.COM /*
3979684SSusan.Gleeson@Sun.COM * ibdma_hca_init()
3989684SSusan.Gleeson@Sun.COM */
3999684SSusan.Gleeson@Sun.COM static ibdma_hca_t *
ibdma_hca_init(ib_guid_t guid)4009684SSusan.Gleeson@Sun.COM ibdma_hca_init(ib_guid_t guid)
4019684SSusan.Gleeson@Sun.COM {
4029684SSusan.Gleeson@Sun.COM ibt_status_t status;
4039684SSusan.Gleeson@Sun.COM ibdma_hca_t *hca;
4049684SSusan.Gleeson@Sun.COM ibdma_port_t *port;
4059684SSusan.Gleeson@Sun.COM ibt_hca_attr_t hca_attr;
4069684SSusan.Gleeson@Sun.COM int ndx;
4079684SSusan.Gleeson@Sun.COM
4089684SSusan.Gleeson@Sun.COM ASSERT(mutex_owned(&ibdma->ms_hca_list_lock));
4099684SSusan.Gleeson@Sun.COM
4109684SSusan.Gleeson@Sun.COM status = ibt_query_hca_byguid(guid, &hca_attr);
4119684SSusan.Gleeson@Sun.COM if (status != IBT_SUCCESS) {
4129684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "hca_init HCA query error (%d)",
4139684SSusan.Gleeson@Sun.COM status);
4149684SSusan.Gleeson@Sun.COM return (NULL);
4159684SSusan.Gleeson@Sun.COM }
4169684SSusan.Gleeson@Sun.COM
4179684SSusan.Gleeson@Sun.COM if (ibdma_find_hca(guid) != NULL) {
4189684SSusan.Gleeson@Sun.COM #ifdef DEBUG_IBDMA
4199684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "hca_init HCA already exists");
4209684SSusan.Gleeson@Sun.COM #endif
4219684SSusan.Gleeson@Sun.COM return (NULL);
4229684SSusan.Gleeson@Sun.COM }
4239684SSusan.Gleeson@Sun.COM
4249684SSusan.Gleeson@Sun.COM hca = kmem_zalloc(sizeof (ibdma_hca_t) +
4259684SSusan.Gleeson@Sun.COM (hca_attr.hca_nports-1)*sizeof (ibdma_port_t), KM_SLEEP);
4269684SSusan.Gleeson@Sun.COM ASSERT(hca != NULL);
4279684SSusan.Gleeson@Sun.COM
4289684SSusan.Gleeson@Sun.COM hca->ih_nports = hca_attr.hca_nports;
4299684SSusan.Gleeson@Sun.COM
4309684SSusan.Gleeson@Sun.COM rw_init(&hca->ih_iou_rwlock, NULL, RW_DRIVER, NULL);
4319684SSusan.Gleeson@Sun.COM rw_enter(&hca->ih_iou_rwlock, RW_WRITER);
4329684SSusan.Gleeson@Sun.COM hca->ih_iou_guid = guid;
4339684SSusan.Gleeson@Sun.COM hca->ih_iou.iou_changeid = h2b16(1);
4349684SSusan.Gleeson@Sun.COM hca->ih_iou.iou_num_ctrl_slots = IBDMA_MAX_IOC;
4359684SSusan.Gleeson@Sun.COM hca->ih_iou.iou_flag = IB_DM_IOU_OPTIONROM_ABSENT;
4369684SSusan.Gleeson@Sun.COM
4379684SSusan.Gleeson@Sun.COM list_create(&hca->ih_hdl_list, sizeof (ibdma_hdl_impl_t),
4389684SSusan.Gleeson@Sun.COM offsetof(ibdma_hdl_impl_t, ih_node));
4399684SSusan.Gleeson@Sun.COM rw_exit(&hca->ih_iou_rwlock);
4409684SSusan.Gleeson@Sun.COM
4419684SSusan.Gleeson@Sun.COM /*
4429684SSusan.Gleeson@Sun.COM * It would be better to not open, but IBTL is setup to only allow
4439684SSusan.Gleeson@Sun.COM * certain managers to get async call backs if not open.
4449684SSusan.Gleeson@Sun.COM */
4459684SSusan.Gleeson@Sun.COM status = ibt_open_hca(ibdma->ms_ibt_hdl, guid, &hca->ih_ibt_hdl);
4469684SSusan.Gleeson@Sun.COM if (status != IBT_SUCCESS) {
4479684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "hca_init() IBT open failed (%d)",
4489684SSusan.Gleeson@Sun.COM status);
4499684SSusan.Gleeson@Sun.COM
4509684SSusan.Gleeson@Sun.COM list_destroy(&hca->ih_hdl_list);
4519684SSusan.Gleeson@Sun.COM rw_destroy(&hca->ih_iou_rwlock);
4529684SSusan.Gleeson@Sun.COM kmem_free(hca, sizeof (ibdma_hca_t) +
4539684SSusan.Gleeson@Sun.COM (hca_attr.hca_nports-1)*sizeof (ibdma_port_t));
4549684SSusan.Gleeson@Sun.COM return (NULL);
4559684SSusan.Gleeson@Sun.COM }
4569684SSusan.Gleeson@Sun.COM
4579684SSusan.Gleeson@Sun.COM /*
4589684SSusan.Gleeson@Sun.COM * Register with the IB Management Framework and setup MAD call-back.
4599684SSusan.Gleeson@Sun.COM */
4609684SSusan.Gleeson@Sun.COM for (ndx = 0; ndx < hca->ih_nports; ndx++) {
4619684SSusan.Gleeson@Sun.COM port = &hca->ih_port[ndx];
4629684SSusan.Gleeson@Sun.COM port->ip_hcap = hca;
4639684SSusan.Gleeson@Sun.COM port->ip_ibmf_reg.ir_ci_guid = hca->ih_iou_guid;
4649684SSusan.Gleeson@Sun.COM port->ip_ibmf_reg.ir_port_num = ndx + 1;
4659684SSusan.Gleeson@Sun.COM port->ip_ibmf_reg.ir_client_class = DEV_MGT_AGENT;
4669684SSusan.Gleeson@Sun.COM
4679684SSusan.Gleeson@Sun.COM status = ibmf_register(&port->ip_ibmf_reg, IBMF_VERSION,
4689684SSusan.Gleeson@Sun.COM 0, NULL, NULL, &port->ip_ibmf_hdl, &port->ip_ibmf_caps);
4699684SSusan.Gleeson@Sun.COM if (status != IBMF_SUCCESS) {
4709684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "hca_init, IBMF register failed (%d)",
4719684SSusan.Gleeson@Sun.COM status);
4729684SSusan.Gleeson@Sun.COM port->ip_ibmf_hdl = NULL;
4739684SSusan.Gleeson@Sun.COM ibdma_hca_fini(hca);
4749684SSusan.Gleeson@Sun.COM return (NULL);
4759684SSusan.Gleeson@Sun.COM }
4769684SSusan.Gleeson@Sun.COM
4779684SSusan.Gleeson@Sun.COM status = ibmf_setup_async_cb(port->ip_ibmf_hdl,
4789684SSusan.Gleeson@Sun.COM IBMF_QP_HANDLE_DEFAULT, ibdma_mad_recv_cb, port, 0);
4799684SSusan.Gleeson@Sun.COM if (status != IBMF_SUCCESS) {
4809684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "hca_init, IBMF cb setup failed (%d)",
4819684SSusan.Gleeson@Sun.COM status);
4829684SSusan.Gleeson@Sun.COM ibdma_hca_fini(hca);
4839684SSusan.Gleeson@Sun.COM return (NULL);
4849684SSusan.Gleeson@Sun.COM }
4859684SSusan.Gleeson@Sun.COM
4869684SSusan.Gleeson@Sun.COM status = ibt_modify_port_byguid(hca->ih_iou_guid,
4879684SSusan.Gleeson@Sun.COM ndx+1, IBT_PORT_SET_DEVMGT, 0);
4889684SSusan.Gleeson@Sun.COM if (status != IBT_SUCCESS) {
4899684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "hca_init, IBT modify port caps"
4909684SSusan.Gleeson@Sun.COM " error (%d)", status);
4919684SSusan.Gleeson@Sun.COM ibdma_hca_fini(hca);
4929684SSusan.Gleeson@Sun.COM return (NULL);
4939684SSusan.Gleeson@Sun.COM }
4949684SSusan.Gleeson@Sun.COM }
4959684SSusan.Gleeson@Sun.COM return (hca);
4969684SSusan.Gleeson@Sun.COM }
4979684SSusan.Gleeson@Sun.COM
4989684SSusan.Gleeson@Sun.COM /*
4999684SSusan.Gleeson@Sun.COM * ibdma_hca_fini()
5009684SSusan.Gleeson@Sun.COM */
5019684SSusan.Gleeson@Sun.COM static void
ibdma_hca_fini(ibdma_hca_t * hca)5029684SSusan.Gleeson@Sun.COM ibdma_hca_fini(ibdma_hca_t *hca)
5039684SSusan.Gleeson@Sun.COM {
5049684SSusan.Gleeson@Sun.COM int status;
5059684SSusan.Gleeson@Sun.COM int ndx;
5069684SSusan.Gleeson@Sun.COM ibdma_port_t *port;
5079684SSusan.Gleeson@Sun.COM ibdma_hdl_impl_t *hdl;
5089684SSusan.Gleeson@Sun.COM ibdma_hdl_impl_t *hdl_next;
5099684SSusan.Gleeson@Sun.COM
5109684SSusan.Gleeson@Sun.COM ASSERT(mutex_owned(&ibdma->ms_hca_list_lock));
5119684SSusan.Gleeson@Sun.COM ASSERT(hca != NULL);
5129684SSusan.Gleeson@Sun.COM
5139684SSusan.Gleeson@Sun.COM rw_enter(&hca->ih_iou_rwlock, RW_WRITER);
5149684SSusan.Gleeson@Sun.COM
5159684SSusan.Gleeson@Sun.COM /*
5169684SSusan.Gleeson@Sun.COM * All handles should have been de-registered, but release
5179684SSusan.Gleeson@Sun.COM * any that are outstanding.
5189684SSusan.Gleeson@Sun.COM */
5199684SSusan.Gleeson@Sun.COM hdl = list_head(&hca->ih_hdl_list);
5209684SSusan.Gleeson@Sun.COM while (hdl != NULL) {
5219684SSusan.Gleeson@Sun.COM hdl_next = list_next(&hca->ih_hdl_list, hdl);
5229684SSusan.Gleeson@Sun.COM list_remove(&hca->ih_hdl_list, hdl);
5239684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "hca_fini, unexpected ibdma user handle"
5249684SSusan.Gleeson@Sun.COM " exists");
5259684SSusan.Gleeson@Sun.COM kmem_free(hdl, sizeof (*hdl));
5269684SSusan.Gleeson@Sun.COM hdl = hdl_next;
5279684SSusan.Gleeson@Sun.COM }
5289684SSusan.Gleeson@Sun.COM list_destroy(&hca->ih_hdl_list);
5299684SSusan.Gleeson@Sun.COM
5309684SSusan.Gleeson@Sun.COM /*
5319684SSusan.Gleeson@Sun.COM * Un-register with the IBMF.
5329684SSusan.Gleeson@Sun.COM */
5339684SSusan.Gleeson@Sun.COM for (ndx = 0; ndx < hca->ih_nports; ndx++) {
5349684SSusan.Gleeson@Sun.COM port = &hca->ih_port[ndx];
5359684SSusan.Gleeson@Sun.COM port->ip_hcap = NULL;
5369684SSusan.Gleeson@Sun.COM
5379684SSusan.Gleeson@Sun.COM status = ibt_modify_port_byguid(hca->ih_iou_guid,
5389684SSusan.Gleeson@Sun.COM ndx+1, IBT_PORT_RESET_DEVMGT, 0);
5399684SSusan.Gleeson@Sun.COM if (status != IBT_SUCCESS)
5409684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "hca_fini, IBT modify port caps"
5419684SSusan.Gleeson@Sun.COM " error (%d)", status);
5429684SSusan.Gleeson@Sun.COM
5439684SSusan.Gleeson@Sun.COM if (port->ip_ibmf_hdl == NULL)
5449684SSusan.Gleeson@Sun.COM continue;
5459684SSusan.Gleeson@Sun.COM
5469684SSusan.Gleeson@Sun.COM status = ibmf_tear_down_async_cb(port->ip_ibmf_hdl,
5479684SSusan.Gleeson@Sun.COM IBMF_QP_HANDLE_DEFAULT, 0);
5489684SSusan.Gleeson@Sun.COM if (status != IBMF_SUCCESS)
5499684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "hca_fini, IBMF tear down cb"
5509684SSusan.Gleeson@Sun.COM " error (%d)", status);
5519684SSusan.Gleeson@Sun.COM
5529684SSusan.Gleeson@Sun.COM status = ibmf_unregister(&port->ip_ibmf_hdl, 0);
5539684SSusan.Gleeson@Sun.COM if (status != IBMF_SUCCESS)
5549684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "hca_fini, IBMF un-register"
5559684SSusan.Gleeson@Sun.COM " error (%d)", status);
5569684SSusan.Gleeson@Sun.COM port->ip_ibmf_hdl = NULL;
5579684SSusan.Gleeson@Sun.COM }
5589684SSusan.Gleeson@Sun.COM
5599684SSusan.Gleeson@Sun.COM status = ibt_close_hca(hca->ih_ibt_hdl);
5609684SSusan.Gleeson@Sun.COM if (status != IBT_SUCCESS)
5619684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "hca_fini close error (%d)", status);
5629684SSusan.Gleeson@Sun.COM
5639684SSusan.Gleeson@Sun.COM rw_exit(&hca->ih_iou_rwlock);
5649684SSusan.Gleeson@Sun.COM rw_destroy(&hca->ih_iou_rwlock);
5659684SSusan.Gleeson@Sun.COM kmem_free(hca, sizeof (ibdma_hca_t) +
5669684SSusan.Gleeson@Sun.COM (hca->ih_nports-1) * sizeof (ibdma_port_t));
5679684SSusan.Gleeson@Sun.COM }
5689684SSusan.Gleeson@Sun.COM
5699684SSusan.Gleeson@Sun.COM /* DM IBMF MAD handlers */
5709684SSusan.Gleeson@Sun.COM /*
5719684SSusan.Gleeson@Sun.COM * ibdma_create_resp_mad()
5729684SSusan.Gleeson@Sun.COM */
5739684SSusan.Gleeson@Sun.COM static void
ibdma_create_resp_mad(ibmf_msg_t * msgp)5749684SSusan.Gleeson@Sun.COM ibdma_create_resp_mad(ibmf_msg_t *msgp)
5759684SSusan.Gleeson@Sun.COM {
5769684SSusan.Gleeson@Sun.COM /*
5779684SSusan.Gleeson@Sun.COM * Allocate send buffer fix up hdr for response.
5789684SSusan.Gleeson@Sun.COM */
5799684SSusan.Gleeson@Sun.COM msgp->im_msgbufs_send.im_bufs_mad_hdr =
5809684SSusan.Gleeson@Sun.COM kmem_zalloc(IBDMA_MAD_SIZE, KM_SLEEP);
5819684SSusan.Gleeson@Sun.COM
5829684SSusan.Gleeson@Sun.COM msgp->im_msgbufs_send.im_bufs_cl_hdr = (uchar_t *)
5839684SSusan.Gleeson@Sun.COM msgp->im_msgbufs_send.im_bufs_mad_hdr + sizeof (ib_mad_hdr_t);
5849684SSusan.Gleeson@Sun.COM msgp->im_msgbufs_send.im_bufs_cl_hdr_len = IBDMA_DM_MAD_HDR_SIZE;
5859684SSusan.Gleeson@Sun.COM msgp->im_msgbufs_send.im_bufs_cl_data =
5869684SSusan.Gleeson@Sun.COM ((char *)msgp->im_msgbufs_send.im_bufs_cl_hdr +
5879684SSusan.Gleeson@Sun.COM IBDMA_DM_MAD_HDR_SIZE);
5889684SSusan.Gleeson@Sun.COM msgp->im_msgbufs_send.im_bufs_cl_data_len =
5899684SSusan.Gleeson@Sun.COM IBDMA_MAD_SIZE - sizeof (ib_mad_hdr_t) - IBDMA_DM_MAD_HDR_SIZE;
5909684SSusan.Gleeson@Sun.COM (void) memcpy(msgp->im_msgbufs_send.im_bufs_mad_hdr,
5919684SSusan.Gleeson@Sun.COM msgp->im_msgbufs_recv.im_bufs_mad_hdr, IBDMA_MAD_SIZE);
5929684SSusan.Gleeson@Sun.COM
5939684SSusan.Gleeson@Sun.COM /*
5949684SSusan.Gleeson@Sun.COM * We may want to support a GRH since this is a GMP; not
5959684SSusan.Gleeson@Sun.COM * required for current SRP device manager platforms.
5969684SSusan.Gleeson@Sun.COM */
5979684SSusan.Gleeson@Sun.COM #if 0
5989684SSusan.Gleeson@Sun.COM if (msgp->im_msg_flags & IBMF_MSG_FLAGS_GLOBAL_ADDRESS) {
5999684SSusan.Gleeson@Sun.COM ib_gid_t temp = msgp->im_global_addr.ig_recver_gid;
6009684SSusan.Gleeson@Sun.COM
6019684SSusan.Gleeson@Sun.COM msgp->im_global_addr.ig_recver_gid =
6029684SSusan.Gleeson@Sun.COM msgp->im_global_addr.ig_sender_gid;
6039684SSusan.Gleeson@Sun.COM msgp->im_global_addr.ig_sender_gid = temp;
6049684SSusan.Gleeson@Sun.COM }
6059684SSusan.Gleeson@Sun.COM #endif
6069684SSusan.Gleeson@Sun.COM }
6079684SSusan.Gleeson@Sun.COM
6089684SSusan.Gleeson@Sun.COM /*
6099684SSusan.Gleeson@Sun.COM * ibdma_mad_send_cb()
6109684SSusan.Gleeson@Sun.COM */
6119684SSusan.Gleeson@Sun.COM /* ARGSUSED */
6129684SSusan.Gleeson@Sun.COM static void
ibdma_mad_send_cb(ibmf_handle_t ibmf_hdl,ibmf_msg_t * msgp,void * arg)6139684SSusan.Gleeson@Sun.COM ibdma_mad_send_cb(ibmf_handle_t ibmf_hdl, ibmf_msg_t *msgp, void *arg)
6149684SSusan.Gleeson@Sun.COM {
6159684SSusan.Gleeson@Sun.COM /*
6169684SSusan.Gleeson@Sun.COM * Just free the buffers and release the message.
6179684SSusan.Gleeson@Sun.COM */
6189684SSusan.Gleeson@Sun.COM if (msgp->im_msgbufs_send.im_bufs_mad_hdr != NULL) {
6199684SSusan.Gleeson@Sun.COM kmem_free(msgp->im_msgbufs_send.im_bufs_mad_hdr,
6209684SSusan.Gleeson@Sun.COM IBDMA_MAD_SIZE);
6219684SSusan.Gleeson@Sun.COM msgp->im_msgbufs_send.im_bufs_mad_hdr = NULL;
6229684SSusan.Gleeson@Sun.COM }
6239684SSusan.Gleeson@Sun.COM if (ibmf_free_msg(ibmf_hdl, &msgp) != IBMF_SUCCESS) {
6249684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "mad_send_cb, IBMF message free error");
6259684SSusan.Gleeson@Sun.COM }
6269684SSusan.Gleeson@Sun.COM }
6279684SSusan.Gleeson@Sun.COM
6289684SSusan.Gleeson@Sun.COM /*
6299684SSusan.Gleeson@Sun.COM * ibdma_mad_recv_cb()
6309684SSusan.Gleeson@Sun.COM */
6319684SSusan.Gleeson@Sun.COM static void
ibdma_mad_recv_cb(ibmf_handle_t ibmf_hdl,ibmf_msg_t * msgp,void * args)6329684SSusan.Gleeson@Sun.COM ibdma_mad_recv_cb(ibmf_handle_t ibmf_hdl, ibmf_msg_t *msgp, void *args)
6339684SSusan.Gleeson@Sun.COM {
6349684SSusan.Gleeson@Sun.COM int status;
6359684SSusan.Gleeson@Sun.COM ib_mad_hdr_t *in_mad;
6369684SSusan.Gleeson@Sun.COM ib_mad_hdr_t *out_mad;
6379684SSusan.Gleeson@Sun.COM ibdma_port_t *port = args;
6389684SSusan.Gleeson@Sun.COM
6399684SSusan.Gleeson@Sun.COM ASSERT(msgp != NULL);
6409684SSusan.Gleeson@Sun.COM ASSERT(port != NULL);
6419684SSusan.Gleeson@Sun.COM
6429684SSusan.Gleeson@Sun.COM if (msgp->im_msg_status != IBMF_SUCCESS) {
6439684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "mad_recv_cb, bad MAD receive status (%d)",
6449684SSusan.Gleeson@Sun.COM msgp->im_msg_status);
6459684SSusan.Gleeson@Sun.COM goto drop;
6469684SSusan.Gleeson@Sun.COM }
6479684SSusan.Gleeson@Sun.COM
6489684SSusan.Gleeson@Sun.COM in_mad = msgp->im_msgbufs_recv.im_bufs_mad_hdr;
6499684SSusan.Gleeson@Sun.COM
6509684SSusan.Gleeson@Sun.COM if (in_mad->MgmtClass != MAD_MGMT_CLASS_DEV_MGT) {
6519684SSusan.Gleeson@Sun.COM #ifdef DEBUG_IBDMA
6529684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "mad_recv_cb, MAD not of Dev Mgmt Class");
6539684SSusan.Gleeson@Sun.COM #endif
6549684SSusan.Gleeson@Sun.COM goto drop;
6559684SSusan.Gleeson@Sun.COM }
6569684SSusan.Gleeson@Sun.COM
6579684SSusan.Gleeson@Sun.COM ibdma_create_resp_mad(msgp);
6589684SSusan.Gleeson@Sun.COM out_mad = msgp->im_msgbufs_send.im_bufs_mad_hdr;
6599684SSusan.Gleeson@Sun.COM
6609684SSusan.Gleeson@Sun.COM out_mad->R_Method = IB_DM_DEVMGT_METHOD_GET_RESP;
6619684SSusan.Gleeson@Sun.COM out_mad->Status = 0;
6629684SSusan.Gleeson@Sun.COM
6639684SSusan.Gleeson@Sun.COM if (in_mad->R_Method == MAD_METHOD_SET) {
6649684SSusan.Gleeson@Sun.COM #ifdef DEBUG_IBDMA
6659684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "mad_recv_cb, no attributes supported"
6669684SSusan.Gleeson@Sun.COM " for set");
6679684SSusan.Gleeson@Sun.COM #endif
6689684SSusan.Gleeson@Sun.COM out_mad->Status = MAD_STATUS_UNSUPP_METHOD_ATTR;
6699684SSusan.Gleeson@Sun.COM goto send_resp;
6709684SSusan.Gleeson@Sun.COM }
6719684SSusan.Gleeson@Sun.COM
6729684SSusan.Gleeson@Sun.COM if (in_mad->R_Method != MAD_METHOD_GET) {
6739684SSusan.Gleeson@Sun.COM #ifdef DEBUG_IBDMA
6749684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "mad_recv_cb, no attributes supported"
6759684SSusan.Gleeson@Sun.COM " for set");
6769684SSusan.Gleeson@Sun.COM #endif
6779684SSusan.Gleeson@Sun.COM out_mad->Status = MAD_STATUS_UNSUPP_METHOD;
6789684SSusan.Gleeson@Sun.COM goto send_resp;
6799684SSusan.Gleeson@Sun.COM }
6809684SSusan.Gleeson@Sun.COM
6819684SSusan.Gleeson@Sun.COM /*
6829684SSusan.Gleeson@Sun.COM * Process a GET method.
6839684SSusan.Gleeson@Sun.COM */
6849684SSusan.Gleeson@Sun.COM switch (b2h16(in_mad->AttributeID)) {
6859684SSusan.Gleeson@Sun.COM
6869684SSusan.Gleeson@Sun.COM case IB_DM_ATTR_CLASSPORTINFO:
6879684SSusan.Gleeson@Sun.COM ibdma_get_class_portinfo(msgp);
6889684SSusan.Gleeson@Sun.COM break;
6899684SSusan.Gleeson@Sun.COM
6909684SSusan.Gleeson@Sun.COM case IB_DM_ATTR_IO_UNITINFO:
6919684SSusan.Gleeson@Sun.COM ibdma_get_io_unitinfo(port->ip_hcap, msgp);
6929684SSusan.Gleeson@Sun.COM break;
6939684SSusan.Gleeson@Sun.COM
6949684SSusan.Gleeson@Sun.COM case IB_DM_ATTR_IOC_CTRL_PROFILE:
6959684SSusan.Gleeson@Sun.COM ibdma_get_ioc_profile(port->ip_hcap, msgp);
6969684SSusan.Gleeson@Sun.COM break;
6979684SSusan.Gleeson@Sun.COM
6989684SSusan.Gleeson@Sun.COM case IB_DM_ATTR_SERVICE_ENTRIES:
6999684SSusan.Gleeson@Sun.COM ibdma_get_ioc_services(port->ip_hcap, msgp);
7009684SSusan.Gleeson@Sun.COM break;
7019684SSusan.Gleeson@Sun.COM
7029684SSusan.Gleeson@Sun.COM default:
7039684SSusan.Gleeson@Sun.COM out_mad->Status = MAD_STATUS_UNSUPP_METHOD_ATTR;
7049684SSusan.Gleeson@Sun.COM break;
7059684SSusan.Gleeson@Sun.COM }
7069684SSusan.Gleeson@Sun.COM
7079684SSusan.Gleeson@Sun.COM send_resp:
7089684SSusan.Gleeson@Sun.COM status = ibmf_msg_transport(ibmf_hdl, IBMF_QP_HANDLE_DEFAULT,
7099684SSusan.Gleeson@Sun.COM msgp, NULL, ibdma_mad_send_cb, NULL, 0);
7109684SSusan.Gleeson@Sun.COM if (status != IBMF_SUCCESS) {
7119684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "mad_recv_cb, send error (%d)", status);
7129684SSusan.Gleeson@Sun.COM ibdma_mad_send_cb(ibmf_hdl, msgp, NULL);
7139684SSusan.Gleeson@Sun.COM }
7149684SSusan.Gleeson@Sun.COM return;
7159684SSusan.Gleeson@Sun.COM
7169684SSusan.Gleeson@Sun.COM drop:
7179684SSusan.Gleeson@Sun.COM status = ibmf_free_msg(ibmf_hdl, &msgp);
7189684SSusan.Gleeson@Sun.COM if (status != IBMF_SUCCESS) {
7199684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "mad_recv_cb, error dropping (%d)",
7209684SSusan.Gleeson@Sun.COM status);
7219684SSusan.Gleeson@Sun.COM }
7229684SSusan.Gleeson@Sun.COM }
7239684SSusan.Gleeson@Sun.COM
7249684SSusan.Gleeson@Sun.COM /*
7259684SSusan.Gleeson@Sun.COM * ibdma_get_class_portinfo()
7269684SSusan.Gleeson@Sun.COM */
7279684SSusan.Gleeson@Sun.COM static void
ibdma_get_class_portinfo(ibmf_msg_t * msg)7289684SSusan.Gleeson@Sun.COM ibdma_get_class_portinfo(ibmf_msg_t *msg)
7299684SSusan.Gleeson@Sun.COM {
7309684SSusan.Gleeson@Sun.COM ib_mad_classportinfo_t *cpip;
7319684SSusan.Gleeson@Sun.COM
7329684SSusan.Gleeson@Sun.COM cpip = (ib_mad_classportinfo_t *)msg->im_msgbufs_send.im_bufs_cl_data;
7339684SSusan.Gleeson@Sun.COM bzero(cpip, sizeof (*cpip));
7349684SSusan.Gleeson@Sun.COM cpip->BaseVersion = MAD_CLASS_BASE_VERS_1;
7359684SSusan.Gleeson@Sun.COM cpip->ClassVersion = IB_DM_CLASS_VERSION_1;
7369684SSusan.Gleeson@Sun.COM cpip->RespTimeValue = h2b32(IBDMA_DM_RESP_TIME);
7379684SSusan.Gleeson@Sun.COM }
7389684SSusan.Gleeson@Sun.COM
7399684SSusan.Gleeson@Sun.COM /*
7409684SSusan.Gleeson@Sun.COM * ibdma_get_io_unitinfo()
7419684SSusan.Gleeson@Sun.COM */
7429684SSusan.Gleeson@Sun.COM static void
ibdma_get_io_unitinfo(ibdma_hca_t * hca,ibmf_msg_t * msg)7439684SSusan.Gleeson@Sun.COM ibdma_get_io_unitinfo(ibdma_hca_t *hca, ibmf_msg_t *msg)
7449684SSusan.Gleeson@Sun.COM {
7459684SSusan.Gleeson@Sun.COM ib_dm_io_unitinfo_t *uip;
7469684SSusan.Gleeson@Sun.COM
7479684SSusan.Gleeson@Sun.COM uip = (ib_dm_io_unitinfo_t *)msg->im_msgbufs_send.im_bufs_cl_data;
7489684SSusan.Gleeson@Sun.COM rw_enter(&hca->ih_iou_rwlock, RW_READER);
7499684SSusan.Gleeson@Sun.COM bcopy(&hca->ih_iou, uip, sizeof (ib_dm_io_unitinfo_t));
7509684SSusan.Gleeson@Sun.COM rw_exit(&hca->ih_iou_rwlock);
7519684SSusan.Gleeson@Sun.COM }
7529684SSusan.Gleeson@Sun.COM
7539684SSusan.Gleeson@Sun.COM /*
7549684SSusan.Gleeson@Sun.COM * ibdma_get_ioc_profile()
7559684SSusan.Gleeson@Sun.COM */
7569684SSusan.Gleeson@Sun.COM static void
ibdma_get_ioc_profile(ibdma_hca_t * hca,ibmf_msg_t * msg)7579684SSusan.Gleeson@Sun.COM ibdma_get_ioc_profile(ibdma_hca_t *hca, ibmf_msg_t *msg)
7589684SSusan.Gleeson@Sun.COM {
7599684SSusan.Gleeson@Sun.COM ib_dm_ioc_ctrl_profile_t *iocp;
7609684SSusan.Gleeson@Sun.COM uint32_t slot;
7619684SSusan.Gleeson@Sun.COM
7629684SSusan.Gleeson@Sun.COM ASSERT(msg != NULL);
7639684SSusan.Gleeson@Sun.COM
7649684SSusan.Gleeson@Sun.COM slot = b2h32(msg->im_msgbufs_recv.im_bufs_mad_hdr->AttributeModifier);
7659684SSusan.Gleeson@Sun.COM iocp = (ib_dm_ioc_ctrl_profile_t *)
7669684SSusan.Gleeson@Sun.COM msg->im_msgbufs_send.im_bufs_cl_data;
7679684SSusan.Gleeson@Sun.COM if (slot == 0 || slot > IBDMA_MAX_IOC) {
7689684SSusan.Gleeson@Sun.COM msg->im_msgbufs_send.im_bufs_mad_hdr->Status =
7699684SSusan.Gleeson@Sun.COM MAD_STATUS_INVALID_FIELD;
7709684SSusan.Gleeson@Sun.COM return;
7719684SSusan.Gleeson@Sun.COM }
7729684SSusan.Gleeson@Sun.COM
7739684SSusan.Gleeson@Sun.COM slot--;
7749684SSusan.Gleeson@Sun.COM rw_enter(&hca->ih_iou_rwlock, RW_READER);
7759684SSusan.Gleeson@Sun.COM if (ibdma_get_ioc_state(hca, slot) == IBDMA_IOC_PRESENT) {
7769684SSusan.Gleeson@Sun.COM bcopy(&hca->ih_ioc[slot].ii_profile, iocp,
7779684SSusan.Gleeson@Sun.COM sizeof (ib_dm_ioc_ctrl_profile_t));
7789684SSusan.Gleeson@Sun.COM } else {
7799684SSusan.Gleeson@Sun.COM msg->im_msgbufs_send.im_bufs_mad_hdr->Status =
7809684SSusan.Gleeson@Sun.COM IB_DM_DEVMGT_MAD_STAT_NORESP;
7819684SSusan.Gleeson@Sun.COM }
7829684SSusan.Gleeson@Sun.COM rw_exit(&hca->ih_iou_rwlock);
7839684SSusan.Gleeson@Sun.COM }
7849684SSusan.Gleeson@Sun.COM
7859684SSusan.Gleeson@Sun.COM /*
7869684SSusan.Gleeson@Sun.COM * ibdma_get_ioc_services()
7879684SSusan.Gleeson@Sun.COM */
7889684SSusan.Gleeson@Sun.COM static void
ibdma_get_ioc_services(ibdma_hca_t * hca,ibmf_msg_t * msg)7899684SSusan.Gleeson@Sun.COM ibdma_get_ioc_services(ibdma_hca_t *hca, ibmf_msg_t *msg)
7909684SSusan.Gleeson@Sun.COM {
7919684SSusan.Gleeson@Sun.COM ib_dm_srv_t *to_svcp;
7929684SSusan.Gleeson@Sun.COM ib_dm_srv_t *from_svcp;
7939684SSusan.Gleeson@Sun.COM uint32_t slot;
7949684SSusan.Gleeson@Sun.COM uint8_t hi;
7959684SSusan.Gleeson@Sun.COM uint8_t low;
7969684SSusan.Gleeson@Sun.COM
7979684SSusan.Gleeson@Sun.COM ASSERT(msg != NULL);
7989684SSusan.Gleeson@Sun.COM
7999684SSusan.Gleeson@Sun.COM slot = b2h32(msg->im_msgbufs_recv.im_bufs_mad_hdr->AttributeModifier);
8009684SSusan.Gleeson@Sun.COM hi = (slot >> 8) & 0x00FF;
8019684SSusan.Gleeson@Sun.COM low = slot & 0x00FF;
8029684SSusan.Gleeson@Sun.COM slot = (slot >> 16) & 0x0FFFF;
8039684SSusan.Gleeson@Sun.COM if (slot == 0 || slot > IBDMA_MAX_IOC) {
8049684SSusan.Gleeson@Sun.COM msg->im_msgbufs_send.im_bufs_mad_hdr->Status =
8059684SSusan.Gleeson@Sun.COM MAD_STATUS_INVALID_FIELD;
8069684SSusan.Gleeson@Sun.COM return;
8079684SSusan.Gleeson@Sun.COM }
8089684SSusan.Gleeson@Sun.COM
8099684SSusan.Gleeson@Sun.COM slot--;
8109684SSusan.Gleeson@Sun.COM
8119684SSusan.Gleeson@Sun.COM rw_enter(&hca->ih_iou_rwlock, RW_READER);
8129684SSusan.Gleeson@Sun.COM if (ibdma_get_ioc_state(hca, slot) != IBDMA_IOC_PRESENT) {
8139684SSusan.Gleeson@Sun.COM msg->im_msgbufs_send.im_bufs_mad_hdr->Status =
8149684SSusan.Gleeson@Sun.COM IB_DM_DEVMGT_MAD_STAT_NORESP;
8159684SSusan.Gleeson@Sun.COM rw_exit(&hca->ih_iou_rwlock);
8169684SSusan.Gleeson@Sun.COM return;
8179684SSusan.Gleeson@Sun.COM }
8189684SSusan.Gleeson@Sun.COM
8199684SSusan.Gleeson@Sun.COM if ((low > hi) || (hi - low > 4)) {
8209684SSusan.Gleeson@Sun.COM msg->im_msgbufs_send.im_bufs_mad_hdr->Status =
8219684SSusan.Gleeson@Sun.COM MAD_STATUS_INVALID_FIELD;
8229684SSusan.Gleeson@Sun.COM rw_exit(&hca->ih_iou_rwlock);
8239684SSusan.Gleeson@Sun.COM return;
8249684SSusan.Gleeson@Sun.COM }
8259684SSusan.Gleeson@Sun.COM
8269684SSusan.Gleeson@Sun.COM if (hi > hca->ih_ioc[slot].ii_profile.ioc_service_entries) {
8279684SSusan.Gleeson@Sun.COM msg->im_msgbufs_send.im_bufs_mad_hdr->Status =
8289684SSusan.Gleeson@Sun.COM MAD_STATUS_INVALID_FIELD;
8299684SSusan.Gleeson@Sun.COM rw_exit(&hca->ih_iou_rwlock);
8309684SSusan.Gleeson@Sun.COM return;
8319684SSusan.Gleeson@Sun.COM }
8329684SSusan.Gleeson@Sun.COM
8339684SSusan.Gleeson@Sun.COM to_svcp = (ib_dm_srv_t *)msg->im_msgbufs_send.im_bufs_cl_data;
8349684SSusan.Gleeson@Sun.COM from_svcp = hca->ih_ioc[slot].ii_srvcs + low;
8359684SSusan.Gleeson@Sun.COM bcopy(from_svcp, to_svcp, sizeof (ib_dm_srv_t) * (hi - low + 1));
8369684SSusan.Gleeson@Sun.COM rw_exit(&hca->ih_iou_rwlock);
8379684SSusan.Gleeson@Sun.COM }
8389684SSusan.Gleeson@Sun.COM
8399684SSusan.Gleeson@Sun.COM
8409684SSusan.Gleeson@Sun.COM /*
8419684SSusan.Gleeson@Sun.COM * Client API internal helpers
8429684SSusan.Gleeson@Sun.COM */
8439684SSusan.Gleeson@Sun.COM
8449684SSusan.Gleeson@Sun.COM /*
8459684SSusan.Gleeson@Sun.COM * ibdma_hdl_to_ioc()
8469684SSusan.Gleeson@Sun.COM */
8479684SSusan.Gleeson@Sun.COM ibdma_hdl_impl_t *
ibdma_get_hdl_impl(ibdma_hdl_t hdl)8489684SSusan.Gleeson@Sun.COM ibdma_get_hdl_impl(ibdma_hdl_t hdl)
8499684SSusan.Gleeson@Sun.COM {
8509684SSusan.Gleeson@Sun.COM ibdma_hca_t *hca;
8519684SSusan.Gleeson@Sun.COM ibdma_hdl_impl_t *hdl_tmp = hdl;
8529684SSusan.Gleeson@Sun.COM ibdma_hdl_impl_t *hdl_impl;
8539684SSusan.Gleeson@Sun.COM
8549684SSusan.Gleeson@Sun.COM ASSERT(mutex_owned(&ibdma->ms_hca_list_lock));
8559684SSusan.Gleeson@Sun.COM
8569684SSusan.Gleeson@Sun.COM if (hdl_tmp == NULL) {
8579684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "get_hdl_impl, NULL handle");
8589684SSusan.Gleeson@Sun.COM return (NULL);
8599684SSusan.Gleeson@Sun.COM }
8609684SSusan.Gleeson@Sun.COM
8619684SSusan.Gleeson@Sun.COM hca = ibdma_find_hca(hdl_tmp->ih_iou_guid);
8629684SSusan.Gleeson@Sun.COM if (hca == NULL) {
8639684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "get_hdl_impl, invalid handle, bad IOU");
8649684SSusan.Gleeson@Sun.COM return (NULL);
8659684SSusan.Gleeson@Sun.COM }
8669684SSusan.Gleeson@Sun.COM
8679684SSusan.Gleeson@Sun.COM hdl_impl = list_head(&hca->ih_hdl_list);
8689684SSusan.Gleeson@Sun.COM while (hdl_impl != NULL) {
8699684SSusan.Gleeson@Sun.COM if (hdl_impl == hdl_tmp) {
8709684SSusan.Gleeson@Sun.COM break;
8719684SSusan.Gleeson@Sun.COM }
8729684SSusan.Gleeson@Sun.COM hdl_impl = list_next(&hca->ih_hdl_list, hdl_impl);
8739684SSusan.Gleeson@Sun.COM }
8749684SSusan.Gleeson@Sun.COM return (hdl_impl);
8759684SSusan.Gleeson@Sun.COM }
8769684SSusan.Gleeson@Sun.COM
8779684SSusan.Gleeson@Sun.COM /*
8789684SSusan.Gleeson@Sun.COM * ibdma_set_ioc_state()
8799684SSusan.Gleeson@Sun.COM *
8809684SSusan.Gleeson@Sun.COM * slot should be 0 based (not DM 1 based slot).
8819684SSusan.Gleeson@Sun.COM *
8829684SSusan.Gleeson@Sun.COM * I/O Unit write lock should be held outside of this function.
8839684SSusan.Gleeson@Sun.COM */
8849684SSusan.Gleeson@Sun.COM static void
ibdma_set_ioc_state(ibdma_hca_t * hca,int slot,ibdma_ioc_state_t state)8859684SSusan.Gleeson@Sun.COM ibdma_set_ioc_state(ibdma_hca_t *hca, int slot, ibdma_ioc_state_t state)
8869684SSusan.Gleeson@Sun.COM {
8879684SSusan.Gleeson@Sun.COM uint8_t cur;
8889684SSusan.Gleeson@Sun.COM uint16_t id;
8899684SSusan.Gleeson@Sun.COM
8909684SSusan.Gleeson@Sun.COM cur = hca->ih_iou.iou_ctrl_list[slot >> 1];
8919684SSusan.Gleeson@Sun.COM if (slot & 1) {
8929684SSusan.Gleeson@Sun.COM cur = (cur & 0xF0) | state;
8939684SSusan.Gleeson@Sun.COM } else {
8949684SSusan.Gleeson@Sun.COM cur = (cur & 0x0F) | (state << 4);
8959684SSusan.Gleeson@Sun.COM }
8969684SSusan.Gleeson@Sun.COM hca->ih_iou.iou_ctrl_list[slot >> 1] = cur;
8979684SSusan.Gleeson@Sun.COM id = b2h16(hca->ih_iou.iou_changeid);
8989684SSusan.Gleeson@Sun.COM id++;
8999684SSusan.Gleeson@Sun.COM hca->ih_iou.iou_changeid = h2b16(id);
9009684SSusan.Gleeson@Sun.COM #ifdef DEBUG_IBDMA
9019684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "set_ioc_state, slot offset(%d), value(%d)",
9029684SSusan.Gleeson@Sun.COM slot, hca->ih_iou.iou_ctrl_list[slot >> 1]);
9039684SSusan.Gleeson@Sun.COM #endif
9049684SSusan.Gleeson@Sun.COM }
9059684SSusan.Gleeson@Sun.COM
9069684SSusan.Gleeson@Sun.COM /*
9079684SSusan.Gleeson@Sun.COM * ibdma_get_ioc_state()
9089684SSusan.Gleeson@Sun.COM *
9099684SSusan.Gleeson@Sun.COM * slot should be 0 based (not DM 1 based slot).
9109684SSusan.Gleeson@Sun.COM *
9119684SSusan.Gleeson@Sun.COM * I/O Unit read lock should be held outside of this function.
9129684SSusan.Gleeson@Sun.COM */
9139684SSusan.Gleeson@Sun.COM static ibdma_ioc_state_t
ibdma_get_ioc_state(ibdma_hca_t * hca,int slot)9149684SSusan.Gleeson@Sun.COM ibdma_get_ioc_state(ibdma_hca_t *hca, int slot)
9159684SSusan.Gleeson@Sun.COM {
9169684SSusan.Gleeson@Sun.COM uint8_t cur;
9179684SSusan.Gleeson@Sun.COM
9189684SSusan.Gleeson@Sun.COM if (slot >= IBDMA_MAX_IOC)
9199684SSusan.Gleeson@Sun.COM return (0xFF);
9209684SSusan.Gleeson@Sun.COM
9219684SSusan.Gleeson@Sun.COM cur = hca->ih_iou.iou_ctrl_list[slot >> 1];
9229684SSusan.Gleeson@Sun.COM cur = slot & 1 ? cur & 0x0F : cur >> 4;
9239684SSusan.Gleeson@Sun.COM return (cur);
9249684SSusan.Gleeson@Sun.COM }
9259684SSusan.Gleeson@Sun.COM
9269684SSusan.Gleeson@Sun.COM /* CLIENT API Implementation */
9279684SSusan.Gleeson@Sun.COM /*
9289684SSusan.Gleeson@Sun.COM * ibdma_ioc_register()
9299684SSusan.Gleeson@Sun.COM *
9309684SSusan.Gleeson@Sun.COM */
9319684SSusan.Gleeson@Sun.COM ibdma_hdl_t
ibdma_ioc_register(ib_guid_t iou_guid,ib_dm_ioc_ctrl_profile_t * profile,ib_dm_srv_t * services)9329684SSusan.Gleeson@Sun.COM ibdma_ioc_register(ib_guid_t iou_guid, ib_dm_ioc_ctrl_profile_t *profile,
9339684SSusan.Gleeson@Sun.COM ib_dm_srv_t *services)
9349684SSusan.Gleeson@Sun.COM {
9359684SSusan.Gleeson@Sun.COM int free_slot = -1;
9369684SSusan.Gleeson@Sun.COM int svc_entries;
9379684SSusan.Gleeson@Sun.COM int slot;
9389684SSusan.Gleeson@Sun.COM ibdma_hca_t *hca;
9399684SSusan.Gleeson@Sun.COM ibdma_hdl_impl_t *hdl;
9409684SSusan.Gleeson@Sun.COM
9419684SSusan.Gleeson@Sun.COM if (profile == NULL || services == NULL) {
9429684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "ioc_register, bad parameter");
9439684SSusan.Gleeson@Sun.COM return (NULL);
9449684SSusan.Gleeson@Sun.COM }
9459684SSusan.Gleeson@Sun.COM
9469684SSusan.Gleeson@Sun.COM svc_entries = profile->ioc_service_entries;
9479684SSusan.Gleeson@Sun.COM if (svc_entries == 0) {
9489684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "ioc_register, bad profile no service");
9499684SSusan.Gleeson@Sun.COM return (NULL);
9509684SSusan.Gleeson@Sun.COM }
9519684SSusan.Gleeson@Sun.COM
9529684SSusan.Gleeson@Sun.COM /*
9539684SSusan.Gleeson@Sun.COM * Find the associated I/O Unit.
9549684SSusan.Gleeson@Sun.COM */
9559684SSusan.Gleeson@Sun.COM mutex_enter(&ibdma->ms_hca_list_lock);
9569684SSusan.Gleeson@Sun.COM hca = ibdma_find_hca(iou_guid);
9579684SSusan.Gleeson@Sun.COM if (hca == NULL) {
9589684SSusan.Gleeson@Sun.COM mutex_exit(&ibdma->ms_hca_list_lock);
9599684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "ioc_register, bad I/O Unit GUID (0x%llx)",
9609684SSusan.Gleeson@Sun.COM (u_longlong_t)iou_guid);
9619684SSusan.Gleeson@Sun.COM return (NULL);
9629684SSusan.Gleeson@Sun.COM }
9639684SSusan.Gleeson@Sun.COM
9649684SSusan.Gleeson@Sun.COM rw_enter(&hca->ih_iou_rwlock, RW_WRITER);
9659684SSusan.Gleeson@Sun.COM for (slot = 0; slot < IBDMA_MAX_IOC; slot++) {
9669684SSusan.Gleeson@Sun.COM if (hca->ih_ioc[slot].ii_inuse == 0) {
9679684SSusan.Gleeson@Sun.COM if (free_slot == -1) {
9689684SSusan.Gleeson@Sun.COM free_slot = slot;
9699684SSusan.Gleeson@Sun.COM }
9709684SSusan.Gleeson@Sun.COM continue;
9719684SSusan.Gleeson@Sun.COM }
9729684SSusan.Gleeson@Sun.COM
9739684SSusan.Gleeson@Sun.COM if (profile->ioc_guid ==
9749684SSusan.Gleeson@Sun.COM hca->ih_ioc[slot].ii_profile.ioc_guid) {
9759684SSusan.Gleeson@Sun.COM rw_exit(&hca->ih_iou_rwlock);
9769684SSusan.Gleeson@Sun.COM mutex_exit(&ibdma->ms_hca_list_lock);
9779684SSusan.Gleeson@Sun.COM #ifdef DEBUG_IBDMA
9789684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "ioc_register, IOC previously"
9799684SSusan.Gleeson@Sun.COM " registered");
9809684SSusan.Gleeson@Sun.COM #endif
9819684SSusan.Gleeson@Sun.COM return (NULL);
9829684SSusan.Gleeson@Sun.COM }
9839684SSusan.Gleeson@Sun.COM }
9849684SSusan.Gleeson@Sun.COM
9859684SSusan.Gleeson@Sun.COM if (free_slot < 0) {
9869684SSusan.Gleeson@Sun.COM rw_exit(&hca->ih_iou_rwlock);
9879684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "ioc_register, error - I/O Unit full");
9889684SSusan.Gleeson@Sun.COM return (NULL);
9899684SSusan.Gleeson@Sun.COM }
9909684SSusan.Gleeson@Sun.COM #ifdef DEBUG_IBDMA
9919684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "ibdma_ioc_register, assigned to 0 based slot (%d)",
9929684SSusan.Gleeson@Sun.COM free_slot);
9939684SSusan.Gleeson@Sun.COM #endif
9949684SSusan.Gleeson@Sun.COM
9959684SSusan.Gleeson@Sun.COM hca->ih_ioc[free_slot].ii_inuse = 1;
9969684SSusan.Gleeson@Sun.COM hca->ih_ioc[free_slot].ii_slot = free_slot;
9979684SSusan.Gleeson@Sun.COM hca->ih_ioc[free_slot].ii_hcap = hca;
9989684SSusan.Gleeson@Sun.COM
9999684SSusan.Gleeson@Sun.COM /*
10009684SSusan.Gleeson@Sun.COM * Allocate local copy of profile and services.
10019684SSusan.Gleeson@Sun.COM */
10029684SSusan.Gleeson@Sun.COM hca->ih_ioc[free_slot].ii_srvcs =
10039684SSusan.Gleeson@Sun.COM kmem_zalloc(sizeof (ib_dm_srv_t) * svc_entries, KM_SLEEP);
10049684SSusan.Gleeson@Sun.COM bcopy(profile, &hca->ih_ioc[free_slot].ii_profile,
10059684SSusan.Gleeson@Sun.COM sizeof (ib_dm_ioc_ctrl_profile_t));
10069684SSusan.Gleeson@Sun.COM bcopy(services, hca->ih_ioc[free_slot].ii_srvcs,
10079684SSusan.Gleeson@Sun.COM sizeof (ib_dm_srv_t) * svc_entries);
10089684SSusan.Gleeson@Sun.COM
10099684SSusan.Gleeson@Sun.COM /*
10109684SSusan.Gleeson@Sun.COM * Update the profile copy with the I/O controller slot assigned.
10119684SSusan.Gleeson@Sun.COM * The slot occupies the lower 8 biths of the vendor ID/slot 32bit
10129684SSusan.Gleeson@Sun.COM * field.
10139684SSusan.Gleeson@Sun.COM */
10149684SSusan.Gleeson@Sun.COM profile->ioc_vendorid |= h2b32(free_slot);
10159684SSusan.Gleeson@Sun.COM
10169684SSusan.Gleeson@Sun.COM ibdma_set_ioc_state(hca, free_slot, IBDMA_IOC_PRESENT);
10179684SSusan.Gleeson@Sun.COM
10189684SSusan.Gleeson@Sun.COM hdl = kmem_alloc(sizeof (*hdl), KM_SLEEP);
10199684SSusan.Gleeson@Sun.COM hdl->ih_iou_guid = hca->ih_iou_guid;
10209684SSusan.Gleeson@Sun.COM hdl->ih_ioc_ndx = (uint8_t)free_slot;
10219684SSusan.Gleeson@Sun.COM list_insert_tail(&hca->ih_hdl_list, hdl);
10229684SSusan.Gleeson@Sun.COM
10239684SSusan.Gleeson@Sun.COM rw_exit(&hca->ih_iou_rwlock);
10249684SSusan.Gleeson@Sun.COM mutex_exit(&ibdma->ms_hca_list_lock);
10259684SSusan.Gleeson@Sun.COM
10269684SSusan.Gleeson@Sun.COM return ((ibdma_hdl_t)hdl);
10279684SSusan.Gleeson@Sun.COM }
10289684SSusan.Gleeson@Sun.COM
10299684SSusan.Gleeson@Sun.COM /*
10309684SSusan.Gleeson@Sun.COM * ibdma_ioc_unregister()
10319684SSusan.Gleeson@Sun.COM *
10329684SSusan.Gleeson@Sun.COM */
10339684SSusan.Gleeson@Sun.COM ibdma_status_t
ibdma_ioc_unregister(ibdma_hdl_t hdl)10349684SSusan.Gleeson@Sun.COM ibdma_ioc_unregister(ibdma_hdl_t hdl)
10359684SSusan.Gleeson@Sun.COM {
10369684SSusan.Gleeson@Sun.COM ibdma_ioc_t *ioc;
10379684SSusan.Gleeson@Sun.COM ibdma_hca_t *hca;
10389684SSusan.Gleeson@Sun.COM int slot;
10399684SSusan.Gleeson@Sun.COM ibdma_hdl_impl_t *hdl_tmp = hdl;
10409684SSusan.Gleeson@Sun.COM ibdma_hdl_impl_t *hdl_impl;
10419684SSusan.Gleeson@Sun.COM
10429684SSusan.Gleeson@Sun.COM if (hdl == NULL) {
10439684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "ioc_unregister, NULL handle");
10449684SSusan.Gleeson@Sun.COM return (IBDMA_BAD_PARAM);
10459684SSusan.Gleeson@Sun.COM }
10469684SSusan.Gleeson@Sun.COM
10479684SSusan.Gleeson@Sun.COM mutex_enter(&ibdma->ms_hca_list_lock);
10489684SSusan.Gleeson@Sun.COM hca = ibdma_find_hca(hdl_tmp->ih_iou_guid);
10499684SSusan.Gleeson@Sun.COM if (hca == NULL) {
10509684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "ioc_unregsiter, invalid handle, IOU"
10519684SSusan.Gleeson@Sun.COM " not found");
10529684SSusan.Gleeson@Sun.COM mutex_exit(&ibdma->ms_hca_list_lock);
10539684SSusan.Gleeson@Sun.COM return (IBDMA_BAD_PARAM);
10549684SSusan.Gleeson@Sun.COM }
10559684SSusan.Gleeson@Sun.COM
10569684SSusan.Gleeson@Sun.COM hdl_impl = list_head(&hca->ih_hdl_list);
10579684SSusan.Gleeson@Sun.COM while (hdl_impl != NULL) {
10589684SSusan.Gleeson@Sun.COM if (hdl_impl == hdl_tmp) {
10599684SSusan.Gleeson@Sun.COM break;
10609684SSusan.Gleeson@Sun.COM }
10619684SSusan.Gleeson@Sun.COM hdl_impl = list_next(&hca->ih_hdl_list, hdl_impl);
10629684SSusan.Gleeson@Sun.COM }
10639684SSusan.Gleeson@Sun.COM
10649684SSusan.Gleeson@Sun.COM if (hdl_impl == NULL) {
10659684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "ioc_unregsiter, invalid handle, not found");
10669684SSusan.Gleeson@Sun.COM mutex_exit(&ibdma->ms_hca_list_lock);
10679684SSusan.Gleeson@Sun.COM return (IBDMA_BAD_PARAM);
10689684SSusan.Gleeson@Sun.COM }
10699684SSusan.Gleeson@Sun.COM
10709684SSusan.Gleeson@Sun.COM list_remove(&hca->ih_hdl_list, hdl_impl);
10719684SSusan.Gleeson@Sun.COM
10729684SSusan.Gleeson@Sun.COM if (hdl_impl->ih_ioc_ndx >= IBDMA_MAX_IOC) {
10739684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "ioc_unregister, corrupted handle");
10749684SSusan.Gleeson@Sun.COM kmem_free(hdl_impl, sizeof (*hdl_impl));
10759684SSusan.Gleeson@Sun.COM mutex_exit(&ibdma->ms_hca_list_lock);
10769684SSusan.Gleeson@Sun.COM return (IBDMA_BAD_PARAM);
10779684SSusan.Gleeson@Sun.COM }
10789684SSusan.Gleeson@Sun.COM ioc = &hca->ih_ioc[hdl_impl->ih_ioc_ndx];
10799684SSusan.Gleeson@Sun.COM kmem_free(hdl_impl, sizeof (*hdl_impl));
10809684SSusan.Gleeson@Sun.COM
10819684SSusan.Gleeson@Sun.COM if (ioc->ii_slot > IBDMA_MAX_IOC) {
10829684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "ioc_unregister, IOC corrupted, bad"
10839684SSusan.Gleeson@Sun.COM " slot in IOC");
10849684SSusan.Gleeson@Sun.COM mutex_exit(&ibdma->ms_hca_list_lock);
10859684SSusan.Gleeson@Sun.COM return (IBDMA_BAD_PARAM);
10869684SSusan.Gleeson@Sun.COM }
10879684SSusan.Gleeson@Sun.COM
10889684SSusan.Gleeson@Sun.COM rw_enter(&ioc->ii_hcap->ih_iou_rwlock, RW_WRITER);
10899684SSusan.Gleeson@Sun.COM if (ioc->ii_inuse == 0) {
10909684SSusan.Gleeson@Sun.COM rw_exit(&ioc->ii_hcap->ih_iou_rwlock);
10919684SSusan.Gleeson@Sun.COM mutex_exit(&ibdma->ms_hca_list_lock);
10929684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "ioc_unregister, slot not in use (%d)",
10939684SSusan.Gleeson@Sun.COM ioc->ii_slot+1);
10949684SSusan.Gleeson@Sun.COM return (IBDMA_BAD_PARAM);
10959684SSusan.Gleeson@Sun.COM }
10969684SSusan.Gleeson@Sun.COM
10979684SSusan.Gleeson@Sun.COM ASSERT(ioc->ii_srvcs != NULL);
10989684SSusan.Gleeson@Sun.COM
10999684SSusan.Gleeson@Sun.COM slot = ioc->ii_slot;
11009684SSusan.Gleeson@Sun.COM hca = ioc->ii_hcap;
11019684SSusan.Gleeson@Sun.COM kmem_free(ioc->ii_srvcs, sizeof (ib_dm_srv_t) *
11029684SSusan.Gleeson@Sun.COM ioc->ii_profile.ioc_service_entries);
11039684SSusan.Gleeson@Sun.COM bzero(ioc, sizeof (ibdma_ioc_t));
11049684SSusan.Gleeson@Sun.COM ibdma_set_ioc_state(hca, slot, IBDMA_IOC_NOT_INSTALLED);
11059684SSusan.Gleeson@Sun.COM
11069684SSusan.Gleeson@Sun.COM rw_exit(&hca->ih_iou_rwlock);
11079684SSusan.Gleeson@Sun.COM mutex_exit(&ibdma->ms_hca_list_lock);
11089684SSusan.Gleeson@Sun.COM
11099684SSusan.Gleeson@Sun.COM return (IBDMA_SUCCESS);
11109684SSusan.Gleeson@Sun.COM }
11119684SSusan.Gleeson@Sun.COM
11129684SSusan.Gleeson@Sun.COM /*
11139684SSusan.Gleeson@Sun.COM * ibdma_ioc_update()
11149684SSusan.Gleeson@Sun.COM *
11159684SSusan.Gleeson@Sun.COM */
11169684SSusan.Gleeson@Sun.COM ibdma_status_t
ibdma_ioc_update(ibdma_hdl_t hdl,ib_dm_ioc_ctrl_profile_t * profile,ib_dm_srv_t * services)11179684SSusan.Gleeson@Sun.COM ibdma_ioc_update(ibdma_hdl_t hdl, ib_dm_ioc_ctrl_profile_t *profile,
11189684SSusan.Gleeson@Sun.COM ib_dm_srv_t *services)
11199684SSusan.Gleeson@Sun.COM {
11209684SSusan.Gleeson@Sun.COM ibdma_ioc_t *ioc;
11219684SSusan.Gleeson@Sun.COM ibdma_hca_t *hca;
11229684SSusan.Gleeson@Sun.COM ibdma_hdl_impl_t *hdl_tmp = hdl;
11239684SSusan.Gleeson@Sun.COM ibdma_hdl_impl_t *hdl_impl;
11249684SSusan.Gleeson@Sun.COM
11259684SSusan.Gleeson@Sun.COM if (hdl == NULL) {
11269684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "ioc_update, NULL handle");
11279684SSusan.Gleeson@Sun.COM return (IBDMA_BAD_PARAM);
11289684SSusan.Gleeson@Sun.COM }
11299684SSusan.Gleeson@Sun.COM
11309684SSusan.Gleeson@Sun.COM if (profile == NULL || services == NULL) {
11319684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "ioc_update, NULL parameter");
11329684SSusan.Gleeson@Sun.COM return (IBDMA_BAD_PARAM);
11339684SSusan.Gleeson@Sun.COM }
11349684SSusan.Gleeson@Sun.COM
11359684SSusan.Gleeson@Sun.COM mutex_enter(&ibdma->ms_hca_list_lock);
11369684SSusan.Gleeson@Sun.COM hca = ibdma_find_hca(hdl_tmp->ih_iou_guid);
11379684SSusan.Gleeson@Sun.COM if (hca == NULL) {
11389684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "ioc_update, invalid handle, IOU not found");
11399684SSusan.Gleeson@Sun.COM mutex_exit(&ibdma->ms_hca_list_lock);
11409684SSusan.Gleeson@Sun.COM return (IBDMA_BAD_PARAM);
11419684SSusan.Gleeson@Sun.COM }
11429684SSusan.Gleeson@Sun.COM
11439684SSusan.Gleeson@Sun.COM hdl_impl = list_head(&hca->ih_hdl_list);
11449684SSusan.Gleeson@Sun.COM while (hdl_impl != NULL) {
11459684SSusan.Gleeson@Sun.COM if (hdl_impl == hdl_tmp) {
11469684SSusan.Gleeson@Sun.COM break;
11479684SSusan.Gleeson@Sun.COM }
11489684SSusan.Gleeson@Sun.COM hdl_impl = list_next(&hca->ih_hdl_list, hdl_impl);
11499684SSusan.Gleeson@Sun.COM }
11509684SSusan.Gleeson@Sun.COM
11519684SSusan.Gleeson@Sun.COM if (hdl_impl == NULL) {
11529684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "ioc_update, invalid handle, not found");
11539684SSusan.Gleeson@Sun.COM mutex_exit(&ibdma->ms_hca_list_lock);
11549684SSusan.Gleeson@Sun.COM return (IBDMA_BAD_PARAM);
11559684SSusan.Gleeson@Sun.COM }
11569684SSusan.Gleeson@Sun.COM
11579684SSusan.Gleeson@Sun.COM if (hdl_impl->ih_ioc_ndx >= IBDMA_MAX_IOC) {
11589684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "ioc_update, corrupted handle");
11599684SSusan.Gleeson@Sun.COM mutex_exit(&ibdma->ms_hca_list_lock);
11609684SSusan.Gleeson@Sun.COM return (IBDMA_BAD_PARAM);
11619684SSusan.Gleeson@Sun.COM }
11629684SSusan.Gleeson@Sun.COM ioc = &hca->ih_ioc[hdl_impl->ih_ioc_ndx];
11639684SSusan.Gleeson@Sun.COM
11649684SSusan.Gleeson@Sun.COM if (ioc->ii_slot >= IBDMA_MAX_IOC || ioc->ii_hcap == NULL) {
11659684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "ioc_update, bad handle (%p)",
11669684SSusan.Gleeson@Sun.COM (void *)hdl);
11679684SSusan.Gleeson@Sun.COM mutex_exit(&ibdma->ms_hca_list_lock);
11689684SSusan.Gleeson@Sun.COM return (IBDMA_BAD_PARAM);
11699684SSusan.Gleeson@Sun.COM }
11709684SSusan.Gleeson@Sun.COM
11719684SSusan.Gleeson@Sun.COM rw_enter(&ioc->ii_hcap->ih_iou_rwlock, RW_WRITER);
11729684SSusan.Gleeson@Sun.COM if (ioc->ii_inuse == 0) {
11739684SSusan.Gleeson@Sun.COM rw_exit(&ioc->ii_hcap->ih_iou_rwlock);
11749684SSusan.Gleeson@Sun.COM mutex_exit(&ibdma->ms_hca_list_lock);
11759684SSusan.Gleeson@Sun.COM cmn_err(CE_NOTE, "ioc_udate slot not in use (%d)",
11769684SSusan.Gleeson@Sun.COM ioc->ii_slot+1);
11779684SSusan.Gleeson@Sun.COM return (IBDMA_BAD_PARAM);
11789684SSusan.Gleeson@Sun.COM }
11799684SSusan.Gleeson@Sun.COM
11809684SSusan.Gleeson@Sun.COM ASSERT(ioc->ii_srvcs != NULL);
11819684SSusan.Gleeson@Sun.COM
11829684SSusan.Gleeson@Sun.COM kmem_free(ioc->ii_srvcs, ioc->ii_profile.ioc_service_entries *
11839684SSusan.Gleeson@Sun.COM sizeof (ib_dm_srv_t));
11849684SSusan.Gleeson@Sun.COM ioc->ii_srvcs = kmem_zalloc(profile->ioc_service_entries *
11859684SSusan.Gleeson@Sun.COM sizeof (ib_dm_srv_t), KM_SLEEP);
11869684SSusan.Gleeson@Sun.COM
11879684SSusan.Gleeson@Sun.COM bcopy(profile, &ioc->ii_profile, sizeof (ib_dm_ioc_ctrl_profile_t));
11889684SSusan.Gleeson@Sun.COM bcopy(services, ioc->ii_srvcs, sizeof (ib_dm_srv_t) *
11899684SSusan.Gleeson@Sun.COM profile->ioc_service_entries);
11909684SSusan.Gleeson@Sun.COM /*
11919684SSusan.Gleeson@Sun.COM * Update the profile copy with the I/O controller slot assigned.
11929684SSusan.Gleeson@Sun.COM * The slot occupies the lower 8 biths of the vendor ID/slot 32bit
11939684SSusan.Gleeson@Sun.COM * field.
11949684SSusan.Gleeson@Sun.COM */
11959684SSusan.Gleeson@Sun.COM profile->ioc_vendorid |= h2b32(ioc->ii_slot);
11969684SSusan.Gleeson@Sun.COM ibdma_set_ioc_state(ioc->ii_hcap, ioc->ii_slot, IBDMA_IOC_PRESENT);
11979684SSusan.Gleeson@Sun.COM rw_exit(&ioc->ii_hcap->ih_iou_rwlock);
11989684SSusan.Gleeson@Sun.COM mutex_exit(&ibdma->ms_hca_list_lock);
11999684SSusan.Gleeson@Sun.COM
12009684SSusan.Gleeson@Sun.COM return (IBDMA_SUCCESS);
12019684SSusan.Gleeson@Sun.COM }
1202