Commit 86f968a0 authored by David S. Miller's avatar David S. Miller

Merge branch 'sfc-driver-for-EF100-family-NICs-part-1'

Edward Cree says:

====================
sfc: driver for EF100 family NICs, part 1

EF100 is a new NIC architecture under development at Xilinx, based
 partly on existing Solarflare technology.  As many of the hardware
 interfaces resemble EF10, support is implemented within the 'sfc'
 driver, which previous patch series "commonised" for this purpose.

In order to maintain bisectability while splitting into patches of a
 reasonable size, I had to do a certain amount of back-and-forth with
 stubs for things that the common code may try to call, mainly because
 we can't do them until we've set up MCDI, but we can't set up MCDI
 without probing the event queues, at which point a lot of the common
 machinery becomes reachable from event handlers.
Consequently, this first series doesn't get as far as actually sending
 and receiving packets.  I have a second series ready to follow it
 which implements the datapath (and a few other things like ethtool).

Changes from v4:
 * Fix build on CONFIG_RETPOLINE=n by using plain prototypes instead
   of INDIRECT_CALLABLE_DECLARE.

Changes from v3:
 * combine both drivers (sfc_ef100 and sfc) into a single module, to
   make non-modular builds work.  Patch #4 now adds a few indirections
   to support this; the ones in the RX and TX path use indirect-call-
   wrappers to minimise the performance impact.

Changes from v2:
 * remove MODULE_VERSION.
 * call efx_destroy_reset_workqueue() from ef100_exit_module().
 * correct uint32_ts to u32s.  While I was at it, I fixed a bunch of
   other style issues in the function-control-window code.
All in patch #4.

Changes from v1:
 * kernel test robot spotted a link error when sfc_ef100 was built
   without mdio.  It turns out the thing we were trying to link to
   was a bogus thing to do on anything but Falcon, so new patch #1
   removes it from this driver.
 * fix undeclared symbols in patch #4 by shuffling around prototypes
   and #includes and adding 'static' where appropriate.
 * fix uninitialised variable 'rc2' in patch #7.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 65ccbbda 1c748843
