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