cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

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}