igc_diag.c (4970B)
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 if (adapter->hw.mac.autoneg) 177 ssleep(5); 178 179 link_up = igc_has_link(adapter); 180 if (!link_up) { 181 *data = 1; 182 return false; 183 } 184 185 return true; 186}