Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.15.
  1// SPDX-License-Identifier: GPL-2.0
  2/* Copyright (c)  2020 Intel Corporation */
  3
  4#include "igc.h"
  5#include "igc_diag.h"
  6
  7static struct igc_reg_test reg_test[] = {
  8	{ IGC_FCAL,	1,	PATTERN_TEST,	0xFFFFFFFF,	0xFFFFFFFF },
  9	{ IGC_FCAH,	1,	PATTERN_TEST,	0x0000FFFF,	0xFFFFFFFF },
 10	{ IGC_FCT,	1,	PATTERN_TEST,	0x0000FFFF,	0xFFFFFFFF },
 11	{ IGC_RDBAH(0), 4,	PATTERN_TEST,	0xFFFFFFFF,	0xFFFFFFFF },
 12	{ IGC_RDBAL(0),	4,	PATTERN_TEST,	0xFFFFFF80,	0xFFFFFF80 },
 13	{ IGC_RDLEN(0),	4,	PATTERN_TEST,	0x000FFF80,	0x000FFFFF },
 14	{ IGC_RDT(0),	4,	PATTERN_TEST,	0x0000FFFF,	0x0000FFFF },
 15	{ IGC_FCRTH,	1,	PATTERN_TEST,	0x0003FFF0,	0x0003FFF0 },
 16	{ IGC_FCTTV,	1,	PATTERN_TEST,	0x0000FFFF,	0x0000FFFF },
 17	{ IGC_TIPG,	1,	PATTERN_TEST,	0x3FFFFFFF,	0x3FFFFFFF },
 18	{ IGC_TDBAH(0),	4,	PATTERN_TEST,	0xFFFFFFFF,	0xFFFFFFFF },
 19	{ IGC_TDBAL(0),	4,	PATTERN_TEST,	0xFFFFFF80,	0xFFFFFF80 },
 20	{ IGC_TDLEN(0),	4,	PATTERN_TEST,	0x000FFF80,	0x000FFFFF },
 21	{ IGC_TDT(0),	4,	PATTERN_TEST,	0x0000FFFF,	0x0000FFFF },
 22	{ IGC_RCTL,	1,	SET_READ_TEST,	0xFFFFFFFF,	0x00000000 },
 23	{ IGC_RCTL,	1,	SET_READ_TEST,	0x04CFB2FE,	0x003FFFFB },
 24	{ IGC_RCTL,	1,	SET_READ_TEST,	0x04CFB2FE,	0xFFFFFFFF },
 25	{ IGC_TCTL,	1,	SET_READ_TEST,	0xFFFFFFFF,	0x00000000 },
 26	{ IGC_RA,	16,	TABLE64_TEST_LO,
 27						0xFFFFFFFF,	0xFFFFFFFF },
 28	{ IGC_RA,	16,	TABLE64_TEST_HI,
 29						0x900FFFFF,	0xFFFFFFFF },
 30	{ IGC_MTA,	128,	TABLE32_TEST,
 31						0xFFFFFFFF,	0xFFFFFFFF },
 32	{ 0, 0, 0, 0}
 33};
 34
 35static bool reg_pattern_test(struct igc_adapter *adapter, u64 *data, int reg,
 36			     u32 mask, u32 write)
 37{
 38	struct igc_hw *hw = &adapter->hw;
 39	u32 pat, val, before;
 40	static const u32 test_pattern[] = {
 41		0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF
 42	};
 43
 44	for (pat = 0; pat < ARRAY_SIZE(test_pattern); pat++) {
 45		before = rd32(reg);
 46		wr32(reg, test_pattern[pat] & write);
 47		val = rd32(reg);
 48		if (val != (test_pattern[pat] & write & mask)) {
 49			netdev_err(adapter->netdev,
 50				   "pattern test reg %04X failed: got 0x%08X expected 0x%08X",
 51				   reg, val, test_pattern[pat] & write & mask);
 52			*data = reg;
 53			wr32(reg, before);
 54			return false;
 55		}
 56		wr32(reg, before);
 57	}
 58	return true;
 59}
 60
 61static bool reg_set_and_check(struct igc_adapter *adapter, u64 *data, int reg,
 62			      u32 mask, u32 write)
 63{
 64	struct igc_hw *hw = &adapter->hw;
 65	u32 val, before;
 66
 67	before = rd32(reg);
 68	wr32(reg, write & mask);
 69	val = rd32(reg);
 70	if ((write & mask) != (val & mask)) {
 71		netdev_err(adapter->netdev,
 72			   "set/check reg %04X test failed: got 0x%08X expected 0x%08X",
 73			   reg, (val & mask), (write & mask));
 74		*data = reg;
 75		wr32(reg, before);
 76		return false;
 77	}
 78	wr32(reg, before);
 79	return true;
 80}
 81
 82bool igc_reg_test(struct igc_adapter *adapter, u64 *data)
 83{
 84	struct igc_reg_test *test = reg_test;
 85	struct igc_hw *hw = &adapter->hw;
 86	u32 value, before, after;
 87	u32 i, toggle, b = false;
 88
 89	/* Because the status register is such a special case,
 90	 * we handle it separately from the rest of the register
 91	 * tests.  Some bits are read-only, some toggle, and some
 92	 * are writeable.
 93	 */
 94	toggle = 0x6800D3;
 95	before = rd32(IGC_STATUS);
 96	value = before & toggle;
 97	wr32(IGC_STATUS, toggle);
 98	after = rd32(IGC_STATUS) & toggle;
 99	if (value != after) {
100		netdev_err(adapter->netdev,
101			   "failed STATUS register test got: 0x%08X expected: 0x%08X",
102			   after, value);
103		*data = 1;
104		return false;
105	}
106	/* restore previous status */
107	wr32(IGC_STATUS, before);
108
109	/* Perform the remainder of the register test, looping through
110	 * the test table until we either fail or reach the null entry.
111	 */
112	while (test->reg) {
113		for (i = 0; i < test->array_len; i++) {
114			switch (test->test_type) {
115			case PATTERN_TEST:
116				b = reg_pattern_test(adapter, data,
117						     test->reg + (i * 0x40),
118						     test->mask,
119						     test->write);
120				break;
121			case SET_READ_TEST:
122				b = reg_set_and_check(adapter, data,
123						      test->reg + (i * 0x40),
124						      test->mask,
125						      test->write);
126				break;
127			case TABLE64_TEST_LO:
128				b = reg_pattern_test(adapter, data,
129						     test->reg + (i * 8),
130						     test->mask,
131						     test->write);
132				break;
133			case TABLE64_TEST_HI:
134				b = reg_pattern_test(adapter, data,
135						     test->reg + 4 + (i * 8),
136						     test->mask,
137						     test->write);
138				break;
139			case TABLE32_TEST:
140				b = reg_pattern_test(adapter, data,
141						     test->reg + (i * 4),
142						     test->mask,
143						     test->write);
144				break;
145			}
146			if (!b)
147				return false;
148		}
149		test++;
150	}
151	*data = 0;
152	return true;
153}
154
155bool igc_eeprom_test(struct igc_adapter *adapter, u64 *data)
156{
157	struct igc_hw *hw = &adapter->hw;
158
159	*data = 0;
160
161	if (hw->nvm.ops.validate(hw) != IGC_SUCCESS) {
162		*data = 1;
163		return false;
164	}
165
166	return true;
167}
168
169bool igc_link_test(struct igc_adapter *adapter, u64 *data)
170{
171	bool link_up;
172
173	*data = 0;
174
175	/* add delay to give enough time for autonegotioation to finish */
176	ssleep(5);
177
178	link_up = igc_has_link(adapter);
179	if (!link_up) {
180		*data = 1;
181		return false;
182	}
183
184	return true;
185}