16495Sspeer /*
26495Sspeer * CDDL HEADER START
36495Sspeer *
46495Sspeer * The contents of this file are subject to the terms of the
56495Sspeer * Common Development and Distribution License (the "License").
66495Sspeer * You may not use this file except in compliance with the License.
76495Sspeer *
86495Sspeer * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
96495Sspeer * or http://www.opensolaris.org/os/licensing.
106495Sspeer * See the License for the specific language governing permissions
116495Sspeer * and limitations under the License.
126495Sspeer *
136495Sspeer * When distributing Covered Code, include this CDDL HEADER in each
146495Sspeer * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
156495Sspeer * If applicable, add the following below this CDDL HEADER, with the
166495Sspeer * fields enclosed by brackets "[]" replaced with your own identifying
176495Sspeer * information: Portions Copyright [yyyy] [name of copyright owner]
186495Sspeer *
196495Sspeer * CDDL HEADER END
206495Sspeer */
216495Sspeer
226495Sspeer /*
2311878SVenu.Iyer@Sun.COM * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
246495Sspeer * Use is subject to license terms.
256495Sspeer */
266495Sspeer
276495Sspeer /*
286495Sspeer * nxge_hio.c
296495Sspeer *
306495Sspeer * This file manages the virtualization resources for Neptune
316495Sspeer * devices. That is, it implements a hybrid I/O (HIO) approach in the
326495Sspeer * Solaris kernel, whereby a guest domain on an LDOMs server may
336495Sspeer * request & use hardware resources from the service domain.
346495Sspeer *
356495Sspeer */
366495Sspeer
378275SEric Cheng #include <sys/mac_provider.h>
386495Sspeer #include <sys/nxge/nxge_impl.h>
396495Sspeer #include <sys/nxge/nxge_fzc.h>
406495Sspeer #include <sys/nxge/nxge_rxdma.h>
416495Sspeer #include <sys/nxge/nxge_txdma.h>
426495Sspeer #include <sys/nxge/nxge_hio.h>
436495Sspeer
446495Sspeer /*
456495Sspeer * External prototypes
466495Sspeer */
476495Sspeer extern npi_status_t npi_rxdma_dump_rdc_table(npi_handle_t, uint8_t);
486495Sspeer
496495Sspeer /* The following function may be found in nxge_main.c */
508275SEric Cheng extern int nxge_m_mmac_remove(void *arg, int slot);
518275SEric Cheng extern int nxge_m_mmac_add_g(void *arg, const uint8_t *maddr, int rdctbl,
528275SEric Cheng boolean_t usetbl);
5311878SVenu.Iyer@Sun.COM extern int nxge_rx_ring_start(mac_ring_driver_t rdriver, uint64_t mr_gen_num);
546495Sspeer
556495Sspeer /* The following function may be found in nxge_[t|r]xdma.c */
566495Sspeer extern npi_status_t nxge_txdma_channel_disable(nxge_t *, int);
576495Sspeer extern nxge_status_t nxge_disable_rxdma_channel(nxge_t *, uint16_t);
586495Sspeer
596495Sspeer /*
606495Sspeer * Local prototypes
616495Sspeer */
626495Sspeer static void nxge_grp_dc_append(nxge_t *, nxge_grp_t *, nxge_hio_dc_t *);
636495Sspeer static nxge_hio_dc_t *nxge_grp_dc_unlink(nxge_t *, nxge_grp_t *, int);
646495Sspeer static void nxge_grp_dc_map(nxge_grp_t *group);
656495Sspeer
666495Sspeer /*
676495Sspeer * These functions are used by both service & guest domains to
686495Sspeer * decide whether they're running in an LDOMs/XEN environment
696495Sspeer * or not. If so, then the Hybrid I/O (HIO) module is initialized.
706495Sspeer */
716495Sspeer
726495Sspeer /*
736495Sspeer * nxge_get_environs
746495Sspeer *
756495Sspeer * Figure out if we are in a guest domain or not.
766495Sspeer *
776495Sspeer * Arguments:
786495Sspeer * nxge
796495Sspeer *
806495Sspeer * Notes:
816495Sspeer *
826495Sspeer * Context:
836495Sspeer * Any domain
846495Sspeer */
856495Sspeer void
nxge_get_environs(nxge_t * nxge)866495Sspeer nxge_get_environs(
876495Sspeer nxge_t *nxge)
886495Sspeer {
896495Sspeer char *string;
906495Sspeer
916495Sspeer /*
926495Sspeer * In the beginning, assume that we are running sans LDOMs/XEN.
936495Sspeer */
946495Sspeer nxge->environs = SOLARIS_DOMAIN;
956495Sspeer
966495Sspeer /*
976495Sspeer * Are we a hybrid I/O (HIO) guest domain driver?
986495Sspeer */
996495Sspeer if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, nxge->dip,
1006495Sspeer DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
1016495Sspeer "niutype", &string)) == DDI_PROP_SUCCESS) {
1026495Sspeer if (strcmp(string, "n2niu") == 0) {
1036495Sspeer nxge->environs = SOLARIS_GUEST_DOMAIN;
1046495Sspeer /* So we can allocate properly-aligned memory. */
1056495Sspeer nxge->niu_type = N2_NIU;
1066495Sspeer NXGE_DEBUG_MSG((nxge, HIO_CTL,
1076495Sspeer "Hybrid IO-capable guest domain"));
1086495Sspeer }
1096495Sspeer ddi_prop_free(string);
1106495Sspeer }
1116495Sspeer }
1126495Sspeer
1136495Sspeer #if !defined(sun4v)
1146495Sspeer
1156495Sspeer /*
1166495Sspeer * nxge_hio_init
1176495Sspeer *
1186495Sspeer * Initialize the HIO module of the NXGE driver.
1196495Sspeer *
1206495Sspeer * Arguments:
1216495Sspeer * nxge
1226495Sspeer *
1236495Sspeer * Notes:
1246495Sspeer * This is the non-hybrid I/O version of this function.
1256495Sspeer *
1266495Sspeer * Context:
1276495Sspeer * Any domain
1286495Sspeer */
1296495Sspeer int
nxge_hio_init(nxge_t * nxge)1307587SMichael.Speer@Sun.COM nxge_hio_init(nxge_t *nxge)
1316495Sspeer {
1326495Sspeer nxge_hio_data_t *nhd;
1338275SEric Cheng int i;
1346495Sspeer
1356495Sspeer nhd = (nxge_hio_data_t *)nxge->nxge_hw_p->hio;
13610577SMichael.Speer@Sun.COM if (nhd == NULL) {
1376495Sspeer nhd = KMEM_ZALLOC(sizeof (*nhd), KM_SLEEP);
1386495Sspeer MUTEX_INIT(&nhd->lock, NULL, MUTEX_DRIVER, NULL);
13910577SMichael.Speer@Sun.COM nhd->type = NXGE_HIO_TYPE_SERVICE;
1406495Sspeer nxge->nxge_hw_p->hio = (uintptr_t)nhd;
1416495Sspeer }
1426495Sspeer
1438275SEric Cheng /*
1448275SEric Cheng * Initialize share and ring group structures.
1458275SEric Cheng */
1468275SEric Cheng for (i = 0; i < NXGE_MAX_TDCS; i++)
1478275SEric Cheng nxge->tdc_is_shared[i] = B_FALSE;
1488275SEric Cheng
1498275SEric Cheng for (i = 0; i < NXGE_MAX_TDC_GROUPS; i++) {
1508275SEric Cheng nxge->tx_hio_groups[i].ghandle = NULL;
1518275SEric Cheng nxge->tx_hio_groups[i].nxgep = nxge;
1528275SEric Cheng nxge->tx_hio_groups[i].type = MAC_RING_TYPE_TX;
1538275SEric Cheng nxge->tx_hio_groups[i].gindex = 0;
1548275SEric Cheng nxge->tx_hio_groups[i].sindex = 0;
1558275SEric Cheng }
1568275SEric Cheng
1578275SEric Cheng for (i = 0; i < NXGE_MAX_RDC_GROUPS; i++) {
1588275SEric Cheng nxge->rx_hio_groups[i].ghandle = NULL;
1598275SEric Cheng nxge->rx_hio_groups[i].nxgep = nxge;
1608275SEric Cheng nxge->rx_hio_groups[i].type = MAC_RING_TYPE_RX;
1618275SEric Cheng nxge->rx_hio_groups[i].gindex = 0;
1628275SEric Cheng nxge->rx_hio_groups[i].sindex = 0;
1638275SEric Cheng nxge->rx_hio_groups[i].started = B_FALSE;
1648597SMichael.Speer@Sun.COM nxge->rx_hio_groups[i].port_default_grp = B_FALSE;
1658275SEric Cheng nxge->rx_hio_groups[i].rdctbl = -1;
1668275SEric Cheng nxge->rx_hio_groups[i].n_mac_addrs = 0;
1678275SEric Cheng }
1688275SEric Cheng
1696495Sspeer nhd->hio.ldoms = B_FALSE;
1706495Sspeer
1716495Sspeer return (NXGE_OK);
1726495Sspeer }
1736495Sspeer
1746495Sspeer #endif
1756495Sspeer
1766495Sspeer void
nxge_hio_uninit(nxge_t * nxge)1777587SMichael.Speer@Sun.COM nxge_hio_uninit(nxge_t *nxge)
1786495Sspeer {
1796495Sspeer nxge_hio_data_t *nhd = (nxge_hio_data_t *)nxge->nxge_hw_p->hio;
1806495Sspeer
1816495Sspeer ASSERT(nxge->nxge_hw_p->ndevs == 0);
1826495Sspeer
1837587SMichael.Speer@Sun.COM if (nhd != NULL) {
1847587SMichael.Speer@Sun.COM MUTEX_DESTROY(&nhd->lock);
1857587SMichael.Speer@Sun.COM KMEM_FREE(nhd, sizeof (*nhd));
1867587SMichael.Speer@Sun.COM nxge->nxge_hw_p->hio = 0;
1877587SMichael.Speer@Sun.COM }
1886495Sspeer }
1896495Sspeer
1906495Sspeer /*
1916495Sspeer * nxge_dci_map
1926495Sspeer *
1936495Sspeer * Map a DMA channel index to a channel number.
1946495Sspeer *
1956495Sspeer * Arguments:
1966495Sspeer * instance The instance number of the driver.
1976495Sspeer * type The type of channel this is: Tx or Rx.
1986495Sspeer * index The index to convert to a channel number
1996495Sspeer *
2006495Sspeer * Notes:
2016495Sspeer * This function is called by nxge_ndd.c:nxge_param_set_port_rdc()
2026495Sspeer *
2036495Sspeer * Context:
2046495Sspeer * Any domain
2056495Sspeer */
2066495Sspeer int
nxge_dci_map(nxge_t * nxge,vpc_type_t type,int index)2076495Sspeer nxge_dci_map(
2086495Sspeer nxge_t *nxge,
2096495Sspeer vpc_type_t type,
2106495Sspeer int index)
2116495Sspeer {
2126495Sspeer nxge_grp_set_t *set;
2136495Sspeer int dc;
2146495Sspeer
2156495Sspeer switch (type) {
2166495Sspeer case VP_BOUND_TX:
2176495Sspeer set = &nxge->tx_set;
2186495Sspeer break;
2196495Sspeer case VP_BOUND_RX:
2206495Sspeer set = &nxge->rx_set;
2216495Sspeer break;
2226495Sspeer }
2236495Sspeer
2246495Sspeer for (dc = 0; dc < NXGE_MAX_TDCS; dc++) {
2256495Sspeer if ((1 << dc) & set->owned.map) {
2266495Sspeer if (index == 0)
2276495Sspeer return (dc);
2286495Sspeer else
2296495Sspeer index--;
2306495Sspeer }
2316495Sspeer }
2326495Sspeer
2336495Sspeer return (-1);
2346495Sspeer }
2356495Sspeer
2366495Sspeer /*
2376495Sspeer * ---------------------------------------------------------------------
2386495Sspeer * These are the general-purpose DMA channel group functions. That is,
2396495Sspeer * these functions are used to manage groups of TDCs or RDCs in an HIO
2406495Sspeer * environment.
2416495Sspeer *
2426495Sspeer * But is also expected that in the future they will be able to manage
2436495Sspeer * Crossbow groups.
2446495Sspeer * ---------------------------------------------------------------------
2456495Sspeer */
2466495Sspeer
2476495Sspeer /*
2487766SMichael.Speer@Sun.COM * nxge_grp_cleanup(p_nxge_t nxge)
2497766SMichael.Speer@Sun.COM *
2507766SMichael.Speer@Sun.COM * Remove all outstanding groups.
2517766SMichael.Speer@Sun.COM *
2527766SMichael.Speer@Sun.COM * Arguments:
2537766SMichael.Speer@Sun.COM * nxge
2547766SMichael.Speer@Sun.COM */
2557766SMichael.Speer@Sun.COM void
nxge_grp_cleanup(p_nxge_t nxge)2567766SMichael.Speer@Sun.COM nxge_grp_cleanup(p_nxge_t nxge)
2577766SMichael.Speer@Sun.COM {
2587766SMichael.Speer@Sun.COM nxge_grp_set_t *set;
2597766SMichael.Speer@Sun.COM int i;
2607766SMichael.Speer@Sun.COM
2617766SMichael.Speer@Sun.COM MUTEX_ENTER(&nxge->group_lock);
2627766SMichael.Speer@Sun.COM
2637766SMichael.Speer@Sun.COM /*
2647766SMichael.Speer@Sun.COM * Find RX groups that need to be cleaned up.
2657766SMichael.Speer@Sun.COM */
2667766SMichael.Speer@Sun.COM set = &nxge->rx_set;
2677766SMichael.Speer@Sun.COM for (i = 0; i < NXGE_LOGICAL_GROUP_MAX; i++) {
2687766SMichael.Speer@Sun.COM if (set->group[i] != NULL) {
2697766SMichael.Speer@Sun.COM KMEM_FREE(set->group[i], sizeof (nxge_grp_t));
2707766SMichael.Speer@Sun.COM set->group[i] = NULL;
2717766SMichael.Speer@Sun.COM }
2727766SMichael.Speer@Sun.COM }
2737766SMichael.Speer@Sun.COM
2747766SMichael.Speer@Sun.COM /*
2757766SMichael.Speer@Sun.COM * Find TX groups that need to be cleaned up.
2767766SMichael.Speer@Sun.COM */
2777766SMichael.Speer@Sun.COM set = &nxge->tx_set;
2787766SMichael.Speer@Sun.COM for (i = 0; i < NXGE_LOGICAL_GROUP_MAX; i++) {
2797766SMichael.Speer@Sun.COM if (set->group[i] != NULL) {
2807766SMichael.Speer@Sun.COM KMEM_FREE(set->group[i], sizeof (nxge_grp_t));
2817766SMichael.Speer@Sun.COM set->group[i] = NULL;
2827766SMichael.Speer@Sun.COM }
2837766SMichael.Speer@Sun.COM }
2847766SMichael.Speer@Sun.COM MUTEX_EXIT(&nxge->group_lock);
2857766SMichael.Speer@Sun.COM }
2867766SMichael.Speer@Sun.COM
2877766SMichael.Speer@Sun.COM
2887766SMichael.Speer@Sun.COM /*
2896495Sspeer * nxge_grp_add
2906495Sspeer *
2916495Sspeer * Add a group to an instance of NXGE.
2926495Sspeer *
2936495Sspeer * Arguments:
2946495Sspeer * nxge
2956495Sspeer * type Tx or Rx
2966495Sspeer *
2976495Sspeer * Notes:
2986495Sspeer *
2996495Sspeer * Context:
3006495Sspeer * Any domain
3016495Sspeer */
3027755SMisaki.Kataoka@Sun.COM nxge_grp_t *
nxge_grp_add(nxge_t * nxge,nxge_grp_type_t type)3036495Sspeer nxge_grp_add(
3046495Sspeer nxge_t *nxge,
3056495Sspeer nxge_grp_type_t type)
3066495Sspeer {
3076495Sspeer nxge_grp_set_t *set;
3086495Sspeer nxge_grp_t *group;
3096495Sspeer int i;
3106495Sspeer
3116495Sspeer group = KMEM_ZALLOC(sizeof (*group), KM_SLEEP);
3126495Sspeer group->nxge = nxge;
3136495Sspeer
3146495Sspeer MUTEX_ENTER(&nxge->group_lock);
3156495Sspeer switch (type) {
3166495Sspeer case NXGE_TRANSMIT_GROUP:
3176495Sspeer case EXT_TRANSMIT_GROUP:
3186495Sspeer set = &nxge->tx_set;
3196495Sspeer break;
3206495Sspeer default:
3216495Sspeer set = &nxge->rx_set;
3226495Sspeer break;
3236495Sspeer }
3246495Sspeer
3256495Sspeer group->type = type;
3266495Sspeer group->active = B_TRUE;
3276495Sspeer group->sequence = set->sequence++;
3286495Sspeer
3296495Sspeer /* Find an empty slot for this logical group. */
3306495Sspeer for (i = 0; i < NXGE_LOGICAL_GROUP_MAX; i++) {
3316495Sspeer if (set->group[i] == 0) {
3326495Sspeer group->index = i;
3336495Sspeer set->group[i] = group;
3346495Sspeer NXGE_DC_SET(set->lg.map, i);
3356495Sspeer set->lg.count++;
3366495Sspeer break;
3376495Sspeer }
3386495Sspeer }
3396495Sspeer MUTEX_EXIT(&nxge->group_lock);
3406495Sspeer
3416495Sspeer NXGE_DEBUG_MSG((nxge, HIO_CTL,
3426495Sspeer "nxge_grp_add: %cgroup = %d.%d",
3436495Sspeer type == NXGE_TRANSMIT_GROUP ? 't' : 'r',
3446495Sspeer nxge->mac.portnum, group->sequence));
3456495Sspeer
3467755SMisaki.Kataoka@Sun.COM return (group);
3476495Sspeer }
3486495Sspeer
3496495Sspeer void
nxge_grp_remove(nxge_t * nxge,nxge_grp_t * group)3506495Sspeer nxge_grp_remove(
3516495Sspeer nxge_t *nxge,
3527755SMisaki.Kataoka@Sun.COM nxge_grp_t *group) /* The group to remove. */
3536495Sspeer {
3546495Sspeer nxge_grp_set_t *set;
3556495Sspeer vpc_type_t type;
3566495Sspeer
35711304SJanie.Lu@Sun.COM if (group == NULL)
35811304SJanie.Lu@Sun.COM return;
35911304SJanie.Lu@Sun.COM
3606495Sspeer MUTEX_ENTER(&nxge->group_lock);
3616495Sspeer switch (group->type) {
3626495Sspeer case NXGE_TRANSMIT_GROUP:
3636495Sspeer case EXT_TRANSMIT_GROUP:
3646495Sspeer set = &nxge->tx_set;
3656495Sspeer break;
3666495Sspeer default:
3676495Sspeer set = &nxge->rx_set;
3686495Sspeer break;
3696495Sspeer }
3706495Sspeer
3716495Sspeer if (set->group[group->index] != group) {
3726495Sspeer MUTEX_EXIT(&nxge->group_lock);
3736495Sspeer return;
3746495Sspeer }
3756495Sspeer
3766495Sspeer set->group[group->index] = 0;
3776495Sspeer NXGE_DC_RESET(set->lg.map, group->index);
3786495Sspeer set->lg.count--;
3796495Sspeer
3806495Sspeer /* While inside the mutex, deactivate <group>. */
3816495Sspeer group->active = B_FALSE;
3826495Sspeer
3836495Sspeer MUTEX_EXIT(&nxge->group_lock);
3846495Sspeer
3856495Sspeer NXGE_DEBUG_MSG((nxge, HIO_CTL,
3866495Sspeer "nxge_grp_remove(%c.%d.%d) called",
3876495Sspeer group->type == NXGE_TRANSMIT_GROUP ? 't' : 'r',
3886495Sspeer nxge->mac.portnum, group->sequence));
3896495Sspeer
3906495Sspeer /* Now, remove any DCs which are still active. */
3916495Sspeer switch (group->type) {
3926495Sspeer default:
3936495Sspeer type = VP_BOUND_TX;
3946495Sspeer break;
3956495Sspeer case NXGE_RECEIVE_GROUP:
3966495Sspeer case EXT_RECEIVE_GROUP:
3976495Sspeer type = VP_BOUND_RX;
3986495Sspeer }
3996495Sspeer
4006495Sspeer while (group->dc) {
4016495Sspeer nxge_grp_dc_remove(nxge, type, group->dc->channel);
4026495Sspeer }
4036495Sspeer
4046495Sspeer KMEM_FREE(group, sizeof (*group));
4056495Sspeer }
4066495Sspeer
4076495Sspeer /*
4087950SMichael.Speer@Sun.COM * nxge_grp_dc_add
4096495Sspeer *
4106495Sspeer * Add a DMA channel to a VR/Group.
4116495Sspeer *
4126495Sspeer * Arguments:
4136495Sspeer * nxge
4146495Sspeer * channel The channel to add.
4156495Sspeer * Notes:
4166495Sspeer *
4176495Sspeer * Context:
4186495Sspeer * Any domain
4196495Sspeer */
4206495Sspeer /* ARGSUSED */
4216495Sspeer int
nxge_grp_dc_add(nxge_t * nxge,nxge_grp_t * group,vpc_type_t type,int channel)4226495Sspeer nxge_grp_dc_add(
4236495Sspeer nxge_t *nxge,
4247755SMisaki.Kataoka@Sun.COM nxge_grp_t *group, /* The group to add <channel> to. */
4256495Sspeer vpc_type_t type, /* Rx or Tx */
4266495Sspeer int channel) /* A physical/logical channel number */
4276495Sspeer {
4286495Sspeer nxge_hio_data_t *nhd = (nxge_hio_data_t *)nxge->nxge_hw_p->hio;
4296495Sspeer nxge_hio_dc_t *dc;
4306495Sspeer nxge_grp_set_t *set;
4316602Sspeer nxge_status_t status = NXGE_OK;
43211878SVenu.Iyer@Sun.COM int error = 0;
4336495Sspeer
4346495Sspeer NXGE_DEBUG_MSG((nxge, HIO_CTL, "==> nxge_grp_dc_add"));
4356495Sspeer
4368275SEric Cheng if (group == 0)
4376495Sspeer return (0);
4386495Sspeer
4396495Sspeer switch (type) {
4407950SMichael.Speer@Sun.COM case VP_BOUND_TX:
4416495Sspeer set = &nxge->tx_set;
4426495Sspeer if (channel > NXGE_MAX_TDCS) {
4436495Sspeer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
4446495Sspeer "nxge_grp_dc_add: TDC = %d", channel));
4456495Sspeer return (NXGE_ERROR);
4466495Sspeer }
4476495Sspeer break;
4486495Sspeer case VP_BOUND_RX:
4496495Sspeer set = &nxge->rx_set;
4506495Sspeer if (channel > NXGE_MAX_RDCS) {
4516495Sspeer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
4526495Sspeer "nxge_grp_dc_add: RDC = %d", channel));
4536495Sspeer return (NXGE_ERROR);
4546495Sspeer }
4556495Sspeer break;
4567950SMichael.Speer@Sun.COM
4577950SMichael.Speer@Sun.COM default:
4587950SMichael.Speer@Sun.COM NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
4597950SMichael.Speer@Sun.COM "nxge_grp_dc_add: unknown type channel(%d)", channel));
4606495Sspeer }
4616495Sspeer
4626495Sspeer NXGE_DEBUG_MSG((nxge, HIO_CTL,
4636495Sspeer "nxge_grp_dc_add: %cgroup = %d.%d.%d, channel = %d",
4646495Sspeer type == VP_BOUND_TX ? 't' : 'r',
4656495Sspeer nxge->mac.portnum, group->sequence, group->count, channel));
4666495Sspeer
4676495Sspeer MUTEX_ENTER(&nxge->group_lock);
4686495Sspeer if (group->active != B_TRUE) {
4696495Sspeer /* We may be in the process of removing this group. */
4706495Sspeer MUTEX_EXIT(&nxge->group_lock);
4716495Sspeer return (NXGE_ERROR);
4726495Sspeer }
4736495Sspeer MUTEX_EXIT(&nxge->group_lock);
4746495Sspeer
4756495Sspeer if (!(dc = nxge_grp_dc_find(nxge, type, channel))) {
4766495Sspeer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
4776495Sspeer "nxge_grp_dc_add(%d): DC FIND failed", channel));
4786495Sspeer return (NXGE_ERROR);
4796495Sspeer }
4806495Sspeer
4816495Sspeer MUTEX_ENTER(&nhd->lock);
4826495Sspeer
4836495Sspeer if (dc->group) {
4846495Sspeer MUTEX_EXIT(&nhd->lock);
4856495Sspeer /* This channel is already in use! */
4866495Sspeer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
4876495Sspeer "nxge_grp_dc_add(%d): channel already in group", channel));
4886495Sspeer return (NXGE_ERROR);
4896495Sspeer }
4906495Sspeer
4916495Sspeer dc->next = 0;
4926495Sspeer dc->page = channel;
4936495Sspeer dc->channel = (nxge_channel_t)channel;
4946495Sspeer
4956495Sspeer dc->type = type;
4966495Sspeer if (type == VP_BOUND_RX) {
4976495Sspeer dc->init = nxge_init_rxdma_channel;
4986495Sspeer dc->uninit = nxge_uninit_rxdma_channel;
4996495Sspeer } else {
5006495Sspeer dc->init = nxge_init_txdma_channel;
5016495Sspeer dc->uninit = nxge_uninit_txdma_channel;
5026495Sspeer }
5036495Sspeer
5047755SMisaki.Kataoka@Sun.COM dc->group = group;
5056495Sspeer
50611878SVenu.Iyer@Sun.COM if (isLDOMguest(nxge)) {
50711878SVenu.Iyer@Sun.COM error = nxge_hio_ldsv_add(nxge, dc);
50811878SVenu.Iyer@Sun.COM if (error != 0) {
50911878SVenu.Iyer@Sun.COM MUTEX_EXIT(&nhd->lock);
51011878SVenu.Iyer@Sun.COM return (NXGE_ERROR);
51111878SVenu.Iyer@Sun.COM }
51211878SVenu.Iyer@Sun.COM }
5136495Sspeer
5146495Sspeer NXGE_DC_SET(set->owned.map, channel);
5156495Sspeer set->owned.count++;
5166495Sspeer
5176495Sspeer MUTEX_EXIT(&nhd->lock);
5186495Sspeer
5196602Sspeer if ((status = (*dc->init)(nxge, channel)) != NXGE_OK) {
5206602Sspeer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
5216602Sspeer "nxge_grp_dc_add(%d): channel init failed", channel));
5227950SMichael.Speer@Sun.COM MUTEX_ENTER(&nhd->lock);
5237950SMichael.Speer@Sun.COM (void) memset(dc, 0, sizeof (*dc));
5247950SMichael.Speer@Sun.COM NXGE_DC_RESET(set->owned.map, channel);
5257950SMichael.Speer@Sun.COM set->owned.count--;
5267950SMichael.Speer@Sun.COM MUTEX_EXIT(&nhd->lock);
5276603Sspeer return (NXGE_ERROR);
5286602Sspeer }
5296602Sspeer
5306495Sspeer nxge_grp_dc_append(nxge, group, dc);
5316495Sspeer
5327812SMichael.Speer@Sun.COM if (type == VP_BOUND_TX) {
5337812SMichael.Speer@Sun.COM MUTEX_ENTER(&nhd->lock);
5347812SMichael.Speer@Sun.COM nxge->tdc_is_shared[channel] = B_FALSE;
5357812SMichael.Speer@Sun.COM MUTEX_EXIT(&nhd->lock);
5367812SMichael.Speer@Sun.COM }
5377812SMichael.Speer@Sun.COM
5386495Sspeer NXGE_DEBUG_MSG((nxge, HIO_CTL, "<== nxge_grp_dc_add"));
5396495Sspeer
5406602Sspeer return ((int)status);
5416495Sspeer }
5426495Sspeer
5436495Sspeer void
nxge_grp_dc_remove(nxge_t * nxge,vpc_type_t type,int channel)5446495Sspeer nxge_grp_dc_remove(
5456495Sspeer nxge_t *nxge,
5466495Sspeer vpc_type_t type,
5476495Sspeer int channel)
5486495Sspeer {
5496495Sspeer nxge_hio_data_t *nhd = (nxge_hio_data_t *)nxge->nxge_hw_p->hio;
5506495Sspeer nxge_hio_dc_t *dc;
5516495Sspeer nxge_grp_set_t *set;
5526495Sspeer nxge_grp_t *group;
5536495Sspeer
5546495Sspeer dc_uninit_t uninit;
5556495Sspeer
5566495Sspeer NXGE_DEBUG_MSG((nxge, HIO_CTL, "==> nxge_grp_dc_remove"));
5576495Sspeer
5587950SMichael.Speer@Sun.COM if ((dc = nxge_grp_dc_find(nxge, type, channel)) == 0)
5597950SMichael.Speer@Sun.COM goto nxge_grp_dc_remove_exit;
5607950SMichael.Speer@Sun.COM
5617950SMichael.Speer@Sun.COM if ((dc->group == NULL) && (dc->next == 0) &&
5627950SMichael.Speer@Sun.COM (dc->channel == 0) && (dc->page == 0) && (dc->type == 0)) {
5637950SMichael.Speer@Sun.COM goto nxge_grp_dc_remove_exit;
5646495Sspeer }
5657950SMichael.Speer@Sun.COM
5666495Sspeer group = (nxge_grp_t *)dc->group;
5676495Sspeer
5686495Sspeer if (isLDOMguest(nxge)) {
5696495Sspeer (void) nxge_hio_intr_remove(nxge, type, channel);
5706495Sspeer }
5716495Sspeer
5726495Sspeer NXGE_DEBUG_MSG((nxge, HIO_CTL,
5736495Sspeer "DC remove: group = %d.%d.%d, %cdc %d",
5746495Sspeer nxge->mac.portnum, group->sequence, group->count,
5756495Sspeer type == VP_BOUND_TX ? 't' : 'r', dc->channel));
5766495Sspeer
5776495Sspeer MUTEX_ENTER(&nhd->lock);
5786495Sspeer
5796602Sspeer set = dc->type == VP_BOUND_TX ? &nxge->tx_set : &nxge->rx_set;
5806602Sspeer
5816495Sspeer /* Remove the DC from its group. */
5826495Sspeer if (nxge_grp_dc_unlink(nxge, group, channel) != dc) {
5836495Sspeer MUTEX_EXIT(&nhd->lock);
5846495Sspeer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
5857950SMichael.Speer@Sun.COM "nxge_grp_dc_remove(%d) failed", channel));
5867950SMichael.Speer@Sun.COM goto nxge_grp_dc_remove_exit;
5876495Sspeer }
5886495Sspeer
5896495Sspeer uninit = dc->uninit;
5906495Sspeer channel = dc->channel;
5916495Sspeer
5926495Sspeer NXGE_DC_RESET(set->owned.map, channel);
5936495Sspeer set->owned.count--;
5946495Sspeer
5956495Sspeer (void) memset(dc, 0, sizeof (*dc));
5966495Sspeer
5976495Sspeer MUTEX_EXIT(&nhd->lock);
5986495Sspeer
5996495Sspeer (*uninit)(nxge, channel);
6006495Sspeer
6017950SMichael.Speer@Sun.COM nxge_grp_dc_remove_exit:
6026495Sspeer NXGE_DEBUG_MSG((nxge, HIO_CTL, "<== nxge_grp_dc_remove"));
6036495Sspeer }
6046495Sspeer
6056495Sspeer nxge_hio_dc_t *
nxge_grp_dc_find(nxge_t * nxge,vpc_type_t type,int channel)6066495Sspeer nxge_grp_dc_find(
6076495Sspeer nxge_t *nxge,
6086495Sspeer vpc_type_t type, /* Rx or Tx */
6096495Sspeer int channel)
6106495Sspeer {
6116495Sspeer nxge_hio_data_t *nhd = (nxge_hio_data_t *)nxge->nxge_hw_p->hio;
6126495Sspeer nxge_hio_dc_t *current;
6136495Sspeer
6146495Sspeer current = (type == VP_BOUND_TX) ? &nhd->tdc[0] : &nhd->rdc[0];
6156495Sspeer
6166495Sspeer if (!isLDOMguest(nxge)) {
6176495Sspeer return (¤t[channel]);
6186495Sspeer } else {
6196495Sspeer /* We're in a guest domain. */
6206495Sspeer int i, limit = (type == VP_BOUND_TX) ?
6216495Sspeer NXGE_MAX_TDCS : NXGE_MAX_RDCS;
6226495Sspeer
6236495Sspeer MUTEX_ENTER(&nhd->lock);
6246495Sspeer for (i = 0; i < limit; i++, current++) {
6256495Sspeer if (current->channel == channel) {
6266495Sspeer if (current->vr && current->vr->nxge ==
6276495Sspeer (uintptr_t)nxge) {
6286495Sspeer MUTEX_EXIT(&nhd->lock);
6296495Sspeer return (current);
6306495Sspeer }
6316495Sspeer }
6326495Sspeer }
6336495Sspeer MUTEX_EXIT(&nhd->lock);
6346495Sspeer }
6356495Sspeer
6366495Sspeer return (0);
6376495Sspeer }
6386495Sspeer
6396495Sspeer /*
6406495Sspeer * nxge_grp_dc_append
6416495Sspeer *
6426495Sspeer * Append a DMA channel to a group.
6436495Sspeer *
6446495Sspeer * Arguments:
6456495Sspeer * nxge
6466495Sspeer * group The group to append to
6476495Sspeer * dc The DMA channel to append
6486495Sspeer *
6496495Sspeer * Notes:
6506495Sspeer *
6516495Sspeer * Context:
6526495Sspeer * Any domain
6536495Sspeer */
6546495Sspeer static
6556495Sspeer void
nxge_grp_dc_append(nxge_t * nxge,nxge_grp_t * group,nxge_hio_dc_t * dc)6566495Sspeer nxge_grp_dc_append(
6576495Sspeer nxge_t *nxge,
6586495Sspeer nxge_grp_t *group,
6596495Sspeer nxge_hio_dc_t *dc)
6606495Sspeer {
6616495Sspeer MUTEX_ENTER(&nxge->group_lock);
6626495Sspeer
6636495Sspeer if (group->dc == 0) {
6646495Sspeer group->dc = dc;
6656495Sspeer } else {
6666495Sspeer nxge_hio_dc_t *current = group->dc;
6676495Sspeer do {
6686495Sspeer if (current->next == 0) {
6696495Sspeer current->next = dc;
6706495Sspeer break;
6716495Sspeer }
6726495Sspeer current = current->next;
6736495Sspeer } while (current);
6746495Sspeer }
6756495Sspeer
6766495Sspeer NXGE_DC_SET(group->map, dc->channel);
6776495Sspeer
6786495Sspeer nxge_grp_dc_map(group);
6796602Sspeer group->count++;
6806495Sspeer
6816495Sspeer MUTEX_EXIT(&nxge->group_lock);
6826495Sspeer }
6836495Sspeer
6846495Sspeer /*
6856495Sspeer * nxge_grp_dc_unlink
6866495Sspeer *
6876495Sspeer * Unlink a DMA channel fromits linked list (group).
6886495Sspeer *
6896495Sspeer * Arguments:
6906495Sspeer * nxge
6916495Sspeer * group The group (linked list) to unlink from
6926495Sspeer * dc The DMA channel to append
6936495Sspeer *
6946495Sspeer * Notes:
6956495Sspeer *
6966495Sspeer * Context:
6976495Sspeer * Any domain
6986495Sspeer */
6996495Sspeer nxge_hio_dc_t *
nxge_grp_dc_unlink(nxge_t * nxge,nxge_grp_t * group,int channel)7008275SEric Cheng nxge_grp_dc_unlink(
7018275SEric Cheng nxge_t *nxge,
7028275SEric Cheng nxge_grp_t *group,
7038275SEric Cheng int channel)
7046495Sspeer {
7056495Sspeer nxge_hio_dc_t *current, *previous;
7066495Sspeer
7076495Sspeer MUTEX_ENTER(&nxge->group_lock);
7086495Sspeer
7097812SMichael.Speer@Sun.COM if (group == NULL) {
7107812SMichael.Speer@Sun.COM MUTEX_EXIT(&nxge->group_lock);
7117812SMichael.Speer@Sun.COM return (0);
7127812SMichael.Speer@Sun.COM }
7137812SMichael.Speer@Sun.COM
7146495Sspeer if ((current = group->dc) == 0) {
7156495Sspeer MUTEX_EXIT(&nxge->group_lock);
7166495Sspeer return (0);
7176495Sspeer }
7186495Sspeer
7196495Sspeer previous = 0;
7206495Sspeer do {
7216495Sspeer if (current->channel == channel) {
7226495Sspeer if (previous)
7236495Sspeer previous->next = current->next;
7246495Sspeer else
7256495Sspeer group->dc = current->next;
7266495Sspeer break;
7276495Sspeer }
7286495Sspeer previous = current;
7296495Sspeer current = current->next;
7306495Sspeer } while (current);
7316495Sspeer
7326495Sspeer if (current == 0) {
7336495Sspeer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
7346495Sspeer "DC unlink: DC %d not found", channel));
7356495Sspeer } else {
7366495Sspeer current->next = 0;
7376495Sspeer current->group = 0;
7386495Sspeer
7398275SEric Cheng NXGE_DC_RESET(group->map, channel);
7406495Sspeer group->count--;
7416495Sspeer }
7426495Sspeer
7436495Sspeer nxge_grp_dc_map(group);
7446495Sspeer
7456495Sspeer MUTEX_EXIT(&nxge->group_lock);
7466495Sspeer
7476495Sspeer return (current);
7486495Sspeer }
7496495Sspeer
7506495Sspeer /*
7516495Sspeer * nxge_grp_dc_map
7526495Sspeer *
7536495Sspeer * Map a linked list to an array of channel numbers.
7546495Sspeer *
7556495Sspeer * Arguments:
7566495Sspeer * nxge
7576495Sspeer * group The group to remap.
7586495Sspeer *
7596495Sspeer * Notes:
7606495Sspeer * It is expected that the caller will hold the correct mutex.
7616495Sspeer *
7626495Sspeer * Context:
7636495Sspeer * Service domain
7646495Sspeer */
7656495Sspeer void
nxge_grp_dc_map(nxge_grp_t * group)7666495Sspeer nxge_grp_dc_map(
7676495Sspeer nxge_grp_t *group)
7686495Sspeer {
7696495Sspeer nxge_channel_t *legend;
7706495Sspeer nxge_hio_dc_t *dc;
7716495Sspeer
7726495Sspeer (void) memset(group->legend, 0, sizeof (group->legend));
7736495Sspeer
7746495Sspeer legend = group->legend;
7756495Sspeer dc = group->dc;
7766495Sspeer while (dc) {
7776495Sspeer *legend = dc->channel;
7786495Sspeer legend++;
7796495Sspeer dc = dc->next;
7806495Sspeer }
7816495Sspeer }
7826495Sspeer
7836495Sspeer /*
7846495Sspeer * ---------------------------------------------------------------------
7856495Sspeer * These are HIO debugging functions.
7866495Sspeer * ---------------------------------------------------------------------
7876495Sspeer */
7886495Sspeer
7896495Sspeer /*
7906495Sspeer * nxge_delay
7916495Sspeer *
7926495Sspeer * Delay <seconds> number of seconds.
7936495Sspeer *
7946495Sspeer * Arguments:
7956495Sspeer * nxge
7966495Sspeer * group The group to append to
7976495Sspeer * dc The DMA channel to append
7986495Sspeer *
7996495Sspeer * Notes:
8006495Sspeer * This is a developer-only function.
8016495Sspeer *
8026495Sspeer * Context:
8036495Sspeer * Any domain
8046495Sspeer */
8056495Sspeer void
nxge_delay(int seconds)8066495Sspeer nxge_delay(
8076495Sspeer int seconds)
8086495Sspeer {
8096495Sspeer delay(drv_usectohz(seconds * 1000000));
8106495Sspeer }
8116495Sspeer
8126495Sspeer static dmc_reg_name_t rx_names[] = {
8136495Sspeer { "RXDMA_CFIG1", 0 },
8146495Sspeer { "RXDMA_CFIG2", 8 },
8156495Sspeer { "RBR_CFIG_A", 0x10 },
8166495Sspeer { "RBR_CFIG_B", 0x18 },
8176495Sspeer { "RBR_KICK", 0x20 },
8186495Sspeer { "RBR_STAT", 0x28 },
8196495Sspeer { "RBR_HDH", 0x30 },
8206495Sspeer { "RBR_HDL", 0x38 },
8216495Sspeer { "RCRCFIG_A", 0x40 },
8226495Sspeer { "RCRCFIG_B", 0x48 },
8236495Sspeer { "RCRSTAT_A", 0x50 },
8246495Sspeer { "RCRSTAT_B", 0x58 },
8256495Sspeer { "RCRSTAT_C", 0x60 },
8266495Sspeer { "RX_DMA_ENT_MSK", 0x68 },
8276495Sspeer { "RX_DMA_CTL_STAT", 0x70 },
8286495Sspeer { "RCR_FLSH", 0x78 },
8296495Sspeer { "RXMISC", 0x90 },
8306495Sspeer { "RX_DMA_CTL_STAT_DBG", 0x98 },
8316495Sspeer { 0, -1 }
8326495Sspeer };
8336495Sspeer
8346495Sspeer static dmc_reg_name_t tx_names[] = {
8356495Sspeer { "Tx_RNG_CFIG", 0 },
8366495Sspeer { "Tx_RNG_HDL", 0x10 },
8376495Sspeer { "Tx_RNG_KICK", 0x18 },
8386495Sspeer { "Tx_ENT_MASK", 0x20 },
8396495Sspeer { "Tx_CS", 0x28 },
8406495Sspeer { "TxDMA_MBH", 0x30 },
8416495Sspeer { "TxDMA_MBL", 0x38 },
8426495Sspeer { "TxDMA_PRE_ST", 0x40 },
8436495Sspeer { "Tx_RNG_ERR_LOGH", 0x48 },
8446495Sspeer { "Tx_RNG_ERR_LOGL", 0x50 },
8456495Sspeer { "TDMC_INTR_DBG", 0x60 },
8466495Sspeer { "Tx_CS_DBG", 0x68 },
8476495Sspeer { 0, -1 }
8486495Sspeer };
8496495Sspeer
8506495Sspeer /*
8516495Sspeer * nxge_xx2str
8526495Sspeer *
8536495Sspeer * Translate a register address into a string.
8546495Sspeer *
8556495Sspeer * Arguments:
8566495Sspeer * offset The address of the register to translate.
8576495Sspeer *
8586495Sspeer * Notes:
8596495Sspeer * These are developer-only function.
8606495Sspeer *
8616495Sspeer * Context:
8626495Sspeer * Any domain
8636495Sspeer */
8646495Sspeer const char *
nxge_rx2str(int offset)8656495Sspeer nxge_rx2str(
8666495Sspeer int offset)
8676495Sspeer {
8686495Sspeer dmc_reg_name_t *reg = &rx_names[0];
8696495Sspeer
8706495Sspeer offset &= DMA_CSR_MASK;
8716495Sspeer
8726495Sspeer while (reg->name) {
8736495Sspeer if (offset == reg->offset)
8746495Sspeer return (reg->name);
8756495Sspeer reg++;
8766495Sspeer }
8776495Sspeer
8786495Sspeer return (0);
8796495Sspeer }
8806495Sspeer
8816495Sspeer const char *
nxge_tx2str(int offset)8826495Sspeer nxge_tx2str(
8836495Sspeer int offset)
8846495Sspeer {
8856495Sspeer dmc_reg_name_t *reg = &tx_names[0];
8866495Sspeer
8876495Sspeer offset &= DMA_CSR_MASK;
8886495Sspeer
8896495Sspeer while (reg->name) {
8906495Sspeer if (offset == reg->offset)
8916495Sspeer return (reg->name);
8926495Sspeer reg++;
8936495Sspeer }
8946495Sspeer
8956495Sspeer return (0);
8966495Sspeer }
8976495Sspeer
8986495Sspeer /*
8996495Sspeer * nxge_ddi_perror
9006495Sspeer *
9016495Sspeer * Map a DDI error number to a string.
9026495Sspeer *
9036495Sspeer * Arguments:
9046495Sspeer * ddi_error The DDI error number to map.
9056495Sspeer *
9066495Sspeer * Notes:
9076495Sspeer *
9086495Sspeer * Context:
9096495Sspeer * Any domain
9106495Sspeer */
9116495Sspeer const char *
nxge_ddi_perror(int ddi_error)9126495Sspeer nxge_ddi_perror(
9136495Sspeer int ddi_error)
9146495Sspeer {
9156495Sspeer switch (ddi_error) {
9166495Sspeer case DDI_SUCCESS:
9176495Sspeer return ("DDI_SUCCESS");
9186495Sspeer case DDI_FAILURE:
9196495Sspeer return ("DDI_FAILURE");
9206495Sspeer case DDI_NOT_WELL_FORMED:
9216495Sspeer return ("DDI_NOT_WELL_FORMED");
9226495Sspeer case DDI_EAGAIN:
9236495Sspeer return ("DDI_EAGAIN");
9246495Sspeer case DDI_EINVAL:
9256495Sspeer return ("DDI_EINVAL");
9266495Sspeer case DDI_ENOTSUP:
9276495Sspeer return ("DDI_ENOTSUP");
9286495Sspeer case DDI_EPENDING:
9296495Sspeer return ("DDI_EPENDING");
9306495Sspeer case DDI_ENOMEM:
9316495Sspeer return ("DDI_ENOMEM");
9326495Sspeer case DDI_EBUSY:
9336495Sspeer return ("DDI_EBUSY");
9346495Sspeer case DDI_ETRANSPORT:
9356495Sspeer return ("DDI_ETRANSPORT");
9366495Sspeer case DDI_ECONTEXT:
9376495Sspeer return ("DDI_ECONTEXT");
9386495Sspeer default:
9396495Sspeer return ("Unknown error");
9406495Sspeer }
9416495Sspeer }
9426495Sspeer
9436495Sspeer /*
9446495Sspeer * ---------------------------------------------------------------------
9456495Sspeer * These are Sun4v HIO function definitions
9466495Sspeer * ---------------------------------------------------------------------
9476495Sspeer */
9486495Sspeer
9496495Sspeer #if defined(sun4v)
9506495Sspeer
9516495Sspeer /*
9526495Sspeer * Local prototypes
9536495Sspeer */
9547755SMisaki.Kataoka@Sun.COM static nxge_hio_vr_t *nxge_hio_vr_share(nxge_t *);
9557755SMisaki.Kataoka@Sun.COM static void nxge_hio_unshare(nxge_hio_vr_t *);
9566495Sspeer
9578275SEric Cheng static int nxge_hio_addres(nxge_hio_vr_t *, mac_ring_type_t, uint64_t *);
9587755SMisaki.Kataoka@Sun.COM static void nxge_hio_remres(nxge_hio_vr_t *, mac_ring_type_t, res_map_t);
9596495Sspeer
9608275SEric Cheng static void nxge_hio_tdc_unshare(nxge_t *nxge, int dev_grpid, int channel);
9618275SEric Cheng static void nxge_hio_rdc_unshare(nxge_t *nxge, int dev_grpid, int channel);
9628275SEric Cheng static int nxge_hio_dc_share(nxge_t *, nxge_hio_vr_t *, mac_ring_type_t, int);
9636495Sspeer static void nxge_hio_dc_unshare(nxge_t *, nxge_hio_vr_t *,
9646495Sspeer mac_ring_type_t, int);
9656495Sspeer
9666495Sspeer /*
9676495Sspeer * nxge_hio_init
9686495Sspeer *
9696495Sspeer * Initialize the HIO module of the NXGE driver.
9706495Sspeer *
9716495Sspeer * Arguments:
9726495Sspeer * nxge
9736495Sspeer *
9746495Sspeer * Notes:
9756495Sspeer *
9766495Sspeer * Context:
9776495Sspeer * Any domain
9786495Sspeer */
9796495Sspeer int
nxge_hio_init(nxge_t * nxge)98010577SMichael.Speer@Sun.COM nxge_hio_init(nxge_t *nxge)
9816495Sspeer {
9826495Sspeer nxge_hio_data_t *nhd;
9836495Sspeer int i, region;
9846495Sspeer
9856495Sspeer nhd = (nxge_hio_data_t *)nxge->nxge_hw_p->hio;
9866495Sspeer if (nhd == 0) {
9876495Sspeer nhd = KMEM_ZALLOC(sizeof (*nhd), KM_SLEEP);
9886495Sspeer MUTEX_INIT(&nhd->lock, NULL, MUTEX_DRIVER, NULL);
98910577SMichael.Speer@Sun.COM if (isLDOMguest(nxge))
99010577SMichael.Speer@Sun.COM nhd->type = NXGE_HIO_TYPE_GUEST;
99110577SMichael.Speer@Sun.COM else
99210577SMichael.Speer@Sun.COM nhd->type = NXGE_HIO_TYPE_SERVICE;
9936495Sspeer nxge->nxge_hw_p->hio = (uintptr_t)nhd;
9946495Sspeer }
9956495Sspeer
9966713Sspeer if ((nxge->environs == SOLARIS_DOMAIN) &&
9976713Sspeer (nxge->niu_type == N2_NIU)) {
9986495Sspeer if (nxge->niu_hsvc_available == B_TRUE) {
9996495Sspeer hsvc_info_t *niu_hsvc = &nxge->niu_hsvc;
100011304SJanie.Lu@Sun.COM /*
100111304SJanie.Lu@Sun.COM * Versions supported now are:
100211304SJanie.Lu@Sun.COM * - major number >= 1 (NIU_MAJOR_VER).
100311304SJanie.Lu@Sun.COM */
100411304SJanie.Lu@Sun.COM if ((niu_hsvc->hsvc_major >= NIU_MAJOR_VER) ||
100511304SJanie.Lu@Sun.COM (niu_hsvc->hsvc_major == 1 &&
100611304SJanie.Lu@Sun.COM niu_hsvc->hsvc_minor == 1)) {
10076495Sspeer nxge->environs = SOLARIS_SERVICE_DOMAIN;
100811304SJanie.Lu@Sun.COM NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
100911304SJanie.Lu@Sun.COM "nxge_hio_init: hypervisor services "
101011304SJanie.Lu@Sun.COM "version %d.%d",
101111304SJanie.Lu@Sun.COM niu_hsvc->hsvc_major,
101211304SJanie.Lu@Sun.COM niu_hsvc->hsvc_minor));
101311304SJanie.Lu@Sun.COM }
10146495Sspeer }
10156495Sspeer }
10166495Sspeer
10178275SEric Cheng /*
10188275SEric Cheng * Initialize share and ring group structures.
10198275SEric Cheng */
10208275SEric Cheng for (i = 0; i < NXGE_MAX_TDC_GROUPS; i++) {
10218275SEric Cheng nxge->tx_hio_groups[i].ghandle = NULL;
10228275SEric Cheng nxge->tx_hio_groups[i].nxgep = nxge;
10238275SEric Cheng nxge->tx_hio_groups[i].type = MAC_RING_TYPE_TX;
10248275SEric Cheng nxge->tx_hio_groups[i].gindex = 0;
10258275SEric Cheng nxge->tx_hio_groups[i].sindex = 0;
10268275SEric Cheng }
10278275SEric Cheng
10288275SEric Cheng for (i = 0; i < NXGE_MAX_RDC_GROUPS; i++) {
10298275SEric Cheng nxge->rx_hio_groups[i].ghandle = NULL;
10308275SEric Cheng nxge->rx_hio_groups[i].nxgep = nxge;
10318275SEric Cheng nxge->rx_hio_groups[i].type = MAC_RING_TYPE_RX;
10328275SEric Cheng nxge->rx_hio_groups[i].gindex = 0;
10338275SEric Cheng nxge->rx_hio_groups[i].sindex = 0;
10348275SEric Cheng nxge->rx_hio_groups[i].started = B_FALSE;
10358597SMichael.Speer@Sun.COM nxge->rx_hio_groups[i].port_default_grp = B_FALSE;
10368275SEric Cheng nxge->rx_hio_groups[i].rdctbl = -1;
10378275SEric Cheng nxge->rx_hio_groups[i].n_mac_addrs = 0;
10388275SEric Cheng }
10398275SEric Cheng
10406495Sspeer if (!isLDOMs(nxge)) {
10416495Sspeer nhd->hio.ldoms = B_FALSE;
10426495Sspeer return (NXGE_OK);
10436495Sspeer }
10446495Sspeer
10456495Sspeer nhd->hio.ldoms = B_TRUE;
10466495Sspeer
10476495Sspeer /*
10486495Sspeer * Fill in what we can.
10496495Sspeer */
10506495Sspeer for (region = 0; region < NXGE_VR_SR_MAX; region++) {
10516495Sspeer nhd->vr[region].region = region;
10526495Sspeer }
10537755SMisaki.Kataoka@Sun.COM nhd->vrs = NXGE_VR_SR_MAX - 2;
10546495Sspeer
10556495Sspeer /*
10568275SEric Cheng * Initialize the share stuctures.
10576495Sspeer */
10587812SMichael.Speer@Sun.COM for (i = 0; i < NXGE_MAX_TDCS; i++)
10597812SMichael.Speer@Sun.COM nxge->tdc_is_shared[i] = B_FALSE;
10607812SMichael.Speer@Sun.COM
10616495Sspeer for (i = 0; i < NXGE_VR_SR_MAX; i++) {
10626495Sspeer nxge->shares[i].nxgep = nxge;
10636495Sspeer nxge->shares[i].index = 0;
10648275SEric Cheng nxge->shares[i].vrp = NULL;
10656495Sspeer nxge->shares[i].tmap = 0;
10666495Sspeer nxge->shares[i].rmap = 0;
10676495Sspeer nxge->shares[i].rxgroup = 0;
10686495Sspeer nxge->shares[i].active = B_FALSE;
10696495Sspeer }
10706495Sspeer
10716495Sspeer /* Fill in the HV HIO function pointers. */
10726495Sspeer nxge_hio_hv_init(nxge);
10736495Sspeer
10746495Sspeer if (isLDOMservice(nxge)) {
10756495Sspeer NXGE_DEBUG_MSG((nxge, HIO_CTL,
10766495Sspeer "Hybrid IO-capable service domain"));
10776495Sspeer return (NXGE_OK);
10786495Sspeer }
10796495Sspeer
10806495Sspeer return (0);
10816495Sspeer }
10828275SEric Cheng #endif /* defined(sun4v) */
10838275SEric Cheng
10848275SEric Cheng static int
nxge_hio_group_mac_add(nxge_t * nxge,nxge_ring_group_t * g,const uint8_t * macaddr)10858275SEric Cheng nxge_hio_group_mac_add(nxge_t *nxge, nxge_ring_group_t *g,
10868275SEric Cheng const uint8_t *macaddr)
10878275SEric Cheng {
10888275SEric Cheng int rv;
10898275SEric Cheng nxge_rdc_grp_t *group;
10908275SEric Cheng
10918275SEric Cheng mutex_enter(nxge->genlock);
10928275SEric Cheng
10938275SEric Cheng /*
10948275SEric Cheng * Initialize the NXGE RDC table data structure.
10958275SEric Cheng */
10968275SEric Cheng group = &nxge->pt_config.rdc_grps[g->rdctbl];
10978275SEric Cheng if (!group->flag) {
10988275SEric Cheng group->port = NXGE_GET_PORT_NUM(nxge->function_num);
10998275SEric Cheng group->config_method = RDC_TABLE_ENTRY_METHOD_REP;
11008275SEric Cheng group->flag = B_TRUE; /* This group has been configured. */
11018275SEric Cheng }
11028275SEric Cheng
11038275SEric Cheng mutex_exit(nxge->genlock);
11048275SEric Cheng
11058275SEric Cheng /*
11068275SEric Cheng * Add the MAC address.
11078275SEric Cheng */
11088275SEric Cheng if ((rv = nxge_m_mmac_add_g((void *)nxge, macaddr,
11098275SEric Cheng g->rdctbl, B_TRUE)) != 0) {
11108275SEric Cheng return (rv);
11118275SEric Cheng }
11128275SEric Cheng
11138275SEric Cheng mutex_enter(nxge->genlock);
11148275SEric Cheng g->n_mac_addrs++;
11158275SEric Cheng mutex_exit(nxge->genlock);
11168275SEric Cheng return (0);
11178275SEric Cheng }
11186495Sspeer
11196495Sspeer static int
nxge_hio_set_unicst(void * arg,const uint8_t * macaddr)11208597SMichael.Speer@Sun.COM nxge_hio_set_unicst(void *arg, const uint8_t *macaddr)
11218597SMichael.Speer@Sun.COM {
11228597SMichael.Speer@Sun.COM p_nxge_t nxgep = (p_nxge_t)arg;
11238597SMichael.Speer@Sun.COM struct ether_addr addrp;
11248597SMichael.Speer@Sun.COM
11258597SMichael.Speer@Sun.COM bcopy(macaddr, (uint8_t *)&addrp, ETHERADDRL);
11268597SMichael.Speer@Sun.COM if (nxge_set_mac_addr(nxgep, &addrp)) {
11278597SMichael.Speer@Sun.COM NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
11288597SMichael.Speer@Sun.COM "<== nxge_m_unicst: set unitcast failed"));
11298597SMichael.Speer@Sun.COM return (EINVAL);
11308597SMichael.Speer@Sun.COM }
11318597SMichael.Speer@Sun.COM
11328597SMichael.Speer@Sun.COM nxgep->primary = B_TRUE;
11338597SMichael.Speer@Sun.COM
11348597SMichael.Speer@Sun.COM return (0);
11358597SMichael.Speer@Sun.COM }
11368597SMichael.Speer@Sun.COM
11378597SMichael.Speer@Sun.COM /*ARGSUSED*/
11388597SMichael.Speer@Sun.COM static int
nxge_hio_clear_unicst(p_nxge_t nxgep,const uint8_t * mac_addr)11398597SMichael.Speer@Sun.COM nxge_hio_clear_unicst(p_nxge_t nxgep, const uint8_t *mac_addr)
11408597SMichael.Speer@Sun.COM {
11418597SMichael.Speer@Sun.COM nxgep->primary = B_FALSE;
11428597SMichael.Speer@Sun.COM return (0);
11438597SMichael.Speer@Sun.COM }
11448597SMichael.Speer@Sun.COM
11458597SMichael.Speer@Sun.COM static int
nxge_hio_add_mac(void * arg,const uint8_t * mac_addr)11466495Sspeer nxge_hio_add_mac(void *arg, const uint8_t *mac_addr)
11476495Sspeer {
114810309SSriharsha.Basavapatna@Sun.COM nxge_ring_group_t *group = (nxge_ring_group_t *)arg;
114910309SSriharsha.Basavapatna@Sun.COM p_nxge_t nxge = group->nxgep;
115010309SSriharsha.Basavapatna@Sun.COM int rv;
115110309SSriharsha.Basavapatna@Sun.COM nxge_hio_vr_t *vr; /* The Virtualization Region */
11526495Sspeer
11538275SEric Cheng ASSERT(group->type == MAC_RING_TYPE_RX);
115410309SSriharsha.Basavapatna@Sun.COM ASSERT(group->nxgep != NULL);
115510309SSriharsha.Basavapatna@Sun.COM
115610309SSriharsha.Basavapatna@Sun.COM if (isLDOMguest(group->nxgep))
115710309SSriharsha.Basavapatna@Sun.COM return (0);
11588275SEric Cheng
11598275SEric Cheng mutex_enter(nxge->genlock);
11606495Sspeer
11618597SMichael.Speer@Sun.COM if (!nxge->primary && group->port_default_grp) {
11628597SMichael.Speer@Sun.COM rv = nxge_hio_set_unicst((void *)nxge, mac_addr);
11638597SMichael.Speer@Sun.COM mutex_exit(nxge->genlock);
11648597SMichael.Speer@Sun.COM return (rv);
11658597SMichael.Speer@Sun.COM }
11668597SMichael.Speer@Sun.COM
11676495Sspeer /*
11688275SEric Cheng * If the group is associated with a VR, then only one
11698275SEric Cheng * address may be assigned to the group.
11706495Sspeer */
11718275SEric Cheng vr = (nxge_hio_vr_t *)nxge->shares[group->sindex].vrp;
11728275SEric Cheng if ((vr != NULL) && (group->n_mac_addrs)) {
11738275SEric Cheng mutex_exit(nxge->genlock);
11748275SEric Cheng return (ENOSPC);
11758275SEric Cheng }
11768275SEric Cheng
11778275SEric Cheng mutex_exit(nxge->genlock);
11788275SEric Cheng
11798275SEric Cheng /*
11808275SEric Cheng * Program the mac address for the group.
11818275SEric Cheng */
118210309SSriharsha.Basavapatna@Sun.COM if ((rv = nxge_hio_group_mac_add(nxge, group, mac_addr)) != 0) {
11836495Sspeer return (rv);
11846495Sspeer }
11856495Sspeer
11866495Sspeer return (0);
11876495Sspeer }
11886495Sspeer
11898275SEric Cheng static int
find_mac_slot(nxge_mmac_t * mmac_info,const uint8_t * mac_addr)11908275SEric Cheng find_mac_slot(nxge_mmac_t *mmac_info, const uint8_t *mac_addr)
11918275SEric Cheng {
11928275SEric Cheng int i;
11938275SEric Cheng for (i = 0; i <= mmac_info->num_mmac; i++) {
11948275SEric Cheng if (memcmp(mmac_info->mac_pool[i].addr, mac_addr,
11958275SEric Cheng ETHERADDRL) == 0) {
11968275SEric Cheng return (i);
11978275SEric Cheng }
11988275SEric Cheng }
11998275SEric Cheng return (-1);
12008275SEric Cheng }
12018275SEric Cheng
12026495Sspeer /* ARGSUSED */
12036495Sspeer static int
nxge_hio_rem_mac(void * arg,const uint8_t * mac_addr)12046495Sspeer nxge_hio_rem_mac(void *arg, const uint8_t *mac_addr)
12056495Sspeer {
12068275SEric Cheng nxge_ring_group_t *group = (nxge_ring_group_t *)arg;
12078597SMichael.Speer@Sun.COM struct ether_addr addrp;
12088275SEric Cheng p_nxge_t nxge = group->nxgep;
12098275SEric Cheng nxge_mmac_t *mmac_info;
12108275SEric Cheng int rv, slot;
12118275SEric Cheng
12128275SEric Cheng ASSERT(group->type == MAC_RING_TYPE_RX);
121310309SSriharsha.Basavapatna@Sun.COM ASSERT(group->nxgep != NULL);
121410309SSriharsha.Basavapatna@Sun.COM
121510309SSriharsha.Basavapatna@Sun.COM if (isLDOMguest(group->nxgep))
121610309SSriharsha.Basavapatna@Sun.COM return (0);
12178275SEric Cheng
12188275SEric Cheng mutex_enter(nxge->genlock);
12196495Sspeer
12208275SEric Cheng mmac_info = &nxge->nxge_mmac_info;
12218275SEric Cheng slot = find_mac_slot(mmac_info, mac_addr);
12228275SEric Cheng if (slot < 0) {
12238597SMichael.Speer@Sun.COM if (group->port_default_grp && nxge->primary) {
12248597SMichael.Speer@Sun.COM bcopy(mac_addr, (uint8_t *)&addrp, ETHERADDRL);
12258597SMichael.Speer@Sun.COM if (ether_cmp(&addrp, &nxge->ouraddr) == 0) {
12268597SMichael.Speer@Sun.COM rv = nxge_hio_clear_unicst(nxge, mac_addr);
12278597SMichael.Speer@Sun.COM mutex_exit(nxge->genlock);
12288597SMichael.Speer@Sun.COM return (rv);
12298597SMichael.Speer@Sun.COM } else {
12308597SMichael.Speer@Sun.COM mutex_exit(nxge->genlock);
12318597SMichael.Speer@Sun.COM return (EINVAL);
12328597SMichael.Speer@Sun.COM }
12338597SMichael.Speer@Sun.COM } else {
12348597SMichael.Speer@Sun.COM mutex_exit(nxge->genlock);
12358597SMichael.Speer@Sun.COM return (EINVAL);
12368597SMichael.Speer@Sun.COM }
12378275SEric Cheng }
12388275SEric Cheng
12398275SEric Cheng mutex_exit(nxge->genlock);
12406495Sspeer
12416495Sspeer /*
12428275SEric Cheng * Remove the mac address for the group
12436495Sspeer */
12448275SEric Cheng if ((rv = nxge_m_mmac_remove(nxge, slot)) != 0) {
12458275SEric Cheng return (rv);
12468275SEric Cheng }
12478275SEric Cheng
12488275SEric Cheng mutex_enter(nxge->genlock);
12498275SEric Cheng group->n_mac_addrs--;
12508275SEric Cheng mutex_exit(nxge->genlock);
12516495Sspeer
12526495Sspeer return (0);
12536495Sspeer }
12546495Sspeer
12558275SEric Cheng static int
nxge_hio_group_start(mac_group_driver_t gdriver)12568275SEric Cheng nxge_hio_group_start(mac_group_driver_t gdriver)
12578275SEric Cheng {
12588275SEric Cheng nxge_ring_group_t *group = (nxge_ring_group_t *)gdriver;
12599047SMichael.Speer@Sun.COM nxge_rdc_grp_t *rdc_grp_p;
12608275SEric Cheng int rdctbl;
12618275SEric Cheng int dev_gindex;
12628275SEric Cheng
12638275SEric Cheng ASSERT(group->type == MAC_RING_TYPE_RX);
126410309SSriharsha.Basavapatna@Sun.COM ASSERT(group->nxgep != NULL);
12658275SEric Cheng
12668275SEric Cheng ASSERT(group->nxgep->nxge_mac_state == NXGE_MAC_STARTED);
12678275SEric Cheng if (group->nxgep->nxge_mac_state != NXGE_MAC_STARTED)
12688275SEric Cheng return (ENXIO);
12698275SEric Cheng
12708275SEric Cheng mutex_enter(group->nxgep->genlock);
127110309SSriharsha.Basavapatna@Sun.COM if (isLDOMguest(group->nxgep))
127210309SSriharsha.Basavapatna@Sun.COM goto nxge_hio_group_start_exit;
127310309SSriharsha.Basavapatna@Sun.COM
12748275SEric Cheng dev_gindex = group->nxgep->pt_config.hw_config.def_mac_rxdma_grpid +
12758275SEric Cheng group->gindex;
12769047SMichael.Speer@Sun.COM rdc_grp_p = &group->nxgep->pt_config.rdc_grps[dev_gindex];
12778275SEric Cheng
12788275SEric Cheng /*
12798275SEric Cheng * Get an rdc table for this group.
12808275SEric Cheng * Group ID is given by the caller, and that's the group it needs
12818275SEric Cheng * to bind to. The default group is already bound when the driver
12828275SEric Cheng * was attached.
12838275SEric Cheng *
12848275SEric Cheng * For Group 0, it's RDC table was allocated at attach time
12858275SEric Cheng * no need to allocate a new table.
12868275SEric Cheng */
12878275SEric Cheng if (group->gindex != 0) {
12888275SEric Cheng rdctbl = nxge_fzc_rdc_tbl_bind(group->nxgep,
12898275SEric Cheng dev_gindex, B_TRUE);
12908275SEric Cheng if (rdctbl < 0) {
12918275SEric Cheng mutex_exit(group->nxgep->genlock);
12928275SEric Cheng return (rdctbl);
12938275SEric Cheng }
12948275SEric Cheng } else {
12958275SEric Cheng rdctbl = group->nxgep->pt_config.hw_config.def_mac_rxdma_grpid;
12968275SEric Cheng }
12978275SEric Cheng
12988275SEric Cheng group->rdctbl = rdctbl;
12998275SEric Cheng
13009047SMichael.Speer@Sun.COM (void) nxge_init_fzc_rdc_tbl(group->nxgep, rdc_grp_p, rdctbl);
13018275SEric Cheng
130210309SSriharsha.Basavapatna@Sun.COM nxge_hio_group_start_exit:
13038275SEric Cheng group->started = B_TRUE;
13048275SEric Cheng mutex_exit(group->nxgep->genlock);
13058275SEric Cheng return (0);
13068275SEric Cheng }
13078275SEric Cheng
13088275SEric Cheng static void
nxge_hio_group_stop(mac_group_driver_t gdriver)13098275SEric Cheng nxge_hio_group_stop(mac_group_driver_t gdriver)
13108275SEric Cheng {
13118275SEric Cheng nxge_ring_group_t *group = (nxge_ring_group_t *)gdriver;
13128275SEric Cheng
13138275SEric Cheng ASSERT(group->type == MAC_RING_TYPE_RX);
13148275SEric Cheng
13158275SEric Cheng mutex_enter(group->nxgep->genlock);
13168275SEric Cheng group->started = B_FALSE;
13178275SEric Cheng
131810309SSriharsha.Basavapatna@Sun.COM if (isLDOMguest(group->nxgep))
131910309SSriharsha.Basavapatna@Sun.COM goto nxge_hio_group_stop_exit;
132010309SSriharsha.Basavapatna@Sun.COM
13218275SEric Cheng /*
13228275SEric Cheng * Unbind the RDC table previously bound for this group.
13238275SEric Cheng *
13248275SEric Cheng * Since RDC table for group 0 was allocated at attach
13258275SEric Cheng * time, no need to unbind the table here.
13268275SEric Cheng */
13278275SEric Cheng if (group->gindex != 0)
13288275SEric Cheng (void) nxge_fzc_rdc_tbl_unbind(group->nxgep, group->rdctbl);
13298275SEric Cheng
133010309SSriharsha.Basavapatna@Sun.COM nxge_hio_group_stop_exit:
13318275SEric Cheng mutex_exit(group->nxgep->genlock);
13328275SEric Cheng }
13338275SEric Cheng
13346495Sspeer /* ARGSUSED */
13356495Sspeer void
nxge_hio_group_get(void * arg,mac_ring_type_t type,int groupid,mac_group_info_t * infop,mac_group_handle_t ghdl)13368275SEric Cheng nxge_hio_group_get(void *arg, mac_ring_type_t type, int groupid,
13376495Sspeer mac_group_info_t *infop, mac_group_handle_t ghdl)
13386495Sspeer {
13398275SEric Cheng p_nxge_t nxgep = (p_nxge_t)arg;
13408275SEric Cheng nxge_ring_group_t *group;
13418275SEric Cheng int dev_gindex;
13426495Sspeer
13436495Sspeer switch (type) {
13446495Sspeer case MAC_RING_TYPE_RX:
13458275SEric Cheng group = &nxgep->rx_hio_groups[groupid];
13468275SEric Cheng group->nxgep = nxgep;
13478275SEric Cheng group->ghandle = ghdl;
13488275SEric Cheng group->gindex = groupid;
13498275SEric Cheng group->sindex = 0; /* not yet bound to a share */
13506495Sspeer
135110309SSriharsha.Basavapatna@Sun.COM if (!isLDOMguest(nxgep)) {
135210309SSriharsha.Basavapatna@Sun.COM dev_gindex =
135310309SSriharsha.Basavapatna@Sun.COM nxgep->pt_config.hw_config.def_mac_rxdma_grpid +
135410309SSriharsha.Basavapatna@Sun.COM groupid;
13558275SEric Cheng
135610309SSriharsha.Basavapatna@Sun.COM if (nxgep->pt_config.hw_config.def_mac_rxdma_grpid ==
135710309SSriharsha.Basavapatna@Sun.COM dev_gindex)
135810309SSriharsha.Basavapatna@Sun.COM group->port_default_grp = B_TRUE;
135910309SSriharsha.Basavapatna@Sun.COM
136010309SSriharsha.Basavapatna@Sun.COM infop->mgi_count =
136110309SSriharsha.Basavapatna@Sun.COM nxgep->pt_config.rdc_grps[dev_gindex].max_rdcs;
136210309SSriharsha.Basavapatna@Sun.COM } else {
136310309SSriharsha.Basavapatna@Sun.COM infop->mgi_count = NXGE_HIO_SHARE_MAX_CHANNELS;
136410309SSriharsha.Basavapatna@Sun.COM }
13658597SMichael.Speer@Sun.COM
13668275SEric Cheng infop->mgi_driver = (mac_group_driver_t)group;
13678275SEric Cheng infop->mgi_start = nxge_hio_group_start;
13688275SEric Cheng infop->mgi_stop = nxge_hio_group_stop;
13698275SEric Cheng infop->mgi_addmac = nxge_hio_add_mac;
13708275SEric Cheng infop->mgi_remmac = nxge_hio_rem_mac;
13716495Sspeer break;
13726495Sspeer
13736495Sspeer case MAC_RING_TYPE_TX:
13748275SEric Cheng /*
13758275SEric Cheng * 'groupid' for TX should be incremented by one since
13768275SEric Cheng * the default group (groupid 0) is not known by the MAC layer
13778275SEric Cheng */
13788275SEric Cheng group = &nxgep->tx_hio_groups[groupid + 1];
13798275SEric Cheng group->nxgep = nxgep;
13808275SEric Cheng group->ghandle = ghdl;
13818275SEric Cheng group->gindex = groupid + 1;
13828275SEric Cheng group->sindex = 0; /* not yet bound to a share */
13838275SEric Cheng
13848275SEric Cheng infop->mgi_driver = (mac_group_driver_t)group;
13858275SEric Cheng infop->mgi_start = NULL;
13868275SEric Cheng infop->mgi_stop = NULL;
13878275SEric Cheng infop->mgi_addmac = NULL; /* not needed */
13888275SEric Cheng infop->mgi_remmac = NULL; /* not needed */
13898275SEric Cheng /* no rings associated with group initially */
13908275SEric Cheng infop->mgi_count = 0;
13916495Sspeer break;
13926495Sspeer }
13936495Sspeer }
13946495Sspeer
13958275SEric Cheng #if defined(sun4v)
13968275SEric Cheng
13976495Sspeer int
nxge_hio_share_assign(nxge_t * nxge,uint64_t cookie,res_map_t * tmap,res_map_t * rmap,nxge_hio_vr_t * vr)13986495Sspeer nxge_hio_share_assign(
13996495Sspeer nxge_t *nxge,
14006495Sspeer uint64_t cookie,
14016495Sspeer res_map_t *tmap,
14026495Sspeer res_map_t *rmap,
14036495Sspeer nxge_hio_vr_t *vr)
14046495Sspeer {
14056495Sspeer nxge_hio_data_t *nhd = (nxge_hio_data_t *)nxge->nxge_hw_p->hio;
14066495Sspeer uint64_t slot, hv_rv;
14076495Sspeer nxge_hio_dc_t *dc;
14086495Sspeer nxhv_vr_fp_t *fp;
14096495Sspeer int i;
141011304SJanie.Lu@Sun.COM uint64_t major;
14116495Sspeer
14126495Sspeer /*
14136495Sspeer * Ask the Hypervisor to set up the VR for us
14146495Sspeer */
14156495Sspeer fp = &nhd->hio.vr;
141611304SJanie.Lu@Sun.COM major = nxge->niu_hsvc.hsvc_major;
141711304SJanie.Lu@Sun.COM switch (major) {
141811304SJanie.Lu@Sun.COM case NIU_MAJOR_VER: /* 1 */
141911304SJanie.Lu@Sun.COM if ((hv_rv = (*fp->assign)(vr->region, cookie, &vr->cookie))) {
142011304SJanie.Lu@Sun.COM NXGE_ERROR_MSG((nxge, HIO_CTL,
142111304SJanie.Lu@Sun.COM "nxge_hio_share_assign: major %d "
142211304SJanie.Lu@Sun.COM "vr->assign() returned %d", major, hv_rv));
142311304SJanie.Lu@Sun.COM nxge_hio_unshare(vr);
142411304SJanie.Lu@Sun.COM return (-EIO);
142511304SJanie.Lu@Sun.COM }
142611304SJanie.Lu@Sun.COM
142711304SJanie.Lu@Sun.COM break;
142811304SJanie.Lu@Sun.COM
142911304SJanie.Lu@Sun.COM case NIU_MAJOR_VER_2: /* 2 */
143011304SJanie.Lu@Sun.COM default:
143111304SJanie.Lu@Sun.COM if ((hv_rv = (*fp->cfgh_assign)
143211304SJanie.Lu@Sun.COM (nxge->niu_cfg_hdl, vr->region, cookie, &vr->cookie))) {
143311304SJanie.Lu@Sun.COM NXGE_ERROR_MSG((nxge, HIO_CTL,
143411304SJanie.Lu@Sun.COM "nxge_hio_share_assign: major %d "
143511304SJanie.Lu@Sun.COM "vr->assign() returned %d", major, hv_rv));
143611304SJanie.Lu@Sun.COM nxge_hio_unshare(vr);
143711304SJanie.Lu@Sun.COM return (-EIO);
143811304SJanie.Lu@Sun.COM }
143911304SJanie.Lu@Sun.COM
144011304SJanie.Lu@Sun.COM break;
14416495Sspeer }
14426495Sspeer
144311304SJanie.Lu@Sun.COM NXGE_DEBUG_MSG((nxge, HIO_CTL,
144411304SJanie.Lu@Sun.COM "nxge_hio_share_assign: major %d "
144511304SJanie.Lu@Sun.COM "vr->assign() success", major));
144611304SJanie.Lu@Sun.COM
14476495Sspeer /*
14486495Sspeer * For each shared TDC, ask the HV to find us an empty slot.
14496495Sspeer */
14506495Sspeer dc = vr->tx_group.dc;
14516495Sspeer for (i = 0; i < NXGE_MAX_TDCS; i++) {
14526495Sspeer nxhv_dc_fp_t *tx = &nhd->hio.tx;
14536495Sspeer while (dc) {
14546495Sspeer hv_rv = (*tx->assign)
14556495Sspeer (vr->cookie, dc->channel, &slot);
14566495Sspeer if (hv_rv != 0) {
14576495Sspeer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
14587950SMichael.Speer@Sun.COM "nxge_hio_share_assign: "
14596495Sspeer "tx->assign(%x, %d) failed: %ld",
14606495Sspeer vr->cookie, dc->channel, hv_rv));
14616495Sspeer return (-EIO);
14626495Sspeer }
14636495Sspeer
14646495Sspeer dc->cookie = vr->cookie;
14656495Sspeer dc->page = (vp_channel_t)slot;
14666495Sspeer
14676495Sspeer /* Inform the caller about the slot chosen. */
14686495Sspeer (*tmap) |= 1 << slot;
14696495Sspeer
14706495Sspeer dc = dc->next;
14716495Sspeer }
14726495Sspeer }
14736495Sspeer
14746495Sspeer /*
14756495Sspeer * For each shared RDC, ask the HV to find us an empty slot.
14766495Sspeer */
14776495Sspeer dc = vr->rx_group.dc;
14786495Sspeer for (i = 0; i < NXGE_MAX_RDCS; i++) {
14796495Sspeer nxhv_dc_fp_t *rx = &nhd->hio.rx;
14806495Sspeer while (dc) {
14816495Sspeer hv_rv = (*rx->assign)
14826495Sspeer (vr->cookie, dc->channel, &slot);
14836495Sspeer if (hv_rv != 0) {
14846495Sspeer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
14857950SMichael.Speer@Sun.COM "nxge_hio_share_assign: "
14866495Sspeer "rx->assign(%x, %d) failed: %ld",
14876495Sspeer vr->cookie, dc->channel, hv_rv));
14886495Sspeer return (-EIO);
14896495Sspeer }
14906495Sspeer
14916495Sspeer dc->cookie = vr->cookie;
14926495Sspeer dc->page = (vp_channel_t)slot;
14936495Sspeer
14946495Sspeer /* Inform the caller about the slot chosen. */
14956495Sspeer (*rmap) |= 1 << slot;
14966495Sspeer
14976495Sspeer dc = dc->next;
14986495Sspeer }
14996495Sspeer }
15006495Sspeer
15016495Sspeer return (0);
15026495Sspeer }
15036495Sspeer
15048275SEric Cheng void
nxge_hio_share_unassign(nxge_hio_vr_t * vr)15056495Sspeer nxge_hio_share_unassign(
15066495Sspeer nxge_hio_vr_t *vr)
15076495Sspeer {
15086495Sspeer nxge_t *nxge = (nxge_t *)vr->nxge;
15096495Sspeer nxge_hio_data_t *nhd;
15106495Sspeer nxge_hio_dc_t *dc;
15116495Sspeer nxhv_vr_fp_t *fp;
15126495Sspeer uint64_t hv_rv;
15136495Sspeer
15146495Sspeer nhd = (nxge_hio_data_t *)nxge->nxge_hw_p->hio;
15156495Sspeer
15166495Sspeer dc = vr->tx_group.dc;
15176495Sspeer while (dc) {
15186495Sspeer nxhv_dc_fp_t *tx = &nhd->hio.tx;
15196495Sspeer hv_rv = (*tx->unassign)(vr->cookie, dc->page);
15206495Sspeer if (hv_rv != 0) {
15216495Sspeer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
15227950SMichael.Speer@Sun.COM "nxge_hio_share_unassign: "
15236495Sspeer "tx->unassign(%x, %d) failed: %ld",
15246495Sspeer vr->cookie, dc->page, hv_rv));
15256495Sspeer }
15266495Sspeer dc = dc->next;
15276495Sspeer }
15286495Sspeer
15296495Sspeer dc = vr->rx_group.dc;
15306495Sspeer while (dc) {
15316495Sspeer nxhv_dc_fp_t *rx = &nhd->hio.rx;
15326495Sspeer hv_rv = (*rx->unassign)(vr->cookie, dc->page);
15336495Sspeer if (hv_rv != 0) {
15346495Sspeer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
15357950SMichael.Speer@Sun.COM "nxge_hio_share_unassign: "
15366495Sspeer "rx->unassign(%x, %d) failed: %ld",
15376495Sspeer vr->cookie, dc->page, hv_rv));
15386495Sspeer }
15396495Sspeer dc = dc->next;
15406495Sspeer }
15416495Sspeer
15426495Sspeer fp = &nhd->hio.vr;
15436495Sspeer if (fp->unassign) {
15446495Sspeer hv_rv = (*fp->unassign)(vr->cookie);
15456495Sspeer if (hv_rv != 0) {
15467950SMichael.Speer@Sun.COM NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
15477950SMichael.Speer@Sun.COM "nxge_hio_share_unassign: "
15486495Sspeer "vr->assign(%x) failed: %ld",
15496495Sspeer vr->cookie, hv_rv));
15506495Sspeer }
15516495Sspeer }
15526495Sspeer }
15536495Sspeer
15546495Sspeer int
nxge_hio_share_alloc(void * arg,mac_share_handle_t * shandle)15558275SEric Cheng nxge_hio_share_alloc(void *arg, mac_share_handle_t *shandle)
15566495Sspeer {
15578275SEric Cheng p_nxge_t nxge = (p_nxge_t)arg;
15588275SEric Cheng nxge_share_handle_t *shp;
15598275SEric Cheng nxge_hio_vr_t *vr; /* The Virtualization Region */
15608275SEric Cheng nxge_hio_data_t *nhd = (nxge_hio_data_t *)nxge->nxge_hw_p->hio;
15616495Sspeer
15626495Sspeer NXGE_DEBUG_MSG((nxge, HIO_CTL, "==> nxge_hio_share"));
15636495Sspeer
15646495Sspeer if (nhd->hio.vr.assign == 0 || nhd->hio.tx.assign == 0 ||
15656495Sspeer nhd->hio.rx.assign == 0) {
15666495Sspeer NXGE_ERROR_MSG((nxge, HIO_CTL, "HV assign function(s) NULL"));
15676495Sspeer return (EIO);
15686495Sspeer }
15696495Sspeer
15706495Sspeer /*
15716495Sspeer * Get a VR.
15726495Sspeer */
15737755SMisaki.Kataoka@Sun.COM if ((vr = nxge_hio_vr_share(nxge)) == 0)
15746495Sspeer return (EAGAIN);
15756495Sspeer
15766495Sspeer shp = &nxge->shares[vr->region];
15778275SEric Cheng shp->nxgep = nxge;
15786495Sspeer shp->index = vr->region;
15796495Sspeer shp->vrp = (void *)vr;
15808275SEric Cheng shp->tmap = shp->rmap = 0; /* to be assigned by ms_sbind */
15818275SEric Cheng shp->rxgroup = 0; /* to be assigned by ms_sadd */
15828275SEric Cheng shp->active = B_FALSE; /* not bound yet */
15836495Sspeer
15846495Sspeer *shandle = (mac_share_handle_t)shp;
15856495Sspeer
15866495Sspeer NXGE_DEBUG_MSG((nxge, HIO_CTL, "<== nxge_hio_share"));
15876495Sspeer return (0);
15886495Sspeer }
15896495Sspeer
15908275SEric Cheng
15916495Sspeer void
nxge_hio_share_free(mac_share_handle_t shandle)15926495Sspeer nxge_hio_share_free(mac_share_handle_t shandle)
15936495Sspeer {
15948275SEric Cheng nxge_share_handle_t *shp = (nxge_share_handle_t *)shandle;
15958275SEric Cheng nxge_hio_vr_t *vr;
15968275SEric Cheng
15978275SEric Cheng /*
15988275SEric Cheng * Clear internal handle state.
15998275SEric Cheng */
16008275SEric Cheng vr = shp->vrp;
16018275SEric Cheng shp->vrp = (void *)NULL;
16028275SEric Cheng shp->index = 0;
16038275SEric Cheng shp->tmap = 0;
16048275SEric Cheng shp->rmap = 0;
16058275SEric Cheng shp->rxgroup = 0;
16068275SEric Cheng shp->active = B_FALSE;
16078275SEric Cheng
16088275SEric Cheng /*
16098275SEric Cheng * Free VR resource.
16108275SEric Cheng */
16118275SEric Cheng nxge_hio_unshare(vr);
16128275SEric Cheng }
16138275SEric Cheng
16148275SEric Cheng
16158275SEric Cheng void
nxge_hio_share_query(mac_share_handle_t shandle,mac_ring_type_t type,mac_ring_handle_t * rings,uint_t * n_rings)16168275SEric Cheng nxge_hio_share_query(mac_share_handle_t shandle, mac_ring_type_t type,
16178275SEric Cheng mac_ring_handle_t *rings, uint_t *n_rings)
16188275SEric Cheng {
16198275SEric Cheng nxge_t *nxge;
16208275SEric Cheng nxge_share_handle_t *shp = (nxge_share_handle_t *)shandle;
16218275SEric Cheng nxge_ring_handle_t *rh;
16228275SEric Cheng uint32_t offset;
16238275SEric Cheng
16248275SEric Cheng nxge = shp->nxgep;
16258275SEric Cheng
16268275SEric Cheng switch (type) {
16278275SEric Cheng case MAC_RING_TYPE_RX:
16288275SEric Cheng rh = nxge->rx_ring_handles;
16298275SEric Cheng offset = nxge->pt_config.hw_config.start_rdc;
16308275SEric Cheng break;
16318275SEric Cheng
16328275SEric Cheng case MAC_RING_TYPE_TX:
16338275SEric Cheng rh = nxge->tx_ring_handles;
16348275SEric Cheng offset = nxge->pt_config.hw_config.tdc.start;
16358275SEric Cheng break;
16368275SEric Cheng }
16378275SEric Cheng
16388275SEric Cheng /*
16398275SEric Cheng * In version 1.0, we may only give a VR 2 RDCs/TDCs. Not only that,
16408275SEric Cheng * but the HV has statically assigned the channels like so:
16418275SEric Cheng * VR0: RDC0 & RDC1
16428275SEric Cheng * VR1: RDC2 & RDC3, etc.
16438275SEric Cheng * The TDCs are assigned in exactly the same way.
16448275SEric Cheng */
16458275SEric Cheng if (rings != NULL) {
16468275SEric Cheng rings[0] = rh[(shp->index * 2) - offset].ring_handle;
16478275SEric Cheng rings[1] = rh[(shp->index * 2 + 1) - offset].ring_handle;
16488275SEric Cheng }
16498275SEric Cheng if (n_rings != NULL) {
16508275SEric Cheng *n_rings = 2;
16518275SEric Cheng }
16528275SEric Cheng }
16538275SEric Cheng
16548275SEric Cheng int
nxge_hio_share_add_group(mac_share_handle_t shandle,mac_group_driver_t ghandle)16558275SEric Cheng nxge_hio_share_add_group(mac_share_handle_t shandle,
16568275SEric Cheng mac_group_driver_t ghandle)
16578275SEric Cheng {
16588275SEric Cheng nxge_t *nxge;
16598275SEric Cheng nxge_share_handle_t *shp = (nxge_share_handle_t *)shandle;
16608275SEric Cheng nxge_ring_group_t *rg = (nxge_ring_group_t *)ghandle;
16618275SEric Cheng nxge_hio_vr_t *vr; /* The Virtualization Region */
16628275SEric Cheng nxge_grp_t *group;
16638275SEric Cheng int i;
16648275SEric Cheng
16658275SEric Cheng if (rg->sindex != 0) {
16668275SEric Cheng /* the group is already bound to a share */
16678275SEric Cheng return (EALREADY);
16688275SEric Cheng }
16698275SEric Cheng
16708400SNicolas.Droux@Sun.COM /*
16718400SNicolas.Droux@Sun.COM * If we are adding a group 0 to a share, this
16728400SNicolas.Droux@Sun.COM * is not correct.
16738400SNicolas.Droux@Sun.COM */
16748400SNicolas.Droux@Sun.COM ASSERT(rg->gindex != 0);
16758400SNicolas.Droux@Sun.COM
16768275SEric Cheng nxge = rg->nxgep;
16778275SEric Cheng vr = shp->vrp;
16788275SEric Cheng
16798275SEric Cheng switch (rg->type) {
16808275SEric Cheng case MAC_RING_TYPE_RX:
16818275SEric Cheng /*
16828275SEric Cheng * Make sure that the group has the right rings associated
16838275SEric Cheng * for the share. In version 1.0, we may only give a VR
16848275SEric Cheng * 2 RDCs. Not only that, but the HV has statically
16858275SEric Cheng * assigned the channels like so:
16868275SEric Cheng * VR0: RDC0 & RDC1
16878275SEric Cheng * VR1: RDC2 & RDC3, etc.
16888275SEric Cheng */
16898275SEric Cheng group = nxge->rx_set.group[rg->gindex];
16908275SEric Cheng
16918275SEric Cheng if (group->count > 2) {
16928275SEric Cheng /* a share can have at most 2 rings */
16938275SEric Cheng return (EINVAL);
16948275SEric Cheng }
16958275SEric Cheng
16968275SEric Cheng for (i = 0; i < NXGE_MAX_RDCS; i++) {
16978275SEric Cheng if (group->map & (1 << i)) {
16988275SEric Cheng if ((i != shp->index * 2) &&
16998275SEric Cheng (i != (shp->index * 2 + 1))) {
17008275SEric Cheng /*
17018275SEric Cheng * A group with invalid rings was
17028275SEric Cheng * attempted to bind to this share
17038275SEric Cheng */
17048275SEric Cheng return (EINVAL);
17058275SEric Cheng }
17068275SEric Cheng }
17078275SEric Cheng }
17088275SEric Cheng
17098275SEric Cheng rg->sindex = vr->region;
17108275SEric Cheng vr->rdc_tbl = rg->rdctbl;
17118275SEric Cheng shp->rxgroup = vr->rdc_tbl;
17128275SEric Cheng break;
17138275SEric Cheng
17148275SEric Cheng case MAC_RING_TYPE_TX:
17158275SEric Cheng /*
17168275SEric Cheng * Make sure that the group has the right rings associated
17178275SEric Cheng * for the share. In version 1.0, we may only give a VR
17188275SEric Cheng * 2 TDCs. Not only that, but the HV has statically
17198275SEric Cheng * assigned the channels like so:
17208275SEric Cheng * VR0: TDC0 & TDC1
17218275SEric Cheng * VR1: TDC2 & TDC3, etc.
17228275SEric Cheng */
17238275SEric Cheng group = nxge->tx_set.group[rg->gindex];
17248275SEric Cheng
17258275SEric Cheng if (group->count > 2) {
17268275SEric Cheng /* a share can have at most 2 rings */
17278275SEric Cheng return (EINVAL);
17288275SEric Cheng }
17298275SEric Cheng
17308275SEric Cheng for (i = 0; i < NXGE_MAX_TDCS; i++) {
17318275SEric Cheng if (group->map & (1 << i)) {
17328275SEric Cheng if ((i != shp->index * 2) &&
17338275SEric Cheng (i != (shp->index * 2 + 1))) {
17348275SEric Cheng /*
17358275SEric Cheng * A group with invalid rings was
17368275SEric Cheng * attempted to bind to this share
17378275SEric Cheng */
17388275SEric Cheng return (EINVAL);
17398275SEric Cheng }
17408275SEric Cheng }
17418275SEric Cheng }
17428275SEric Cheng
17438275SEric Cheng vr->tdc_tbl = nxge->pt_config.hw_config.def_mac_txdma_grpid +
17448275SEric Cheng rg->gindex;
17458275SEric Cheng rg->sindex = vr->region;
17468275SEric Cheng break;
17478275SEric Cheng }
17488275SEric Cheng return (0);
17498275SEric Cheng }
17508275SEric Cheng
17518275SEric Cheng int
nxge_hio_share_rem_group(mac_share_handle_t shandle,mac_group_driver_t ghandle)17528275SEric Cheng nxge_hio_share_rem_group(mac_share_handle_t shandle,
17538275SEric Cheng mac_group_driver_t ghandle)
17548275SEric Cheng {
17558275SEric Cheng nxge_share_handle_t *shp = (nxge_share_handle_t *)shandle;
17568275SEric Cheng nxge_ring_group_t *group = (nxge_ring_group_t *)ghandle;
17578275SEric Cheng nxge_hio_vr_t *vr; /* The Virtualization Region */
17588275SEric Cheng int rv = 0;
17598275SEric Cheng
17608275SEric Cheng vr = shp->vrp;
17618275SEric Cheng
17628275SEric Cheng switch (group->type) {
17638275SEric Cheng case MAC_RING_TYPE_RX:
17648275SEric Cheng group->sindex = 0;
17658275SEric Cheng vr->rdc_tbl = 0;
17668275SEric Cheng shp->rxgroup = 0;
17678275SEric Cheng break;
17688275SEric Cheng
17698275SEric Cheng case MAC_RING_TYPE_TX:
17708275SEric Cheng group->sindex = 0;
17718275SEric Cheng vr->tdc_tbl = 0;
17728275SEric Cheng break;
17738275SEric Cheng }
17748275SEric Cheng
17758275SEric Cheng return (rv);
17768275SEric Cheng }
17778275SEric Cheng
17788275SEric Cheng int
nxge_hio_share_bind(mac_share_handle_t shandle,uint64_t cookie,uint64_t * rcookie)17798275SEric Cheng nxge_hio_share_bind(mac_share_handle_t shandle, uint64_t cookie,
17808275SEric Cheng uint64_t *rcookie)
17818275SEric Cheng {
17828275SEric Cheng nxge_t *nxge;
17838275SEric Cheng nxge_share_handle_t *shp = (nxge_share_handle_t *)shandle;
17848275SEric Cheng nxge_hio_vr_t *vr;
17858275SEric Cheng uint64_t rmap, tmap, hv_rmap, hv_tmap;
17868275SEric Cheng int rv;
17878275SEric Cheng
178811878SVenu.Iyer@Sun.COM ASSERT(shp != NULL);
178911878SVenu.Iyer@Sun.COM ASSERT(shp->nxgep != NULL);
179011878SVenu.Iyer@Sun.COM ASSERT(shp->vrp != NULL);
179111878SVenu.Iyer@Sun.COM
17928275SEric Cheng nxge = shp->nxgep;
17938275SEric Cheng vr = (nxge_hio_vr_t *)shp->vrp;
17948275SEric Cheng
17958275SEric Cheng /*
17968275SEric Cheng * Add resources to the share.
17978275SEric Cheng * For each DMA channel associated with the VR, bind its resources
17988275SEric Cheng * to the VR.
17998275SEric Cheng */
18008275SEric Cheng tmap = 0;
18018275SEric Cheng rv = nxge_hio_addres(vr, MAC_RING_TYPE_TX, &tmap);
18028275SEric Cheng if (rv != 0) {
18038275SEric Cheng return (rv);
18048275SEric Cheng }
18058275SEric Cheng
18068275SEric Cheng rmap = 0;
18078275SEric Cheng rv = nxge_hio_addres(vr, MAC_RING_TYPE_RX, &rmap);
18088275SEric Cheng if (rv != 0) {
18098275SEric Cheng nxge_hio_remres(vr, MAC_RING_TYPE_TX, tmap);
18108275SEric Cheng return (rv);
18118275SEric Cheng }
18128275SEric Cheng
18138275SEric Cheng /*
18148275SEric Cheng * Ask the Hypervisor to set up the VR and allocate slots for
18158275SEric Cheng * each rings associated with the VR.
18168275SEric Cheng */
18178275SEric Cheng hv_tmap = hv_rmap = 0;
18188275SEric Cheng if ((rv = nxge_hio_share_assign(nxge, cookie,
18198275SEric Cheng &hv_tmap, &hv_rmap, vr))) {
18208275SEric Cheng nxge_hio_remres(vr, MAC_RING_TYPE_TX, tmap);
18218275SEric Cheng nxge_hio_remres(vr, MAC_RING_TYPE_RX, rmap);
18228275SEric Cheng return (rv);
18238275SEric Cheng }
18248275SEric Cheng
18258275SEric Cheng shp->active = B_TRUE;
18268275SEric Cheng shp->tmap = hv_tmap;
18278275SEric Cheng shp->rmap = hv_rmap;
18288275SEric Cheng
18298275SEric Cheng /* high 32 bits are cfg_hdl and low 32 bits are HV cookie */
18308275SEric Cheng *rcookie = (((uint64_t)nxge->niu_cfg_hdl) << 32) | vr->cookie;
18318275SEric Cheng
18328275SEric Cheng return (0);
18338275SEric Cheng }
18348275SEric Cheng
18358275SEric Cheng void
nxge_hio_share_unbind(mac_share_handle_t shandle)18368275SEric Cheng nxge_hio_share_unbind(mac_share_handle_t shandle)
18378275SEric Cheng {
18386495Sspeer nxge_share_handle_t *shp = (nxge_share_handle_t *)shandle;
18396495Sspeer
18406495Sspeer /*
18416495Sspeer * First, unassign the VR (take it back),
18426495Sspeer * so we can enable interrupts again.
18436495Sspeer */
18448275SEric Cheng nxge_hio_share_unassign(shp->vrp);
18456495Sspeer
18466495Sspeer /*
18476495Sspeer * Free Ring Resources for TX and RX
18486495Sspeer */
18497755SMisaki.Kataoka@Sun.COM nxge_hio_remres(shp->vrp, MAC_RING_TYPE_TX, shp->tmap);
18507755SMisaki.Kataoka@Sun.COM nxge_hio_remres(shp->vrp, MAC_RING_TYPE_RX, shp->rmap);
18516495Sspeer }
18526495Sspeer
18536495Sspeer
18546495Sspeer /*
18556495Sspeer * nxge_hio_vr_share
18566495Sspeer *
18576495Sspeer * Find an unused Virtualization Region (VR).
18586495Sspeer *
18596495Sspeer * Arguments:
18606495Sspeer * nxge
18616495Sspeer *
18626495Sspeer * Notes:
18636495Sspeer *
18646495Sspeer * Context:
18656495Sspeer * Service domain
18666495Sspeer */
18677755SMisaki.Kataoka@Sun.COM nxge_hio_vr_t *
nxge_hio_vr_share(nxge_t * nxge)18686495Sspeer nxge_hio_vr_share(
18696495Sspeer nxge_t *nxge)
18706495Sspeer {
18716495Sspeer nxge_hio_data_t *nhd = (nxge_hio_data_t *)nxge->nxge_hw_p->hio;
18726495Sspeer nxge_hio_vr_t *vr;
18736495Sspeer
18746495Sspeer int first, limit, region;
18756495Sspeer
18766495Sspeer NXGE_DEBUG_MSG((nxge, HIO_CTL, "==> nxge_hio_vr_share"));
18776495Sspeer
18786495Sspeer MUTEX_ENTER(&nhd->lock);
18796495Sspeer
18807755SMisaki.Kataoka@Sun.COM if (nhd->vrs == 0) {
18816495Sspeer MUTEX_EXIT(&nhd->lock);
18826495Sspeer return (0);
18836495Sspeer }
18846495Sspeer
18856495Sspeer /* Find an empty virtual region (VR). */
18866495Sspeer if (nxge->function_num == 0) {
18876495Sspeer // FUNC0_VIR0 'belongs' to NIU port 0.
18886495Sspeer first = FUNC0_VIR1;
18896495Sspeer limit = FUNC2_VIR0;
18906495Sspeer } else if (nxge->function_num == 1) {
18916495Sspeer // FUNC2_VIR0 'belongs' to NIU port 1.
18926495Sspeer first = FUNC2_VIR1;
18936495Sspeer limit = FUNC_VIR_MAX;
18946495Sspeer } else {
18956495Sspeer cmn_err(CE_WARN,
18966495Sspeer "Shares not supported on function(%d) at this time.\n",
18976495Sspeer nxge->function_num);
18986495Sspeer }
18996495Sspeer
19006495Sspeer for (region = first; region < limit; region++) {
19016495Sspeer if (nhd->vr[region].nxge == 0)
19026495Sspeer break;
19036495Sspeer }
19046495Sspeer
19056495Sspeer if (region == limit) {
19066495Sspeer MUTEX_EXIT(&nhd->lock);
19076495Sspeer return (0);
19086495Sspeer }
19096495Sspeer
19106495Sspeer vr = &nhd->vr[region];
19116495Sspeer vr->nxge = (uintptr_t)nxge;
19126495Sspeer vr->region = (uintptr_t)region;
19136495Sspeer
19147755SMisaki.Kataoka@Sun.COM nhd->vrs--;
19156495Sspeer
19166495Sspeer MUTEX_EXIT(&nhd->lock);
19176495Sspeer
19186495Sspeer NXGE_DEBUG_MSG((nxge, HIO_CTL, "<== nxge_hio_vr_share"));
19196495Sspeer
19207755SMisaki.Kataoka@Sun.COM return (vr);
19216495Sspeer }
19226495Sspeer
19236495Sspeer void
nxge_hio_unshare(nxge_hio_vr_t * vr)19246495Sspeer nxge_hio_unshare(
19257755SMisaki.Kataoka@Sun.COM nxge_hio_vr_t *vr)
19266495Sspeer {
19276495Sspeer nxge_t *nxge = (nxge_t *)vr->nxge;
19286495Sspeer nxge_hio_data_t *nhd;
19296495Sspeer
19306495Sspeer vr_region_t region;
19316495Sspeer
19326495Sspeer NXGE_DEBUG_MSG((nxge, HIO_CTL, "==> nxge_hio_unshare"));
19336495Sspeer
19346495Sspeer if (!nxge) {
19357950SMichael.Speer@Sun.COM NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL, "nxge_hio_unshare: "
19366495Sspeer "vr->nxge is NULL"));
19376495Sspeer return;
19386495Sspeer }
19396495Sspeer
19406495Sspeer /*
19416495Sspeer * This function is no longer called, but I will keep it
19426495Sspeer * here in case we want to revisit this topic in the future.
19436495Sspeer *
19446495Sspeer * nxge_hio_hostinfo_uninit(nxge, vr);
19456495Sspeer */
19468275SEric Cheng
19478275SEric Cheng /*
19488275SEric Cheng * XXX: This is done by ms_sremove?
19498275SEric Cheng * (void) nxge_fzc_rdc_tbl_unbind(nxge, vr->rdc_tbl);
19508275SEric Cheng */
19516495Sspeer
19526495Sspeer nhd = (nxge_hio_data_t *)nxge->nxge_hw_p->hio;
19536495Sspeer
19546495Sspeer MUTEX_ENTER(&nhd->lock);
19556495Sspeer
19566495Sspeer region = vr->region;
19576495Sspeer (void) memset(vr, 0, sizeof (*vr));
19586495Sspeer vr->region = region;
19596495Sspeer
19607755SMisaki.Kataoka@Sun.COM nhd->vrs++;
19616495Sspeer
19626495Sspeer MUTEX_EXIT(&nhd->lock);
19636495Sspeer
19646495Sspeer NXGE_DEBUG_MSG((nxge, HIO_CTL, "<== nxge_hio_unshare"));
19656495Sspeer }
19666495Sspeer
19676495Sspeer int
nxge_hio_addres(nxge_hio_vr_t * vr,mac_ring_type_t type,uint64_t * map)196810577SMichael.Speer@Sun.COM nxge_hio_addres(nxge_hio_vr_t *vr, mac_ring_type_t type, uint64_t *map)
19696495Sspeer {
197011878SVenu.Iyer@Sun.COM nxge_t *nxge;
19718275SEric Cheng nxge_grp_t *group;
19728275SEric Cheng int groupid;
197310577SMichael.Speer@Sun.COM int i, rv = 0;
19748275SEric Cheng int max_dcs;
19756495Sspeer
197611878SVenu.Iyer@Sun.COM ASSERT(vr != NULL);
197711878SVenu.Iyer@Sun.COM ASSERT(vr->nxge != NULL);
197811878SVenu.Iyer@Sun.COM nxge = (nxge_t *)vr->nxge;
19796495Sspeer
198011878SVenu.Iyer@Sun.COM NXGE_DEBUG_MSG((nxge, HIO_CTL, "==> nxge_hio_addres"));
19816495Sspeer
19828275SEric Cheng /*
19838275SEric Cheng * For each ring associated with the group, add the resources
19848275SEric Cheng * to the group and bind.
19858275SEric Cheng */
19868275SEric Cheng max_dcs = (type == MAC_RING_TYPE_TX) ? NXGE_MAX_TDCS : NXGE_MAX_RDCS;
19878275SEric Cheng if (type == MAC_RING_TYPE_TX) {
19888275SEric Cheng /* set->group is an array of group indexed by a port group id */
19898275SEric Cheng groupid = vr->tdc_tbl -
19908275SEric Cheng nxge->pt_config.hw_config.def_mac_txdma_grpid;
19918275SEric Cheng group = nxge->tx_set.group[groupid];
19928275SEric Cheng } else {
19938275SEric Cheng /* set->group is an array of group indexed by a port group id */
19948275SEric Cheng groupid = vr->rdc_tbl -
19958275SEric Cheng nxge->pt_config.hw_config.def_mac_rxdma_grpid;
19968275SEric Cheng group = nxge->rx_set.group[groupid];
19978275SEric Cheng }
19988275SEric Cheng
199911878SVenu.Iyer@Sun.COM ASSERT(group != NULL);
200011878SVenu.Iyer@Sun.COM
20018275SEric Cheng if (group->map == 0) {
20028275SEric Cheng NXGE_DEBUG_MSG((nxge, HIO_CTL, "There is no rings associated "
20038275SEric Cheng "with this VR"));
20048275SEric Cheng return (EINVAL);
20058275SEric Cheng }
20068275SEric Cheng
20078275SEric Cheng for (i = 0; i < max_dcs; i++) {
20088275SEric Cheng if (group->map & (1 << i)) {
20098275SEric Cheng if ((rv = nxge_hio_dc_share(nxge, vr, type, i)) < 0) {
20108275SEric Cheng if (*map == 0) /* Couldn't get even one DC. */
20118275SEric Cheng return (-rv);
20128275SEric Cheng else
20138275SEric Cheng break;
20148275SEric Cheng }
20158275SEric Cheng *map |= (1 << i);
20166495Sspeer }
20176495Sspeer }
20186495Sspeer
201910577SMichael.Speer@Sun.COM if ((*map == 0) || (rv != 0)) {
202010577SMichael.Speer@Sun.COM NXGE_DEBUG_MSG((nxge, HIO_CTL,
202110577SMichael.Speer@Sun.COM "<== nxge_hio_addres: rv(%x)", rv));
202210577SMichael.Speer@Sun.COM return (EIO);
202310577SMichael.Speer@Sun.COM }
202410577SMichael.Speer@Sun.COM
20256495Sspeer NXGE_DEBUG_MSG((nxge, HIO_CTL, "<== nxge_hio_addres"));
20266495Sspeer return (0);
20276495Sspeer }
20286495Sspeer
20296495Sspeer /* ARGSUSED */
20306495Sspeer void
nxge_hio_remres(nxge_hio_vr_t * vr,mac_ring_type_t type,res_map_t res_map)20316495Sspeer nxge_hio_remres(
20327755SMisaki.Kataoka@Sun.COM nxge_hio_vr_t *vr,
20336495Sspeer mac_ring_type_t type,
20346495Sspeer res_map_t res_map)
20356495Sspeer {
20366495Sspeer nxge_t *nxge = (nxge_t *)vr->nxge;
20376495Sspeer nxge_grp_t *group;
20386495Sspeer
20396495Sspeer if (!nxge) {
20407950SMichael.Speer@Sun.COM NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL, "nxge_hio_remres: "
20416495Sspeer "vr->nxge is NULL"));
20426495Sspeer return;
20436495Sspeer }
20446495Sspeer
20456495Sspeer NXGE_DEBUG_MSG((nxge, HIO_CTL, "==> nxge_hio_remres(%lx)", res_map));
20466495Sspeer
20478275SEric Cheng /*
20488275SEric Cheng * For each ring bound to the group, remove the DMA resources
20498275SEric Cheng * from the group and unbind.
20508275SEric Cheng */
20516495Sspeer group = (type == MAC_RING_TYPE_TX ? &vr->tx_group : &vr->rx_group);
20526495Sspeer while (group->dc) {
20536495Sspeer nxge_hio_dc_t *dc = group->dc;
20546495Sspeer NXGE_DC_RESET(res_map, dc->page);
20556495Sspeer nxge_hio_dc_unshare(nxge, vr, type, dc->channel);
20566495Sspeer }
20576495Sspeer
20586495Sspeer if (res_map) {
20596495Sspeer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL, "nxge_hio_remres: "
20606495Sspeer "res_map %lx", res_map));
20616495Sspeer }
20626495Sspeer
20636495Sspeer NXGE_DEBUG_MSG((nxge, HIO_CTL, "<== nxge_hio_remres"));
20646495Sspeer }
20656495Sspeer
20666495Sspeer /*
20676495Sspeer * nxge_hio_tdc_share
20686495Sspeer *
20696495Sspeer * Share an unused TDC channel.
20706495Sspeer *
20716495Sspeer * Arguments:
20726495Sspeer * nxge
20736495Sspeer *
20746495Sspeer * Notes:
20756495Sspeer *
20766495Sspeer * A.7.3 Reconfigure Tx DMA channel
20776495Sspeer * Disable TxDMA A.9.6.10
20786495Sspeer * [Rebind TxDMA channel to Port A.9.6.7]
20796495Sspeer *
20806495Sspeer * We don't have to Rebind the TDC to the port - it always already bound.
20816495Sspeer *
20826495Sspeer * Soft Reset TxDMA A.9.6.2
20836495Sspeer *
20846495Sspeer * This procedure will be executed by nxge_init_txdma_channel() in the
20856495Sspeer * guest domain:
20866495Sspeer *
20876495Sspeer * Re-initialize TxDMA A.9.6.8
20886495Sspeer * Reconfigure TxDMA
20896495Sspeer * Enable TxDMA A.9.6.9
20906495Sspeer *
20916495Sspeer * Context:
20926495Sspeer * Service domain
20936495Sspeer */
20946495Sspeer int
nxge_hio_tdc_share(nxge_t * nxge,int channel)20956495Sspeer nxge_hio_tdc_share(
20966495Sspeer nxge_t *nxge,
20976495Sspeer int channel)
20986495Sspeer {
20997812SMichael.Speer@Sun.COM nxge_hio_data_t *nhd = (nxge_hio_data_t *)nxge->nxge_hw_p->hio;
21006495Sspeer nxge_grp_set_t *set = &nxge->tx_set;
21016495Sspeer tx_ring_t *ring;
21026713Sspeer int count;
21036495Sspeer
21046495Sspeer NXGE_DEBUG_MSG((nxge, HIO_CTL, "==> nxge_hio_tdc_share"));
21056495Sspeer
21066495Sspeer /*
21076495Sspeer * Wait until this channel is idle.
21086495Sspeer */
21096495Sspeer ring = nxge->tx_rings->rings[channel];
21109730SMichael.Speer@Sun.COM ASSERT(ring != NULL);
21116713Sspeer
21126713Sspeer (void) atomic_swap_32(&ring->tx_ring_offline, NXGE_TX_RING_OFFLINING);
21136886Sspeer if (ring->tx_ring_busy) {
21146886Sspeer /*
21156886Sspeer * Wait for 30 seconds.
21166886Sspeer */
21176886Sspeer for (count = 30 * 1000; count; count--) {
21186886Sspeer if (ring->tx_ring_offline & NXGE_TX_RING_OFFLINED) {
21196886Sspeer break;
21206886Sspeer }
21216886Sspeer
21226886Sspeer drv_usecwait(1000);
21236495Sspeer }
21246713Sspeer
21256886Sspeer if (count == 0) {
21266886Sspeer (void) atomic_swap_32(&ring->tx_ring_offline,
21276886Sspeer NXGE_TX_RING_ONLINE);
21287950SMichael.Speer@Sun.COM NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
21297950SMichael.Speer@Sun.COM "nxge_hio_tdc_share: "
21306886Sspeer "Tx ring %d was always BUSY", channel));
21316886Sspeer return (-EIO);
21326886Sspeer }
21336886Sspeer } else {
21346713Sspeer (void) atomic_swap_32(&ring->tx_ring_offline,
21356886Sspeer NXGE_TX_RING_OFFLINED);
21366495Sspeer }
21376495Sspeer
21387812SMichael.Speer@Sun.COM MUTEX_ENTER(&nhd->lock);
21397812SMichael.Speer@Sun.COM nxge->tdc_is_shared[channel] = B_TRUE;
21407812SMichael.Speer@Sun.COM MUTEX_EXIT(&nhd->lock);
21417812SMichael.Speer@Sun.COM
21426495Sspeer if (nxge_intr_remove(nxge, VP_BOUND_TX, channel) != NXGE_OK) {
21437950SMichael.Speer@Sun.COM NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL, "nxge_hio_tdc_share: "
21446495Sspeer "Failed to remove interrupt for TxDMA channel %d",
21456495Sspeer channel));
21468275SEric Cheng return (-EINVAL);
21476495Sspeer }
21486495Sspeer
21496495Sspeer /* Disable TxDMA A.9.6.10 */
21506495Sspeer (void) nxge_txdma_channel_disable(nxge, channel);
21516495Sspeer
21526495Sspeer /* The SD is sharing this channel. */
21536495Sspeer NXGE_DC_SET(set->shared.map, channel);
21546495Sspeer set->shared.count++;
21556495Sspeer
21566602Sspeer /* Soft Reset TxDMA A.9.6.2 */
21576602Sspeer nxge_grp_dc_remove(nxge, VP_BOUND_TX, channel);
21586602Sspeer
21596495Sspeer /*
21606495Sspeer * Initialize the DC-specific FZC control registers.
21616495Sspeer * -----------------------------------------------------
21626495Sspeer */
21636495Sspeer if (nxge_init_fzc_tdc(nxge, channel) != NXGE_OK) {
21646495Sspeer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
21657950SMichael.Speer@Sun.COM "nxge_hio_tdc_share: FZC TDC failed: %d", channel));
21666495Sspeer return (-EIO);
21676495Sspeer }
21686495Sspeer
21696495Sspeer NXGE_DEBUG_MSG((nxge, HIO_CTL, "<== nxge_hio_tdc_share"));
21706495Sspeer
21716495Sspeer return (0);
21726495Sspeer }
21736495Sspeer
21746495Sspeer /*
21756495Sspeer * nxge_hio_rdc_share
21766495Sspeer *
21776495Sspeer * Share an unused RDC channel.
21786495Sspeer *
21796495Sspeer * Arguments:
21806495Sspeer * nxge
21816495Sspeer *
21826495Sspeer * Notes:
21836495Sspeer *
21846495Sspeer * This is the latest version of the procedure to
21856495Sspeer * Reconfigure an Rx DMA channel:
21866495Sspeer *
21876495Sspeer * A.6.3 Reconfigure Rx DMA channel
21886495Sspeer * Stop RxMAC A.9.2.6
21896495Sspeer * Drain IPP Port A.9.3.6
21906495Sspeer * Stop and reset RxDMA A.9.5.3
21916495Sspeer *
21926495Sspeer * This procedure will be executed by nxge_init_rxdma_channel() in the
21936495Sspeer * guest domain:
21946495Sspeer *
21956495Sspeer * Initialize RxDMA A.9.5.4
21966495Sspeer * Reconfigure RxDMA
21976495Sspeer * Enable RxDMA A.9.5.5
21986495Sspeer *
21996495Sspeer * We will do this here, since the RDC is a canalis non grata:
22006495Sspeer * Enable RxMAC A.9.2.10
22016495Sspeer *
22026495Sspeer * Context:
22036495Sspeer * Service domain
22046495Sspeer */
22056495Sspeer int
nxge_hio_rdc_share(nxge_t * nxge,nxge_hio_vr_t * vr,int channel)22066495Sspeer nxge_hio_rdc_share(
22076495Sspeer nxge_t *nxge,
22086495Sspeer nxge_hio_vr_t *vr,
22096495Sspeer int channel)
22106495Sspeer {
22116495Sspeer nxge_grp_set_t *set = &nxge->rx_set;
22126495Sspeer nxge_rdc_grp_t *rdc_grp;
22136495Sspeer
22146495Sspeer NXGE_DEBUG_MSG((nxge, HIO_CTL, "==> nxge_hio_rdc_share"));
22156495Sspeer
22166495Sspeer /* Disable interrupts. */
22176495Sspeer if (nxge_intr_remove(nxge, VP_BOUND_RX, channel) != NXGE_OK) {
22187950SMichael.Speer@Sun.COM NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL, "nxge_hio_rdc_share: "
22196495Sspeer "Failed to remove interrupt for RxDMA channel %d",
22206495Sspeer channel));
22216495Sspeer return (NXGE_ERROR);
22226495Sspeer }
22236495Sspeer
22246495Sspeer /* Stop RxMAC = A.9.2.6 */
22256495Sspeer if (nxge_rx_mac_disable(nxge) != NXGE_OK) {
22266495Sspeer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL, "nxge_hio_rdc_share: "
22276495Sspeer "Failed to disable RxMAC"));
22286495Sspeer }
22296495Sspeer
22306495Sspeer /* Drain IPP Port = A.9.3.6 */
22316495Sspeer (void) nxge_ipp_drain(nxge);
22326495Sspeer
22336495Sspeer /* Stop and reset RxDMA = A.9.5.3 */
22346495Sspeer // De-assert EN: RXDMA_CFIG1[31] = 0 (DMC+00000 )
22356495Sspeer if (nxge_disable_rxdma_channel(nxge, channel) != NXGE_OK) {
22366495Sspeer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL, "nxge_hio_rdc_share: "
22376495Sspeer "Failed to disable RxDMA channel %d", channel));
22386495Sspeer }
22396495Sspeer
22406495Sspeer /* The SD is sharing this channel. */
22416495Sspeer NXGE_DC_SET(set->shared.map, channel);
22426495Sspeer set->shared.count++;
22436495Sspeer
22446602Sspeer // Assert RST: RXDMA_CFIG1[30] = 1
22456602Sspeer nxge_grp_dc_remove(nxge, VP_BOUND_RX, channel);
22466602Sspeer
22476495Sspeer /*
22486495Sspeer * The guest domain will reconfigure the RDC later.
22496495Sspeer *
22506495Sspeer * But in the meantime, we must re-enable the Rx MAC so
22516495Sspeer * that we can start receiving packets again on the
22526495Sspeer * remaining RDCs:
22536495Sspeer *
22546495Sspeer * Enable RxMAC = A.9.2.10
22556495Sspeer */
22566495Sspeer if (nxge_rx_mac_enable(nxge) != NXGE_OK) {
22576495Sspeer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
22587950SMichael.Speer@Sun.COM "nxge_hio_rdc_share: Rx MAC still disabled"));
22596495Sspeer }
22606495Sspeer
22616495Sspeer /*
22626495Sspeer * Initialize the DC-specific FZC control registers.
22636495Sspeer * -----------------------------------------------------
22646495Sspeer */
22656495Sspeer if (nxge_init_fzc_rdc(nxge, channel) != NXGE_OK) {
22666495Sspeer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
22677950SMichael.Speer@Sun.COM "nxge_hio_rdc_share: RZC RDC failed: %ld", channel));
22686495Sspeer return (-EIO);
22696495Sspeer }
22706495Sspeer
22716495Sspeer /*
22729047SMichael.Speer@Sun.COM * Update the RDC group.
22736495Sspeer */
22746495Sspeer rdc_grp = &nxge->pt_config.rdc_grps[vr->rdc_tbl];
22756495Sspeer NXGE_DC_SET(rdc_grp->map, channel);
22766495Sspeer
22776495Sspeer NXGE_DEBUG_MSG((nxge, HIO_CTL, "<== nxge_hio_rdc_share"));
22786495Sspeer
22796495Sspeer return (0);
22806495Sspeer }
22816495Sspeer
22826495Sspeer /*
22836495Sspeer * nxge_hio_dc_share
22846495Sspeer *
22856495Sspeer * Share a DMA channel with a guest domain.
22866495Sspeer *
22876495Sspeer * Arguments:
22886495Sspeer * nxge
22896495Sspeer * vr The VR that <channel> will belong to.
22906495Sspeer * type Tx or Rx.
22918275SEric Cheng * channel Channel to share
22926495Sspeer *
22936495Sspeer * Notes:
22946495Sspeer *
22956495Sspeer * Context:
22966495Sspeer * Service domain
22976495Sspeer */
22986495Sspeer int
nxge_hio_dc_share(nxge_t * nxge,nxge_hio_vr_t * vr,mac_ring_type_t type,int channel)22996495Sspeer nxge_hio_dc_share(
23006495Sspeer nxge_t *nxge,
23016495Sspeer nxge_hio_vr_t *vr,
23028275SEric Cheng mac_ring_type_t type,
23038275SEric Cheng int channel)
23046495Sspeer {
23056495Sspeer nxge_hio_data_t *nhd = (nxge_hio_data_t *)nxge->nxge_hw_p->hio;
23066495Sspeer nxge_hio_dc_t *dc;
23076495Sspeer nxge_grp_t *group;
23086495Sspeer int slot;
23096495Sspeer
23106495Sspeer NXGE_DEBUG_MSG((nxge, HIO_CTL, "==> nxge_hio_dc_share(%cdc %d",
23116495Sspeer type == MAC_RING_TYPE_TX ? 't' : 'r', channel));
23126495Sspeer
23136495Sspeer
23146495Sspeer /* -------------------------------------------------- */
23156495Sspeer slot = (type == MAC_RING_TYPE_TX) ?
23166495Sspeer nxge_hio_tdc_share(nxge, channel) :
23176495Sspeer nxge_hio_rdc_share(nxge, vr, channel);
23186495Sspeer
23196495Sspeer if (slot < 0) {
23206495Sspeer if (type == MAC_RING_TYPE_RX) {
23218275SEric Cheng nxge_hio_rdc_unshare(nxge, vr->rdc_tbl, channel);
23226495Sspeer } else {
23238275SEric Cheng nxge_hio_tdc_unshare(nxge, vr->tdc_tbl, channel);
23246495Sspeer }
23256495Sspeer return (slot);
23266495Sspeer }
23276495Sspeer
23286495Sspeer MUTEX_ENTER(&nhd->lock);
23296495Sspeer
23306495Sspeer /*
23316495Sspeer * Tag this channel.
23326495Sspeer * --------------------------------------------------
23336495Sspeer */
23346495Sspeer dc = type == MAC_RING_TYPE_TX ? &nhd->tdc[channel] : &nhd->rdc[channel];
23356495Sspeer
23366495Sspeer dc->vr = vr;
23376495Sspeer dc->channel = (nxge_channel_t)channel;
23386495Sspeer
23396495Sspeer MUTEX_EXIT(&nhd->lock);
23406495Sspeer
23416495Sspeer /*
23426495Sspeer * vr->[t|r]x_group is used by the service domain to
23436495Sspeer * keep track of its shared DMA channels.
23446495Sspeer */
23456495Sspeer MUTEX_ENTER(&nxge->group_lock);
23466495Sspeer group = (type == MAC_RING_TYPE_TX ? &vr->tx_group : &vr->rx_group);
23476495Sspeer
23487755SMisaki.Kataoka@Sun.COM dc->group = group;
23496495Sspeer /* Initialize <group>, if necessary */
23506495Sspeer if (group->count == 0) {
23516495Sspeer group->nxge = nxge;
23526495Sspeer group->type = (type == MAC_RING_TYPE_TX) ?
23536495Sspeer VP_BOUND_TX : VP_BOUND_RX;
23546495Sspeer group->sequence = nhd->sequence++;
23556495Sspeer group->active = B_TRUE;
23566495Sspeer }
23576495Sspeer
23586495Sspeer MUTEX_EXIT(&nxge->group_lock);
23596495Sspeer
23606495Sspeer NXGE_ERROR_MSG((nxge, HIO_CTL,
23616495Sspeer "DC share: %cDC %d was assigned to slot %d",
23626495Sspeer type == MAC_RING_TYPE_TX ? 'T' : 'R', channel, slot));
23636495Sspeer
23646495Sspeer nxge_grp_dc_append(nxge, group, dc);
23656495Sspeer
23666495Sspeer NXGE_DEBUG_MSG((nxge, HIO_CTL, "<== nxge_hio_dc_share"));
23676495Sspeer
23686495Sspeer return (0);
23696495Sspeer }
23706495Sspeer
23716495Sspeer /*
23726495Sspeer * nxge_hio_tdc_unshare
23736495Sspeer *
23746495Sspeer * Unshare a TDC.
23756495Sspeer *
23766495Sspeer * Arguments:
23776495Sspeer * nxge
23786495Sspeer * channel The channel to unshare (add again).
23796495Sspeer *
23806495Sspeer * Notes:
23816495Sspeer *
23826495Sspeer * Context:
23836495Sspeer * Service domain
23846495Sspeer */
23856495Sspeer void
nxge_hio_tdc_unshare(nxge_t * nxge,int dev_grpid,int channel)23866495Sspeer nxge_hio_tdc_unshare(
23876495Sspeer nxge_t *nxge,
23888275SEric Cheng int dev_grpid,
23896495Sspeer int channel)
23906495Sspeer {
23916495Sspeer nxge_grp_set_t *set = &nxge->tx_set;
23928275SEric Cheng nxge_grp_t *group;
23938275SEric Cheng int grpid;
23946495Sspeer
23956495Sspeer NXGE_DEBUG_MSG((nxge, HIO_CTL, "==> nxge_hio_tdc_unshare"));
23966495Sspeer
23976495Sspeer NXGE_DC_RESET(set->shared.map, channel);
23986495Sspeer set->shared.count--;
23996495Sspeer
24008275SEric Cheng grpid = dev_grpid - nxge->pt_config.hw_config.def_mac_txdma_grpid;
24018275SEric Cheng group = set->group[grpid];
24028275SEric Cheng
24037755SMisaki.Kataoka@Sun.COM if ((nxge_grp_dc_add(nxge, group, VP_BOUND_TX, channel))) {
24046495Sspeer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL, "nxge_hio_tdc_unshare: "
24056495Sspeer "Failed to initialize TxDMA channel %d", channel));
24066495Sspeer return;
24076495Sspeer }
24086495Sspeer
24096495Sspeer /* Re-add this interrupt. */
24106495Sspeer if (nxge_intr_add(nxge, VP_BOUND_TX, channel) != NXGE_OK) {
24116495Sspeer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL, "nxge_hio_tdc_unshare: "
24126495Sspeer "Failed to add interrupt for TxDMA channel %d", channel));
24136495Sspeer }
24146495Sspeer
24156495Sspeer NXGE_DEBUG_MSG((nxge, HIO_CTL, "<== nxge_hio_tdc_unshare"));
24166495Sspeer }
24176495Sspeer
24186495Sspeer /*
24196495Sspeer * nxge_hio_rdc_unshare
24206495Sspeer *
24216495Sspeer * Unshare an RDC: add it to the SD's RDC groups (tables).
24226495Sspeer *
24236495Sspeer * Arguments:
24246495Sspeer * nxge
24256495Sspeer * channel The channel to unshare (add again).
24266495Sspeer *
24276495Sspeer * Notes:
24286495Sspeer *
24296495Sspeer * Context:
24306495Sspeer * Service domain
24316495Sspeer */
24326495Sspeer void
nxge_hio_rdc_unshare(nxge_t * nxge,int dev_grpid,int channel)24336495Sspeer nxge_hio_rdc_unshare(
24346495Sspeer nxge_t *nxge,
24358275SEric Cheng int dev_grpid,
24366495Sspeer int channel)
24376495Sspeer {
24388275SEric Cheng nxge_grp_set_t *set = &nxge->rx_set;
24398275SEric Cheng nxge_grp_t *group;
24408275SEric Cheng int grpid;
244111878SVenu.Iyer@Sun.COM int i;
24426495Sspeer
24436495Sspeer NXGE_DEBUG_MSG((nxge, HIO_CTL, "==> nxge_hio_rdc_unshare"));
24446495Sspeer
24456495Sspeer /* Stop RxMAC = A.9.2.6 */
24466495Sspeer if (nxge_rx_mac_disable(nxge) != NXGE_OK) {
24476495Sspeer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL, "nxge_hio_rdc_unshare: "
24486495Sspeer "Failed to disable RxMAC"));
24496495Sspeer }
24506495Sspeer
24516495Sspeer /* Drain IPP Port = A.9.3.6 */
24526495Sspeer (void) nxge_ipp_drain(nxge);
24536495Sspeer
24546495Sspeer /* Stop and reset RxDMA = A.9.5.3 */
24556495Sspeer // De-assert EN: RXDMA_CFIG1[31] = 0 (DMC+00000 )
24566495Sspeer if (nxge_disable_rxdma_channel(nxge, channel) != NXGE_OK) {
24576495Sspeer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL, "nxge_hio_rdc_unshare: "
24586495Sspeer "Failed to disable RxDMA channel %d", channel));
24596495Sspeer }
24606495Sspeer
24616495Sspeer NXGE_DC_RESET(set->shared.map, channel);
24626495Sspeer set->shared.count--;
24636495Sspeer
24648275SEric Cheng grpid = dev_grpid - nxge->pt_config.hw_config.def_mac_rxdma_grpid;
24658275SEric Cheng group = set->group[grpid];
24668275SEric Cheng
24676495Sspeer /*
24686495Sspeer * Assert RST: RXDMA_CFIG1[30] = 1
24696495Sspeer *
24706495Sspeer * Initialize RxDMA A.9.5.4
24716495Sspeer * Reconfigure RxDMA
24726495Sspeer * Enable RxDMA A.9.5.5
24736495Sspeer */
24747755SMisaki.Kataoka@Sun.COM if ((nxge_grp_dc_add(nxge, group, VP_BOUND_RX, channel))) {
24756495Sspeer /* Be sure to re-enable the RX MAC. */
24766495Sspeer if (nxge_rx_mac_enable(nxge) != NXGE_OK) {
24776495Sspeer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
24788275SEric Cheng "nxge_hio_rdc_share: Rx MAC still disabled"));
24796495Sspeer }
24806495Sspeer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL, "nxge_hio_rdc_unshare: "
24816495Sspeer "Failed to initialize RxDMA channel %d", channel));
24826495Sspeer return;
24836495Sspeer }
24846495Sspeer
24856495Sspeer /*
24866495Sspeer * Enable RxMAC = A.9.2.10
24876495Sspeer */
24886495Sspeer if (nxge_rx_mac_enable(nxge) != NXGE_OK) {
24896495Sspeer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
24908275SEric Cheng "nxge_hio_rdc_share: Rx MAC still disabled"));
24916495Sspeer return;
24926495Sspeer }
24936495Sspeer
24946495Sspeer /* Re-add this interrupt. */
24956495Sspeer if (nxge_intr_add(nxge, VP_BOUND_RX, channel) != NXGE_OK) {
24966495Sspeer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
24977950SMichael.Speer@Sun.COM "nxge_hio_rdc_unshare: Failed to add interrupt for "
24986495Sspeer "RxDMA CHANNEL %d", channel));
24996495Sspeer }
25006495Sspeer
25016495Sspeer NXGE_DEBUG_MSG((nxge, HIO_CTL, "<== nxge_hio_rdc_unshare"));
250211878SVenu.Iyer@Sun.COM
250311878SVenu.Iyer@Sun.COM for (i = 0; i < NXGE_MAX_RDCS; i++) {
250411878SVenu.Iyer@Sun.COM if (nxge->rx_ring_handles[i].channel == channel) {
2505*11881SVenu.Iyer@Sun.COM (void) nxge_rx_ring_start(
250611878SVenu.Iyer@Sun.COM (mac_ring_driver_t)&nxge->rx_ring_handles[i],
250711878SVenu.Iyer@Sun.COM nxge->rx_ring_handles[i].ring_gen_num);
250811878SVenu.Iyer@Sun.COM }
250911878SVenu.Iyer@Sun.COM }
25106495Sspeer }
25116495Sspeer
25126495Sspeer /*
25136495Sspeer * nxge_hio_dc_unshare
25146495Sspeer *
25156495Sspeer * Unshare (reuse) a DMA channel.
25166495Sspeer *
25176495Sspeer * Arguments:
25186495Sspeer * nxge
25196495Sspeer * vr The VR that <channel> belongs to.
25206495Sspeer * type Tx or Rx.
25216495Sspeer * channel The DMA channel to reuse.
25226495Sspeer *
25236495Sspeer * Notes:
25246495Sspeer *
25256495Sspeer * Context:
25266495Sspeer * Service domain
25276495Sspeer */
25286495Sspeer void
nxge_hio_dc_unshare(nxge_t * nxge,nxge_hio_vr_t * vr,mac_ring_type_t type,int channel)25296495Sspeer nxge_hio_dc_unshare(
25306495Sspeer nxge_t *nxge,
25316495Sspeer nxge_hio_vr_t *vr,
25326495Sspeer mac_ring_type_t type,
25336495Sspeer int channel)
25346495Sspeer {
25356495Sspeer nxge_grp_t *group;
25366495Sspeer nxge_hio_dc_t *dc;
25376495Sspeer
25386495Sspeer NXGE_DEBUG_MSG((nxge, HIO_CTL, "==> nxge_hio_dc_unshare(%cdc %d)",
25396495Sspeer type == MAC_RING_TYPE_TX ? 't' : 'r', channel));
25406495Sspeer
25416495Sspeer /* Unlink the channel from its group. */
25426495Sspeer /* -------------------------------------------------- */
25436495Sspeer group = (type == MAC_RING_TYPE_TX) ? &vr->tx_group : &vr->rx_group;
25446602Sspeer NXGE_DC_RESET(group->map, channel);
25456495Sspeer if ((dc = nxge_grp_dc_unlink(nxge, group, channel)) == 0) {
25466495Sspeer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
25477950SMichael.Speer@Sun.COM "nxge_hio_dc_unshare(%d) failed", channel));
25486495Sspeer return;
25496495Sspeer }
25506495Sspeer
25516495Sspeer dc->vr = 0;
25526495Sspeer dc->cookie = 0;
25536495Sspeer
25546495Sspeer if (type == MAC_RING_TYPE_RX) {
25558275SEric Cheng nxge_hio_rdc_unshare(nxge, vr->rdc_tbl, channel);
25566495Sspeer } else {
25578275SEric Cheng nxge_hio_tdc_unshare(nxge, vr->tdc_tbl, channel);
25586495Sspeer }
25596495Sspeer
25606495Sspeer NXGE_DEBUG_MSG((nxge, HIO_CTL, "<== nxge_hio_dc_unshare"));
25616495Sspeer }
25626495Sspeer
25638400SNicolas.Droux@Sun.COM
25648400SNicolas.Droux@Sun.COM /*
25658400SNicolas.Droux@Sun.COM * nxge_hio_rxdma_bind_intr():
25668400SNicolas.Droux@Sun.COM *
25678400SNicolas.Droux@Sun.COM * For the guest domain driver, need to bind the interrupt group
25688400SNicolas.Droux@Sun.COM * and state to the rx_rcr_ring_t.
25698400SNicolas.Droux@Sun.COM */
25708400SNicolas.Droux@Sun.COM
25718400SNicolas.Droux@Sun.COM int
nxge_hio_rxdma_bind_intr(nxge_t * nxge,rx_rcr_ring_t * ring,int channel)25728400SNicolas.Droux@Sun.COM nxge_hio_rxdma_bind_intr(nxge_t *nxge, rx_rcr_ring_t *ring, int channel)
25738400SNicolas.Droux@Sun.COM {
25748400SNicolas.Droux@Sun.COM nxge_hio_dc_t *dc;
25758400SNicolas.Droux@Sun.COM nxge_ldgv_t *control;
25768400SNicolas.Droux@Sun.COM nxge_ldg_t *group;
25778400SNicolas.Droux@Sun.COM nxge_ldv_t *device;
25788400SNicolas.Droux@Sun.COM
25798400SNicolas.Droux@Sun.COM /*
25808400SNicolas.Droux@Sun.COM * Find the DMA channel.
25818400SNicolas.Droux@Sun.COM */
25828400SNicolas.Droux@Sun.COM if (!(dc = nxge_grp_dc_find(nxge, VP_BOUND_RX, channel))) {
25838400SNicolas.Droux@Sun.COM return (NXGE_ERROR);
25848400SNicolas.Droux@Sun.COM }
25858400SNicolas.Droux@Sun.COM
25868400SNicolas.Droux@Sun.COM /*
25878400SNicolas.Droux@Sun.COM * Get the control structure.
25888400SNicolas.Droux@Sun.COM */
25898400SNicolas.Droux@Sun.COM control = nxge->ldgvp;
25908400SNicolas.Droux@Sun.COM if (control == NULL) {
25918400SNicolas.Droux@Sun.COM return (NXGE_ERROR);
25928400SNicolas.Droux@Sun.COM }
25938400SNicolas.Droux@Sun.COM
25948400SNicolas.Droux@Sun.COM group = &control->ldgp[dc->ldg.vector];
25958400SNicolas.Droux@Sun.COM device = &control->ldvp[dc->ldg.ldsv];
25968400SNicolas.Droux@Sun.COM
25978400SNicolas.Droux@Sun.COM MUTEX_ENTER(&ring->lock);
25988400SNicolas.Droux@Sun.COM ring->ldgp = group;
25998400SNicolas.Droux@Sun.COM ring->ldvp = device;
26008400SNicolas.Droux@Sun.COM MUTEX_EXIT(&ring->lock);
26018400SNicolas.Droux@Sun.COM
26028400SNicolas.Droux@Sun.COM return (NXGE_OK);
26038400SNicolas.Droux@Sun.COM }
26046495Sspeer #endif /* if defined(sun4v) */
2605