mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	igc: add support to eeprom, registers and link self-tests
Introduced igc_diag.c and igc_diag.h, these files have the diagnostics functionality of igc driver. For the time being these files are being used by ethtool self-test callbacks. Which mean that eeprom, registers and link self-tests for ethtool were implemented. Signed-off-by: Vitaly Lifshits <vitaly.lifshits@intel.com> Reported-by: kbuild test robot <lkp@intel.com> Reported-by: Dan Carpenter <dan.carpenter@oracle.com> Tested-by: Aaron Brown <aaron.f.brown@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
This commit is contained in:
		
							parent
							
								
									25f06eff75
								
							
						
					
					
						commit
						f026d8ca29
					
				
					 7 changed files with 285 additions and 3 deletions
				
			
		| 
						 | 
					@ -8,4 +8,4 @@
 | 
				
			||||||
obj-$(CONFIG_IGC) += igc.o
 | 
					obj-$(CONFIG_IGC) += igc.o
 | 
				
			||||||
 | 
					
 | 
				
			||||||
igc-objs := igc_main.o igc_mac.o igc_i225.o igc_base.o igc_nvm.o igc_phy.o \
 | 
					igc-objs := igc_main.o igc_mac.o igc_i225.o igc_base.o igc_nvm.o igc_phy.o \
 | 
				
			||||||
