nxge_ipp.c revision 59ac0c1669407488b67ae9e273667a340dccc611
/*
* 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
* 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 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <nxge_impl.h>
#include <nxge_ipp.h>
#define NXGE_IPP_FIFO_SYNC_TRY_COUNT 100
/* ARGSUSED */
{
int i;
/* Initialize ECC and parity in SRAM of DFIFO and PFIFO */
if (portn < 2)
else
} else {
goto fail;
}
for (i = 0; i < dfifo_entries; i++) {
portn, i, 0, 0, 0, 0, 0)) != NPI_SUCCESS)
goto fail;
goto fail;
}
/* Clear PFIFO DFIFO status bits */
goto fail;
goto fail;
/*
* Soft reset to make sure we bring the FIFO pointers back to the
* original initial position.
*/
goto fail;
/* Clean up ECC counter */
goto fail;
/* Configure IPP port */
!= NPI_SUCCESS)
goto fail;
goto fail;
/* Set max packet size */
IPP_MAX_PKT_SIZE)) != NPI_SUCCESS)
goto fail;
return (NXGE_OK);
fail:
"nxge_ipp_init: Fail to initialize IPP Port #%d\n",
portn));
return (NXGE_ERROR | rs);
}
/* ARGSUSED */
{
(void) nxge_rx_mac_disable(nxgep);
/*
* Wait until ip read and write fifo pointers are equal
*/
try_count--;
}
if (try_count == 0) {
" nxge_ipp_disable: port%d failed"
" rd_fifo != wr_fifo", portn));
goto fail;
}
}
/* disable the IPP */
goto fail;
/* IPP soft reset */
goto fail;
return (NXGE_OK);
fail:
"nxge_ipp_disable: Fail to disable IPP Port #%d\n", portn));
return (NXGE_ERROR | rs);
}
/* ARGSUSED */
{
/* disable the IPP */
goto fail;
/*
* Wait until ip read and write fifo pointers are equal
*/
try_count--;
}
if (try_count == 0) {
" nxge_ipp_disable: port%d failed"
" rd_fifo != wr_fifo", portn));
goto fail;
}
}
/* IPP soft reset */
goto fail;
}
/* to reset control FIFO */
goto fail;
/*
* Making sure that error source is cleared if this is an injected
* error.
*/
return (NXGE_OK);
fail:
"nxge_ipp_init: Fail to Reset IPP Port #%d\n",
portn));
return (NXGE_ERROR | rs);
}
/* ARGSUSED */
{
goto fail;
/* Set max packet size */
IPP_MAX_PKT_SIZE)) != NPI_SUCCESS)
goto fail;
return (NXGE_OK);
fail:
"nxge_ipp_init: Fail to Enable IPP Port #%d\n", portn));
return (NXGE_ERROR | rs);
}
/* ARGSUSED */
{
return (NXGE_ERROR | rs);
/*
* The error is not initiated from this port, so just exit.
*/
return (NXGE_OK);
}
return (NXGE_ERROR | rs);
return (NXGE_ERROR | rs);
"nxge_ipp_err_evnts: fatal error: sop_miss\n"));
}
return (NXGE_ERROR | rs);
return (NXGE_ERROR | rs);
"nxge_ipp_err_evnts: fatal error: eop_miss\n"));
}
&ue_ecc_valid)) != NXGE_OK)
return (status);
if (ue_ecc_valid) {
return (NXGE_ERROR | rs);
"nxge_ipp_err_evnts: fatal error: dfifo_ue\n"));
}
}
statsp->pfifo_perr++;
"nxge_ipp_err_evnts: "
"fatal error: pre_pifo_perr\n"));
}
statsp->pfifo_over++;
"nxge_ipp_err_evnts: "
"fatal error: pfifo_over\n"));
}
"nxge_ipp_err_evnts: "
"fatal error: pfifo_und\n"));
}
"nxge_ipp_err_evnts: bad_cs_max\n"));
}
"nxge_ipp_err_evnts: pkt_dis_max\n"));
}
/*
* Making sure that error source is cleared if this is an injected
* error.
*/
if (rxport_fatal) {
" nxge_ipp_handle_sys_errors:"
" fatal Error on Port #%d\n", portn));
}
}
return (status);
}
/* ARGSUSED */
void
{
switch (err_id) {
break;
break;
if (err_id == NXGE_FM_EREPORT_IPP_EOP_MISS)
else if (err_id == NXGE_FM_EREPORT_IPP_SOP_MISS)
else if (err_id == NXGE_FM_EREPORT_IPP_DFIFO_UE)
else if (err_id == NXGE_FM_EREPORT_IPP_DFIFO_CE)
else if (err_id == NXGE_FM_EREPORT_IPP_PFIFO_PERR)
else if (err_id == NXGE_FM_EREPORT_IPP_ECC_ERR_MAX)
else if (err_id == NXGE_FM_EREPORT_IPP_PFIFO_OVER)
else if (err_id == NXGE_FM_EREPORT_IPP_PFIFO_UND)
else if (err_id == NXGE_FM_EREPORT_IPP_BAD_CS_MX)
else if (err_id == NXGE_FM_EREPORT_IPP_PKT_DIS_MX)
break;
}
}
/* ARGSUSED */
{
int i;
"Recovering from RxPort error..."));
/*
* Making sure that error source is cleared if this is an injected
* error.
*/
/* Disable RxMAC */
goto fail;
/* When recovering from IPP, RxDMA channel resets are not necessary */
/* Reset ZCP CFIFO */
goto fail;
/*
* Wait until ip read and write fifo pointers are equal
*/
try_count = 512;
try_count--;
}
if (try_count == 0) {
" nxge_ipp_reset: port%d IPP stalled..."
" rd_fifo_ptr = 0x%x wr_fifo_ptr = 0x%x",
/*
* This means the fatal error occurred on the first line of the
* fifo. In this case, just reset the IPP without draining the
* PFIFO.
*/
}
if (portn < 2)
else
} else {
goto fail;
}
/* Clean up DFIFO SRAM entries */
for (i = 0; i < dfifo_entries; i++) {
i, 0, 0, 0, 0, 0)) != NPI_SUCCESS)
goto fail;
goto fail;
}
/* Clear PFIFO DFIFO status bits */
goto fail;
goto fail;
/* Reset IPP */
goto fail;
goto fail;
goto fail;
goto fail;
"Recovery Sucessful, RxPort Restored"));
return (NXGE_OK);
fail:
}
/* ARGSUSED */
/*
* A hardware bug may cause a faked ECCUE(ECC Uncorrectable Error).
* This function checks if a ECCUE is real(valid) or not. It is not
* real if rd_ptr == wr_ptr.
* The hardware module that has the bug is used not only by the IPP
* FIFO but also by the ZCP FIFO, therefore this function is also
* called by nxge_zcp_handle_sys_errors for validating the ZCP FIFO
* error.
*/
{
!= NPI_SUCCESS)
goto fail;
!= NPI_SUCCESS)
goto fail;
} else {
stall_cnt = 0;
while (stall_cnt < 16) {
goto fail;
goto fail;
stall_cnt++;
else {
break;
}
}
if (valid) {
/* futher check to see if ECC UE is valid */
&d4)) != NPI_SUCCESS)
goto fail;
}
}
return (NXGE_OK);
fail:
return (NXGE_ERROR | rs);
}