diff options
Diffstat (limited to 'drivers/net/ethernet/sfc')
-rw-r--r-- | drivers/net/ethernet/sfc/ef10.c | 27 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/ef10_regs.h | 61 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/efx.c | 33 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/efx.h | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/ethtool.c | 39 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/falcon.c | 6 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/farch.c | 5 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/filter.h | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/mcdi.c | 14 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/mcdi_port.c | 4 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/net_driver.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/nic.c | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/ptp.c | 93 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/selftest.c | 6 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/siena_sriov.c | 13 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/tx.c | 21 |
16 files changed, 127 insertions, 201 deletions
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index 174a92f5fe51..21c20ea0dad0 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -162,8 +162,8 @@ static int efx_ef10_get_mac_address(struct efx_nic *efx, u8 *mac_address) if (outlen < MC_CMD_GET_MAC_ADDRESSES_OUT_LEN) return -EIO; - memcpy(mac_address, - MCDI_PTR(outbuf, GET_MAC_ADDRESSES_OUT_MAC_ADDR_BASE), ETH_ALEN); + ether_addr_copy(mac_address, + MCDI_PTR(outbuf, GET_MAC_ADDRESSES_OUT_MAC_ADDR_BASE)); return 0; } @@ -172,8 +172,8 @@ static int efx_ef10_probe(struct efx_nic *efx) struct efx_ef10_nic_data *nic_data; int i, rc; - /* We can have one VI for each 8K region. However we need - * multiple TX queues per channel. + /* We can have one VI for each 8K region. However, until we + * use TX option descriptors we need two TX queues per channel. */ efx->max_channels = min_t(unsigned int, @@ -565,10 +565,17 @@ static int efx_ef10_dimension_resources(struct efx_nic *efx) * several of each (in fact that's the only option if host * page size is >4K). So we may allocate some extra VIs just * for writing PIO buffers through. + * + * The UC mapping contains (min_vis - 1) complete VIs and the + * first half of the next VI. Then the WC mapping begins with + * the second half of this last VI. */ uc_mem_map_size = PAGE_ALIGN((min_vis - 1) * EFX_VI_PAGE_SIZE + ER_DZ_TX_PIOBUF); if (nic_data->n_piobufs) { + /* pio_write_vi_base rounds down to give the number of complete + * VIs inside the UC mapping. + */ pio_write_vi_base = uc_mem_map_size / EFX_VI_PAGE_SIZE; wc_mem_map_size = (PAGE_ALIGN((pio_write_vi_base + nic_data->n_piobufs) * @@ -1955,6 +1962,9 @@ static int efx_ef10_ev_process(struct efx_channel *channel, int quota) int tx_descs = 0; int spent = 0; + if (quota <= 0) + return spent; + read_ptr = channel->eventq_read_ptr; for (;;) { @@ -3145,12 +3155,10 @@ static void efx_ef10_filter_sync_rx_mode(struct efx_nic *efx) table->dev_uc_count = -1; } else { table->dev_uc_count = 1 + netdev_uc_count(net_dev); - memcpy(table->dev_uc_list[0].addr, net_dev->dev_addr, - ETH_ALEN); + ether_addr_copy(table->dev_uc_list[0].addr, net_dev->dev_addr); i = 1; netdev_for_each_uc_addr(uc, net_dev) { - memcpy(table->dev_uc_list[i].addr, - uc->addr, ETH_ALEN); + ether_addr_copy(table->dev_uc_list[i].addr, uc->addr); i++; } } @@ -3162,8 +3170,7 @@ static void efx_ef10_filter_sync_rx_mode(struct efx_nic *efx) eth_broadcast_addr(table->dev_mc_list[0].addr); i = 1; netdev_for_each_mc_addr(mc, net_dev) { - memcpy(table->dev_mc_list[i].addr, - mc->addr, ETH_ALEN); + ether_addr_copy(table->dev_mc_list[i].addr, mc->addr); i++; } } diff --git a/drivers/net/ethernet/sfc/ef10_regs.h b/drivers/net/ethernet/sfc/ef10_regs.h index 207ac9a1e3de..62a55dde61d5 100644 --- a/drivers/net/ethernet/sfc/ef10_regs.h +++ b/drivers/net/ethernet/sfc/ef10_regs.h @@ -227,36 +227,6 @@ #define ESF_DZ_RX_KER_BUF_ADDR_LBN 0 #define ESF_DZ_RX_KER_BUF_ADDR_WIDTH 48 -/* RX_USER_DESC */ -#define ESF_DZ_RX_USR_RESERVED_LBN 62 -#define ESF_DZ_RX_USR_RESERVED_WIDTH 2 -#define ESF_DZ_RX_USR_BYTE_CNT_LBN 48 -#define ESF_DZ_RX_USR_BYTE_CNT_WIDTH 14 -#define ESF_DZ_RX_USR_BUF_PAGE_SIZE_LBN 44 -#define ESF_DZ_RX_USR_BUF_PAGE_SIZE_WIDTH 4 -#define ESE_DZ_USR_BUF_PAGE_SZ_4MB 10 -#define ESE_DZ_USR_BUF_PAGE_SZ_1MB 8 -#define ESE_DZ_USR_BUF_PAGE_SZ_64KB 4 -#define ESE_DZ_USR_BUF_PAGE_SZ_4KB 0 -#define ESF_DZ_RX_USR_BUF_ID_OFFSET_LBN 0 -#define ESF_DZ_RX_USR_BUF_ID_OFFSET_WIDTH 44 -#define ESF_DZ_RX_USR_4KBPS_BUF_ID_LBN 12 -#define ESF_DZ_RX_USR_4KBPS_BUF_ID_WIDTH 32 -#define ESF_DZ_RX_USR_64KBPS_BUF_ID_LBN 16 -#define ESF_DZ_RX_USR_64KBPS_BUF_ID_WIDTH 28 -#define ESF_DZ_RX_USR_1MBPS_BUF_ID_LBN 20 -#define ESF_DZ_RX_USR_1MBPS_BUF_ID_WIDTH 24 -#define ESF_DZ_RX_USR_4MBPS_BUF_ID_LBN 22 -#define ESF_DZ_RX_USR_4MBPS_BUF_ID_WIDTH 22 -#define ESF_DZ_RX_USR_4MBPS_BYTE_OFFSET_LBN 0 -#define ESF_DZ_RX_USR_4MBPS_BYTE_OFFSET_WIDTH 22 -#define ESF_DZ_RX_USR_1MBPS_BYTE_OFFSET_LBN 0 -#define ESF_DZ_RX_USR_1MBPS_BYTE_OFFSET_WIDTH 20 -#define ESF_DZ_RX_USR_64KBPS_BYTE_OFFSET_LBN 0 -#define ESF_DZ_RX_USR_64KBPS_BYTE_OFFSET_WIDTH 16 -#define ESF_DZ_RX_USR_4KBPS_BYTE_OFFSET_LBN 0 -#define ESF_DZ_RX_USR_4KBPS_BYTE_OFFSET_WIDTH 12 - /* TX_CSUM_TSTAMP_DESC */ #define ESF_DZ_TX_DESC_IS_OPT_LBN 63 #define ESF_DZ_TX_DESC_IS_OPT_WIDTH 1 @@ -338,37 +308,6 @@ #define ESF_DZ_TX_TSO_TCP_SEQNO_LBN 0 #define ESF_DZ_TX_TSO_TCP_SEQNO_WIDTH 32 -/* TX_USER_DESC */ -#define ESF_DZ_TX_USR_TYPE_LBN 63 -#define ESF_DZ_TX_USR_TYPE_WIDTH 1 -#define ESF_DZ_TX_USR_CONT_LBN 62 -#define ESF_DZ_TX_USR_CONT_WIDTH 1 -#define ESF_DZ_TX_USR_BYTE_CNT_LBN 48 -#define ESF_DZ_TX_USR_BYTE_CNT_WIDTH 14 -#define ESF_DZ_TX_USR_BUF_PAGE_SIZE_LBN 44 -#define ESF_DZ_TX_USR_BUF_PAGE_SIZE_WIDTH 4 -#define ESE_DZ_USR_BUF_PAGE_SZ_4MB 10 -#define ESE_DZ_USR_BUF_PAGE_SZ_1MB 8 -#define ESE_DZ_USR_BUF_PAGE_SZ_64KB 4 -#define ESE_DZ_USR_BUF_PAGE_SZ_4KB 0 -#define ESF_DZ_TX_USR_BUF_ID_OFFSET_LBN 0 -#define ESF_DZ_TX_USR_BUF_ID_OFFSET_WIDTH 44 -#define ESF_DZ_TX_USR_4KBPS_BUF_ID_LBN 12 -#define ESF_DZ_TX_USR_4KBPS_BUF_ID_WIDTH 32 -#define ESF_DZ_TX_USR_64KBPS_BUF_ID_LBN 16 -#define ESF_DZ_TX_USR_64KBPS_BUF_ID_WIDTH 28 -#define ESF_DZ_TX_USR_1MBPS_BUF_ID_LBN 20 -#define ESF_DZ_TX_USR_1MBPS_BUF_ID_WIDTH 24 -#define ESF_DZ_TX_USR_4MBPS_BUF_ID_LBN 22 -#define ESF_DZ_TX_USR_4MBPS_BUF_ID_WIDTH 22 -#define ESF_DZ_TX_USR_4MBPS_BYTE_OFFSET_LBN 0 -#define ESF_DZ_TX_USR_4MBPS_BYTE_OFFSET_WIDTH 22 -#define ESF_DZ_TX_USR_1MBPS_BYTE_OFFSET_LBN 0 -#define ESF_DZ_TX_USR_1MBPS_BYTE_OFFSET_WIDTH 20 -#define ESF_DZ_TX_USR_64KBPS_BYTE_OFFSET_LBN 0 -#define ESF_DZ_TX_USR_64KBPS_BYTE_OFFSET_WIDTH 16 -#define ESF_DZ_TX_USR_4KBPS_BYTE_OFFSET_LBN 0 -#define ESF_DZ_TX_USR_4KBPS_BYTE_OFFSET_WIDTH 12 /*************************************************************************/ /* TX_DESC_UPD_REG: Transmit descriptor update register. diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index 83d464347021..57b971e5e6b2 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -503,8 +503,6 @@ static int efx_probe_channel(struct efx_channel *channel) goto fail; } - channel->n_rx_frm_trunc = 0; - return 0; fail: @@ -1014,7 +1012,7 @@ static int efx_probe_port(struct efx_nic *efx) return rc; /* Initialise MAC address to permanent address */ - memcpy(efx->net_dev->dev_addr, efx->net_dev->perm_addr, ETH_ALEN); + ether_addr_copy(efx->net_dev->dev_addr, efx->net_dev->perm_addr); return 0; } @@ -1346,20 +1344,23 @@ static int efx_probe_interrupts(struct efx_nic *efx) for (i = 0; i < n_channels; i++) xentries[i].entry = i; - rc = pci_enable_msix(efx->pci_dev, xentries, n_channels); - if (rc > 0) { + rc = pci_enable_msix_range(efx->pci_dev, + xentries, 1, n_channels); + if (rc < 0) { + /* Fall back to single channel MSI */ + efx->interrupt_mode = EFX_INT_MODE_MSI; + netif_err(efx, drv, efx->net_dev, + "could not enable MSI-X\n"); + } else if (rc < n_channels) { netif_err(efx, drv, efx->net_dev, "WARNING: Insufficient MSI-X vectors" " available (%d < %u).\n", rc, n_channels); netif_err(efx, drv, efx->net_dev, "WARNING: Performance may be reduced.\n"); - EFX_BUG_ON_PARANOID(rc >= n_channels); n_channels = rc; - rc = pci_enable_msix(efx->pci_dev, xentries, - n_channels); } - if (rc == 0) { + if (rc > 0) { efx->n_channels = n_channels; if (n_channels > extra_channels) n_channels -= extra_channels; @@ -1375,11 +1376,6 @@ static int efx_probe_interrupts(struct efx_nic *efx) for (i = 0; i < efx->n_channels; i++) efx_get_channel(efx, i)->irq = xentries[i].vector; - } else { - /* Fall back to single channel MSI */ - efx->interrupt_mode = EFX_INT_MODE_MSI; - netif_err(efx, drv, efx->net_dev, - "could not enable MSI-X\n"); } } @@ -1603,6 +1599,8 @@ static int efx_probe_nic(struct efx_nic *efx) if (rc) goto fail1; + efx_set_channels(efx); + rc = efx->type->dimension_resources(efx); if (rc) goto fail2; @@ -1613,7 +1611,6 @@ static int efx_probe_nic(struct efx_nic *efx) efx->rx_indir_table[i] = ethtool_rxfh_indir_default(i, efx->rss_spread); - efx_set_channels(efx); netif_set_real_num_tx_queues(efx->net_dev, efx->n_tx_channels); netif_set_real_num_rx_queues(efx->net_dev, efx->n_rx_channels); @@ -2115,7 +2112,7 @@ static int efx_set_mac_address(struct net_device *net_dev, void *data) { struct efx_nic *efx = netdev_priv(net_dev); struct sockaddr *addr = data; - char *new_addr = addr->sa_data; + u8 *new_addr = addr->sa_data; if (!is_valid_ether_addr(new_addr)) { netif_err(efx, drv, efx->net_dev, @@ -2124,7 +2121,7 @@ static int efx_set_mac_address(struct net_device *net_dev, void *data) return -EADDRNOTAVAIL; } - memcpy(net_dev->dev_addr, new_addr, net_dev->addr_len); + ether_addr_copy(net_dev->dev_addr, new_addr); efx_sriov_mac_address_changed(efx); /* Reconfigure the MAC */ @@ -3273,6 +3270,6 @@ module_exit(efx_exit_module); MODULE_AUTHOR("Solarflare Communications and " "Michael Brown <mbrown@fensystems.co.uk>"); -MODULE_DESCRIPTION("Solarflare Communications network driver"); +MODULE_DESCRIPTION("Solarflare network driver"); MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(pci, efx_pci_table); diff --git a/drivers/net/ethernet/sfc/efx.h b/drivers/net/ethernet/sfc/efx.h index dbd7b78fe01c..99032581336f 100644 --- a/drivers/net/ethernet/sfc/efx.h +++ b/drivers/net/ethernet/sfc/efx.h @@ -14,7 +14,7 @@ #include "net_driver.h" #include "filter.h" -/* Solarstorm controllers use BAR 0 for I/O space and BAR 2(&3) for memory */ +/* All controllers use BAR 0 for I/O space and BAR 2(&3) for memory */ #define EFX_MEM_BAR 2 /* TX */ diff --git a/drivers/net/ethernet/sfc/ethtool.c b/drivers/net/ethernet/sfc/ethtool.c index 229428915aa8..0de8b07c24c2 100644 --- a/drivers/net/ethernet/sfc/ethtool.c +++ b/drivers/net/ethernet/sfc/ethtool.c @@ -251,6 +251,9 @@ static void efx_fill_test(unsigned int test_index, u8 *strings, u64 *data, * @test_index: Starting index of the test * @strings: Ethtool strings, or %NULL * @data: Ethtool test results, or %NULL + * + * Fill in a block of loopback self-test entries. Return new test + * index. */ static int efx_fill_loopback_test(struct efx_nic *efx, struct efx_loopback_self_tests *lb_tests, @@ -290,6 +293,12 @@ static int efx_fill_loopback_test(struct efx_nic *efx, * @tests: Efx self-test results structure, or %NULL * @strings: Ethtool strings, or %NULL * @data: Ethtool test results, or %NULL + * + * Get self-test number of strings, strings, and/or test results. + * Return number of strings (== number of test results). + * + * The reason for merging these three functions is to make sure that + * they can never be inconsistent. */ static int efx_ethtool_fill_self_tests(struct efx_nic *efx, struct efx_self_tests *tests, @@ -444,7 +453,7 @@ static void efx_ethtool_self_test(struct net_device *net_dev, { struct efx_nic *efx = netdev_priv(net_dev); struct efx_self_tests *efx_tests; - int already_up; + bool already_up; int rc = -ENOMEM; efx_tests = kzalloc(sizeof(*efx_tests), GFP_KERNEL); @@ -452,8 +461,8 @@ static void efx_ethtool_self_test(struct net_device *net_dev, goto fail; if (efx->state != STATE_READY) { - rc = -EIO; - goto fail1; + rc = -EBUSY; + goto out; } netif_info(efx, drv, efx->net_dev, "starting %sline testing\n", @@ -466,7 +475,7 @@ static void efx_ethtool_self_test(struct net_device *net_dev, if (rc) { netif_err(efx, drv, efx->net_dev, "failed opening device.\n"); - goto fail1; + goto out; } } @@ -479,8 +488,7 @@ static void efx_ethtool_self_test(struct net_device *net_dev, rc == 0 ? "passed" : "failed", (test->flags & ETH_TEST_FL_OFFLINE) ? "off" : "on"); -fail1: - /* Fill ethtool results structures */ +out: efx_ethtool_fill_self_tests(efx, efx_tests, NULL, data); kfree(efx_tests); fail: @@ -691,7 +699,6 @@ static void efx_ethtool_get_pauseparam(struct net_device *net_dev, pause->autoneg = !!(efx->wanted_fc & EFX_FC_AUTO); } - static void efx_ethtool_get_wol(struct net_device *net_dev, struct ethtool_wolinfo *wol) { @@ -720,7 +727,7 @@ static int efx_ethtool_reset(struct net_device *net_dev, u32 *flags) } /* MAC address mask including only I/G bit */ -static const u8 mac_addr_ig_mask[ETH_ALEN] = { 0x01, 0, 0, 0, 0, 0 }; +static const u8 mac_addr_ig_mask[ETH_ALEN] __aligned(2) = {0x01, 0, 0, 0, 0, 0}; #define IP4_ADDR_FULL_MASK ((__force __be32)~0) #define PORT_FULL_MASK ((__force __be16)~0) @@ -780,16 +787,16 @@ static int efx_ethtool_get_class_rule(struct efx_nic *efx, rule->flow_type = ETHER_FLOW; if (spec.match_flags & (EFX_FILTER_MATCH_LOC_MAC | EFX_FILTER_MATCH_LOC_MAC_IG)) { - memcpy(mac_entry->h_dest, spec.loc_mac, ETH_ALEN); + ether_addr_copy(mac_entry->h_dest, spec.loc_mac); if (spec.match_flags & EFX_FILTER_MATCH_LOC_MAC) - memset(mac_mask->h_dest, ~0, ETH_ALEN); + eth_broadcast_addr(mac_mask->h_dest); else - memcpy(mac_mask->h_dest, mac_addr_ig_mask, - ETH_ALEN); + ether_addr_copy(mac_mask->h_dest, + mac_addr_ig_mask); } if (spec.match_flags & EFX_FILTER_MATCH_REM_MAC) { - memcpy(mac_entry->h_source, spec.rem_mac, ETH_ALEN); - memset(mac_mask->h_source, ~0, ETH_ALEN); + ether_addr_copy(mac_entry->h_source, spec.rem_mac); + eth_broadcast_addr(mac_mask->h_source); } if (spec.match_flags & EFX_FILTER_MATCH_ETHER_TYPE) { mac_entry->h_proto = spec.ether_type; @@ -961,13 +968,13 @@ static int efx_ethtool_set_class_rule(struct efx_nic *efx, spec.match_flags |= EFX_FILTER_MATCH_LOC_MAC; else return -EINVAL; - memcpy(spec.loc_mac, mac_entry->h_dest, ETH_ALEN); + ether_addr_copy(spec.loc_mac, mac_entry->h_dest); } if (!is_zero_ether_addr(mac_mask->h_source)) { if (!is_broadcast_ether_addr(mac_mask->h_source)) return -EINVAL; spec.match_flags |= EFX_FILTER_MATCH_REM_MAC; - memcpy(spec.rem_mac, mac_entry->h_source, ETH_ALEN); + ether_addr_copy(spec.rem_mac, mac_entry->h_source); } if (mac_mask->h_proto) { if (mac_mask->h_proto != ETHER_TYPE_FULL_MASK) diff --git a/drivers/net/ethernet/sfc/falcon.c b/drivers/net/ethernet/sfc/falcon.c index 18d6f761f4d0..8ec20b713cc6 100644 --- a/drivers/net/ethernet/sfc/falcon.c +++ b/drivers/net/ethernet/sfc/falcon.c @@ -422,7 +422,6 @@ static inline void falcon_irq_ack_a1(struct efx_nic *efx) efx_readd(efx, ®, FR_AA_WORK_AROUND_BROKEN_PCI_READS); } - static irqreturn_t falcon_legacy_interrupt_a1(int irq, void *dev_id) { struct efx_nic *efx = dev_id; @@ -467,6 +466,7 @@ static irqreturn_t falcon_legacy_interrupt_a1(int irq, void *dev_id) efx_schedule_channel_irq(efx_get_channel(efx, 1)); return IRQ_HANDLED; } + /************************************************************************** * * RSS @@ -1358,6 +1358,7 @@ static void falcon_reconfigure_mac_wrapper(struct efx_nic *efx) case 100: link_speed = 1; break; default: link_speed = 0; break; } + /* MAC_LINK_STATUS controls MAC backpressure but doesn't work * as advertised. Disable to ensure packets are not * indefinitely held and TX queue can be flushed at any point @@ -2182,7 +2183,7 @@ static int falcon_probe_nvconfig(struct efx_nic *efx) } /* Read the MAC addresses */ - memcpy(efx->net_dev->perm_addr, nvconfig->mac_address[0], ETH_ALEN); + ether_addr_copy(efx->net_dev->perm_addr, nvconfig->mac_address[0]); netif_dbg(efx, probe, efx->net_dev, "PHY is %d phy_id %d\n", efx->phy_type, efx->mdio.prtad); @@ -2868,4 +2869,3 @@ const struct efx_nic_type falcon_b0_nic_type = { .mcdi_max_ver = -1, .max_rx_ip_filters = FR_BZ_RX_FILTER_TBL0_ROWS, }; - diff --git a/drivers/net/ethernet/sfc/farch.c b/drivers/net/ethernet/sfc/farch.c index f72489a105ca..a08761360cdf 100644 --- a/drivers/net/ethernet/sfc/farch.c +++ b/drivers/net/ethernet/sfc/farch.c @@ -311,7 +311,6 @@ static inline void efx_farch_push_tx_desc(struct efx_tx_queue *tx_queue, */ void efx_farch_tx_write(struct efx_tx_queue *tx_queue) { - struct efx_tx_buffer *buffer; efx_qword_t *txd; unsigned write_ptr; @@ -1249,6 +1248,9 @@ int efx_farch_ev_process(struct efx_channel *channel, int budget) int tx_packets = 0; int spent = 0; + if (budget <= 0) + return spent; + read_ptr = channel->eventq_read_ptr; for (;;) { @@ -1609,7 +1611,6 @@ irqreturn_t efx_farch_msi_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } - /* Setup RSS indirection table. * This maps from the hash value of the packet to RXQ */ diff --git a/drivers/net/ethernet/sfc/filter.h b/drivers/net/ethernet/sfc/filter.h index 3ef298d3c47e..d0ed7f71ea7e 100644 --- a/drivers/net/ethernet/sfc/filter.h +++ b/drivers/net/ethernet/sfc/filter.h @@ -243,7 +243,7 @@ static inline int efx_filter_set_eth_local(struct efx_filter_spec *spec, } if (addr != NULL) { spec->match_flags |= EFX_FILTER_MATCH_LOC_MAC; - memcpy(spec->loc_mac, addr, ETH_ALEN); + ether_addr_copy(spec->loc_mac, addr); } return 0; } diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c index eb59abb57e85..7bd4b14bf3b3 100644 --- a/drivers/net/ethernet/sfc/mcdi.c +++ b/drivers/net/ethernet/sfc/mcdi.c @@ -1187,6 +1187,9 @@ int efx_mcdi_get_board_cfg(struct efx_nic *efx, u8 *mac_address, int rc; BUILD_BUG_ON(MC_CMD_GET_BOARD_CFG_IN_LEN != 0); + /* we need __aligned(2) for ether_addr_copy */ + BUILD_BUG_ON(MC_CMD_GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT0_OFST & 1); + BUILD_BUG_ON(MC_CMD_GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT1_OFST & 1); rc = efx_mcdi_rpc(efx, MC_CMD_GET_BOARD_CFG, NULL, 0, outbuf, sizeof(outbuf), &outlen); @@ -1199,11 +1202,10 @@ int efx_mcdi_get_board_cfg(struct efx_nic *efx, u8 *mac_address, } if (mac_address) - memcpy(mac_address, - port_num ? - MCDI_PTR(outbuf, GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT1) : - MCDI_PTR(outbuf, GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT0), - ETH_ALEN); + ether_addr_copy(mac_address, + port_num ? + MCDI_PTR(outbuf, GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT1) : + MCDI_PTR(outbuf, GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT0)); if (fw_subtype_list) { for (i = 0; i < MCDI_VAR_ARRAY_LEN(outlen, @@ -1532,7 +1534,7 @@ static int efx_mcdi_wol_filter_set(struct efx_nic *efx, u32 type, MCDI_SET_DWORD(inbuf, WOL_FILTER_SET_IN_WOL_TYPE, type); MCDI_SET_DWORD(inbuf, WOL_FILTER_SET_IN_FILTER_MODE, MC_CMD_FILTER_MODE_SIMPLE); - memcpy(MCDI_PTR(inbuf, WOL_FILTER_SET_IN_MAGIC_MAC), mac, ETH_ALEN); + ether_addr_copy(MCDI_PTR(inbuf, WOL_FILTER_SET_IN_MAGIC_MAC), mac); rc = efx_mcdi_rpc(efx, MC_CMD_WOL_FILTER_SET, inbuf, sizeof(inbuf), outbuf, sizeof(outbuf), &outlen); diff --git a/drivers/net/ethernet/sfc/mcdi_port.c b/drivers/net/ethernet/sfc/mcdi_port.c index 91d23252f8fa..e5fc4e1574b5 100644 --- a/drivers/net/ethernet/sfc/mcdi_port.c +++ b/drivers/net/ethernet/sfc/mcdi_port.c @@ -854,8 +854,8 @@ int efx_mcdi_set_mac(struct efx_nic *efx) BUILD_BUG_ON(MC_CMD_SET_MAC_OUT_LEN != 0); - memcpy(MCDI_PTR(cmdbytes, SET_MAC_IN_ADDR), - efx->net_dev->dev_addr, ETH_ALEN); + ether_addr_copy(MCDI_PTR(cmdbytes, SET_MAC_IN_ADDR), + efx->net_dev->dev_addr); MCDI_SET_DWORD(cmdbytes, SET_MAC_IN_MTU, EFX_MAX_FRAME_LEN(efx->net_dev->mtu)); diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index af2b8c59a903..8a400a0595eb 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -1323,7 +1323,6 @@ static inline struct efx_rx_buffer *efx_rx_buffer(struct efx_rx_queue *rx_queue, return &rx_queue->buffer[index]; } - /** * EFX_MAX_FRAME_LEN - calculate maximum frame length * diff --git a/drivers/net/ethernet/sfc/nic.c b/drivers/net/ethernet/sfc/nic.c index 79226b19e3c4..32d969e857f7 100644 --- a/drivers/net/ethernet/sfc/nic.c +++ b/drivers/net/ethernet/sfc/nic.c @@ -530,4 +530,3 @@ void efx_nic_fix_nodesc_drop_stat(struct efx_nic *efx, u64 *rx_nodesc_drops) efx->rx_nodesc_drops_prev_state = !!(efx->net_dev->flags & IFF_UP); *rx_nodesc_drops -= efx->rx_nodesc_drops_while_down; } - diff --git a/drivers/net/ethernet/sfc/ptp.c b/drivers/net/ethernet/sfc/ptp.c index d7a36829649a..6b861e3de4b0 100644 --- a/drivers/net/ethernet/sfc/ptp.c +++ b/drivers/net/ethernet/sfc/ptp.c @@ -223,7 +223,6 @@ struct efx_ptp_timeset { * @evt_list: List of MC receive events awaiting packets * @evt_free_list: List of free events * @evt_lock: Lock for manipulating evt_list and evt_free_list - * @evt_overflow: Boolean indicating that event list has overflowed * @rx_evts: Instantiated events (on evt_list and evt_free_list) * @workwq: Work queue for processing pending PTP operations * @work: Work task @@ -275,7 +274,6 @@ struct efx_ptp_data { struct list_head evt_list; struct list_head evt_free_list; spinlock_t evt_lock; - bool evt_overflow; struct efx_ptp_event_rx rx_evts[MAX_RECEIVE_EVENTS]; struct workqueue_struct *workwq; struct work_struct work; @@ -768,37 +766,36 @@ efx_ptp_process_times(struct efx_nic *efx, MCDI_DECLARE_STRUCT_PTR(synch_buf), return -EAGAIN; } - /* Convert the NIC time into kernel time. No correction is required- - * this time is the output of a firmware process. - */ - mc_time = ptp->nic_to_kernel_time(ptp->timeset[last_good].major, - ptp->timeset[last_good].minor, 0); - - /* Calculate delay from actual PPS to last_time */ - delta = ktime_to_timespec(mc_time); - delta.tv_nsec += - last_time->ts_real.tv_nsec - - (ptp->timeset[last_good].host_start & MC_NANOSECOND_MASK); - - /* It is possible that the seconds rolled over between taking + /* Calculate delay from last good sync (host time) to last_time. + * It is possible that the seconds rolled over between taking * the start reading and the last value written by the host. The * timescales are such that a gap of more than one second is never - * expected. + * expected. delta is *not* normalised. */ start_sec = ptp->timeset[last_good].host_start >> MC_NANOSECOND_BITS; last_sec = last_time->ts_real.tv_sec & MC_SECOND_MASK; - if (start_sec != last_sec) { - if (((start_sec + 1) & MC_SECOND_MASK) != last_sec) { - netif_warn(efx, hw, efx->net_dev, - "PTP bad synchronisation seconds\n"); - return -EAGAIN; - } else { - delta.tv_sec = 1; - } - } else { - delta.tv_sec = 0; + if (start_sec != last_sec && + ((start_sec + 1) & MC_SECOND_MASK) != last_sec) { + netif_warn(efx, hw, efx->net_dev, + "PTP bad synchronisation seconds\n"); + return -EAGAIN; } + delta.tv_sec = (last_sec - start_sec) & 1; + delta.tv_nsec = + last_time->ts_real.tv_nsec - + (ptp->timeset[last_good].host_start & MC_NANOSECOND_MASK); + + /* Convert the NIC time at last good sync into kernel time. + * No correction is required - this time is the output of a + * firmware process. + */ + mc_time = ptp->nic_to_kernel_time(ptp->timeset[last_good].major, + ptp->timeset[last_good].minor, 0); + + /* Calculate delay from NIC top of second to last_time */ + delta.tv_nsec += ktime_to_timespec(mc_time).tv_nsec; + /* Set PPS timestamp to match NIC top of second */ ptp->host_time_pps = *last_time; pps_sub_ts(&ptp->host_time_pps, delta); @@ -941,11 +938,6 @@ static void efx_ptp_drop_time_expired_events(struct efx_nic *efx) } } } - /* If the event overflow flag is set and the event list is now empty - * clear the flag to re-enable the overflow warning message. - */ - if (ptp->evt_overflow && list_empty(&ptp->evt_list)) - ptp->evt_overflow = false; spin_unlock_bh(&ptp->evt_lock); } @@ -989,11 +981,6 @@ static enum ptp_packet_state efx_ptp_match_rx(struct efx_nic *efx, break; } } - /* If the event overflow flag is set and the event list is now empty - * clear the flag to re-enable the overflow warning message. - */ - if (ptp->evt_overflow && list_empty(&ptp->evt_list)) - ptp->evt_overflow = false; spin_unlock_bh(&ptp->evt_lock); return rc; @@ -1147,7 +1134,6 @@ static int efx_ptp_stop(struct efx_nic *efx) list_for_each_safe(cursor, next, &efx->ptp_data->evt_list) { list_move(cursor, &efx->ptp_data->evt_free_list); } - ptp->evt_overflow = false; spin_unlock_bh(&efx->ptp_data->evt_lock); return rc; @@ -1208,6 +1194,7 @@ static const struct ptp_clock_info efx_phc_clock_info = { .n_alarm = 0, .n_ext_ts = 0, .n_per_out = 0, + .n_pins = 0, .pps = 1, .adjfreq = efx_phc_adjfreq, .adjtime = efx_phc_adjtime, @@ -1253,7 +1240,6 @@ int efx_ptp_probe(struct efx_nic *efx, struct efx_channel *channel) spin_lock_init(&ptp->evt_lock); for (pos = 0; pos < MAX_RECEIVE_EVENTS; pos++) list_add(&ptp->rx_evts[pos].link, &ptp->evt_free_list); - ptp->evt_overflow = false; /* Get the NIC PTP attributes and set up time conversions */ rc = efx_ptp_get_attributes(efx); @@ -1380,6 +1366,7 @@ static bool efx_ptp_rx(struct efx_channel *channel, struct sk_buff *skb) struct efx_ptp_match *match = (struct efx_ptp_match *)skb->cb; u8 *match_data_012, *match_data_345; unsigned int version; + u8 *data; match->expiry = jiffies + msecs_to_jiffies(PKT_EVENT_LIFETIME_MS); @@ -1388,7 +1375,8 @@ static bool efx_ptp_rx(struct efx_channel *channel, struct sk_buff *skb) if (!pskb_may_pull(skb, PTP_V1_MIN_LENGTH)) { return false; } - version = ntohs(*(__be16 *)&skb->data[PTP_V1_VERSION_OFFSET]); + data = skb->data; + version = ntohs(*(__be16 *)&data[PTP_V1_VERSION_OFFSET]); if (version != PTP_VERSION_V1) { return false; } @@ -1396,13 +1384,14 @@ static bool efx_ptp_rx(struct efx_channel *channel, struct sk_buff *skb) /* PTP V1 uses all six bytes of the UUID to match the packet * to the timestamp */ - match_data_012 = skb->data + PTP_V1_UUID_OFFSET; - match_data_345 = skb->data + PTP_V1_UUID_OFFSET + 3; + match_data_012 = data + PTP_V1_UUID_OFFSET; + match_data_345 = data + PTP_V1_UUID_OFFSET + 3; } else { if (!pskb_may_pull(skb, PTP_V2_MIN_LENGTH)) { return false; } - version = skb->data[PTP_V2_VERSION_OFFSET]; + data = skb->data; + version = data[PTP_V2_VERSION_OFFSET]; if ((version & PTP_VERSION_V2_MASK) != PTP_VERSION_V2) { return false; } @@ -1414,17 +1403,17 @@ static bool efx_ptp_rx(struct efx_channel *channel, struct sk_buff *skb) * enhanced mode fixes this issue and uses bytes 0-2 * and byte 5-7 of the UUID. */ - match_data_345 = skb->data + PTP_V2_UUID_OFFSET + 5; + match_data_345 = data + PTP_V2_UUID_OFFSET + 5; if (ptp->mode == MC_CMD_PTP_MODE_V2) { - match_data_012 = skb->data + PTP_V2_UUID_OFFSET + 2; + match_data_012 = data + PTP_V2_UUID_OFFSET + 2; } else { - match_data_012 = skb->data + PTP_V2_UUID_OFFSET + 0; + match_data_012 = data + PTP_V2_UUID_OFFSET + 0; BUG_ON(ptp->mode != MC_CMD_PTP_MODE_V2_ENHANCED); } } /* Does this packet require timestamping? */ - if (ntohs(*(__be16 *)&skb->data[PTP_DPORT_OFFSET]) == PTP_EVENT_PORT) { + if (ntohs(*(__be16 *)&data[PTP_DPORT_OFFSET]) == PTP_EVENT_PORT) { match->state = PTP_PACKET_STATE_UNMATCHED; /* We expect the sequence number to be in the same position in @@ -1440,8 +1429,8 @@ static bool efx_ptp_rx(struct efx_channel *channel, struct sk_buff *skb) (match_data_345[0] << 24)); match->words[1] = (match_data_345[1] | (match_data_345[2] << 8) | - (skb->data[PTP_V1_SEQUENCE_OFFSET + - PTP_V1_SEQUENCE_LENGTH - 1] << + (data[PTP_V1_SEQUENCE_OFFSET + + PTP_V1_SEQUENCE_LENGTH - 1] << 16)); } else { match->state = PTP_PACKET_STATE_MATCH_UNWANTED; @@ -1635,13 +1624,9 @@ static void ptp_event_rx(struct efx_nic *efx, struct efx_ptp_data *ptp) list_add_tail(&evt->link, &ptp->evt_list); queue_work(ptp->workwq, &ptp->work); - } else if (!ptp->evt_overflow) { - /* Log a warning message and set the event overflow flag. - * The message won't be logged again until the event queue - * becomes empty. - */ + } else if (net_ratelimit()) { + /* Log a rate-limited warning message. */ netif_err(efx, rx_err, efx->net_dev, "PTP event queue overflow\n"); - ptp->evt_overflow = true; } spin_unlock_bh(&ptp->evt_lock); } diff --git a/drivers/net/ethernet/sfc/selftest.c b/drivers/net/ethernet/sfc/selftest.c index 26641817a9c7..0fc5baef45b1 100644 --- a/drivers/net/ethernet/sfc/selftest.c +++ b/drivers/net/ethernet/sfc/selftest.c @@ -50,7 +50,7 @@ struct efx_loopback_payload { } __packed; /* Loopback test source MAC address */ -static const unsigned char payload_source[ETH_ALEN] = { +static const u8 payload_source[ETH_ALEN] __aligned(2) = { 0x00, 0x0f, 0x53, 0x1b, 0x1b, 0x1b, }; @@ -366,8 +366,8 @@ static void efx_iterate_state(struct efx_nic *efx) struct efx_loopback_payload *payload = &state->payload; /* Initialise the layerII header */ - memcpy(&payload->header.h_dest, net_dev->dev_addr, ETH_ALEN); - memcpy(&payload->header.h_source, &payload_source, ETH_ALEN); + ether_addr_copy((u8 *)&payload->header.h_dest, net_dev->dev_addr); + ether_addr_copy((u8 *)&payload->header.h_source, payload_source); payload->header.h_proto = htons(ETH_P_IP); /* saddr set later and used as incrementing count */ diff --git a/drivers/net/ethernet/sfc/siena_sriov.c b/drivers/net/ethernet/sfc/siena_sriov.c index 0c38f926871e..9a9205e77896 100644 --- a/drivers/net/ethernet/sfc/siena_sriov.c +++ b/drivers/net/ethernet/sfc/siena_sriov.c @@ -1095,7 +1095,7 @@ static void efx_sriov_peer_work(struct work_struct *data) /* Fill the remaining addresses */ list_for_each_entry(local_addr, &efx->local_addr_list, link) { - memcpy(peer->mac_addr, local_addr->addr, ETH_ALEN); + ether_addr_copy(peer->mac_addr, local_addr->addr); peer->tci = 0; ++peer; ++peer_count; @@ -1303,8 +1303,7 @@ int efx_sriov_init(struct efx_nic *efx) goto fail_vfs; rtnl_lock(); - memcpy(vfdi_status->peers[0].mac_addr, - net_dev->dev_addr, ETH_ALEN); + ether_addr_copy(vfdi_status->peers[0].mac_addr, net_dev->dev_addr); efx->vf_init_count = efx->vf_count; rtnl_unlock(); @@ -1452,8 +1451,8 @@ void efx_sriov_mac_address_changed(struct efx_nic *efx) if (!efx->vf_init_count) return; - memcpy(vfdi_status->peers[0].mac_addr, - efx->net_dev->dev_addr, ETH_ALEN); + ether_addr_copy(vfdi_status->peers[0].mac_addr, + efx->net_dev->dev_addr); queue_work(vfdi_workqueue, &efx->peer_work); } @@ -1570,7 +1569,7 @@ int efx_sriov_set_vf_mac(struct net_device *net_dev, int vf_i, u8 *mac) vf = efx->vf + vf_i; mutex_lock(&vf->status_lock); - memcpy(vf->addr.mac_addr, mac, ETH_ALEN); + ether_addr_copy(vf->addr.mac_addr, mac); __efx_sriov_update_vf_addr(vf); mutex_unlock(&vf->status_lock); @@ -1633,7 +1632,7 @@ int efx_sriov_get_vf_config(struct net_device *net_dev, int vf_i, vf = efx->vf + vf_i; ivi->vf = vf_i; - memcpy(ivi->mac, vf->addr.mac_addr, ETH_ALEN); + ether_addr_copy(ivi->mac, vf->addr.mac_addr); ivi->tx_rate = 0; tci = ntohs(vf->addr.tci); ivi->vlan = tci & VLAN_VID_MASK; diff --git a/drivers/net/ethernet/sfc/tx.c b/drivers/net/ethernet/sfc/tx.c index 75d11fa4eb0a..fa9475300411 100644 --- a/drivers/net/ethernet/sfc/tx.c +++ b/drivers/net/ethernet/sfc/tx.c @@ -787,15 +787,6 @@ void efx_remove_tx_queue(struct efx_tx_queue *tx_queue) * Requires TX checksum offload support. */ -/* Number of bytes inserted at the start of a TSO header buffer, - * similar to NET_IP_ALIGN. - */ -#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS -#define TSOH_OFFSET 0 -#else -#define TSOH_OFFSET NET_IP_ALIGN -#endif - #define PTR_DIFF(p1, p2) ((u8 *)(p1) - (u8 *)(p2)) /** @@ -882,13 +873,13 @@ static u8 *efx_tsoh_get_buffer(struct efx_tx_queue *tx_queue, EFX_BUG_ON_PARANOID(buffer->flags); EFX_BUG_ON_PARANOID(buffer->unmap_len); - if (likely(len <= TSOH_STD_SIZE - TSOH_OFFSET)) { + if (likely(len <= TSOH_STD_SIZE - NET_IP_ALIGN)) { unsigned index = (tx_queue->insert_count & tx_queue->ptr_mask) / 2; struct efx_buffer *page_buf = &tx_queue->tsoh_page[index / TSOH_PER_PAGE]; unsigned offset = - TSOH_STD_SIZE * (index % TSOH_PER_PAGE) + TSOH_OFFSET; + TSOH_STD_SIZE * (index % TSOH_PER_PAGE) + NET_IP_ALIGN; if (unlikely(!page_buf->addr) && efx_nic_alloc_buffer(tx_queue->efx, page_buf, PAGE_SIZE, @@ -901,10 +892,10 @@ static u8 *efx_tsoh_get_buffer(struct efx_tx_queue *tx_queue, } else { tx_queue->tso_long_headers++; - buffer->heap_buf = kmalloc(TSOH_OFFSET + len, GFP_ATOMIC); + buffer->heap_buf = kmalloc(NET_IP_ALIGN + len, GFP_ATOMIC); if (unlikely(!buffer->heap_buf)) return NULL; - result = (u8 *)buffer->heap_buf + TSOH_OFFSET; + result = (u8 *)buffer->heap_buf + NET_IP_ALIGN; buffer->flags = EFX_TX_BUF_CONT | EFX_TX_BUF_HEAP; } @@ -1011,7 +1002,7 @@ static void efx_enqueue_unwind(struct efx_tx_queue *tx_queue) static int tso_start(struct tso_state *st, struct efx_nic *efx, const struct sk_buff *skb) { - bool use_options = efx_nic_rev(efx) >= EFX_REV_HUNT_A0; + bool use_opt_desc = efx_nic_rev(efx) >= EFX_REV_HUNT_A0; struct device *dma_dev = &efx->pci_dev->dev; unsigned int header_len, in_len; dma_addr_t dma_addr; @@ -1037,7 +1028,7 @@ static int tso_start(struct tso_state *st, struct efx_nic *efx, st->out_len = skb->len - header_len; - if (!use_options) { + if (!use_opt_desc) { st->header_unmap_len = 0; if (likely(in_len == 0)) { |