diff options
Diffstat (limited to 'drivers/net/ethernet/sfc/selftest.c')
| -rw-r--r-- | drivers/net/ethernet/sfc/selftest.c | 113 |
1 files changed, 60 insertions, 53 deletions
diff --git a/drivers/net/ethernet/sfc/selftest.c b/drivers/net/ethernet/sfc/selftest.c index f6936949fc85..894fad0bb5ea 100644 --- a/drivers/net/ethernet/sfc/selftest.c +++ b/drivers/net/ethernet/sfc/selftest.c @@ -1,11 +1,8 @@ +// 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. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation, incorporated herein by reference. */ #include <linux/netdevice.h> @@ -21,7 +18,10 @@ #include <linux/slab.h> #include "net_driver.h" #include "efx.h" +#include "efx_common.h" +#include "efx_channels.h" #include "nic.h" +#include "mcdi_port_common.h" #include "selftest.h" #include "workarounds.h" @@ -38,16 +38,20 @@ /* * Loopback test packet structure * - * The self-test should stress every RSS vector, and unfortunately - * Falcon only performs RSS on TCP/UDP packets. + * The self-test should stress every RSS vector. */ struct efx_loopback_payload { - struct ethhdr header; - struct iphdr ip; - struct udphdr udp; - __be16 iteration; - char msg[64]; -} __packed; + char pad[2]; /* Ensures ip is 4-byte aligned */ + struct_group_attr(packet, __packed, + struct ethhdr header; + struct iphdr ip; + struct udphdr udp; + __be16 iteration; + char msg[64]; + ); +} __packed __aligned(4); +#define EFX_LOOPBACK_PAYLOAD_LEN \ + sizeof_field(struct efx_loopback_payload, packet) /* Loopback test source MAC address */ static const u8 payload_source[ETH_ALEN] __aligned(2) = { @@ -68,7 +72,7 @@ static const char *const efx_interrupt_mode_names[] = { STRING_TABLE_LOOKUP(efx->interrupt_mode, efx_interrupt_mode) /** - * efx_loopback_state - persistent state during a loopback selftest + * struct efx_loopback_state - persistent state during a loopback selftest * @flush: Drop all packets in efx_loopback_rx_packet * @packet_count: Number of packets being used in this test * @skbs: An array of skbs transmitted @@ -100,10 +104,8 @@ static int efx_test_phy_alive(struct efx_nic *efx, struct efx_self_tests *tests) { int rc = 0; - if (efx->phy_op->test_alive) { - rc = efx->phy_op->test_alive(efx); - tests->phy_alive = rc ? -1 : 1; - } + rc = efx_mcdi_phy_test_alive(efx); + tests->phy_alive = rc ? -1 : 1; return rc; } @@ -258,11 +260,8 @@ static int efx_test_phy(struct efx_nic *efx, struct efx_self_tests *tests, { int rc; - if (!efx->phy_op->run_tests) - return 0; - mutex_lock(&efx->mac_lock); - rc = efx->phy_op->run_tests(efx, tests->phy_ext, flags); + rc = efx_mcdi_phy_run_tests(efx, tests->phy_ext, flags); mutex_unlock(&efx->mac_lock); if (rc == -EPERM) rc = 0; @@ -287,7 +286,7 @@ void efx_loopback_rx_packet(struct efx_nic *efx, const char *buf_ptr, int pkt_len) { struct efx_loopback_state *state = efx->loopback_selftest; - struct efx_loopback_payload *received; + struct efx_loopback_payload received; struct efx_loopback_payload *payload; BUG_ON(!buf_ptr); @@ -298,13 +297,14 @@ void efx_loopback_rx_packet(struct efx_nic *efx, payload = &state->payload; - received = (struct efx_loopback_payload *) buf_ptr; - received->ip.saddr = payload->ip.saddr; + memcpy(&received.packet, buf_ptr, + min_t(int, pkt_len, EFX_LOOPBACK_PAYLOAD_LEN)); + received.ip.saddr = payload->ip.saddr; if (state->offload_csum) - received->ip.check = payload->ip.check; + received.ip.check = payload->ip.check; /* Check that header exists */ - if (pkt_len < sizeof(received->header)) { + if (pkt_len < sizeof(received.header)) { netif_err(efx, drv, efx->net_dev, "saw runt RX packet (length %d) in %s loopback " "test\n", pkt_len, LOOPBACK_MODE(efx)); @@ -312,7 +312,7 @@ void efx_loopback_rx_packet(struct efx_nic *efx, } /* Check that the ethernet header exists */ - if (memcmp(&received->header, &payload->header, ETH_HLEN) != 0) { + if (memcmp(&received.header, &payload->header, ETH_HLEN) != 0) { netif_err(efx, drv, efx->net_dev, "saw non-loopback RX packet in %s loopback test\n", LOOPBACK_MODE(efx)); @@ -320,16 +320,16 @@ void efx_loopback_rx_packet(struct efx_nic *efx, } /* Check packet length */ - if (pkt_len != sizeof(*payload)) { + if (pkt_len != EFX_LOOPBACK_PAYLOAD_LEN) { netif_err(efx, drv, efx->net_dev, "saw incorrect RX packet length %d (wanted %d) in " - "%s loopback test\n", pkt_len, (int)sizeof(*payload), - LOOPBACK_MODE(efx)); + "%s loopback test\n", pkt_len, + (int)EFX_LOOPBACK_PAYLOAD_LEN, LOOPBACK_MODE(efx)); goto err; } /* Check that IP header matches */ - if (memcmp(&received->ip, &payload->ip, sizeof(payload->ip)) != 0) { + if (memcmp(&received.ip, &payload->ip, sizeof(payload->ip)) != 0) { netif_err(efx, drv, efx->net_dev, "saw corrupted IP header in %s loopback test\n", LOOPBACK_MODE(efx)); @@ -337,7 +337,7 @@ void efx_loopback_rx_packet(struct efx_nic *efx, } /* Check that msg and padding matches */ - if (memcmp(&received->msg, &payload->msg, sizeof(received->msg)) != 0) { + if (memcmp(&received.msg, &payload->msg, sizeof(received.msg)) != 0) { netif_err(efx, drv, efx->net_dev, "saw corrupted RX packet in %s loopback test\n", LOOPBACK_MODE(efx)); @@ -345,10 +345,10 @@ void efx_loopback_rx_packet(struct efx_nic *efx, } /* Check that iteration matches */ - if (received->iteration != payload->iteration) { + if (received.iteration != payload->iteration) { netif_err(efx, drv, efx->net_dev, "saw RX packet from iteration %d (wanted %d) in " - "%s loopback test\n", ntohs(received->iteration), + "%s loopback test\n", ntohs(received.iteration), ntohs(payload->iteration), LOOPBACK_MODE(efx)); goto err; } @@ -368,7 +368,8 @@ void efx_loopback_rx_packet(struct efx_nic *efx, buf_ptr, pkt_len, 0); netif_err(efx, drv, efx->net_dev, "expected packet:\n"); print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 0x10, 1, - &state->payload, sizeof(state->payload), 0); + &state->payload.packet, EFX_LOOPBACK_PAYLOAD_LEN, + 0); } #endif atomic_inc(&state->rx_bad); @@ -390,14 +391,15 @@ static void efx_iterate_state(struct efx_nic *efx) payload->ip.daddr = htonl(INADDR_LOOPBACK); payload->ip.ihl = 5; payload->ip.check = (__force __sum16) htons(0xdead); - payload->ip.tot_len = htons(sizeof(*payload) - sizeof(struct ethhdr)); + payload->ip.tot_len = htons(sizeof(*payload) - + offsetof(struct efx_loopback_payload, ip)); payload->ip.version = IPVERSION; payload->ip.protocol = IPPROTO_UDP; /* Initialise udp header */ payload->udp.source = 0; - payload->udp.len = htons(sizeof(*payload) - sizeof(struct ethhdr) - - sizeof(struct iphdr)); + payload->udp.len = htons(sizeof(*payload) - + offsetof(struct efx_loopback_payload, udp)); payload->udp.check = 0; /* checksum ignored */ /* Fill out payload */ @@ -434,6 +436,10 @@ static int efx_begin_loopback(struct efx_tx_queue *tx_queue) payload = skb_put(skb, sizeof(state->payload)); memcpy(payload, &state->payload, sizeof(state->payload)); payload->ip.saddr = htonl(INADDR_LOOPBACK | (i << 2)); + /* Strip off the leading padding */ + skb_pull(skb, offsetof(struct efx_loopback_payload, header)); + /* Strip off the trailing padding */ + skb_trim(skb, EFX_LOOPBACK_PAYLOAD_LEN); /* Ensure everything we've written is visible to the * interrupt handler. */ @@ -446,7 +452,7 @@ static int efx_begin_loopback(struct efx_tx_queue *tx_queue) if (rc != NETDEV_TX_OK) { netif_err(efx, drv, efx->net_dev, "TX queue %d could not transmit packet %d of " - "%d in %s loopback test\n", tx_queue->queue, + "%d in %s loopback test\n", tx_queue->label, i + 1, state->packet_count, LOOPBACK_MODE(efx)); @@ -498,7 +504,7 @@ static int efx_end_loopback(struct efx_tx_queue *tx_queue, netif_err(efx, drv, efx->net_dev, "TX queue %d saw only %d out of an expected %d " "TX completion events in %s loopback test\n", - tx_queue->queue, tx_done, state->packet_count, + tx_queue->label, tx_done, state->packet_count, LOOPBACK_MODE(efx)); rc = -ETIMEDOUT; /* Allow to fall through so we see the RX errors as well */ @@ -509,15 +515,15 @@ static int efx_end_loopback(struct efx_tx_queue *tx_queue, netif_dbg(efx, drv, efx->net_dev, "TX queue %d saw only %d out of an expected %d " "received packets in %s loopback test\n", - tx_queue->queue, rx_good, state->packet_count, + tx_queue->label, rx_good, state->packet_count, LOOPBACK_MODE(efx)); rc = -ETIMEDOUT; /* Fall through */ } /* Update loopback test structure */ - lb_tests->tx_sent[tx_queue->queue] += state->packet_count; - lb_tests->tx_done[tx_queue->queue] += tx_done; + lb_tests->tx_sent[tx_queue->label] += state->packet_count; + lb_tests->tx_done[tx_queue->label] += tx_done; lb_tests->rx_good += rx_good; lb_tests->rx_bad += rx_bad; @@ -543,8 +549,8 @@ efx_test_loopback(struct efx_tx_queue *tx_queue, state->flush = false; netif_dbg(efx, drv, efx->net_dev, - "TX queue %d testing %s loopback with %d packets\n", - tx_queue->queue, LOOPBACK_MODE(efx), + "TX queue %d (hw %d) testing %s loopback with %d packets\n", + tx_queue->label, tx_queue->queue, LOOPBACK_MODE(efx), state->packet_count); efx_iterate_state(efx); @@ -571,16 +577,12 @@ efx_test_loopback(struct efx_tx_queue *tx_queue, netif_dbg(efx, drv, efx->net_dev, "TX queue %d passed %s loopback test with a burst length " - "of %d packets\n", tx_queue->queue, LOOPBACK_MODE(efx), + "of %d packets\n", tx_queue->label, LOOPBACK_MODE(efx), state->packet_count); return 0; } -/* Wait for link up. On Falcon, we would prefer to rely on efx_monitor, but - * any contention on the mac lock (via e.g. efx_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 efx_wait_for_link(struct efx_nic *efx) { struct efx_link_state *link_state = &efx->link_state; @@ -661,8 +663,8 @@ static int efx_test_loopbacks(struct efx_nic *efx, struct efx_self_tests *tests, /* Test all enabled types of TX queue */ efx_for_each_channel_tx_queue(tx_queue, channel) { - state->offload_csum = (tx_queue->queue & - EFX_TXQ_TYPE_OFFLOAD); + state->offload_csum = (tx_queue->type & + EFX_TXQ_TYPE_OUTER_CSUM); rc = efx_test_loopback(tx_queue, &tests->loopback[mode]); if (rc) @@ -786,7 +788,7 @@ void efx_selftest_async_cancel(struct efx_nic *efx) cancel_delayed_work_sync(&efx->selftest_work); } -void efx_selftest_async_work(struct work_struct *data) +static void efx_selftest_async_work(struct work_struct *data) { struct efx_nic *efx = container_of(data, struct efx_nic, selftest_work.work); @@ -805,3 +807,8 @@ void efx_selftest_async_work(struct work_struct *data) channel->channel, cpu); } } + +void efx_selftest_async_init(struct efx_nic *efx) +{ + INIT_DELAYED_WORK(&efx->selftest_work, efx_selftest_async_work); +} |