......@@ -17,7 +17,7 @@ config NET_VENDOR_SOLARFLARE
if NET_VENDOR_SOLARFLARE
config SFC
tristate "Solarflare SFC9000/SFC9100-family support"
tristate "Solarflare SFC9000/SFC9100/EF100-family support"
depends on PCI
select MDIO
select CRC32
......@@ -26,6 +26,9 @@ config SFC
This driver supports 10/40-gigabit Ethernet cards based on
the Solarflare SFC9000-family and SFC9100-family controllers.
It also supports 10/25/40/100-gigabit Ethernet cards based
on the Solarflare EF100 networking IP in Xilinx FPGAs.
To compile this driver as a module, choose M here. The module
will be called sfc.
config SFC_MTD
......
......@@ -4,7 +4,9 @@ sfc-y += efx.o efx_common.o efx_channels.o nic.o \
tx.o tx_common.o tx_tso.o rx.o rx_common.o \
selftest.o ethtool.o ethtool_common.o ptp.o \
mcdi.o mcdi_port.o mcdi_port_common.o \
mcdi_functions.o mcdi_filters.o mcdi_mon.o
mcdi_functions.o mcdi_filters.o mcdi_mon.o \
ef100.o ef100_nic.o ef100_netdev.o \
ef100_ethtool.o ef100_rx.o ef100_tx.o
sfc-$(CONFIG_SFC_MTD) += mtd.o
sfc-$(CONFIG_SFC_SRIOV) += sriov.o siena_sriov.o ef10_sriov.o
......
......@@ -6,6 +6,7 @@
#include "net_driver.h"
#include "rx_common.h"
#include "tx_common.h"
#include "ef10_regs.h"
#include "io.h"
#include "mcdi.h"
......@@ -3977,6 +3978,7 @@ const struct efx_nic_type efx_hunt_a0_vf_nic_type = {
.tx_remove = efx_mcdi_tx_remove,
.tx_write = efx_ef10_tx_write,
.tx_limit_len = efx_ef10_tx_limit_len,
.tx_enqueue = __efx_enqueue_skb,
.rx_push_rss_config = efx_mcdi_vf_rx_push_rss_config,
.rx_pull_rss_config = efx_mcdi_rx_pull_rss_config,
.rx_probe = efx_mcdi_rx_probe,
......@@ -3984,6 +3986,7 @@ const struct efx_nic_type efx_hunt_a0_vf_nic_type = {
.rx_remove = efx_mcdi_rx_remove,
.rx_write = efx_ef10_rx_write,
.rx_defer_refill = efx_ef10_rx_defer_refill,
.rx_packet = __efx_rx_packet,
.ev_probe = efx_mcdi_ev_probe,
.ev_init = efx_ef10_ev_init,
.ev_fini = efx_mcdi_ev_fini,
......@@ -4038,6 +4041,7 @@ const struct efx_nic_type efx_hunt_a0_vf_nic_type = {
.rx_hash_key_size = 40,
.check_caps = ef10_check_caps,
.print_additional_fwver = efx_ef10_print_additional_fwver,
.sensor_event = efx_mcdi_sensor_event,
};
const struct efx_nic_type efx_hunt_a0_nic_type = {
......@@ -4087,6 +4091,7 @@ const struct efx_nic_type efx_hunt_a0_nic_type = {
.tx_remove = efx_mcdi_tx_remove,
.tx_write = efx_ef10_tx_write,
.tx_limit_len = efx_ef10_tx_limit_len,
.tx_enqueue = __efx_enqueue_skb,
.rx_push_rss_config = efx_mcdi_pf_rx_push_rss_config,
.rx_pull_rss_config = efx_mcdi_rx_pull_rss_config,
.rx_push_rss_context_config = efx_mcdi_rx_push_rss_context_config,
......@@ -4097,6 +4102,7 @@ const struct efx_nic_type efx_hunt_a0_nic_type = {
.rx_remove = efx_mcdi_rx_remove,
.rx_write = efx_ef10_rx_write,
.rx_defer_refill = efx_ef10_rx_defer_refill,
.rx_packet = __efx_rx_packet,
.ev_probe = efx_mcdi_ev_probe,
.ev_init = efx_ef10_ev_init,
.ev_fini = efx_mcdi_ev_fini,
......@@ -4172,4 +4178,5 @@ const struct efx_nic_type efx_hunt_a0_nic_type = {
.rx_hash_key_size = 40,
.check_caps = ef10_check_caps,
.print_additional_fwver = efx_ef10_print_additional_fwver,
.sensor_event = efx_mcdi_sensor_event,
};
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0-only */
/****************************************************************************
* Driver for Solarflare network controllers and boards
* Copyright 2018 Solarflare Communications Inc.
* Copyright 2019-2020 Xilinx 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.
*/
extern struct pci_driver ef100_pci_driver;
// SPDX-License-Identifier: GPL-2.0-only
/****************************************************************************
* Driver for Solarflare network controllers and boards
* Copyright 2018 Solarflare Communications Inc.
* Copyright 2019-2020 Xilinx 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/module.h>
#include <linux/netdevice.h>
#include "net_driver.h"
#include "efx.h"
#include "mcdi_port_common.h"
#include "ethtool_common.h"
#include "ef100_ethtool.h"
#include "mcdi_functions.h"
/* Ethtool options available
*/
const struct ethtool_ops ef100_ethtool_ops = {
.get_drvinfo = efx_ethtool_get_drvinfo,
};
/* SPDX-License-Identifier: GPL-2.0-only */
/****************************************************************************
* Driver for Solarflare network controllers and boards
* Copyright 2018 Solarflare Communications Inc.
* Copyright 2019-2020 Xilinx 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.
*/
extern const struct ethtool_ops ef100_ethtool_ops;
// SPDX-License-Identifier: GPL-2.0-only
/****************************************************************************
* Driver for Solarflare network controllers and boards
* Copyright 2018 Solarflare Communications Inc.
* Copyright 2019-2020 Xilinx 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 "net_driver.h"
#include "mcdi_port_common.h"
#include "mcdi_functions.h"
#include "efx_common.h"
#include "efx_channels.h"
#include "tx_common.h"
#include "ef100_netdev.h"
#include "ef100_ethtool.h"
#include "efx_common.h"
#include "nic_common.h"
#include "ef100_nic.h"
#include "ef100_tx.h"
#include "ef100_regs.h"
#include "mcdi_filters.h"
#include "rx_common.h"
static void ef100_update_name(struct efx_nic *efx)
{
strcpy(efx->name, efx->net_dev->name);
}
static int ef100_alloc_vis(struct efx_nic *efx, unsigned int *allocated_vis)
{
/* EF100 uses a single TXQ per channel, as all checksum offloading
* is configured in the TX descriptor, and there is no TX Pacer for
* HIGHPRI queues.
*/
unsigned int tx_vis = efx->n_tx_channels + efx->n_extra_tx_channels;
unsigned int rx_vis = efx->n_rx_channels;
unsigned int min_vis, max_vis;
EFX_WARN_ON_PARANOID(efx->tx_queues_per_channel != 1);
tx_vis += efx->n_xdp_channels * efx->xdp_tx_per_channel;
max_vis = max(rx_vis, tx_vis);
/* Currently don't handle resource starvation and only accept
* our maximum needs and no less.
*/
min_vis = max_vis;
return efx_mcdi_alloc_vis(efx, min_vis, max_vis,
NULL, allocated_vis);
}
static int ef100_remap_bar(struct efx_nic *efx, int max_vis)
{
unsigned int uc_mem_map_size;
void __iomem *membase;
efx->max_vis = max_vis;
uc_mem_map_size = PAGE_ALIGN(max_vis * efx->vi_stride);
/* Extend the original UC mapping of the memory BAR */
membase = ioremap(efx->membase_phys, uc_mem_map_size);
if (!membase) {
netif_err(efx, probe, efx->net_dev,
"could not extend memory BAR to %x\n",
uc_mem_map_size);
return -ENOMEM;
}
iounmap(efx->membase);
efx->membase = membase;
return 0;
}
/* Context: process, rtnl_lock() held.
* Note that the kernel will ignore our return code; this method
* should really be a void.
*/
static int ef100_net_stop(struct net_device *net_dev)
{
struct efx_nic *efx = netdev_priv(net_dev);
netif_dbg(efx, ifdown, efx->net_dev, "closing on CPU %d\n",
raw_smp_processor_id());
netif_stop_queue(net_dev);
efx_stop_all(efx);
efx_disable_interrupts(efx);
efx_clear_interrupt_affinity(efx);
efx_nic_fini_interrupt(efx);
efx_fini_napi(efx);
efx_remove_channels(efx);
efx_mcdi_free_vis(efx);
efx_remove_interrupts(efx);
return 0;
}
/* Context: process, rtnl_lock() held. */
static int ef100_net_open(struct net_device *net_dev)
{
struct efx_nic *efx = netdev_priv(net_dev);
unsigned int allocated_vis;
int rc;
ef100_update_name(efx);
netif_dbg(efx, ifup, net_dev, "opening device on CPU %d\n",
raw_smp_processor_id());
rc = efx_check_disabled(efx);
if (rc)
goto fail;
rc = efx_probe_interrupts(efx);
if (rc)
goto fail;
rc = efx_set_channels(efx);
if (rc)
goto fail;
rc = efx_mcdi_free_vis(efx);
if (rc)
goto fail;
rc = ef100_alloc_vis(efx, &allocated_vis);
if (rc)
goto fail;
rc = efx_probe_channels(efx);
if (rc)
return rc;
rc = ef100_remap_bar(efx, allocated_vis);
if (rc)
goto fail;
efx_init_napi(efx);
rc = efx_nic_init_interrupt(efx);
if (rc)
goto fail;
efx_set_interrupt_affinity(efx);
rc = efx_enable_interrupts(efx);
if (rc)
goto fail;
/* in case the MC rebooted while we were stopped, consume the change
* to the warm reboot count
*/
(void) efx_mcdi_poll_reboot(efx);
efx_start_all(efx);
/* Link state detection is normally event-driven; we have
* to poll now because we could have missed a change
*/
mutex_lock(&efx->mac_lock);
if (efx_mcdi_phy_poll(efx))
efx_link_status_changed(efx);
mutex_unlock(&efx->mac_lock);
return 0;
fail:
ef100_net_stop(net_dev);
return rc;
}
/* Initiate a packet transmission. We use one channel per CPU
* (sharing when we have more CPUs than channels).
*
* Context: non-blocking.
* Note that returning anything other than NETDEV_TX_OK will cause the
* OS to free the skb.
*/
static netdev_tx_t ef100_hard_start_xmit(struct sk_buff *skb,
struct net_device *net_dev)
{
struct efx_nic *efx = netdev_priv(net_dev);
struct efx_tx_queue *tx_queue;
struct efx_channel *channel;
int rc;
channel = efx_get_tx_channel(efx, skb_get_queue_mapping(skb));
netif_vdbg(efx, tx_queued, efx->net_dev,
"%s len %d data %d channel %d\n", __func__,
skb->len, skb->data_len, channel->channel);
if (!efx->n_channels || !efx->n_tx_channels || !channel) {
netif_stop_queue(net_dev);
goto err;
}
tx_queue = &channel->tx_queue[0];
rc = ef100_enqueue_skb(tx_queue, skb);
if (rc == 0)
return NETDEV_TX_OK;
err:
net_dev->stats.tx_dropped++;
return NETDEV_TX_OK;
}
static const struct net_device_ops ef100_netdev_ops = {
.ndo_open = ef100_net_open,
.ndo_stop = ef100_net_stop,
.ndo_start_xmit = ef100_hard_start_xmit,
.ndo_get_phys_port_id = efx_get_phys_port_id,
.ndo_get_phys_port_name = efx_get_phys_port_name,
};
/* Netdev registration
*/
int ef100_netdev_event(struct notifier_block *this,
unsigned long event, void *ptr)
{
struct efx_nic *efx = container_of(this, struct efx_nic, netdev_notifier);
struct net_device *net_dev = netdev_notifier_info_to_dev(ptr);
if (netdev_priv(net_dev) == efx && event == NETDEV_CHANGENAME)
ef100_update_name(efx);
return NOTIFY_DONE;
}
int ef100_register_netdev(struct efx_nic *efx)
{
struct net_device *net_dev = efx->net_dev;
int rc;
net_dev->watchdog_timeo = 5 * HZ;
net_dev->irq = efx->pci_dev->irq;
net_dev->netdev_ops = &ef100_netdev_ops;
net_dev->min_mtu = EFX_MIN_MTU;
net_dev->max_mtu = EFX_MAX_MTU;
net_dev->ethtool_ops = &ef100_ethtool_ops;
rtnl_lock();
rc = dev_alloc_name(net_dev, net_dev->name);
if (rc < 0)
goto fail_locked;
ef100_update_name(efx);
rc = register_netdevice(net_dev);
if (rc)
goto fail_locked;
/* Always start with carrier off; PHY events will detect the link */
netif_carrier_off(net_dev);
efx->state = STATE_READY;
rtnl_unlock();
efx_init_mcdi_logging(efx);
return 0;
fail_locked:
rtnl_unlock();
netif_err(efx, drv, efx->net_dev, "could not register net dev\n");
return rc;
}
void ef100_unregister_netdev(struct efx_nic *efx)
{
if (efx_dev_registered(efx)) {
efx_fini_mcdi_logging(efx);
efx->state = STATE_UNINIT;
unregister_netdev(efx->net_dev);
}
}
/* SPDX-License-Identifier: GPL-2.0-only */
/****************************************************************************
* Driver for Solarflare network controllers and boards
* Copyright 2018 Solarflare Communications Inc.
* Copyright 2019-2020 Xilinx 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>
int ef100_netdev_event(struct notifier_block *this,
unsigned long event, void *ptr);
int ef100_register_netdev(struct efx_nic *efx);
void ef100_unregister_netdev(struct efx_nic *efx);
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0-only */
/****************************************************************************
* Driver for Solarflare network controllers and boards
* Copyright 2018 Solarflare Communications Inc.
* Copyright 2019-2020 Xilinx 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 "net_driver.h"
#include "nic_common.h"
extern const struct efx_nic_type ef100_pf_nic_type;
int ef100_probe_pf(struct efx_nic *efx);
void ef100_remove(struct efx_nic *efx);
struct ef100_nic_data {
struct efx_nic *efx;
struct efx_buffer mcdi_buf;
u32 datapath_caps;
u32 datapath_caps2;
u32 datapath_caps3;
u16 warm_boot_count;
u8 port_id[ETH_ALEN];
DECLARE_BITMAP(evq_phases, EFX_MAX_CHANNELS);
};
#define efx_ef100_has_cap(caps, flag) \
(!!((caps) & BIT_ULL(MC_CMD_GET_CAPABILITIES_V4_OUT_ ## flag ## _LBN)))
This diff is collapsed.
// SPDX-License-Identifier: GPL-2.0-only
/****************************************************************************
* Driver for Solarflare network controllers and boards
* Copyright 2005-2019 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 "net_driver.h"
#include "ef100_rx.h"
#include "rx_common.h"
#include "efx.h"
/* RX stubs */
void ef100_rx_write(struct efx_rx_queue *rx_queue)
{
}
void __ef100_rx_packet(struct efx_channel *channel)
{
/* Stub. No RX path yet. Discard the buffer. */
struct efx_rx_buffer *rx_buf = efx_rx_buffer(&channel->rx_queue,
channel->rx_pkt_index);
struct efx_rx_queue *rx_queue = efx_channel_get_rx_queue(channel);
efx_free_rx_buffers(rx_queue, rx_buf, 1);
channel->rx_pkt_n_frags = 0;
}
/* SPDX-License-Identifier: GPL-2.0-only */
/****************************************************************************
* Driver for Solarflare network controllers and boards
* Copyright 2019 Solarflare Communications Inc.
* Copyright 2019-2020 Xilinx 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.
*/
#ifndef EFX_EF100_RX_H
#define EFX_EF100_RX_H
#include "net_driver.h"
void ef100_rx_write(struct efx_rx_queue *rx_queue);
void __ef100_rx_packet(struct efx_channel *channel);
#endif
// SPDX-License-Identifier: GPL-2.0-only
/****************************************************************************
* Driver for Solarflare network controllers and boards
* Copyright 2018 Solarflare Communications Inc.
* Copyright 2019-2020 Xilinx 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 "net_driver.h"
#include "tx_common.h"
#include "nic_common.h"
#include "ef100_tx.h"
/* TX queue stubs */
int ef100_tx_probe(struct efx_tx_queue *tx_queue)
{
return 0;
}
void ef100_tx_init(struct efx_tx_queue *tx_queue)
{
/* must be the inverse of lookup in efx_get_tx_channel */
tx_queue->core_txq =
netdev_get_tx_queue(tx_queue->efx->net_dev,
tx_queue->channel->channel -
tx_queue->efx->tx_channel_offset);
}
void ef100_tx_write(struct efx_tx_queue *tx_queue)
{
}
/* Add a socket buffer to a TX queue
*
* You must hold netif_tx_lock() to call this function.
*
* Returns 0 on success, error code otherwise. In case of an error this
* function will free the SKB.
*/
int ef100_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
{
/* Stub. No TX path yet. */
struct efx_nic *efx = tx_queue->efx;
netif_stop_queue(efx->net_dev);
dev_kfree_skb_any(skb);
return -ENODEV;
}
/* SPDX-License-Identifier: GPL-2.0-only */
/****************************************************************************
* Driver for Solarflare network controllers and boards
* Copyright 2019 Solarflare Communications Inc.
* Copyright 2019-2020 Xilinx 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.
*/
#ifndef EFX_EF100_TX_H
#define EFX_EF100_TX_H
#include "net_driver.h"
int ef100_tx_probe(struct efx_tx_queue *tx_queue);
void ef100_tx_init(struct efx_tx_queue *tx_queue);
void ef100_tx_write(struct efx_tx_queue *tx_queue);
netdev_tx_t ef100_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb);
#endif
......@@ -25,6 +25,7 @@
#include "efx.h"
#include "efx_common.h"
#include "efx_channels.h"
#include "ef100.h"
#include "rx_common.h"
#include "tx_common.h"
#include "nic.h"
......@@ -1360,8 +1361,14 @@ static int __init efx_init_module(void)
if (rc < 0)
goto err_pci;
rc = pci_register_driver(&ef100_pci_driver);
if (rc < 0)
goto err_pci_ef100;
return 0;
err_pci_ef100:
pci_unregister_driver(&efx_pci_driver);
err_pci:
efx_destroy_reset_workqueue();
err_reset:
......@@ -1378,6 +1385,7 @@ static void __exit efx_exit_module(void)
{
printk(KERN_INFO "Solarflare NET driver unloading\n");
pci_unregister_driver(&ef100_pci_driver);
pci_unregister_driver(&efx_pci_driver);
efx_destroy_reset_workqueue();
#ifdef CONFIG_SFC_SRIOV
......
......@@ -8,7 +8,10 @@
#ifndef EFX_EFX_H
#define EFX_EFX_H
#include <linux/indirect_call_wrapper.h>
#include "net_driver.h"
#include "ef100_rx.h"
#include "ef100_tx.h"
#include "filter.h"
int efx_net_open(struct net_device *net_dev);
......@@ -18,13 +21,18 @@ int efx_net_stop(struct net_device *net_dev);
void efx_init_tx_queue_core_txq(struct efx_tx_queue *tx_queue);
netdev_tx_t efx_hard_start_xmit(struct sk_buff *skb,
struct net_device *net_dev);
netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb);
netdev_tx_t __efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb);
static inline netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
{
return INDIRECT_CALL_2(tx_queue->efx->type->tx_enqueue,
ef100_enqueue_skb, __efx_enqueue_skb,
tx_queue, skb);
}
void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index);
void efx_xmit_done_single(struct efx_tx_queue *tx_queue);
int efx_setup_tc(struct net_device *net_dev, enum tc_setup_type type,
void *type_data);
extern unsigned int efx_piobuf_size;
extern bool efx_separate_tx_channels;
/* RX */
void __efx_rx_packet(struct efx_channel *channel);
......@@ -33,7 +41,9 @@ void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index,
static inline void efx_rx_flush_packet(struct efx_channel *channel)
{
if (channel->rx_pkt_n_frags)
__efx_rx_packet(channel);
INDIRECT_CALL_2(channel->efx->type->rx_packet,
__ef100_rx_packet, __efx_rx_packet,
channel);
}
/* Maximum number of TCP segments we support for soft-TSO */
......
......@@ -814,14 +814,18 @@ int efx_reset_up(struct efx_nic *efx, enum reset_type method, bool ok)
*/
int efx_reset(struct efx_nic *efx, enum reset_type method)
{
int rc, rc2 = 0;
bool disabled;
int rc, rc2;
netif_info(efx, drv, efx->net_dev, "resetting (%s)\n",
RESET_TYPE(method));
efx_device_detach_sync(efx);
efx_reset_down(efx, method);
/* efx_reset_down() grabs locks that prevent recovery on EF100.
* EF100 reset is handled in the efx_nic_type callback below.
*/
if (efx_nic_rev(efx) != EFX_REV_EF100)
efx_reset_down(efx, method);
rc = efx->type->reset(efx, method);
if (rc) {
......@@ -849,7 +853,8 @@ int efx_reset(struct efx_nic *efx, enum reset_type method)
disabled = rc ||
method == RESET_TYPE_DISABLE ||
method == RESET_TYPE_RECOVER_OR_DISABLE;
rc2 = efx_reset_up(efx, method, !disabled);
if (efx_nic_rev(efx) != EFX_REV_EF100)
rc2 = efx_reset_up(efx, method, !disabled);
if (rc2) {
disabled = true;
if (!rc)
......
......@@ -221,8 +221,6 @@ static int efx_ethtool_get_ts_info(struct net_device *net_dev,
return 0;
}
const char *efx_driver_name = KBUILD_MODNAME;
const struct ethtool_ops efx_ethtool_ops = {
.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
ETHTOOL_COALESCE_USECS_IRQ |
......@@ -232,7 +230,6 @@ const struct ethtool_ops efx_ethtool_ops = {
.get_regs = efx_ethtool_get_regs,
.get_msglevel = efx_ethtool_get_msglevel,
.set_msglevel = efx_ethtool_set_msglevel,
.nway_reset = efx_ethtool_nway_reset,
.get_link = ethtool_op_get_link,
.get_coalesce = efx_ethtool_get_coalesce,
.set_coalesce = efx_ethtool_set_coalesce,
......
......@@ -104,7 +104,7 @@ void efx_ethtool_get_drvinfo(struct net_device *net_dev,
{
struct efx_nic *efx = netdev_priv(net_dev);
strlcpy(info->driver, efx_driver_name, sizeof(info->driver));
strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
strlcpy(info->version, EFX_DRIVER_VERSION, sizeof(info->version));
efx_mcdi_print_fwver(efx, info->fw_version,
sizeof(info->fw_version));
......@@ -173,14 +173,6 @@ void efx_ethtool_self_test(struct net_device *net_dev,
test->flags |= ETH_TEST_FL_FAILED;
}
/* Restart autonegotiation */
int efx_ethtool_nway_reset(struct net_device *net_dev)
{
struct efx_nic *efx = netdev_priv(net_dev);
return mdio45_nway_restart(&efx->mdio);
}
void efx_ethtool_get_pauseparam(struct net_device *net_dev,
struct ethtool_pauseparam *pause)
{
......
......@@ -11,15 +11,12 @@
#ifndef EFX_ETHTOOL_COMMON_H
#define EFX_ETHTOOL_COMMON_H
extern const char *efx_driver_name;
void efx_ethtool_get_drvinfo(struct net_device *net_dev,
struct ethtool_drvinfo *info);
u32 efx_ethtool_get_msglevel(struct net_device *net_dev);
void efx_ethtool_set_msglevel(struct net_device *net_dev, u32 msg_enable);
void efx_ethtool_self_test(struct net_device *net_dev,
struct ethtool_test *test, u64 *data);
int efx_ethtool_nway_reset(struct net_device *net_dev);
void efx_ethtool_get_pauseparam(struct net_device *net_dev,
struct ethtool_pauseparam *pause);
int efx_ethtool_set_pauseparam(struct net_device *net_dev,
......
......@@ -75,6 +75,11 @@
#endif
#endif
static inline u32 efx_reg(struct efx_nic *efx, unsigned int reg)
{
return efx->reg_base + reg;
}
#ifdef EFX_USE_QWORD_IO
static inline void _efx_writeq(struct efx_nic *efx, __le64 value,
unsigned int reg)
......@@ -217,8 +222,11 @@ static inline void efx_reado_table(struct efx_nic *efx, efx_oword_t *value,
efx_reado(efx, value, reg + index * sizeof(efx_oword_t));
}
/* default VI stride (step between per-VI registers) is 8K */
#define EFX_DEFAULT_VI_STRIDE 0x2000
/* default VI stride (step between per-VI registers) is 8K on EF10 and
* 64K on EF100
*/
#define EFX_DEFAULT_VI_STRIDE 0x2000
#define EF100_DEFAULT_VI_STRIDE 0x10000
/* Calculate offset to page-mapped register */
static inline unsigned int efx_paged_reg(struct efx_nic *efx, unsigned int page,
......@@ -265,7 +273,9 @@ _efx_writed_page(struct efx_nic *efx, const efx_dword_t *value,
#define efx_writed_page(efx, value, reg, page) \
_efx_writed_page(efx, value, \
reg + \
BUILD_BUG_ON_ZERO((reg) != 0x400 && \
BUILD_BUG_ON_ZERO((reg) != 0x180 && \
(reg) != 0x200 && \
(reg) != 0x400 && \
(reg) != 0x420 && \
(reg) != 0x830 && \
(reg) != 0x83c && \
......
......@@ -1337,7 +1337,7 @@ void efx_mcdi_process_event(struct efx_channel *channel,
efx_mcdi_process_link_change(efx, event);
break;
case MCDI_EVENT_CODE_SENSOREVT:
efx_mcdi_sensor_event(efx, event);
efx_sensor_event(efx, event);
break;
case MCDI_EVENT_CODE_SCHEDERR:
netif_dbg(efx, hw, efx->net_dev,
......
......@@ -327,10 +327,10 @@ void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev);
EFX_QWORD_FIELD(_ev, MCDI_EVENT_ ## _field)
#define MCDI_CAPABILITY(field) \
MC_CMD_GET_CAPABILITIES_V4_OUT_ ## field ## _LBN
MC_CMD_GET_CAPABILITIES_V8_OUT_ ## field ## _LBN
#define MCDI_CAPABILITY_OFST(field) \
MC_CMD_GET_CAPABILITIES_V4_OUT_ ## field ## _OFST
MC_CMD_GET_CAPABILITIES_V8_OUT_ ## field ## _OFST
#define efx_has_cap(efx, field) \
efx->type->check_caps(efx, \
......
......@@ -963,7 +963,9 @@ struct efx_async_filter_insertion {
* @vpd_sn: Serial number read from VPD
* @xdp_rxq_info_failed: Have any of the rx queues failed to initialise their
* xdp_rxq_info structures?
* @netdev_notifier: Netdevice notifier.
* @mem_bar: The BAR that is mapped into membase.
* @reg_base: Offset from the start of the bar to the function control window.
* @monitor_work: Hardware monitor workitem
* @biu_lock: BIU (bus interface unit) lock
* @last_irq_cpu: Last CPU to handle a possible test interrupt. This
......@@ -1141,7 +1143,10 @@ struct efx_nic {
char *vpd_sn;
bool xdp_rxq_info_failed;
struct notifier_block netdev_notifier;
unsigned int mem_bar;
u32 reg_base;
/* The following fields may be written more often */
......@@ -1244,6 +1249,7 @@ struct efx_udp_tunnel {
* @tx_init: Initialise TX queue on the NIC
* @tx_remove: Free resources for TX queue
* @tx_write: Write TX descriptors and doorbell
* @tx_enqueue: Add an SKB to TX queue
* @rx_push_rss_config: Write RSS hash key and indirection table to the NIC
* @rx_pull_rss_config: Read RSS hash key and indirection table back from the NIC
* @rx_push_rss_context_config: Write RSS hash key and indirection table for
......@@ -1255,6 +1261,7 @@ struct efx_udp_tunnel {
* @rx_remove: Free resources for RX queue
* @rx_write: Write RX descriptors and doorbell
* @rx_defer_refill: Generate a refill reminder event
* @rx_packet: Receive the queued RX buffer on a channel
* @ev_probe: Allocate resources for event queue
* @ev_init: Initialise event queue on the NIC
* @ev_fini: Deinitialise event queue on the NIC
......@@ -1299,6 +1306,7 @@ struct efx_udp_tunnel {
* @udp_tnl_push_ports: Push the list of UDP tunnel ports to the NIC if required.
* @udp_tnl_has_port: Check if a port has been added as UDP tunnel
* @print_additional_fwver: Dump NIC-specific additional FW version info
* @sensor_event: Handle a sensor event from MCDI
* @revision: Hardware architecture revision
* @txd_ptr_tbl_base: TX descriptor ring base address
* @rxd_ptr_tbl_base: RX descriptor ring base address
......@@ -1379,6 +1387,7 @@ struct efx_nic_type {
void (*tx_init)(struct efx_tx_queue *tx_queue);
void (*tx_remove)(struct efx_tx_queue *tx_queue);
void (*tx_write)(struct efx_tx_queue *tx_queue);
netdev_tx_t (*tx_enqueue)(struct efx_tx_queue *tx_queue, struct sk_buff *skb);
unsigned int (*tx_limit_len)(struct efx_tx_queue *tx_queue,
dma_addr_t dma_addr, unsigned int len);
int (*rx_push_rss_config)(struct efx_nic *efx, bool user,
......@@ -1396,6 +1405,7 @@ struct efx_nic_type {
void (*rx_remove)(struct efx_rx_queue *rx_queue);
void (*rx_write)(struct efx_rx_queue *rx_queue);
void (*rx_defer_refill)(struct efx_rx_queue *rx_queue);
void (*rx_packet)(struct efx_channel *channel);
int (*ev_probe)(struct efx_channel *channel);
int (*ev_init)(struct efx_channel *channel);
void (*ev_fini)(struct efx_channel *channel);
......@@ -1470,6 +1480,7 @@ struct efx_nic_type {
bool (*udp_tnl_has_port)(struct efx_nic *efx, __be16 port);
size_t (*print_additional_fwver)(struct efx_nic *efx, char *buf,
size_t len);
void (*sensor_event)(struct efx_nic *efx, efx_qword_t *ev);
int revision;
unsigned int txd_ptr_tbl_base;
......@@ -1521,6 +1532,13 @@ efx_get_channel(struct efx_nic *efx, unsigned index)
_channel = _channel->channel ? \
(_efx)->channel[_channel->channel - 1] : NULL)
static inline struct efx_channel *
efx_get_tx_channel(struct efx_nic *efx, unsigned int index)
{
EFX_WARN_ON_ONCE_PARANOID(index >= efx->n_tx_channels);
return efx->channel[efx->tx_channel_offset + index];
}
static inline struct efx_tx_queue *
efx_get_tx_queue(struct efx_nic *efx, unsigned index, unsigned type)
{
......
......@@ -225,6 +225,12 @@ void efx_nic_event_test_start(struct efx_channel *channel);
bool efx_nic_event_present(struct efx_channel *channel);
static inline void efx_sensor_event(struct efx_nic *efx, efx_qword_t *ev)
{
if (efx->type->sensor_event)
efx->type->sensor_event(efx, ev);
}
/* Some statistics are computed as A - B where A and B each increase
* linearly with some hardware counter(s) and the counters are read
* asynchronously. If the counters contributing to B are always read
......
......@@ -1018,6 +1018,7 @@ const struct efx_nic_type siena_a0_nic_type = {
.tx_remove = efx_farch_tx_remove,
.tx_write = efx_farch_tx_write,
.tx_limit_len = efx_farch_tx_limit_len,
.tx_enqueue = __efx_enqueue_skb,
.rx_push_rss_config = siena_rx_push_rss_config,
.rx_pull_rss_config = siena_rx_pull_rss_config,
.rx_probe = efx_farch_rx_probe,
......@@ -1025,6 +1026,7 @@ const struct efx_nic_type siena_a0_nic_type = {
.rx_remove = efx_farch_rx_remove,
.rx_write = efx_farch_rx_write,
.rx_defer_refill = efx_farch_rx_defer_refill,
.rx_packet = __efx_rx_packet,
.ev_probe = efx_farch_ev_probe,
.ev_init = efx_farch_ev_init,
.ev_fini = efx_farch_ev_fini,
......@@ -1096,4 +1098,5 @@ const struct efx_nic_type siena_a0_nic_type = {
1 << HWTSTAMP_FILTER_PTP_V2_L4_EVENT),
.rx_hash_key_size = 16,
.check_caps = siena_check_caps,
.sensor_event = efx_mcdi_sensor_event,
};
......@@ -284,7 +284,7 @@ static int efx_enqueue_skb_pio(struct efx_tx_queue *tx_queue,
* Returns NETDEV_TX_OK.
* You must hold netif_tx_lock() to call this function.
*/
netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
netdev_tx_t __efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
{
unsigned int old_insert_count = tx_queue->insert_count;
bool xmit_more = netdev_xmit_more();
......@@ -503,7 +503,7 @@ netdev_tx_t efx_hard_start_xmit(struct sk_buff *skb,
}
tx_queue = efx_get_tx_queue(efx, index, type);
return efx_enqueue_skb(tx_queue, skb);
return __efx_enqueue_skb(tx_queue, skb);
}
void efx_xmit_done_single(struct efx_tx_queue *tx_queue)
......
......@@ -40,4 +40,6 @@ int efx_tx_map_data(struct efx_tx_queue *tx_queue, struct sk_buff *skb,
unsigned int efx_tx_max_skb_descs(struct efx_nic *efx);
int efx_tx_tso_fallback(struct efx_tx_queue *tx_queue, struct sk_buff *skb);
extern bool efx_separate_tx_channels;
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment