1d48523cbSMartin Habets // SPDX-License-Identifier: GPL-2.0-only 2d48523cbSMartin Habets /**************************************************************************** 3d48523cbSMartin Habets * Driver for Solarflare network controllers and boards 4d48523cbSMartin Habets * Copyright 2005-2006 Fen Systems Ltd. 5d48523cbSMartin Habets * Copyright 2006-2012 Solarflare Communications Inc. 6d48523cbSMartin Habets */ 7d48523cbSMartin Habets 8d48523cbSMartin Habets #include <linux/netdevice.h> 9d48523cbSMartin Habets #include <linux/module.h> 10d48523cbSMartin Habets #include <linux/delay.h> 11d48523cbSMartin Habets #include <linux/kernel_stat.h> 12d48523cbSMartin Habets #include <linux/pci.h> 13d48523cbSMartin Habets #include <linux/ethtool.h> 14d48523cbSMartin Habets #include <linux/ip.h> 15d48523cbSMartin Habets #include <linux/in.h> 16d48523cbSMartin Habets #include <linux/udp.h> 17d48523cbSMartin Habets #include <linux/rtnetlink.h> 18d48523cbSMartin Habets #include <linux/slab.h> 19d48523cbSMartin Habets #include "net_driver.h" 20d48523cbSMartin Habets #include "efx.h" 21d48523cbSMartin Habets #include "efx_common.h" 22d48523cbSMartin Habets #include "efx_channels.h" 23d48523cbSMartin Habets #include "nic.h" 24d48523cbSMartin Habets #include "mcdi_port_common.h" 25d48523cbSMartin Habets #include "selftest.h" 26d48523cbSMartin Habets #include "workarounds.h" 27d48523cbSMartin Habets 28d48523cbSMartin Habets /* IRQ latency can be enormous because: 29d48523cbSMartin Habets * - All IRQs may be disabled on a CPU for a *long* time by e.g. a 30d48523cbSMartin Habets * slow serial console or an old IDE driver doing error recovery 31d48523cbSMartin Habets * - The PREEMPT_RT patches mostly deal with this, but also allow a 32d48523cbSMartin Habets * tasklet or normal task to be given higher priority than our IRQ 33d48523cbSMartin Habets * threads 34d48523cbSMartin Habets * Try to avoid blaming the hardware for this. 35d48523cbSMartin Habets */ 36d48523cbSMartin Habets #define IRQ_TIMEOUT HZ 37d48523cbSMartin Habets 38d48523cbSMartin Habets /* 39d48523cbSMartin Habets * Loopback test packet structure 40d48523cbSMartin Habets * 41d48523cbSMartin Habets * The self-test should stress every RSS vector, and unfortunately 42d48523cbSMartin Habets * Falcon only performs RSS on TCP/UDP packets. 43d48523cbSMartin Habets */ 44d48523cbSMartin Habets struct efx_loopback_payload { 4530c24dd8SEdward Cree char pad[2]; /* Ensures ip is 4-byte aligned */ 46*55c1528fSEdward Cree struct_group_attr(packet, __packed, 47d48523cbSMartin Habets struct ethhdr header; 48d48523cbSMartin Habets struct iphdr ip; 49d48523cbSMartin Habets struct udphdr udp; 50d48523cbSMartin Habets __be16 iteration; 51d48523cbSMartin Habets char msg[64]; 52*55c1528fSEdward Cree ); 5330c24dd8SEdward Cree } __packed __aligned(4); 54*55c1528fSEdward Cree #define EFX_LOOPBACK_PAYLOAD_LEN \ 55*55c1528fSEdward Cree sizeof_field(struct efx_loopback_payload, packet) 56d48523cbSMartin Habets 57d48523cbSMartin Habets /* Loopback test source MAC address */ 58d48523cbSMartin Habets static const u8 payload_source[ETH_ALEN] __aligned(2) = { 59d48523cbSMartin Habets 0x00, 0x0f, 0x53, 0x1b, 0x1b, 0x1b, 60d48523cbSMartin Habets }; 61d48523cbSMartin Habets 62d48523cbSMartin Habets static const char payload_msg[] = 63d48523cbSMartin Habets "Hello world! This is an Efx loopback test in progress!"; 64d48523cbSMartin Habets 65d48523cbSMartin Habets /* Interrupt mode names */ 6671ad88f6SMartin Habets static const unsigned int efx_siena_interrupt_mode_max = EFX_INT_MODE_MAX; 6771ad88f6SMartin Habets static const char *const efx_siena_interrupt_mode_names[] = { 68d48523cbSMartin Habets [EFX_INT_MODE_MSIX] = "MSI-X", 69d48523cbSMartin Habets [EFX_INT_MODE_MSI] = "MSI", 70d48523cbSMartin Habets [EFX_INT_MODE_LEGACY] = "legacy", 71d48523cbSMartin Habets }; 72d48523cbSMartin Habets #define INT_MODE(efx) \ 7371ad88f6SMartin Habets STRING_TABLE_LOOKUP(efx->interrupt_mode, efx_siena_interrupt_mode) 74d48523cbSMartin Habets 75d48523cbSMartin Habets /** 76d48523cbSMartin Habets * struct efx_loopback_state - persistent state during a loopback selftest 7795e96f77SMartin Habets * @flush: Drop all packets in efx_siena_loopback_rx_packet 78d48523cbSMartin Habets * @packet_count: Number of packets being used in this test 79d48523cbSMartin Habets * @skbs: An array of skbs transmitted 80d48523cbSMartin Habets * @offload_csum: Checksums are being offloaded 81d48523cbSMartin Habets * @rx_good: RX good packet count 82d48523cbSMartin Habets * @rx_bad: RX bad packet count 83d48523cbSMartin Habets * @payload: Payload used in tests 84d48523cbSMartin Habets */ 85d48523cbSMartin Habets struct efx_loopback_state { 86d48523cbSMartin Habets bool flush; 87d48523cbSMartin Habets int packet_count; 88d48523cbSMartin Habets struct sk_buff **skbs; 89d48523cbSMartin Habets bool offload_csum; 90d48523cbSMartin Habets atomic_t rx_good; 91d48523cbSMartin Habets atomic_t rx_bad; 92d48523cbSMartin Habets struct efx_loopback_payload payload; 93d48523cbSMartin Habets }; 94d48523cbSMartin Habets 95d48523cbSMartin Habets /* How long to wait for all the packets to arrive (in ms) */ 96d48523cbSMartin Habets #define LOOPBACK_TIMEOUT_MS 1000 97d48523cbSMartin Habets 98d48523cbSMartin Habets /************************************************************************** 99d48523cbSMartin Habets * 100d48523cbSMartin Habets * MII, NVRAM and register tests 101d48523cbSMartin Habets * 102d48523cbSMartin Habets **************************************************************************/ 103d48523cbSMartin Habets 104d48523cbSMartin Habets static int efx_test_phy_alive(struct efx_nic *efx, struct efx_self_tests *tests) 105d48523cbSMartin Habets { 106d48523cbSMartin Habets int rc = 0; 107d48523cbSMartin Habets 1084d49e5cdSMartin Habets rc = efx_siena_mcdi_phy_test_alive(efx); 109d48523cbSMartin Habets tests->phy_alive = rc ? -1 : 1; 110d48523cbSMartin Habets 111d48523cbSMartin Habets return rc; 112d48523cbSMartin Habets } 113d48523cbSMartin Habets 114d48523cbSMartin Habets static int efx_test_nvram(struct efx_nic *efx, struct efx_self_tests *tests) 115d48523cbSMartin Habets { 116d48523cbSMartin Habets int rc = 0; 117d48523cbSMartin Habets 118d48523cbSMartin Habets if (efx->type->test_nvram) { 119d48523cbSMartin Habets rc = efx->type->test_nvram(efx); 120d48523cbSMartin Habets if (rc == -EPERM) 121d48523cbSMartin Habets rc = 0; 122d48523cbSMartin Habets else 123d48523cbSMartin Habets tests->nvram = rc ? -1 : 1; 124d48523cbSMartin Habets } 125d48523cbSMartin Habets 126d48523cbSMartin Habets return rc; 127d48523cbSMartin Habets } 128d48523cbSMartin Habets 129d48523cbSMartin Habets /************************************************************************** 130d48523cbSMartin Habets * 131d48523cbSMartin Habets * Interrupt and event queue testing 132d48523cbSMartin Habets * 133d48523cbSMartin Habets **************************************************************************/ 134d48523cbSMartin Habets 135d48523cbSMartin Habets /* Test generation and receipt of interrupts */ 136d48523cbSMartin Habets static int efx_test_interrupts(struct efx_nic *efx, 137d48523cbSMartin Habets struct efx_self_tests *tests) 138d48523cbSMartin Habets { 139d48523cbSMartin Habets unsigned long timeout, wait; 140d48523cbSMartin Habets int cpu; 141d48523cbSMartin Habets int rc; 142d48523cbSMartin Habets 143d48523cbSMartin Habets netif_dbg(efx, drv, efx->net_dev, "testing interrupts\n"); 144d48523cbSMartin Habets tests->interrupt = -1; 145d48523cbSMartin Habets 146c8443b69SMartin Habets rc = efx_siena_irq_test_start(efx); 147d48523cbSMartin Habets if (rc == -ENOTSUPP) { 148d48523cbSMartin Habets netif_dbg(efx, drv, efx->net_dev, 149d48523cbSMartin Habets "direct interrupt testing not supported\n"); 150d48523cbSMartin Habets tests->interrupt = 0; 151d48523cbSMartin Habets return 0; 152d48523cbSMartin Habets } 153d48523cbSMartin Habets 154d48523cbSMartin Habets timeout = jiffies + IRQ_TIMEOUT; 155d48523cbSMartin Habets wait = 1; 156d48523cbSMartin Habets 157d48523cbSMartin Habets /* Wait for arrival of test interrupt. */ 158d48523cbSMartin Habets netif_dbg(efx, drv, efx->net_dev, "waiting for test interrupt\n"); 159d48523cbSMartin Habets do { 160d48523cbSMartin Habets schedule_timeout_uninterruptible(wait); 161d48523cbSMartin Habets cpu = efx_nic_irq_test_irq_cpu(efx); 162d48523cbSMartin Habets if (cpu >= 0) 163d48523cbSMartin Habets goto success; 164d48523cbSMartin Habets wait *= 2; 165d48523cbSMartin Habets } while (time_before(jiffies, timeout)); 166d48523cbSMartin Habets 167d48523cbSMartin Habets netif_err(efx, drv, efx->net_dev, "timed out waiting for interrupt\n"); 168d48523cbSMartin Habets return -ETIMEDOUT; 169d48523cbSMartin Habets 170d48523cbSMartin Habets success: 171d48523cbSMartin Habets netif_dbg(efx, drv, efx->net_dev, "%s test interrupt seen on CPU%d\n", 172d48523cbSMartin Habets INT_MODE(efx), cpu); 173d48523cbSMartin Habets tests->interrupt = 1; 174d48523cbSMartin Habets return 0; 175d48523cbSMartin Habets } 176d48523cbSMartin Habets 177d48523cbSMartin Habets /* Test generation and receipt of interrupting events */ 178d48523cbSMartin Habets static int efx_test_eventq_irq(struct efx_nic *efx, 179d48523cbSMartin Habets struct efx_self_tests *tests) 180d48523cbSMartin Habets { 181d48523cbSMartin Habets struct efx_channel *channel; 182d48523cbSMartin Habets unsigned int read_ptr[EFX_MAX_CHANNELS]; 183d48523cbSMartin Habets unsigned long napi_ran = 0, dma_pend = 0, int_pend = 0; 184d48523cbSMartin Habets unsigned long timeout, wait; 185d48523cbSMartin Habets 186d48523cbSMartin Habets BUILD_BUG_ON(EFX_MAX_CHANNELS > BITS_PER_LONG); 187d48523cbSMartin Habets 188d48523cbSMartin Habets efx_for_each_channel(channel, efx) { 189d48523cbSMartin Habets read_ptr[channel->channel] = channel->eventq_read_ptr; 190d48523cbSMartin Habets set_bit(channel->channel, &dma_pend); 191d48523cbSMartin Habets set_bit(channel->channel, &int_pend); 192c8443b69SMartin Habets efx_siena_event_test_start(channel); 193d48523cbSMartin Habets } 194d48523cbSMartin Habets 195d48523cbSMartin Habets timeout = jiffies + IRQ_TIMEOUT; 196d48523cbSMartin Habets wait = 1; 197d48523cbSMartin Habets 198d48523cbSMartin Habets /* Wait for arrival of interrupts. NAPI processing may or may 199d48523cbSMartin Habets * not complete in time, but we can cope in any case. 200d48523cbSMartin Habets */ 201d48523cbSMartin Habets do { 202d48523cbSMartin Habets schedule_timeout_uninterruptible(wait); 203d48523cbSMartin Habets 204d48523cbSMartin Habets efx_for_each_channel(channel, efx) { 20571ad88f6SMartin Habets efx_siena_stop_eventq(channel); 206d48523cbSMartin Habets if (channel->eventq_read_ptr != 207d48523cbSMartin Habets read_ptr[channel->channel]) { 208d48523cbSMartin Habets set_bit(channel->channel, &napi_ran); 209d48523cbSMartin Habets clear_bit(channel->channel, &dma_pend); 210d48523cbSMartin Habets clear_bit(channel->channel, &int_pend); 211d48523cbSMartin Habets } else { 212c8443b69SMartin Habets if (efx_siena_event_present(channel)) 213d48523cbSMartin Habets clear_bit(channel->channel, &dma_pend); 214d48523cbSMartin Habets if (efx_nic_event_test_irq_cpu(channel) >= 0) 215d48523cbSMartin Habets clear_bit(channel->channel, &int_pend); 216d48523cbSMartin Habets } 21771ad88f6SMartin Habets efx_siena_start_eventq(channel); 218d48523cbSMartin Habets } 219d48523cbSMartin Habets 220d48523cbSMartin Habets wait *= 2; 221d48523cbSMartin Habets } while ((dma_pend || int_pend) && time_before(jiffies, timeout)); 222d48523cbSMartin Habets 223d48523cbSMartin Habets efx_for_each_channel(channel, efx) { 224d48523cbSMartin Habets bool dma_seen = !test_bit(channel->channel, &dma_pend); 225d48523cbSMartin Habets bool int_seen = !test_bit(channel->channel, &int_pend); 226d48523cbSMartin Habets 227d48523cbSMartin Habets tests->eventq_dma[channel->channel] = dma_seen ? 1 : -1; 228d48523cbSMartin Habets tests->eventq_int[channel->channel] = int_seen ? 1 : -1; 229d48523cbSMartin Habets 230d48523cbSMartin Habets if (dma_seen && int_seen) { 231d48523cbSMartin Habets netif_dbg(efx, drv, efx->net_dev, 232d48523cbSMartin Habets "channel %d event queue passed (with%s NAPI)\n", 233d48523cbSMartin Habets channel->channel, 234d48523cbSMartin Habets test_bit(channel->channel, &napi_ran) ? 235d48523cbSMartin Habets "" : "out"); 236d48523cbSMartin Habets } else { 237d48523cbSMartin Habets /* Report failure and whether either interrupt or DMA 238d48523cbSMartin Habets * worked 239d48523cbSMartin Habets */ 240d48523cbSMartin Habets netif_err(efx, drv, efx->net_dev, 241d48523cbSMartin Habets "channel %d timed out waiting for event queue\n", 242d48523cbSMartin Habets channel->channel); 243d48523cbSMartin Habets if (int_seen) 244d48523cbSMartin Habets netif_err(efx, drv, efx->net_dev, 245d48523cbSMartin Habets "channel %d saw interrupt " 246d48523cbSMartin Habets "during event queue test\n", 247d48523cbSMartin Habets channel->channel); 248d48523cbSMartin Habets if (dma_seen) 249d48523cbSMartin Habets netif_err(efx, drv, efx->net_dev, 250d48523cbSMartin Habets "channel %d event was generated, but " 251d48523cbSMartin Habets "failed to trigger an interrupt\n", 252d48523cbSMartin Habets channel->channel); 253d48523cbSMartin Habets } 254d48523cbSMartin Habets } 255d48523cbSMartin Habets 256d48523cbSMartin Habets return (dma_pend || int_pend) ? -ETIMEDOUT : 0; 257d48523cbSMartin Habets } 258d48523cbSMartin Habets 259d48523cbSMartin Habets static int efx_test_phy(struct efx_nic *efx, struct efx_self_tests *tests, 260d48523cbSMartin Habets unsigned flags) 261d48523cbSMartin Habets { 262d48523cbSMartin Habets int rc; 263d48523cbSMartin Habets 264d48523cbSMartin Habets mutex_lock(&efx->mac_lock); 2654d49e5cdSMartin Habets rc = efx_siena_mcdi_phy_run_tests(efx, tests->phy_ext, flags); 266d48523cbSMartin Habets mutex_unlock(&efx->mac_lock); 267d48523cbSMartin Habets if (rc == -EPERM) 268d48523cbSMartin Habets rc = 0; 269d48523cbSMartin Habets else 270d48523cbSMartin Habets netif_info(efx, drv, efx->net_dev, 271d48523cbSMartin Habets "%s phy selftest\n", rc ? "Failed" : "Passed"); 272d48523cbSMartin Habets 273d48523cbSMartin Habets return rc; 274d48523cbSMartin Habets } 275d48523cbSMartin Habets 276d48523cbSMartin Habets /************************************************************************** 277d48523cbSMartin Habets * 278d48523cbSMartin Habets * Loopback testing 279d48523cbSMartin Habets * NB Only one loopback test can be executing concurrently. 280d48523cbSMartin Habets * 281d48523cbSMartin Habets **************************************************************************/ 282d48523cbSMartin Habets 283d48523cbSMartin Habets /* Loopback test RX callback 284d48523cbSMartin Habets * This is called for each received packet during loopback testing. 285d48523cbSMartin Habets */ 28695e96f77SMartin Habets void efx_siena_loopback_rx_packet(struct efx_nic *efx, 287d48523cbSMartin Habets const char *buf_ptr, int pkt_len) 288d48523cbSMartin Habets { 289d48523cbSMartin Habets struct efx_loopback_state *state = efx->loopback_selftest; 29030c24dd8SEdward Cree struct efx_loopback_payload received; 291d48523cbSMartin Habets struct efx_loopback_payload *payload; 292d48523cbSMartin Habets 293d48523cbSMartin Habets BUG_ON(!buf_ptr); 294d48523cbSMartin Habets 295d48523cbSMartin Habets /* If we are just flushing, then drop the packet */ 296d48523cbSMartin Habets if ((state == NULL) || state->flush) 297d48523cbSMartin Habets return; 298d48523cbSMartin Habets 299d48523cbSMartin Habets payload = &state->payload; 300d48523cbSMartin Habets 301*55c1528fSEdward Cree memcpy(&received.packet, buf_ptr, 30230c24dd8SEdward Cree min_t(int, pkt_len, EFX_LOOPBACK_PAYLOAD_LEN)); 30330c24dd8SEdward Cree received.ip.saddr = payload->ip.saddr; 304d48523cbSMartin Habets if (state->offload_csum) 30530c24dd8SEdward Cree received.ip.check = payload->ip.check; 306d48523cbSMartin Habets 307d48523cbSMartin Habets /* Check that header exists */ 30830c24dd8SEdward Cree if (pkt_len < sizeof(received.header)) { 309d48523cbSMartin Habets netif_err(efx, drv, efx->net_dev, 310d48523cbSMartin Habets "saw runt RX packet (length %d) in %s loopback " 311d48523cbSMartin Habets "test\n", pkt_len, LOOPBACK_MODE(efx)); 312d48523cbSMartin Habets goto err; 313d48523cbSMartin Habets } 314d48523cbSMartin Habets 315d48523cbSMartin Habets /* Check that the ethernet header exists */ 31630c24dd8SEdward Cree if (memcmp(&received.header, &payload->header, ETH_HLEN) != 0) { 317d48523cbSMartin Habets netif_err(efx, drv, efx->net_dev, 318d48523cbSMartin Habets "saw non-loopback RX packet in %s loopback test\n", 319d48523cbSMartin Habets LOOPBACK_MODE(efx)); 320d48523cbSMartin Habets goto err; 321d48523cbSMartin Habets } 322d48523cbSMartin Habets 323d48523cbSMartin Habets /* Check packet length */ 32430c24dd8SEdward Cree if (pkt_len != EFX_LOOPBACK_PAYLOAD_LEN) { 325d48523cbSMartin Habets netif_err(efx, drv, efx->net_dev, 326d48523cbSMartin Habets "saw incorrect RX packet length %d (wanted %d) in " 32730c24dd8SEdward Cree "%s loopback test\n", pkt_len, 32830c24dd8SEdward Cree (int)EFX_LOOPBACK_PAYLOAD_LEN, LOOPBACK_MODE(efx)); 329d48523cbSMartin Habets goto err; 330d48523cbSMartin Habets } 331d48523cbSMartin Habets 332d48523cbSMartin Habets /* Check that IP header matches */ 33330c24dd8SEdward Cree if (memcmp(&received.ip, &payload->ip, sizeof(payload->ip)) != 0) { 334d48523cbSMartin Habets netif_err(efx, drv, efx->net_dev, 335d48523cbSMartin Habets "saw corrupted IP header in %s loopback test\n", 336d48523cbSMartin Habets LOOPBACK_MODE(efx)); 337d48523cbSMartin Habets goto err; 338d48523cbSMartin Habets } 339d48523cbSMartin Habets 340d48523cbSMartin Habets /* Check that msg and padding matches */ 34130c24dd8SEdward Cree if (memcmp(&received.msg, &payload->msg, sizeof(received.msg)) != 0) { 342d48523cbSMartin Habets netif_err(efx, drv, efx->net_dev, 343d48523cbSMartin Habets "saw corrupted RX packet in %s loopback test\n", 344d48523cbSMartin Habets LOOPBACK_MODE(efx)); 345d48523cbSMartin Habets goto err; 346d48523cbSMartin Habets } 347d48523cbSMartin Habets 348d48523cbSMartin Habets /* Check that iteration matches */ 34930c24dd8SEdward Cree if (received.iteration != payload->iteration) { 350d48523cbSMartin Habets netif_err(efx, drv, efx->net_dev, 351d48523cbSMartin Habets "saw RX packet from iteration %d (wanted %d) in " 35230c24dd8SEdward Cree "%s loopback test\n", ntohs(received.iteration), 353d48523cbSMartin Habets ntohs(payload->iteration), LOOPBACK_MODE(efx)); 354d48523cbSMartin Habets goto err; 355d48523cbSMartin Habets } 356d48523cbSMartin Habets 357d48523cbSMartin Habets /* Increase correct RX count */ 358d48523cbSMartin Habets netif_vdbg(efx, drv, efx->net_dev, 359d48523cbSMartin Habets "got loopback RX in %s loopback test\n", LOOPBACK_MODE(efx)); 360d48523cbSMartin Habets 361d48523cbSMartin Habets atomic_inc(&state->rx_good); 362d48523cbSMartin Habets return; 363d48523cbSMartin Habets 364d48523cbSMartin Habets err: 365d48523cbSMartin Habets #ifdef DEBUG 366d48523cbSMartin Habets if (atomic_read(&state->rx_bad) == 0) { 367d48523cbSMartin Habets netif_err(efx, drv, efx->net_dev, "received packet:\n"); 368d48523cbSMartin Habets print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 0x10, 1, 369d48523cbSMartin Habets buf_ptr, pkt_len, 0); 370d48523cbSMartin Habets netif_err(efx, drv, efx->net_dev, "expected packet:\n"); 371d48523cbSMartin Habets print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 0x10, 1, 372*55c1528fSEdward Cree &state->payload.packet, EFX_LOOPBACK_PAYLOAD_LEN, 37330c24dd8SEdward Cree 0); 374d48523cbSMartin Habets } 375d48523cbSMartin Habets #endif 376d48523cbSMartin Habets atomic_inc(&state->rx_bad); 377d48523cbSMartin Habets } 378d48523cbSMartin Habets 37995e96f77SMartin Habets /* Initialise an efx_siena_selftest_state for a new iteration */ 380d48523cbSMartin Habets static void efx_iterate_state(struct efx_nic *efx) 381d48523cbSMartin Habets { 382d48523cbSMartin Habets struct efx_loopback_state *state = efx->loopback_selftest; 383d48523cbSMartin Habets struct net_device *net_dev = efx->net_dev; 384d48523cbSMartin Habets struct efx_loopback_payload *payload = &state->payload; 385d48523cbSMartin Habets 386d48523cbSMartin Habets /* Initialise the layerII header */ 387d48523cbSMartin Habets ether_addr_copy((u8 *)&payload->header.h_dest, net_dev->dev_addr); 388d48523cbSMartin Habets ether_addr_copy((u8 *)&payload->header.h_source, payload_source); 389d48523cbSMartin Habets payload->header.h_proto = htons(ETH_P_IP); 390d48523cbSMartin Habets 391d48523cbSMartin Habets /* saddr set later and used as incrementing count */ 392d48523cbSMartin Habets payload->ip.daddr = htonl(INADDR_LOOPBACK); 393d48523cbSMartin Habets payload->ip.ihl = 5; 394d48523cbSMartin Habets payload->ip.check = (__force __sum16) htons(0xdead); 39530c24dd8SEdward Cree payload->ip.tot_len = htons(sizeof(*payload) - 39630c24dd8SEdward Cree offsetof(struct efx_loopback_payload, ip)); 397d48523cbSMartin Habets payload->ip.version = IPVERSION; 398d48523cbSMartin Habets payload->ip.protocol = IPPROTO_UDP; 399d48523cbSMartin Habets 400d48523cbSMartin Habets /* Initialise udp header */ 401d48523cbSMartin Habets payload->udp.source = 0; 40230c24dd8SEdward Cree payload->udp.len = htons(sizeof(*payload) - 40330c24dd8SEdward Cree offsetof(struct efx_loopback_payload, udp)); 404d48523cbSMartin Habets payload->udp.check = 0; /* checksum ignored */ 405d48523cbSMartin Habets 406d48523cbSMartin Habets /* Fill out payload */ 407d48523cbSMartin Habets payload->iteration = htons(ntohs(payload->iteration) + 1); 408d48523cbSMartin Habets memcpy(&payload->msg, payload_msg, sizeof(payload_msg)); 409d48523cbSMartin Habets 410d48523cbSMartin Habets /* Fill out remaining state members */ 411d48523cbSMartin Habets atomic_set(&state->rx_good, 0); 412d48523cbSMartin Habets atomic_set(&state->rx_bad, 0); 413d48523cbSMartin Habets smp_wmb(); 414d48523cbSMartin Habets } 415d48523cbSMartin Habets 416d48523cbSMartin Habets static int efx_begin_loopback(struct efx_tx_queue *tx_queue) 417d48523cbSMartin Habets { 418d48523cbSMartin Habets struct efx_nic *efx = tx_queue->efx; 419d48523cbSMartin Habets struct efx_loopback_state *state = efx->loopback_selftest; 420d48523cbSMartin Habets struct efx_loopback_payload *payload; 421d48523cbSMartin Habets struct sk_buff *skb; 422d48523cbSMartin Habets int i; 423d48523cbSMartin Habets netdev_tx_t rc; 424d48523cbSMartin Habets 425d48523cbSMartin Habets /* Transmit N copies of buffer */ 426d48523cbSMartin Habets for (i = 0; i < state->packet_count; i++) { 427d48523cbSMartin Habets /* Allocate an skb, holding an extra reference for 428d48523cbSMartin Habets * transmit completion counting */ 42930c24dd8SEdward Cree skb = alloc_skb(EFX_LOOPBACK_PAYLOAD_LEN, GFP_KERNEL); 430d48523cbSMartin Habets if (!skb) 431d48523cbSMartin Habets return -ENOMEM; 432d48523cbSMartin Habets state->skbs[i] = skb; 433d48523cbSMartin Habets skb_get(skb); 434d48523cbSMartin Habets 435d48523cbSMartin Habets /* Copy the payload in, incrementing the source address to 436d48523cbSMartin Habets * exercise the rss vectors */ 437d48523cbSMartin Habets payload = skb_put(skb, sizeof(state->payload)); 438d48523cbSMartin Habets memcpy(payload, &state->payload, sizeof(state->payload)); 439d48523cbSMartin Habets payload->ip.saddr = htonl(INADDR_LOOPBACK | (i << 2)); 44030c24dd8SEdward Cree /* Strip off the leading padding */ 44130c24dd8SEdward Cree skb_pull(skb, offsetof(struct efx_loopback_payload, header)); 442*55c1528fSEdward Cree /* Strip off the trailing padding */ 443*55c1528fSEdward Cree skb_trim(skb, EFX_LOOPBACK_PAYLOAD_LEN); 444d48523cbSMartin Habets 445d48523cbSMartin Habets /* Ensure everything we've written is visible to the 446d48523cbSMartin Habets * interrupt handler. */ 447d48523cbSMartin Habets smp_wmb(); 448d48523cbSMartin Habets 449d48523cbSMartin Habets netif_tx_lock_bh(efx->net_dev); 450d48523cbSMartin Habets rc = efx_enqueue_skb(tx_queue, skb); 451d48523cbSMartin Habets netif_tx_unlock_bh(efx->net_dev); 452d48523cbSMartin Habets 453d48523cbSMartin Habets if (rc != NETDEV_TX_OK) { 454d48523cbSMartin Habets netif_err(efx, drv, efx->net_dev, 455d48523cbSMartin Habets "TX queue %d could not transmit packet %d of " 456d48523cbSMartin Habets "%d in %s loopback test\n", tx_queue->label, 457d48523cbSMartin Habets i + 1, state->packet_count, 458d48523cbSMartin Habets LOOPBACK_MODE(efx)); 459d48523cbSMartin Habets 460d48523cbSMartin Habets /* Defer cleaning up the other skbs for the caller */ 461d48523cbSMartin Habets kfree_skb(skb); 462d48523cbSMartin Habets return -EPIPE; 463d48523cbSMartin Habets } 464d48523cbSMartin Habets } 465d48523cbSMartin Habets 466d48523cbSMartin Habets return 0; 467d48523cbSMartin Habets } 468d48523cbSMartin Habets 469d48523cbSMartin Habets static int efx_poll_loopback(struct efx_nic *efx) 470d48523cbSMartin Habets { 471d48523cbSMartin Habets struct efx_loopback_state *state = efx->loopback_selftest; 472d48523cbSMartin Habets 473d48523cbSMartin Habets return atomic_read(&state->rx_good) == state->packet_count; 474d48523cbSMartin Habets } 475d48523cbSMartin Habets 476d48523cbSMartin Habets static int efx_end_loopback(struct efx_tx_queue *tx_queue, 477d48523cbSMartin Habets struct efx_loopback_self_tests *lb_tests) 478d48523cbSMartin Habets { 479d48523cbSMartin Habets struct efx_nic *efx = tx_queue->efx; 480d48523cbSMartin Habets struct efx_loopback_state *state = efx->loopback_selftest; 481d48523cbSMartin Habets struct sk_buff *skb; 482d48523cbSMartin Habets int tx_done = 0, rx_good, rx_bad; 483d48523cbSMartin Habets int i, rc = 0; 484d48523cbSMartin Habets 485d48523cbSMartin Habets netif_tx_lock_bh(efx->net_dev); 486d48523cbSMartin Habets 487d48523cbSMartin Habets /* Count the number of tx completions, and decrement the refcnt. Any 488d48523cbSMartin Habets * skbs not already completed will be free'd when the queue is flushed */ 489d48523cbSMartin Habets for (i = 0; i < state->packet_count; i++) { 490d48523cbSMartin Habets skb = state->skbs[i]; 491d48523cbSMartin Habets if (skb && !skb_shared(skb)) 492d48523cbSMartin Habets ++tx_done; 493d48523cbSMartin Habets dev_kfree_skb(skb); 494d48523cbSMartin Habets } 495d48523cbSMartin Habets 496d48523cbSMartin Habets netif_tx_unlock_bh(efx->net_dev); 497d48523cbSMartin Habets 498d48523cbSMartin Habets /* Check TX completion and received packet counts */ 499d48523cbSMartin Habets rx_good = atomic_read(&state->rx_good); 500d48523cbSMartin Habets rx_bad = atomic_read(&state->rx_bad); 501d48523cbSMartin Habets if (tx_done != state->packet_count) { 502d48523cbSMartin Habets /* Don't free the skbs; they will be picked up on TX 503d48523cbSMartin Habets * overflow or channel teardown. 504d48523cbSMartin Habets */ 505d48523cbSMartin Habets netif_err(efx, drv, efx->net_dev, 506d48523cbSMartin Habets "TX queue %d saw only %d out of an expected %d " 507d48523cbSMartin Habets "TX completion events in %s loopback test\n", 508d48523cbSMartin Habets tx_queue->label, tx_done, state->packet_count, 509d48523cbSMartin Habets LOOPBACK_MODE(efx)); 510d48523cbSMartin Habets rc = -ETIMEDOUT; 511d48523cbSMartin Habets /* Allow to fall through so we see the RX errors as well */ 512d48523cbSMartin Habets } 513d48523cbSMartin Habets 514d48523cbSMartin Habets /* We may always be up to a flush away from our desired packet total */ 515d48523cbSMartin Habets if (rx_good != state->packet_count) { 516d48523cbSMartin Habets netif_dbg(efx, drv, efx->net_dev, 517d48523cbSMartin Habets "TX queue %d saw only %d out of an expected %d " 518d48523cbSMartin Habets "received packets in %s loopback test\n", 519d48523cbSMartin Habets tx_queue->label, rx_good, state->packet_count, 520d48523cbSMartin Habets LOOPBACK_MODE(efx)); 521d48523cbSMartin Habets rc = -ETIMEDOUT; 522d48523cbSMartin Habets /* Fall through */ 523d48523cbSMartin Habets } 524d48523cbSMartin Habets 525d48523cbSMartin Habets /* Update loopback test structure */ 526d48523cbSMartin Habets lb_tests->tx_sent[tx_queue->label] += state->packet_count; 527d48523cbSMartin Habets lb_tests->tx_done[tx_queue->label] += tx_done; 528d48523cbSMartin Habets lb_tests->rx_good += rx_good; 529d48523cbSMartin Habets lb_tests->rx_bad += rx_bad; 530d48523cbSMartin Habets 531d48523cbSMartin Habets return rc; 532d48523cbSMartin Habets } 533d48523cbSMartin Habets 534d48523cbSMartin Habets static int 535d48523cbSMartin Habets efx_test_loopback(struct efx_tx_queue *tx_queue, 536d48523cbSMartin Habets struct efx_loopback_self_tests *lb_tests) 537d48523cbSMartin Habets { 538d48523cbSMartin Habets struct efx_nic *efx = tx_queue->efx; 539d48523cbSMartin Habets struct efx_loopback_state *state = efx->loopback_selftest; 540d48523cbSMartin Habets int i, begin_rc, end_rc; 541d48523cbSMartin Habets 542d48523cbSMartin Habets for (i = 0; i < 3; i++) { 543d48523cbSMartin Habets /* Determine how many packets to send */ 544d48523cbSMartin Habets state->packet_count = efx->txq_entries / 3; 545d48523cbSMartin Habets state->packet_count = min(1 << (i << 2), state->packet_count); 546d48523cbSMartin Habets state->skbs = kcalloc(state->packet_count, 547d48523cbSMartin Habets sizeof(state->skbs[0]), GFP_KERNEL); 548d48523cbSMartin Habets if (!state->skbs) 549d48523cbSMartin Habets return -ENOMEM; 550d48523cbSMartin Habets state->flush = false; 551d48523cbSMartin Habets 552d48523cbSMartin Habets netif_dbg(efx, drv, efx->net_dev, 553d48523cbSMartin Habets "TX queue %d (hw %d) testing %s loopback with %d packets\n", 554d48523cbSMartin Habets tx_queue->label, tx_queue->queue, LOOPBACK_MODE(efx), 555d48523cbSMartin Habets state->packet_count); 556d48523cbSMartin Habets 557d48523cbSMartin Habets efx_iterate_state(efx); 558d48523cbSMartin Habets begin_rc = efx_begin_loopback(tx_queue); 559d48523cbSMartin Habets 560d48523cbSMartin Habets /* This will normally complete very quickly, but be 561d48523cbSMartin Habets * prepared to wait much longer. */ 562d48523cbSMartin Habets msleep(1); 563d48523cbSMartin Habets if (!efx_poll_loopback(efx)) { 564d48523cbSMartin Habets msleep(LOOPBACK_TIMEOUT_MS); 565d48523cbSMartin Habets efx_poll_loopback(efx); 566d48523cbSMartin Habets } 567d48523cbSMartin Habets 568d48523cbSMartin Habets end_rc = efx_end_loopback(tx_queue, lb_tests); 569d48523cbSMartin Habets kfree(state->skbs); 570d48523cbSMartin Habets 571d48523cbSMartin Habets if (begin_rc || end_rc) { 572d48523cbSMartin Habets /* Wait a while to ensure there are no packets 573d48523cbSMartin Habets * floating around after a failure. */ 574d48523cbSMartin Habets schedule_timeout_uninterruptible(HZ / 10); 575d48523cbSMartin Habets return begin_rc ? begin_rc : end_rc; 576d48523cbSMartin Habets } 577d48523cbSMartin Habets } 578d48523cbSMartin Habets 579d48523cbSMartin Habets netif_dbg(efx, drv, efx->net_dev, 580d48523cbSMartin Habets "TX queue %d passed %s loopback test with a burst length " 581d48523cbSMartin Habets "of %d packets\n", tx_queue->label, LOOPBACK_MODE(efx), 582d48523cbSMartin Habets state->packet_count); 583d48523cbSMartin Habets 584d48523cbSMartin Habets return 0; 585d48523cbSMartin Habets } 586d48523cbSMartin Habets 587d48523cbSMartin Habets /* Wait for link up. On Falcon, we would prefer to rely on efx_monitor, but 588d48523cbSMartin Habets * any contention on the mac lock (via e.g. efx_mac_mcast_work) causes it 589d48523cbSMartin Habets * to delay and retry. Therefore, it's safer to just poll directly. Wait 590d48523cbSMartin Habets * for link up and any faults to dissipate. */ 591d48523cbSMartin Habets static int efx_wait_for_link(struct efx_nic *efx) 592d48523cbSMartin Habets { 593d48523cbSMartin Habets struct efx_link_state *link_state = &efx->link_state; 594d48523cbSMartin Habets int count, link_up_count = 0; 595d48523cbSMartin Habets bool link_up; 596d48523cbSMartin Habets 597d48523cbSMartin Habets for (count = 0; count < 40; count++) { 598d48523cbSMartin Habets schedule_timeout_uninterruptible(HZ / 10); 599d48523cbSMartin Habets 600d48523cbSMartin Habets if (efx->type->monitor != NULL) { 601d48523cbSMartin Habets mutex_lock(&efx->mac_lock); 602d48523cbSMartin Habets efx->type->monitor(efx); 603d48523cbSMartin Habets mutex_unlock(&efx->mac_lock); 604d48523cbSMartin Habets } 605d48523cbSMartin Habets 606d48523cbSMartin Habets mutex_lock(&efx->mac_lock); 607d48523cbSMartin Habets link_up = link_state->up; 608d48523cbSMartin Habets if (link_up) 609d48523cbSMartin Habets link_up = !efx->type->check_mac_fault(efx); 610d48523cbSMartin Habets mutex_unlock(&efx->mac_lock); 611d48523cbSMartin Habets 612d48523cbSMartin Habets if (link_up) { 613d48523cbSMartin Habets if (++link_up_count == 2) 614d48523cbSMartin Habets return 0; 615d48523cbSMartin Habets } else { 616d48523cbSMartin Habets link_up_count = 0; 617d48523cbSMartin Habets } 618d48523cbSMartin Habets } 619d48523cbSMartin Habets 620d48523cbSMartin Habets return -ETIMEDOUT; 621d48523cbSMartin Habets } 622d48523cbSMartin Habets 623d48523cbSMartin Habets static int efx_test_loopbacks(struct efx_nic *efx, struct efx_self_tests *tests, 624d48523cbSMartin Habets unsigned int loopback_modes) 625d48523cbSMartin Habets { 626d48523cbSMartin Habets enum efx_loopback_mode mode; 627d48523cbSMartin Habets struct efx_loopback_state *state; 628d48523cbSMartin Habets struct efx_channel *channel = 629d48523cbSMartin Habets efx_get_channel(efx, efx->tx_channel_offset); 630d48523cbSMartin Habets struct efx_tx_queue *tx_queue; 631d48523cbSMartin Habets int rc = 0; 632d48523cbSMartin Habets 633d48523cbSMartin Habets /* Set the port loopback_selftest member. From this point on 634d48523cbSMartin Habets * all received packets will be dropped. Mark the state as 635d48523cbSMartin Habets * "flushing" so all inflight packets are dropped */ 636d48523cbSMartin Habets state = kzalloc(sizeof(*state), GFP_KERNEL); 637d48523cbSMartin Habets if (state == NULL) 638d48523cbSMartin Habets return -ENOMEM; 639d48523cbSMartin Habets BUG_ON(efx->loopback_selftest); 640d48523cbSMartin Habets state->flush = true; 641d48523cbSMartin Habets efx->loopback_selftest = state; 642d48523cbSMartin Habets 643d48523cbSMartin Habets /* Test all supported loopback modes */ 644d48523cbSMartin Habets for (mode = LOOPBACK_NONE; mode <= LOOPBACK_TEST_MAX; mode++) { 645d48523cbSMartin Habets if (!(loopback_modes & (1 << mode))) 646d48523cbSMartin Habets continue; 647d48523cbSMartin Habets 648d48523cbSMartin Habets /* Move the port into the specified loopback mode. */ 649d48523cbSMartin Habets state->flush = true; 650d48523cbSMartin Habets mutex_lock(&efx->mac_lock); 651d48523cbSMartin Habets efx->loopback_mode = mode; 65271ad88f6SMartin Habets rc = __efx_siena_reconfigure_port(efx); 653d48523cbSMartin Habets mutex_unlock(&efx->mac_lock); 654d48523cbSMartin Habets if (rc) { 655d48523cbSMartin Habets netif_err(efx, drv, efx->net_dev, 656d48523cbSMartin Habets "unable to move into %s loopback\n", 657d48523cbSMartin Habets LOOPBACK_MODE(efx)); 658d48523cbSMartin Habets goto out; 659d48523cbSMartin Habets } 660d48523cbSMartin Habets 661d48523cbSMartin Habets rc = efx_wait_for_link(efx); 662d48523cbSMartin Habets if (rc) { 663d48523cbSMartin Habets netif_err(efx, drv, efx->net_dev, 664d48523cbSMartin Habets "loopback %s never came up\n", 665d48523cbSMartin Habets LOOPBACK_MODE(efx)); 666d48523cbSMartin Habets goto out; 667d48523cbSMartin Habets } 668d48523cbSMartin Habets 669d48523cbSMartin Habets /* Test all enabled types of TX queue */ 670d48523cbSMartin Habets efx_for_each_channel_tx_queue(tx_queue, channel) { 671d48523cbSMartin Habets state->offload_csum = (tx_queue->type & 672d48523cbSMartin Habets EFX_TXQ_TYPE_OUTER_CSUM); 673d48523cbSMartin Habets rc = efx_test_loopback(tx_queue, 674d48523cbSMartin Habets &tests->loopback[mode]); 675d48523cbSMartin Habets if (rc) 676d48523cbSMartin Habets goto out; 677d48523cbSMartin Habets } 678d48523cbSMartin Habets } 679d48523cbSMartin Habets 680d48523cbSMartin Habets out: 681d48523cbSMartin Habets /* Remove the flush. The caller will remove the loopback setting */ 682d48523cbSMartin Habets state->flush = true; 683d48523cbSMartin Habets efx->loopback_selftest = NULL; 684d48523cbSMartin Habets wmb(); 685d48523cbSMartin Habets kfree(state); 686d48523cbSMartin Habets 687d48523cbSMartin Habets if (rc == -EPERM) 688d48523cbSMartin Habets rc = 0; 689d48523cbSMartin Habets 690d48523cbSMartin Habets return rc; 691d48523cbSMartin Habets } 692d48523cbSMartin Habets 693d48523cbSMartin Habets /************************************************************************** 694d48523cbSMartin Habets * 695d48523cbSMartin Habets * Entry point 696d48523cbSMartin Habets * 697d48523cbSMartin Habets *************************************************************************/ 698d48523cbSMartin Habets 69995e96f77SMartin Habets int efx_siena_selftest(struct efx_nic *efx, struct efx_self_tests *tests, 70095e96f77SMartin Habets unsigned int flags) 701d48523cbSMartin Habets { 702d48523cbSMartin Habets enum efx_loopback_mode loopback_mode = efx->loopback_mode; 703d48523cbSMartin Habets int phy_mode = efx->phy_mode; 704d48523cbSMartin Habets int rc_test = 0, rc_reset, rc; 705d48523cbSMartin Habets 70695e96f77SMartin Habets efx_siena_selftest_async_cancel(efx); 707d48523cbSMartin Habets 708d48523cbSMartin Habets /* Online (i.e. non-disruptive) testing 709d48523cbSMartin Habets * This checks interrupt generation, event delivery and PHY presence. */ 710d48523cbSMartin Habets 711d48523cbSMartin Habets rc = efx_test_phy_alive(efx, tests); 712d48523cbSMartin Habets if (rc && !rc_test) 713d48523cbSMartin Habets rc_test = rc; 714d48523cbSMartin Habets 715d48523cbSMartin Habets rc = efx_test_nvram(efx, tests); 716d48523cbSMartin Habets if (rc && !rc_test) 717d48523cbSMartin Habets rc_test = rc; 718d48523cbSMartin Habets 719d48523cbSMartin Habets rc = efx_test_interrupts(efx, tests); 720d48523cbSMartin Habets if (rc && !rc_test) 721d48523cbSMartin Habets rc_test = rc; 722d48523cbSMartin Habets 723d48523cbSMartin Habets rc = efx_test_eventq_irq(efx, tests); 724d48523cbSMartin Habets if (rc && !rc_test) 725d48523cbSMartin Habets rc_test = rc; 726d48523cbSMartin Habets 727d48523cbSMartin Habets if (rc_test) 728d48523cbSMartin Habets return rc_test; 729d48523cbSMartin Habets 730d48523cbSMartin Habets if (!(flags & ETH_TEST_FL_OFFLINE)) 731d48523cbSMartin Habets return efx_test_phy(efx, tests, flags); 732d48523cbSMartin Habets 733d48523cbSMartin Habets /* Offline (i.e. disruptive) testing 734d48523cbSMartin Habets * This checks MAC and PHY loopback on the specified port. */ 735d48523cbSMartin Habets 736d48523cbSMartin Habets /* Detach the device so the kernel doesn't transmit during the 737d48523cbSMartin Habets * loopback test and the watchdog timeout doesn't fire. 738d48523cbSMartin Habets */ 739d48523cbSMartin Habets efx_device_detach_sync(efx); 740d48523cbSMartin Habets 741d48523cbSMartin Habets if (efx->type->test_chip) { 742d48523cbSMartin Habets rc_reset = efx->type->test_chip(efx, tests); 743d48523cbSMartin Habets if (rc_reset) { 744d48523cbSMartin Habets netif_err(efx, hw, efx->net_dev, 745d48523cbSMartin Habets "Unable to recover from chip test\n"); 74671ad88f6SMartin Habets efx_siena_schedule_reset(efx, RESET_TYPE_DISABLE); 747d48523cbSMartin Habets return rc_reset; 748d48523cbSMartin Habets } 749d48523cbSMartin Habets 750d48523cbSMartin Habets if ((tests->memory < 0 || tests->registers < 0) && !rc_test) 751d48523cbSMartin Habets rc_test = -EIO; 752d48523cbSMartin Habets } 753d48523cbSMartin Habets 754d48523cbSMartin Habets /* Ensure that the phy is powered and out of loopback 755d48523cbSMartin Habets * for the bist and loopback tests */ 756d48523cbSMartin Habets mutex_lock(&efx->mac_lock); 757d48523cbSMartin Habets efx->phy_mode &= ~PHY_MODE_LOW_POWER; 758d48523cbSMartin Habets efx->loopback_mode = LOOPBACK_NONE; 75971ad88f6SMartin Habets __efx_siena_reconfigure_port(efx); 760d48523cbSMartin Habets mutex_unlock(&efx->mac_lock); 761d48523cbSMartin Habets 762d48523cbSMartin Habets rc = efx_test_phy(efx, tests, flags); 763d48523cbSMartin Habets if (rc && !rc_test) 764d48523cbSMartin Habets rc_test = rc; 765d48523cbSMartin Habets 766d48523cbSMartin Habets rc = efx_test_loopbacks(efx, tests, efx->loopback_modes); 767d48523cbSMartin Habets if (rc && !rc_test) 768d48523cbSMartin Habets rc_test = rc; 769d48523cbSMartin Habets 770d48523cbSMartin Habets /* restore the PHY to the previous state */ 771d48523cbSMartin Habets mutex_lock(&efx->mac_lock); 772d48523cbSMartin Habets efx->phy_mode = phy_mode; 773d48523cbSMartin Habets efx->loopback_mode = loopback_mode; 77471ad88f6SMartin Habets __efx_siena_reconfigure_port(efx); 775d48523cbSMartin Habets mutex_unlock(&efx->mac_lock); 776d48523cbSMartin Habets 777d48523cbSMartin Habets efx_device_attach_if_not_resetting(efx); 778d48523cbSMartin Habets 779d48523cbSMartin Habets return rc_test; 780d48523cbSMartin Habets } 781d48523cbSMartin Habets 78295e96f77SMartin Habets void efx_siena_selftest_async_start(struct efx_nic *efx) 783d48523cbSMartin Habets { 784d48523cbSMartin Habets struct efx_channel *channel; 785d48523cbSMartin Habets 786d48523cbSMartin Habets efx_for_each_channel(channel, efx) 787c8443b69SMartin Habets efx_siena_event_test_start(channel); 788d48523cbSMartin Habets schedule_delayed_work(&efx->selftest_work, IRQ_TIMEOUT); 789d48523cbSMartin Habets } 790d48523cbSMartin Habets 79195e96f77SMartin Habets void efx_siena_selftest_async_cancel(struct efx_nic *efx) 792d48523cbSMartin Habets { 793d48523cbSMartin Habets cancel_delayed_work_sync(&efx->selftest_work); 794d48523cbSMartin Habets } 795d48523cbSMartin Habets 79695e96f77SMartin Habets static void efx_siena_selftest_async_work(struct work_struct *data) 797d48523cbSMartin Habets { 798d48523cbSMartin Habets struct efx_nic *efx = container_of(data, struct efx_nic, 799d48523cbSMartin Habets selftest_work.work); 800d48523cbSMartin Habets struct efx_channel *channel; 801d48523cbSMartin Habets int cpu; 802d48523cbSMartin Habets 803d48523cbSMartin Habets efx_for_each_channel(channel, efx) { 804d48523cbSMartin Habets cpu = efx_nic_event_test_irq_cpu(channel); 805d48523cbSMartin Habets if (cpu < 0) 806d48523cbSMartin Habets netif_err(efx, ifup, efx->net_dev, 807d48523cbSMartin Habets "channel %d failed to trigger an interrupt\n", 808d48523cbSMartin Habets channel->channel); 809d48523cbSMartin Habets else 810d48523cbSMartin Habets netif_dbg(efx, ifup, efx->net_dev, 811d48523cbSMartin Habets "channel %d triggered interrupt on CPU %d\n", 812d48523cbSMartin Habets channel->channel, cpu); 813d48523cbSMartin Habets } 814d48523cbSMartin Habets } 815d48523cbSMartin Habets 81695e96f77SMartin Habets void efx_siena_selftest_async_init(struct efx_nic *efx) 817d48523cbSMartin Habets { 81895e96f77SMartin Habets INIT_DELAYED_WORK(&efx->selftest_work, efx_siena_selftest_async_work); 819d48523cbSMartin Habets } 820