igc_ethtool.o igc_ptp.o igc_dump.o igc_tsn.o
 | 
					igc_diag.o igc_ethtool.o igc_ptp.o igc_dump.o igc_tsn.o
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -198,6 +198,8 @@ struct igc_adapter {
 | 
				
			||||||
	unsigned long link_check_timeout;
 | 
						unsigned long link_check_timeout;
 | 
				
			||||||
	struct igc_info ei;
 | 
						struct igc_info ei;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						u32 test_icr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct ptp_clock *ptp_clock;
 | 
						struct ptp_clock *ptp_clock;
 | 
				
			||||||
	struct ptp_clock_info ptp_caps;
 | 
						struct ptp_clock_info ptp_caps;
 | 
				
			||||||
	struct work_struct ptp_tx_work;
 | 
						struct work_struct ptp_tx_work;
 | 
				
			||||||
| 
						 | 
					@ -215,6 +217,8 @@ struct igc_adapter {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void igc_up(struct igc_adapter *adapter);
 | 
					void igc_up(struct igc_adapter *adapter);
 | 
				
			||||||
void igc_down(struct igc_adapter *adapter);
 | 
					void igc_down(struct igc_adapter *adapter);
 | 
				
			||||||
 | 
					int igc_open(struct net_device *netdev);
 | 
				
			||||||
 | 
					int igc_close(struct net_device *netdev);
 | 
				
			||||||
int igc_setup_tx_resources(struct igc_ring *ring);
 | 
					int igc_setup_tx_resources(struct igc_ring *ring);
 | 
				
			||||||
int igc_setup_rx_resources(struct igc_ring *ring);
 | 
					int igc_setup_rx_resources(struct igc_ring *ring);
 | 
				
			||||||
void igc_free_tx_resources(struct igc_ring *ring);
 | 
					void igc_free_tx_resources(struct igc_ring *ring);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										186
									
								
								drivers/net/ethernet/intel/igc/igc_diag.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										186
									
								
								drivers/net/ethernet/intel/igc/igc_diag.c
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,186 @@
 | 
				
			||||||
 | 
					// SPDX-License-Identifier: GPL-2.0
 | 
				
			||||||
 | 
					/* Copyright (c)  2020 Intel Corporation */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "igc.h"
 | 
				
			||||||
 | 
					#include "igc_diag.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct igc_reg_test reg_test[] = {
 | 
				
			||||||
 | 
						{ IGC_FCAL,	1,	PATTERN_TEST,	0xFFFFFFFF,	0xFFFFFFFF },
 | 
				
			||||||
 | 
						{ IGC_FCAH,	1,	PATTERN_TEST,	0x0000FFFF,	0xFFFFFFFF },
 | 
				
			||||||
 | 
						{ IGC_FCT,	1,	PATTERN_TEST,	0x0000FFFF,	0xFFFFFFFF },
 | 
				
			||||||
 | 
						{ IGC_RDBAH(0), 4,	PATTERN_TEST,	0xFFFFFFFF,	0xFFFFFFFF },
 | 
				
			||||||
 | 
						{ IGC_RDBAL(0),	4,	PATTERN_TEST,	0xFFFFFF80,	0xFFFFFF80 },
 | 
				
			||||||
 | 
						{ IGC_RDLEN(0),	4,	PATTERN_TEST,	0x000FFF80,	0x000FFFFF },
 | 
				
			||||||
 | 
						{ IGC_RDT(0),	4,	PATTERN_TEST,	0x0000FFFF,	0x0000FFFF },
 | 
				
			||||||
 | 
						{ IGC_FCRTH,	1,	PATTERN_TEST,	0x0003FFF0,	0x0003FFF0 },
 | 
				
			||||||
 | 
						{ IGC_FCTTV,	1,	PATTERN_TEST,	0x0000FFFF,	0x0000FFFF },
 | 
				
			||||||
 | 
						{ IGC_TIPG,	1,	PATTERN_TEST,	0x3FFFFFFF,	0x3FFFFFFF },
 | 
				
			||||||
 | 
						{ IGC_TDBAH(0),	4,	PATTERN_TEST,	0xFFFFFFFF,	0xFFFFFFFF },
 | 
				
			||||||
 | 
						{ IGC_TDBAL(0),	4,	PATTERN_TEST,	0xFFFFFF80,	0xFFFFFF80 },
 | 
				
			||||||
 | 
						{ IGC_TDLEN(0),	4,	PATTERN_TEST,	0x000FFF80,	0x000FFFFF },
 | 
				
			||||||
 | 
						{ IGC_TDT(0),	4,	PATTERN_TEST,	0x0000FFFF,	0x0000FFFF },
 | 
				
			||||||
 | 
						{ IGC_RCTL,	1,	SET_READ_TEST,	0xFFFFFFFF,	0x00000000 },
 | 
				
			||||||
 | 
						{ IGC_RCTL,	1,	SET_READ_TEST,	0x04CFB2FE,	0x003FFFFB },
 | 
				
			||||||
 | 
						{ IGC_RCTL,	1,	SET_READ_TEST,	0x04CFB2FE,	0xFFFFFFFF },
 | 
				
			||||||
 | 
						{ IGC_TCTL,	1,	SET_READ_TEST,	0xFFFFFFFF,	0x00000000 },
 | 
				
			||||||
 | 
						{ IGC_RA,	16,	TABLE64_TEST_LO,
 | 
				
			||||||
 | 
											0xFFFFFFFF,	0xFFFFFFFF },
 | 
				
			||||||
 | 
						{ IGC_RA,	16,	TABLE64_TEST_HI,
 | 
				
			||||||
 | 
											0x900FFFFF,	0xFFFFFFFF },
 | 
				
			||||||
 | 
						{ IGC_MTA,	128,	TABLE32_TEST,
 | 
				
			||||||
 | 
											0xFFFFFFFF,	0xFFFFFFFF },
 | 
				
			||||||
 | 
						{ 0, 0, 0, 0}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool reg_pattern_test(struct igc_adapter *adapter, u64 *data, int reg,
 | 
				
			||||||
 | 
								     u32 mask, u32 write)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct igc_hw *hw = &adapter->hw;
 | 
				
			||||||
 | 
						u32 pat, val, before;
 | 
				
			||||||
 | 
						static const u32 test_pattern[] = {
 | 
				
			||||||
 | 
							0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (pat = 0; pat < ARRAY_SIZE(test_pattern); pat++) {
 | 
				
			||||||
 | 
							before = rd32(reg);
 | 
				
			||||||
 | 
							wr32(reg, test_pattern[pat] & write);
 | 
				
			||||||
 | 
							val = rd32(reg);
 | 
				
			||||||
 | 
							if (val != (test_pattern[pat] & write & mask)) {
 | 
				
			||||||
 | 
								netdev_err(adapter->netdev,
 | 
				
			||||||
 | 
									   "pattern test reg %04X failed: got 0x%08X expected 0x%08X",
 | 
				
			||||||
 | 
									   reg, val, test_pattern[pat] & write & mask);
 | 
				
			||||||
 | 
								*data = reg;
 | 
				
			||||||
 | 
								wr32(reg, before);
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							wr32(reg, before);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool reg_set_and_check(struct igc_adapter *adapter, u64 *data, int reg,
 | 
				
			||||||
 | 
								      u32 mask, u32 write)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct igc_hw *hw = &adapter->hw;
 | 
				
			||||||
 | 
						u32 val, before;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						before = rd32(reg);
 | 
				
			||||||
 | 
						wr32(reg, write & mask);
 | 
				
			||||||
 | 
						val = rd32(reg);
 | 
				
			||||||
 | 
						if ((write & mask) != (val & mask)) {
 | 
				
			||||||
 | 
							netdev_err(adapter->netdev,
 | 
				
			||||||
 | 
								   "set/check reg %04X test failed: got 0x%08X expected 0x%08X",
 | 
				
			||||||
 | 
								   reg, (val & mask), (write & mask));
 | 
				
			||||||
 | 
							*data = reg;
 | 
				
			||||||
 | 
							wr32(reg, before);
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						wr32(reg, before);
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool igc_reg_test(struct igc_adapter *adapter, u64 *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct igc_reg_test *test = reg_test;
 | 
				
			||||||
 | 
						struct igc_hw *hw = &adapter->hw;
 | 
				
			||||||
 | 
						u32 value, before, after;
 | 
				
			||||||
 | 
						u32 i, toggle, b = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Because the status register is such a special case,
 | 
				
			||||||
 | 
						 * we handle it separately from the rest of the register
 | 
				
			||||||
 | 
						 * tests.  Some bits are read-only, some toggle, and some
 | 
				
			||||||
 | 
						 * are writeable.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						toggle = 0x6800D3;
 | 
				
			||||||
 | 
						before = rd32(IGC_STATUS);
 | 
				
			||||||
 | 
						value = before & toggle;
 | 
				
			||||||
 | 
						wr32(IGC_STATUS, toggle);
 | 
				
			||||||
 | 
						after = rd32(IGC_STATUS) & toggle;
 | 
				
			||||||
 | 
						if (value != after) {
 | 
				
			||||||
 | 
							netdev_err(adapter->netdev,
 | 
				
			||||||
 | 
								   "failed STATUS register test got: 0x%08X expected: 0x%08X",
 | 
				
			||||||
 | 
								   after, value);
 | 
				
			||||||
 | 
							*data = 1;
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						/* restore previous status */
 | 
				
			||||||
 | 
						wr32(IGC_STATUS, before);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Perform the remainder of the register test, looping through
 | 
				
			||||||
 | 
						 * the test table until we either fail or reach the null entry.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						while (test->reg) {
 | 
				
			||||||
 | 
							for (i = 0; i < test->array_len; i++) {
 | 
				
			||||||
 | 
								switch (test->test_type) {
 | 
				
			||||||
 | 
								case PATTERN_TEST:
 | 
				
			||||||
 | 
									b = reg_pattern_test(adapter, data,
 | 
				
			||||||
 | 
											     test->reg + (i * 0x40),
 | 
				
			||||||
 | 
											     test->mask,
 | 
				
			||||||
 | 
											     test->write);
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								case SET_READ_TEST:
 | 
				
			||||||
 | 
									b = reg_set_and_check(adapter, data,
 | 
				
			||||||
 | 
											      test->reg + (i * 0x40),
 | 
				
			||||||
 | 
											      test->mask,
 | 
				
			||||||
 | 
											      test->write);
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								case TABLE64_TEST_LO:
 | 
				
			||||||
 | 
									b = reg_pattern_test(adapter, data,
 | 
				
			||||||
 | 
											     test->reg + (i * 8),
 | 
				
			||||||
 | 
											     test->mask,
 | 
				
			||||||
 | 
											     test->write);
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								case TABLE64_TEST_HI:
 | 
				
			||||||
 | 
									b = reg_pattern_test(adapter, data,
 | 
				
			||||||
 | 
											     test->reg + 4 + (i * 8),
 | 
				
			||||||
 | 
											     test->mask,
 | 
				
			||||||
 | 
											     test->write);
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								case TABLE32_TEST:
 | 
				
			||||||
 | 
									b = reg_pattern_test(adapter, data,
 | 
				
			||||||
 | 
											     test->reg + (i * 4),
 | 
				
			||||||
 | 
											     test->mask,
 | 
				
			||||||
 | 
											     test->write);
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if (!b)
 | 
				
			||||||
 | 
									return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							test++;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						*data = 0;
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool igc_eeprom_test(struct igc_adapter *adapter, u64 *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct igc_hw *hw = &adapter->hw;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*data = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (hw->nvm.ops.validate(hw) != IGC_SUCCESS) {
 | 
				
			||||||
 | 
							*data = 1;
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool igc_link_test(struct igc_adapter *adapter, u64 *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						bool link_up;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*data = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* add delay to give enough time for autonegotioation to finish */
 | 
				
			||||||
 | 
						if (adapter->hw.mac.autoneg)
 | 
				
			||||||
 | 
							ssleep(5);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						link_up = igc_has_link(adapter);
 | 
				
			||||||
 | 
						if (!link_up) {
 | 
				
			||||||
 | 
							*data = 1;
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										30
									
								
								drivers/net/ethernet/intel/igc/igc_diag.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								drivers/net/ethernet/intel/igc/igc_diag.h
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,30 @@
 | 
				
			||||||
 | 
					/* SPDX-License-Identifier: GPL-2.0 */
 | 
				
			||||||
 | 
					/* Copyright (c)  2020 Intel Corporation */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool igc_reg_test(struct igc_adapter *adapter, u64 *data);
 | 
				
			||||||
 | 
					bool igc_eeprom_test(struct igc_adapter *adapter, u64 *data);
 | 
				
			||||||
 | 
					bool igc_link_test(struct igc_adapter *adapter, u64 *data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct igc_reg_test {
 | 
				
			||||||
 | 
						u16 reg;
 | 
				
			||||||
 | 
						u8 array_len;
 | 
				
			||||||
 | 
						u8 test_type;
 | 
				
			||||||
 | 
						u32 mask;
 | 
				
			||||||
 | 
						u32 write;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* In the hardware, registers are laid out either singly, in arrays
 | 
				
			||||||
 | 
					 * spaced 0x40 bytes apart, or in contiguous tables.  We assume
 | 
				
			||||||
 | 
					 * most tests take place on arrays or single registers (handled
 | 
				
			||||||
 | 
					 * as a single-element array) and special-case the tables.
 | 
				
			||||||
 | 
					 * Table tests are always pattern tests.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * We also make provision for some required setup steps by specifying
 | 
				
			||||||
 | 
					 * registers to be written without any read-back testing.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define PATTERN_TEST	1
 | 
				
			||||||
 | 
					#define SET_READ_TEST	2
 | 
				
			||||||
 | 
					#define TABLE32_TEST	3
 | 
				
			||||||
 | 
					#define TABLE64_TEST_LO	4
 | 
				
			||||||
 | 
					#define TABLE64_TEST_HI	5
 | 
				
			||||||
| 
						 | 
					@ -6,6 +6,7 @@
 | 
				
			||||||
#include <linux/pm_runtime.h>
 | 
					#include <linux/pm_runtime.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "igc.h"
 | 
					#include "igc.h"
 | 
				
			||||||
 | 
					#include "igc_diag.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* forward declaration */
 | 
					/* forward declaration */
 | 
				
			||||||
struct igc_stats {
 | 
					struct igc_stats {
 | 
				
			||||||
| 
						 | 
					@ -1896,6 +1897,64 @@ static int igc_set_link_ksettings(struct net_device *netdev,
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void igc_diag_test(struct net_device *netdev,
 | 
				
			||||||
 | 
								  struct ethtool_test *eth_test, u64 *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct igc_adapter *adapter = netdev_priv(netdev);
 | 
				
			||||||
 | 
						bool if_running = netif_running(netdev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (eth_test->flags == ETH_TEST_FL_OFFLINE) {
 | 
				
			||||||
 | 
							netdev_info(adapter->netdev, "offline testing starting");
 | 
				
			||||||
 | 
							set_bit(__IGC_TESTING, &adapter->state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* Link test performed before hardware reset so autoneg doesn't
 | 
				
			||||||
 | 
							 * interfere with test result
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							if (!igc_link_test(adapter, &data[TEST_LINK]))
 | 
				
			||||||
 | 
								eth_test->flags |= ETH_TEST_FL_FAILED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (if_running)
 | 
				
			||||||
 | 
								igc_close(netdev);
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								igc_reset(adapter);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							netdev_info(adapter->netdev, "register testing starting");
 | 
				
			||||||
 | 
							if (!igc_reg_test(adapter, &data[TEST_REG]))
 | 
				
			||||||
 | 
								eth_test->flags |= ETH_TEST_FL_FAILED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							igc_reset(adapter);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							netdev_info(adapter->netdev, "eeprom testing starting");
 | 
				
			||||||
 | 
							if (!igc_eeprom_test(adapter, &data[TEST_EEP]))
 | 
				
			||||||
 | 
								eth_test->flags |= ETH_TEST_FL_FAILED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							igc_reset(adapter);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* loopback and interrupt tests
 | 
				
			||||||
 | 
							 * will be implemented in the future
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							data[TEST_LOOP] = 0;
 | 
				
			||||||
 | 
							data[TEST_IRQ] = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							clear_bit(__IGC_TESTING, &adapter->state);
 | 
				
			||||||
 | 
							if (if_running)
 | 
				
			||||||
 | 
								igc_open(netdev);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							netdev_info(adapter->netdev, "online testing starting");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* register, eeprom, intr and loopback tests not run online */
 | 
				
			||||||
 | 
							data[TEST_REG] = 0;
 | 
				
			||||||
 | 
							data[TEST_EEP] = 0;
 | 
				
			||||||
 | 
							data[TEST_IRQ] = 0;
 | 
				
			||||||
 | 
							data[TEST_LOOP] = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!igc_link_test(adapter, &data[TEST_LINK]))
 | 
				
			||||||
 | 
								eth_test->flags |= ETH_TEST_FL_FAILED;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						msleep_interruptible(4 * 1000);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const struct ethtool_ops igc_ethtool_ops = {
 | 
					static const struct ethtool_ops igc_ethtool_ops = {
 | 
				
			||||||
	.supported_coalesce_params = ETHTOOL_COALESCE_USECS,
 | 
						.supported_coalesce_params = ETHTOOL_COALESCE_USECS,
 | 
				
			||||||
	.get_drvinfo		= igc_get_drvinfo,
 | 
						.get_drvinfo		= igc_get_drvinfo,
 | 
				
			||||||
| 
						 | 
					@ -1933,6 +1992,7 @@ static const struct ethtool_ops igc_ethtool_ops = {
 | 
				
			||||||
	.complete		= igc_ethtool_complete,
 | 
						.complete		= igc_ethtool_complete,
 | 
				
			||||||
	.get_link_ksettings	= igc_get_link_ksettings,
 | 
						.get_link_ksettings	= igc_get_link_ksettings,
 | 
				
			||||||
	.set_link_ksettings	= igc_set_link_ksettings,
 | 
						.set_link_ksettings	= igc_set_link_ksettings,
 | 
				
			||||||
 | 
						.self_test		= igc_diag_test,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void igc_set_ethtool_ops(struct net_device *netdev)
 | 
					void igc_set_ethtool_ops(struct net_device *netdev)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4380,7 +4380,7 @@ static int __igc_open(struct net_device *netdev, bool resuming)
 | 
				
			||||||
	return err;
 | 
						return err;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int igc_open(struct net_device *netdev)
 | 
					int igc_open(struct net_device *netdev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return __igc_open(netdev, false);
 | 
						return __igc_open(netdev, false);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -4422,7 +4422,7 @@ static int __igc_close(struct net_device *netdev, bool suspending)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int igc_close(struct net_device *netdev)
 | 
					int igc_close(struct net_device *netdev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (netif_device_present(netdev) || netdev->dismantle)
 | 
						if (netif_device_present(netdev) || netdev->dismantle)
 | 
				
			||||||
		return __igc_close(netdev, false);
 | 
							return __igc_close(netdev, false);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -49,6 +49,7 @@
 | 
				
			||||||
#define IGC_FACTPS		0x05B30
 | 
					#define IGC_FACTPS		0x05B30
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Interrupt Register Description */
 | 
					/* Interrupt Register Description */
 | 
				
			||||||
 | 
					#define IGC_EICR		0x01580  /* Ext. Interrupt Cause read - W0 */
 | 
				
			||||||
#define IGC_EICS		0x01520  /* Ext. Interrupt Cause Set - W0 */
 | 
					#define IGC_EICS		0x01520  /* Ext. Interrupt Cause Set - W0 */
 | 
				
			||||||
#define IGC_EIMS		0x01524  /* Ext. Interrupt Mask Set/Read - RW */
 | 
					#define IGC_EIMS		0x01524  /* Ext. Interrupt Mask Set/Read - RW */
 | 
				
			||||||
#define IGC_EIMC		0x01528  /* Ext. Interrupt Mask Clear - WO */
 | 
					#define IGC_EIMC		0x01528  /* Ext. Interrupt Mask Clear - WO */
 | 
				
			||||||
| 
						 | 
					@ -119,6 +120,7 @@
 | 
				
			||||||
#define IGC_RLPML		0x05004  /* Rx Long Packet Max Length */
 | 
					#define IGC_RLPML		0x05004  /* Rx Long Packet Max Length */
 | 
				
			||||||
#define IGC_RFCTL		0x05008  /* Receive Filter Control*/
 | 
					#define IGC_RFCTL		0x05008  /* Receive Filter Control*/
 | 
				
			||||||
#define IGC_MTA			0x05200  /* Multicast Table Array - RW Array */
 | 
					#define IGC_MTA			0x05200  /* Multicast Table Array - RW Array */
 | 
				
			||||||
 | 
					#define IGC_RA			0x05400  /* Receive Address - RW Array */
 | 
				
			||||||
#define IGC_UTA			0x0A000  /* Unicast Table Array - RW */
 | 
					#define IGC_UTA			0x0A000  /* Unicast Table Array - RW */
 | 
				
			||||||
#define IGC_RAL(_n)		(0x05400 + ((_n) * 0x08))
 | 
					#define IGC_RAL(_n)		(0x05400 + ((_n) * 0x08))
 | 
				
			||||||
#define IGC_RAH(_n)		(0x05404 + ((_n) * 0x08))
 | 
					#define IGC_RAH(_n)		(0x05404 + ((_n) * 0x08))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue