diff options
Diffstat (limited to 'drivers/net/ethernet/intel/i40e/i40e_diag.c')
| -rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_diag.c | 154 | 
1 files changed, 154 insertions, 0 deletions
diff --git a/drivers/net/ethernet/intel/i40e/i40e_diag.c b/drivers/net/ethernet/intel/i40e/i40e_diag.c new file mode 100644 index 00000000000..56438bd579e --- /dev/null +++ b/drivers/net/ethernet/intel/i40e/i40e_diag.c @@ -0,0 +1,154 @@ +/******************************************************************************* + * + * Intel Ethernet Controller XL710 Family Linux Driver + * Copyright(c) 2013 - 2014 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program.  If not, see <http://www.gnu.org/licenses/>. + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Contact Information: + * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net> + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + ******************************************************************************/ + +#include "i40e_diag.h" +#include "i40e_prototype.h" + +/** + * i40e_diag_reg_pattern_test + * @hw: pointer to the hw struct + * @reg: reg to be tested + * @mask: bits to be touched + **/ +static i40e_status i40e_diag_reg_pattern_test(struct i40e_hw *hw, +							u32 reg, u32 mask) +{ +	const u32 patterns[] = {0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF}; +	u32 pat, val, orig_val; +	int i; + +	orig_val = rd32(hw, reg); +	for (i = 0; i < ARRAY_SIZE(patterns); i++) { +		pat = patterns[i]; +		wr32(hw, reg, (pat & mask)); +		val = rd32(hw, reg); +		if ((val & mask) != (pat & mask)) { +			i40e_debug(hw, I40E_DEBUG_DIAG, +				   "%s: reg pattern test failed - reg 0x%08x pat 0x%08x val 0x%08x\n", +				   __func__, reg, pat, val); +			return I40E_ERR_DIAG_TEST_FAILED; +		} +	} + +	wr32(hw, reg, orig_val); +	val = rd32(hw, reg); +	if (val != orig_val) { +		i40e_debug(hw, I40E_DEBUG_DIAG, +			   "%s: reg restore test failed - reg 0x%08x orig_val 0x%08x val 0x%08x\n", +			   __func__, reg, orig_val, val); +		return I40E_ERR_DIAG_TEST_FAILED; +	} + +	return 0; +} + +struct i40e_diag_reg_test_info i40e_reg_list[] = { +	/* offset               mask         elements   stride */ +	{I40E_QTX_CTL(0),       0x0000FFBF, 1, +		I40E_QTX_CTL(1) - I40E_QTX_CTL(0)}, +	{I40E_PFINT_ITR0(0),    0x00000FFF, 3, +		I40E_PFINT_ITR0(1) - I40E_PFINT_ITR0(0)}, +	{I40E_PFINT_ITRN(0, 0), 0x00000FFF, 1, +		I40E_PFINT_ITRN(0, 1) - I40E_PFINT_ITRN(0, 0)}, +	{I40E_PFINT_ITRN(1, 0), 0x00000FFF, 1, +		I40E_PFINT_ITRN(1, 1) - I40E_PFINT_ITRN(1, 0)}, +	{I40E_PFINT_ITRN(2, 0), 0x00000FFF, 1, +		I40E_PFINT_ITRN(2, 1) - I40E_PFINT_ITRN(2, 0)}, +	{I40E_PFINT_STAT_CTL0,  0x0000000C, 1, 0}, +	{I40E_PFINT_LNKLST0,    0x00001FFF, 1, 0}, +	{I40E_PFINT_LNKLSTN(0), 0x000007FF, 1, +		I40E_PFINT_LNKLSTN(1) - I40E_PFINT_LNKLSTN(0)}, +	{I40E_QINT_TQCTL(0),    0x000000FF, 1, +		I40E_QINT_TQCTL(1) - I40E_QINT_TQCTL(0)}, +	{I40E_QINT_RQCTL(0),    0x000000FF, 1, +		I40E_QINT_RQCTL(1) - I40E_QINT_RQCTL(0)}, +	{I40E_PFINT_ICR0_ENA,   0xF7F20000, 1, 0}, +	{ 0 } +}; + +/** + * i40e_diag_reg_test + * @hw: pointer to the hw struct + * + * Perform registers diagnostic test + **/ +i40e_status i40e_diag_reg_test(struct i40e_hw *hw) +{ +	i40e_status ret_code = 0; +	u32 reg, mask; +	u32 i, j; + +	for (i = 0; i40e_reg_list[i].offset != 0 && +					     !ret_code; i++) { + +		/* set actual reg range for dynamically allocated resources */ +		if (i40e_reg_list[i].offset == I40E_QTX_CTL(0) && +		    hw->func_caps.num_tx_qp != 0) +			i40e_reg_list[i].elements = hw->func_caps.num_tx_qp; +		if ((i40e_reg_list[i].offset == I40E_PFINT_ITRN(0, 0) || +		     i40e_reg_list[i].offset == I40E_PFINT_ITRN(1, 0) || +		     i40e_reg_list[i].offset == I40E_PFINT_ITRN(2, 0) || +		     i40e_reg_list[i].offset == I40E_QINT_TQCTL(0) || +		     i40e_reg_list[i].offset == I40E_QINT_RQCTL(0)) && +		    hw->func_caps.num_msix_vectors != 0) +			i40e_reg_list[i].elements = +				hw->func_caps.num_msix_vectors - 1; + +		/* test register access */ +		mask = i40e_reg_list[i].mask; +		for (j = 0; j < i40e_reg_list[i].elements && !ret_code; j++) { +			reg = i40e_reg_list[i].offset + +			      (j * i40e_reg_list[i].stride); +			ret_code = i40e_diag_reg_pattern_test(hw, reg, mask); +		} +	} + +	return ret_code; +} + +/** + * i40e_diag_eeprom_test + * @hw: pointer to the hw struct + * + * Perform EEPROM diagnostic test + **/ +i40e_status i40e_diag_eeprom_test(struct i40e_hw *hw) +{ +	i40e_status ret_code; +	u16 reg_val; + +	/* read NVM control word and if NVM valid, validate EEPROM checksum*/ +	ret_code = i40e_read_nvm_word(hw, I40E_SR_NVM_CONTROL_WORD, ®_val); +	if (!ret_code && +	    ((reg_val & I40E_SR_CONTROL_WORD_1_MASK) == +	     (0x01 << I40E_SR_CONTROL_WORD_1_SHIFT))) { +		ret_code = i40e_validate_nvm_checksum(hw, NULL); +	} else { +		ret_code = I40E_ERR_DIAG_TEST_FAILED; +	} + +	return ret_code; +}  | 
