nxge_hio.c revision 6895688e5f0e768b4c49108ae73903afa1bd1997
0N/A * The contents of this file are subject to the terms of the 0N/A * Common Development and Distribution License (the "License"). 0N/A * You may not use this file except in compliance with the License. 0N/A * See the License for the specific language governing permissions 0N/A * and limitations under the License. 0N/A * When distributing Covered Code, include this CDDL HEADER in each 0N/A * If applicable, add the following below this CDDL HEADER, with the 0N/A * fields enclosed by brackets "[]" replaced with your own identifying 0N/A * information: Portions Copyright [yyyy] [name of copyright owner] 0N/A * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 0N/A * Use is subject to license terms. 0N/A#
pragma ident "%Z%%M% %I% %E% SMI" 0N/A * This file manages the virtualization resources for Neptune 0N/A * devices. That is, it implements a hybrid I/O (HIO) approach in the 0N/A * Solaris kernel, whereby a guest domain on an LDOMs server may 0N/A * request & use hardware resources from the service domain. 0N/A * External prototypes 0N/A/* The following function may be found in nxge_[t|r]xdma.c */ 0N/A * These functions are used by both service & guest domains to 0N/A * decide whether they're running in an LDOMs/XEN environment 0N/A * or not. If so, then the Hybrid I/O (HIO) module is initialized. 0N/A * Figure out if we are in a guest domain or not. 0N/A * In the beginning, assume that we are running sans LDOMs/XEN. 0N/A * Are we a hybrid I/O (HIO) guest domain driver? 0N/A /* So we can allocate properly-aligned memory. */ 0N/A "Hybrid IO-capable guest domain"));
0N/A * Initialize the HIO module of the NXGE driver. 0N/A * This is the non-hybrid I/O version of this function. 0N/A * Map a DMA channel index to a channel number. 0N/A * instance The instance number of the driver. 0N/A * type The type of channel this is: Tx or Rx. 0N/A * index The index to convert to a channel number * This function is called by nxge_ndd.c:nxge_param_set_port_rdc() * --------------------------------------------------------------------- * These are the general-purpose DMA channel group functions. That is, * these functions are used to manage groups of TDCs or RDCs in an HIO * But is also expected that in the future they will be able to manage * --------------------------------------------------------------------- * Add a group to an instance of NXGE. /* Find an empty slot for this logical group. */ "nxge_grp_add: %cgroup = %d.%d",
/* While inside the mutex, deactivate <group>. */ "nxge_grp_remove(%c.%d.%d) called",
/* Now, remove any DCs which are still active. */ * channel The channel to add. "nxge_grp_dc_add: TDC = %d",
channel));
"nxge_grp_dc_add: RDC = %d",
channel));
"nxge_grp_dc_add: %cgroup = %d.%d.%d, channel = %d",
/* We may be in the process of removing this group. */ "nxge_grp_dc_add(%d): DC FIND failed",
channel));
/* This channel is already in use! */ "nxge_grp_dc_add(%d): channel already in group",
channel));
"nxge_grp_dc_add(%d): channel init failed",
channel));
"nx_hio_dc_remove: find(%d) failed",
channel));
"DC remove: group = %d.%d.%d, %cdc %d",
/* Remove the DC from its group. */ "nx_hio_dc_remove(%d) failed",
channel));
/* We're in a guest domain. */ * Append a DMA channel to a group. * group The group to append to * dc The DMA channel to append * Unlink a DMA channel fromits linked list (group). * group The group (linked list) to unlink from * dc The DMA channel to append "DC unlink: DC %d not found",
channel));
* Map a linked list to an array of channel numbers. * group The group to remap. * It is expected that the caller will hold the correct mutex. * --------------------------------------------------------------------- * These are HIO debugging functions. * --------------------------------------------------------------------- * Delay <seconds> number of seconds. * group The group to append to * dc The DMA channel to append * This is a developer-only function. {
"RX_DMA_ENT_MSK",
0x68 },
{
"RX_DMA_CTL_STAT",
0x70 },
{
"RX_DMA_CTL_STAT_DBG",
0x98 },
{
"TxDMA_PRE_ST",
0x40 },
{
"Tx_RNG_ERR_LOGH",
0x48 },
{
"Tx_RNG_ERR_LOGL",
0x50 },
{
"TDMC_INTR_DBG",
0x60 },
* Translate a register address into a string. * offset The address of the register to translate. * These are developer-only function. * Map a DDI error number to a string. * ddi_error The DDI error number to map. return (
"DDI_NOT_WELL_FORMED");
return (
"DDI_ETRANSPORT");
return (
"Unknown error");
* --------------------------------------------------------------------- * These are Sun4v HIO function definitions * --------------------------------------------------------------------- * Initialize the HIO module of the NXGE driver. "nxge_hio_init: hypervisor services " * Initialize share and ring group structures. /* Fill in the HV HIO function pointers. */ "Hybrid IO-capable service domain"));
* isLDOMguest(nxge) == B_TRUE * Ask the Hypervisor to set up the VR for us "vr->assign() returned %d",
hv_rv));
* For each shared TDC, ask the HV to find us an empty slot. * ----------------------------------------------------- "tx->assign(%x, %d) failed: %ld",
/* Inform the caller about the slot chosen. */ * For each shared RDC, ask the HV to find us an empty slot. * ----------------------------------------------------- "rx->assign(%x, %d) failed: %ld",
/* Inform the caller about the slot chosen. */ "tx->unassign(%x, %d) failed: %ld",
"rx->unassign(%x, %d) failed: %ld",
"vr->assign(%x) failed: %ld",
* Get an RDC group for us to use. * Add resources to the share. /* high 32 bits are cfg_hdl and low 32 bits are HV cookie */ * First, unassign the VR (take it back), * so we can enable interrupts again. * Free Ring Resources for TX and RX * Clear internal handle state. * Find an unused Virtualization Region (VR). /* Find an empty virtual region (VR). */ // FUNC0_VIR0 'belongs' to NIU port 0. // FUNC2_VIR0 'belongs' to NIU port 1. "Shares not supported on function(%d) at this time.\n",
* This function is no longer called, but I will keep it * here in case we want to revisit this topic in the future. * nxge_hio_hostinfo_uninit(nxge, vr); for (i = 0; i <
count; i++) {
if (i == 0)
/* Couldn't get even one DC. */ * Share an unused TDC channel. * A.7.3 Reconfigure Tx DMA channel * [Rebind TxDMA channel to Port A.9.6.7] * We don't have to Rebind the TDC to the port - it always already bound. * Soft Reset TxDMA A.9.6.2 * This procedure will be executed by nxge_init_txdma_channel() in the * Re-initialize TxDMA A.9.6.8 * Wait until this channel is idle. "Tx ring %d was always BUSY",
channel));
"Failed to remove interrupt for TxDMA channel %d",
/* Disable TxDMA A.9.6.10 */ /* The SD is sharing this channel. */ /* Soft Reset TxDMA A.9.6.2 */ * Initialize the DC-specific FZC control registers. * ----------------------------------------------------- "nx_hio_dc_share: FZC TDC failed: %d",
channel));
* Share an unused RDC channel. * This is the latest version of the procedure to * Reconfigure an Rx DMA channel: * A.6.3 Reconfigure Rx DMA channel * Stop and reset RxDMA A.9.5.3 * This procedure will be executed by nxge_init_rxdma_channel() in the * Initialize RxDMA A.9.5.4 * We will do this here, since the RDC is a canalis non grata: /* Disable interrupts. */ "Failed to remove interrupt for RxDMA channel %d",
/* Stop RxMAC = A.9.2.6 */ "Failed to disable RxMAC"));
/* Drain IPP Port = A.9.3.6 */ /* Stop and reset RxDMA = A.9.5.3 */ // De-assert EN: RXDMA_CFIG1[31] = 0 (DMC+00000 ) "Failed to disable RxDMA channel %d",
channel));
/* The SD is sharing this channel. */ // Assert RST: RXDMA_CFIG1[30] = 1 * We have to reconfigure the RDC table(s) * to which this channel belongs. * The guest domain will reconfigure the RDC later. * But in the meantime, we must re-enable the Rx MAC so * that we can start receiving packets again on the * Enable RxMAC = A.9.2.10 "nx_hio_rdc_share: Rx MAC still disabled"));
* Initialize the DC-specific FZC control registers. * ----------------------------------------------------- "nx_hio_rdc_share: RZC RDC failed: %ld",
channel));
* We have to initialize the guest's RDC table, too. * ----------------------------------------------------- "nx_hio_rdc_share: nxge_init_fzc_rdc_tbl failed"));
* Share a DMA channel with a guest domain. * vr The VR that <channel> will belong to. * res_map The resource map used by the caller, which we will * In version 1.0, we may only give a VR 2 RDCs or TDCs. * Not only that, but the HV has statically assigned the * The TDCs are assigned in exactly the same way. * hardware->start_rdc + vr->region * 2; * VR1: hardware->start_rdc + 1 * 2; * VR3: hardware->start_rdc + 3 * 2; * If start_rdc is 0, we end up with 2 or 6. * If start_rdc is 8, we end up with 10 or 14. // This code is still NIU-specific (assuming only 2 ports) "nx_hio_dc_share: there are no channels to share"));
/* -------------------------------------------------- */ * -------------------------------------------------- * vr->[t|r]x_group is used by the service domain to * keep track of its shared DMA channels. /* Initialize <group>, if necessary */ "DC share: %cDC %d was assigned to slot %d",
* channel The channel to unshare (add again). "Failed to initialize TxDMA channel %d",
channel));
/* Re-add this interrupt. */ "Failed to add interrupt for TxDMA channel %d",
channel));
* Unshare an RDC: add it to the SD's RDC groups (tables). * channel The channel to unshare (add again). /* Stop RxMAC = A.9.2.6 */ "Failed to disable RxMAC"));
/* Drain IPP Port = A.9.3.6 */ /* Stop and reset RxDMA = A.9.5.3 */ // De-assert EN: RXDMA_CFIG1[31] = 0 (DMC+00000 ) "Failed to disable RxDMA channel %d",
channel));
* Assert RST: RXDMA_CFIG1[30] = 1 * Initialize RxDMA A.9.5.4 /* Be sure to re-enable the RX MAC. */ "nx_hio_rdc_share: Rx MAC still disabled"));
"Failed to initialize RxDMA channel %d",
channel));
* We have to reconfigure the RDC table(s) * to which this channel once again belongs. * Enable RxMAC = A.9.2.10 "nx_hio_rdc_share: Rx MAC still disabled"));
/* Re-add this interrupt. */ "nx_hio_rdc_unshare: Failed to add interrupt for " * Unshare (reuse) a DMA channel. * vr The VR that <channel> belongs to. * channel The DMA channel to reuse. /* Unlink the channel from its group. */ /* -------------------------------------------------- */ "nx_hio_dc_unshare(%d) failed",
channel));
#
endif /* if defined(sun4v) */