// SPDX-License-Identifier: GPL-2.0-only /**************************************************************************** * Driver for Solarflare network controllers and boards * Copyright 2005-2006 Fen Systems Ltd. * Copyright 2006-2012 Solarflare Communications Inc. */ #include <linux/netdevice.h> #include <linux/module.h> #include <linux/delay.h> #include <linux/kernel_stat.h> #include <linux/pci.h> #include <linux/ethtool.h> #include <linux/ip.h> #include <linux/in.h> #include <linux/udp.h> #include <linux/rtnetlink.h> #include <linux/slab.h> #include "net_driver.h" #include "efx.h" #include "nic.h" #include "selftest.h" #include "workarounds.h" /* IRQ latency can be enormous because: * - All IRQs may be disabled on a CPU for a *long* time by e.g. a * slow serial console or an old IDE driver doing error recovery * - The PREEMPT_RT patches mostly deal with this, but also allow a * tasklet or normal task to be given higher priority than our IRQ * threads * Try to avoid blaming the hardware for this. */ #define IRQ_TIMEOUT … /* * Loopback test packet structure * * The self-test should stress every RSS vector, and unfortunately * Falcon only performs RSS on TCP/UDP packets. */ struct ef4_loopback_payload { … } __packed __aligned(…); #define EF4_LOOPBACK_PAYLOAD_LEN … /* Loopback test source MAC address */ static const u8 payload_source[ETH_ALEN] __aligned(2) = …; static const char payload_msg[] = …; /* Interrupt mode names */ static const unsigned int ef4_interrupt_mode_max = …; static const char *const ef4_interrupt_mode_names[] = …; #define INT_MODE(efx) … /** * struct ef4_loopback_state - persistent state during a loopback selftest * @flush: Drop all packets in ef4_loopback_rx_packet * @packet_count: Number of packets being used in this test * @skbs: An array of skbs transmitted * @offload_csum: Checksums are being offloaded * @rx_good: RX good packet count * @rx_bad: RX bad packet count * @payload: Payload used in tests */ struct ef4_loopback_state { … }; /* How long to wait for all the packets to arrive (in ms) */ #define LOOPBACK_TIMEOUT_MS … /************************************************************************** * * MII, NVRAM and register tests * **************************************************************************/ static int ef4_test_phy_alive(struct ef4_nic *efx, struct ef4_self_tests *tests) { … } static int ef4_test_nvram(struct ef4_nic *efx, struct ef4_self_tests *tests) { … } /************************************************************************** * * Interrupt and event queue testing * **************************************************************************/ /* Test generation and receipt of interrupts */ static int ef4_test_interrupts(struct ef4_nic *efx, struct ef4_self_tests *tests) { … } /* Test generation and receipt of interrupting events */ static int ef4_test_eventq_irq(struct ef4_nic *efx, struct ef4_self_tests *tests) { … } static int ef4_test_phy(struct ef4_nic *efx, struct ef4_self_tests *tests, unsigned flags) { … } /************************************************************************** * * Loopback testing * NB Only one loopback test can be executing concurrently. * **************************************************************************/ /* Loopback test RX callback * This is called for each received packet during loopback testing. */ void ef4_loopback_rx_packet(struct ef4_nic *efx, const char *buf_ptr, int pkt_len) { … } /* Initialise an ef4_selftest_state for a new iteration */ static void ef4_iterate_state(struct ef4_nic *efx) { … } static int ef4_begin_loopback(struct ef4_tx_queue *tx_queue) { … } static int ef4_poll_loopback(struct ef4_nic *efx) { … } static int ef4_end_loopback(struct ef4_tx_queue *tx_queue, struct ef4_loopback_self_tests *lb_tests) { … } static int ef4_test_loopback(struct ef4_tx_queue *tx_queue, struct ef4_loopback_self_tests *lb_tests) { … } /* Wait for link up. On Falcon, we would prefer to rely on ef4_monitor, but * any contention on the mac lock (via e.g. ef4_mac_mcast_work) causes it * to delay and retry. Therefore, it's safer to just poll directly. Wait * for link up and any faults to dissipate. */ static int ef4_wait_for_link(struct ef4_nic *efx) { … } static int ef4_test_loopbacks(struct ef4_nic *efx, struct ef4_self_tests *tests, unsigned int loopback_modes) { … } /************************************************************************** * * Entry point * *************************************************************************/ int ef4_selftest(struct ef4_nic *efx, struct ef4_self_tests *tests, unsigned flags) { … } void ef4_selftest_async_start(struct ef4_nic *efx) { … } void ef4_selftest_async_cancel(struct ef4_nic *efx) { … } void ef4_selftest_async_work(struct work_struct *data) { … }