/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <nxge_impl.h>
#include <npi_mac.h>
#include <npi_rxdma.h>
#include <nxge_hio.h>
#if defined(sun4v) && defined(NIU_LP_WORKAROUND)
static int nxge_herr2kerr(uint64_t);
static uint64_t nxge_init_hv_fzc_lp_op(p_nxge_t, uint64_t,
uint64_t, uint64_t, uint64_t, uint64_t);
#endif
static nxge_status_t nxge_init_fzc_rdc_pages(p_nxge_t,
uint16_t, dma_log_page_t *, dma_log_page_t *);
static nxge_status_t nxge_init_fzc_tdc_pages(p_nxge_t,
uint16_t, dma_log_page_t *, dma_log_page_t *);
/*
* The following interfaces are controlled by the
* function control registers. Some global registers
* are to be initialized by only byt one of the 2/4 functions.
* Use the test and set register.
*/
/*ARGSUSED*/
nxge_status_t
nxge_test_and_set(p_nxge_t nxgep, uint8_t tas)
{
npi_handle_t handle;
npi_status_t rs = NPI_SUCCESS;
handle = NXGE_DEV_NPI_HANDLE(nxgep);
if ((rs = npi_dev_func_sr_sr_get_set_clear(handle, tas))
!= NPI_SUCCESS) {
return (NXGE_ERROR | rs);
}
return (NXGE_OK);
}
nxge_status_t
nxge_set_fzc_multi_part_ctl(p_nxge_t nxgep, boolean_t mpc)
{
npi_handle_t handle;
npi_status_t rs = NPI_SUCCESS;
NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_set_fzc_multi_part_ctl"));
/*
* In multi-partitioning, the partition manager
* who owns function zero should set this multi-partition
* control bit.
*/
if (nxgep->use_partition && nxgep->function_num) {
return (NXGE_ERROR);
}
handle = NXGE_DEV_NPI_HANDLE(nxgep);
if ((rs = npi_fzc_mpc_set(handle, mpc)) != NPI_SUCCESS) {
NXGE_DEBUG_MSG((nxgep, DMA_CTL,
"<== nxge_set_fzc_multi_part_ctl"));
return (NXGE_ERROR | rs);
}
NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_set_fzc_multi_part_ctl"));
return (NXGE_OK);
}
nxge_status_t
nxge_get_fzc_multi_part_ctl(p_nxge_t nxgep, boolean_t *mpc_p)
{
npi_handle_t handle;
npi_status_t rs = NPI_SUCCESS;
NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_get_fzc_multi_part_ctl"));
handle = NXGE_DEV_NPI_HANDLE(nxgep);
if ((rs = npi_fzc_mpc_get(handle, mpc_p)) != NPI_SUCCESS) {
NXGE_DEBUG_MSG((nxgep, DMA_CTL,
"<== nxge_set_fzc_multi_part_ctl"));
return (NXGE_ERROR | rs);
}
NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_get_fzc_multi_part_ctl"));
return (NXGE_OK);
}
/*
* System interrupt registers that are under function zero
* management.
*/
nxge_status_t
nxge_fzc_intr_init(p_nxge_t nxgep)
{
nxge_status_t status = NXGE_OK;
NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_fzc_intr_init"));
/* Configure the initial timer resolution */
if ((status = nxge_fzc_intr_tmres_set(nxgep)) != NXGE_OK) {
return (status);
}
if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
/*
* Set up the logical device group's logical devices that
* the group owns.
*/
if ((status = nxge_fzc_intr_ldg_num_set(nxgep)) != NXGE_OK)
goto fzc_intr_init_exit;
/* Configure the system interrupt data */
if ((status = nxge_fzc_intr_sid_set(nxgep)) != NXGE_OK)
goto fzc_intr_init_exit;
}
fzc_intr_init_exit:
NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_fzc_intr_init"));
return (status);
}
nxge_status_t
nxge_fzc_intr_ldg_num_set(p_nxge_t nxgep)
{
p_nxge_ldg_t ldgp;
p_nxge_ldv_t ldvp;
npi_handle_t handle;
int i, j;
npi_status_t rs = NPI_SUCCESS;
NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_fzc_intr_ldg_num_set"));
if (nxgep->ldgvp == NULL) {
return (NXGE_ERROR);
}
ldgp = nxgep->ldgvp->ldgp;
ldvp = nxgep->ldgvp->ldvp;
if (ldgp == NULL || ldvp == NULL) {
return (NXGE_ERROR);
}
handle = NXGE_DEV_NPI_HANDLE(nxgep);
for (i = 0; i < nxgep->ldgvp->ldg_intrs; i++, ldgp++) {
NXGE_DEBUG_MSG((nxgep, INT_CTL,
"==> nxge_fzc_intr_ldg_num_set "
"<== nxge_f(Neptune): # ldv %d "
"in group %d", ldgp->nldvs, ldgp->ldg));
for (j = 0; j < ldgp->nldvs; j++, ldvp++) {
rs = npi_fzc_ldg_num_set(handle, ldvp->ldv,
ldvp->ldg_assigned);
if (rs != NPI_SUCCESS) {
NXGE_DEBUG_MSG((nxgep, INT_CTL,
"<== nxge_fzc_intr_ldg_num_set failed "
" rs 0x%x ldv %d ldg %d",
rs, ldvp->ldv, ldvp->ldg_assigned));
return (NXGE_ERROR | rs);
}
NXGE_DEBUG_MSG((nxgep, INT_CTL,
"<== nxge_fzc_intr_ldg_num_set OK "
" ldv %d ldg %d",
ldvp->ldv, ldvp->ldg_assigned));
}
}
NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_fzc_intr_ldg_num_set"));
return (NXGE_OK);
}
nxge_status_t
nxge_fzc_intr_tmres_set(p_nxge_t nxgep)
{
npi_handle_t handle;
npi_status_t rs = NPI_SUCCESS;
NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_fzc_intr_tmrese_set"));
if (nxgep->ldgvp == NULL) {
return (NXGE_ERROR);
}
handle = NXGE_DEV_NPI_HANDLE(nxgep);
if ((rs = npi_fzc_ldg_timer_res_set(handle, nxgep->ldgvp->tmres))) {
return (NXGE_ERROR | rs);
}
NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_fzc_intr_tmrese_set"));
return (NXGE_OK);
}
nxge_status_t
nxge_fzc_intr_sid_set(p_nxge_t nxgep)
{
npi_handle_t handle;
p_nxge_ldg_t ldgp;
fzc_sid_t sid;
int i;
npi_status_t rs = NPI_SUCCESS;
NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_fzc_intr_sid_set"));
if (nxgep->ldgvp == NULL) {
NXGE_DEBUG_MSG((nxgep, INT_CTL,
"<== nxge_fzc_intr_sid_set: no ldg"));
return (NXGE_ERROR);
}
handle = NXGE_DEV_NPI_HANDLE(nxgep);
ldgp = nxgep->ldgvp->ldgp;
NXGE_DEBUG_MSG((nxgep, INT_CTL,
"==> nxge_fzc_intr_sid_set: #int %d", nxgep->ldgvp->ldg_intrs));
for (i = 0; i < nxgep->ldgvp->ldg_intrs; i++, ldgp++) {
sid.ldg = ldgp->ldg;
sid.niu = B_FALSE;
sid.func = ldgp->func;
sid.vector = ldgp->vector;
NXGE_DEBUG_MSG((nxgep, INT_CTL,
"==> nxge_fzc_intr_sid_set(%d): func %d group %d "
"vector %d",
i, sid.func, sid.ldg, sid.vector));
rs = npi_fzc_sid_set(handle, sid);
if (rs != NPI_SUCCESS) {
NXGE_DEBUG_MSG((nxgep, INT_CTL,
"<== nxge_fzc_intr_sid_set:failed 0x%x",
rs));
return (NXGE_ERROR | rs);
}
}
NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_fzc_intr_sid_set"));
return (NXGE_OK);
}
/*
* nxge_init_fzc_rdc
*
* Initialize all of a RDC's FZC_DMC registers.
* This is executed by the service domain, on behalf of a
* guest domain, who cannot access these registers.
*
* Arguments:
* nxgep
* channel The channel to initialize.
*
* NPI_NXGE function calls:
* nxge_init_fzc_rdc_pages()
*
* Context:
* Service Domain
*/
/*ARGSUSED*/
nxge_status_t
nxge_init_fzc_rdc(p_nxge_t nxgep, uint16_t channel)
{
nxge_status_t status = NXGE_OK;
dma_log_page_t page1, page2;
npi_handle_t handle;
rdc_red_para_t red;
/*
* Initialize the RxDMA channel-specific FZC control
* registers.
*/
NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_init_fzc_tdc"));
handle = NXGE_DEV_NPI_HANDLE(nxgep);
/* Reset RXDMA channel */
status = npi_rxdma_cfg_rdc_reset(handle, channel);
if (status != NPI_SUCCESS) {
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"==> nxge_init_fzc_rdc: npi_rxdma_cfg_rdc_reset(%d) "
"returned 0x%08x", channel, status));
return (NXGE_ERROR | status);
}
/*
* These values have been copied from
* nxge_txdma.c:nxge_map_txdma_channel_cfg_ring().
*/
page1.page_num = 0;
page1.valid = 1;
page1.func_num = nxgep->function_num;
page1.mask = 0;
page1.value = 0;
page1.reloc = 0;
page2.page_num = 1;
page2.valid = 1;
page2.func_num = nxgep->function_num;
page2.mask = 0;
page2.value = 0;
page2.reloc = 0;
if (nxgep->niu_type == N2_NIU) {
#if !defined(NIU_HV_WORKAROUND)
status = NXGE_OK;
#else
NXGE_DEBUG_MSG((nxgep, RX_CTL,
"==> nxge_init_fzc_rxdma_channel: N2_NIU - NEED to "
"set up logical pages"));
/* Initialize the RXDMA logical pages */
status = nxge_init_fzc_rdc_pages(nxgep, channel,
&page1, &page2);
if (status != NXGE_OK) {
return (status);
}
#endif
} else if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
/* Initialize the RXDMA logical pages */
status = nxge_init_fzc_rdc_pages(nxgep, channel,
&page1, &page2);
if (status != NXGE_OK) {
return (status);
}
} else {
return (NXGE_ERROR);
}
/*
* Configure RED parameters
*/
red.value = 0;
red.bits.ldw.win = RXDMA_RED_WINDOW_DEFAULT;
red.bits.ldw.thre =
(nxgep->nxge_port_rcr_size - RXDMA_RED_LESS_ENTRIES);
red.bits.ldw.win_syn = RXDMA_RED_WINDOW_DEFAULT;
red.bits.ldw.thre_sync =
(nxgep->nxge_port_rcr_size - RXDMA_RED_LESS_ENTRIES);
NXGE_DEBUG_MSG((nxgep, DMA_CTL,
"==> nxge_init_fzc_rxdma_channel_red(thre_sync %d(%x))",
red.bits.ldw.thre_sync,
red.bits.ldw.thre_sync));
status |= npi_rxdma_cfg_wred_param(handle, channel, &red);
NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_init_fzc_rdc"));
return (status);
}
/*
* nxge_init_fzc_rxdma_channel
*
* Initialize all per-channel FZC_DMC registers.
*
* Arguments:
* nxgep
* channel The channel to start
*
* NPI_NXGE function calls:
* nxge_init_hv_fzc_rxdma_channel_pages()
* nxge_init_fzc_rxdma_channel_pages()
* nxge_init_fzc_rxdma_channel_red()
*
* Context:
* Service Domain
*/
/*ARGSUSED*/
nxge_status_t
nxge_init_fzc_rxdma_channel(p_nxge_t nxgep, uint16_t channel)
{
rx_rbr_ring_t *rbr_ring;
rx_rcr_ring_t *rcr_ring;
nxge_status_t status = NXGE_OK;
NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_init_fzc_rxdma_channel"));
rbr_ring = nxgep->rx_rbr_rings->rbr_rings[channel];
rcr_ring = nxgep->rx_rcr_rings->rcr_rings[channel];
if (nxgep->niu_type == N2_NIU) {
#ifndef NIU_HV_WORKAROUND
#if defined(sun4v) && defined(NIU_LP_WORKAROUND)
NXGE_DEBUG_MSG((nxgep, RX_CTL,
"==> nxge_init_fzc_rxdma_channel: N2_NIU - call HV "
"set up logical pages"));
/* Initialize the RXDMA logical pages */
status = nxge_init_hv_fzc_rxdma_channel_pages(nxgep, channel,
rbr_ring);
if (status != NXGE_OK) {
return (status);
}
#endif
status = NXGE_OK;
#else
NXGE_DEBUG_MSG((nxgep, RX_CTL,
"==> nxge_init_fzc_rxdma_channel: N2_NIU - NEED to "
"set up logical pages"));
/* Initialize the RXDMA logical pages */
status = nxge_init_fzc_rxdma_channel_pages(nxgep, channel,
rbr_ring);
if (status != NXGE_OK) {
return (status);
}
#endif
} else if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
/* Initialize the RXDMA logical pages */
status = nxge_init_fzc_rxdma_channel_pages(nxgep,
channel, rbr_ring);
if (status != NXGE_OK) {
return (status);
}
} else {
return (NXGE_ERROR);
}
/* Configure RED parameters */
status = nxge_init_fzc_rxdma_channel_red(nxgep, channel, rcr_ring);
NXGE_DEBUG_MSG((nxgep, RX_CTL, "<== nxge_init_fzc_rxdma_channel"));
return (status);
}
/*
* nxge_init_fzc_rdc_pages
*
* Configure a TDC's logical pages.
*
* This function is executed by the service domain, on behalf of
* a guest domain, to whom this RDC has been loaned.
*
* Arguments:
* nxgep
* channel The channel to initialize.
* page0 Logical page 0 definition.
* page1 Logical page 1 definition.
*
* Notes:
* I think that this function can be called from any
* domain, but I need to check.
*
* NPI/NXGE function calls:
* hv_niu_tx_logical_page_conf()
* hv_niu_tx_logical_page_info()
*
* Context:
* Any domain
*/
nxge_status_t
nxge_init_fzc_rdc_pages(
p_nxge_t nxgep,
uint16_t channel,
dma_log_page_t *page0,
dma_log_page_t *page1)
{
npi_handle_t handle;
npi_status_t rs;
uint64_t page_handle;
NXGE_DEBUG_MSG((nxgep, DMA_CTL,
"==> nxge_init_fzc_txdma_channel_pages"));
#ifndef NIU_HV_WORKAROUND
if (nxgep->niu_type == N2_NIU) {
NXGE_DEBUG_MSG((nxgep, DMA_CTL,
"<== nxge_init_fzc_rdc_pages: "
"N2_NIU: no need to set rxdma logical pages"));
return (NXGE_OK);
}
#else
if (nxgep->niu_type == N2_NIU) {
NXGE_DEBUG_MSG((nxgep, DMA_CTL,
"<== nxge_init_fzc_rdc_pages: "
"N2_NIU: NEED to set rxdma logical pages"));
}
#endif
/*
* Initialize logical page 1.
*/
handle = NXGE_DEV_NPI_HANDLE(nxgep);
if ((rs = npi_rxdma_cfg_logical_page(handle, channel, page0))
!= NPI_SUCCESS)
return (NXGE_ERROR | rs);
/*
* Initialize logical page 2.
*/
if ((rs = npi_rxdma_cfg_logical_page(handle, channel, page1))
!= NPI_SUCCESS)
return (NXGE_ERROR | rs);
/*
* Initialize the page handle.
* (In the current driver, this is always set to 0.)
*/
page_handle = 0;
rs = npi_rxdma_cfg_logical_page_handle(handle, channel, page_handle);
if (rs == NPI_SUCCESS) {
return (NXGE_OK);
} else {
return (NXGE_ERROR | rs);
}
}
/*ARGSUSED*/
nxge_status_t
nxge_init_fzc_rxdma_channel_pages(p_nxge_t nxgep,
uint16_t channel, p_rx_rbr_ring_t rbrp)
{
npi_handle_t handle;
dma_log_page_t cfg;
npi_status_t rs = NPI_SUCCESS;
NXGE_DEBUG_MSG((nxgep, DMA_CTL,
"==> nxge_init_fzc_rxdma_channel_pages"));
handle = NXGE_DEV_NPI_HANDLE(nxgep);
/*
* Initialize logical page 1.
*/
cfg.func_num = nxgep->function_num;
cfg.page_num = 0;
cfg.valid = rbrp->page_valid.bits.ldw.page0;
cfg.value = rbrp->page_value_1.value;
cfg.mask = rbrp->page_mask_1.value;
cfg.reloc = rbrp->page_reloc_1.value;
rs = npi_rxdma_cfg_logical_page(handle, channel,
(p_dma_log_page_t)&cfg);
if (rs != NPI_SUCCESS) {
return (NXGE_ERROR | rs);
}
/*
* Initialize logical page 2.
*/
cfg.page_num = 1;
cfg.valid = rbrp->page_valid.bits.ldw.page1;
cfg.value = rbrp->page_value_2.value;
cfg.mask = rbrp->page_mask_2.value;
cfg.reloc = rbrp->page_reloc_2.value;
rs = npi_rxdma_cfg_logical_page(handle, channel, &cfg);
if (rs != NPI_SUCCESS) {
return (NXGE_ERROR | rs);
}
/* Initialize the page handle */
rs = npi_rxdma_cfg_logical_page_handle(handle, channel,
rbrp->page_hdl.bits.ldw.handle);
if (rs != NPI_SUCCESS) {
return (NXGE_ERROR | rs);
}
NXGE_DEBUG_MSG((nxgep, DMA_CTL,
"<== nxge_init_fzc_rxdma_channel_pages"));
return (NXGE_OK);
}
/*ARGSUSED*/
nxge_status_t
nxge_init_fzc_rxdma_channel_red(p_nxge_t nxgep,
uint16_t channel, p_rx_rcr_ring_t rcr_p)
{
npi_handle_t handle;
rdc_red_para_t red;
npi_status_t rs = NPI_SUCCESS;
NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_init_fzc_rxdma_channel_red"));
handle = NXGE_DEV_NPI_HANDLE(nxgep);
red.value = 0;
red.bits.ldw.win = RXDMA_RED_WINDOW_DEFAULT;
red.bits.ldw.thre = (rcr_p->comp_size - RXDMA_RED_LESS_ENTRIES);
red.bits.ldw.win_syn = RXDMA_RED_WINDOW_DEFAULT;
red.bits.ldw.thre_sync = (rcr_p->comp_size - RXDMA_RED_LESS_ENTRIES);
NXGE_DEBUG_MSG((nxgep, DMA_CTL,
"==> nxge_init_fzc_rxdma_channel_red(thre_sync %d(%x))",
red.bits.ldw.thre_sync,
red.bits.ldw.thre_sync));
rs = npi_rxdma_cfg_wred_param(handle, channel, &red);
if (rs != NPI_SUCCESS) {
return (NXGE_ERROR | rs);
}
NXGE_DEBUG_MSG((nxgep, DMA_CTL,
"<== nxge_init_fzc_rxdma_channel_red"));
return (NXGE_OK);
}
/*
* nxge_init_fzc_tdc
*
* Initialize all of a TDC's FZC_DMC registers.
* This is executed by the service domain, on behalf of a
* guest domain, who cannot access these registers.
*
* Arguments:
* nxgep
* channel The channel to initialize.
*
* NPI_NXGE function calls:
* nxge_init_fzc_tdc_pages()
* npi_txc_dma_max_burst_set()
*
* Registers accessed:
* TXC_DMA_MAX_BURST
*
* Context:
* Service Domain
*/
/*ARGSUSED*/
nxge_status_t
nxge_init_fzc_tdc(p_nxge_t nxgep, uint16_t channel)
{
nxge_status_t status = NXGE_OK;
dma_log_page_t page1, page2;
npi_handle_t handle;
NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_init_fzc_tdc"));
/*
* These values have been copied from
* nxge_txdma.c:nxge_map_txdma_channel_cfg_ring().
*/
page1.page_num = 0;
page1.valid = 1;
page1.func_num = nxgep->function_num;
page1.mask = 0;
page1.value = 0;
page1.reloc = 0;
page1.page_num = 1;
page1.valid = 1;
page1.func_num = nxgep->function_num;
page1.mask = 0;
page1.value = 0;
page1.reloc = 0;
#ifdef NIU_HV_WORKAROUND
if (nxgep->niu_type == N2_NIU) {
NXGE_DEBUG_MSG((nxgep, DMA_CTL,
"==> nxge_init_fzc_txdma_channel "
"N2_NIU: NEED to set up txdma logical pages"));
/* Initialize the TXDMA logical pages */
(void) nxge_init_fzc_tdc_pages(nxgep, channel,
&page1, &page2);
}
#endif
if (nxgep->niu_type != N2_NIU) {
if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
/* Initialize the TXDMA logical pages */
(void) nxge_init_fzc_tdc_pages(nxgep, channel,
&page1, &page2);
} else
return (NXGE_ERROR);
}
/*
* Configure the TXC DMA Max Burst value.
*
* PRM.13.5
*
* TXC DMA Max Burst. TXC_DMA_MAX (FZC_TXC + 0000016)
* 19:0 dma_max_burst RW
* Max burst value associated with DMA. Used by DRR engine
* for computing when DMA has gone into deficit.
*/
handle = NXGE_DEV_NPI_HANDLE(nxgep);
(void) npi_txc_dma_max_burst_set(
handle, channel, TXC_DMA_MAX_BURST_DEFAULT);
NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_init_fzc_tdc"));
return (status);
}
/*ARGSUSED*/
nxge_status_t
nxge_init_fzc_txdma_channel(p_nxge_t nxgep, uint16_t channel,
p_tx_ring_t tx_ring_p, p_tx_mbox_t mbox_p)
{
nxge_status_t status = NXGE_OK;
NXGE_DEBUG_MSG((nxgep, DMA_CTL,
"==> nxge_init_fzc_txdma_channel"));
if (nxgep->niu_type == N2_NIU) {
#ifndef NIU_HV_WORKAROUND
#if defined(sun4v) && defined(NIU_LP_WORKAROUND)
NXGE_DEBUG_MSG((nxgep, DMA_CTL,
"==> nxge_init_fzc_txdma_channel "
"N2_NIU: call HV to set up txdma logical pages"));
status = nxge_init_hv_fzc_txdma_channel_pages(nxgep, channel,
tx_ring_p);
if (status != NXGE_OK) {
return (status);
}
#endif
status = NXGE_OK;
#else
NXGE_DEBUG_MSG((nxgep, DMA_CTL,
"==> nxge_init_fzc_txdma_channel "
"N2_NIU: NEED to set up txdma logical pages"));
/* Initialize the TXDMA logical pages */
(void) nxge_init_fzc_txdma_channel_pages(nxgep, channel,
tx_ring_p);
#endif
} else if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
/* Initialize the TXDMA logical pages */
(void) nxge_init_fzc_txdma_channel_pages(nxgep,
channel, tx_ring_p);
} else {
return (NXGE_ERROR);
}
/*
* Configure Transmit DRR Weight parameters
* (It actually programs the TXC max burst register).
*/
(void) nxge_init_fzc_txdma_channel_drr(nxgep, channel, tx_ring_p);
NXGE_DEBUG_MSG((nxgep, DMA_CTL,
"<== nxge_init_fzc_txdma_channel"));
return (status);
}
nxge_status_t
nxge_init_fzc_rx_common(p_nxge_t nxgep)
{
npi_handle_t handle;
npi_status_t rs = NPI_SUCCESS;
nxge_status_t status = NXGE_OK;
nxge_rdc_grp_t *rdc_grp_p;
clock_t lbolt;
int table;
nxge_hw_pt_cfg_t *hardware;
NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_init_fzc_rx_common"));
handle = NXGE_DEV_NPI_HANDLE(nxgep);
if (!handle.regp) {
NXGE_DEBUG_MSG((nxgep, DMA_CTL,
"==> nxge_init_fzc_rx_common null ptr"));
return (NXGE_ERROR);
}
/*
* Configure the rxdma clock divider
* This is the granularity counter based on
* the hardware system clock (i.e. 300 Mhz) and
* it is running around 3 nanoseconds.
* So, set the clock divider counter to 1000 to get
* microsecond granularity.
* For example, for a 3 microsecond timeout, the timeout
* will be set to 1.
*/
rs = npi_rxdma_cfg_clock_div_set(handle, RXDMA_CK_DIV_DEFAULT);
if (rs != NPI_SUCCESS)
return (NXGE_ERROR | rs);
#if defined(__i386)
rs = npi_rxdma_cfg_32bitmode_enable(handle);
if (rs != NPI_SUCCESS)
return (NXGE_ERROR | rs);
rs = npi_txdma_mode32_set(handle, B_TRUE);
if (rs != NPI_SUCCESS)
return (NXGE_ERROR | rs);
#endif
/*
* Enable WRED and program an initial value.
* Use time to set the initial random number.
*/
(void) drv_getparm(LBOLT, &lbolt);
rs = npi_rxdma_cfg_red_rand_init(handle, (uint16_t)lbolt);
if (rs != NPI_SUCCESS)
return (NXGE_ERROR | rs);
hardware = &nxgep->pt_config.hw_config;
for (table = 0; table < NXGE_MAX_RDC_GRPS; table++) {
/* Does this table belong to <nxgep>? */
if (hardware->grpids[table] == (nxgep->function_num + 256)) {
rdc_grp_p = &nxgep->pt_config.rdc_grps[table];
status = nxge_init_fzc_rdc_tbl(nxgep, rdc_grp_p, table);
}
}
/* Ethernet Timeout Counter (?) */
NXGE_DEBUG_MSG((nxgep, DMA_CTL,
"<== nxge_init_fzc_rx_common:status 0x%08x", status));
return (status);
}
nxge_status_t
nxge_init_fzc_rdc_tbl(p_nxge_t nxge, nxge_rdc_grp_t *group, int rdc_tbl)
{
nxge_hio_data_t *nhd = (nxge_hio_data_t *)nxge->nxge_hw_p->hio;
nx_rdc_tbl_t *table;
npi_handle_t handle;
npi_status_t rs = NPI_SUCCESS;
nxge_status_t status = NXGE_OK;
NXGE_DEBUG_MSG((nxge, DMA_CTL, "==> nxge_init_fzc_rdc_tbl(%d)", table));
/* This RDC table must have been previously bound to <nxge>. */
MUTEX_ENTER(&nhd->lock);
table = &nhd->rdc_tbl[rdc_tbl];
if (table->nxge != (uintptr_t)nxge) {
MUTEX_EXIT(&nhd->lock);
NXGE_ERROR_MSG((nxge, DMA_CTL,
"nxge_init_fzc_rdc_tbl(%d): not owner", table));
return (NXGE_ERROR);
} else {
table->map = group->map;
}
MUTEX_EXIT(&nhd->lock);
handle = NXGE_DEV_NPI_HANDLE(nxge);
rs = npi_rxdma_rdc_table_config(handle, rdc_tbl,
group->map, group->max_rdcs);
if (rs != NPI_SUCCESS) {
status = NXGE_ERROR | rs;
}
NXGE_DEBUG_MSG((nxge, DMA_CTL, "<== nxge_init_fzc_rdc_tbl(%d)", table));
return (status);
}
static
int
rdc_tbl_bind(p_nxge_t nxge, int rdc_tbl)
{
nxge_hio_data_t *nhd = (nxge_hio_data_t *)nxge->nxge_hw_p->hio;
nx_rdc_tbl_t *table;
int i;
NXGE_DEBUG_MSG((nxge, DMA_CTL, "==> nxge_fzc_rdc_tbl_bind"));
MUTEX_ENTER(&nhd->lock);
/* is the caller asking for a particular table? */
if (rdc_tbl >= 0 && rdc_tbl < NXGE_MAX_RDC_GROUPS) {
table = &nhd->rdc_tbl[rdc_tbl];
if (table->nxge == 0) {
table->nxge = (uintptr_t)nxge; /* It is now bound. */
NXGE_DEBUG_MSG((nxge, DMA_CTL,
"<== nxge_fzc_rdc_tbl_bind(%d)", rdc_tbl));
MUTEX_EXIT(&nhd->lock);
return (rdc_tbl);
}
} else { /* The caller will take any old RDC table. */
for (i = 0; i < NXGE_MAX_RDC_GROUPS; i++) {
nx_rdc_tbl_t *table = &nhd->rdc_tbl[i];
if (table->nxge == 0) {
table->nxge = (uintptr_t)nxge;
/* It is now bound. */
MUTEX_EXIT(&nhd->lock);
NXGE_DEBUG_MSG((nxge, DMA_CTL,
"<== nxge_fzc_rdc_tbl_bind: %d", i));
return (i);
}
}
}
MUTEX_EXIT(&nhd->lock);
NXGE_DEBUG_MSG((nxge, HIO_CTL, "<== nxge_fzc_rdc_tbl_bind"));
return (-EBUSY); /* RDC tables are bound. */
}
int
nxge_fzc_rdc_tbl_bind(
nxge_t *nxge,
int grp_index,
int acceptNoSubstitutes)
{
nxge_hw_pt_cfg_t *hardware;
int index;
hardware = &nxge->pt_config.hw_config;
if ((index = rdc_tbl_bind(nxge, grp_index)) < 0) {
if (acceptNoSubstitutes)
return (index);
index = rdc_tbl_bind(nxge, grp_index);
if (index < 0) {
NXGE_ERROR_MSG((nxge, OBP_CTL,
"nxge_fzc_rdc_tbl_init: "
"there are no free RDC tables!"));
return (index);
}
}
hardware->grpids[index] = nxge->function_num + 256;
return (index);
}
int
nxge_fzc_rdc_tbl_unbind(p_nxge_t nxge, int rdc_tbl)
{
nxge_hio_data_t *nhd = (nxge_hio_data_t *)nxge->nxge_hw_p->hio;
nx_rdc_tbl_t *table;
if (nhd == NULL)
return (0);
NXGE_DEBUG_MSG((nxge, DMA_CTL, "==> nxge_fzc_rdc_tbl_unbind(%d)",
rdc_tbl));
MUTEX_ENTER(&nhd->lock);
table = &nhd->rdc_tbl[rdc_tbl];
if (table->nxge != (uintptr_t)nxge) {
NXGE_ERROR_MSG((nxge, DMA_CTL,
"nxge_fzc_rdc_tbl_unbind(%d): func%d not owner",
nxge->function_num, rdc_tbl));
MUTEX_EXIT(&nhd->lock);
return (EINVAL);
} else {
bzero(table, sizeof (*table));
}
MUTEX_EXIT(&nhd->lock);
NXGE_DEBUG_MSG((nxge, DMA_CTL, "<== nxge_fzc_rdc_tbl_unbind(%d)",
rdc_tbl));
return (0);
}
nxge_status_t
nxge_init_fzc_rxdma_port(p_nxge_t nxgep)
{
npi_handle_t handle;
p_nxge_dma_pt_cfg_t p_all_cfgp;
p_nxge_hw_pt_cfg_t p_cfgp;
hostinfo_t hostinfo;
int i;
npi_status_t rs = NPI_SUCCESS;
p_nxge_class_pt_cfg_t p_class_cfgp;
NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_init_fzc_rxdma_port"));
p_all_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
p_cfgp = (p_nxge_hw_pt_cfg_t)&p_all_cfgp->hw_config;
handle = NXGE_DEV_NPI_HANDLE(nxgep);
/*
* Initialize the port scheduler DRR weight.
* npi_rxdma_cfg_port_ddr_weight();
*/
if ((nxgep->mac.portmode == PORT_1G_COPPER) ||
(nxgep->mac.portmode == PORT_1G_FIBER) ||
(nxgep->mac.portmode == PORT_1G_TN1010) ||
(nxgep->mac.portmode == PORT_1G_SERDES)) {
rs = npi_rxdma_cfg_port_ddr_weight(handle,
nxgep->function_num, NXGE_RX_DRR_WT_1G);
if (rs != NPI_SUCCESS) {
return (NXGE_ERROR | rs);
}
}
/* Program the default RDC of a port */
rs = npi_rxdma_cfg_default_port_rdc(handle, nxgep->function_num,
p_cfgp->def_rdc);
if (rs != NPI_SUCCESS) {
return (NXGE_ERROR | rs);
}
/*
* Configure the MAC host info table with RDC tables
*/
hostinfo.value = 0;
p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
for (i = 0; i < p_cfgp->max_macs; i++) {
hostinfo.bits.w0.rdc_tbl_num = p_cfgp->def_mac_rxdma_grpid;
hostinfo.bits.w0.mac_pref = p_cfgp->mac_pref;
if (p_class_cfgp->mac_host_info[i].flag) {
hostinfo.bits.w0.rdc_tbl_num =
p_class_cfgp->mac_host_info[i].rdctbl;
hostinfo.bits.w0.mac_pref =
p_class_cfgp->mac_host_info[i].mpr_npr;
}
rs = npi_mac_hostinfo_entry(handle, OP_SET,
nxgep->function_num, i, &hostinfo);
if (rs != NPI_SUCCESS)
return (NXGE_ERROR | rs);
}
NXGE_DEBUG_MSG((nxgep, DMA_CTL,
"<== nxge_init_fzc_rxdma_port rs 0x%08x", rs));
return (NXGE_OK);
}
nxge_status_t
nxge_fzc_dmc_def_port_rdc(p_nxge_t nxgep, uint8_t port, uint16_t rdc)
{
npi_status_t rs = NPI_SUCCESS;
rs = npi_rxdma_cfg_default_port_rdc(nxgep->npi_reg_handle,
port, rdc);
if (rs & NPI_FAILURE)
return (NXGE_ERROR | rs);
return (NXGE_OK);
}
/*
* nxge_init_fzc_tdc_pages
*
* Configure a TDC's logical pages.
*
* This function is executed by the service domain, on behalf of
* a guest domain, to whom this TDC has been loaned.
*
* Arguments:
* nxgep
* channel The channel to initialize.
* page0 Logical page 0 definition.
* page1 Logical page 1 definition.
*
* Notes:
* I think that this function can be called from any
* domain, but I need to check.
*
* NPI/NXGE function calls:
* hv_niu_tx_logical_page_conf()
* hv_niu_tx_logical_page_info()
*
* Context:
* Any domain
*/
nxge_status_t
nxge_init_fzc_tdc_pages(
p_nxge_t nxgep,
uint16_t channel,
dma_log_page_t *page0,
dma_log_page_t *page1)
{
npi_handle_t handle;
npi_status_t rs;
log_page_hdl_t page_handle;
NXGE_DEBUG_MSG((nxgep, DMA_CTL,
"==> nxge_init_fzc_txdma_channel_pages"));
#ifndef NIU_HV_WORKAROUND
if (nxgep->niu_type == N2_NIU) {
NXGE_DEBUG_MSG((nxgep, DMA_CTL,
"<== nxge_init_fzc_tdc_pages: "
"N2_NIU: no need to set txdma logical pages"));
return (NXGE_OK);
}
#else
if (nxgep->niu_type == N2_NIU) {
NXGE_DEBUG_MSG((nxgep, DMA_CTL,
"<== nxge_init_fzc_tdc_pages: "
"N2_NIU: NEED to set txdma logical pages"));
}
#endif
/*
* Initialize logical page 1.
*/
handle = NXGE_DEV_NPI_HANDLE(nxgep);
if ((rs = npi_txdma_log_page_set(handle, channel, page0))
!= NPI_SUCCESS)
return (NXGE_ERROR | rs);
/*
* Initialize logical page 2.
*/
if ((rs = npi_txdma_log_page_set(handle, channel, page1))
!= NPI_SUCCESS)
return (NXGE_ERROR | rs);
/*
* Initialize the page handle.
* (In the current driver, this is always set to 0.)
*/
page_handle.value = 0;
rs = npi_txdma_log_page_handle_set(handle, channel, &page_handle);
if (rs == NPI_SUCCESS) {
return (NXGE_OK);
} else {
return (NXGE_ERROR | rs);
}
}
nxge_status_t
nxge_init_fzc_txdma_channel_pages(p_nxge_t nxgep, uint16_t channel,
p_tx_ring_t tx_ring_p)
{
npi_handle_t handle;
dma_log_page_t cfg;
npi_status_t rs = NPI_SUCCESS;
NXGE_DEBUG_MSG((nxgep, DMA_CTL,
"==> nxge_init_fzc_txdma_channel_pages"));
#ifndef NIU_HV_WORKAROUND
if (nxgep->niu_type == N2_NIU) {
NXGE_DEBUG_MSG((nxgep, DMA_CTL,
"<== nxge_init_fzc_txdma_channel_pages: "
"N2_NIU: no need to set txdma logical pages"));
return (NXGE_OK);
}
#else
if (nxgep->niu_type == N2_NIU) {
NXGE_DEBUG_MSG((nxgep, DMA_CTL,
"<== nxge_init_fzc_txdma_channel_pages: "
"N2_NIU: NEED to set txdma logical pages"));
}
#endif
/*
* Initialize logical page 1.
*/
handle = NXGE_DEV_NPI_HANDLE(nxgep);
cfg.func_num = nxgep->function_num;
cfg.page_num = 0;
cfg.valid = tx_ring_p->page_valid.bits.ldw.page0;
cfg.value = tx_ring_p->page_value_1.value;
cfg.mask = tx_ring_p->page_mask_1.value;
cfg.reloc = tx_ring_p->page_reloc_1.value;
rs = npi_txdma_log_page_set(handle, channel,
(p_dma_log_page_t)&cfg);
if (rs != NPI_SUCCESS) {
return (NXGE_ERROR | rs);
}
/*
* Initialize logical page 2.
*/
cfg.page_num = 1;
cfg.valid = tx_ring_p->page_valid.bits.ldw.page1;
cfg.value = tx_ring_p->page_value_2.value;
cfg.mask = tx_ring_p->page_mask_2.value;
cfg.reloc = tx_ring_p->page_reloc_2.value;
rs = npi_txdma_log_page_set(handle, channel, &cfg);
if (rs != NPI_SUCCESS) {
return (NXGE_ERROR | rs);
}
/* Initialize the page handle */
rs = npi_txdma_log_page_handle_set(handle, channel,
&tx_ring_p->page_hdl);
if (rs == NPI_SUCCESS) {
return (NXGE_OK);
} else {
return (NXGE_ERROR | rs);
}
}
nxge_status_t
nxge_init_fzc_txdma_channel_drr(p_nxge_t nxgep, uint16_t channel,
p_tx_ring_t tx_ring_p)
{
npi_status_t rs = NPI_SUCCESS;
npi_handle_t handle;
handle = NXGE_DEV_NPI_HANDLE(nxgep);
rs = npi_txc_dma_max_burst_set(handle, channel,
tx_ring_p->max_burst.value);
if (rs == NPI_SUCCESS) {
return (NXGE_OK);
} else {
return (NXGE_ERROR | rs);
}
}
nxge_status_t
nxge_fzc_sys_err_mask_set(p_nxge_t nxgep, uint64_t mask)
{
npi_status_t rs = NPI_SUCCESS;
npi_handle_t handle;
handle = NXGE_DEV_NPI_HANDLE(nxgep);
rs = npi_fzc_sys_err_mask_set(handle, mask);
if (rs == NPI_SUCCESS) {
return (NXGE_OK);
} else {
return (NXGE_ERROR | rs);
}
}
/*
* nxge_init_hv_fzc_txdma_channel_pages
*
* Configure a TDC's logical pages.
*
* Arguments:
* nxgep
* channel The channel to initialize.
* tx_ring_p The transmit ring.
*
* Notes:
* I think that this function can be called from any
* domain, but I need to check.
*
* NPI/NXGE function calls:
* hv_niu_tx_logical_page_conf()
* hv_niu_tx_logical_page_info()
*
* Context:
* Any domain
*/
#if defined(sun4v) && defined(NIU_LP_WORKAROUND)
nxge_status_t
nxge_init_hv_fzc_txdma_channel_pages(p_nxge_t nxgep, uint16_t channel,
p_tx_ring_t tx_ring_p)
{
int err;
uint64_t hverr;
#ifdef DEBUG
uint64_t ra, size;
#endif
NXGE_DEBUG_MSG((nxgep, TX_CTL,
"==> nxge_init_hv_fzc_txdma_channel_pages"));
if (tx_ring_p->hv_set) {
return (NXGE_OK);
}
/*
* Initialize logical page 1 for data buffers.
*/
hverr = nxge_init_hv_fzc_lp_op(nxgep, (uint64_t)channel,
(uint64_t)0, N2NIU_TX_LP_CONF,
tx_ring_p->hv_tx_buf_base_ioaddr_pp,
tx_ring_p->hv_tx_buf_ioaddr_size);
err = (nxge_status_t)nxge_herr2kerr(hverr);
if (err != 0) {
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"<== nxge_init_hv_fzc_txdma_channel_pages: channel %d "
"error status 0x%x "
"(page 0 data buf) hverr 0x%llx "
"ioaddr_pp $%p "
"size 0x%llx ",
channel,
err,
hverr,
tx_ring_p->hv_tx_buf_base_ioaddr_pp,
tx_ring_p->hv_tx_buf_ioaddr_size));
return (NXGE_ERROR | err);
}
#ifdef DEBUG
ra = size = 0;
hverr = nxge_init_hv_fzc_lp_op(nxgep, (uint64_t)channel,
(uint64_t)0, N2NIU_TX_LP_INFO,
(uint64_t)&ra, (uint64_t)&size);
NXGE_DEBUG_MSG((nxgep, TX_CTL,
"==> nxge_init_hv_fzc_txdma_channel_pages: channel %d "
"ok status 0x%x "
"(page 0 data buf) hverr 0x%llx "
"set ioaddr_pp $%p "
"set size 0x%llx "
"get ra ioaddr_pp $%p "
"get size 0x%llx ",
channel,
err,
hverr,
tx_ring_p->hv_tx_buf_base_ioaddr_pp,
tx_ring_p->hv_tx_buf_ioaddr_size,
ra,
size));
#endif
NXGE_DEBUG_MSG((nxgep, TX_CTL,
"==> nxge_init_hv_fzc_txdma_channel_pages: channel %d "
"(page 0 data buf) hverr 0x%llx "
"ioaddr_pp $%p "
"size 0x%llx ",
channel,
hverr,
tx_ring_p->hv_tx_buf_base_ioaddr_pp,
tx_ring_p->hv_tx_buf_ioaddr_size));
/*
* Initialize logical page 2 for control buffers.
*/
hverr = nxge_init_hv_fzc_lp_op(nxgep, (uint64_t)channel,
(uint64_t)1, N2NIU_TX_LP_CONF,
tx_ring_p->hv_tx_cntl_base_ioaddr_pp,
tx_ring_p->hv_tx_cntl_ioaddr_size);
err = (nxge_status_t)nxge_herr2kerr(hverr);
NXGE_DEBUG_MSG((nxgep, TX_CTL,
"==> nxge_init_hv_fzc_txdma_channel_pages: channel %d"
"ok status 0x%x "
"(page 1 cntl buf) hverr 0x%llx "
"ioaddr_pp $%p "
"size 0x%llx ",
channel,
err,
hverr,
tx_ring_p->hv_tx_cntl_base_ioaddr_pp,
tx_ring_p->hv_tx_cntl_ioaddr_size));
if (err != 0) {
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"<== nxge_init_hv_fzc_txdma_channel_pages: channel %d"
"error status 0x%x "
"(page 1 cntl buf) hverr 0x%llx "
"ioaddr_pp $%p "
"size 0x%llx ",
channel,
err,
hverr,
tx_ring_p->hv_tx_cntl_base_ioaddr_pp,
tx_ring_p->hv_tx_cntl_ioaddr_size));
return (NXGE_ERROR | err);
}
#ifdef DEBUG
ra = size = 0;
hverr = nxge_init_hv_fzc_lp_op(nxgep, (uint64_t)channel,
(uint64_t)1, N2NIU_TX_LP_INFO,
(uint64_t)&ra, (uint64_t)&size);
NXGE_DEBUG_MSG((nxgep, TX_CTL,
"==> nxge_init_hv_fzc_txdma_channel_pages: channel %d "
"(page 1 cntl buf) hverr 0x%llx "
"set ioaddr_pp $%p "
"set size 0x%llx "
"get ra ioaddr_pp $%p "
"get size 0x%llx ",
channel,
hverr,
tx_ring_p->hv_tx_cntl_base_ioaddr_pp,
tx_ring_p->hv_tx_cntl_ioaddr_size,
ra,
size));
#endif
tx_ring_p->hv_set = B_TRUE;
NXGE_DEBUG_MSG((nxgep, TX_CTL,
"<== nxge_init_hv_fzc_txdma_channel_pages"));
return (NXGE_OK);
}
/*ARGSUSED*/
nxge_status_t
nxge_init_hv_fzc_rxdma_channel_pages(p_nxge_t nxgep,
uint16_t channel, p_rx_rbr_ring_t rbrp)
{
int err;
uint64_t hverr;
#ifdef DEBUG
uint64_t ra, size;
#endif
NXGE_DEBUG_MSG((nxgep, RX_CTL,
"==> nxge_init_hv_fzc_rxdma_channel_pages"));
if (rbrp->hv_set) {
return (NXGE_OK);
}
/* Initialize data buffers for page 0 */
hverr = nxge_init_hv_fzc_lp_op(nxgep, (uint64_t)channel,
(uint64_t)0, N2NIU_RX_LP_CONF,
rbrp->hv_rx_buf_base_ioaddr_pp,
rbrp->hv_rx_buf_ioaddr_size);
err = (nxge_status_t)nxge_herr2kerr(hverr);
if (err != 0) {
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"<== nxge_init_hv_fzc_rxdma_channel_pages: channel %d"
"error status 0x%x "
"(page 0 data buf) hverr 0x%llx "
"ioaddr_pp $%p "
"size 0x%llx ",
channel,
err,
hverr,
rbrp->hv_rx_buf_base_ioaddr_pp,
rbrp->hv_rx_buf_ioaddr_size));
return (NXGE_ERROR | err);
}
#ifdef DEBUG
ra = size = 0;
hverr = nxge_init_hv_fzc_lp_op(nxgep, (uint64_t)channel,
(uint64_t)0, N2NIU_RX_LP_INFO,
(uint64_t)&ra, (uint64_t)&size);
NXGE_DEBUG_MSG((nxgep, RX_CTL,
"==> nxge_init_hv_fzc_rxdma_channel_pages: channel %d "
"ok status 0x%x "
"(page 0 data buf) hverr 0x%llx "
"set databuf ioaddr_pp $%p "
"set databuf size 0x%llx "
"get databuf ra ioaddr_pp %p "
"get databuf size 0x%llx",
channel,
err,
hverr,
rbrp->hv_rx_buf_base_ioaddr_pp,
rbrp->hv_rx_buf_ioaddr_size,
ra,
size));
#endif
/* Initialize control buffers for logical page 1. */
hverr = nxge_init_hv_fzc_lp_op(nxgep, (uint64_t)channel,
(uint64_t)1, N2NIU_RX_LP_CONF,
rbrp->hv_rx_cntl_base_ioaddr_pp,
rbrp->hv_rx_cntl_ioaddr_size);
err = (nxge_status_t)nxge_herr2kerr(hverr);
if (err != 0) {
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"<== nxge_init_hv_fzc_rxdma_channel_pages: channel %d"
"error status 0x%x "
"(page 1 cntl buf) hverr 0x%llx "
"ioaddr_pp $%p "
"size 0x%llx ",
channel,
err,
hverr,
rbrp->hv_rx_buf_base_ioaddr_pp,
rbrp->hv_rx_buf_ioaddr_size));
return (NXGE_ERROR | err);
}
#ifdef DEBUG
ra = size = 0;
hverr = nxge_init_hv_fzc_lp_op(nxgep, (uint64_t)channel,
(uint64_t)1, N2NIU_RX_LP_INFO,
(uint64_t)&ra, (uint64_t)&size);
NXGE_DEBUG_MSG((nxgep, RX_CTL,
"==> nxge_init_hv_fzc_rxdma_channel_pages: channel %d "
"error status 0x%x "
"(page 1 cntl buf) hverr 0x%llx "
"set cntl ioaddr_pp $%p "
"set cntl size 0x%llx "
"get cntl ioaddr_pp $%p "
"get cntl size 0x%llx ",
channel,
err,
hverr,
rbrp->hv_rx_cntl_base_ioaddr_pp,
rbrp->hv_rx_cntl_ioaddr_size,
ra,
size));
#endif
rbrp->hv_set = B_FALSE;
NXGE_DEBUG_MSG((nxgep, RX_CTL,
"<== nxge_init_hv_fzc_rxdma_channel_pages"));
return (NXGE_OK);
}
/*
* Map hypervisor error code to errno. Only
* H_ENORADDR, H_EBADALIGN and H_EINVAL are meaningful
* for niu driver. Any other error codes are mapped to EINVAL.
*/
static int
nxge_herr2kerr(uint64_t hv_errcode)
{
int s_errcode;
switch (hv_errcode) {
case H_ENORADDR:
case H_EBADALIGN:
s_errcode = EFAULT;
break;
case H_EOK:
s_errcode = 0;
break;
default:
s_errcode = EINVAL;
break;
}
return (s_errcode);
}
uint64_t
nxge_init_hv_fzc_lp_op(p_nxge_t nxgep, uint64_t channel,
uint64_t page_no, uint64_t op_type,
uint64_t ioaddr_pp, uint64_t ioaddr_size)
{
uint64_t hverr;
uint64_t major;
nxge_hio_data_t *nhd = (nxge_hio_data_t *)nxgep->nxge_hw_p->hio;
nxhv_dc_fp_t *io_fp;
NXGE_DEBUG_MSG((nxgep, DMA_CTL,
"==> nxge_init_hv_fzc_lp_op"));
major = nxgep->niu_hsvc.hsvc_major;
NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL,
"==> nxge_init_hv_fzc_lp_op (major %d): channel %d op_type 0x%x "
"page_no %d ioaddr_pp $%p ioaddr_size 0x%llx",
major, channel, op_type, page_no, ioaddr_pp, ioaddr_size));
/* Call the transmit conf function. */
switch (major) {
case NIU_MAJOR_VER: /* 1 */
switch (op_type) {
case N2NIU_TX_LP_CONF:
io_fp = &nhd->hio.tx;
hverr = (*io_fp->lp_conf)((uint64_t)channel,
(uint64_t)page_no,
(uint64_t)ioaddr_pp,
(uint64_t)ioaddr_size);
NXGE_DEBUG_MSG((nxgep, DMA_CTL,
"==> nxge_init_hv_fzc_lp_op(tx_conf): major %d "
"op 0x%x hverr 0x%x", major, op_type, hverr));
break;
case N2NIU_TX_LP_INFO:
io_fp = &nhd->hio.tx;
hverr = (*io_fp->lp_info)((uint64_t)channel,
(uint64_t)page_no,
(uint64_t *)ioaddr_pp,
(uint64_t *)ioaddr_size);
break;
case N2NIU_RX_LP_CONF:
io_fp = &nhd->hio.rx;
hverr = (*io_fp->lp_conf)((uint64_t)channel,
(uint64_t)page_no,
(uint64_t)ioaddr_pp,
(uint64_t)ioaddr_size);
break;
case N2NIU_RX_LP_INFO:
io_fp = &nhd->hio.rx;
hverr = (*io_fp->lp_info)((uint64_t)channel,
(uint64_t)page_no,
(uint64_t *)ioaddr_pp,
(uint64_t *)ioaddr_size);
NXGE_DEBUG_MSG((nxgep, DMA_CTL,
"==> nxge_init_hv_fzc_lp_op(rx_conf): major %d "
"op 0x%x hverr 0x%x", major, op_type, hverr));
break;
default:
hverr = EINVAL;
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"==> nxge_init_hv_fzc_lp_op(rx_conf): major %d "
"invalid op 0x%x hverr 0x%x", major,
op_type, hverr));
break;
}
break;
case NIU_MAJOR_VER_2: /* 2 */
switch (op_type) {
case N2NIU_TX_LP_CONF:
io_fp = &nhd->hio.tx;
hverr = (*io_fp->lp_cfgh_conf)(nxgep->niu_cfg_hdl,
(uint64_t)channel,
(uint64_t)page_no, ioaddr_pp, ioaddr_size);
NXGE_DEBUG_MSG((nxgep, DMA_CTL,
"==> nxge_init_hv_fzc_lp_op(tx_conf): major %d "
"op 0x%x hverr 0x%x", major, op_type, hverr));
break;
case N2NIU_TX_LP_INFO:
io_fp = &nhd->hio.tx;
hverr = (*io_fp->lp_cfgh_info)(nxgep->niu_cfg_hdl,
(uint64_t)channel,
(uint64_t)page_no,
(uint64_t *)ioaddr_pp,
(uint64_t *)ioaddr_size);
break;
case N2NIU_RX_LP_CONF:
io_fp = &nhd->hio.rx;
hverr = (*io_fp->lp_cfgh_conf)(nxgep->niu_cfg_hdl,
(uint64_t)channel,
(uint64_t)page_no,
(uint64_t)ioaddr_pp,
(uint64_t)ioaddr_size);
NXGE_DEBUG_MSG((nxgep, DMA_CTL,
"==> nxge_init_hv_fzc_lp_op(rx_conf): major %d "
"hverr 0x%x", major, hverr));
break;
case N2NIU_RX_LP_INFO:
io_fp = &nhd->hio.rx;
hverr = (*io_fp->lp_cfgh_info)(nxgep->niu_cfg_hdl,
(uint64_t)channel,
(uint64_t)page_no,
(uint64_t *)ioaddr_pp,
(uint64_t *)ioaddr_size);
break;
default:
hverr = EINVAL;
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"==> nxge_init_hv_fzc_lp_op(rx_conf): major %d "
"invalid op 0x%x hverr 0x%x", major,
op_type, hverr));
break;
}
break;
default:
hverr = EINVAL;
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"==> nxge_init_hv_fzc_lp_op(rx_conf): invalid major %d "
"op 0x%x hverr 0x%x", major, op_type, hverr));
break;
}
NXGE_DEBUG_MSG((nxgep, DMA_CTL,
"<== nxge_init_hv_fzc_lp_op: 0x%x", hverr));
return (hverr);
}
#endif /* sun4v and NIU_LP_WORKAROUND */