summaryrefslogtreecommitdiffstats
path: root/drivers/net/sfc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/sfc')
-rw-r--r--drivers/net/sfc/Makefile7
-rw-r--r--drivers/net/sfc/efx.c647
-rw-r--r--drivers/net/sfc/efx.h55
-rw-r--r--drivers/net/sfc/ethtool.c344
-rw-r--r--drivers/net/sfc/falcon.c326
-rw-r--r--drivers/net/sfc/falcon_boards.c236
-rw-r--r--drivers/net/sfc/falcon_gmac.c230
-rw-r--r--drivers/net/sfc/falcon_xmac.c7
-rw-r--r--drivers/net/sfc/filter.c454
-rw-r--r--drivers/net/sfc/filter.h189
-rw-r--r--drivers/net/sfc/io.h37
-rw-r--r--drivers/net/sfc/mac.h2
-rw-r--r--drivers/net/sfc/mcdi.c102
-rw-r--r--drivers/net/sfc/mcdi.h2
-rw-r--r--drivers/net/sfc/mcdi_mac.c8
-rw-r--r--drivers/net/sfc/mcdi_phy.c44
-rw-r--r--drivers/net/sfc/mdio_10g.c69
-rw-r--r--drivers/net/sfc/mdio_10g.h3
-rw-r--r--drivers/net/sfc/mtd.c23
-rw-r--r--drivers/net/sfc/net_driver.h205
-rw-r--r--drivers/net/sfc/nic.c728
-rw-r--r--drivers/net/sfc/nic.h9
-rw-r--r--drivers/net/sfc/phy.h18
-rw-r--r--drivers/net/sfc/qt202x_phy.c42
-rw-r--r--drivers/net/sfc/regs.h14
-rw-r--r--drivers/net/sfc/rx.c506
-rw-r--r--drivers/net/sfc/selftest.c171
-rw-r--r--drivers/net/sfc/siena.c72
-rw-r--r--drivers/net/sfc/tenxpress.c432
-rw-r--r--drivers/net/sfc/tx.c115
-rw-r--r--drivers/net/sfc/txc43128_phy.c560
-rw-r--r--drivers/net/sfc/workarounds.h11
32 files changed, 3584 insertions, 2084 deletions
diff --git a/drivers/net/sfc/Makefile b/drivers/net/sfc/Makefile
index 1047b19c60a5..ab31c7124db1 100644
--- a/drivers/net/sfc/Makefile
+++ b/drivers/net/sfc/Makefile
@@ -1,7 +1,8 @@
-sfc-y += efx.o nic.o falcon.o siena.o tx.o rx.o \
- falcon_gmac.o falcon_xmac.o mcdi_mac.o \
+sfc-y += efx.o nic.o falcon.o siena.o tx.o rx.o filter.o \
+ falcon_xmac.o mcdi_mac.o \
selftest.o ethtool.o qt202x_phy.o mdio_10g.o \
- tenxpress.o falcon_boards.o mcdi.o mcdi_phy.o
+ tenxpress.o txc43128_phy.o falcon_boards.o \
+ mcdi.o mcdi_phy.o
sfc-$(CONFIG_SFC_MTD) += mtd.o
obj-$(CONFIG_SFC) += sfc.o
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
index 156460527231..05df20e47976 100644
--- a/drivers/net/sfc/efx.c
+++ b/drivers/net/sfc/efx.c
@@ -27,6 +27,7 @@
#include "nic.h"
#include "mcdi.h"
+#include "workarounds.h"
/**************************************************************************
*
@@ -67,14 +68,6 @@ const char *efx_loopback_mode_names[] = {
[LOOPBACK_PHYXS_WS] = "PHYXS_WS",
};
-/* Interrupt mode names (see INT_MODE())) */
-const unsigned int efx_interrupt_mode_max = EFX_INT_MODE_MAX;
-const char *efx_interrupt_mode_names[] = {
- [EFX_INT_MODE_MSIX] = "MSI-X",
- [EFX_INT_MODE_MSI] = "MSI",
- [EFX_INT_MODE_LEGACY] = "legacy",
-};
-
const unsigned int efx_reset_type_max = RESET_TYPE_MAX;
const char *efx_reset_type_names[] = {
[RESET_TYPE_INVISIBLE] = "INVISIBLE",
@@ -92,13 +85,6 @@ const char *efx_reset_type_names[] = {
#define EFX_MAX_MTU (9 * 1024)
-/* RX slow fill workqueue. If memory allocation fails in the fast path,
- * a work item is pushed onto this work queue to retry the allocation later,
- * to avoid the NIC being starved of RX buffers. Since this is a per cpu
- * workqueue, there is nothing to be gained in making it per NIC
- */
-static struct workqueue_struct *refill_workqueue;
-
/* Reset workqueue. If any NIC has a hardware failure then a reset will be
* queued onto this work queue. This is not a per-nic work queue, because
* efx_reset_work() acquires the rtnl lock, so resets are naturally serialised.
@@ -120,7 +106,7 @@ static struct workqueue_struct *reset_workqueue;
* This is only used in MSI-X interrupt mode
*/
static unsigned int separate_tx_channels;
-module_param(separate_tx_channels, uint, 0644);
+module_param(separate_tx_channels, uint, 0444);
MODULE_PARM_DESC(separate_tx_channels,
"Use separate channels for TX and RX");
@@ -130,10 +116,11 @@ MODULE_PARM_DESC(separate_tx_channels,
static int napi_weight = 64;
/* This is the time (in jiffies) between invocations of the hardware
- * monitor, which checks for known hardware bugs and resets the
- * hardware and driver as necessary.
+ * monitor. On Falcon-based NICs, this will:
+ * - Check the on-board hardware monitor;
+ * - Poll the link state and reconfigure the hardware as necessary.
*/
-unsigned int efx_monitor_interval = 1 * HZ;
+static unsigned int efx_monitor_interval = 1 * HZ;
/* This controls whether or not the driver will initialise devices
* with invalid MAC addresses stored in the EEPROM or flash. If true,
@@ -195,15 +182,25 @@ module_param(irq_adapt_high_thresh, uint, 0644);
MODULE_PARM_DESC(irq_adapt_high_thresh,
"Threshold score for increasing IRQ moderation");
+static unsigned debug = (NETIF_MSG_DRV | NETIF_MSG_PROBE |
+ NETIF_MSG_LINK | NETIF_MSG_IFDOWN |
+ NETIF_MSG_IFUP | NETIF_MSG_RX_ERR |
+ NETIF_MSG_TX_ERR | NETIF_MSG_HW);
+module_param(debug, uint, 0);
+MODULE_PARM_DESC(debug, "Bitmapped debugging message enable value");
+
/**************************************************************************
*
* Utility functions and prototypes
*
*************************************************************************/
-static void efx_remove_channel(struct efx_channel *channel);
+
+static void efx_remove_channels(struct efx_nic *efx);
static void efx_remove_port(struct efx_nic *efx);
static void efx_fini_napi(struct efx_nic *efx);
-static void efx_fini_channels(struct efx_nic *efx);
+static void efx_fini_struct(struct efx_nic *efx);
+static void efx_start_all(struct efx_nic *efx);
+static void efx_stop_all(struct efx_nic *efx);
#define EFX_ASSERT_RESET_SERIALISED(efx) \
do { \
@@ -247,7 +244,7 @@ static int efx_process_channel(struct efx_channel *channel, int budget)
efx_rx_strategy(channel);
- efx_fast_push_rx_descriptors(&efx->rx_queue[channel->channel]);
+ efx_fast_push_rx_descriptors(efx_channel_get_rx_queue(channel));
return spent;
}
@@ -278,16 +275,16 @@ static int efx_poll(struct napi_struct *napi, int budget)
{
struct efx_channel *channel =
container_of(napi, struct efx_channel, napi_str);
+ struct efx_nic *efx = channel->efx;
int spent;
- EFX_TRACE(channel->efx, "channel %d NAPI poll executing on CPU %d\n",
- channel->channel, raw_smp_processor_id());
+ netif_vdbg(efx, intr, efx->net_dev,
+ "channel %d NAPI poll executing on CPU %d\n",
+ channel->channel, raw_smp_processor_id());
spent = efx_process_channel(channel, budget);
if (spent < budget) {
- struct efx_nic *efx = channel->efx;
-
if (channel->channel < efx->n_rx_channels &&
efx->irq_rx_adaptive &&
unlikely(++channel->irq_count == 1000)) {
@@ -333,6 +330,7 @@ void efx_process_channel_now(struct efx_channel *channel)
{
struct efx_nic *efx = channel->efx;
+ BUG_ON(channel->channel >= efx->n_channels);
BUG_ON(!channel->enabled);
/* Disable interrupts and wait for ISRs to complete */
@@ -346,7 +344,7 @@ void efx_process_channel_now(struct efx_channel *channel)
napi_disable(&channel->napi_str);
/* Poll the channel */
- efx_process_channel(channel, EFX_EVQ_SIZE);
+ efx_process_channel(channel, channel->eventq_mask + 1);
/* Ack the eventq. This may cause an interrupt to be generated
* when they are reenabled */
@@ -363,7 +361,17 @@ void efx_process_channel_now(struct efx_channel *channel)
*/
static int efx_probe_eventq(struct efx_channel *channel)
{
- EFX_LOG(channel->efx, "chan %d create event queue\n", channel->channel);
+ struct efx_nic *efx = channel->efx;
+ unsigned long entries;
+
+ netif_dbg(channel->efx, probe, channel->efx->net_dev,
+ "chan %d create event queue\n", channel->channel);
+
+ /* Build an event queue with room for one event per tx and rx buffer,
+ * plus some extra for link state events and MCDI completions. */
+ entries = roundup_pow_of_two(efx->rxq_entries + efx->txq_entries + 128);
+ EFX_BUG_ON_PARANOID(entries > EFX_MAX_EVQ_SIZE);
+ channel->eventq_mask = max(entries, EFX_MIN_EVQ_SIZE) - 1;
return efx_nic_probe_eventq(channel);
}
@@ -371,7 +379,8 @@ static int efx_probe_eventq(struct efx_channel *channel)
/* Prepare channel's event queue */
static void efx_init_eventq(struct efx_channel *channel)
{
- EFX_LOG(channel->efx, "chan %d init event queue\n", channel->channel);
+ netif_dbg(channel->efx, drv, channel->efx->net_dev,
+ "chan %d init event queue\n", channel->channel);
channel->eventq_read_ptr = 0;
@@ -380,14 +389,16 @@ static void efx_init_eventq(struct efx_channel *channel)
static void efx_fini_eventq(struct efx_channel *channel)
{
- EFX_LOG(channel->efx, "chan %d fini event queue\n", channel->channel);
+ netif_dbg(channel->efx, drv, channel->efx->net_dev,
+ "chan %d fini event queue\n", channel->channel);
efx_nic_fini_eventq(channel);
}
static void efx_remove_eventq(struct efx_channel *channel)
{
- EFX_LOG(channel->efx, "chan %d remove event queue\n", channel->channel);
+ netif_dbg(channel->efx, drv, channel->efx->net_dev,
+ "chan %d remove event queue\n", channel->channel);
efx_nic_remove_eventq(channel);
}
@@ -398,13 +409,71 @@ static void efx_remove_eventq(struct efx_channel *channel)
*
*************************************************************************/
+/* Allocate and initialise a channel structure, optionally copying
+ * parameters (but not resources) from an old channel structure. */
+static struct efx_channel *
+efx_alloc_channel(struct efx_nic *efx, int i, struct efx_channel *old_channel)
+{
+ struct efx_channel *channel;
+ struct efx_rx_queue *rx_queue;
+ struct efx_tx_queue *tx_queue;
+ int j;
+
+ if (old_channel) {
+ channel = kmalloc(sizeof(*channel), GFP_KERNEL);
+ if (!channel)
+ return NULL;
+
+ *channel = *old_channel;
+
+ memset(&channel->eventq, 0, sizeof(channel->eventq));
+
+ rx_queue = &channel->rx_queue;
+ rx_queue->buffer = NULL;
+ memset(&rx_queue->rxd, 0, sizeof(rx_queue->rxd));
+
+ for (j = 0; j < EFX_TXQ_TYPES; j++) {
+ tx_queue = &channel->tx_queue[j];
+ if (tx_queue->channel)
+ tx_queue->channel = channel;
+ tx_queue->buffer = NULL;
+ memset(&tx_queue->txd, 0, sizeof(tx_queue->txd));
+ }
+ } else {
+ channel = kzalloc(sizeof(*channel), GFP_KERNEL);
+ if (!channel)
+ return NULL;
+
+ channel->efx = efx;
+ channel->channel = i;
+
+ for (j = 0; j < EFX_TXQ_TYPES; j++) {
+ tx_queue = &channel->tx_queue[j];
+ tx_queue->efx = efx;
+ tx_queue->queue = i * EFX_TXQ_TYPES + j;
+ tx_queue->channel = channel;
+ }
+ }
+
+ spin_lock_init(&channel->tx_stop_lock);
+ atomic_set(&channel->tx_stop_count, 1);
+
+ rx_queue = &channel->rx_queue;
+ rx_queue->efx = efx;
+ setup_timer(&rx_queue->slow_fill, efx_rx_slow_fill,
+ (unsigned long)rx_queue);
+
+ return channel;
+}
+
static int efx_probe_channel(struct efx_channel *channel)
{
struct efx_tx_queue *tx_queue;
struct efx_rx_queue *rx_queue;
int rc;
- EFX_LOG(channel->efx, "creating channel %d\n", channel->channel);
+ netif_dbg(channel->efx, probe, channel->efx->net_dev,
+ "creating channel %d\n", channel->channel);
rc = efx_probe_eventq(channel);
if (rc)
@@ -453,11 +522,38 @@ static void efx_set_channel_names(struct efx_nic *efx)
number -= efx->n_rx_channels;
}
}
- snprintf(channel->name, sizeof(channel->name),
+ snprintf(efx->channel_name[channel->channel],
+ sizeof(efx->channel_name[0]),
"%s%s-%d", efx->name, type, number);
}
}
+static int efx_probe_channels(struct efx_nic *efx)
+{
+ struct efx_channel *channel;
+ int rc;
+
+ /* Restart special buffer allocation */
+ efx->next_buffer_table = 0;
+
+ efx_for_each_channel(channel, efx) {
+ rc = efx_probe_channel(channel);
+ if (rc) {
+ netif_err(efx, probe, efx->net_dev,
+ "failed to create channel %d\n",
+ channel->channel);
+ goto fail;
+ }
+ }
+ efx_set_channel_names(efx);
+
+ return 0;
+
+fail:
+ efx_remove_channels(efx);
+ return rc;
+}
+
/* Channels are shutdown and reinitialised whilst the NIC is running
* to propagate configuration changes (mtu, checksum offload), or
* to clear hardware error conditions
@@ -474,12 +570,15 @@ static void efx_init_channels(struct efx_nic *efx)
*/
efx->rx_buffer_len = (max(EFX_PAGE_IP_ALIGN, NET_IP_ALIGN) +
EFX_MAX_FRAME_LEN(efx->net_dev->mtu) +
+ efx->type->rx_buffer_hash_size +
efx->type->rx_buffer_padding);
- efx->rx_buffer_order = get_order(efx->rx_buffer_len);
+ efx->rx_buffer_order = get_order(efx->rx_buffer_len +
+ sizeof(struct efx_rx_page_state));
/* Initialise the channels */
efx_for_each_channel(channel, efx) {
- EFX_LOG(channel->efx, "init chan %d\n", channel->channel);
+ netif_dbg(channel->efx, drv, channel->efx->net_dev,
+ "init chan %d\n", channel->channel);
efx_init_eventq(channel);
@@ -506,7 +605,8 @@ static void efx_start_channel(struct efx_channel *channel)
{
struct efx_rx_queue *rx_queue;
- EFX_LOG(channel->efx, "starting chan %d\n", channel->channel);
+ netif_dbg(channel->efx, ifup, channel->efx->net_dev,
+ "starting chan %d\n", channel->channel);
/* The interrupt handler for this channel may set work_pending
* as soon as we enable it. Make sure it's cleared before
@@ -515,11 +615,11 @@ static void efx_start_channel(struct efx_channel *channel)
channel->enabled = true;
smp_wmb();
- napi_enable(&channel->napi_str);
-
- /* Load up RX descriptors */
+ /* Fill the queues before enabling NAPI */
efx_for_each_channel_rx_queue(rx_queue, channel)
efx_fast_push_rx_descriptors(rx_queue);
+
+ napi_enable(&channel->napi_str);
}
/* This disables event queue processing and packet transmission.
@@ -528,21 +628,14 @@ static void efx_start_channel(struct efx_channel *channel)
*/
static void efx_stop_channel(struct efx_channel *channel)
{
- struct efx_rx_queue *rx_queue;
-
if (!channel->enabled)
return;
- EFX_LOG(channel->efx, "stop chan %d\n", channel->channel);
+ netif_dbg(channel->efx, ifdown, channel->efx->net_dev,
+ "stop chan %d\n", channel->channel);
channel->enabled = false;
napi_disable(&channel->napi_str);
-
- /* Ensure that any worker threads have exited or will be no-ops */
- efx_for_each_channel_rx_queue(rx_queue, channel) {
- spin_lock_bh(&rx_queue->add_lock);
- spin_unlock_bh(&rx_queue->add_lock);
- }
}
static void efx_fini_channels(struct efx_nic *efx)
@@ -556,13 +649,24 @@ static void efx_fini_channels(struct efx_nic *efx)
BUG_ON(efx->port_enabled);
rc = efx_nic_flush_queues(efx);
- if (rc)
- EFX_ERR(efx, "failed to flush queues\n");
- else
- EFX_LOG(efx, "successfully flushed all queues\n");
+ if (rc && EFX_WORKAROUND_7803(efx)) {
+ /* Schedule a reset to recover from the flush failure. The
+ * descriptor caches reference memory we're about to free,
+ * but falcon_reconfigure_mac_wrapper() won't reconnect
+ * the MACs because of the pending reset. */
+ netif_err(efx, drv, efx->net_dev,
+ "Resetting to recover from flush failure\n");
+ efx_schedule_reset(efx, RESET_TYPE_ALL);
+ } else if (rc) {
+ netif_err(efx, drv, efx->net_dev, "failed to flush queues\n");
+ } else {
+ netif_dbg(efx, drv, efx->net_dev,
+ "successfully flushed all queues\n");
+ }
efx_for_each_channel(channel, efx) {
- EFX_LOG(channel->efx, "shut down chan %d\n", channel->channel);
+ netif_dbg(channel->efx, drv, channel->efx->net_dev,
+ "shut down chan %d\n", channel->channel);
efx_for_each_channel_rx_queue(rx_queue, channel)
efx_fini_rx_queue(rx_queue);
@@ -577,7 +681,8 @@ static void efx_remove_channel(struct efx_channel *channel)
struct efx_tx_queue *tx_queue;
struct efx_rx_queue *rx_queue;
- EFX_LOG(channel->efx, "destroy chan %d\n", channel->channel);
+ netif_dbg(channel->efx, drv, channel->efx->net_dev,
+ "destroy chan %d\n", channel->channel);
efx_for_each_channel_rx_queue(rx_queue, channel)
efx_remove_rx_queue(rx_queue);
@@ -586,9 +691,78 @@ static void efx_remove_channel(struct efx_channel *channel)
efx_remove_eventq(channel);
}
-void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue, int delay)
+static void efx_remove_channels(struct efx_nic *efx)
{
- queue_delayed_work(refill_workqueue, &rx_queue->work, delay);
+ struct efx_channel *channel;
+
+ efx_for_each_channel(channel, efx)
+ efx_remove_channel(channel);
+}
+
+int
+efx_realloc_channels(struct efx_nic *efx, u32 rxq_entries, u32 txq_entries)
+{
+ struct efx_channel *other_channel[EFX_MAX_CHANNELS], *channel;
+ u32 old_rxq_entries, old_txq_entries;
+ unsigned i;
+ int rc;
+
+ efx_stop_all(efx);
+ efx_fini_channels(efx);
+
+ /* Clone channels */
+ memset(other_channel, 0, sizeof(other_channel));
+ for (i = 0; i < efx->n_channels; i++) {
+ channel = efx_alloc_channel(efx, i, efx->channel[i]);
+ if (!channel) {
+ rc = -ENOMEM;
+ goto out;
+ }
+ other_channel[i] = channel;
+ }
+
+ /* Swap entry counts and channel pointers */
+ old_rxq_entries = efx->rxq_entries;
+ old_txq_entries = efx->txq_entries;
+ efx->rxq_entries = rxq_entries;
+ efx->txq_entries = txq_entries;
+ for (i = 0; i < efx->n_channels; i++) {
+ channel = efx->channel[i];
+ efx->channel[i] = other_channel[i];
+ other_channel[i] = channel;
+ }
+
+ rc = efx_probe_channels(efx);
+ if (rc)
+ goto rollback;
+
+ /* Destroy old channels */
+ for (i = 0; i < efx->n_channels; i++)
+ efx_remove_channel(other_channel[i]);
+out:
+ /* Free unused channel structures */
+ for (i = 0; i < efx->n_channels; i++)
+ kfree(other_channel[i]);
+
+ efx_init_channels(efx);
+ efx_start_all(efx);
+ return rc;
+
+rollback:
+ /* Swap back */
+ efx->rxq_entries = old_rxq_entries;
+ efx->txq_entries = old_txq_entries;
+ for (i = 0; i < efx->n_channels; i++) {
+ channel = efx->channel[i];
+ efx->channel[i] = other_channel[i];
+ other_channel[i] = channel;
+ }
+ goto out;
+}
+
+void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue)
+{
+ mod_timer(&rx_queue->slow_fill, jiffies + msecs_to_jiffies(100));
}
/**************************************************************************
@@ -628,12 +802,13 @@ void efx_link_status_changed(struct efx_nic *efx)
/* Status message for kernel log */
if (link_state->up) {
- EFX_INFO(efx, "link up at %uMbps %s-duplex (MTU %d)%s\n",
- link_state->speed, link_state->fd ? "full" : "half",
- efx->net_dev->mtu,
- (efx->promiscuous ? " [PROMISC]" : ""));
+ netif_info(efx, link, efx->net_dev,
+ "link up at %uMbps %s-duplex (MTU %d)%s\n",
+ link_state->speed, link_state->fd ? "full" : "half",
+ efx->net_dev->mtu,
+ (efx->promiscuous ? " [PROMISC]" : ""));
} else {
- EFX_INFO(efx, "link down\n");
+ netif_info(efx, link, efx->net_dev, "link down\n");
}
}
@@ -737,7 +912,7 @@ static int efx_probe_port(struct efx_nic *efx)
{
int rc;
- EFX_LOG(efx, "create port\n");
+ netif_dbg(efx, probe, efx->net_dev, "create port\n");
if (phy_flash_cfg)
efx->phy_mode = PHY_MODE_SPECIAL;
@@ -745,27 +920,28 @@ static int efx_probe_port(struct efx_nic *efx)
/* Connect up MAC/PHY operations table */
rc = efx->type->probe_port(efx);
if (rc)
- goto err;
+ return rc;
/* Sanity check MAC address */
if (is_valid_ether_addr(efx->mac_address)) {
memcpy(efx->net_dev->dev_addr, efx->mac_address, ETH_ALEN);
} else {
- EFX_ERR(efx, "invalid MAC address %pM\n",
- efx->mac_address);
+ netif_err(efx, probe, efx->net_dev, "invalid MAC address %pM\n",
+ efx->mac_address);
if (!allow_bad_hwaddr) {
rc = -EINVAL;
goto err;
}
random_ether_addr(efx->net_dev->dev_addr);
- EFX_INFO(efx, "using locally-generated MAC %pM\n",
- efx->net_dev->dev_addr);
+ netif_info(efx, probe, efx->net_dev,
+ "using locally-generated MAC %pM\n",
+ efx->net_dev->dev_addr);
}
return 0;
err:
- efx_remove_port(efx);
+ efx->type->remove_port(efx);
return rc;
}
@@ -773,7 +949,7 @@ static int efx_init_port(struct efx_nic *efx)
{
int rc;
- EFX_LOG(efx, "init port\n");
+ netif_dbg(efx, drv, efx->net_dev, "init port\n");
mutex_lock(&efx->mac_lock);
@@ -804,7 +980,7 @@ fail1:
static void efx_start_port(struct efx_nic *efx)
{
- EFX_LOG(efx, "start port\n");
+ netif_dbg(efx, ifup, efx->net_dev, "start port\n");
BUG_ON(efx->port_enabled);
mutex_lock(&efx->mac_lock);
@@ -821,7 +997,7 @@ static void efx_start_port(struct efx_nic *efx)
/* Prevent efx_mac_work() and efx_monitor() from working */
static void efx_stop_port(struct efx_nic *efx)
{
- EFX_LOG(efx, "stop port\n");
+ netif_dbg(efx, ifdown, efx->net_dev, "stop port\n");
mutex_lock(&efx->mac_lock);
efx->port_enabled = false;
@@ -836,7 +1012,7 @@ static void efx_stop_port(struct efx_nic *efx)
static void efx_fini_port(struct efx_nic *efx)
{
- EFX_LOG(efx, "shut down port\n");
+ netif_dbg(efx, drv, efx->net_dev, "shut down port\n");
if (!efx->port_initialized)
return;
@@ -850,7 +1026,7 @@ static void efx_fini_port(struct efx_nic *efx)
static void efx_remove_port(struct efx_nic *efx)
{
- EFX_LOG(efx, "destroying port\n");
+ netif_dbg(efx, drv, efx->net_dev, "destroying port\n");
efx->type->remove_port(efx);
}
@@ -868,11 +1044,12 @@ static int efx_init_io(struct efx_nic *efx)
dma_addr_t dma_mask = efx->type->max_dma_mask;
int rc;
- EFX_LOG(efx, "initialising I/O\n");
+ netif_dbg(efx, probe, efx->net_dev, "initialising I/O\n");
rc = pci_enable_device(pci_dev);
if (rc) {
- EFX_ERR(efx, "failed to enable PCI device\n");
+ netif_err(efx, probe, efx->net_dev,
+ "failed to enable PCI device\n");
goto fail1;
}
@@ -890,39 +1067,45 @@ static int efx_init_io(struct efx_nic *efx)
dma_mask >>= 1;
}
if (rc) {
- EFX_ERR(efx, "could not find a suitable DMA mask\n");
+ netif_err(efx, probe, efx->net_dev,
+ "could not find a suitable DMA mask\n");
goto fail2;
}
- EFX_LOG(efx, "using DMA mask %llx\n", (unsigned long long) dma_mask);
+ netif_dbg(efx, probe, efx->net_dev,
+ "using DMA mask %llx\n", (unsigned long long) dma_mask);
rc = pci_set_consistent_dma_mask(pci_dev, dma_mask);
if (rc) {
/* pci_set_consistent_dma_mask() is not *allowed* to
* fail with a mask that pci_set_dma_mask() accepted,
* but just in case...
*/
- EFX_ERR(efx, "failed to set consistent DMA mask\n");
+ netif_err(efx, probe, efx->net_dev,
+ "failed to set consistent DMA mask\n");
goto fail2;
}
efx->membase_phys = pci_resource_start(efx->pci_dev, EFX_MEM_BAR);
rc = pci_request_region(pci_dev, EFX_MEM_BAR, "sfc");
if (rc) {
- EFX_ERR(efx, "request for memory BAR failed\n");
+ netif_err(efx, probe, efx->net_dev,
+ "request for memory BAR failed\n");
rc = -EIO;
goto fail3;
}
efx->membase = ioremap_nocache(efx->membase_phys,
efx->type->mem_map_size);
if (!efx->membase) {
- EFX_ERR(efx, "could not map memory BAR at %llx+%x\n",
- (unsigned long long)efx->membase_phys,
- efx->type->mem_map_size);
+ netif_err(efx, probe, efx->net_dev,
+ "could not map memory BAR at %llx+%x\n",
+ (unsigned long long)efx->membase_phys,
+ efx->type->mem_map_size);
rc = -ENOMEM;
goto fail4;
}
- EFX_LOG(efx, "memory BAR at %llx+%x (virtual %p)\n",
- (unsigned long long)efx->membase_phys,
- efx->type->mem_map_size, efx->membase);
+ netif_dbg(efx, probe, efx->net_dev,
+ "memory BAR at %llx+%x (virtual %p)\n",
+ (unsigned long long)efx->membase_phys,
+ efx->type->mem_map_size, efx->membase);
return 0;
@@ -938,7 +1121,7 @@ static int efx_init_io(struct efx_nic *efx)
static void efx_fini_io(struct efx_nic *efx)
{
- EFX_LOG(efx, "shutting down I/O\n");
+ netif_dbg(efx, drv, efx->net_dev, "shutting down I/O\n");
if (efx->membase) {
iounmap(efx->membase);
@@ -1002,9 +1185,11 @@ static void efx_probe_interrupts(struct efx_nic *efx)
xentries[i].entry = i;
rc = pci_enable_msix(efx->pci_dev, xentries, n_channels);
if (rc > 0) {
- EFX_ERR(efx, "WARNING: Insufficient MSI-X vectors"
- " available (%d < %d).\n", rc, n_channels);
- EFX_ERR(efx, "WARNING: Performance may be reduced.\n");
+ netif_err(efx, drv, efx->net_dev,
+ "WARNING: Insufficient MSI-X vectors"
+ " available (%d < %d).\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,
@@ -1024,11 +1209,13 @@ static void efx_probe_interrupts(struct efx_nic *efx)
efx->n_rx_channels = efx->n_channels;
}
for (i = 0; i < n_channels; i++)
- efx->channel[i].irq = xentries[i].vector;
+ efx_get_channel(efx, i)->irq =
+ xentries[i].vector;
} else {
/* Fall back to single channel MSI */
efx->interrupt_mode = EFX_INT_MODE_MSI;
- EFX_ERR(efx, "could not enable MSI-X\n");
+ netif_err(efx, drv, efx->net_dev,
+ "could not enable MSI-X\n");
}
}
@@ -1039,9 +1226,10 @@ static void efx_probe_interrupts(struct efx_nic *efx)
efx->n_tx_channels = 1;
rc = pci_enable_msi(efx->pci_dev);
if (rc == 0) {
- efx->channel[0].irq = efx->pci_dev->irq;
+ efx_get_channel(efx, 0)->irq = efx->pci_dev->irq;
} else {
- EFX_ERR(efx, "could not enable MSI\n");
+ netif_err(efx, drv, efx->net_dev,
+ "could not enable MSI\n");
efx->interrupt_mode = EFX_INT_MODE_LEGACY;
}
}
@@ -1069,33 +1257,40 @@ static void efx_remove_interrupts(struct efx_nic *efx)
efx->legacy_irq = 0;
}
+struct efx_tx_queue *
+efx_get_tx_queue(struct efx_nic *efx, unsigned index, unsigned type)
+{
+ unsigned tx_channel_offset =
+ separate_tx_channels ? efx->n_channels - efx->n_tx_channels : 0;
+ EFX_BUG_ON_PARANOID(index >= efx->n_tx_channels ||
+ type >= EFX_TXQ_TYPES);
+ return &efx->channel[tx_channel_offset + index]->tx_queue[type];
+}
+
static void efx_set_channels(struct efx_nic *efx)
{
struct efx_channel *channel;
struct efx_tx_queue *tx_queue;
- struct efx_rx_queue *rx_queue;
unsigned tx_channel_offset =
separate_tx_channels ? efx->n_channels - efx->n_tx_channels : 0;
+ /* Channel pointers were set in efx_init_struct() but we now
+ * need to clear them for TX queues in any RX-only channels. */
efx_for_each_channel(channel, efx) {
- if (channel->channel - tx_channel_offset < efx->n_tx_channels) {
- channel->tx_queue = &efx->tx_queue[
- (channel->channel - tx_channel_offset) *
- EFX_TXQ_TYPES];
+ if (channel->channel - tx_channel_offset >=
+ efx->n_tx_channels) {
efx_for_each_channel_tx_queue(tx_queue, channel)
- tx_queue->channel = channel;
+ tx_queue->channel = NULL;
}
}
-
- efx_for_each_rx_queue(rx_queue, efx)
- rx_queue->channel = &efx->channel[rx_queue->queue];
}
static int efx_probe_nic(struct efx_nic *efx)
{
+ size_t i;
int rc;
- EFX_LOG(efx, "creating NIC\n");
+ netif_dbg(efx, probe, efx->net_dev, "creating NIC\n");
/* Carry out hardware-type specific initialisation */
rc = efx->type->probe(efx);
@@ -1106,8 +1301,14 @@ static int efx_probe_nic(struct efx_nic *efx)
* in MSI-X interrupts. */
efx_probe_interrupts(efx);
+ if (efx->n_channels > 1)
+ get_random_bytes(&efx->rx_hash_key, sizeof(efx->rx_hash_key));
+ for (i = 0; i < ARRAY_SIZE(efx->rx_indir_table); i++)
+ efx->rx_indir_table[i] = i % efx->n_rx_channels;
+
efx_set_channels(efx);
- efx->net_dev->real_num_tx_queues = efx->n_tx_channels;
+ 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);
/* Initialise the interrupt moderation settings */
efx_init_irq_moderation(efx, tx_irq_mod_usec, rx_irq_mod_usec, true);
@@ -1117,7 +1318,7 @@ static int efx_probe_nic(struct efx_nic *efx)
static void efx_remove_nic(struct efx_nic *efx)
{
- EFX_LOG(efx, "destroying NIC\n");
+ netif_dbg(efx, drv, efx->net_dev, "destroying NIC\n");
efx_remove_interrupts(efx);
efx->type->remove(efx);
@@ -1131,39 +1332,37 @@ static void efx_remove_nic(struct efx_nic *efx)
static int efx_probe_all(struct efx_nic *efx)
{
- struct efx_channel *channel;
int rc;
- /* Create NIC */
rc = efx_probe_nic(efx);
if (rc) {
- EFX_ERR(efx, "failed to create NIC\n");
+ netif_err(efx, probe, efx->net_dev, "failed to create NIC\n");
goto fail1;
}
- /* Create port */
rc = efx_probe_port(efx);
if (rc) {
- EFX_ERR(efx, "failed to create port\n");
+ netif_err(efx, probe, efx->net_dev, "failed to create port\n");
goto fail2;
}
- /* Create channels */
- efx_for_each_channel(channel, efx) {
- rc = efx_probe_channel(channel);
- if (rc) {
- EFX_ERR(efx, "failed to create channel %d\n",
- channel->channel);
- goto fail3;
- }
+ efx->rxq_entries = efx->txq_entries = EFX_DEFAULT_DMAQ_SIZE;
+ rc = efx_probe_channels(efx);
+ if (rc)
+ goto fail3;
+
+ rc = efx_probe_filters(efx);
+ if (rc) {
+ netif_err(efx, probe, efx->net_dev,
+ "failed to create filter tables\n");
+ goto fail4;
}
- efx_set_channel_names(efx);
return 0;
+ fail4:
+ efx_remove_channels(efx);
fail3:
- efx_for_each_channel(channel, efx)
- efx_remove_channel(channel);
efx_remove_port(efx);
fail2:
efx_remove_nic(efx);
@@ -1233,15 +1432,8 @@ static void efx_start_all(struct efx_nic *efx)
* since we're holding the rtnl_lock at this point. */
static void efx_flush_all(struct efx_nic *efx)
{
- struct efx_rx_queue *rx_queue;
-
/* Make sure the hardware monitor is stopped */
cancel_delayed_work_sync(&efx->monitor_work);
-
- /* Ensure that all RX slow refills are complete. */
- efx_for_each_rx_queue(rx_queue, efx)
- cancel_delayed_work_sync(&rx_queue->work);
-
/* Stop scheduled port reconfigurations */
cancel_work_sync(&efx->mac_work);
}
@@ -1300,10 +1492,8 @@ static void efx_stop_all(struct efx_nic *efx)
static void efx_remove_all(struct efx_nic *efx)
{
- struct efx_channel *channel;
-
- efx_for_each_channel(channel, efx)
- efx_remove_channel(channel);
+ efx_remove_filters(efx);
+ efx_remove_channels(efx);
efx_remove_port(efx);
efx_remove_nic(efx);
}
@@ -1327,20 +1517,20 @@ static unsigned irq_mod_ticks(int usecs, int resolution)
void efx_init_irq_moderation(struct efx_nic *efx, int tx_usecs, int rx_usecs,
bool rx_adaptive)
{
- struct efx_tx_queue *tx_queue;
- struct efx_rx_queue *rx_queue;
+ struct efx_channel *channel;
unsigned tx_ticks = irq_mod_ticks(tx_usecs, EFX_IRQ_MOD_RESOLUTION);
unsigned rx_ticks = irq_mod_ticks(rx_usecs, EFX_IRQ_MOD_RESOLUTION);
EFX_ASSERT_RESET_SERIALISED(efx);
- efx_for_each_tx_queue(tx_queue, efx)
- tx_queue->channel->irq_moderation = tx_ticks;
-
efx->irq_rx_adaptive = rx_adaptive;
efx->irq_rx_moderation = rx_ticks;
- efx_for_each_rx_queue(rx_queue, efx)
- rx_queue->channel->irq_moderation = rx_ticks;
+ efx_for_each_channel(channel, efx) {
+ if (efx_channel_get_rx_queue(channel))
+ channel->irq_moderation = rx_ticks;
+ else if (efx_channel_get_tx_queue(channel, 0))
+ channel->irq_moderation = tx_ticks;
+ }
}
/**************************************************************************
@@ -1349,29 +1539,26 @@ void efx_init_irq_moderation(struct efx_nic *efx, int tx_usecs, int rx_usecs,
*
**************************************************************************/
-/* Run periodically off the general workqueue. Serialised against
- * efx_reconfigure_port via the mac_lock */
+/* Run periodically off the general workqueue */
static void efx_monitor(struct work_struct *data)
{
struct efx_nic *efx = container_of(data, struct efx_nic,
monitor_work.work);
- EFX_TRACE(efx, "hardware monitor executing on CPU %d\n",
- raw_smp_processor_id());
+ netif_vdbg(efx, timer, efx->net_dev,
+ "hardware monitor executing on CPU %d\n",
+ raw_smp_processor_id());
BUG_ON(efx->type->monitor == NULL);
/* If the mac_lock is already held then it is likely a port
* reconfiguration is already in place, which will likely do
- * most of the work of check_hw() anyway. */
- if (!mutex_trylock(&efx->mac_lock))
- goto out_requeue;
- if (!efx->port_enabled)
- goto out_unlock;
- efx->type->monitor(efx);
+ * most of the work of monitor() anyway. */
+ if (mutex_trylock(&efx->mac_lock)) {
+ if (efx->port_enabled)
+ efx->type->monitor(efx);
+ mutex_unlock(&efx->mac_lock);
+ }
-out_unlock:
- mutex_unlock(&efx->mac_lock);
-out_requeue:
queue_delayed_work(efx->workqueue, &efx->monitor_work,
efx_monitor_interval);
}
@@ -1464,8 +1651,8 @@ static int efx_net_open(struct net_device *net_dev)
struct efx_nic *efx = netdev_priv(net_dev);
EFX_ASSERT_RESET_SERIALISED(efx);
- EFX_LOG(efx, "opening device %s on CPU %d\n", net_dev->name,
- raw_smp_processor_id());
+ netif_dbg(efx, ifup, efx->net_dev, "opening device on CPU %d\n",
+ raw_smp_processor_id());
if (efx->state == STATE_DISABLED)
return -EIO;
@@ -1490,8 +1677,8 @@ static int efx_net_stop(struct net_device *net_dev)
{
struct efx_nic *efx = netdev_priv(net_dev);
- EFX_LOG(efx, "closing %s on CPU %d\n", net_dev->name,
- raw_smp_processor_id());
+ netif_dbg(efx, ifdown, efx->net_dev, "closing on CPU %d\n",
+ raw_smp_processor_id());
if (efx->state != STATE_DISABLED) {
/* Stop the device and flush all the channels */
@@ -1504,11 +1691,10 @@ static int efx_net_stop(struct net_device *net_dev)
}
/* Context: process, dev_base_lock or RTNL held, non-blocking. */
-static struct net_device_stats *efx_net_stats(struct net_device *net_dev)
+static struct rtnl_link_stats64 *efx_net_stats(struct net_device *net_dev, struct rtnl_link_stats64 *stats)
{
struct efx_nic *efx = netdev_priv(net_dev);
struct efx_mac_stats *mac_stats = &efx->mac_stats;
- struct net_device_stats *stats = &net_dev->stats;
spin_lock_bh(&efx->stats_lock);
efx->type->update_stats(efx);
@@ -1518,11 +1704,11 @@ static struct net_device_stats *efx_net_stats(struct net_device *net_dev)
stats->tx_packets = mac_stats->tx_packets;
stats->rx_bytes = mac_stats->rx_bytes;
stats->tx_bytes = mac_stats->tx_bytes;
+ stats->rx_dropped = efx->n_rx_nodesc_drop_cnt;
stats->multicast = mac_stats->rx_multicast;
stats->collisions = mac_stats->tx_collision;
stats->rx_length_errors = (mac_stats->rx_gtjumbo +
mac_stats->rx_length_error);
- stats->rx_over_errors = efx->n_rx_nodesc_drop_cnt;
stats->rx_crc_errors = mac_stats->rx_bad;
stats->rx_frame_errors = mac_stats->rx_align_error;
stats->rx_fifo_errors = mac_stats->rx_overflow;
@@ -1530,11 +1716,8 @@ static struct net_device_stats *efx_net_stats(struct net_device *net_dev)
stats->tx_window_errors = mac_stats->tx_late_collision;
stats->rx_errors = (stats->rx_length_errors +
- stats->rx_over_errors +
stats->rx_crc_errors +
stats->rx_frame_errors +
- stats->rx_fifo_errors +
- stats->rx_missed_errors +
mac_stats->rx_symbol_error);
stats->tx_errors = (stats->tx_window_errors +
mac_stats->tx_bad);
@@ -1547,8 +1730,9 @@ static void efx_watchdog(struct net_device *net_dev)
{
struct efx_nic *efx = netdev_priv(net_dev);
- EFX_ERR(efx, "TX stuck with port_enabled=%d: resetting channels\n",
- efx->port_enabled);
+ netif_err(efx, tx_err, efx->net_dev,
+ "TX stuck with port_enabled=%d: resetting channels\n",
+ efx->port_enabled);
efx_schedule_reset(efx, RESET_TYPE_TX_WATCHDOG);
}
@@ -1567,7 +1751,7 @@ static int efx_change_mtu(struct net_device *net_dev, int new_mtu)
efx_stop_all(efx);
- EFX_LOG(efx, "changing MTU to %d\n", new_mtu);
+ netif_dbg(efx, drv, efx->net_dev, "changing MTU to %d\n", new_mtu);
efx_fini_channels(efx);
@@ -1593,8 +1777,9 @@ static int efx_set_mac_address(struct net_device *net_dev, void *data)
EFX_ASSERT_RESET_SERIALISED(efx);
if (!is_valid_ether_addr(new_addr)) {
- EFX_ERR(efx, "invalid ethernet MAC address requested: %pM\n",
- new_addr);
+ netif_err(efx, drv, efx->net_dev,
+ "invalid ethernet MAC address requested: %pM\n",
+ new_addr);
return -EINVAL;
}
@@ -1645,7 +1830,7 @@ static void efx_set_multicast_list(struct net_device *net_dev)
static const struct net_device_ops efx_netdev_ops = {
.ndo_open = efx_net_open,
.ndo_stop = efx_net_stop,
- .ndo_get_stats = efx_net_stats,
+ .ndo_get_stats64 = efx_net_stats,
.ndo_tx_timeout = efx_watchdog,
.ndo_start_xmit = efx_hard_start_xmit,
.ndo_validate_addr = eth_validate_addr,
@@ -1697,7 +1882,6 @@ static int efx_register_netdev(struct efx_nic *efx)
net_dev->watchdog_timeo = 5 * HZ;
net_dev->irq = efx->pci_dev->irq;
net_dev->netdev_ops = &efx_netdev_ops;
- SET_NETDEV_DEV(net_dev, &efx->pci_dev->dev);
SET_ETHTOOL_OPS(net_dev, &efx_ethtool_ops);
/* Clear MAC statistics */
@@ -1722,7 +1906,8 @@ static int efx_register_netdev(struct efx_nic *efx)
rc = device_create_file(&efx->pci_dev->dev, &dev_attr_phy_type);
if (rc) {
- EFX_ERR(efx, "failed to init net dev attributes\n");
+ netif_err(efx, drv, efx->net_dev,
+ "failed to init net dev attributes\n");
goto fail_registered;
}
@@ -1730,7 +1915,7 @@ static int efx_register_netdev(struct efx_nic *efx)
fail_locked:
rtnl_unlock();
- EFX_ERR(efx, "could not register net dev\n");
+ netif_err(efx, drv, efx->net_dev, "could not register net dev\n");
return rc;
fail_registered:
@@ -1740,6 +1925,7 @@ fail_registered:
static void efx_unregister_netdev(struct efx_nic *efx)
{
+ struct efx_channel *channel;
struct efx_tx_queue *tx_queue;
if (!efx->net_dev)
@@ -1750,8 +1936,10 @@ static void efx_unregister_netdev(struct efx_nic *efx)
/* Free up any skbs still remaining. This has to happen before
* we try to unregister the netdev as running their destructors
* may be needed to get the device ref. count to 0. */
- efx_for_each_tx_queue(tx_queue, efx)
- efx_release_tx_buffers(tx_queue);
+ efx_for_each_channel(channel, efx) {
+ efx_for_each_channel_tx_queue(tx_queue, channel)
+ efx_release_tx_buffers(tx_queue);
+ }
if (efx_dev_registered(efx)) {
strlcpy(efx->name, pci_name(efx->pci_dev), sizeof(efx->name));
@@ -1795,7 +1983,7 @@ int efx_reset_up(struct efx_nic *efx, enum reset_type method, bool ok)
rc = efx->type->init(efx);
if (rc) {
- EFX_ERR(efx, "failed to initialise NIC\n");
+ netif_err(efx, drv, efx->net_dev, "failed to initialise NIC\n");
goto fail;
}
@@ -1807,12 +1995,14 @@ int efx_reset_up(struct efx_nic *efx, enum reset_type method, bool ok)
if (rc)
goto fail;
if (efx->phy_op->reconfigure(efx))
- EFX_ERR(efx, "could not restore PHY settings\n");
+ netif_err(efx, drv, efx->net_dev,
+ "could not restore PHY settings\n");
}
efx->mac_op->reconfigure(efx);
efx_init_channels(efx);
+ efx_restore_filters(efx);
mutex_unlock(&efx->spi_lock);
mutex_unlock(&efx->mac_lock);
@@ -1840,13 +2030,14 @@ int efx_reset(struct efx_nic *efx, enum reset_type method)
int rc, rc2;
bool disabled;
- EFX_INFO(efx, "resetting (%s)\n", RESET_TYPE(method));
+ netif_info(efx, drv, efx->net_dev, "resetting (%s)\n",
+ RESET_TYPE(method));
efx_reset_down(efx, method);
rc = efx->type->reset(efx, method);
if (rc) {
- EFX_ERR(efx, "failed to reset hardware\n");
+ netif_err(efx, drv, efx->net_dev, "failed to reset hardware\n");
goto out;
}
@@ -1871,10 +2062,10 @@ out:
if (disabled) {
dev_close(efx->net_dev);
- EFX_ERR(efx, "has been disabled\n");
+ netif_err(efx, drv, efx->net_dev, "has been disabled\n");
efx->state = STATE_DISABLED;
} else {
- EFX_LOG(efx, "reset complete\n");
+ netif_dbg(efx, drv, efx->net_dev, "reset complete\n");
}
return rc;
}
@@ -1886,10 +2077,14 @@ static void efx_reset_work(struct work_struct *data)
{
struct efx_nic *efx = container_of(data, struct efx_nic, reset_work);
+ if (efx->reset_pending == RESET_TYPE_NONE)
+ return;
+
/* If we're not RUNNING then don't reset. Leave the reset_pending
* flag set so that efx_pci_probe_main will be retried */
if (efx->state != STATE_RUNNING) {
- EFX_INFO(efx, "scheduled reset quenched. NIC not RUNNING\n");
+ netif_info(efx, drv, efx->net_dev,
+ "scheduled reset quenched. NIC not RUNNING\n");
return;
}
@@ -1903,7 +2098,8 @@ void efx_schedule_reset(struct efx_nic *efx, enum reset_type type)
enum reset_type method;
if (efx->reset_pending != RESET_TYPE_NONE) {
- EFX_INFO(efx, "quenching already scheduled reset\n");
+ netif_info(efx, drv, efx->net_dev,
+ "quenching already scheduled reset\n");
return;
}
@@ -1927,10 +2123,12 @@ void efx_schedule_reset(struct efx_nic *efx, enum reset_type type)
}
if (method != type)
- EFX_LOG(efx, "scheduling %s reset for %s\n",
- RESET_TYPE(method), RESET_TYPE(type));
+ netif_dbg(efx, drv, efx->net_dev,
+ "scheduling %s reset for %s\n",
+ RESET_TYPE(method), RESET_TYPE(type));
else
- EFX_LOG(efx, "scheduling %s reset\n", RESET_TYPE(method));
+ netif_dbg(efx, drv, efx->net_dev, "scheduling %s reset\n",
+ RESET_TYPE(method));
efx->reset_pending = method;
@@ -1974,10 +2172,8 @@ int efx_port_dummy_op_int(struct efx_nic *efx)
return 0;
}
void efx_port_dummy_op_void(struct efx_nic *efx) {}
-void efx_port_dummy_op_set_id_led(struct efx_nic *efx, enum efx_led_mode mode)
-{
-}
-bool efx_port_dummy_op_poll(struct efx_nic *efx)
+
+static bool efx_port_dummy_op_poll(struct efx_nic *efx)
{
return false;
}
@@ -2001,9 +2197,6 @@ static struct efx_phy_operations efx_dummy_phy_operations = {
static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type,
struct pci_dev *pci_dev, struct net_device *net_dev)
{
- struct efx_channel *channel;
- struct efx_tx_queue *tx_queue;
- struct efx_rx_queue *rx_queue;
int i;
/* Initialise common structures */
@@ -2017,6 +2210,7 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type,
INIT_WORK(&efx->reset_work, efx_reset_work);
INIT_DELAYED_WORK(&efx->monitor_work, efx_monitor);
efx->pci_dev = pci_dev;
+ efx->msg_enable = debug;
efx->state = STATE_INIT;
efx->reset_pending = RESET_TYPE_NONE;
strlcpy(efx->name, pci_name(pci_dev), sizeof(efx->name));
@@ -2031,36 +2225,13 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type,
INIT_WORK(&efx->mac_work, efx_mac_work);
for (i = 0; i < EFX_MAX_CHANNELS; i++) {
- channel = &efx->channel[i];
- channel->efx = efx;
- channel->channel = i;
- channel->work_pending = false;
- spin_lock_init(&channel->tx_stop_lock);
- atomic_set(&channel->tx_stop_count, 1);
- }
- for (i = 0; i < EFX_MAX_TX_QUEUES; i++) {
- tx_queue = &efx->tx_queue[i];
- tx_queue->efx = efx;
- tx_queue->queue = i;
- tx_queue->buffer = NULL;
- tx_queue->channel = &efx->channel[0]; /* for safety */
- tx_queue->tso_headers_free = NULL;
- }
- for (i = 0; i < EFX_MAX_RX_QUEUES; i++) {
- rx_queue = &efx->rx_queue[i];
- rx_queue->efx = efx;
- rx_queue->queue = i;
- rx_queue->channel = &efx->channel[0]; /* for safety */
- rx_queue->buffer = NULL;
- spin_lock_init(&rx_queue->add_lock);
- INIT_DELAYED_WORK(&rx_queue->work, efx_rx_work);
+ efx->channel[i] = efx_alloc_channel(efx, i, NULL);
+ if (!efx->channel[i])
+ goto fail;
}
efx->type = type;
- /* As close as we can get to guaranteeing that we don't overflow */
- BUILD_BUG_ON(EFX_EVQ_SIZE < EFX_TXQ_SIZE + EFX_RXQ_SIZE);
-
EFX_BUG_ON_PARANOID(efx->type->phys_addr_channels > EFX_MAX_CHANNELS);
/* Higher numbered interrupt modes are less capable! */
@@ -2072,13 +2243,22 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type,
pci_name(pci_dev));
efx->workqueue = create_singlethread_workqueue(efx->workqueue_name);
if (!efx->workqueue)
- return -ENOMEM;
+ goto fail;
return 0;
+
+fail:
+ efx_fini_struct(efx);
+ return -ENOMEM;
}
static void efx_fini_struct(struct efx_nic *efx)
{
+ int i;
+
+ for (i = 0; i < EFX_MAX_CHANNELS; i++)
+ kfree(efx->channel[i]);
+
if (efx->workqueue) {
destroy_workqueue(efx->workqueue);
efx->workqueue = NULL;
@@ -2136,7 +2316,7 @@ static void efx_pci_remove(struct pci_dev *pci_dev)
efx_pci_remove_main(efx);
efx_fini_io(efx);
- EFX_LOG(efx, "shutdown successful\n");
+ netif_dbg(efx, drv, efx->net_dev, "shutdown successful\n");
pci_set_drvdata(pci_dev, NULL);
efx_fini_struct(efx);
@@ -2161,13 +2341,15 @@ static int efx_pci_probe_main(struct efx_nic *efx)
rc = efx->type->init(efx);
if (rc) {
- EFX_ERR(efx, "failed to initialise NIC\n");
+ netif_err(efx, probe, efx->net_dev,
+ "failed to initialise NIC\n");
goto fail3;
}
rc = efx_init_port(efx);
if (rc) {
- EFX_ERR(efx, "failed to initialise port\n");
+ netif_err(efx, probe, efx->net_dev,
+ "failed to initialise port\n");
goto fail4;
}
@@ -2223,11 +2405,13 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev,
NETIF_F_HIGHDMA | NETIF_F_TSO);
efx = netdev_priv(net_dev);
pci_set_drvdata(pci_dev, efx);
+ SET_NETDEV_DEV(net_dev, &pci_dev->dev);
rc = efx_init_struct(efx, type, pci_dev, net_dev);
if (rc)
goto fail1;
- EFX_INFO(efx, "Solarflare Communications NIC detected\n");
+ netif_info(efx, probe, efx->net_dev,
+ "Solarflare Communications NIC detected\n");
/* Set up basic I/O (BAR mappings etc) */
rc = efx_init_io(efx);
@@ -2265,7 +2449,7 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev,
}
if (rc) {
- EFX_ERR(efx, "Could not reset NIC\n");
+ netif_err(efx, probe, efx->net_dev, "Could not reset NIC\n");
goto fail4;
}
@@ -2277,7 +2461,7 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev,
if (rc)
goto fail5;
- EFX_LOG(efx, "initialisation successful\n");
+ netif_dbg(efx, probe, efx->net_dev, "initialisation successful\n");
rtnl_lock();
efx_mtd_probe(efx); /* allowed to fail */
@@ -2293,7 +2477,7 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev,
efx_fini_struct(efx);
fail1:
WARN_ON(rc > 0);
- EFX_LOG(efx, "initialisation failed. rc=%d\n", rc);
+ netif_dbg(efx, drv, efx->net_dev, "initialisation failed. rc=%d\n", rc);
free_netdev(net_dev);
return rc;
}
@@ -2332,6 +2516,9 @@ static int efx_pm_thaw(struct device *dev)
efx->type->resume_wol(efx);
+ /* Reschedule any quenched resets scheduled during efx_pm_freeze() */
+ queue_work(reset_workqueue, &efx->reset_work);
+
return 0;
}
@@ -2394,7 +2581,7 @@ static struct dev_pm_ops efx_pm_ops = {
};
static struct pci_driver efx_pci_driver = {
- .name = EFX_DRIVER_NAME,
+ .name = KBUILD_MODNAME,
.id_table = efx_pci_table,
.probe = efx_pci_probe,
.remove = efx_pci_remove,
@@ -2421,11 +2608,6 @@ static int __init efx_init_module(void)
if (rc)
goto err_notifier;
- refill_workqueue = create_workqueue("sfc_refill");
- if (!refill_workqueue) {
- rc = -ENOMEM;
- goto err_refill;
- }
reset_workqueue = create_singlethread_workqueue("sfc_reset");
if (!reset_workqueue) {
rc = -ENOMEM;
@@ -2441,8 +2623,6 @@ static int __init efx_init_module(void)
err_pci:
destroy_workqueue(reset_workqueue);
err_reset:
- destroy_workqueue(refill_workqueue);
- err_refill:
unregister_netdevice_notifier(&efx_netdev_notifier);
err_notifier:
return rc;
@@ -2454,7 +2634,6 @@ static void __exit efx_exit_module(void)
pci_unregister_driver(&efx_pci_driver);
destroy_workqueue(reset_workqueue);
- destroy_workqueue(refill_workqueue);
unregister_netdevice_notifier(&efx_netdev_notifier);
}
diff --git a/drivers/net/sfc/efx.h b/drivers/net/sfc/efx.h
index ffd708c5304a..10a1bf40da96 100644
--- a/drivers/net/sfc/efx.h
+++ b/drivers/net/sfc/efx.h
@@ -12,6 +12,7 @@
#define EFX_EFX_H
#include "net_driver.h"
+#include "filter.h"
/* PCI IDs */
#define EFX_VENDID_SFC 0x1924
@@ -37,8 +38,6 @@ efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb);
extern void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index);
extern void efx_stop_queue(struct efx_channel *channel);
extern void efx_wake_queue(struct efx_channel *channel);
-#define EFX_TXQ_SIZE 1024
-#define EFX_TXQ_MASK (EFX_TXQ_SIZE - 1)
/* RX */
extern int efx_probe_rx_queue(struct efx_rx_queue *rx_queue);
@@ -47,29 +46,48 @@ extern void efx_init_rx_queue(struct efx_rx_queue *rx_queue);
extern void efx_fini_rx_queue(struct efx_rx_queue *rx_queue);
extern void efx_rx_strategy(struct efx_channel *channel);
extern void efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue);
-extern void efx_rx_work(struct work_struct *data);
+extern void efx_rx_slow_fill(unsigned long context);
extern void __efx_rx_packet(struct efx_channel *channel,
struct efx_rx_buffer *rx_buf, bool checksummed);
extern void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index,
unsigned int len, bool checksummed, bool discard);
-extern void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue, int delay);
-#define EFX_RXQ_SIZE 1024
-#define EFX_RXQ_MASK (EFX_RXQ_SIZE - 1)
+extern void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue);
+
+#define EFX_MAX_DMAQ_SIZE 4096UL
+#define EFX_DEFAULT_DMAQ_SIZE 1024UL
+#define EFX_MIN_DMAQ_SIZE 512UL
+
+#define EFX_MAX_EVQ_SIZE 16384UL
+#define EFX_MIN_EVQ_SIZE 512UL
+
+/* The smallest [rt]xq_entries that the driver supports. Callers of
+ * efx_wake_queue() assume that they can subsequently send at least one
+ * skb. Falcon/A1 may require up to three descriptors per skb_frag. */
+#define EFX_MIN_RING_SIZE (roundup_pow_of_two(2 * 3 * MAX_SKB_FRAGS))
+
+/* Filters */
+extern int efx_probe_filters(struct efx_nic *efx);
+extern void efx_restore_filters(struct efx_nic *efx);
+extern void efx_remove_filters(struct efx_nic *efx);
+extern int efx_filter_insert_filter(struct efx_nic *efx,
+ struct efx_filter_spec *spec,
+ bool replace);
+extern int efx_filter_remove_filter(struct efx_nic *efx,
+ struct efx_filter_spec *spec);
+extern void efx_filter_table_clear(struct efx_nic *efx,
+ enum efx_filter_table_id table_id,
+ enum efx_filter_priority priority);
/* Channels */
extern void efx_process_channel_now(struct efx_channel *channel);
-#define EFX_EVQ_SIZE 4096
-#define EFX_EVQ_MASK (EFX_EVQ_SIZE - 1)
+extern int
+efx_realloc_channels(struct efx_nic *efx, u32 rxq_entries, u32 txq_entries);
/* Ports */
extern int efx_reconfigure_port(struct efx_nic *efx);
extern int __efx_reconfigure_port(struct efx_nic *efx);
/* Ethtool support */
-extern int efx_ethtool_get_settings(struct net_device *net_dev,
- struct ethtool_cmd *ecmd);
-extern int efx_ethtool_set_settings(struct net_device *net_dev,
- struct ethtool_cmd *ecmd);
extern const struct ethtool_ops efx_ethtool_ops;
/* Reset handling */
@@ -81,15 +99,11 @@ extern int efx_reset_up(struct efx_nic *efx, enum reset_type method, bool ok);
extern void efx_schedule_reset(struct efx_nic *efx, enum reset_type type);
extern void efx_init_irq_moderation(struct efx_nic *efx, int tx_usecs,
int rx_usecs, bool rx_adaptive);
-extern int efx_request_power(struct efx_nic *efx, int mw, const char *name);
-extern void efx_hex_dump(const u8 *, unsigned int, const char *);
/* Dummy PHY ops for PHY drivers */
extern int efx_port_dummy_op_int(struct efx_nic *efx);
extern void efx_port_dummy_op_void(struct efx_nic *efx);
-extern void
-efx_port_dummy_op_set_id_led(struct efx_nic *efx, enum efx_led_mode mode);
-extern bool efx_port_dummy_op_poll(struct efx_nic *efx);
+
/* MTD */
#ifdef CONFIG_SFC_MTD
@@ -102,12 +116,11 @@ static inline void efx_mtd_rename(struct efx_nic *efx) {}
static inline void efx_mtd_remove(struct efx_nic *efx) {}
#endif
-extern unsigned int efx_monitor_interval;
-
static inline void efx_schedule_channel(struct efx_channel *channel)
{
- EFX_TRACE(channel->efx, "channel %d scheduling NAPI poll on CPU%d\n",
- channel->channel, raw_smp_processor_id());
+ netif_vdbg(channel->efx, intr, channel->efx->net_dev,
+ "channel %d scheduling NAPI poll on CPU%d\n",
+ channel->channel, raw_smp_processor_id());
channel->work_pending = true;
napi_schedule(&channel->napi_str);
diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c
index 22026bfbc4c1..edb9d16b8b47 100644
--- a/drivers/net/sfc/ethtool.c
+++ b/drivers/net/sfc/ethtool.c
@@ -15,6 +15,7 @@
#include "workarounds.h"
#include "selftest.h"
#include "efx.h"
+#include "filter.h"
#include "nic.h"
#include "spi.h"
#include "mdio_10g.h"
@@ -186,8 +187,8 @@ static int efx_ethtool_phys_id(struct net_device *net_dev, u32 count)
}
/* This must be called with rtnl_lock held. */
-int efx_ethtool_get_settings(struct net_device *net_dev,
- struct ethtool_cmd *ecmd)
+static int efx_ethtool_get_settings(struct net_device *net_dev,
+ struct ethtool_cmd *ecmd)
{
struct efx_nic *efx = netdev_priv(net_dev);
struct efx_link_state *link_state = &efx->link_state;
@@ -210,16 +211,16 @@ int efx_ethtool_get_settings(struct net_device *net_dev,
}
/* This must be called with rtnl_lock held. */
-int efx_ethtool_set_settings(struct net_device *net_dev,
- struct ethtool_cmd *ecmd)
+static int efx_ethtool_set_settings(struct net_device *net_dev,
+ struct ethtool_cmd *ecmd)
{
struct efx_nic *efx = netdev_priv(net_dev);
int rc;
/* GMAC does not support 1000Mbps HD */
if (ecmd->speed == SPEED_1000 && ecmd->duplex != DUPLEX_FULL) {
- EFX_LOG(efx, "rejecting unsupported 1000Mbps HD"
- " setting\n");
+ netif_dbg(efx, drv, efx->net_dev,
+ "rejecting unsupported 1000Mbps HD setting\n");
return -EINVAL;
}
@@ -234,7 +235,7 @@ static 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));
if (efx_nic_rev(efx) >= EFX_REV_SIENA_A0)
siena_print_fwver(efx, info->fw_version,
@@ -242,6 +243,32 @@ static void efx_ethtool_get_drvinfo(struct net_device *net_dev,
strlcpy(info->bus_info, pci_name(efx->pci_dev), sizeof(info->bus_info));
}
+static int efx_ethtool_get_regs_len(struct net_device *net_dev)
+{
+ return efx_nic_get_regs_len(netdev_priv(net_dev));
+}
+
+static void efx_ethtool_get_regs(struct net_device *net_dev,
+ struct ethtool_regs *regs, void *buf)
+{
+ struct efx_nic *efx = netdev_priv(net_dev);
+
+ regs->version = efx->type->revision;
+ efx_nic_get_regs(efx, buf);
+}
+
+static u32 efx_ethtool_get_msglevel(struct net_device *net_dev)
+{
+ struct efx_nic *efx = netdev_priv(net_dev);
+ return efx->msg_enable;
+}
+
+static void efx_ethtool_set_msglevel(struct net_device *net_dev, u32 msg_enable)
+{
+ struct efx_nic *efx = netdev_priv(net_dev);
+ efx->msg_enable = msg_enable;
+}
+
/**
* efx_fill_test - fill in an individual self-test entry
* @test_index: Index of the test
@@ -302,9 +329,10 @@ static int efx_fill_loopback_test(struct efx_nic *efx,
unsigned int test_index,
struct ethtool_string *strings, u64 *data)
{
+ struct efx_channel *channel = efx_get_channel(efx, 0);
struct efx_tx_queue *tx_queue;
- efx_for_each_channel_tx_queue(tx_queue, &efx->channel[0]) {
+ efx_for_each_channel_tx_queue(tx_queue, channel) {
efx_fill_test(test_index++, strings, data,
&lb_tests->tx_sent[tx_queue->queue],
EFX_TX_QUEUE_NAME(tx_queue),
@@ -443,12 +471,13 @@ static void efx_ethtool_get_stats(struct net_device *net_dev,
struct efx_mac_stats *mac_stats = &efx->mac_stats;
struct efx_ethtool_stat *stat;
struct efx_channel *channel;
+ struct rtnl_link_stats64 temp;
int i;
EFX_BUG_ON_PARANOID(stats->n_stats != EFX_ETHTOOL_NUM_STATS);
/* Update MAC and NIC statistics */
- dev_get_stats(net_dev);
+ dev_get_stats(net_dev, &temp);
/* Fill detailed statistics buffer */
for (i = 0; i < EFX_ETHTOOL_NUM_STATS; i++) {
@@ -520,6 +549,27 @@ static u32 efx_ethtool_get_rx_csum(struct net_device *net_dev)
return efx->rx_checksum_enabled;
}
+static int efx_ethtool_set_flags(struct net_device *net_dev, u32 data)
+{
+ struct efx_nic *efx = netdev_priv(net_dev);
+ u32 supported = (efx->type->offload_features &
+ (ETH_FLAG_RXHASH | ETH_FLAG_NTUPLE));
+ int rc;
+
+ rc = ethtool_op_set_flags(net_dev, data, supported);
+ if (rc)
+ return rc;
+
+ if (!(data & ETH_FLAG_NTUPLE)) {
+ efx_filter_table_clear(efx, EFX_FILTER_TABLE_RX_IP,
+ EFX_FILTER_PRI_MANUAL);
+ efx_filter_table_clear(efx, EFX_FILTER_TABLE_RX_MAC,
+ EFX_FILTER_PRI_MANUAL);
+ }
+
+ return 0;
+}
+
static void efx_ethtool_self_test(struct net_device *net_dev,
struct ethtool_test *test, u64 *data)
{
@@ -539,7 +589,8 @@ static void efx_ethtool_self_test(struct net_device *net_dev,
if (!already_up) {
rc = dev_open(efx->net_dev);
if (rc) {
- EFX_ERR(efx, "failed opening device.\n");
+ netif_err(efx, drv, efx->net_dev,
+ "failed opening device.\n");
goto fail2;
}
}
@@ -551,9 +602,9 @@ static void efx_ethtool_self_test(struct net_device *net_dev,
if (!already_up)
dev_close(efx->net_dev);
- EFX_LOG(efx, "%s %sline self-tests\n",
- rc == 0 ? "passed" : "failed",
- (test->flags & ETH_TEST_FL_OFFLINE) ? "off" : "on");
+ netif_dbg(efx, drv, efx->net_dev, "%s %sline self-tests\n",
+ rc == 0 ? "passed" : "failed",
+ (test->flags & ETH_TEST_FL_OFFLINE) ? "off" : "on");
fail2:
fail1:
@@ -637,15 +688,15 @@ static int efx_ethtool_get_coalesce(struct net_device *net_dev,
struct ethtool_coalesce *coalesce)
{
struct efx_nic *efx = netdev_priv(net_dev);
- struct efx_tx_queue *tx_queue;
struct efx_channel *channel;
memset(coalesce, 0, sizeof(*coalesce));
/* Find lowest IRQ moderation across all used TX queues */
coalesce->tx_coalesce_usecs_irq = ~((u32) 0);
- efx_for_each_tx_queue(tx_queue, efx) {
- channel = tx_queue->channel;
+ efx_for_each_channel(channel, efx) {
+ if (!efx_channel_get_tx_queue(channel, 0))
+ continue;
if (channel->irq_moderation < coalesce->tx_coalesce_usecs_irq) {
if (channel->channel < efx->n_rx_channels)
coalesce->tx_coalesce_usecs_irq =
@@ -672,15 +723,14 @@ static int efx_ethtool_set_coalesce(struct net_device *net_dev,
{
struct efx_nic *efx = netdev_priv(net_dev);
struct efx_channel *channel;
- struct efx_tx_queue *tx_queue;
unsigned tx_usecs, rx_usecs, adaptive;
if (coalesce->use_adaptive_tx_coalesce)
return -EOPNOTSUPP;
if (coalesce->rx_coalesce_usecs || coalesce->tx_coalesce_usecs) {
- EFX_ERR(efx, "invalid coalescing setting. "
- "Only rx/tx_coalesce_usecs_irq are supported\n");
+ netif_err(efx, drv, efx->net_dev, "invalid coalescing setting. "
+ "Only rx/tx_coalesce_usecs_irq are supported\n");
return -EOPNOTSUPP;
}
@@ -689,11 +739,12 @@ static int efx_ethtool_set_coalesce(struct net_device *net_dev,
adaptive = coalesce->use_adaptive_rx_coalesce;
/* If the channel is shared only allow RX parameters to be set */
- efx_for_each_tx_queue(tx_queue, efx) {
- if ((tx_queue->channel->channel < efx->n_rx_channels) &&
+ efx_for_each_channel(channel, efx) {
+ if (efx_channel_get_rx_queue(channel) &&
+ efx_channel_get_tx_queue(channel, 0) &&
tx_usecs) {
- EFX_ERR(efx, "Channel is shared. "
- "Only RX coalescing may be set\n");
+ netif_err(efx, drv, efx->net_dev, "Channel is shared. "
+ "Only RX coalescing may be set\n");
return -EOPNOTSUPP;
}
}
@@ -705,6 +756,42 @@ static int efx_ethtool_set_coalesce(struct net_device *net_dev,
return 0;
}
+static void efx_ethtool_get_ringparam(struct net_device *net_dev,
+ struct ethtool_ringparam *ring)
+{
+ struct efx_nic *efx = netdev_priv(net_dev);
+
+ ring->rx_max_pending = EFX_MAX_DMAQ_SIZE;
+ ring->tx_max_pending = EFX_MAX_DMAQ_SIZE;
+ ring->rx_mini_max_pending = 0;
+ ring->rx_jumbo_max_pending = 0;
+ ring->rx_pending = efx->rxq_entries;
+ ring->tx_pending = efx->txq_entries;
+ ring->rx_mini_pending = 0;
+ ring->rx_jumbo_pending = 0;
+}
+
+static int efx_ethtool_set_ringparam(struct net_device *net_dev,
+ struct ethtool_ringparam *ring)
+{
+ struct efx_nic *efx = netdev_priv(net_dev);
+
+ if (ring->rx_mini_pending || ring->rx_jumbo_pending ||
+ ring->rx_pending > EFX_MAX_DMAQ_SIZE ||
+ ring->tx_pending > EFX_MAX_DMAQ_SIZE)
+ return -EINVAL;
+
+ if (ring->rx_pending < EFX_MIN_RING_SIZE ||
+ ring->tx_pending < EFX_MIN_RING_SIZE) {
+ netif_err(efx, drv, efx->net_dev,
+ "TX and RX queues cannot be smaller than %ld\n",
+ EFX_MIN_RING_SIZE);
+ return -EINVAL;
+ }
+
+ return efx_realloc_channels(efx, ring->rx_pending, ring->tx_pending);
+}
+
static int efx_ethtool_set_pauseparam(struct net_device *net_dev,
struct ethtool_pauseparam *pause)
{
@@ -721,13 +808,15 @@ static int efx_ethtool_set_pauseparam(struct net_device *net_dev,
(pause->autoneg ? EFX_FC_AUTO : 0));
if ((wanted_fc & EFX_FC_TX) && !(wanted_fc & EFX_FC_RX)) {
- EFX_LOG(efx, "Flow control unsupported: tx ON rx OFF\n");
+ netif_dbg(efx, drv, efx->net_dev,
+ "Flow control unsupported: tx ON rx OFF\n");
rc = -EINVAL;
goto out;
}
if ((wanted_fc & EFX_FC_AUTO) && !efx->link_advertising) {
- EFX_LOG(efx, "Autonegotiation is disabled\n");
+ netif_dbg(efx, drv, efx->net_dev,
+ "Autonegotiation is disabled\n");
rc = -EINVAL;
goto out;
}
@@ -758,8 +847,9 @@ static int efx_ethtool_set_pauseparam(struct net_device *net_dev,
(efx->wanted_fc ^ old_fc) & EFX_FC_AUTO) {
rc = efx->phy_op->reconfigure(efx);
if (rc) {
- EFX_ERR(efx, "Unable to advertise requested flow "
- "control setting\n");
+ netif_err(efx, drv, efx->net_dev,
+ "Unable to advertise requested flow "
+ "control setting\n");
goto out;
}
}
@@ -801,7 +891,7 @@ static int efx_ethtool_set_wol(struct net_device *net_dev,
return efx->type->set_wol(efx, wol->wolopts);
}
-extern int efx_ethtool_reset(struct net_device *net_dev, u32 *flags)
+static int efx_ethtool_reset(struct net_device *net_dev, u32 *flags)
{
struct efx_nic *efx = netdev_priv(net_dev);
enum reset_type method;
@@ -830,10 +920,200 @@ extern int efx_ethtool_reset(struct net_device *net_dev, u32 *flags)
return efx_reset(efx, method);
}
+static int
+efx_ethtool_get_rxnfc(struct net_device *net_dev,
+ struct ethtool_rxnfc *info, void *rules __always_unused)
+{
+ struct efx_nic *efx = netdev_priv(net_dev);
+
+ switch (info->cmd) {
+ case ETHTOOL_GRXRINGS:
+ info->data = efx->n_rx_channels;
+ return 0;
+
+ case ETHTOOL_GRXFH: {
+ unsigned min_revision = 0;
+
+ info->data = 0;
+ switch (info->flow_type) {
+ case TCP_V4_FLOW:
+ info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
+ /* fall through */
+ case UDP_V4_FLOW:
+ case SCTP_V4_FLOW:
+ case AH_ESP_V4_FLOW:
+ case IPV4_FLOW:
+ info->data |= RXH_IP_SRC | RXH_IP_DST;
+ min_revision = EFX_REV_FALCON_B0;
+ break;
+ case TCP_V6_FLOW:
+ info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
+ /* fall through */
+ case UDP_V6_FLOW:
+ case SCTP_V6_FLOW:
+ case AH_ESP_V6_FLOW:
+ case IPV6_FLOW:
+ info->data |= RXH_IP_SRC | RXH_IP_DST;
+ min_revision = EFX_REV_SIENA_A0;
+ break;
+ default:
+ break;
+ }
+ if (efx_nic_rev(efx) < min_revision)
+ info->data = 0;
+ return 0;
+ }
+
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int efx_ethtool_set_rx_ntuple(struct net_device *net_dev,
+ struct ethtool_rx_ntuple *ntuple)
+{
+ struct efx_nic *efx = netdev_priv(net_dev);
+ struct ethtool_tcpip4_spec *ip_entry = &ntuple->fs.h_u.tcp_ip4_spec;
+ struct ethtool_tcpip4_spec *ip_mask = &ntuple->fs.m_u.tcp_ip4_spec;
+ struct ethhdr *mac_entry = &ntuple->fs.h_u.ether_spec;
+ struct ethhdr *mac_mask = &ntuple->fs.m_u.ether_spec;
+ struct efx_filter_spec filter;
+
+ /* Range-check action */
+ if (ntuple->fs.action < ETHTOOL_RXNTUPLE_ACTION_CLEAR ||
+ ntuple->fs.action >= (s32)efx->n_rx_channels)
+ return -EINVAL;
+
+ if (~ntuple->fs.data_mask)
+ return -EINVAL;
+
+ switch (ntuple->fs.flow_type) {
+ case TCP_V4_FLOW:
+ case UDP_V4_FLOW:
+ /* Must match all of destination, */
+ if (ip_mask->ip4dst | ip_mask->pdst)
+ return -EINVAL;
+ /* all or none of source, */
+ if ((ip_mask->ip4src | ip_mask->psrc) &&
+ ((__force u32)~ip_mask->ip4src |
+ (__force u16)~ip_mask->psrc))
+ return -EINVAL;
+ /* and nothing else */
+ if ((u8)~ip_mask->tos | (u16)~ntuple->fs.vlan_tag_mask)
+ return -EINVAL;
+ break;
+ case ETHER_FLOW:
+ /* Must match all of destination, */
+ if (!is_zero_ether_addr(mac_mask->h_dest))
+ return -EINVAL;
+ /* all or none of VID, */
+ if (ntuple->fs.vlan_tag_mask != 0xf000 &&
+ ntuple->fs.vlan_tag_mask != 0xffff)
+ return -EINVAL;
+ /* and nothing else */
+ if (!is_broadcast_ether_addr(mac_mask->h_source) ||
+ mac_mask->h_proto != htons(0xffff))
+ return -EINVAL;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ filter.priority = EFX_FILTER_PRI_MANUAL;
+ filter.flags = 0;
+
+ switch (ntuple->fs.flow_type) {
+ case TCP_V4_FLOW:
+ if (!ip_mask->ip4src)
+ efx_filter_set_rx_tcp_full(&filter,
+ htonl(ip_entry->ip4src),
+ htons(ip_entry->psrc),
+ htonl(ip_entry->ip4dst),
+ htons(ip_entry->pdst));
+ else
+ efx_filter_set_rx_tcp_wild(&filter,
+ htonl(ip_entry->ip4dst),
+ htons(ip_entry->pdst));
+ break;
+ case UDP_V4_FLOW:
+ if (!ip_mask->ip4src)
+ efx_filter_set_rx_udp_full(&filter,
+ htonl(ip_entry->ip4src),
+ htons(ip_entry->psrc),
+ htonl(ip_entry->ip4dst),
+ htons(ip_entry->pdst));
+ else
+ efx_filter_set_rx_udp_wild(&filter,
+ htonl(ip_entry->ip4dst),
+ htons(ip_entry->pdst));
+ break;
+ case ETHER_FLOW:
+ if (ntuple->fs.vlan_tag_mask == 0xf000)
+ efx_filter_set_rx_mac_full(&filter,
+ ntuple->fs.vlan_tag & 0xfff,
+ mac_entry->h_dest);
+ else
+ efx_filter_set_rx_mac_wild(&filter, mac_entry->h_dest);
+ break;
+ }
+
+ if (ntuple->fs.action == ETHTOOL_RXNTUPLE_ACTION_CLEAR) {
+ return efx_filter_remove_filter(efx, &filter);
+ } else {
+ if (ntuple->fs.action == ETHTOOL_RXNTUPLE_ACTION_DROP)
+ filter.dmaq_id = 0xfff;
+ else
+ filter.dmaq_id = ntuple->fs.action;
+ return efx_filter_insert_filter(efx, &filter, true);
+ }
+}
+
+static int efx_ethtool_get_rxfh_indir(struct net_device *net_dev,
+ struct ethtool_rxfh_indir *indir)
+{
+ struct efx_nic *efx = netdev_priv(net_dev);
+ size_t copy_size =
+ min_t(size_t, indir->size, ARRAY_SIZE(efx->rx_indir_table));
+
+ if (efx_nic_rev(efx) < EFX_REV_FALCON_B0)
+ return -EOPNOTSUPP;
+
+ indir->size = ARRAY_SIZE(efx->rx_indir_table);
+ memcpy(indir->ring_index, efx->rx_indir_table,
+ copy_size * sizeof(indir->ring_index[0]));
+ return 0;
+}
+
+static int efx_ethtool_set_rxfh_indir(struct net_device *net_dev,
+ const struct ethtool_rxfh_indir *indir)
+{
+ struct efx_nic *efx = netdev_priv(net_dev);
+ size_t i;
+
+ if (efx_nic_rev(efx) < EFX_REV_FALCON_B0)
+ return -EOPNOTSUPP;
+
+ /* Validate size and indices */
+ if (indir->size != ARRAY_SIZE(efx->rx_indir_table))
+ return -EINVAL;
+ for (i = 0; i < ARRAY_SIZE(efx->rx_indir_table); i++)
+ if (indir->ring_index[i] >= efx->n_rx_channels)
+ return -EINVAL;
+
+ memcpy(efx->rx_indir_table, indir->ring_index,
+ sizeof(efx->rx_indir_table));
+ efx_nic_push_rx_indir_table(efx);
+ return 0;
+}
+
const struct ethtool_ops efx_ethtool_ops = {
.get_settings = efx_ethtool_get_settings,
.set_settings = efx_ethtool_set_settings,
.get_drvinfo = efx_ethtool_get_drvinfo,
+ .get_regs_len = efx_ethtool_get_regs_len,
+ .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 = efx_ethtool_get_link,
.get_eeprom_len = efx_ethtool_get_eeprom_len,
@@ -841,6 +1121,8 @@ const struct ethtool_ops efx_ethtool_ops = {
.set_eeprom = efx_ethtool_set_eeprom,
.get_coalesce = efx_ethtool_get_coalesce,
.set_coalesce = efx_ethtool_set_coalesce,
+ .get_ringparam = efx_ethtool_get_ringparam,
+ .set_ringparam = efx_ethtool_set_ringparam,
.get_pauseparam = efx_ethtool_get_pauseparam,
.set_pauseparam = efx_ethtool_set_pauseparam,
.get_rx_csum = efx_ethtool_get_rx_csum,
@@ -854,7 +1136,7 @@ const struct ethtool_ops efx_ethtool_ops = {
/* Need to enable/disable TSO-IPv6 too */
.set_tso = efx_ethtool_set_tso,
.get_flags = ethtool_op_get_flags,
- .set_flags = ethtool_op_set_flags,
+ .set_flags = efx_ethtool_set_flags,
.get_sset_count = efx_ethtool_get_sset_count,
.self_test = efx_ethtool_self_test,
.get_strings = efx_ethtool_get_strings,
@@ -863,4 +1145,8 @@ const struct ethtool_ops efx_ethtool_ops = {
.get_wol = efx_ethtool_get_wol,
.set_wol = efx_ethtool_set_wol,
.reset = efx_ethtool_reset,
+ .get_rxnfc = efx_ethtool_get_rxnfc,
+ .set_rx_ntuple = efx_ethtool_set_rx_ntuple,
+ .get_rxfh_indir = efx_ethtool_get_rxfh_indir,
+ .set_rxfh_indir = efx_ethtool_set_rxfh_indir,
};
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c
index 655b697b45b2..267019bb2b15 100644
--- a/drivers/net/sfc/falcon.c
+++ b/drivers/net/sfc/falcon.c
@@ -159,7 +159,6 @@ irqreturn_t falcon_legacy_interrupt_a1(int irq, void *dev_id)
{
struct efx_nic *efx = dev_id;
efx_oword_t *int_ker = efx->irq_status.addr;
- struct efx_channel *channel;
int syserr;
int queues;
@@ -167,13 +166,15 @@ irqreturn_t falcon_legacy_interrupt_a1(int irq, void *dev_id)
* exit without having touched the hardware.
*/
if (unlikely(EFX_OWORD_IS_ZERO(*int_ker))) {
- EFX_TRACE(efx, "IRQ %d on CPU %d not for me\n", irq,
- raw_smp_processor_id());
+ netif_vdbg(efx, intr, efx->net_dev,
+ "IRQ %d on CPU %d not for me\n", irq,
+ raw_smp_processor_id());
return IRQ_NONE;
}
efx->last_irq_cpu = raw_smp_processor_id();
- EFX_TRACE(efx, "IRQ %d on CPU %d status " EFX_OWORD_FMT "\n",
- irq, raw_smp_processor_id(), EFX_OWORD_VAL(*int_ker));
+ netif_vdbg(efx, intr, efx->net_dev,
+ "IRQ %d on CPU %d status " EFX_OWORD_FMT "\n",
+ irq, raw_smp_processor_id(), EFX_OWORD_VAL(*int_ker));
/* Determine interrupting queues, clear interrupt status
* register and acknowledge the device interrupt.
@@ -192,15 +193,10 @@ irqreturn_t falcon_legacy_interrupt_a1(int irq, void *dev_id)
wmb(); /* Ensure the vector is cleared before interrupt ack */
falcon_irq_ack_a1(efx);
- /* Schedule processing of any interrupting queues */
- channel = &efx->channel[0];
- while (queues) {
- if (queues & 0x01)
- efx_schedule_channel(channel);
- channel++;
- queues >>= 1;
- }
-
+ if (queues & 1)
+ efx_schedule_channel(efx_get_channel(efx, 0));
+ if (queues & 2)
+ efx_schedule_channel(efx_get_channel(efx, 1));
return IRQ_HANDLED;
}
/**************************************************************************
@@ -239,7 +235,8 @@ static int falcon_spi_wait(struct efx_nic *efx)
if (!falcon_spi_poll(efx))
return 0;
if (time_after_eq(jiffies, timeout)) {
- EFX_ERR(efx, "timed out waiting for SPI\n");
+ netif_err(efx, hw, efx->net_dev,
+ "timed out waiting for SPI\n");
return -ETIMEDOUT;
}
schedule_timeout_uninterruptible(1);
@@ -333,9 +330,10 @@ falcon_spi_wait_write(struct efx_nic *efx, const struct efx_spi_device *spi)
if (!(status & SPI_STATUS_NRDY))
return 0;
if (time_after_eq(jiffies, timeout)) {
- EFX_ERR(efx, "SPI write timeout on device %d"
- " last status=0x%02x\n",
- spi->device_id, status);
+ netif_err(efx, hw, efx->net_dev,
+ "SPI write timeout on device %d"
+ " last status=0x%02x\n",
+ spi->device_id, status);
return -ETIMEDOUT;
}
schedule_timeout_uninterruptible(1);
@@ -448,29 +446,19 @@ static void falcon_reset_macs(struct efx_nic *efx)
/* It's not safe to use GLB_CTL_REG to reset the
* macs, so instead use the internal MAC resets
*/
- if (!EFX_IS10G(efx)) {
- EFX_POPULATE_OWORD_1(reg, FRF_AB_GM_SW_RST, 1);
- efx_writeo(efx, &reg, FR_AB_GM_CFG1);
- udelay(1000);
-
- EFX_POPULATE_OWORD_1(reg, FRF_AB_GM_SW_RST, 0);
- efx_writeo(efx, &reg, FR_AB_GM_CFG1);
- udelay(1000);
- return;
- } else {
- EFX_POPULATE_OWORD_1(reg, FRF_AB_XM_CORE_RST, 1);
- efx_writeo(efx, &reg, FR_AB_XM_GLB_CFG);
-
- for (count = 0; count < 10000; count++) {
- efx_reado(efx, &reg, FR_AB_XM_GLB_CFG);
- if (EFX_OWORD_FIELD(reg, FRF_AB_XM_CORE_RST) ==
- 0)
- return;
- udelay(10);
- }
-
- EFX_ERR(efx, "timed out waiting for XMAC core reset\n");
+ EFX_POPULATE_OWORD_1(reg, FRF_AB_XM_CORE_RST, 1);
+ efx_writeo(efx, &reg, FR_AB_XM_GLB_CFG);
+
+ for (count = 0; count < 10000; count++) {
+ efx_reado(efx, &reg, FR_AB_XM_GLB_CFG);
+ if (EFX_OWORD_FIELD(reg, FRF_AB_XM_CORE_RST) ==
+ 0)
+ return;
+ udelay(10);
}
+
+ netif_err(efx, hw, efx->net_dev,
+ "timed out waiting for XMAC core reset\n");
}
/* Mac stats will fail whist the TX fifo is draining */
@@ -492,12 +480,13 @@ static void falcon_reset_macs(struct efx_nic *efx)
if (!EFX_OWORD_FIELD(reg, FRF_AB_RST_XGTX) &&
!EFX_OWORD_FIELD(reg, FRF_AB_RST_XGRX) &&
!EFX_OWORD_FIELD(reg, FRF_AB_RST_EM)) {
- EFX_LOG(efx, "Completed MAC reset after %d loops\n",
- count);
+ netif_dbg(efx, hw, efx->net_dev,
+ "Completed MAC reset after %d loops\n",
+ count);
break;
}
if (count > 20) {
- EFX_ERR(efx, "MAC reset failed\n");
+ netif_err(efx, hw, efx->net_dev, "MAC reset failed\n");
break;
}
count++;
@@ -508,7 +497,6 @@ static void falcon_reset_macs(struct efx_nic *efx)
* are re-enabled by the caller */
efx_writeo(efx, &mac_ctrl, FR_AB_MAC_CTRL);
- /* This can run even when the GMAC is selected */
falcon_setup_xaui(efx);
}
@@ -548,7 +536,9 @@ void falcon_reconfigure_mac_wrapper(struct efx_nic *efx)
{
struct efx_link_state *link_state = &efx->link_state;
efx_oword_t reg;
- int link_speed;
+ int link_speed, isolate;
+
+ isolate = (efx->reset_pending != RESET_TYPE_NONE);
switch (link_state->speed) {
case 10000: link_speed = 3; break;
@@ -570,7 +560,7 @@ void falcon_reconfigure_mac_wrapper(struct efx_nic *efx)
* discarded. */
if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0) {
EFX_SET_OWORD_FIELD(reg, FRF_BB_TXFIFO_DRAIN_EN,
- !link_state->up);
+ !link_state->up || isolate);
}
efx_writeo(efx, &reg, FR_AB_MAC_CTRL);
@@ -584,7 +574,7 @@ void falcon_reconfigure_mac_wrapper(struct efx_nic *efx)
EFX_SET_OWORD_FIELD(reg, FRF_AZ_RX_XOFF_MAC_EN, 1);
/* Unisolate the MAC -> RX */
if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0)
- EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_INGR_EN, 1);
+ EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_INGR_EN, !isolate);
efx_writeo(efx, &reg, FR_AZ_RX_CFG);
}
@@ -625,7 +615,8 @@ static void falcon_stats_complete(struct efx_nic *efx)
rmb(); /* read the done flag before the stats */
efx->mac_op->update_stats(efx);
} else {
- EFX_ERR(efx, "timed out waiting for statistics\n");
+ netif_err(efx, hw, efx->net_dev,
+ "timed out waiting for statistics\n");
}
}
@@ -643,8 +634,6 @@ static void falcon_stats_timer_func(unsigned long context)
spin_unlock(&efx->stats_lock);
}
-static void falcon_switch_mac(struct efx_nic *efx);
-
static bool falcon_loopback_link_poll(struct efx_nic *efx)
{
struct efx_link_state old_state = efx->link_state;
@@ -655,11 +644,7 @@ static bool falcon_loopback_link_poll(struct efx_nic *efx)
efx->link_state.fd = true;
efx->link_state.fc = efx->wanted_fc;
efx->link_state.up = true;
-
- if (efx->loopback_mode == LOOPBACK_GMAC)
- efx->link_state.speed = 1000;
- else
- efx->link_state.speed = 10000;
+ efx->link_state.speed = 10000;
return !efx_link_state_equal(&efx->link_state, &old_state);
}
@@ -682,7 +667,7 @@ static int falcon_reconfigure_port(struct efx_nic *efx)
falcon_stop_nic_stats(efx);
falcon_deconfigure_mac_wrapper(efx);
- falcon_switch_mac(efx);
+ falcon_reset_macs(efx);
efx->phy_op->reconfigure(efx);
rc = efx->mac_op->reconfigure(efx);
@@ -715,16 +700,17 @@ static int falcon_gmii_wait(struct efx_nic *efx)
if (EFX_OWORD_FIELD(md_stat, FRF_AB_MD_BSY) == 0) {
if (EFX_OWORD_FIELD(md_stat, FRF_AB_MD_LNFL) != 0 ||
EFX_OWORD_FIELD(md_stat, FRF_AB_MD_BSERR) != 0) {
- EFX_ERR(efx, "error from GMII access "
- EFX_OWORD_FMT"\n",
- EFX_OWORD_VAL(md_stat));
+ netif_err(efx, hw, efx->net_dev,
+ "error from GMII access "
+ EFX_OWORD_FMT"\n",
+ EFX_OWORD_VAL(md_stat));
return -EIO;
}
return 0;
}
udelay(10);
}
- EFX_ERR(efx, "timed out waiting for GMII\n");
+ netif_err(efx, hw, efx->net_dev, "timed out waiting for GMII\n");
return -ETIMEDOUT;
}
@@ -736,7 +722,8 @@ static int falcon_mdio_write(struct net_device *net_dev,
efx_oword_t reg;
int rc;
- EFX_REGDUMP(efx, "writing MDIO %d register %d.%d with 0x%04x\n",
+ netif_vdbg(efx, hw, efx->net_dev,
+ "writing MDIO %d register %d.%d with 0x%04x\n",
prtad, devad, addr, value);
mutex_lock(&efx->mdio_lock);
@@ -810,8 +797,9 @@ static int falcon_mdio_read(struct net_device *net_dev,
if (rc == 0) {
efx_reado(efx, &reg, FR_AB_MD_RXD);
rc = EFX_OWORD_FIELD(reg, FRF_AB_MD_RXD);
- EFX_REGDUMP(efx, "read from MDIO %d register %d.%d, got %04x\n",
- prtad, devad, addr, rc);
+ netif_vdbg(efx, hw, efx->net_dev,
+ "read from MDIO %d register %d.%d, got %04x\n",
+ prtad, devad, addr, rc);
} else {
/* Abort the read operation */
EFX_POPULATE_OWORD_2(reg,
@@ -819,8 +807,9 @@ static int falcon_mdio_read(struct net_device *net_dev,
FRF_AB_MD_GC, 1);
efx_writeo(efx, &reg, FR_AB_MD_CS);
- EFX_LOG(efx, "read from MDIO %d register %d.%d, got error %d\n",
- prtad, devad, addr, rc);
+ netif_dbg(efx, hw, efx->net_dev,
+ "read from MDIO %d register %d.%d, got error %d\n",
+ prtad, devad, addr, rc);
}
out:
@@ -828,75 +817,26 @@ out:
return rc;
}
-static void falcon_clock_mac(struct efx_nic *efx)
-{
- unsigned strap_val;
- efx_oword_t nic_stat;
-
- /* Configure the NIC generated MAC clock correctly */
- efx_reado(efx, &nic_stat, FR_AB_NIC_STAT);
- strap_val = EFX_IS10G(efx) ? 5 : 3;
- if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0) {
- EFX_SET_OWORD_FIELD(nic_stat, FRF_BB_EE_STRAP_EN, 1);
- EFX_SET_OWORD_FIELD(nic_stat, FRF_BB_EE_STRAP, strap_val);
- efx_writeo(efx, &nic_stat, FR_AB_NIC_STAT);
- } else {
- /* Falcon A1 does not support 1G/10G speed switching
- * and must not be used with a PHY that does. */
- BUG_ON(EFX_OWORD_FIELD(nic_stat, FRF_AB_STRAP_PINS) !=
- strap_val);
- }
-}
-
-static void falcon_switch_mac(struct efx_nic *efx)
-{
- struct efx_mac_operations *old_mac_op = efx->mac_op;
- struct falcon_nic_data *nic_data = efx->nic_data;
- unsigned int stats_done_offset;
-
- WARN_ON(!mutex_is_locked(&efx->mac_lock));
- WARN_ON(nic_data->stats_disable_count == 0);
-
- efx->mac_op = (EFX_IS10G(efx) ?
- &falcon_xmac_operations : &falcon_gmac_operations);
-
- if (EFX_IS10G(efx))
- stats_done_offset = XgDmaDone_offset;
- else
- stats_done_offset = GDmaDone_offset;
- nic_data->stats_dma_done = efx->stats_buffer.addr + stats_done_offset;
-
- if (old_mac_op == efx->mac_op)
- return;
-
- falcon_clock_mac(efx);
-
- EFX_LOG(efx, "selected %cMAC\n", EFX_IS10G(efx) ? 'X' : 'G');
- /* Not all macs support a mac-level link state */
- efx->xmac_poll_required = false;
- falcon_reset_macs(efx);
-}
-
/* This call is responsible for hooking in the MAC and PHY operations */
static int falcon_probe_port(struct efx_nic *efx)
{
+ struct falcon_nic_data *nic_data = efx->nic_data;
int rc;
switch (efx->phy_type) {
case PHY_TYPE_SFX7101:
efx->phy_op = &falcon_sfx7101_phy_ops;
break;
- case PHY_TYPE_SFT9001A:
- case PHY_TYPE_SFT9001B:
- efx->phy_op = &falcon_sft9001_phy_ops;
- break;
case PHY_TYPE_QT2022C2:
case PHY_TYPE_QT2025C:
efx->phy_op = &falcon_qt202x_phy_ops;
break;
+ case PHY_TYPE_TXC43128:
+ efx->phy_op = &falcon_txc_phy_ops;
+ break;
default:
- EFX_ERR(efx, "Unknown PHY type %d\n",
- efx->phy_type);
+ netif_err(efx, probe, efx->net_dev, "Unknown PHY type %d\n",
+ efx->phy_type);
return -ENODEV;
}
@@ -924,10 +864,12 @@ static int falcon_probe_port(struct efx_nic *efx)
FALCON_MAC_STATS_SIZE);
if (rc)
return rc;
- EFX_LOG(efx, "stats buffer at %llx (virt %p phys %llx)\n",
- (u64)efx->stats_buffer.dma_addr,
- efx->stats_buffer.addr,
- (u64)virt_to_phys(efx->stats_buffer.addr));
+ netif_dbg(efx, probe, efx->net_dev,
+ "stats buffer at %llx (virt %p phys %llx)\n",
+ (u64)efx->stats_buffer.dma_addr,
+ efx->stats_buffer.addr,
+ (u64)virt_to_phys(efx->stats_buffer.addr));
+ nic_data->stats_dma_done = efx->stats_buffer.addr + XgDmaDone_offset;
return 0;
}
@@ -967,8 +909,8 @@ falcon_read_nvram(struct efx_nic *efx, struct falcon_nvconfig *nvconfig_out)
rc = falcon_spi_read(efx, spi, 0, FALCON_NVCONFIG_END, NULL, region);
mutex_unlock(&efx->spi_lock);
if (rc) {
- EFX_ERR(efx, "Failed to read %s\n",
- efx->spi_flash ? "flash" : "EEPROM");
+ netif_err(efx, hw, efx->net_dev, "Failed to read %s\n",
+ efx->spi_flash ? "flash" : "EEPROM");
rc = -EIO;
goto out;
}
@@ -978,11 +920,13 @@ falcon_read_nvram(struct efx_nic *efx, struct falcon_nvconfig *nvconfig_out)
rc = -EINVAL;
if (magic_num != FALCON_NVCONFIG_BOARD_MAGIC_NUM) {
- EFX_ERR(efx, "NVRAM bad magic 0x%x\n", magic_num);
+ netif_err(efx, hw, efx->net_dev,
+ "NVRAM bad magic 0x%x\n", magic_num);
goto out;
}
if (struct_ver < 2) {
- EFX_ERR(efx, "NVRAM has ancient version 0x%x\n", struct_ver);
+ netif_err(efx, hw, efx->net_dev,
+ "NVRAM has ancient version 0x%x\n", struct_ver);
goto out;
} else if (struct_ver < 4) {
word = &nvconfig->board_magic_num;
@@ -995,7 +939,8 @@ falcon_read_nvram(struct efx_nic *efx, struct falcon_nvconfig *nvconfig_out)
csum += le16_to_cpu(*word);
if (~csum & 0xffff) {
- EFX_ERR(efx, "NVRAM has incorrect checksum\n");
+ netif_err(efx, hw, efx->net_dev,
+ "NVRAM has incorrect checksum\n");
goto out;
}
@@ -1073,22 +1018,25 @@ static int falcon_reset_hw(struct efx_nic *efx, enum reset_type method)
efx_oword_t glb_ctl_reg_ker;
int rc;
- EFX_LOG(efx, "performing %s hardware reset\n", RESET_TYPE(method));
+ netif_dbg(efx, hw, efx->net_dev, "performing %s hardware reset\n",
+ RESET_TYPE(method));
/* Initiate device reset */
if (method == RESET_TYPE_WORLD) {
rc = pci_save_state(efx->pci_dev);
if (rc) {
- EFX_ERR(efx, "failed to backup PCI state of primary "
- "function prior to hardware reset\n");
+ netif_err(efx, drv, efx->net_dev,
+ "failed to backup PCI state of primary "
+ "function prior to hardware reset\n");
goto fail1;
}
if (efx_nic_is_dual_func(efx)) {
rc = pci_save_state(nic_data->pci_dev2);
if (rc) {
- EFX_ERR(efx, "failed to backup PCI state of "
- "secondary function prior to "
- "hardware reset\n");
+ netif_err(efx, drv, efx->net_dev,
+ "failed to backup PCI state of "
+ "secondary function prior to "
+ "hardware reset\n");
goto fail2;
}
}
@@ -1113,7 +1061,7 @@ static int falcon_reset_hw(struct efx_nic *efx, enum reset_type method)
}
efx_writeo(efx, &glb_ctl_reg_ker, FR_AB_GLB_CTL);
- EFX_LOG(efx, "waiting for hardware reset\n");
+ netif_dbg(efx, hw, efx->net_dev, "waiting for hardware reset\n");
schedule_timeout_uninterruptible(HZ / 20);
/* Restore PCI configuration if needed */
@@ -1121,28 +1069,32 @@ static int falcon_reset_hw(struct efx_nic *efx, enum reset_type method)
if (efx_nic_is_dual_func(efx)) {
rc = pci_restore_state(nic_data->pci_dev2);
if (rc) {
- EFX_ERR(efx, "failed to restore PCI config for "
- "the secondary function\n");
+ netif_err(efx, drv, efx->net_dev,
+ "failed to restore PCI config for "
+ "the secondary function\n");
goto fail3;
}
}
rc = pci_restore_state(efx->pci_dev);
if (rc) {
- EFX_ERR(efx, "failed to restore PCI config for the "
- "primary function\n");
+ netif_err(efx, drv, efx->net_dev,
+ "failed to restore PCI config for the "
+ "primary function\n");
goto fail4;
}
- EFX_LOG(efx, "successfully restored PCI config\n");
+ netif_dbg(efx, drv, efx->net_dev,
+ "successfully restored PCI config\n");
}
/* Assert that reset complete */
efx_reado(efx, &glb_ctl_reg_ker, FR_AB_GLB_CTL);
if (EFX_OWORD_FIELD(glb_ctl_reg_ker, FRF_AB_SWRST) != 0) {
rc = -ETIMEDOUT;
- EFX_ERR(efx, "timed out waiting for hardware reset\n");
+ netif_err(efx, hw, efx->net_dev,
+ "timed out waiting for hardware reset\n");
goto fail5;
}
- EFX_LOG(efx, "hardware reset complete\n");
+ netif_dbg(efx, hw, efx->net_dev, "hardware reset complete\n");
return 0;
@@ -1165,8 +1117,9 @@ static void falcon_monitor(struct efx_nic *efx)
rc = falcon_board(efx)->type->monitor(efx);
if (rc) {
- EFX_ERR(efx, "Board sensor %s; shutting down PHY\n",
- (rc == -ERANGE) ? "reported fault" : "failed");
+ netif_err(efx, hw, efx->net_dev,
+ "Board sensor %s; shutting down PHY\n",
+ (rc == -ERANGE) ? "reported fault" : "failed");
efx->phy_mode |= PHY_MODE_LOW_POWER;
rc = __efx_reconfigure_port(efx);
WARN_ON(rc);
@@ -1181,7 +1134,7 @@ static void falcon_monitor(struct efx_nic *efx)
falcon_stop_nic_stats(efx);
falcon_deconfigure_mac_wrapper(efx);
- falcon_switch_mac(efx);
+ falcon_reset_macs(efx);
rc = efx->mac_op->reconfigure(efx);
BUG_ON(rc);
@@ -1190,8 +1143,7 @@ static void falcon_monitor(struct efx_nic *efx)
efx_link_status_changed(efx);
}
- if (EFX_IS10G(efx))
- falcon_poll_xmac(efx);
+ falcon_poll_xmac(efx);
}
/* Zeroes out the SRAM contents. This routine must be called in
@@ -1217,7 +1169,8 @@ static int falcon_reset_sram(struct efx_nic *efx)
/* Wait for SRAM reset to complete */
count = 0;
do {
- EFX_LOG(efx, "waiting for SRAM reset (attempt %d)...\n", count);
+ netif_dbg(efx, hw, efx->net_dev,
+ "waiting for SRAM reset (attempt %d)...\n", count);
/* SRAM reset is slow; expect around 16ms */
schedule_timeout_uninterruptible(HZ / 50);
@@ -1225,13 +1178,14 @@ static int falcon_reset_sram(struct efx_nic *efx)
/* Check for reset complete */
efx_reado(efx, &srm_cfg_reg_ker, FR_AZ_SRM_CFG);
if (!EFX_OWORD_FIELD(srm_cfg_reg_ker, FRF_AZ_SRM_INIT_EN)) {
- EFX_LOG(efx, "SRAM reset complete\n");
+ netif_dbg(efx, hw, efx->net_dev,
+ "SRAM reset complete\n");
return 0;
}
} while (++count < 20); /* wait upto 0.4 sec */
- EFX_ERR(efx, "timed out waiting for SRAM reset\n");
+ netif_err(efx, hw, efx->net_dev, "timed out waiting for SRAM reset\n");
return -ETIMEDOUT;
}
@@ -1290,7 +1244,8 @@ static int falcon_probe_nvconfig(struct efx_nic *efx)
rc = falcon_read_nvram(efx, nvconfig);
if (rc == -EINVAL) {
- EFX_ERR(efx, "NVRAM is invalid therefore using defaults\n");
+ netif_err(efx, probe, efx->net_dev,
+ "NVRAM is invalid therefore using defaults\n");
efx->phy_type = PHY_TYPE_NONE;
efx->mdio.prtad = MDIO_PRTAD_NONE;
board_rev = 0;
@@ -1324,7 +1279,8 @@ static int falcon_probe_nvconfig(struct efx_nic *efx)
/* Read the MAC addresses */
memcpy(efx->mac_address, nvconfig->mac_address[0], ETH_ALEN);
- EFX_LOG(efx, "PHY is %d phy_id %d\n", efx->phy_type, efx->mdio.prtad);
+ netif_dbg(efx, probe, efx->net_dev, "PHY is %d phy_id %d\n",
+ efx->phy_type, efx->mdio.prtad);
rc = falcon_probe_board(efx, board_rev);
if (rc)
@@ -1353,14 +1309,16 @@ static void falcon_probe_spi_devices(struct efx_nic *efx)
if (EFX_OWORD_FIELD(gpio_ctl, FRF_AB_GPIO3_PWRUP_VALUE)) {
boot_dev = (EFX_OWORD_FIELD(nic_stat, FRF_AB_SF_PRST) ?
FFE_AB_SPI_DEVICE_FLASH : FFE_AB_SPI_DEVICE_EEPROM);
- EFX_LOG(efx, "Booted from %s\n",
- boot_dev == FFE_AB_SPI_DEVICE_FLASH ? "flash" : "EEPROM");
+ netif_dbg(efx, probe, efx->net_dev, "Booted from %s\n",
+ boot_dev == FFE_AB_SPI_DEVICE_FLASH ?
+ "flash" : "EEPROM");
} else {
/* Disable VPD and set clock dividers to safe
* values for initial programming. */
boot_dev = -1;
- EFX_LOG(efx, "Booted from internal ASIC settings;"
- " setting SPI config\n");
+ netif_dbg(efx, probe, efx->net_dev,
+ "Booted from internal ASIC settings;"
+ " setting SPI config\n");
EFX_POPULATE_OWORD_3(ee_vpd_cfg, FRF_AB_EE_VPD_EN, 0,
/* 125 MHz / 7 ~= 20 MHz */
FRF_AB_EE_SF_CLOCK_DIV, 7,
@@ -1394,7 +1352,8 @@ static int falcon_probe_nic(struct efx_nic *efx)
rc = -ENODEV;
if (efx_nic_fpga_ver(efx) != 0) {
- EFX_ERR(efx, "Falcon FPGA not supported\n");
+ netif_err(efx, probe, efx->net_dev,
+ "Falcon FPGA not supported\n");
goto fail1;
}
@@ -1404,16 +1363,19 @@ static int falcon_probe_nic(struct efx_nic *efx)
u8 pci_rev = efx->pci_dev->revision;
if ((pci_rev == 0xff) || (pci_rev == 0)) {
- EFX_ERR(efx, "Falcon rev A0 not supported\n");
+ netif_err(efx, probe, efx->net_dev,
+ "Falcon rev A0 not supported\n");
goto fail1;
}
efx_reado(efx, &nic_stat, FR_AB_NIC_STAT);
if (EFX_OWORD_FIELD(nic_stat, FRF_AB_STRAP_10G) == 0) {
- EFX_ERR(efx, "Falcon rev A1 1G not supported\n");
+ netif_err(efx, probe, efx->net_dev,
+ "Falcon rev A1 1G not supported\n");
goto fail1;
}
if (EFX_OWORD_FIELD(nic_stat, FRF_AA_STRAP_PCIE) == 0) {
- EFX_ERR(efx, "Falcon rev A1 PCI-X not supported\n");
+ netif_err(efx, probe, efx->net_dev,
+ "Falcon rev A1 PCI-X not supported\n");
goto fail1;
}
@@ -1427,7 +1389,8 @@ static int falcon_probe_nic(struct efx_nic *efx)
}
}
if (!nic_data->pci_dev2) {
- EFX_ERR(efx, "failed to find secondary function\n");
+ netif_err(efx, probe, efx->net_dev,
+ "failed to find secondary function\n");
rc = -ENODEV;
goto fail2;
}
@@ -1436,7 +1399,7 @@ static int falcon_probe_nic(struct efx_nic *efx)
/* Now we can reset the NIC */
rc = falcon_reset_hw(efx, RESET_TYPE_ALL);
if (rc) {
- EFX_ERR(efx, "failed to reset NIC\n");
+ netif_err(efx, probe, efx->net_dev, "failed to reset NIC\n");
goto fail3;
}
@@ -1446,9 +1409,11 @@ static int falcon_probe_nic(struct efx_nic *efx)
goto fail4;
BUG_ON(efx->irq_status.dma_addr & 0x0f);
- EFX_LOG(efx, "INT_KER at %llx (virt %p phys %llx)\n",
- (u64)efx->irq_status.dma_addr,
- efx->irq_status.addr, (u64)virt_to_phys(efx->irq_status.addr));
+ netif_dbg(efx, probe, efx->net_dev,
+ "INT_KER at %llx (virt %p phys %llx)\n",
+ (u64)efx->irq_status.dma_addr,
+ efx->irq_status.addr,
+ (u64)virt_to_phys(efx->irq_status.addr));
falcon_probe_spi_devices(efx);
@@ -1472,7 +1437,8 @@ static int falcon_probe_nic(struct efx_nic *efx)
rc = falcon_board(efx)->type->init(efx);
if (rc) {
- EFX_ERR(efx, "failed to initialise board\n");
+ netif_err(efx, probe, efx->net_dev,
+ "failed to initialise board\n");
goto fail6;
}
@@ -1542,6 +1508,13 @@ static void falcon_init_rx_cfg(struct efx_nic *efx)
EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_XON_TX_TH, ctrl_xon_thr);
EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_XOFF_TX_TH, ctrl_xoff_thr);
EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_INGR_EN, 1);
+
+ /* Enable hash insertion. This is broken for the
+ * 'Falcon' hash so also select Toeplitz TCP/IPv4 and
+ * IPv4 hashes. */
+ EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_HASH_INSRT_HDR, 1);
+ EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_HASH_ALG, 1);
+ EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_IP_HASH, 1);
}
/* Always enable XOFF signal from RX FIFO. We enable
* or disable transmission of pause frames at the MAC. */
@@ -1563,16 +1536,6 @@ static int falcon_init_nic(struct efx_nic *efx)
EFX_SET_OWORD_FIELD(temp, FRF_AB_ONCHIP_SRAM, 1);
efx_writeo(efx, &temp, FR_AB_NIC_STAT);
- /* Set the source of the GMAC clock */
- if (efx_nic_rev(efx) == EFX_REV_FALCON_B0) {
- efx_reado(efx, &temp, FR_AB_GPIO_CTL);
- EFX_SET_OWORD_FIELD(temp, FRF_AB_USE_NIC_CLK, true);
- efx_writeo(efx, &temp, FR_AB_GPIO_CTL);
- }
-
- /* Select the correct MAC */
- falcon_clock_mac(efx);
-
rc = falcon_reset_sram(efx);
if (rc)
return rc;
@@ -1615,8 +1578,12 @@ static int falcon_init_nic(struct efx_nic *efx)
falcon_init_rx_cfg(efx);
- /* Set destination of both TX and RX Flush events */
if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0) {
+ /* Set hash key for IPv4 */
+ memcpy(&temp, efx->rx_hash_key, sizeof(temp));
+ efx_writeo(efx, &temp, FR_BZ_RX_RSS_TKEY);
+
+ /* Set destination of both TX and RX Flush events */
EFX_POPULATE_OWORD_1(temp, FRF_BZ_FLS_EVQ_ID, 0);
efx_writeo(efx, &temp, FR_BZ_DP_CTRL);
}
@@ -1821,6 +1788,7 @@ struct efx_nic_type falcon_b0_nic_type = {
.evq_ptr_tbl_base = FR_BZ_EVQ_PTR_TBL,
.evq_rptr_tbl_base = FR_BZ_EVQ_RPTR,
.max_dma_mask = DMA_BIT_MASK(FSF_AZ_TX_KER_BUF_ADDR_WIDTH),
+ .rx_buffer_hash_size = 0x10,
.rx_buffer_padding = 0,
.max_interrupt_mode = EFX_INT_MODE_MSIX,
.phys_addr_channels = 32, /* Hardware limit is 64, but the legacy
@@ -1828,7 +1796,7 @@ struct efx_nic_type falcon_b0_nic_type = {
* channels */
.tx_dc_base = 0x130000,
.rx_dc_base = 0x100000,
- .offload_features = NETIF_F_IP_CSUM,
+ .offload_features = NETIF_F_IP_CSUM | NETIF_F_RXHASH | NETIF_F_NTUPLE,
.reset_world_flags = ETH_RESET_IRQ,
};
diff --git a/drivers/net/sfc/falcon_boards.c b/drivers/net/sfc/falcon_boards.c
index c7a933a3292e..cfc6a5b5a477 100644
--- a/drivers/net/sfc/falcon_boards.c
+++ b/drivers/net/sfc/falcon_boards.c
@@ -26,7 +26,7 @@
/* Board types */
#define FALCON_BOARD_SFE4001 0x01
#define FALCON_BOARD_SFE4002 0x02
-#define FALCON_BOARD_SFN4111T 0x51
+#define FALCON_BOARD_SFE4003 0x03
#define FALCON_BOARD_SFN4112F 0x52
/* Board temperature is about 15°C above ambient when air flow is
@@ -106,12 +106,17 @@ static int efx_check_lm87(struct efx_nic *efx, unsigned mask)
alarms1 &= mask;
alarms2 &= mask >> 8;
if (alarms1 || alarms2) {
- EFX_ERR(efx,
- "LM87 detected a hardware failure (status %02x:%02x)"
- "%s%s\n",
- alarms1, alarms2,
- (alarms1 & LM87_ALARM_TEMP_INT) ? " INTERNAL" : "",
- (alarms1 & LM87_ALARM_TEMP_EXT1) ? " EXTERNAL" : "");
+ netif_err(efx, hw, efx->net_dev,
+ "LM87 detected a hardware failure (status %02x:%02x)"
+ "%s%s%s\n",
+ alarms1, alarms2,
+ (alarms1 & LM87_ALARM_TEMP_INT) ?
+ "; board is overheating" : "",
+ (alarms1 & LM87_ALARM_TEMP_EXT1) ?
+ "; controller is overheating" : "",
+ (alarms1 & ~(LM87_ALARM_TEMP_INT | LM87_ALARM_TEMP_EXT1)
+ || alarms2) ?
+ "; electrical fault" : "");
return -ERANGE;
}
@@ -137,17 +142,17 @@ static inline int efx_check_lm87(struct efx_nic *efx, unsigned mask)
#endif /* CONFIG_SENSORS_LM87 */
/*****************************************************************************
- * Support for the SFE4001 and SFN4111T NICs.
+ * Support for the SFE4001 NIC.
*
* The SFE4001 does not power-up fully at reset due to its high power
* consumption. We control its power via a PCA9539 I/O expander.
- * Both boards have a MAX6647 temperature monitor which we expose to
+ * It also has a MAX6647 temperature monitor which we expose to
* the lm90 driver.
*
* This also provides minimal support for reflashing the PHY, which is
* initiated by resetting it with the FLASH_CFG_1 pin pulled down.
* On SFE4001 rev A2 and later this is connected to the 3V3X output of
- * the IO-expander; on the SFN4111T it is connected to Falcon's GPIO3.
+ * the IO-expander.
* We represent reflash mode as PHY_MODE_SPECIAL and make it mutually
* exclusive with the network device being open.
*/
@@ -243,7 +248,7 @@ static int sfe4001_poweron(struct efx_nic *efx)
(0 << P0_EN_3V3X_LBN) | (0 << P0_EN_5V_LBN) |
(0 << P0_EN_1V0X_LBN));
if (rc != out) {
- EFX_INFO(efx, "power-cycling PHY\n");
+ netif_info(efx, hw, efx->net_dev, "power-cycling PHY\n");
rc = i2c_smbus_write_byte_data(ioexp_client, P0_OUT, out);
if (rc)
goto fail_on;
@@ -269,7 +274,8 @@ static int sfe4001_poweron(struct efx_nic *efx)
if (rc)
goto fail_on;
- EFX_INFO(efx, "waiting for DSP boot (attempt %d)...\n", i);
+ netif_info(efx, hw, efx->net_dev,
+ "waiting for DSP boot (attempt %d)...\n", i);
/* In flash config mode, DSP does not turn on AFE, so
* just wait 1 second.
@@ -291,41 +297,13 @@ static int sfe4001_poweron(struct efx_nic *efx)
}
}
- EFX_INFO(efx, "timed out waiting for DSP boot\n");
+ netif_info(efx, hw, efx->net_dev, "timed out waiting for DSP boot\n");
rc = -ETIMEDOUT;
fail_on:
sfe4001_poweroff(efx);
return rc;
}
-static int sfn4111t_reset(struct efx_nic *efx)
-{
- struct falcon_board *board = falcon_board(efx);
- efx_oword_t reg;
-
- /* GPIO 3 and the GPIO register are shared with I2C, so block that */
- i2c_lock_adapter(&board->i2c_adap);
-
- /* Pull RST_N (GPIO 2) low then let it up again, setting the
- * FLASH_CFG_1 strap (GPIO 3) appropriately. Only change the
- * output enables; the output levels should always be 0 (low)
- * and we rely on external pull-ups. */
- efx_reado(efx, &reg, FR_AB_GPIO_CTL);
- EFX_SET_OWORD_FIELD(reg, FRF_AB_GPIO2_OEN, true);
- efx_writeo(efx, &reg, FR_AB_GPIO_CTL);
- msleep(1000);
- EFX_SET_OWORD_FIELD(reg, FRF_AB_GPIO2_OEN, false);
- EFX_SET_OWORD_FIELD(reg, FRF_AB_GPIO3_OEN,
- !!(efx->phy_mode & PHY_MODE_SPECIAL));
- efx_writeo(efx, &reg, FR_AB_GPIO_CTL);
- msleep(1);
-
- i2c_unlock_adapter(&board->i2c_adap);
-
- ssleep(1);
- return 0;
-}
-
static ssize_t show_phy_flash_cfg(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -357,10 +335,7 @@ static ssize_t set_phy_flash_cfg(struct device *dev,
efx->phy_mode = new_mode;
if (new_mode & PHY_MODE_SPECIAL)
falcon_stop_nic_stats(efx);
- if (falcon_board(efx)->type->id == FALCON_BOARD_SFE4001)
- err = sfe4001_poweron(efx);
- else
- err = sfn4111t_reset(efx);
+ err = sfe4001_poweron(efx);
if (!err)
err = efx_reconfigure_port(efx);
if (!(new_mode & PHY_MODE_SPECIAL))
@@ -377,7 +352,7 @@ static void sfe4001_fini(struct efx_nic *efx)
{
struct falcon_board *board = falcon_board(efx);
- EFX_INFO(efx, "%s\n", __func__);
+ netif_info(efx, drv, efx->net_dev, "%s\n", __func__);
device_remove_file(&efx->pci_dev->dev, &dev_attr_phy_flash_cfg);
sfe4001_poweroff(efx);
@@ -461,7 +436,7 @@ static int sfe4001_init(struct efx_nic *efx)
if (rc)
goto fail_on;
- EFX_INFO(efx, "PHY is powered on\n");
+ netif_info(efx, hw, efx->net_dev, "PHY is powered on\n");
return 0;
fail_on:
@@ -473,83 +448,6 @@ fail_hwmon:
return rc;
}
-static int sfn4111t_check_hw(struct efx_nic *efx)
-{
- s32 status;
-
- /* If XAUI link is up then do not monitor */
- if (EFX_WORKAROUND_7884(efx) && !efx->xmac_poll_required)
- return 0;
-
- /* Test LHIGH, RHIGH, FAULT, EOT and IOT alarms */
- status = i2c_smbus_read_byte_data(falcon_board(efx)->hwmon_client,
- MAX664X_REG_RSL);
- if (status < 0)
- return -EIO;
- if (status & 0x57)
- return -ERANGE;
- return 0;
-}
-
-static void sfn4111t_fini(struct efx_nic *efx)
-{
- EFX_INFO(efx, "%s\n", __func__);
-
- device_remove_file(&efx->pci_dev->dev, &dev_attr_phy_flash_cfg);
- i2c_unregister_device(falcon_board(efx)->hwmon_client);
-}
-
-static struct i2c_board_info sfn4111t_a0_hwmon_info = {
- I2C_BOARD_INFO("max6647", 0x4e),
-};
-
-static struct i2c_board_info sfn4111t_r5_hwmon_info = {
- I2C_BOARD_INFO("max6646", 0x4d),
-};
-
-static void sfn4111t_init_phy(struct efx_nic *efx)
-{
- if (!(efx->phy_mode & PHY_MODE_SPECIAL)) {
- if (sft9001_wait_boot(efx) != -EINVAL)
- return;
-
- efx->phy_mode = PHY_MODE_SPECIAL;
- falcon_stop_nic_stats(efx);
- }
-
- sfn4111t_reset(efx);
- sft9001_wait_boot(efx);
-}
-
-static int sfn4111t_init(struct efx_nic *efx)
-{
- struct falcon_board *board = falcon_board(efx);
- int rc;
-
- board->hwmon_client =
- i2c_new_device(&board->i2c_adap,
- (board->minor < 5) ?
- &sfn4111t_a0_hwmon_info :
- &sfn4111t_r5_hwmon_info);
- if (!board->hwmon_client)
- return -EIO;
-
- rc = device_create_file(&efx->pci_dev->dev, &dev_attr_phy_flash_cfg);
- if (rc)
- goto fail_hwmon;
-
- if (efx->phy_mode & PHY_MODE_SPECIAL)
- /* PHY may not generate a 156.25 MHz clock and MAC
- * stats fetch will fail. */
- falcon_stop_nic_stats(efx);
-
- return 0;
-
-fail_hwmon:
- i2c_unregister_device(board->hwmon_client);
- return rc;
-}
-
/*****************************************************************************
* Support for the SFE4002
*
@@ -685,6 +583,75 @@ static int sfn4112f_init(struct efx_nic *efx)
return efx_init_lm87(efx, &sfn4112f_hwmon_info, sfn4112f_lm87_regs);
}
+/*****************************************************************************
+ * Support for the SFE4003
+ *
+ */
+static u8 sfe4003_lm87_channel = 0x03; /* use AIN not FAN inputs */
+
+static const u8 sfe4003_lm87_regs[] = {
+ LM87_IN_LIMITS(0, 0x67, 0x7f), /* 2.5V: 1.5V +/- 10% */
+ LM87_IN_LIMITS(1, 0x4c, 0x5e), /* Vccp1: 1.2V +/- 10% */
+ LM87_IN_LIMITS(2, 0xac, 0xd4), /* 3.3V: 3.3V +/- 10% */
+ LM87_IN_LIMITS(4, 0xac, 0xe0), /* 12V: 10.8-14V */
+ LM87_IN_LIMITS(5, 0x3f, 0x4f), /* Vccp2: 1.0V +/- 10% */
+ LM87_TEMP_INT_LIMITS(0, 70 + FALCON_BOARD_TEMP_BIAS),
+ 0
+};
+
+static struct i2c_board_info sfe4003_hwmon_info = {
+ I2C_BOARD_INFO("lm87", 0x2e),
+ .platform_data = &sfe4003_lm87_channel,
+};
+
+/* Board-specific LED info. */
+#define SFE4003_RED_LED_GPIO 11
+#define SFE4003_LED_ON 1
+#define SFE4003_LED_OFF 0
+
+static void sfe4003_set_id_led(struct efx_nic *efx, enum efx_led_mode mode)
+{
+ struct falcon_board *board = falcon_board(efx);
+
+ /* The LEDs were not wired to GPIOs before A3 */
+ if (board->minor < 3 && board->major == 0)
+ return;
+
+ falcon_txc_set_gpio_val(
+ efx, SFE4003_RED_LED_GPIO,
+ (mode == EFX_LED_ON) ? SFE4003_LED_ON : SFE4003_LED_OFF);
+}
+
+static void sfe4003_init_phy(struct efx_nic *efx)
+{
+ struct falcon_board *board = falcon_board(efx);
+
+ /* The LEDs were not wired to GPIOs before A3 */
+ if (board->minor < 3 && board->major == 0)
+ return;
+
+ falcon_txc_set_gpio_dir(efx, SFE4003_RED_LED_GPIO, TXC_GPIO_DIR_OUTPUT);
+ falcon_txc_set_gpio_val(efx, SFE4003_RED_LED_GPIO, SFE4003_LED_OFF);
+}
+
+static int sfe4003_check_hw(struct efx_nic *efx)
+{
+ struct falcon_board *board = falcon_board(efx);
+
+ /* A0/A1/A2 board rev. 4003s report a temperature fault the whole time
+ * (bad sensor) so we mask it out. */
+ unsigned alarm_mask =
+ (board->major == 0 && board->minor <= 2) ?
+ ~LM87_ALARM_TEMP_EXT1 : ~0;
+
+ return efx_check_lm87(efx, alarm_mask);
+}
+
+static int sfe4003_init(struct efx_nic *efx)
+{
+ return efx_init_lm87(efx, &sfe4003_hwmon_info, sfe4003_lm87_regs);
+}
+
static const struct falcon_board_type board_types[] = {
{
.id = FALCON_BOARD_SFE4001,
@@ -707,14 +674,14 @@ static const struct falcon_board_type board_types[] = {
.monitor = sfe4002_check_hw,
},
{
- .id = FALCON_BOARD_SFN4111T,
- .ref_model = "SFN4111T",
- .gen_type = "100/1000/10GBASE-T adapter",
- .init = sfn4111t_init,
- .init_phy = sfn4111t_init_phy,
- .fini = sfn4111t_fini,
- .set_id_led = tenxpress_set_id_led,
- .monitor = sfn4111t_check_hw,
+ .id = FALCON_BOARD_SFE4003,
+ .ref_model = "SFE4003",
+ .gen_type = "10GBASE-CX4 adapter",
+ .init = sfe4003_init,
+ .init_phy = sfe4003_init_phy,
+ .fini = efx_fini_lm87,
+ .set_id_led = sfe4003_set_id_led,
+ .monitor = sfe4003_check_hw,
},
{
.id = FALCON_BOARD_SFN4112F,
@@ -742,13 +709,14 @@ int falcon_probe_board(struct efx_nic *efx, u16 revision_info)
board->type = &board_types[i];
if (board->type) {
- EFX_INFO(efx, "board is %s rev %c%d\n",
+ netif_info(efx, probe, efx->net_dev, "board is %s rev %c%d\n",
(efx->pci_dev->subsystem_vendor == EFX_VENDID_SFC)
? board->type->ref_model : board->type->gen_type,
'A' + board->major, board->minor);
return 0;
} else {
- EFX_ERR(efx, "unknown board type %d\n", type_id);
+ netif_err(efx, probe, efx->net_dev, "unknown board type %d\n",
+ type_id);
return -ENODEV;
}
}
diff --git a/drivers/net/sfc/falcon_gmac.c b/drivers/net/sfc/falcon_gmac.c
deleted file mode 100644
index 7dadfcbd6ce7..000000000000
--- a/drivers/net/sfc/falcon_gmac.c
+++ /dev/null
@@ -1,230 +0,0 @@
-/****************************************************************************
- * Driver for Solarflare Solarstorm network controllers and boards
- * Copyright 2005-2006 Fen Systems Ltd.
- * Copyright 2006-2009 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/delay.h>
-#include "net_driver.h"
-#include "efx.h"
-#include "nic.h"
-#include "mac.h"
-#include "regs.h"
-#include "io.h"
-
-/**************************************************************************
- *
- * MAC operations
- *
- *************************************************************************/
-
-static int falcon_reconfigure_gmac(struct efx_nic *efx)
-{
- struct efx_link_state *link_state = &efx->link_state;
- bool loopback, tx_fc, rx_fc, bytemode;
- int if_mode;
- unsigned int max_frame_len;
- efx_oword_t reg;
-
- /* Configuration register 1 */
- tx_fc = (link_state->fc & EFX_FC_TX) || !link_state->fd;
- rx_fc = !!(link_state->fc & EFX_FC_RX);
- loopback = (efx->loopback_mode == LOOPBACK_GMAC);
- bytemode = (link_state->speed == 1000);
-
- EFX_POPULATE_OWORD_5(reg,
- FRF_AB_GM_LOOP, loopback,
- FRF_AB_GM_TX_EN, 1,
- FRF_AB_GM_TX_FC_EN, tx_fc,
- FRF_AB_GM_RX_EN, 1,
- FRF_AB_GM_RX_FC_EN, rx_fc);
- efx_writeo(efx, &reg, FR_AB_GM_CFG1);
- udelay(10);
-
- /* Configuration register 2 */
- if_mode = (bytemode) ? 2 : 1;
- EFX_POPULATE_OWORD_5(reg,
- FRF_AB_GM_IF_MODE, if_mode,
- FRF_AB_GM_PAD_CRC_EN, 1,
- FRF_AB_GM_LEN_CHK, 1,
- FRF_AB_GM_FD, link_state->fd,
- FRF_AB_GM_PAMBL_LEN, 0x7/*datasheet recommended */);
-
- efx_writeo(efx, &reg, FR_AB_GM_CFG2);
- udelay(10);
-
- /* Max frame len register */
- max_frame_len = EFX_MAX_FRAME_LEN(efx->net_dev->mtu);
- EFX_POPULATE_OWORD_1(reg, FRF_AB_GM_MAX_FLEN, max_frame_len);
- efx_writeo(efx, &reg, FR_AB_GM_MAX_FLEN);
- udelay(10);
-
- /* FIFO configuration register 0 */
- EFX_POPULATE_OWORD_5(reg,
- FRF_AB_GMF_FTFENREQ, 1,
- FRF_AB_GMF_STFENREQ, 1,
- FRF_AB_GMF_FRFENREQ, 1,
- FRF_AB_GMF_SRFENREQ, 1,
- FRF_AB_GMF_WTMENREQ, 1);
- efx_writeo(efx, &reg, FR_AB_GMF_CFG0);
- udelay(10);
-
- /* FIFO configuration register 1 */
- EFX_POPULATE_OWORD_2(reg,
- FRF_AB_GMF_CFGFRTH, 0x12,
- FRF_AB_GMF_CFGXOFFRTX, 0xffff);
- efx_writeo(efx, &reg, FR_AB_GMF_CFG1);
- udelay(10);
-
- /* FIFO configuration register 2 */
- EFX_POPULATE_OWORD_2(reg,
- FRF_AB_GMF_CFGHWM, 0x3f,
- FRF_AB_GMF_CFGLWM, 0xa);
- efx_writeo(efx, &reg, FR_AB_GMF_CFG2);
- udelay(10);
-
- /* FIFO configuration register 3 */
- EFX_POPULATE_OWORD_2(reg,
- FRF_AB_GMF_CFGHWMFT, 0x1c,
- FRF_AB_GMF_CFGFTTH, 0x08);
- efx_writeo(efx, &reg, FR_AB_GMF_CFG3);
- udelay(10);
-
- /* FIFO configuration register 4 */
- EFX_POPULATE_OWORD_1(reg, FRF_AB_GMF_HSTFLTRFRM_PAUSE, 1);
- efx_writeo(efx, &reg, FR_AB_GMF_CFG4);
- udelay(10);
-
- /* FIFO configuration register 5 */
- efx_reado(efx, &reg, FR_AB_GMF_CFG5);
- EFX_SET_OWORD_FIELD(reg, FRF_AB_GMF_CFGBYTMODE, bytemode);
- EFX_SET_OWORD_FIELD(reg, FRF_AB_GMF_CFGHDPLX, !link_state->fd);
- EFX_SET_OWORD_FIELD(reg, FRF_AB_GMF_HSTDRPLT64, !link_state->fd);
- EFX_SET_OWORD_FIELD(reg, FRF_AB_GMF_HSTFLTRFRMDC_PAUSE, 0);
- efx_writeo(efx, &reg, FR_AB_GMF_CFG5);
- udelay(10);
-
- /* MAC address */
- EFX_POPULATE_OWORD_4(reg,
- FRF_AB_GM_ADR_B0, efx->net_dev->dev_addr[5],
- FRF_AB_GM_ADR_B1, efx->net_dev->dev_addr[4],
- FRF_AB_GM_ADR_B2, efx->net_dev->dev_addr[3],
- FRF_AB_GM_ADR_B3, efx->net_dev->dev_addr[2]);
- efx_writeo(efx, &reg, FR_AB_GM_ADR1);
- udelay(10);
- EFX_POPULATE_OWORD_2(reg,
- FRF_AB_GM_ADR_B4, efx->net_dev->dev_addr[1],
- FRF_AB_GM_ADR_B5, efx->net_dev->dev_addr[0]);
- efx_writeo(efx, &reg, FR_AB_GM_ADR2);
- udelay(10);
-
- falcon_reconfigure_mac_wrapper(efx);
-
- return 0;
-}
-
-static void falcon_update_stats_gmac(struct efx_nic *efx)
-{
- struct efx_mac_stats *mac_stats = &efx->mac_stats;
- unsigned long old_rx_pause, old_tx_pause;
- unsigned long new_rx_pause, new_tx_pause;
-
- /* Pause frames are erroneously counted as errors (SFC bug 3269) */
- old_rx_pause = mac_stats->rx_pause;
- old_tx_pause = mac_stats->tx_pause;
-
- /* Update MAC stats from DMAed values */
- FALCON_STAT(efx, GRxGoodOct, rx_good_bytes);
- FALCON_STAT(efx, GRxBadOct, rx_bad_bytes);
- FALCON_STAT(efx, GRxMissPkt, rx_missed);
- FALCON_STAT(efx, GRxFalseCRS, rx_false_carrier);
- FALCON_STAT(efx, GRxPausePkt, rx_pause);
- FALCON_STAT(efx, GRxBadPkt, rx_bad);
- FALCON_STAT(efx, GRxUcastPkt, rx_unicast);
- FALCON_STAT(efx, GRxMcastPkt, rx_multicast);
- FALCON_STAT(efx, GRxBcastPkt, rx_broadcast);
- FALCON_STAT(efx, GRxGoodLt64Pkt, rx_good_lt64);
- FALCON_STAT(efx, GRxBadLt64Pkt, rx_bad_lt64);
- FALCON_STAT(efx, GRx64Pkt, rx_64);
- FALCON_STAT(efx, GRx65to127Pkt, rx_65_to_127);
- FALCON_STAT(efx, GRx128to255Pkt, rx_128_to_255);
- FALCON_STAT(efx, GRx256to511Pkt, rx_256_to_511);
- FALCON_STAT(efx, GRx512to1023Pkt, rx_512_to_1023);
- FALCON_STAT(efx, GRx1024to15xxPkt, rx_1024_to_15xx);
- FALCON_STAT(efx, GRx15xxtoJumboPkt, rx_15xx_to_jumbo);
- FALCON_STAT(efx, GRxGtJumboPkt, rx_gtjumbo);
- FALCON_STAT(efx, GRxFcsErr64to15xxPkt, rx_bad_64_to_15xx);
- FALCON_STAT(efx, GRxFcsErr15xxtoJumboPkt, rx_bad_15xx_to_jumbo);
- FALCON_STAT(efx, GRxFcsErrGtJumboPkt, rx_bad_gtjumbo);
- FALCON_STAT(efx, GTxGoodBadOct, tx_bytes);
- FALCON_STAT(efx, GTxGoodOct, tx_good_bytes);
- FALCON_STAT(efx, GTxSglColPkt, tx_single_collision);
- FALCON_STAT(efx, GTxMultColPkt, tx_multiple_collision);
- FALCON_STAT(efx, GTxExColPkt, tx_excessive_collision);
- FALCON_STAT(efx, GTxDefPkt, tx_deferred);
- FALCON_STAT(efx, GTxLateCol, tx_late_collision);
- FALCON_STAT(efx, GTxExDefPkt, tx_excessive_deferred);
- FALCON_STAT(efx, GTxPausePkt, tx_pause);
- FALCON_STAT(efx, GTxBadPkt, tx_bad);
- FALCON_STAT(efx, GTxUcastPkt, tx_unicast);
- FALCON_STAT(efx, GTxMcastPkt, tx_multicast);
- FALCON_STAT(efx, GTxBcastPkt, tx_broadcast);
- FALCON_STAT(efx, GTxLt64Pkt, tx_lt64);
- FALCON_STAT(efx, GTx64Pkt, tx_64);
- FALCON_STAT(efx, GTx65to127Pkt, tx_65_to_127);
- FALCON_STAT(efx, GTx128to255Pkt, tx_128_to_255);
- FALCON_STAT(efx, GTx256to511Pkt, tx_256_to_511);
- FALCON_STAT(efx, GTx512to1023Pkt, tx_512_to_1023);
- FALCON_STAT(efx, GTx1024to15xxPkt, tx_1024_to_15xx);
- FALCON_STAT(efx, GTx15xxtoJumboPkt, tx_15xx_to_jumbo);
- FALCON_STAT(efx, GTxGtJumboPkt, tx_gtjumbo);
- FALCON_STAT(efx, GTxNonTcpUdpPkt, tx_non_tcpudp);
- FALCON_STAT(efx, GTxMacSrcErrPkt, tx_mac_src_error);
- FALCON_STAT(efx, GTxIpSrcErrPkt, tx_ip_src_error);
-
- /* Pause frames are erroneously counted as errors (SFC bug 3269) */
- new_rx_pause = mac_stats->rx_pause;
- new_tx_pause = mac_stats->tx_pause;
- mac_stats->rx_bad -= (new_rx_pause - old_rx_pause);
- mac_stats->tx_bad -= (new_tx_pause - old_tx_pause);
-
- /* Derive stats that the MAC doesn't provide directly */
- mac_stats->tx_bad_bytes =
- mac_stats->tx_bytes - mac_stats->tx_good_bytes;
- mac_stats->tx_packets =
- mac_stats->tx_lt64 + mac_stats->tx_64 +
- mac_stats->tx_65_to_127 + mac_stats->tx_128_to_255 +
- mac_stats->tx_256_to_511 + mac_stats->tx_512_to_1023 +
- mac_stats->tx_1024_to_15xx + mac_stats->tx_15xx_to_jumbo +
- mac_stats->tx_gtjumbo;
- mac_stats->tx_collision =
- mac_stats->tx_single_collision +
- mac_stats->tx_multiple_collision +
- mac_stats->tx_excessive_collision +
- mac_stats->tx_late_collision;
- mac_stats->rx_bytes =
- mac_stats->rx_good_bytes + mac_stats->rx_bad_bytes;
- mac_stats->rx_packets =
- mac_stats->rx_good_lt64 + mac_stats->rx_bad_lt64 +
- mac_stats->rx_64 + mac_stats->rx_65_to_127 +
- mac_stats->rx_128_to_255 + mac_stats->rx_256_to_511 +
- mac_stats->rx_512_to_1023 + mac_stats->rx_1024_to_15xx +
- mac_stats->rx_15xx_to_jumbo + mac_stats->rx_gtjumbo;
- mac_stats->rx_good = mac_stats->rx_packets - mac_stats->rx_bad;
- mac_stats->rx_lt64 = mac_stats->rx_good_lt64 + mac_stats->rx_bad_lt64;
-}
-
-static bool falcon_gmac_check_fault(struct efx_nic *efx)
-{
- return false;
-}
-
-struct efx_mac_operations falcon_gmac_operations = {
- .reconfigure = falcon_reconfigure_gmac,
- .update_stats = falcon_update_stats_gmac,
- .check_fault = falcon_gmac_check_fault,
-};
diff --git a/drivers/net/sfc/falcon_xmac.c b/drivers/net/sfc/falcon_xmac.c
index c84a2ce2ccbb..b31f595ebb5b 100644
--- a/drivers/net/sfc/falcon_xmac.c
+++ b/drivers/net/sfc/falcon_xmac.c
@@ -81,7 +81,8 @@ int falcon_reset_xaui(struct efx_nic *efx)
}
udelay(10);
}
- EFX_ERR(efx, "timed out waiting for XAUI/XGXS reset\n");
+ netif_err(efx, hw, efx->net_dev,
+ "timed out waiting for XAUI/XGXS reset\n");
return -ETIMEDOUT;
}
@@ -142,7 +143,7 @@ static bool falcon_xmac_link_ok(struct efx_nic *efx)
efx_mdio_phyxgxs_lane_sync(efx));
}
-void falcon_reconfigure_xmac_core(struct efx_nic *efx)
+static void falcon_reconfigure_xmac_core(struct efx_nic *efx)
{
unsigned int max_frame_len;
efx_oword_t reg;
@@ -256,7 +257,7 @@ static bool falcon_xmac_link_ok_retry(struct efx_nic *efx, int tries)
falcon_stop_nic_stats(efx);
while (!mac_up && tries) {
- EFX_LOG(efx, "bashing xaui\n");
+ netif_dbg(efx, hw, efx->net_dev, "bashing xaui\n");
falcon_reset_xaui(efx);
udelay(200);
diff --git a/drivers/net/sfc/filter.c b/drivers/net/sfc/filter.c
new file mode 100644
index 000000000000..52cb6082b910
--- /dev/null
+++ b/drivers/net/sfc/filter.c
@@ -0,0 +1,454 @@
+/****************************************************************************
+ * Driver for Solarflare Solarstorm network controllers and boards
+ * Copyright 2005-2010 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 "efx.h"
+#include "filter.h"
+#include "io.h"
+#include "nic.h"
+#include "regs.h"
+
+/* "Fudge factors" - difference between programmed value and actual depth.
+ * Due to pipelined implementation we need to program H/W with a value that
+ * is larger than the hop limit we want.
+ */
+#define FILTER_CTL_SRCH_FUDGE_WILD 3
+#define FILTER_CTL_SRCH_FUDGE_FULL 1
+
+/* Hard maximum hop limit. Hardware will time-out beyond 200-something.
+ * We also need to avoid infinite loops in efx_filter_search() when the
+ * table is full.
+ */
+#define FILTER_CTL_SRCH_MAX 200
+
+struct efx_filter_table {
+ u32 offset; /* address of table relative to BAR */
+ unsigned size; /* number of entries */
+ unsigned step; /* step between entries */
+ unsigned used; /* number currently used */
+ unsigned long *used_bitmap;
+ struct efx_filter_spec *spec;
+};
+
+struct efx_filter_state {
+ spinlock_t lock;
+ struct efx_filter_table table[EFX_FILTER_TABLE_COUNT];
+ unsigned search_depth[EFX_FILTER_TYPE_COUNT];
+};
+
+/* The filter hash function is LFSR polynomial x^16 + x^3 + 1 of a 32-bit
+ * key derived from the n-tuple. The initial LFSR state is 0xffff. */
+static u16 efx_filter_hash(u32 key)
+{
+ u16 tmp;
+
+ /* First 16 rounds */
+ tmp = 0x1fff ^ key >> 16;
+ tmp = tmp ^ tmp >> 3 ^ tmp >> 6;
+ tmp = tmp ^ tmp >> 9;
+ /* Last 16 rounds */
+ tmp = tmp ^ tmp << 13 ^ key;
+ tmp = tmp ^ tmp >> 3 ^ tmp >> 6;
+ return tmp ^ tmp >> 9;
+}
+
+/* To allow for hash collisions, filter search continues at these
+ * increments from the first possible entry selected by the hash. */
+static u16 efx_filter_increment(u32 key)
+{
+ return key * 2 - 1;
+}
+
+static enum efx_filter_table_id
+efx_filter_type_table_id(enum efx_filter_type type)
+{
+ BUILD_BUG_ON(EFX_FILTER_TABLE_RX_IP != (EFX_FILTER_RX_TCP_FULL >> 2));
+ BUILD_BUG_ON(EFX_FILTER_TABLE_RX_IP != (EFX_FILTER_RX_TCP_WILD >> 2));
+ BUILD_BUG_ON(EFX_FILTER_TABLE_RX_IP != (EFX_FILTER_RX_UDP_FULL >> 2));
+ BUILD_BUG_ON(EFX_FILTER_TABLE_RX_IP != (EFX_FILTER_RX_UDP_WILD >> 2));
+ BUILD_BUG_ON(EFX_FILTER_TABLE_RX_MAC != (EFX_FILTER_RX_MAC_FULL >> 2));
+ BUILD_BUG_ON(EFX_FILTER_TABLE_RX_MAC != (EFX_FILTER_RX_MAC_WILD >> 2));
+ return type >> 2;
+}
+
+static void
+efx_filter_table_reset_search_depth(struct efx_filter_state *state,
+ enum efx_filter_table_id table_id)
+{
+ memset(state->search_depth + (table_id << 2), 0,
+ sizeof(state->search_depth[0]) << 2);
+}
+
+static void efx_filter_push_rx_limits(struct efx_nic *efx)
+{
+ struct efx_filter_state *state = efx->filter_state;
+ efx_oword_t filter_ctl;
+
+ efx_reado(efx, &filter_ctl, FR_BZ_RX_FILTER_CTL);
+
+ EFX_SET_OWORD_FIELD(filter_ctl, FRF_BZ_TCP_FULL_SRCH_LIMIT,
+ state->search_depth[EFX_FILTER_RX_TCP_FULL] +
+ FILTER_CTL_SRCH_FUDGE_FULL);
+ EFX_SET_OWORD_FIELD(filter_ctl, FRF_BZ_TCP_WILD_SRCH_LIMIT,
+ state->search_depth[EFX_FILTER_RX_TCP_WILD] +
+ FILTER_CTL_SRCH_FUDGE_WILD);
+ EFX_SET_OWORD_FIELD(filter_ctl, FRF_BZ_UDP_FULL_SRCH_LIMIT,
+ state->search_depth[EFX_FILTER_RX_UDP_FULL] +
+ FILTER_CTL_SRCH_FUDGE_FULL);
+ EFX_SET_OWORD_FIELD(filter_ctl, FRF_BZ_UDP_WILD_SRCH_LIMIT,
+ state->search_depth[EFX_FILTER_RX_UDP_WILD] +
+ FILTER_CTL_SRCH_FUDGE_WILD);
+
+ if (state->table[EFX_FILTER_TABLE_RX_MAC].size) {
+ EFX_SET_OWORD_FIELD(
+ filter_ctl, FRF_CZ_ETHERNET_FULL_SEARCH_LIMIT,
+ state->search_depth[EFX_FILTER_RX_MAC_FULL] +
+ FILTER_CTL_SRCH_FUDGE_FULL);
+ EFX_SET_OWORD_FIELD(
+ filter_ctl, FRF_CZ_ETHERNET_WILDCARD_SEARCH_LIMIT,
+ state->search_depth[EFX_FILTER_RX_MAC_WILD] +
+ FILTER_CTL_SRCH_FUDGE_WILD);
+ }
+
+ efx_writeo(efx, &filter_ctl, FR_BZ_RX_FILTER_CTL);
+}
+
+/* Build a filter entry and return its n-tuple key. */
+static u32 efx_filter_build(efx_oword_t *filter, struct efx_filter_spec *spec)
+{
+ u32 data3;
+
+ switch (efx_filter_type_table_id(spec->type)) {
+ case EFX_FILTER_TABLE_RX_IP: {
+ bool is_udp = (spec->type == EFX_FILTER_RX_UDP_FULL ||
+ spec->type == EFX_FILTER_RX_UDP_WILD);
+ EFX_POPULATE_OWORD_7(
+ *filter,
+ FRF_BZ_RSS_EN,
+ !!(spec->flags & EFX_FILTER_FLAG_RX_RSS),
+ FRF_BZ_SCATTER_EN,
+ !!(spec->flags & EFX_FILTER_FLAG_RX_SCATTER),
+ FRF_BZ_TCP_UDP, is_udp,
+ FRF_BZ_RXQ_ID, spec->dmaq_id,
+ EFX_DWORD_2, spec->data[2],
+ EFX_DWORD_1, spec->data[1],
+ EFX_DWORD_0, spec->data[0]);
+ data3 = is_udp;
+ break;
+ }
+
+ case EFX_FILTER_TABLE_RX_MAC: {
+ bool is_wild = spec->type == EFX_FILTER_RX_MAC_WILD;
+ EFX_POPULATE_OWORD_8(
+ *filter,
+ FRF_CZ_RMFT_RSS_EN,
+ !!(spec->flags & EFX_FILTER_FLAG_RX_RSS),
+ FRF_CZ_RMFT_SCATTER_EN,
+ !!(spec->flags & EFX_FILTER_FLAG_RX_SCATTER),
+ FRF_CZ_RMFT_IP_OVERRIDE,
+ !!(spec->flags & EFX_FILTER_FLAG_RX_OVERRIDE_IP),
+ FRF_CZ_RMFT_RXQ_ID, spec->dmaq_id,
+ FRF_CZ_RMFT_WILDCARD_MATCH, is_wild,
+ FRF_CZ_RMFT_DEST_MAC_HI, spec->data[2],
+ FRF_CZ_RMFT_DEST_MAC_LO, spec->data[1],
+ FRF_CZ_RMFT_VLAN_ID, spec->data[0]);
+ data3 = is_wild;
+ break;
+ }
+
+ default:
+ BUG();
+ }
+
+ return spec->data[0] ^ spec->data[1] ^ spec->data[2] ^ data3;
+}
+
+static bool efx_filter_equal(const struct efx_filter_spec *left,
+ const struct efx_filter_spec *right)
+{
+ if (left->type != right->type ||
+ memcmp(left->data, right->data, sizeof(left->data)))
+ return false;
+
+ return true;
+}
+
+static int efx_filter_search(struct efx_filter_table *table,
+ struct efx_filter_spec *spec, u32 key,
+ bool for_insert, int *depth_required)
+{
+ unsigned hash, incr, filter_idx, depth;
+ struct efx_filter_spec *cmp;
+
+ hash = efx_filter_hash(key);
+ incr = efx_filter_increment(key);
+
+ for (depth = 1, filter_idx = hash & (table->size - 1);
+ depth <= FILTER_CTL_SRCH_MAX &&
+ test_bit(filter_idx, table->used_bitmap);
+ ++depth) {
+ cmp = &table->spec[filter_idx];
+ if (efx_filter_equal(spec, cmp))
+ goto found;
+ filter_idx = (filter_idx + incr) & (table->size - 1);
+ }
+ if (!for_insert)
+ return -ENOENT;
+ if (depth > FILTER_CTL_SRCH_MAX)
+ return -EBUSY;
+found:
+ *depth_required = depth;
+ return filter_idx;
+}
+
+/**
+ * efx_filter_insert_filter - add or replace a filter
+ * @efx: NIC in which to insert the filter
+ * @spec: Specification for the filter
+ * @replace: Flag for whether the specified filter may replace a filter
+ * with an identical match expression and equal or lower priority
+ *
+ * On success, return the filter index within its table.
+ * On failure, return a negative error code.
+ */
+int efx_filter_insert_filter(struct efx_nic *efx, struct efx_filter_spec *spec,
+ bool replace)
+{
+ struct efx_filter_state *state = efx->filter_state;
+ enum efx_filter_table_id table_id =
+ efx_filter_type_table_id(spec->type);
+ struct efx_filter_table *table = &state->table[table_id];
+ struct efx_filter_spec *saved_spec;
+ efx_oword_t filter;
+ int filter_idx, depth;
+ u32 key;
+ int rc;
+
+ if (table->size == 0)
+ return -EINVAL;
+
+ key = efx_filter_build(&filter, spec);
+
+ netif_vdbg(efx, hw, efx->net_dev,
+ "%s: type %d search_depth=%d", __func__, spec->type,
+ state->search_depth[spec->type]);
+
+ spin_lock_bh(&state->lock);
+
+ rc = efx_filter_search(table, spec, key, true, &depth);
+ if (rc < 0)
+ goto out;
+ filter_idx = rc;
+ BUG_ON(filter_idx >= table->size);
+ saved_spec = &table->spec[filter_idx];
+
+ if (test_bit(filter_idx, table->used_bitmap)) {
+ /* Should we replace the existing filter? */
+ if (!replace) {
+ rc = -EEXIST;
+ goto out;
+ }
+ if (spec->priority < saved_spec->priority) {
+ rc = -EPERM;
+ goto out;
+ }
+ } else {
+ __set_bit(filter_idx, table->used_bitmap);
+ ++table->used;
+ }
+ *saved_spec = *spec;
+
+ if (state->search_depth[spec->type] < depth) {
+ state->search_depth[spec->type] = depth;
+ efx_filter_push_rx_limits(efx);
+ }
+
+ efx_writeo(efx, &filter, table->offset + table->step * filter_idx);
+
+ netif_vdbg(efx, hw, efx->net_dev,
+ "%s: filter type %d index %d rxq %u set",
+ __func__, spec->type, filter_idx, spec->dmaq_id);
+
+out:
+ spin_unlock_bh(&state->lock);
+ return rc;
+}
+
+static void efx_filter_table_clear_entry(struct efx_nic *efx,
+ struct efx_filter_table *table,
+ int filter_idx)
+{
+ static efx_oword_t filter;
+
+ if (test_bit(filter_idx, table->used_bitmap)) {
+ __clear_bit(filter_idx, table->used_bitmap);
+ --table->used;
+ memset(&table->spec[filter_idx], 0, sizeof(table->spec[0]));
+
+ efx_writeo(efx, &filter,
+ table->offset + table->step * filter_idx);
+ }
+}
+
+/**
+ * efx_filter_remove_filter - remove a filter by specification
+ * @efx: NIC from which to remove the filter
+ * @spec: Specification for the filter
+ *
+ * On success, return zero.
+ * On failure, return a negative error code.
+ */
+int efx_filter_remove_filter(struct efx_nic *efx, struct efx_filter_spec *spec)
+{
+ struct efx_filter_state *state = efx->filter_state;
+ enum efx_filter_table_id table_id =
+ efx_filter_type_table_id(spec->type);
+ struct efx_filter_table *table = &state->table[table_id];
+ struct efx_filter_spec *saved_spec;
+ efx_oword_t filter;
+ int filter_idx, depth;
+ u32 key;
+ int rc;
+
+ key = efx_filter_build(&filter, spec);
+
+ spin_lock_bh(&state->lock);
+
+ rc = efx_filter_search(table, spec, key, false, &depth);
+ if (rc < 0)
+ goto out;
+ filter_idx = rc;
+ saved_spec = &table->spec[filter_idx];
+
+ if (spec->priority < saved_spec->priority) {
+ rc = -EPERM;
+ goto out;
+ }
+
+ efx_filter_table_clear_entry(efx, table, filter_idx);
+ if (table->used == 0)
+ efx_filter_table_reset_search_depth(state, table_id);
+ rc = 0;
+
+out:
+ spin_unlock_bh(&state->lock);
+ return rc;
+}
+
+/**
+ * efx_filter_table_clear - remove filters from a table by priority
+ * @efx: NIC from which to remove the filters
+ * @table_id: Table from which to remove the filters
+ * @priority: Maximum priority to remove
+ */
+void efx_filter_table_clear(struct efx_nic *efx,
+ enum efx_filter_table_id table_id,
+ enum efx_filter_priority priority)
+{
+ struct efx_filter_state *state = efx->filter_state;
+ struct efx_filter_table *table = &state->table[table_id];
+ int filter_idx;
+
+ spin_lock_bh(&state->lock);
+
+ for (filter_idx = 0; filter_idx < table->size; ++filter_idx)
+ if (table->spec[filter_idx].priority <= priority)
+ efx_filter_table_clear_entry(efx, table, filter_idx);
+ if (table->used == 0)
+ efx_filter_table_reset_search_depth(state, table_id);
+
+ spin_unlock_bh(&state->lock);
+}
+
+/* Restore filter stater after reset */
+void efx_restore_filters(struct efx_nic *efx)
+{
+ struct efx_filter_state *state = efx->filter_state;
+ enum efx_filter_table_id table_id;
+ struct efx_filter_table *table;
+ efx_oword_t filter;
+ int filter_idx;
+
+ spin_lock_bh(&state->lock);
+
+ for (table_id = 0; table_id < EFX_FILTER_TABLE_COUNT; table_id++) {
+ table = &state->table[table_id];
+ for (filter_idx = 0; filter_idx < table->size; filter_idx++) {
+ if (!test_bit(filter_idx, table->used_bitmap))
+ continue;
+ efx_filter_build(&filter, &table->spec[filter_idx]);
+ efx_writeo(efx, &filter,
+ table->offset + table->step * filter_idx);
+ }
+ }
+
+ efx_filter_push_rx_limits(efx);
+
+ spin_unlock_bh(&state->lock);
+}
+
+int efx_probe_filters(struct efx_nic *efx)
+{
+ struct efx_filter_state *state;
+ struct efx_filter_table *table;
+ unsigned table_id;
+
+ state = kzalloc(sizeof(*efx->filter_state), GFP_KERNEL);
+ if (!state)
+ return -ENOMEM;
+ efx->filter_state = state;
+
+ spin_lock_init(&state->lock);
+
+ if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0) {
+ table = &state->table[EFX_FILTER_TABLE_RX_IP];
+ table->offset = FR_BZ_RX_FILTER_TBL0;
+ table->size = FR_BZ_RX_FILTER_TBL0_ROWS;
+ table->step = FR_BZ_RX_FILTER_TBL0_STEP;
+ }
+
+ if (efx_nic_rev(efx) >= EFX_REV_SIENA_A0) {
+ table = &state->table[EFX_FILTER_TABLE_RX_MAC];
+ table->offset = FR_CZ_RX_MAC_FILTER_TBL0;
+ table->size = FR_CZ_RX_MAC_FILTER_TBL0_ROWS;
+ table->step = FR_CZ_RX_MAC_FILTER_TBL0_STEP;
+ }
+
+ for (table_id = 0; table_id < EFX_FILTER_TABLE_COUNT; table_id++) {
+ table = &state->table[table_id];
+ if (table->size == 0)
+ continue;
+ table->used_bitmap = kcalloc(BITS_TO_LONGS(table->size),
+ sizeof(unsigned long),
+ GFP_KERNEL);
+ if (!table->used_bitmap)
+ goto fail;
+ table->spec = vmalloc(table->size * sizeof(*table->spec));
+ if (!table->spec)
+ goto fail;
+ memset(table->spec, 0, table->size * sizeof(*table->spec));
+ }
+
+ return 0;
+
+fail:
+ efx_remove_filters(efx);
+ return -ENOMEM;
+}
+
+void efx_remove_filters(struct efx_nic *efx)
+{
+ struct efx_filter_state *state = efx->filter_state;
+ enum efx_filter_table_id table_id;
+
+ for (table_id = 0; table_id < EFX_FILTER_TABLE_COUNT; table_id++) {
+ kfree(state->table[table_id].used_bitmap);
+ vfree(state->table[table_id].spec);
+ }
+ kfree(state);
+}
diff --git a/drivers/net/sfc/filter.h b/drivers/net/sfc/filter.h
new file mode 100644
index 000000000000..a53319ded79c
--- /dev/null
+++ b/drivers/net/sfc/filter.h
@@ -0,0 +1,189 @@
+/****************************************************************************
+ * Driver for Solarflare Solarstorm network controllers and boards
+ * Copyright 2005-2010 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.
+ */
+
+#ifndef EFX_FILTER_H
+#define EFX_FILTER_H
+
+#include <linux/types.h>
+
+enum efx_filter_table_id {
+ EFX_FILTER_TABLE_RX_IP = 0,
+ EFX_FILTER_TABLE_RX_MAC,
+ EFX_FILTER_TABLE_COUNT,
+};
+
+/**
+ * enum efx_filter_type - type of hardware filter
+ * @EFX_FILTER_RX_TCP_FULL: RX, matching TCP/IPv4 4-tuple
+ * @EFX_FILTER_RX_TCP_WILD: RX, matching TCP/IPv4 destination (host, port)
+ * @EFX_FILTER_RX_UDP_FULL: RX, matching UDP/IPv4 4-tuple
+ * @EFX_FILTER_RX_UDP_WILD: RX, matching UDP/IPv4 destination (host, port)
+ * @EFX_FILTER_RX_MAC_FULL: RX, matching Ethernet destination MAC address, VID
+ * @EFX_FILTER_RX_MAC_WILD: RX, matching Ethernet destination MAC address
+ *
+ * Falcon NICs only support the RX TCP/IPv4 and UDP/IPv4 filter types.
+ */
+enum efx_filter_type {
+ EFX_FILTER_RX_TCP_FULL = 0,
+ EFX_FILTER_RX_TCP_WILD,
+ EFX_FILTER_RX_UDP_FULL,
+ EFX_FILTER_RX_UDP_WILD,
+ EFX_FILTER_RX_MAC_FULL = 4,
+ EFX_FILTER_RX_MAC_WILD,
+ EFX_FILTER_TYPE_COUNT,
+};
+
+/**
+ * enum efx_filter_priority - priority of a hardware filter specification
+ * @EFX_FILTER_PRI_HINT: Performance hint
+ * @EFX_FILTER_PRI_MANUAL: Manually configured filter
+ * @EFX_FILTER_PRI_REQUIRED: Required for correct behaviour
+ */
+enum efx_filter_priority {
+ EFX_FILTER_PRI_HINT = 0,
+ EFX_FILTER_PRI_MANUAL,
+ EFX_FILTER_PRI_REQUIRED,
+};
+
+/**
+ * enum efx_filter_flags - flags for hardware filter specifications
+ * @EFX_FILTER_FLAG_RX_RSS: Use RSS to spread across multiple queues.
+ * By default, matching packets will be delivered only to the
+ * specified queue. If this flag is set, they will be delivered
+ * to a range of queues offset from the specified queue number
+ * according to the indirection table.
+ * @EFX_FILTER_FLAG_RX_SCATTER: Enable DMA scatter on the receiving
+ * queue.
+ * @EFX_FILTER_FLAG_RX_OVERRIDE_IP: Enables a MAC filter to override
+ * any IP filter that matches the same packet. By default, IP
+ * filters take precedence.
+ *
+ * Currently, no flags are defined for TX filters.
+ */
+enum efx_filter_flags {
+ EFX_FILTER_FLAG_RX_RSS = 0x01,
+ EFX_FILTER_FLAG_RX_SCATTER = 0x02,
+ EFX_FILTER_FLAG_RX_OVERRIDE_IP = 0x04,
+};
+
+/**
+ * struct efx_filter_spec - specification for a hardware filter
+ * @type: Type of match to be performed, from &enum efx_filter_type
+ * @priority: Priority of the filter, from &enum efx_filter_priority
+ * @flags: Miscellaneous flags, from &enum efx_filter_flags
+ * @dmaq_id: Source/target queue index
+ * @data: Match data (type-dependent)
+ *
+ * Use the efx_filter_set_*() functions to initialise the @type and
+ * @data fields.
+ */
+struct efx_filter_spec {
+ u8 type:4;
+ u8 priority:4;
+ u8 flags;
+ u16 dmaq_id;
+ u32 data[3];
+};
+
+/**
+ * efx_filter_set_rx_tcp_full - specify RX filter with TCP/IPv4 full match
+ * @spec: Specification to initialise
+ * @shost: Source host address (host byte order)
+ * @sport: Source port (host byte order)
+ * @dhost: Destination host address (host byte order)
+ * @dport: Destination port (host byte order)
+ */
+static inline void
+efx_filter_set_rx_tcp_full(struct efx_filter_spec *spec,
+ u32 shost, u16 sport, u32 dhost, u16 dport)
+{
+ spec->type = EFX_FILTER_RX_TCP_FULL;
+ spec->data[0] = sport | shost << 16;
+ spec->data[1] = dport << 16 | shost >> 16;
+ spec->data[2] = dhost;
+}
+
+/**
+ * efx_filter_set_rx_tcp_wild - specify RX filter with TCP/IPv4 wildcard match
+ * @spec: Specification to initialise
+ * @dhost: Destination host address (host byte order)
+ * @dport: Destination port (host byte order)
+ */
+static inline void
+efx_filter_set_rx_tcp_wild(struct efx_filter_spec *spec, u32 dhost, u16 dport)
+{
+ spec->type = EFX_FILTER_RX_TCP_WILD;
+ spec->data[0] = 0;
+ spec->data[1] = dport << 16;
+ spec->data[2] = dhost;
+}
+
+/**
+ * efx_filter_set_rx_udp_full - specify RX filter with UDP/IPv4 full match
+ * @spec: Specification to initialise
+ * @shost: Source host address (host byte order)
+ * @sport: Source port (host byte order)
+ * @dhost: Destination host address (host byte order)
+ * @dport: Destination port (host byte order)
+ */
+static inline void
+efx_filter_set_rx_udp_full(struct efx_filter_spec *spec,
+ u32 shost, u16 sport, u32 dhost, u16 dport)
+{
+ spec->type = EFX_FILTER_RX_UDP_FULL;
+ spec->data[0] = sport | shost << 16;
+ spec->data[1] = dport << 16 | shost >> 16;
+ spec->data[2] = dhost;
+}
+
+/**
+ * efx_filter_set_rx_udp_wild - specify RX filter with UDP/IPv4 wildcard match
+ * @spec: Specification to initialise
+ * @dhost: Destination host address (host byte order)
+ * @dport: Destination port (host byte order)
+ */
+static inline void
+efx_filter_set_rx_udp_wild(struct efx_filter_spec *spec, u32 dhost, u16 dport)
+{
+ spec->type = EFX_FILTER_RX_UDP_WILD;
+ spec->data[0] = dport;
+ spec->data[1] = 0;
+ spec->data[2] = dhost;
+}
+
+/**
+ * efx_filter_set_rx_mac_full - specify RX filter with MAC full match
+ * @spec: Specification to initialise
+ * @vid: VLAN ID
+ * @addr: Destination MAC address
+ */
+static inline void efx_filter_set_rx_mac_full(struct efx_filter_spec *spec,
+ u16 vid, const u8 *addr)
+{
+ spec->type = EFX_FILTER_RX_MAC_FULL;
+ spec->data[0] = vid;
+ spec->data[1] = addr[2] << 24 | addr[3] << 16 | addr[4] << 8 | addr[5];
+ spec->data[2] = addr[0] << 8 | addr[1];
+}
+
+/**
+ * efx_filter_set_rx_mac_full - specify RX filter with MAC wildcard match
+ * @spec: Specification to initialise
+ * @addr: Destination MAC address
+ */
+static inline void efx_filter_set_rx_mac_wild(struct efx_filter_spec *spec,
+ const u8 *addr)
+{
+ spec->type = EFX_FILTER_RX_MAC_WILD;
+ spec->data[0] = 0;
+ spec->data[1] = addr[2] << 24 | addr[3] << 16 | addr[4] << 8 | addr[5];
+ spec->data[2] = addr[0] << 8 | addr[1];
+}
+
+#endif /* EFX_FILTER_H */
diff --git a/drivers/net/sfc/io.h b/drivers/net/sfc/io.h
index b89177c27f4a..85a99fe87437 100644
--- a/drivers/net/sfc/io.h
+++ b/drivers/net/sfc/io.h
@@ -78,8 +78,9 @@ static inline void efx_writeo(struct efx_nic *efx, efx_oword_t *value,
{
unsigned long flags __attribute__ ((unused));
- EFX_REGDUMP(efx, "writing register %x with " EFX_OWORD_FMT "\n", reg,
- EFX_OWORD_VAL(*value));
+ netif_vdbg(efx, hw, efx->net_dev,
+ "writing register %x with " EFX_OWORD_FMT "\n", reg,
+ EFX_OWORD_VAL(*value));
spin_lock_irqsave(&efx->biu_lock, flags);
#ifdef EFX_USE_QWORD_IO
@@ -105,8 +106,9 @@ static inline void efx_sram_writeq(struct efx_nic *efx, void __iomem *membase,
unsigned int addr = index * sizeof(*value);
unsigned long flags __attribute__ ((unused));
- EFX_REGDUMP(efx, "writing SRAM address %x with " EFX_QWORD_FMT "\n",
- addr, EFX_QWORD_VAL(*value));
+ netif_vdbg(efx, hw, efx->net_dev,
+ "writing SRAM address %x with " EFX_QWORD_FMT "\n",
+ addr, EFX_QWORD_VAL(*value));
spin_lock_irqsave(&efx->biu_lock, flags);
#ifdef EFX_USE_QWORD_IO
@@ -129,8 +131,9 @@ static inline void efx_sram_writeq(struct efx_nic *efx, void __iomem *membase,
static inline void efx_writed(struct efx_nic *efx, efx_dword_t *value,
unsigned int reg)
{
- EFX_REGDUMP(efx, "writing partial register %x with "EFX_DWORD_FMT"\n",
- reg, EFX_DWORD_VAL(*value));
+ netif_vdbg(efx, hw, efx->net_dev,
+ "writing partial register %x with "EFX_DWORD_FMT"\n",
+ reg, EFX_DWORD_VAL(*value));
/* No lock required */
_efx_writed(efx, value->u32[0], reg);
@@ -155,8 +158,9 @@ static inline void efx_reado(struct efx_nic *efx, efx_oword_t *value,
value->u32[3] = _efx_readd(efx, reg + 12);
spin_unlock_irqrestore(&efx->biu_lock, flags);
- EFX_REGDUMP(efx, "read from register %x, got " EFX_OWORD_FMT "\n", reg,
- EFX_OWORD_VAL(*value));
+ netif_vdbg(efx, hw, efx->net_dev,
+ "read from register %x, got " EFX_OWORD_FMT "\n", reg,
+ EFX_OWORD_VAL(*value));
}
/* Read an 8-byte SRAM entry through supplied mapping,
@@ -177,8 +181,9 @@ static inline void efx_sram_readq(struct efx_nic *efx, void __iomem *membase,
#endif
spin_unlock_irqrestore(&efx->biu_lock, flags);
- EFX_REGDUMP(efx, "read from SRAM address %x, got "EFX_QWORD_FMT"\n",
- addr, EFX_QWORD_VAL(*value));
+ netif_vdbg(efx, hw, efx->net_dev,
+ "read from SRAM address %x, got "EFX_QWORD_FMT"\n",
+ addr, EFX_QWORD_VAL(*value));
}
/* Read dword from register that allows partial writes (sic) */
@@ -186,8 +191,9 @@ static inline void efx_readd(struct efx_nic *efx, efx_dword_t *value,
unsigned int reg)
{
value->u32[0] = _efx_readd(efx, reg);
- EFX_REGDUMP(efx, "read from register %x, got "EFX_DWORD_FMT"\n",
- reg, EFX_DWORD_VAL(*value));
+ netif_vdbg(efx, hw, efx->net_dev,
+ "read from register %x, got "EFX_DWORD_FMT"\n",
+ reg, EFX_DWORD_VAL(*value));
}
/* Write to a register forming part of a table */
@@ -211,6 +217,13 @@ static inline void efx_writed_table(struct efx_nic *efx, efx_dword_t *value,
efx_writed(efx, value, reg + index * sizeof(efx_oword_t));
}
+/* Read from a dword register forming part of a table */
+static inline void efx_readd_table(struct efx_nic *efx, efx_dword_t *value,
+ unsigned int reg, unsigned int index)
+{
+ efx_readd(efx, value, reg + index * sizeof(efx_dword_t));
+}
+
/* Page-mapped register block size */
#define EFX_PAGE_BLOCK_SIZE 0x2000
diff --git a/drivers/net/sfc/mac.h b/drivers/net/sfc/mac.h
index f1aa5f374890..6886cdf87c12 100644
--- a/drivers/net/sfc/mac.h
+++ b/drivers/net/sfc/mac.h
@@ -13,10 +13,8 @@
#include "net_driver.h"
-extern struct efx_mac_operations falcon_gmac_operations;
extern struct efx_mac_operations falcon_xmac_operations;
extern struct efx_mac_operations efx_mcdi_mac_operations;
-extern void falcon_reconfigure_xmac_core(struct efx_nic *efx);
extern int efx_mcdi_mac_stats(struct efx_nic *efx, dma_addr_t dma_addr,
u32 dma_len, int enable, int clear);
diff --git a/drivers/net/sfc/mcdi.c b/drivers/net/sfc/mcdi.c
index 93cc3c1b9450..12cf910c2ce7 100644
--- a/drivers/net/sfc/mcdi.c
+++ b/drivers/net/sfc/mcdi.c
@@ -168,11 +168,12 @@ static int efx_mcdi_poll(struct efx_nic *efx)
error = EFX_DWORD_FIELD(reg, MCDI_HEADER_ERROR);
if (error && mcdi->resplen == 0) {
- EFX_ERR(efx, "MC rebooted\n");
+ netif_err(efx, hw, efx->net_dev, "MC rebooted\n");
rc = EIO;
} else if ((respseq ^ mcdi->seqno) & SEQ_MASK) {
- EFX_ERR(efx, "MC response mismatch tx seq 0x%x rx seq 0x%x\n",
- respseq, mcdi->seqno);
+ netif_err(efx, hw, efx->net_dev,
+ "MC response mismatch tx seq 0x%x rx seq 0x%x\n",
+ respseq, mcdi->seqno);
rc = EIO;
} else if (error) {
efx_readd(efx, &reg, pdu + 4);
@@ -303,8 +304,9 @@ static void efx_mcdi_ev_cpl(struct efx_nic *efx, unsigned int seqno,
/* The request has been cancelled */
--mcdi->credits;
else
- EFX_ERR(efx, "MC response mismatch tx seq 0x%x rx "
- "seq 0x%x\n", seqno, mcdi->seqno);
+ netif_err(efx, hw, efx->net_dev,
+ "MC response mismatch tx seq 0x%x rx "
+ "seq 0x%x\n", seqno, mcdi->seqno);
} else {
mcdi->resprc = errno;
mcdi->resplen = datalen;
@@ -352,8 +354,9 @@ int efx_mcdi_rpc(struct efx_nic *efx, unsigned cmd,
++mcdi->credits;
spin_unlock_bh(&mcdi->iface_lock);
- EFX_ERR(efx, "MC command 0x%x inlen %d mode %d timed out\n",
- cmd, (int)inlen, mcdi->mode);
+ netif_err(efx, hw, efx->net_dev,
+ "MC command 0x%x inlen %d mode %d timed out\n",
+ cmd, (int)inlen, mcdi->mode);
} else {
size_t resplen;
@@ -374,11 +377,13 @@ int efx_mcdi_rpc(struct efx_nic *efx, unsigned cmd,
} else if (cmd == MC_CMD_REBOOT && rc == -EIO)
; /* Don't reset if MC_CMD_REBOOT returns EIO */
else if (rc == -EIO || rc == -EINTR) {
- EFX_ERR(efx, "MC fatal error %d\n", -rc);
+ netif_err(efx, hw, efx->net_dev, "MC fatal error %d\n",
+ -rc);
efx_schedule_reset(efx, RESET_TYPE_MC_FAILURE);
} else
- EFX_ERR(efx, "MC command 0x%x inlen %d failed rc=%d\n",
- cmd, (int)inlen, -rc);
+ netif_err(efx, hw, efx->net_dev,
+ "MC command 0x%x inlen %d failed rc=%d\n",
+ cmd, (int)inlen, -rc);
}
efx_mcdi_release(mcdi);
@@ -534,8 +539,9 @@ static void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev)
EFX_BUG_ON_PARANOID(state >= ARRAY_SIZE(sensor_status_names));
state_txt = sensor_status_names[state];
- EFX_ERR(efx, "Sensor %d (%s) reports condition '%s' for raw value %d\n",
- monitor, name, state_txt, value);
+ netif_err(efx, hw, efx->net_dev,
+ "Sensor %d (%s) reports condition '%s' for raw value %d\n",
+ monitor, name, state_txt, value);
}
/* Called from falcon_process_eventq for MCDI events */
@@ -548,12 +554,13 @@ void efx_mcdi_process_event(struct efx_channel *channel,
switch (code) {
case MCDI_EVENT_CODE_BADSSERT:
- EFX_ERR(efx, "MC watchdog or assertion failure at 0x%x\n", data);
+ netif_err(efx, hw, efx->net_dev,
+ "MC watchdog or assertion failure at 0x%x\n", data);
efx_mcdi_ev_death(efx, EINTR);
break;
case MCDI_EVENT_CODE_PMNOTICE:
- EFX_INFO(efx, "MCDI PM event.\n");
+ netif_info(efx, wol, efx->net_dev, "MCDI PM event.\n");
break;
case MCDI_EVENT_CODE_CMDDONE:
@@ -570,10 +577,11 @@ void efx_mcdi_process_event(struct efx_channel *channel,
efx_mcdi_sensor_event(efx, event);
break;
case MCDI_EVENT_CODE_SCHEDERR:
- EFX_INFO(efx, "MC Scheduler error address=0x%x\n", data);
+ netif_info(efx, hw, efx->net_dev,
+ "MC Scheduler error address=0x%x\n", data);
break;
case MCDI_EVENT_CODE_REBOOT:
- EFX_INFO(efx, "MC Reboot\n");
+ netif_info(efx, hw, efx->net_dev, "MC Reboot\n");
efx_mcdi_ev_death(efx, EIO);
break;
case MCDI_EVENT_CODE_MAC_STATS_DMA:
@@ -581,7 +589,8 @@ void efx_mcdi_process_event(struct efx_channel *channel,
break;
default:
- EFX_ERR(efx, "Unknown MCDI event 0x%x\n", code);
+ netif_err(efx, hw, efx->net_dev, "Unknown MCDI event 0x%x\n",
+ code);
}
}
@@ -627,7 +636,7 @@ int efx_mcdi_fwver(struct efx_nic *efx, u64 *version, u32 *build)
return 0;
fail:
- EFX_ERR(efx, "%s: failed rc=%d\n", __func__, rc);
+ netif_err(efx, probe, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
return rc;
}
@@ -657,7 +666,7 @@ int efx_mcdi_drv_attach(struct efx_nic *efx, bool driver_operating,
return 0;
fail:
- EFX_ERR(efx, "%s: failed rc=%d\n", __func__, rc);
+ netif_err(efx, probe, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
return rc;
}
@@ -695,7 +704,8 @@ int efx_mcdi_get_board_cfg(struct efx_nic *efx, u8 *mac_address,
return 0;
fail:
- EFX_ERR(efx, "%s: failed rc=%d len=%d\n", __func__, rc, (int)outlen);
+ netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d len=%d\n",
+ __func__, rc, (int)outlen);
return rc;
}
@@ -724,7 +734,7 @@ int efx_mcdi_log_ctrl(struct efx_nic *efx, bool evq, bool uart, u32 dest_evq)
return 0;
fail:
- EFX_ERR(efx, "%s: failed rc=%d\n", __func__, rc);
+ netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
return rc;
}
@@ -749,8 +759,8 @@ int efx_mcdi_nvram_types(struct efx_nic *efx, u32 *nvram_types_out)
return 0;
fail:
- EFX_ERR(efx, "%s: failed rc=%d\n",
- __func__, rc);
+ netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n",
+ __func__, rc);
return rc;
}
@@ -781,7 +791,7 @@ int efx_mcdi_nvram_info(struct efx_nic *efx, unsigned int type,
return 0;
fail:
- EFX_ERR(efx, "%s: failed rc=%d\n", __func__, rc);
+ netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
return rc;
}
@@ -802,7 +812,7 @@ int efx_mcdi_nvram_update_start(struct efx_nic *efx, unsigned int type)
return 0;
fail:
- EFX_ERR(efx, "%s: failed rc=%d\n", __func__, rc);
+ netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
return rc;
}
@@ -827,7 +837,7 @@ int efx_mcdi_nvram_read(struct efx_nic *efx, unsigned int type,
return 0;
fail:
- EFX_ERR(efx, "%s: failed rc=%d\n", __func__, rc);
+ netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
return rc;
}
@@ -853,7 +863,7 @@ int efx_mcdi_nvram_write(struct efx_nic *efx, unsigned int type,
return 0;
fail:
- EFX_ERR(efx, "%s: failed rc=%d\n", __func__, rc);
+ netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
return rc;
}
@@ -877,7 +887,7 @@ int efx_mcdi_nvram_erase(struct efx_nic *efx, unsigned int type,
return 0;
fail:
- EFX_ERR(efx, "%s: failed rc=%d\n", __func__, rc);
+ netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
return rc;
}
@@ -898,7 +908,7 @@ int efx_mcdi_nvram_update_finish(struct efx_nic *efx, unsigned int type)
return 0;
fail:
- EFX_ERR(efx, "%s: failed rc=%d\n", __func__, rc);
+ netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
return rc;
}
@@ -948,9 +958,10 @@ int efx_mcdi_nvram_test_all(struct efx_nic *efx)
return 0;
fail2:
- EFX_ERR(efx, "%s: failed type=%u\n", __func__, type);
+ netif_err(efx, hw, efx->net_dev, "%s: failed type=%u\n",
+ __func__, type);
fail1:
- EFX_ERR(efx, "%s: failed rc=%d\n", __func__, rc);
+ netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
return rc;
}
@@ -994,14 +1005,15 @@ static int efx_mcdi_read_assertion(struct efx_nic *efx)
: (flags == MC_CMD_GET_ASSERTS_FLAGS_WDOG_FIRED)
? "watchdog reset"
: "unknown assertion";
- EFX_ERR(efx, "MCPU %s at PC = 0x%.8x in thread 0x%.8x\n", reason,
- MCDI_DWORD(outbuf, GET_ASSERTS_OUT_SAVED_PC_OFFS),
- MCDI_DWORD(outbuf, GET_ASSERTS_OUT_THREAD_OFFS));
+ netif_err(efx, hw, efx->net_dev,
+ "MCPU %s at PC = 0x%.8x in thread 0x%.8x\n", reason,
+ MCDI_DWORD(outbuf, GET_ASSERTS_OUT_SAVED_PC_OFFS),
+ MCDI_DWORD(outbuf, GET_ASSERTS_OUT_THREAD_OFFS));
/* Print out the registers */
ofst = MC_CMD_GET_ASSERTS_OUT_GP_REGS_OFFS_OFST;
for (index = 1; index < 32; index++) {
- EFX_ERR(efx, "R%.2d (?): 0x%.8x\n", index,
+ netif_err(efx, hw, efx->net_dev, "R%.2d (?): 0x%.8x\n", index,
MCDI_DWORD2(outbuf, ofst));
ofst += sizeof(efx_dword_t);
}
@@ -1050,14 +1062,16 @@ void efx_mcdi_set_id_led(struct efx_nic *efx, enum efx_led_mode mode)
rc = efx_mcdi_rpc(efx, MC_CMD_SET_ID_LED, inbuf, sizeof(inbuf),
NULL, 0, NULL);
if (rc)
- EFX_ERR(efx, "%s: failed rc=%d\n", __func__, rc);
+ netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n",
+ __func__, rc);
}
int efx_mcdi_reset_port(struct efx_nic *efx)
{
int rc = efx_mcdi_rpc(efx, MC_CMD_PORT_RESET, NULL, 0, NULL, 0, NULL);
if (rc)
- EFX_ERR(efx, "%s: failed rc=%d\n", __func__, rc);
+ netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n",
+ __func__, rc);
return rc;
}
@@ -1075,12 +1089,12 @@ int efx_mcdi_reset_mc(struct efx_nic *efx)
return 0;
if (rc == 0)
rc = -EIO;
- EFX_ERR(efx, "%s: failed rc=%d\n", __func__, rc);
+ netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
return rc;
}
-int efx_mcdi_wol_filter_set(struct efx_nic *efx, u32 type,
- const u8 *mac, int *id_out)
+static int efx_mcdi_wol_filter_set(struct efx_nic *efx, u32 type,
+ const u8 *mac, int *id_out)
{
u8 inbuf[MC_CMD_WOL_FILTER_SET_IN_LEN];
u8 outbuf[MC_CMD_WOL_FILTER_SET_OUT_LEN];
@@ -1108,7 +1122,7 @@ int efx_mcdi_wol_filter_set(struct efx_nic *efx, u32 type,
fail:
*id_out = -1;
- EFX_ERR(efx, "%s: failed rc=%d\n", __func__, rc);
+ netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
return rc;
}
@@ -1143,7 +1157,7 @@ int efx_mcdi_wol_filter_get_magic(struct efx_nic *efx, int *id_out)
fail:
*id_out = -1;
- EFX_ERR(efx, "%s: failed rc=%d\n", __func__, rc);
+ netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
return rc;
}
@@ -1163,7 +1177,7 @@ int efx_mcdi_wol_filter_remove(struct efx_nic *efx, int id)
return 0;
fail:
- EFX_ERR(efx, "%s: failed rc=%d\n", __func__, rc);
+ netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
return rc;
}
@@ -1179,7 +1193,7 @@ int efx_mcdi_wol_filter_reset(struct efx_nic *efx)
return 0;
fail:
- EFX_ERR(efx, "%s: failed rc=%d\n", __func__, rc);
+ netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
return rc;
}
diff --git a/drivers/net/sfc/mcdi.h b/drivers/net/sfc/mcdi.h
index f1f89ad4075a..c792f1d65e48 100644
--- a/drivers/net/sfc/mcdi.h
+++ b/drivers/net/sfc/mcdi.h
@@ -121,8 +121,6 @@ extern int efx_mcdi_handle_assertion(struct efx_nic *efx);
extern void efx_mcdi_set_id_led(struct efx_nic *efx, enum efx_led_mode mode);
extern int efx_mcdi_reset_port(struct efx_nic *efx);
extern int efx_mcdi_reset_mc(struct efx_nic *efx);
-extern int efx_mcdi_wol_filter_set(struct efx_nic *efx, u32 type,
- const u8 *mac, int *id_out);
extern int efx_mcdi_wol_filter_set_magic(struct efx_nic *efx,
const u8 *mac, int *id_out);
extern int efx_mcdi_wol_filter_get_magic(struct efx_nic *efx, int *id_out);
diff --git a/drivers/net/sfc/mcdi_mac.c b/drivers/net/sfc/mcdi_mac.c
index 39182631ac92..f88f4bf986ff 100644
--- a/drivers/net/sfc/mcdi_mac.c
+++ b/drivers/net/sfc/mcdi_mac.c
@@ -69,8 +69,8 @@ static int efx_mcdi_get_mac_faults(struct efx_nic *efx, u32 *faults)
return 0;
fail:
- EFX_ERR(efx, "%s: failed rc=%d\n",
- __func__, rc);
+ netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n",
+ __func__, rc);
return rc;
}
@@ -110,8 +110,8 @@ int efx_mcdi_mac_stats(struct efx_nic *efx, dma_addr_t dma_addr,
return 0;
fail:
- EFX_ERR(efx, "%s: %s failed rc=%d\n",
- __func__, enable ? "enable" : "disable", rc);
+ netif_err(efx, hw, efx->net_dev, "%s: %s failed rc=%d\n",
+ __func__, enable ? "enable" : "disable", rc);
return rc;
}
diff --git a/drivers/net/sfc/mcdi_phy.c b/drivers/net/sfc/mcdi_phy.c
index 6032c0e1f1f8..c992742446b1 100644
--- a/drivers/net/sfc/mcdi_phy.c
+++ b/drivers/net/sfc/mcdi_phy.c
@@ -20,7 +20,7 @@
#include "nic.h"
#include "selftest.h"
-struct efx_mcdi_phy_cfg {
+struct efx_mcdi_phy_data {
u32 flags;
u32 type;
u32 supported_cap;
@@ -35,7 +35,7 @@ struct efx_mcdi_phy_cfg {
};
static int
-efx_mcdi_get_phy_cfg(struct efx_nic *efx, struct efx_mcdi_phy_cfg *cfg)
+efx_mcdi_get_phy_cfg(struct efx_nic *efx, struct efx_mcdi_phy_data *cfg)
{
u8 outbuf[MC_CMD_GET_PHY_CFG_OUT_LEN];
size_t outlen;
@@ -71,7 +71,7 @@ efx_mcdi_get_phy_cfg(struct efx_nic *efx, struct efx_mcdi_phy_cfg *cfg)
return 0;
fail:
- EFX_ERR(efx, "%s: failed rc=%d\n", __func__, rc);
+ netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
return rc;
}
@@ -97,7 +97,7 @@ static int efx_mcdi_set_link(struct efx_nic *efx, u32 capabilities,
return 0;
fail:
- EFX_ERR(efx, "%s: failed rc=%d\n", __func__, rc);
+ netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
return rc;
}
@@ -122,7 +122,7 @@ static int efx_mcdi_loopback_modes(struct efx_nic *efx, u64 *loopback_modes)
return 0;
fail:
- EFX_ERR(efx, "%s: failed rc=%d\n", __func__, rc);
+ netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
return rc;
}
@@ -150,7 +150,7 @@ int efx_mcdi_mdio_read(struct efx_nic *efx, unsigned int bus,
return 0;
fail:
- EFX_ERR(efx, "%s: failed rc=%d\n", __func__, rc);
+ netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
return rc;
}
@@ -178,7 +178,7 @@ int efx_mcdi_mdio_write(struct efx_nic *efx, unsigned int bus,
return 0;
fail:
- EFX_ERR(efx, "%s: failed rc=%d\n", __func__, rc);
+ netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
return rc;
}
@@ -259,7 +259,7 @@ static u32 ethtool_to_mcdi_cap(u32 cap)
static u32 efx_get_mcdi_phy_flags(struct efx_nic *efx)
{
- struct efx_mcdi_phy_cfg *phy_cfg = efx->phy_data;
+ struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
enum efx_phy_mode mode, supported;
u32 flags;
@@ -307,7 +307,7 @@ static u32 mcdi_to_ethtool_media(u32 media)
static int efx_mcdi_phy_probe(struct efx_nic *efx)
{
- struct efx_mcdi_phy_cfg *phy_data;
+ struct efx_mcdi_phy_data *phy_data;
u8 outbuf[MC_CMD_GET_LINK_OUT_LEN];
u32 caps;
int rc;
@@ -395,6 +395,7 @@ static int efx_mcdi_phy_probe(struct efx_nic *efx)
efx->wanted_fc = EFX_FC_RX | EFX_FC_TX;
if (phy_data->supported_cap & (1 << MC_CMD_PHY_CAP_AN_LBN))
efx->wanted_fc |= EFX_FC_AUTO;
+ efx_link_set_wanted_fc(efx, efx->wanted_fc);
return 0;
@@ -405,7 +406,7 @@ fail:
int efx_mcdi_phy_reconfigure(struct efx_nic *efx)
{
- struct efx_mcdi_phy_cfg *phy_cfg = efx->phy_data;
+ struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
u32 caps = (efx->link_advertising ?
ethtool_to_mcdi_cap(efx->link_advertising) :
phy_cfg->forced_cap);
@@ -446,7 +447,7 @@ void efx_mcdi_phy_decode_link(struct efx_nic *efx,
*/
void efx_mcdi_phy_check_fcntl(struct efx_nic *efx, u32 lpa)
{
- struct efx_mcdi_phy_cfg *phy_cfg = efx->phy_data;
+ struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
u32 rmtadv;
/* The link partner capabilities are only relevent if the
@@ -465,8 +466,8 @@ void efx_mcdi_phy_check_fcntl(struct efx_nic *efx, u32 lpa)
rmtadv |= ADVERTISED_Asym_Pause;
if ((efx->wanted_fc & EFX_FC_TX) && rmtadv == ADVERTISED_Asym_Pause)
- EFX_ERR(efx, "warning: link partner doesn't support "
- "pause frames");
+ netif_err(efx, link, efx->net_dev,
+ "warning: link partner doesn't support pause frames");
}
static bool efx_mcdi_phy_poll(struct efx_nic *efx)
@@ -482,7 +483,8 @@ static bool efx_mcdi_phy_poll(struct efx_nic *efx)
rc = efx_mcdi_rpc(efx, MC_CMD_GET_LINK, NULL, 0,
outbuf, sizeof(outbuf), NULL);
if (rc) {
- EFX_ERR(efx, "%s: failed rc=%d\n", __func__, rc);
+ netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n",
+ __func__, rc);
efx->link_state.up = false;
} else {
efx_mcdi_phy_decode_link(
@@ -505,7 +507,7 @@ static void efx_mcdi_phy_remove(struct efx_nic *efx)
static void efx_mcdi_phy_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
{
- struct efx_mcdi_phy_cfg *phy_cfg = efx->phy_data;
+ struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
u8 outbuf[MC_CMD_GET_LINK_OUT_LEN];
int rc;
@@ -525,7 +527,8 @@ static void efx_mcdi_phy_get_settings(struct efx_nic *efx, struct ethtool_cmd *e
rc = efx_mcdi_rpc(efx, MC_CMD_GET_LINK, NULL, 0,
outbuf, sizeof(outbuf), NULL);
if (rc) {
- EFX_ERR(efx, "%s: failed rc=%d\n", __func__, rc);
+ netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n",
+ __func__, rc);
return;
}
ecmd->lp_advertising =
@@ -535,7 +538,7 @@ static void efx_mcdi_phy_get_settings(struct efx_nic *efx, struct ethtool_cmd *e
static int efx_mcdi_phy_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
{
- struct efx_mcdi_phy_cfg *phy_cfg = efx->phy_data;
+ struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
u32 caps;
int rc;
@@ -674,7 +677,7 @@ out:
static int efx_mcdi_phy_run_tests(struct efx_nic *efx, int *results,
unsigned flags)
{
- struct efx_mcdi_phy_cfg *phy_cfg = efx->phy_data;
+ struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
u32 mode;
int rc;
@@ -710,9 +713,10 @@ static int efx_mcdi_phy_run_tests(struct efx_nic *efx, int *results,
return 0;
}
-const char *efx_mcdi_phy_test_name(struct efx_nic *efx, unsigned int index)
+static const char *efx_mcdi_phy_test_name(struct efx_nic *efx,
+ unsigned int index)
{
- struct efx_mcdi_phy_cfg *phy_cfg = efx->phy_data;
+ struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_BIST_LBN)) {
if (index == 0)
diff --git a/drivers/net/sfc/mdio_10g.c b/drivers/net/sfc/mdio_10g.c
index 0548fcbbdcd0..98d946020429 100644
--- a/drivers/net/sfc/mdio_10g.c
+++ b/drivers/net/sfc/mdio_10g.c
@@ -63,7 +63,8 @@ static int efx_mdio_check_mmd(struct efx_nic *efx, int mmd, int fault_fatal)
/* Read MMD STATUS2 to check it is responding. */
status = efx_mdio_read(efx, mmd, MDIO_STAT2);
if ((status & MDIO_STAT2_DEVPRST) != MDIO_STAT2_DEVPRST_VAL) {
- EFX_ERR(efx, "PHY MMD %d not responding.\n", mmd);
+ netif_err(efx, hw, efx->net_dev,
+ "PHY MMD %d not responding.\n", mmd);
return -EIO;
}
}
@@ -72,12 +73,14 @@ static int efx_mdio_check_mmd(struct efx_nic *efx, int mmd, int fault_fatal)
status = efx_mdio_read(efx, mmd, MDIO_STAT1);
if (status & MDIO_STAT1_FAULT) {
if (fault_fatal) {
- EFX_ERR(efx, "PHY MMD %d reporting fatal"
- " fault: status %x\n", mmd, status);
+ netif_err(efx, hw, efx->net_dev,
+ "PHY MMD %d reporting fatal"
+ " fault: status %x\n", mmd, status);
return -EIO;
} else {
- EFX_LOG(efx, "PHY MMD %d reporting status"
- " %x (expected)\n", mmd, status);
+ netif_dbg(efx, hw, efx->net_dev,
+ "PHY MMD %d reporting status"
+ " %x (expected)\n", mmd, status);
}
}
return 0;
@@ -103,8 +106,9 @@ int efx_mdio_wait_reset_mmds(struct efx_nic *efx, unsigned int mmd_mask)
if (mask & 1) {
stat = efx_mdio_read(efx, mmd, MDIO_CTRL1);
if (stat < 0) {
- EFX_ERR(efx, "failed to read status of"
- " MMD %d\n", mmd);
+ netif_err(efx, hw, efx->net_dev,
+ "failed to read status of"
+ " MMD %d\n", mmd);
return -EIO;
}
if (stat & MDIO_CTRL1_RESET)
@@ -119,8 +123,9 @@ int efx_mdio_wait_reset_mmds(struct efx_nic *efx, unsigned int mmd_mask)
msleep(spintime);
}
if (in_reset != 0) {
- EFX_ERR(efx, "not all MMDs came out of reset in time."
- " MMDs still in reset: %x\n", in_reset);
+ netif_err(efx, hw, efx->net_dev,
+ "not all MMDs came out of reset in time."
+ " MMDs still in reset: %x\n", in_reset);
rc = -ETIMEDOUT;
}
return rc;
@@ -142,16 +147,18 @@ int efx_mdio_check_mmds(struct efx_nic *efx,
devs1 = efx_mdio_read(efx, probe_mmd, MDIO_DEVS1);
devs2 = efx_mdio_read(efx, probe_mmd, MDIO_DEVS2);
if (devs1 < 0 || devs2 < 0) {
- EFX_ERR(efx, "failed to read devices present\n");
+ netif_err(efx, hw, efx->net_dev,
+ "failed to read devices present\n");
return -EIO;
}
devices = devs1 | (devs2 << 16);
if ((devices & mmd_mask) != mmd_mask) {
- EFX_ERR(efx, "required MMDs not present: got %x, "
- "wanted %x\n", devices, mmd_mask);
+ netif_err(efx, hw, efx->net_dev,
+ "required MMDs not present: got %x, wanted %x\n",
+ devices, mmd_mask);
return -ENODEV;
}
- EFX_TRACE(efx, "Devices present: %x\n", devices);
+ netif_vdbg(efx, hw, efx->net_dev, "Devices present: %x\n", devices);
/* Check all required MMDs are responding and happy. */
while (mmd_mask) {
@@ -219,7 +226,7 @@ static void efx_mdio_set_mmd_lpower(struct efx_nic *efx,
{
int stat = efx_mdio_read(efx, mmd, MDIO_STAT1);
- EFX_TRACE(efx, "Setting low power mode for MMD %d to %d\n",
+ netif_vdbg(efx, drv, efx->net_dev, "Setting low power mode for MMD %d to %d\n",
mmd, lpower);
if (stat & MDIO_STAT1_LPOWERABLE) {
@@ -279,46 +286,24 @@ int efx_mdio_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
*/
void efx_mdio_an_reconfigure(struct efx_nic *efx)
{
- bool xnp = (efx->link_advertising & ADVERTISED_10000baseT_Full
- || EFX_WORKAROUND_13204(efx));
int reg;
WARN_ON(!(efx->mdio.mmds & MDIO_DEVS_AN));
/* Set up the base page */
- reg = ADVERTISE_CSMA;
- if (efx->link_advertising & ADVERTISED_10baseT_Half)
- reg |= ADVERTISE_10HALF;
- if (efx->link_advertising & ADVERTISED_10baseT_Full)
- reg |= ADVERTISE_10FULL;
- if (efx->link_advertising & ADVERTISED_100baseT_Half)
- reg |= ADVERTISE_100HALF;
- if (efx->link_advertising & ADVERTISED_100baseT_Full)
- reg |= ADVERTISE_100FULL;
- if (xnp)
- reg |= ADVERTISE_RESV;
- else if (efx->link_advertising & (ADVERTISED_1000baseT_Half |
- ADVERTISED_1000baseT_Full))
- reg |= ADVERTISE_NPAGE;
+ reg = ADVERTISE_CSMA | ADVERTISE_RESV;
if (efx->link_advertising & ADVERTISED_Pause)
reg |= ADVERTISE_PAUSE_CAP;
if (efx->link_advertising & ADVERTISED_Asym_Pause)
reg |= ADVERTISE_PAUSE_ASYM;
efx_mdio_write(efx, MDIO_MMD_AN, MDIO_AN_ADVERTISE, reg);
- /* Set up the (extended) next page if necessary */
- if (efx->phy_op->set_npage_adv)
- efx->phy_op->set_npage_adv(efx, efx->link_advertising);
+ /* Set up the (extended) next page */
+ efx->phy_op->set_npage_adv(efx, efx->link_advertising);
/* Enable and restart AN */
reg = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_CTRL1);
- reg |= MDIO_AN_CTRL1_ENABLE;
- if (!(EFX_WORKAROUND_15195(efx) && LOOPBACK_EXTERNAL(efx)))
- reg |= MDIO_AN_CTRL1_RESTART;
- if (xnp)
- reg |= MDIO_AN_CTRL1_XNP;
- else
- reg &= ~MDIO_AN_CTRL1_XNP;
+ reg |= MDIO_AN_CTRL1_ENABLE | MDIO_AN_CTRL1_RESTART | MDIO_AN_CTRL1_XNP;
efx_mdio_write(efx, MDIO_MMD_AN, MDIO_CTRL1, reg);
}
@@ -349,8 +334,8 @@ int efx_mdio_test_alive(struct efx_nic *efx)
if ((physid1 == 0x0000) || (physid1 == 0xffff) ||
(physid2 == 0x0000) || (physid2 == 0xffff)) {
- EFX_ERR(efx, "no MDIO PHY present with ID %d\n",
- efx->mdio.prtad);
+ netif_err(efx, hw, efx->net_dev,
+ "no MDIO PHY present with ID %d\n", efx->mdio.prtad);
rc = -EINVAL;
} else {
rc = efx_mdio_check_mmds(efx, efx->mdio.mmds, 0);
diff --git a/drivers/net/sfc/mdio_10g.h b/drivers/net/sfc/mdio_10g.h
index f89e71929603..75791d3d4963 100644
--- a/drivers/net/sfc/mdio_10g.h
+++ b/drivers/net/sfc/mdio_10g.h
@@ -51,7 +51,8 @@ static inline bool efx_mdio_phyxgxs_lane_sync(struct efx_nic *efx)
sync = !!(lane_status & MDIO_PHYXS_LNSTAT_ALIGN);
if (!sync)
- EFX_LOG(efx, "XGXS lane status: %x\n", lane_status);
+ netif_dbg(efx, hw, efx->net_dev, "XGXS lane status: %x\n",
+ lane_status);
return sync;
}
diff --git a/drivers/net/sfc/mtd.c b/drivers/net/sfc/mtd.c
index f3ac7f30b5e7..02e54b4f701f 100644
--- a/drivers/net/sfc/mtd.c
+++ b/drivers/net/sfc/mtd.c
@@ -15,7 +15,6 @@
#include <linux/slab.h>
#include <linux/rtnetlink.h>
-#define EFX_DRIVER_NAME "sfc_mtd"
#include "net_driver.h"
#include "spi.h"
#include "efx.h"
@@ -71,8 +70,10 @@ static int siena_mtd_probe(struct efx_nic *efx);
/* SPI utilities */
-static int efx_spi_slow_wait(struct efx_mtd *efx_mtd, bool uninterruptible)
+static int
+efx_spi_slow_wait(struct efx_mtd_partition *part, bool uninterruptible)
{
+ struct efx_mtd *efx_mtd = part->mtd.priv;
const struct efx_spi_device *spi = efx_mtd->spi;
struct efx_nic *efx = efx_mtd->efx;
u8 status;
@@ -92,7 +93,7 @@ static int efx_spi_slow_wait(struct efx_mtd *efx_mtd, bool uninterruptible)
if (signal_pending(current))
return -EINTR;
}
- EFX_ERR(efx, "timed out waiting for %s\n", efx_mtd->name);
+ pr_err("%s: timed out waiting for %s\n", part->name, efx_mtd->name);
return -ETIMEDOUT;
}
@@ -131,8 +132,10 @@ efx_spi_unlock(struct efx_nic *efx, const struct efx_spi_device *spi)
return 0;
}
-static int efx_spi_erase(struct efx_mtd *efx_mtd, loff_t start, size_t len)
+static int
+efx_spi_erase(struct efx_mtd_partition *part, loff_t start, size_t len)
{
+ struct efx_mtd *efx_mtd = part->mtd.priv;
const struct efx_spi_device *spi = efx_mtd->spi;
struct efx_nic *efx = efx_mtd->efx;
unsigned pos, block_len;
@@ -156,7 +159,7 @@ static int efx_spi_erase(struct efx_mtd *efx_mtd, loff_t start, size_t len)
NULL, 0);
if (rc)
return rc;
- rc = efx_spi_slow_wait(efx_mtd, false);
+ rc = efx_spi_slow_wait(part, false);
/* Verify the entire region has been wiped */
memset(empty, 0xff, sizeof(empty));
@@ -198,13 +201,14 @@ static int efx_mtd_erase(struct mtd_info *mtd, struct erase_info *erase)
static void efx_mtd_sync(struct mtd_info *mtd)
{
+ struct efx_mtd_partition *part = to_efx_mtd_partition(mtd);
struct efx_mtd *efx_mtd = mtd->priv;
- struct efx_nic *efx = efx_mtd->efx;
int rc;
rc = efx_mtd->ops->sync(mtd);
if (rc)
- EFX_ERR(efx, "%s sync failed (%d)\n", efx_mtd->name, rc);
+ pr_err("%s: %s sync failed (%d)\n",
+ part->name, efx_mtd->name, rc);
}
static void efx_mtd_remove_partition(struct efx_mtd_partition *part)
@@ -338,7 +342,7 @@ static int falcon_mtd_erase(struct mtd_info *mtd, loff_t start, size_t len)
rc = mutex_lock_interruptible(&efx->spi_lock);
if (rc)
return rc;
- rc = efx_spi_erase(efx_mtd, part->offset + start, len);
+ rc = efx_spi_erase(part, part->offset + start, len);
mutex_unlock(&efx->spi_lock);
return rc;
}
@@ -363,12 +367,13 @@ static int falcon_mtd_write(struct mtd_info *mtd, loff_t start,
static int falcon_mtd_sync(struct mtd_info *mtd)
{
+ struct efx_mtd_partition *part = to_efx_mtd_partition(mtd);
struct efx_mtd *efx_mtd = mtd->priv;
struct efx_nic *efx = efx_mtd->efx;
int rc;
mutex_lock(&efx->spi_lock);
- rc = efx_spi_slow_wait(efx_mtd, true);
+ rc = efx_spi_slow_wait(part, true);
mutex_unlock(&efx->spi_lock);
return rc;
}
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h
index 4762c91cb587..0a7e26d73b52 100644
--- a/drivers/net/sfc/net_driver.h
+++ b/drivers/net/sfc/net_driver.h
@@ -13,17 +13,23 @@
#ifndef EFX_NET_DRIVER_H
#define EFX_NET_DRIVER_H
+#if defined(EFX_ENABLE_DEBUG) && !defined(DEBUG)
+#define DEBUG
+#endif
+
#include <linux/version.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
#include <linux/if_vlan.h>
+#include <linux/timer.h>
#include <linux/mdio.h>
#include <linux/list.h>
#include <linux/pci.h>
#include <linux/device.h>
#include <linux/highmem.h>
#include <linux/workqueue.h>
+#include <linux/vmalloc.h>
#include <linux/i2c.h>
#include "enum.h"
@@ -34,9 +40,7 @@
* Build definitions
*
**************************************************************************/
-#ifndef EFX_DRIVER_NAME
-#define EFX_DRIVER_NAME "sfc"
-#endif
+
#define EFX_DRIVER_VERSION "3.0"
#ifdef EFX_ENABLE_DEBUG
@@ -47,35 +51,6 @@
#define EFX_WARN_ON_PARANOID(x) do {} while (0)
#endif
-/* Un-rate-limited logging */
-#define EFX_ERR(efx, fmt, args...) \
-dev_err(&((efx)->pci_dev->dev), "ERR: %s " fmt, efx_dev_name(efx), ##args)
-
-#define EFX_INFO(efx, fmt, args...) \
-dev_info(&((efx)->pci_dev->dev), "INFO: %s " fmt, efx_dev_name(efx), ##args)
-
-#ifdef EFX_ENABLE_DEBUG
-#define EFX_LOG(efx, fmt, args...) \
-dev_info(&((efx)->pci_dev->dev), "DBG: %s " fmt, efx_dev_name(efx), ##args)
-#else
-#define EFX_LOG(efx, fmt, args...) \
-dev_dbg(&((efx)->pci_dev->dev), "DBG: %s " fmt, efx_dev_name(efx), ##args)
-#endif
-
-#define EFX_TRACE(efx, fmt, args...) do {} while (0)
-
-#define EFX_REGDUMP(efx, fmt, args...) do {} while (0)
-
-/* Rate-limited logging */
-#define EFX_ERR_RL(efx, fmt, args...) \
-do {if (net_ratelimit()) EFX_ERR(efx, fmt, ##args); } while (0)
-
-#define EFX_INFO_RL(efx, fmt, args...) \
-do {if (net_ratelimit()) EFX_INFO(efx, fmt, ##args); } while (0)
-
-#define EFX_LOG_RL(efx, fmt, args...) \
-do {if (net_ratelimit()) EFX_LOG(efx, fmt, ##args); } while (0)
-
/**************************************************************************
*
* Efx data structures
@@ -163,6 +138,7 @@ struct efx_tx_buffer {
* @channel: The associated channel
* @buffer: The software buffer ring
* @txd: The hardware descriptor ring
+ * @ptr_mask: The size of the ring minus 1.
* @flushed: Used when handling queue flushing
* @read_count: Current read pointer.
* This is the number of buffers that have been removed from both rings.
@@ -196,6 +172,7 @@ struct efx_tx_queue {
struct efx_nic *nic;
struct efx_tx_buffer *buffer;
struct efx_special_buffer txd;
+ unsigned int ptr_mask;
enum efx_flush_state flushed;
/* Members used mainly on the completion path */
@@ -221,7 +198,6 @@ struct efx_tx_queue {
* If both this and skb are %NULL, the buffer slot is currently free.
* @data: Pointer to ethernet header
* @len: Buffer length, in bytes.
- * @unmap_addr: DMA address to unmap
*/
struct efx_rx_buffer {
dma_addr_t dma_addr;
@@ -229,23 +205,35 @@ struct efx_rx_buffer {
struct page *page;
char *data;
unsigned int len;
- dma_addr_t unmap_addr;
+};
+
+/**
+ * struct efx_rx_page_state - Page-based rx buffer state
+ *
+ * Inserted at the start of every page allocated for receive buffers.
+ * Used to facilitate sharing dma mappings between recycled rx buffers
+ * and those passed up to the kernel.
+ *
+ * @refcnt: Number of struct efx_rx_buffer's referencing this page.
+ * When refcnt falls to zero, the page is unmapped for dma
+ * @dma_addr: The dma address of this page.
+ */
+struct efx_rx_page_state {
+ unsigned refcnt;
+ dma_addr_t dma_addr;
+
+ unsigned int __pad[0] ____cacheline_aligned;
};
/**
* struct efx_rx_queue - An Efx RX queue
* @efx: The associated Efx NIC
- * @queue: DMA queue number
- * @channel: The associated channel
* @buffer: The software buffer ring
* @rxd: The hardware descriptor ring
+ * @ptr_mask: The size of the ring minus 1.
* @added_count: Number of buffers added to the receive queue.
* @notified_count: Number of buffers given to NIC (<= @added_count).
* @removed_count: Number of buffers removed from the receive queue.
- * @add_lock: Receive queue descriptor add spin lock.
- * This lock must be held in order to add buffers to the RX
- * descriptor ring (rxd and buffer) and to update added_count (but
- * not removed_count).
* @max_fill: RX descriptor maximum fill level (<= ring size)
* @fast_fill_trigger: RX descriptor fill level that will trigger a fast fill
* (<= @max_fill)
@@ -254,30 +242,20 @@ struct efx_rx_buffer {
* @min_fill: RX descriptor minimum non-zero fill level.
* This records the minimum fill level observed when a ring
* refill was triggered.
- * @min_overfill: RX descriptor minimum overflow fill level.
- * This records the minimum fill level at which RX queue
- * overflow was observed. It should never be set.
* @alloc_page_count: RX allocation strategy counter.
* @alloc_skb_count: RX allocation strategy counter.
- * @work: Descriptor push work thread
- * @buf_page: Page for next RX buffer.
- * We can use a single page for multiple RX buffers. This tracks
- * the remaining space in the allocation.
- * @buf_dma_addr: Page's DMA address.
- * @buf_data: Page's host address.
+ * @slow_fill: Timer used to defer efx_nic_generate_fill_event().
* @flushed: Use when handling queue flushing
*/
struct efx_rx_queue {
struct efx_nic *efx;
- int queue;
- struct efx_channel *channel;
struct efx_rx_buffer *buffer;
struct efx_special_buffer rxd;
+ unsigned int ptr_mask;
int added_count;
int notified_count;
int removed_count;
- spinlock_t add_lock;
unsigned int max_fill;
unsigned int fast_fill_trigger;
unsigned int fast_fill_limit;
@@ -285,12 +263,9 @@ struct efx_rx_queue {
unsigned int min_overfill;
unsigned int alloc_page_count;
unsigned int alloc_skb_count;
- struct delayed_work work;
+ struct timer_list slow_fill;
unsigned int slow_fill_count;
- struct page *buf_page;
- dma_addr_t buf_dma_addr;
- char *buf_data;
enum efx_flush_state flushed;
};
@@ -325,7 +300,6 @@ enum efx_rx_alloc_method {
*
* @efx: Associated Efx NIC
* @channel: Channel instance number
- * @name: Name for channel and IRQ
* @enabled: Channel enabled indicator
* @irq: IRQ number (MSI and MSI-X only)
* @irq_moderation: IRQ moderation value (in hardware ticks)
@@ -334,9 +308,10 @@ enum efx_rx_alloc_method {
* @reset_work: Scheduled reset work thread
* @work_pending: Is work pending via NAPI?
* @eventq: Event queue buffer
+ * @eventq_mask: Event queue pointer mask
* @eventq_read_ptr: Event queue read pointer
* @last_eventq_read_ptr: Last event queue read pointer value.
- * @eventq_magic: Event queue magic value for driver-generated test events
+ * @magic_count: Event queue test event count
* @irq_count: Number of IRQs since last adaptive moderation decision
* @irq_mod_score: IRQ moderation score
* @rx_alloc_level: Watermark based heuristic counter for pushing descriptors
@@ -350,14 +325,14 @@ enum efx_rx_alloc_method {
* @n_rx_frm_trunc: Count of RX_FRM_TRUNC errors
* @n_rx_overlength: Count of RX_OVERLENGTH errors
* @n_skbuff_leaks: Count of skbuffs leaked due to RX overrun
- * @tx_queue: Pointer to first TX queue, or %NULL if not used for TX
+ * @rx_queue: RX queue for this channel
* @tx_stop_count: Core TX queue stop count
* @tx_stop_lock: Core TX queue stop lock
+ * @tx_queue: TX queues for this channel
*/
struct efx_channel {
struct efx_nic *efx;
int channel;
- char name[IFNAMSIZ + 6];
bool enabled;
int irq;
unsigned int irq_moderation;
@@ -365,9 +340,10 @@ struct efx_channel {
struct napi_struct napi_str;
bool work_pending;
struct efx_special_buffer eventq;
+ unsigned int eventq_mask;
unsigned int eventq_read_ptr;
unsigned int last_eventq_read_ptr;
- unsigned int eventq_magic;
+ unsigned int magic_count;
unsigned int irq_count;
unsigned int irq_mod_score;
@@ -389,9 +365,12 @@ struct efx_channel {
struct efx_rx_buffer *rx_pkt;
bool rx_pkt_csummed;
- struct efx_tx_queue *tx_queue;
+ struct efx_rx_queue rx_queue;
+
atomic_t tx_stop_count;
spinlock_t tx_stop_lock;
+
+ struct efx_tx_queue tx_queue[2];
};
enum efx_led_mode {
@@ -408,11 +387,6 @@ extern const unsigned int efx_loopback_mode_max;
#define LOOPBACK_MODE(efx) \
STRING_TABLE_LOOKUP((efx)->loopback_mode, efx_loopback_mode)
-extern const char *efx_interrupt_mode_names[];
-extern const unsigned int efx_interrupt_mode_max;
-#define INT_MODE(efx) \
- STRING_TABLE_LOOKUP(efx->interrupt_mode, efx_interrupt_mode)
-
extern const char *efx_reset_type_names[];
extern const unsigned int efx_reset_type_max;
#define RESET_TYPE(type) \
@@ -427,8 +401,6 @@ enum efx_int_mode {
};
#define EFX_INT_MODE_USE_MSI(x) (((x)->interrupt_mode) <= EFX_INT_MODE_MSI)
-#define EFX_IS10G(efx) ((efx)->link_state.speed == 10000)
-
enum nic_state {
STATE_INIT = 0,
STATE_RUNNING = 1,
@@ -641,6 +613,8 @@ union efx_multicast_hash {
efx_oword_t oword[EFX_MCAST_HASH_ENTRIES / sizeof(efx_oword_t) / 8];
};
+struct efx_filter_state;
+
/**
* struct efx_nic - an Efx NIC
* @name: Device name (net device name or bus id before net device registered)
@@ -658,17 +632,22 @@ union efx_multicast_hash {
* @interrupt_mode: Interrupt mode
* @irq_rx_adaptive: Adaptive IRQ moderation enabled for RX event queues
* @irq_rx_moderation: IRQ moderation time for RX event queues
+ * @msg_enable: Log message enable flags
* @state: Device state flag. Serialised by the rtnl_lock.
* @reset_pending: Pending reset method (normally RESET_TYPE_NONE)
* @tx_queue: TX DMA queues
* @rx_queue: RX DMA queues
* @channel: Channels
+ * @channel_name: Names for channels and their IRQs
+ * @rxq_entries: Size of receive queues requested by user.
+ * @txq_entries: Size of transmit queues requested by user.
* @next_buffer_table: First available buffer table id
* @n_channels: Number of channels in use
* @n_rx_channels: Number of channels used for RX (= number of RX queues)
* @n_tx_channels: Number of channels used for TX
* @rx_buffer_len: RX buffer length
* @rx_buffer_order: Order (log2) of number of pages for each RX buffer
+ * @rx_indir_table: Indirection table for RSS
* @int_error_count: Number of internal errors seen recently
* @int_error_expire: Time at which error count will be expired
* @irq_status: Interrupt status buffer
@@ -740,20 +719,24 @@ struct efx_nic {
enum efx_int_mode interrupt_mode;
bool irq_rx_adaptive;
unsigned int irq_rx_moderation;
+ u32 msg_enable;
enum nic_state state;
enum reset_type reset_pending;
- struct efx_tx_queue tx_queue[EFX_MAX_TX_QUEUES];
- struct efx_rx_queue rx_queue[EFX_MAX_RX_QUEUES];
- struct efx_channel channel[EFX_MAX_CHANNELS];
+ struct efx_channel *channel[EFX_MAX_CHANNELS];
+ char channel_name[EFX_MAX_CHANNELS][IFNAMSIZ + 6];
+ unsigned rxq_entries;
+ unsigned txq_entries;
unsigned next_buffer_table;
unsigned n_channels;
unsigned n_rx_channels;
unsigned n_tx_channels;
unsigned int rx_buffer_len;
unsigned int rx_buffer_order;
+ u8 rx_hash_key[40];
+ u32 rx_indir_table[128];
unsigned int_error_count;
unsigned long int_error_expire;
@@ -812,6 +795,8 @@ struct efx_nic {
u64 loopback_modes;
void *loopback_selftest;
+
+ struct efx_filter_state *filter_state;
};
static inline int efx_dev_registered(struct efx_nic *efx)
@@ -866,7 +851,8 @@ static inline unsigned int efx_port_num(struct efx_nic *efx)
* @evq_ptr_tbl_base: Event queue pointer table base address
* @evq_rptr_tbl_base: Event queue read-pointer table base address
* @max_dma_mask: Maximum possible DMA mask
- * @rx_buffer_padding: Padding added to each RX buffer
+ * @rx_buffer_hash_size: Size of hash at start of RX buffer
+ * @rx_buffer_padding: Size of padding at end of RX buffer
* @max_interrupt_mode: Highest capability interrupt mode supported
* from &enum efx_init_mode.
* @phys_addr_channels: Number of channels with physically addressed
@@ -910,6 +896,7 @@ struct efx_nic_type {
unsigned int evq_ptr_tbl_base;
unsigned int evq_rptr_tbl_base;
u64 max_dma_mask;
+ unsigned int rx_buffer_hash_size;
unsigned int rx_buffer_padding;
unsigned int max_interrupt_mode;
unsigned int phys_addr_channels;
@@ -925,39 +912,67 @@ struct efx_nic_type {
*
*************************************************************************/
+static inline struct efx_channel *
+efx_get_channel(struct efx_nic *efx, unsigned index)
+{
+ EFX_BUG_ON_PARANOID(index >= efx->n_channels);
+ return efx->channel[index];
+}
+
/* Iterate over all used channels */
#define efx_for_each_channel(_channel, _efx) \
- for (_channel = &((_efx)->channel[0]); \
- _channel < &((_efx)->channel[(efx)->n_channels]); \
- _channel++)
-
-/* Iterate over all used TX queues */
-#define efx_for_each_tx_queue(_tx_queue, _efx) \
- for (_tx_queue = &((_efx)->tx_queue[0]); \
- _tx_queue < &((_efx)->tx_queue[EFX_TXQ_TYPES * \
- (_efx)->n_tx_channels]); \
- _tx_queue++)
+ for (_channel = (_efx)->channel[0]; \
+ _channel; \
+ _channel = (_channel->channel + 1 < (_efx)->n_channels) ? \
+ (_efx)->channel[_channel->channel + 1] : NULL)
+
+extern struct efx_tx_queue *
+efx_get_tx_queue(struct efx_nic *efx, unsigned index, unsigned type);
+
+static inline struct efx_tx_queue *
+efx_channel_get_tx_queue(struct efx_channel *channel, unsigned type)
+{
+ struct efx_tx_queue *tx_queue = channel->tx_queue;
+ EFX_BUG_ON_PARANOID(type >= EFX_TXQ_TYPES);
+ return tx_queue->channel ? tx_queue + type : NULL;
+}
/* Iterate over all TX queues belonging to a channel */
#define efx_for_each_channel_tx_queue(_tx_queue, _channel) \
- for (_tx_queue = (_channel)->tx_queue; \
+ for (_tx_queue = efx_channel_get_tx_queue(channel, 0); \
_tx_queue && _tx_queue < (_channel)->tx_queue + EFX_TXQ_TYPES; \
_tx_queue++)
-/* Iterate over all used RX queues */
-#define efx_for_each_rx_queue(_rx_queue, _efx) \
- for (_rx_queue = &((_efx)->rx_queue[0]); \
- _rx_queue < &((_efx)->rx_queue[(_efx)->n_rx_channels]); \
- _rx_queue++)
+static inline struct efx_rx_queue *
+efx_get_rx_queue(struct efx_nic *efx, unsigned index)
+{
+ EFX_BUG_ON_PARANOID(index >= efx->n_rx_channels);
+ return &efx->channel[index]->rx_queue;
+}
+
+static inline struct efx_rx_queue *
+efx_channel_get_rx_queue(struct efx_channel *channel)
+{
+ return channel->channel < channel->efx->n_rx_channels ?
+ &channel->rx_queue : NULL;
+}
/* Iterate over all RX queues belonging to a channel */
#define efx_for_each_channel_rx_queue(_rx_queue, _channel) \
- for (_rx_queue = &((_channel)->efx->rx_queue[(_channel)->channel]); \
+ for (_rx_queue = efx_channel_get_rx_queue(channel); \
_rx_queue; \
- _rx_queue = NULL) \
- if (_rx_queue->channel != (_channel)) \
- continue; \
- else
+ _rx_queue = NULL)
+
+static inline struct efx_channel *
+efx_rx_queue_channel(struct efx_rx_queue *rx_queue)
+{
+ return container_of(rx_queue, struct efx_channel, rx_queue);
+}
+
+static inline int efx_rx_queue_index(struct efx_rx_queue *rx_queue)
+{
+ return efx_rx_queue_channel(rx_queue)->channel;
+}
/* Returns a pointer to the specified receive buffer in the RX
* descriptor queue.
@@ -965,7 +980,7 @@ struct efx_nic_type {
static inline struct efx_rx_buffer *efx_rx_buffer(struct efx_rx_queue *rx_queue,
unsigned int index)
{
- return (&rx_queue->buffer[index]);
+ return &rx_queue->buffer[index];
}
/* Set bit in a little-endian bitfield */
diff --git a/drivers/net/sfc/nic.c b/drivers/net/sfc/nic.c
index 5d3aaec58556..41c36b9a4244 100644
--- a/drivers/net/sfc/nic.c
+++ b/drivers/net/sfc/nic.c
@@ -79,6 +79,14 @@ MODULE_PARM_DESC(rx_xon_thresh_bytes, "RX fifo XON threshold");
/* Depth of RX flush request fifo */
#define EFX_RX_FLUSH_COUNT 4
+/* Generated event code for efx_generate_test_event() */
+#define EFX_CHANNEL_MAGIC_TEST(_channel) \
+ (0x00010100 + (_channel)->channel)
+
+/* Generated event code for efx_generate_fill_event() */
+#define EFX_CHANNEL_MAGIC_FILL(_channel) \
+ (0x00010200 + (_channel)->channel)
+
/**************************************************************************
*
* Solarstorm hardware access
@@ -96,7 +104,7 @@ static inline void efx_write_buf_tbl(struct efx_nic *efx, efx_qword_t *value,
static inline efx_qword_t *efx_event(struct efx_channel *channel,
unsigned int index)
{
- return (((efx_qword_t *) (channel->eventq.addr)) + index);
+ return ((efx_qword_t *) (channel->eventq.addr)) + index;
}
/* See if an event is present
@@ -111,8 +119,8 @@ static inline efx_qword_t *efx_event(struct efx_channel *channel,
*/
static inline int efx_event_present(efx_qword_t *event)
{
- return (!(EFX_DWORD_IS_ALL_ONES(event->dword[0]) |
- EFX_DWORD_IS_ALL_ONES(event->dword[1])));
+ return !(EFX_DWORD_IS_ALL_ONES(event->dword[0]) |
+ EFX_DWORD_IS_ALL_ONES(event->dword[1]));
}
static bool efx_masked_compare_oword(const efx_oword_t *a, const efx_oword_t *b,
@@ -171,9 +179,10 @@ int efx_nic_test_registers(struct efx_nic *efx,
return 0;
fail:
- EFX_ERR(efx, "wrote "EFX_OWORD_FMT" read "EFX_OWORD_FMT
- " at address 0x%x mask "EFX_OWORD_FMT"\n", EFX_OWORD_VAL(reg),
- EFX_OWORD_VAL(buf), address, EFX_OWORD_VAL(mask));
+ netif_err(efx, hw, efx->net_dev,
+ "wrote "EFX_OWORD_FMT" read "EFX_OWORD_FMT
+ " at address 0x%x mask "EFX_OWORD_FMT"\n", EFX_OWORD_VAL(reg),
+ EFX_OWORD_VAL(buf), address, EFX_OWORD_VAL(mask));
return -EIO;
}
@@ -206,8 +215,9 @@ efx_init_special_buffer(struct efx_nic *efx, struct efx_special_buffer *buffer)
for (i = 0; i < buffer->entries; i++) {
index = buffer->index + i;
dma_addr = buffer->dma_addr + (i * 4096);
- EFX_LOG(efx, "mapping special buffer %d at %llx\n",
- index, (unsigned long long)dma_addr);
+ netif_dbg(efx, probe, efx->net_dev,
+ "mapping special buffer %d at %llx\n",
+ index, (unsigned long long)dma_addr);
EFX_POPULATE_QWORD_3(buf_desc,
FRF_AZ_BUF_ADR_REGION, 0,
FRF_AZ_BUF_ADR_FBUF, dma_addr >> 12,
@@ -227,8 +237,8 @@ efx_fini_special_buffer(struct efx_nic *efx, struct efx_special_buffer *buffer)
if (!buffer->entries)
return;
- EFX_LOG(efx, "unmapping special buffers %d-%d\n",
- buffer->index, buffer->index + buffer->entries - 1);
+ netif_dbg(efx, hw, efx->net_dev, "unmapping special buffers %d-%d\n",
+ buffer->index, buffer->index + buffer->entries - 1);
EFX_POPULATE_OWORD_4(buf_tbl_upd,
FRF_AZ_BUF_UPD_CMD, 0,
@@ -253,8 +263,8 @@ static int efx_alloc_special_buffer(struct efx_nic *efx,
{
len = ALIGN(len, EFX_BUF_SIZE);
- buffer->addr = pci_alloc_consistent(efx->pci_dev, len,
- &buffer->dma_addr);
+ buffer->addr = dma_alloc_coherent(&efx->pci_dev->dev, len,
+ &buffer->dma_addr, GFP_KERNEL);
if (!buffer->addr)
return -ENOMEM;
buffer->len = len;
@@ -268,11 +278,12 @@ static int efx_alloc_special_buffer(struct efx_nic *efx,
buffer->index = efx->next_buffer_table;
efx->next_buffer_table += buffer->entries;
- EFX_LOG(efx, "allocating special buffers %d-%d at %llx+%x "
- "(virt %p phys %llx)\n", buffer->index,
- buffer->index + buffer->entries - 1,
- (u64)buffer->dma_addr, len,
- buffer->addr, (u64)virt_to_phys(buffer->addr));
+ netif_dbg(efx, probe, efx->net_dev,
+ "allocating special buffers %d-%d at %llx+%x "
+ "(virt %p phys %llx)\n", buffer->index,
+ buffer->index + buffer->entries - 1,
+ (u64)buffer->dma_addr, len,
+ buffer->addr, (u64)virt_to_phys(buffer->addr));
return 0;
}
@@ -283,14 +294,15 @@ efx_free_special_buffer(struct efx_nic *efx, struct efx_special_buffer *buffer)
if (!buffer->addr)
return;
- EFX_LOG(efx, "deallocating special buffers %d-%d at %llx+%x "
- "(virt %p phys %llx)\n", buffer->index,
- buffer->index + buffer->entries - 1,
- (u64)buffer->dma_addr, buffer->len,
- buffer->addr, (u64)virt_to_phys(buffer->addr));
+ netif_dbg(efx, hw, efx->net_dev,
+ "deallocating special buffers %d-%d at %llx+%x "
+ "(virt %p phys %llx)\n", buffer->index,
+ buffer->index + buffer->entries - 1,
+ (u64)buffer->dma_addr, buffer->len,
+ buffer->addr, (u64)virt_to_phys(buffer->addr));
- pci_free_consistent(efx->pci_dev, buffer->len, buffer->addr,
- buffer->dma_addr);
+ dma_free_coherent(&efx->pci_dev->dev, buffer->len, buffer->addr,
+ buffer->dma_addr);
buffer->addr = NULL;
buffer->entries = 0;
}
@@ -335,7 +347,7 @@ void efx_nic_free_buffer(struct efx_nic *efx, struct efx_buffer *buffer)
static inline efx_qword_t *
efx_tx_desc(struct efx_tx_queue *tx_queue, unsigned int index)
{
- return (((efx_qword_t *) (tx_queue->txd.addr)) + index);
+ return ((efx_qword_t *) (tx_queue->txd.addr)) + index;
}
/* This writes to the TX_DESC_WPTR; write pointer for TX descriptor ring */
@@ -344,7 +356,7 @@ static inline void efx_notify_tx_desc(struct efx_tx_queue *tx_queue)
unsigned write_ptr;
efx_dword_t reg;
- write_ptr = tx_queue->write_count & EFX_TXQ_MASK;
+ write_ptr = tx_queue->write_count & tx_queue->ptr_mask;
EFX_POPULATE_DWORD_1(reg, FRF_AZ_TX_DESC_WPTR_DWORD, write_ptr);
efx_writed_page(tx_queue->efx, &reg,
FR_AZ_TX_DESC_UPD_DWORD_P0, tx_queue->queue);
@@ -365,7 +377,7 @@ void efx_nic_push_buffers(struct efx_tx_queue *tx_queue)
BUG_ON(tx_queue->write_count == tx_queue->insert_count);
do {
- write_ptr = tx_queue->write_count & EFX_TXQ_MASK;
+ write_ptr = tx_queue->write_count & tx_queue->ptr_mask;
buffer = &tx_queue->buffer[write_ptr];
txd = efx_tx_desc(tx_queue, write_ptr);
++tx_queue->write_count;
@@ -386,10 +398,11 @@ void efx_nic_push_buffers(struct efx_tx_queue *tx_queue)
int efx_nic_probe_tx(struct efx_tx_queue *tx_queue)
{
struct efx_nic *efx = tx_queue->efx;
- BUILD_BUG_ON(EFX_TXQ_SIZE < 512 || EFX_TXQ_SIZE > 4096 ||
- EFX_TXQ_SIZE & EFX_TXQ_MASK);
+ unsigned entries;
+
+ entries = tx_queue->ptr_mask + 1;
return efx_alloc_special_buffer(efx, &tx_queue->txd,
- EFX_TXQ_SIZE * sizeof(efx_qword_t));
+ entries * sizeof(efx_qword_t));
}
void efx_nic_init_tx(struct efx_tx_queue *tx_queue)
@@ -489,7 +502,7 @@ void efx_nic_remove_tx(struct efx_tx_queue *tx_queue)
static inline efx_qword_t *
efx_rx_desc(struct efx_rx_queue *rx_queue, unsigned int index)
{
- return (((efx_qword_t *) (rx_queue->rxd.addr)) + index);
+ return ((efx_qword_t *) (rx_queue->rxd.addr)) + index;
}
/* This creates an entry in the RX descriptor queue */
@@ -514,30 +527,32 @@ efx_build_rx_desc(struct efx_rx_queue *rx_queue, unsigned index)
*/
void efx_nic_notify_rx_desc(struct efx_rx_queue *rx_queue)
{
+ struct efx_nic *efx = rx_queue->efx;
efx_dword_t reg;
unsigned write_ptr;
while (rx_queue->notified_count != rx_queue->added_count) {
- efx_build_rx_desc(rx_queue,
- rx_queue->notified_count &
- EFX_RXQ_MASK);
+ efx_build_rx_desc(
+ rx_queue,
+ rx_queue->notified_count & rx_queue->ptr_mask);
++rx_queue->notified_count;
}
wmb();
- write_ptr = rx_queue->added_count & EFX_RXQ_MASK;
+ write_ptr = rx_queue->added_count & rx_queue->ptr_mask;
EFX_POPULATE_DWORD_1(reg, FRF_AZ_RX_DESC_WPTR_DWORD, write_ptr);
- efx_writed_page(rx_queue->efx, &reg,
- FR_AZ_RX_DESC_UPD_DWORD_P0, rx_queue->queue);
+ efx_writed_page(efx, &reg, FR_AZ_RX_DESC_UPD_DWORD_P0,
+ efx_rx_queue_index(rx_queue));
}
int efx_nic_probe_rx(struct efx_rx_queue *rx_queue)
{
struct efx_nic *efx = rx_queue->efx;
- BUILD_BUG_ON(EFX_RXQ_SIZE < 512 || EFX_RXQ_SIZE > 4096 ||
- EFX_RXQ_SIZE & EFX_RXQ_MASK);
+ unsigned entries;
+
+ entries = rx_queue->ptr_mask + 1;
return efx_alloc_special_buffer(efx, &rx_queue->rxd,
- EFX_RXQ_SIZE * sizeof(efx_qword_t));
+ entries * sizeof(efx_qword_t));
}
void efx_nic_init_rx(struct efx_rx_queue *rx_queue)
@@ -547,9 +562,10 @@ void efx_nic_init_rx(struct efx_rx_queue *rx_queue)
bool is_b0 = efx_nic_rev(efx) >= EFX_REV_FALCON_B0;
bool iscsi_digest_en = is_b0;
- EFX_LOG(efx, "RX queue %d ring in special buffers %d-%d\n",
- rx_queue->queue, rx_queue->rxd.index,
- rx_queue->rxd.index + rx_queue->rxd.entries - 1);
+ netif_dbg(efx, hw, efx->net_dev,
+ "RX queue %d ring in special buffers %d-%d\n",
+ efx_rx_queue_index(rx_queue), rx_queue->rxd.index,
+ rx_queue->rxd.index + rx_queue->rxd.entries - 1);
rx_queue->flushed = FLUSH_NONE;
@@ -562,9 +578,10 @@ void efx_nic_init_rx(struct efx_rx_queue *rx_queue)
FRF_AZ_RX_ISCSI_HDIG_EN, iscsi_digest_en,
FRF_AZ_RX_DESCQ_BUF_BASE_ID, rx_queue->rxd.index,
FRF_AZ_RX_DESCQ_EVQ_ID,
- rx_queue->channel->channel,
+ efx_rx_queue_channel(rx_queue)->channel,
FRF_AZ_RX_DESCQ_OWNER_ID, 0,
- FRF_AZ_RX_DESCQ_LABEL, rx_queue->queue,
+ FRF_AZ_RX_DESCQ_LABEL,
+ efx_rx_queue_index(rx_queue),
FRF_AZ_RX_DESCQ_SIZE,
__ffs(rx_queue->rxd.entries),
FRF_AZ_RX_DESCQ_TYPE, 0 /* kernel queue */ ,
@@ -572,7 +589,7 @@ void efx_nic_init_rx(struct efx_rx_queue *rx_queue)
FRF_AZ_RX_DESCQ_JUMBO, !is_b0,
FRF_AZ_RX_DESCQ_EN, 1);
efx_writeo_table(efx, &rx_desc_ptr, efx->type->rxd_ptr_tbl_base,
- rx_queue->queue);
+ efx_rx_queue_index(rx_queue));
}
static void efx_flush_rx_queue(struct efx_rx_queue *rx_queue)
@@ -585,7 +602,8 @@ static void efx_flush_rx_queue(struct efx_rx_queue *rx_queue)
/* Post a flush command */
EFX_POPULATE_OWORD_2(rx_flush_descq,
FRF_AZ_RX_FLUSH_DESCQ_CMD, 1,
- FRF_AZ_RX_FLUSH_DESCQ, rx_queue->queue);
+ FRF_AZ_RX_FLUSH_DESCQ,
+ efx_rx_queue_index(rx_queue));
efx_writeo(efx, &rx_flush_descq, FR_AZ_RX_FLUSH_DESCQ);
}
@@ -600,7 +618,7 @@ void efx_nic_fini_rx(struct efx_rx_queue *rx_queue)
/* Remove RX descriptor ring from card */
EFX_ZERO_OWORD(rx_desc_ptr);
efx_writeo_table(efx, &rx_desc_ptr, efx->type->rxd_ptr_tbl_base,
- rx_queue->queue);
+ efx_rx_queue_index(rx_queue));
/* Unpin RX descriptor ring */
efx_fini_special_buffer(efx, &rx_queue->rxd);
@@ -635,7 +653,7 @@ void efx_nic_eventq_read_ack(struct efx_channel *channel)
}
/* Use HW to insert a SW defined event */
-void efx_generate_event(struct efx_channel *channel, efx_qword_t *event)
+static void efx_generate_event(struct efx_channel *channel, efx_qword_t *event)
{
efx_oword_t drv_ev_reg;
@@ -667,15 +685,17 @@ efx_handle_tx_event(struct efx_channel *channel, efx_qword_t *event)
/* Transmit completion */
tx_ev_desc_ptr = EFX_QWORD_FIELD(*event, FSF_AZ_TX_EV_DESC_PTR);
tx_ev_q_label = EFX_QWORD_FIELD(*event, FSF_AZ_TX_EV_Q_LABEL);
- tx_queue = &efx->tx_queue[tx_ev_q_label];
+ tx_queue = efx_channel_get_tx_queue(
+ channel, tx_ev_q_label % EFX_TXQ_TYPES);
tx_packets = ((tx_ev_desc_ptr - tx_queue->read_count) &
- EFX_TXQ_MASK);
+ tx_queue->ptr_mask);
channel->irq_mod_score += tx_packets;
efx_xmit_done(tx_queue, tx_ev_desc_ptr);
} else if (EFX_QWORD_FIELD(*event, FSF_AZ_TX_EV_WQ_FF_FULL)) {
/* Rewrite the FIFO write pointer */
tx_ev_q_label = EFX_QWORD_FIELD(*event, FSF_AZ_TX_EV_Q_LABEL);
- tx_queue = &efx->tx_queue[tx_ev_q_label];
+ tx_queue = efx_channel_get_tx_queue(
+ channel, tx_ev_q_label % EFX_TXQ_TYPES);
if (efx_dev_registered(efx))
netif_tx_lock(efx->net_dev);
@@ -686,9 +706,10 @@ efx_handle_tx_event(struct efx_channel *channel, efx_qword_t *event)
EFX_WORKAROUND_10727(efx)) {
efx_schedule_reset(efx, RESET_TYPE_TX_DESC_FETCH);
} else {
- EFX_ERR(efx, "channel %d unexpected TX event "
- EFX_QWORD_FMT"\n", channel->channel,
- EFX_QWORD_VAL(*event));
+ netif_err(efx, tx_err, efx->net_dev,
+ "channel %d unexpected TX event "
+ EFX_QWORD_FMT"\n", channel->channel,
+ EFX_QWORD_VAL(*event));
}
return tx_packets;
@@ -700,6 +721,7 @@ static void efx_handle_rx_not_ok(struct efx_rx_queue *rx_queue,
bool *rx_ev_pkt_ok,
bool *discard)
{
+ struct efx_channel *channel = efx_rx_queue_channel(rx_queue);
struct efx_nic *efx = rx_queue->efx;
bool rx_ev_buf_owner_id_err, rx_ev_ip_hdr_chksum_err;
bool rx_ev_tcp_udp_chksum_err, rx_ev_eth_crc_err;
@@ -732,14 +754,14 @@ static void efx_handle_rx_not_ok(struct efx_rx_queue *rx_queue,
/* Count errors that are not in MAC stats. Ignore expected
* checksum errors during self-test. */
if (rx_ev_frm_trunc)
- ++rx_queue->channel->n_rx_frm_trunc;
+ ++channel->n_rx_frm_trunc;
else if (rx_ev_tobe_disc)
- ++rx_queue->channel->n_rx_tobe_disc;
+ ++channel->n_rx_tobe_disc;
else if (!efx->loopback_selftest) {
if (rx_ev_ip_hdr_chksum_err)
- ++rx_queue->channel->n_rx_ip_hdr_chksum_err;
+ ++channel->n_rx_ip_hdr_chksum_err;
else if (rx_ev_tcp_udp_chksum_err)
- ++rx_queue->channel->n_rx_tcp_udp_chksum_err;
+ ++channel->n_rx_tcp_udp_chksum_err;
}
/* The frame must be discarded if any of these are true. */
@@ -751,20 +773,21 @@ static void efx_handle_rx_not_ok(struct efx_rx_queue *rx_queue,
* to a FIFO overflow.
*/
#ifdef EFX_ENABLE_DEBUG
- if (rx_ev_other_err) {
- EFX_INFO_RL(efx, " RX queue %d unexpected RX event "
- EFX_QWORD_FMT "%s%s%s%s%s%s%s%s\n",
- rx_queue->queue, EFX_QWORD_VAL(*event),
- rx_ev_buf_owner_id_err ? " [OWNER_ID_ERR]" : "",
- rx_ev_ip_hdr_chksum_err ?
- " [IP_HDR_CHKSUM_ERR]" : "",
- rx_ev_tcp_udp_chksum_err ?
- " [TCP_UDP_CHKSUM_ERR]" : "",
- rx_ev_eth_crc_err ? " [ETH_CRC_ERR]" : "",
- rx_ev_frm_trunc ? " [FRM_TRUNC]" : "",
- rx_ev_drib_nib ? " [DRIB_NIB]" : "",
- rx_ev_tobe_disc ? " [TOBE_DISC]" : "",
- rx_ev_pause_frm ? " [PAUSE]" : "");
+ if (rx_ev_other_err && net_ratelimit()) {
+ netif_dbg(efx, rx_err, efx->net_dev,
+ " RX queue %d unexpected RX event "
+ EFX_QWORD_FMT "%s%s%s%s%s%s%s%s\n",
+ efx_rx_queue_index(rx_queue), EFX_QWORD_VAL(*event),
+ rx_ev_buf_owner_id_err ? " [OWNER_ID_ERR]" : "",
+ rx_ev_ip_hdr_chksum_err ?
+ " [IP_HDR_CHKSUM_ERR]" : "",
+ rx_ev_tcp_udp_chksum_err ?
+ " [TCP_UDP_CHKSUM_ERR]" : "",
+ rx_ev_eth_crc_err ? " [ETH_CRC_ERR]" : "",
+ rx_ev_frm_trunc ? " [FRM_TRUNC]" : "",
+ rx_ev_drib_nib ? " [DRIB_NIB]" : "",
+ rx_ev_tobe_disc ? " [TOBE_DISC]" : "",
+ rx_ev_pause_frm ? " [PAUSE]" : "");
}
#endif
}
@@ -776,10 +799,11 @@ efx_handle_rx_bad_index(struct efx_rx_queue *rx_queue, unsigned index)
struct efx_nic *efx = rx_queue->efx;
unsigned expected, dropped;
- expected = rx_queue->removed_count & EFX_RXQ_MASK;
- dropped = (index - expected) & EFX_RXQ_MASK;
- EFX_INFO(efx, "dropped %d events (index=%d expected=%d)\n",
- dropped, index, expected);
+ expected = rx_queue->removed_count & rx_queue->ptr_mask;
+ dropped = (index - expected) & rx_queue->ptr_mask;
+ netif_info(efx, rx_err, efx->net_dev,
+ "dropped %d events (index=%d expected=%d)\n",
+ dropped, index, expected);
efx_schedule_reset(efx, EFX_WORKAROUND_5676(efx) ?
RESET_TYPE_RX_RECOVERY : RESET_TYPE_DISABLE);
@@ -811,10 +835,10 @@ efx_handle_rx_event(struct efx_channel *channel, const efx_qword_t *event)
WARN_ON(EFX_QWORD_FIELD(*event, FSF_AZ_RX_EV_Q_LABEL) !=
channel->channel);
- rx_queue = &efx->rx_queue[channel->channel];
+ rx_queue = efx_channel_get_rx_queue(channel);
rx_ev_desc_ptr = EFX_QWORD_FIELD(*event, FSF_AZ_RX_EV_DESC_PTR);
- expected_ptr = rx_queue->removed_count & EFX_RXQ_MASK;
+ expected_ptr = rx_queue->removed_count & rx_queue->ptr_mask;
if (unlikely(rx_ev_desc_ptr != expected_ptr))
efx_handle_rx_bad_index(rx_queue, rx_ev_desc_ptr);
@@ -850,6 +874,26 @@ efx_handle_rx_event(struct efx_channel *channel, const efx_qword_t *event)
checksummed, discard);
}
+static void
+efx_handle_generated_event(struct efx_channel *channel, efx_qword_t *event)
+{
+ struct efx_nic *efx = channel->efx;
+ unsigned code;
+
+ code = EFX_QWORD_FIELD(*event, FSF_AZ_DRV_GEN_EV_MAGIC);
+ if (code == EFX_CHANNEL_MAGIC_TEST(channel))
+ ++channel->magic_count;
+ else if (code == EFX_CHANNEL_MAGIC_FILL(channel))
+ /* The queue must be empty, so we won't receive any rx
+ * events, so efx_process_channel() won't refill the
+ * queue. Refill it here */
+ efx_fast_push_rx_descriptors(efx_channel_get_rx_queue(channel));
+ else
+ netif_dbg(efx, hw, efx->net_dev, "channel %d received "
+ "generated event "EFX_QWORD_FMT"\n",
+ channel->channel, EFX_QWORD_VAL(*event));
+}
+
/* Global events are basically PHY events */
static void
efx_handle_global_event(struct efx_channel *channel, efx_qword_t *event)
@@ -873,8 +917,9 @@ efx_handle_global_event(struct efx_channel *channel, efx_qword_t *event)
if (efx_nic_rev(efx) <= EFX_REV_FALCON_A1 ?
EFX_QWORD_FIELD(*event, FSF_AA_GLB_EV_RX_RECOVERY) :
EFX_QWORD_FIELD(*event, FSF_BB_GLB_EV_RX_RECOVERY)) {
- EFX_ERR(efx, "channel %d seen global RX_RESET "
- "event. Resetting.\n", channel->channel);
+ netif_err(efx, rx_err, efx->net_dev,
+ "channel %d seen global RX_RESET event. Resetting.\n",
+ channel->channel);
atomic_inc(&efx->rx_reset);
efx_schedule_reset(efx, EFX_WORKAROUND_6555(efx) ?
@@ -883,9 +928,10 @@ efx_handle_global_event(struct efx_channel *channel, efx_qword_t *event)
}
if (!handled)
- EFX_ERR(efx, "channel %d unknown global event "
- EFX_QWORD_FMT "\n", channel->channel,
- EFX_QWORD_VAL(*event));
+ netif_err(efx, hw, efx->net_dev,
+ "channel %d unknown global event "
+ EFX_QWORD_FMT "\n", channel->channel,
+ EFX_QWORD_VAL(*event));
}
static void
@@ -900,31 +946,35 @@ efx_handle_driver_event(struct efx_channel *channel, efx_qword_t *event)
switch (ev_sub_code) {
case FSE_AZ_TX_DESCQ_FLS_DONE_EV:
- EFX_TRACE(efx, "channel %d TXQ %d flushed\n",
- channel->channel, ev_sub_data);
+ netif_vdbg(efx, hw, efx->net_dev, "channel %d TXQ %d flushed\n",
+ channel->channel, ev_sub_data);
break;
case FSE_AZ_RX_DESCQ_FLS_DONE_EV:
- EFX_TRACE(efx, "channel %d RXQ %d flushed\n",
- channel->channel, ev_sub_data);
+ netif_vdbg(efx, hw, efx->net_dev, "channel %d RXQ %d flushed\n",
+ channel->channel, ev_sub_data);
break;
case FSE_AZ_EVQ_INIT_DONE_EV:
- EFX_LOG(efx, "channel %d EVQ %d initialised\n",
- channel->channel, ev_sub_data);
+ netif_dbg(efx, hw, efx->net_dev,
+ "channel %d EVQ %d initialised\n",
+ channel->channel, ev_sub_data);
break;
case FSE_AZ_SRM_UPD_DONE_EV:
- EFX_TRACE(efx, "channel %d SRAM update done\n",
- channel->channel);
+ netif_vdbg(efx, hw, efx->net_dev,
+ "channel %d SRAM update done\n", channel->channel);
break;
case FSE_AZ_WAKE_UP_EV:
- EFX_TRACE(efx, "channel %d RXQ %d wakeup event\n",
- channel->channel, ev_sub_data);
+ netif_vdbg(efx, hw, efx->net_dev,
+ "channel %d RXQ %d wakeup event\n",
+ channel->channel, ev_sub_data);
break;
case FSE_AZ_TIMER_EV:
- EFX_TRACE(efx, "channel %d RX queue %d timer expired\n",
- channel->channel, ev_sub_data);
+ netif_vdbg(efx, hw, efx->net_dev,
+ "channel %d RX queue %d timer expired\n",
+ channel->channel, ev_sub_data);
break;
case FSE_AA_RX_RECOVER_EV:
- EFX_ERR(efx, "channel %d seen DRIVER RX_RESET event. "
+ netif_err(efx, rx_err, efx->net_dev,
+ "channel %d seen DRIVER RX_RESET event. "
"Resetting.\n", channel->channel);
atomic_inc(&efx->rx_reset);
efx_schedule_reset(efx,
@@ -933,25 +983,29 @@ efx_handle_driver_event(struct efx_channel *channel, efx_qword_t *event)
RESET_TYPE_DISABLE);
break;
case FSE_BZ_RX_DSC_ERROR_EV:
- EFX_ERR(efx, "RX DMA Q %d reports descriptor fetch error."
- " RX Q %d is disabled.\n", ev_sub_data, ev_sub_data);
+ netif_err(efx, rx_err, efx->net_dev,
+ "RX DMA Q %d reports descriptor fetch error."
+ " RX Q %d is disabled.\n", ev_sub_data, ev_sub_data);
efx_schedule_reset(efx, RESET_TYPE_RX_DESC_FETCH);
break;
case FSE_BZ_TX_DSC_ERROR_EV:
- EFX_ERR(efx, "TX DMA Q %d reports descriptor fetch error."
- " TX Q %d is disabled.\n", ev_sub_data, ev_sub_data);
+ netif_err(efx, tx_err, efx->net_dev,
+ "TX DMA Q %d reports descriptor fetch error."
+ " TX Q %d is disabled.\n", ev_sub_data, ev_sub_data);
efx_schedule_reset(efx, RESET_TYPE_TX_DESC_FETCH);
break;
default:
- EFX_TRACE(efx, "channel %d unknown driver event code %d "
- "data %04x\n", channel->channel, ev_sub_code,
- ev_sub_data);
+ netif_vdbg(efx, hw, efx->net_dev,
+ "channel %d unknown driver event code %d "
+ "data %04x\n", channel->channel, ev_sub_code,
+ ev_sub_data);
break;
}
}
int efx_nic_process_eventq(struct efx_channel *channel, int budget)
{
+ struct efx_nic *efx = channel->efx;
unsigned int read_ptr;
efx_qword_t event, *p_event;
int ev_code;
@@ -968,14 +1022,15 @@ int efx_nic_process_eventq(struct efx_channel *channel, int budget)
/* End of events */
break;
- EFX_TRACE(channel->efx, "channel %d event is "EFX_QWORD_FMT"\n",
- channel->channel, EFX_QWORD_VAL(event));
+ netif_vdbg(channel->efx, intr, channel->efx->net_dev,
+ "channel %d event is "EFX_QWORD_FMT"\n",
+ channel->channel, EFX_QWORD_VAL(event));
/* Clear this event by marking it all ones */
EFX_SET_QWORD(*p_event);
/* Increment read pointer */
- read_ptr = (read_ptr + 1) & EFX_EVQ_MASK;
+ read_ptr = (read_ptr + 1) & channel->eventq_mask;
ev_code = EFX_QWORD_FIELD(event, FSF_AZ_EV_CODE);
@@ -987,17 +1042,13 @@ int efx_nic_process_eventq(struct efx_channel *channel, int budget)
break;
case FSE_AZ_EV_CODE_TX_EV:
tx_packets += efx_handle_tx_event(channel, &event);
- if (tx_packets >= EFX_TXQ_SIZE) {
+ if (tx_packets > efx->txq_entries) {
spent = budget;
goto out;
}
break;
case FSE_AZ_EV_CODE_DRV_GEN_EV:
- channel->eventq_magic = EFX_QWORD_FIELD(
- event, FSF_AZ_DRV_GEN_EV_MAGIC);
- EFX_LOG(channel->efx, "channel %d received generated "
- "event "EFX_QWORD_FMT"\n", channel->channel,
- EFX_QWORD_VAL(event));
+ efx_handle_generated_event(channel, &event);
break;
case FSE_AZ_EV_CODE_GLOBAL_EV:
efx_handle_global_event(channel, &event);
@@ -1009,9 +1060,10 @@ int efx_nic_process_eventq(struct efx_channel *channel, int budget)
efx_mcdi_process_event(channel, &event);
break;
default:
- EFX_ERR(channel->efx, "channel %d unknown event type %d"
- " (data " EFX_QWORD_FMT ")\n", channel->channel,
- ev_code, EFX_QWORD_VAL(event));
+ netif_err(channel->efx, hw, channel->efx->net_dev,
+ "channel %d unknown event type %d (data "
+ EFX_QWORD_FMT ")\n", channel->channel,
+ ev_code, EFX_QWORD_VAL(event));
}
}
@@ -1025,10 +1077,11 @@ out:
int efx_nic_probe_eventq(struct efx_channel *channel)
{
struct efx_nic *efx = channel->efx;
- BUILD_BUG_ON(EFX_EVQ_SIZE < 512 || EFX_EVQ_SIZE > 32768 ||
- EFX_EVQ_SIZE & EFX_EVQ_MASK);
+ unsigned entries;
+
+ entries = channel->eventq_mask + 1;
return efx_alloc_special_buffer(efx, &channel->eventq,
- EFX_EVQ_SIZE * sizeof(efx_qword_t));
+ entries * sizeof(efx_qword_t));
}
void efx_nic_init_eventq(struct efx_channel *channel)
@@ -1036,9 +1089,10 @@ void efx_nic_init_eventq(struct efx_channel *channel)
efx_oword_t reg;
struct efx_nic *efx = channel->efx;
- EFX_LOG(efx, "channel %d event queue in special buffers %d-%d\n",
- channel->channel, channel->eventq.index,
- channel->eventq.index + channel->eventq.entries - 1);
+ netif_dbg(efx, hw, efx->net_dev,
+ "channel %d event queue in special buffers %d-%d\n",
+ channel->channel, channel->eventq.index,
+ channel->eventq.index + channel->eventq.entries - 1);
if (efx_nic_rev(efx) >= EFX_REV_SIENA_A0) {
EFX_POPULATE_OWORD_3(reg,
@@ -1088,12 +1142,20 @@ void efx_nic_remove_eventq(struct efx_channel *channel)
}
-/* Generates a test event on the event queue. A subsequent call to
- * process_eventq() should pick up the event and place the value of
- * "magic" into channel->eventq_magic;
- */
-void efx_nic_generate_test_event(struct efx_channel *channel, unsigned int magic)
+void efx_nic_generate_test_event(struct efx_channel *channel)
+{
+ unsigned int magic = EFX_CHANNEL_MAGIC_TEST(channel);
+ efx_qword_t test_event;
+
+ EFX_POPULATE_QWORD_2(test_event, FSF_AZ_EV_CODE,
+ FSE_AZ_EV_CODE_DRV_GEN_EV,
+ FSF_AZ_DRV_GEN_EV_MAGIC, magic);
+ efx_generate_event(channel, &test_event);
+}
+
+void efx_nic_generate_fill_event(struct efx_channel *channel)
{
+ unsigned int magic = EFX_CHANNEL_MAGIC_FILL(channel);
efx_qword_t test_event;
EFX_POPULATE_QWORD_2(test_event, FSF_AZ_EV_CODE,
@@ -1111,11 +1173,11 @@ void efx_nic_generate_test_event(struct efx_channel *channel, unsigned int magic
static void efx_poll_flush_events(struct efx_nic *efx)
{
- struct efx_channel *channel = &efx->channel[0];
+ struct efx_channel *channel = efx_get_channel(efx, 0);
struct efx_tx_queue *tx_queue;
struct efx_rx_queue *rx_queue;
unsigned int read_ptr = channel->eventq_read_ptr;
- unsigned int end_ptr = (read_ptr - 1) & EFX_EVQ_MASK;
+ unsigned int end_ptr = (read_ptr - 1) & channel->eventq_mask;
do {
efx_qword_t *event = efx_event(channel, read_ptr);
@@ -1133,7 +1195,9 @@ static void efx_poll_flush_events(struct efx_nic *efx)
ev_queue = EFX_QWORD_FIELD(*event,
FSF_AZ_DRIVER_EV_SUBDATA);
if (ev_queue < EFX_TXQ_TYPES * efx->n_tx_channels) {
- tx_queue = efx->tx_queue + ev_queue;
+ tx_queue = efx_get_tx_queue(
+ efx, ev_queue / EFX_TXQ_TYPES,
+ ev_queue % EFX_TXQ_TYPES);
tx_queue->flushed = FLUSH_DONE;
}
} else if (ev_code == FSE_AZ_EV_CODE_DRIVER_EV &&
@@ -1143,7 +1207,7 @@ static void efx_poll_flush_events(struct efx_nic *efx)
ev_failed = EFX_QWORD_FIELD(
*event, FSF_AZ_DRIVER_EV_RX_FLUSH_FAIL);
if (ev_queue < efx->n_rx_channels) {
- rx_queue = efx->rx_queue + ev_queue;
+ rx_queue = efx_get_rx_queue(efx, ev_queue);
rx_queue->flushed =
ev_failed ? FLUSH_FAILED : FLUSH_DONE;
}
@@ -1153,7 +1217,7 @@ static void efx_poll_flush_events(struct efx_nic *efx)
* it's ok to throw away every non-flush event */
EFX_SET_QWORD(*event);
- read_ptr = (read_ptr + 1) & EFX_EVQ_MASK;
+ read_ptr = (read_ptr + 1) & channel->eventq_mask;
} while (read_ptr != end_ptr);
channel->eventq_read_ptr = read_ptr;
@@ -1164,6 +1228,7 @@ static void efx_poll_flush_events(struct efx_nic *efx)
* serialise them */
int efx_nic_flush_queues(struct efx_nic *efx)
{
+ struct efx_channel *channel;
struct efx_rx_queue *rx_queue;
struct efx_tx_queue *tx_queue;
int i, tx_pending, rx_pending;
@@ -1172,29 +1237,35 @@ int efx_nic_flush_queues(struct efx_nic *efx)
efx->type->prepare_flush(efx);
/* Flush all tx queues in parallel */
- efx_for_each_tx_queue(tx_queue, efx)
- efx_flush_tx_queue(tx_queue);
+ efx_for_each_channel(channel, efx) {
+ efx_for_each_channel_tx_queue(tx_queue, channel)
+ efx_flush_tx_queue(tx_queue);
+ }
/* The hardware supports four concurrent rx flushes, each of which may
* need to be retried if there is an outstanding descriptor fetch */
for (i = 0; i < EFX_FLUSH_POLL_COUNT; ++i) {
rx_pending = tx_pending = 0;
- efx_for_each_rx_queue(rx_queue, efx) {
- if (rx_queue->flushed == FLUSH_PENDING)
- ++rx_pending;
- }
- efx_for_each_rx_queue(rx_queue, efx) {
- if (rx_pending == EFX_RX_FLUSH_COUNT)
- break;
- if (rx_queue->flushed == FLUSH_FAILED ||
- rx_queue->flushed == FLUSH_NONE) {
- efx_flush_rx_queue(rx_queue);
- ++rx_pending;
+ efx_for_each_channel(channel, efx) {
+ efx_for_each_channel_rx_queue(rx_queue, channel) {
+ if (rx_queue->flushed == FLUSH_PENDING)
+ ++rx_pending;
}
}
- efx_for_each_tx_queue(tx_queue, efx) {
- if (tx_queue->flushed != FLUSH_DONE)
- ++tx_pending;
+ efx_for_each_channel(channel, efx) {
+ efx_for_each_channel_rx_queue(rx_queue, channel) {
+ if (rx_pending == EFX_RX_FLUSH_COUNT)
+ break;
+ if (rx_queue->flushed == FLUSH_FAILED ||
+ rx_queue->flushed == FLUSH_NONE) {
+ efx_flush_rx_queue(rx_queue);
+ ++rx_pending;
+ }
+ }
+ efx_for_each_channel_tx_queue(tx_queue, channel) {
+ if (tx_queue->flushed != FLUSH_DONE)
+ ++tx_pending;
+ }
}
if (rx_pending == 0 && tx_pending == 0)
@@ -1206,22 +1277,23 @@ int efx_nic_flush_queues(struct efx_nic *efx)
/* Mark the queues as all flushed. We're going to return failure
* leading to a reset, or fake up success anyway */
- efx_for_each_tx_queue(tx_queue, efx) {
- if (tx_queue->flushed != FLUSH_DONE)
- EFX_ERR(efx, "tx queue %d flush command timed out\n",
- tx_queue->queue);
- tx_queue->flushed = FLUSH_DONE;
- }
- efx_for_each_rx_queue(rx_queue, efx) {
- if (rx_queue->flushed != FLUSH_DONE)
- EFX_ERR(efx, "rx queue %d flush command timed out\n",
- rx_queue->queue);
- rx_queue->flushed = FLUSH_DONE;
+ efx_for_each_channel(channel, efx) {
+ efx_for_each_channel_tx_queue(tx_queue, channel) {
+ if (tx_queue->flushed != FLUSH_DONE)
+ netif_err(efx, hw, efx->net_dev,
+ "tx queue %d flush command timed out\n",
+ tx_queue->queue);
+ tx_queue->flushed = FLUSH_DONE;
+ }
+ efx_for_each_channel_rx_queue(rx_queue, channel) {
+ if (rx_queue->flushed != FLUSH_DONE)
+ netif_err(efx, hw, efx->net_dev,
+ "rx queue %d flush command timed out\n",
+ efx_rx_queue_index(rx_queue));
+ rx_queue->flushed = FLUSH_DONE;
+ }
}
- if (EFX_WORKAROUND_7803(efx))
- return 0;
-
return -ETIMEDOUT;
}
@@ -1290,10 +1362,10 @@ irqreturn_t efx_nic_fatal_interrupt(struct efx_nic *efx)
efx_reado(efx, &fatal_intr, FR_AZ_FATAL_INTR_KER);
error = EFX_OWORD_FIELD(fatal_intr, FRF_AZ_FATAL_INTR);
- EFX_ERR(efx, "SYSTEM ERROR " EFX_OWORD_FMT " status "
- EFX_OWORD_FMT ": %s\n", EFX_OWORD_VAL(*int_ker),
- EFX_OWORD_VAL(fatal_intr),
- error ? "disabling bus mastering" : "no recognised error");
+ netif_err(efx, hw, efx->net_dev, "SYSTEM ERROR "EFX_OWORD_FMT" status "
+ EFX_OWORD_FMT ": %s\n", EFX_OWORD_VAL(*int_ker),
+ EFX_OWORD_VAL(fatal_intr),
+ error ? "disabling bus mastering" : "no recognised error");
/* If this is a memory parity error dump which blocks are offending */
mem_perr = (EFX_OWORD_FIELD(fatal_intr, FRF_AZ_MEM_PERR_INT_KER) ||
@@ -1301,8 +1373,9 @@ irqreturn_t efx_nic_fatal_interrupt(struct efx_nic *efx)
if (mem_perr) {
efx_oword_t reg;
efx_reado(efx, &reg, FR_AZ_MEM_STAT);
- EFX_ERR(efx, "SYSTEM ERROR: memory parity error "
- EFX_OWORD_FMT "\n", EFX_OWORD_VAL(reg));
+ netif_err(efx, hw, efx->net_dev,
+ "SYSTEM ERROR: memory parity error "EFX_OWORD_FMT"\n",
+ EFX_OWORD_VAL(reg));
}
/* Disable both devices */
@@ -1319,11 +1392,13 @@ irqreturn_t efx_nic_fatal_interrupt(struct efx_nic *efx)
jiffies + EFX_INT_ERROR_EXPIRE * HZ;
}
if (++efx->int_error_count < EFX_MAX_INT_ERRORS) {
- EFX_ERR(efx, "SYSTEM ERROR - reset scheduled\n");
+ netif_err(efx, hw, efx->net_dev,
+ "SYSTEM ERROR - reset scheduled\n");
efx_schedule_reset(efx, RESET_TYPE_INT_ERROR);
} else {
- EFX_ERR(efx, "SYSTEM ERROR - max number of errors seen."
- "NIC will be disabled\n");
+ netif_err(efx, hw, efx->net_dev,
+ "SYSTEM ERROR - max number of errors seen."
+ "NIC will be disabled\n");
efx_schedule_reset(efx, RESET_TYPE_DISABLE);
}
@@ -1386,8 +1461,9 @@ static irqreturn_t efx_legacy_interrupt(int irq, void *dev_id)
if (result == IRQ_HANDLED) {
efx->last_irq_cpu = raw_smp_processor_id();
- EFX_TRACE(efx, "IRQ %d on CPU %d status " EFX_DWORD_FMT "\n",
- irq, raw_smp_processor_id(), EFX_DWORD_VAL(reg));
+ netif_vdbg(efx, intr, efx->net_dev,
+ "IRQ %d on CPU %d status " EFX_DWORD_FMT "\n",
+ irq, raw_smp_processor_id(), EFX_DWORD_VAL(reg));
}
return result;
@@ -1402,14 +1478,15 @@ static irqreturn_t efx_legacy_interrupt(int irq, void *dev_id)
*/
static irqreturn_t efx_msi_interrupt(int irq, void *dev_id)
{
- struct efx_channel *channel = dev_id;
+ struct efx_channel *channel = *(struct efx_channel **)dev_id;
struct efx_nic *efx = channel->efx;
efx_oword_t *int_ker = efx->irq_status.addr;
int syserr;
efx->last_irq_cpu = raw_smp_processor_id();
- EFX_TRACE(efx, "IRQ %d on CPU %d status " EFX_OWORD_FMT "\n",
- irq, raw_smp_processor_id(), EFX_OWORD_VAL(*int_ker));
+ netif_vdbg(efx, intr, efx->net_dev,
+ "IRQ %d on CPU %d status " EFX_OWORD_FMT "\n",
+ irq, raw_smp_processor_id(), EFX_OWORD_VAL(*int_ker));
/* Check to see if we have a serious error condition */
if (channel->channel == efx->fatal_irq_level) {
@@ -1428,22 +1505,21 @@ static irqreturn_t efx_msi_interrupt(int irq, void *dev_id)
/* Setup RSS indirection table.
* This maps from the hash value of the packet to RXQ
*/
-static void efx_setup_rss_indir_table(struct efx_nic *efx)
+void efx_nic_push_rx_indir_table(struct efx_nic *efx)
{
- int i = 0;
- unsigned long offset;
+ size_t i = 0;
efx_dword_t dword;
if (efx_nic_rev(efx) < EFX_REV_FALCON_B0)
return;
- for (offset = FR_BZ_RX_INDIRECTION_TBL;
- offset < FR_BZ_RX_INDIRECTION_TBL + 0x800;
- offset += 0x10) {
+ BUILD_BUG_ON(ARRAY_SIZE(efx->rx_indir_table) !=
+ FR_BZ_RX_INDIRECTION_TBL_ROWS);
+
+ for (i = 0; i < FR_BZ_RX_INDIRECTION_TBL_ROWS; i++) {
EFX_POPULATE_DWORD_1(dword, FRF_BZ_IT_QUEUE,
- i % efx->n_rx_channels);
- efx_writed(efx, &dword, offset);
- i++;
+ efx->rx_indir_table[i]);
+ efx_writed_table(efx, &dword, FR_BZ_RX_INDIRECTION_TBL, i);
}
}
@@ -1465,8 +1541,9 @@ int efx_nic_init_interrupt(struct efx_nic *efx)
rc = request_irq(efx->legacy_irq, handler, IRQF_SHARED,
efx->name, efx);
if (rc) {
- EFX_ERR(efx, "failed to hook legacy IRQ %d\n",
- efx->pci_dev->irq);
+ netif_err(efx, drv, efx->net_dev,
+ "failed to hook legacy IRQ %d\n",
+ efx->pci_dev->irq);
goto fail1;
}
return 0;
@@ -1476,9 +1553,11 @@ int efx_nic_init_interrupt(struct efx_nic *efx)
efx_for_each_channel(channel, efx) {
rc = request_irq(channel->irq, efx_msi_interrupt,
IRQF_PROBE_SHARED, /* Not shared */
- channel->name, channel);
+ efx->channel_name[channel->channel],
+ &efx->channel[channel->channel]);
if (rc) {
- EFX_ERR(efx, "failed to hook IRQ %d\n", channel->irq);
+ netif_err(efx, drv, efx->net_dev,
+ "failed to hook IRQ %d\n", channel->irq);
goto fail2;
}
}
@@ -1487,7 +1566,7 @@ int efx_nic_init_interrupt(struct efx_nic *efx)
fail2:
efx_for_each_channel(channel, efx)
- free_irq(channel->irq, channel);
+ free_irq(channel->irq, &efx->channel[channel->channel]);
fail1:
return rc;
}
@@ -1500,7 +1579,7 @@ void efx_nic_fini_interrupt(struct efx_nic *efx)
/* Disable MSI/MSI-X interrupts */
efx_for_each_channel(channel, efx) {
if (channel->irq)
- free_irq(channel->irq, channel);
+ free_irq(channel->irq, &efx->channel[channel->channel]);
}
/* ACK legacy interrupt */
@@ -1576,7 +1655,7 @@ void efx_nic_init_common(struct efx_nic *efx)
EFX_INVERT_OWORD(temp);
efx_writeo(efx, &temp, FR_AZ_FATAL_INTR_KER);
- efx_setup_rss_indir_table(efx);
+ efx_nic_push_rx_indir_table(efx);
/* Disable the ugly timer-based TX DMA backoff and allow TX DMA to be
* controlled by the RX FIFO fill level. Set arbitration to one pkt/Q.
@@ -1598,3 +1677,268 @@ void efx_nic_init_common(struct efx_nic *efx)
EFX_SET_OWORD_FIELD(temp, FRF_BZ_TX_FLUSH_MIN_LEN_EN, 1);
efx_writeo(efx, &temp, FR_AZ_TX_RESERVED);
}
+
+/* Register dump */
+
+#define REGISTER_REVISION_A 1
+#define REGISTER_REVISION_B 2
+#define REGISTER_REVISION_C 3
+#define REGISTER_REVISION_Z 3 /* latest revision */
+
+struct efx_nic_reg {
+ u32 offset:24;
+ u32 min_revision:2, max_revision:2;
+};
+
+#define REGISTER(name, min_rev, max_rev) { \
+ FR_ ## min_rev ## max_rev ## _ ## name, \
+ REGISTER_REVISION_ ## min_rev, REGISTER_REVISION_ ## max_rev \
+}
+#define REGISTER_AA(name) REGISTER(name, A, A)
+#define REGISTER_AB(name) REGISTER(name, A, B)
+#define REGISTER_AZ(name) REGISTER(name, A, Z)
+#define REGISTER_BB(name) REGISTER(name, B, B)
+#define REGISTER_BZ(name) REGISTER(name, B, Z)
+#define REGISTER_CZ(name) REGISTER(name, C, Z)
+
+static const struct efx_nic_reg efx_nic_regs[] = {
+ REGISTER_AZ(ADR_REGION),
+ REGISTER_AZ(INT_EN_KER),
+ REGISTER_BZ(INT_EN_CHAR),
+ REGISTER_AZ(INT_ADR_KER),
+ REGISTER_BZ(INT_ADR_CHAR),
+ /* INT_ACK_KER is WO */
+ /* INT_ISR0 is RC */
+ REGISTER_AZ(HW_INIT),
+ REGISTER_CZ(USR_EV_CFG),
+ REGISTER_AB(EE_SPI_HCMD),
+ REGISTER_AB(EE_SPI_HADR),
+ REGISTER_AB(EE_SPI_HDATA),
+ REGISTER_AB(EE_BASE_PAGE),
+ REGISTER_AB(EE_VPD_CFG0),
+ /* EE_VPD_SW_CNTL and EE_VPD_SW_DATA are not used */
+ /* PMBX_DBG_IADDR and PBMX_DBG_IDATA are indirect */
+ /* PCIE_CORE_INDIRECT is indirect */
+ REGISTER_AB(NIC_STAT),
+ REGISTER_AB(GPIO_CTL),
+ REGISTER_AB(GLB_CTL),
+ /* FATAL_INTR_KER and FATAL_INTR_CHAR are partly RC */
+ REGISTER_BZ(DP_CTRL),
+ REGISTER_AZ(MEM_STAT),
+ REGISTER_AZ(CS_DEBUG),
+ REGISTER_AZ(ALTERA_BUILD),
+ REGISTER_AZ(CSR_SPARE),
+ REGISTER_AB(PCIE_SD_CTL0123),
+ REGISTER_AB(PCIE_SD_CTL45),
+ REGISTER_AB(PCIE_PCS_CTL_STAT),
+ /* DEBUG_DATA_OUT is not used */
+ /* DRV_EV is WO */
+ REGISTER_AZ(EVQ_CTL),
+ REGISTER_AZ(EVQ_CNT1),
+ REGISTER_AZ(EVQ_CNT2),
+ REGISTER_AZ(BUF_TBL_CFG),
+ REGISTER_AZ(SRM_RX_DC_CFG),
+ REGISTER_AZ(SRM_TX_DC_CFG),
+ REGISTER_AZ(SRM_CFG),
+ /* BUF_TBL_UPD is WO */
+ REGISTER_AZ(SRM_UPD_EVQ),
+ REGISTER_AZ(SRAM_PARITY),
+ REGISTER_AZ(RX_CFG),
+ REGISTER_BZ(RX_FILTER_CTL),
+ /* RX_FLUSH_DESCQ is WO */
+ REGISTER_AZ(RX_DC_CFG),
+ REGISTER_AZ(RX_DC_PF_WM),
+ REGISTER_BZ(RX_RSS_TKEY),
+ /* RX_NODESC_DROP is RC */
+ REGISTER_AA(RX_SELF_RST),
+ /* RX_DEBUG, RX_PUSH_DROP are not used */
+ REGISTER_CZ(RX_RSS_IPV6_REG1),
+ REGISTER_CZ(RX_RSS_IPV6_REG2),
+ REGISTER_CZ(RX_RSS_IPV6_REG3),
+ /* TX_FLUSH_DESCQ is WO */
+ REGISTER_AZ(TX_DC_CFG),
+ REGISTER_AA(TX_CHKSM_CFG),
+ REGISTER_AZ(TX_CFG),
+ /* TX_PUSH_DROP is not used */
+ REGISTER_AZ(TX_RESERVED),
+ REGISTER_BZ(TX_PACE),
+ /* TX_PACE_DROP_QID is RC */
+ REGISTER_BB(TX_VLAN),
+ REGISTER_BZ(TX_IPFIL_PORTEN),
+ REGISTER_AB(MD_TXD),
+ REGISTER_AB(MD_RXD),
+ REGISTER_AB(MD_CS),
+ REGISTER_AB(MD_PHY_ADR),
+ REGISTER_AB(MD_ID),
+ /* MD_STAT is RC */
+ REGISTER_AB(MAC_STAT_DMA),
+ REGISTER_AB(MAC_CTRL),
+ REGISTER_BB(GEN_MODE),
+ REGISTER_AB(MAC_MC_HASH_REG0),
+ REGISTER_AB(MAC_MC_HASH_REG1),
+ REGISTER_AB(GM_CFG1),
+ REGISTER_AB(GM_CFG2),
+ /* GM_IPG and GM_HD are not used */
+ REGISTER_AB(GM_MAX_FLEN),
+ /* GM_TEST is not used */
+ REGISTER_AB(GM_ADR1),
+ REGISTER_AB(GM_ADR2),
+ REGISTER_AB(GMF_CFG0),
+ REGISTER_AB(GMF_CFG1),
+ REGISTER_AB(GMF_CFG2),
+ REGISTER_AB(GMF_CFG3),
+ REGISTER_AB(GMF_CFG4),
+ REGISTER_AB(GMF_CFG5),
+ REGISTER_BB(TX_SRC_MAC_CTL),
+ REGISTER_AB(XM_ADR_LO),
+ REGISTER_AB(XM_ADR_HI),
+ REGISTER_AB(XM_GLB_CFG),
+ REGISTER_AB(XM_TX_CFG),
+ REGISTER_AB(XM_RX_CFG),
+ REGISTER_AB(XM_MGT_INT_MASK),
+ REGISTER_AB(XM_FC),
+ REGISTER_AB(XM_PAUSE_TIME),
+ REGISTER_AB(XM_TX_PARAM),
+ REGISTER_AB(XM_RX_PARAM),
+ /* XM_MGT_INT_MSK (note no 'A') is RC */
+ REGISTER_AB(XX_PWR_RST),
+ REGISTER_AB(XX_SD_CTL),
+ REGISTER_AB(XX_TXDRV_CTL),
+ /* XX_PRBS_CTL, XX_PRBS_CHK and XX_PRBS_ERR are not used */
+ /* XX_CORE_STAT is partly RC */
+};
+
+struct efx_nic_reg_table {
+ u32 offset:24;
+ u32 min_revision:2, max_revision:2;
+ u32 step:6, rows:21;
+};
+
+#define REGISTER_TABLE_DIMENSIONS(_, offset, min_rev, max_rev, step, rows) { \
+ offset, \
+ REGISTER_REVISION_ ## min_rev, REGISTER_REVISION_ ## max_rev, \
+ step, rows \
+}
+#define REGISTER_TABLE(name, min_rev, max_rev) \
+ REGISTER_TABLE_DIMENSIONS( \
+ name, FR_ ## min_rev ## max_rev ## _ ## name, \
+ min_rev, max_rev, \
+ FR_ ## min_rev ## max_rev ## _ ## name ## _STEP, \
+ FR_ ## min_rev ## max_rev ## _ ## name ## _ROWS)
+#define REGISTER_TABLE_AA(name) REGISTER_TABLE(name, A, A)
+#define REGISTER_TABLE_AZ(name) REGISTER_TABLE(name, A, Z)
+#define REGISTER_TABLE_BB(name) REGISTER_TABLE(name, B, B)
+#define REGISTER_TABLE_BZ(name) REGISTER_TABLE(name, B, Z)
+#define REGISTER_TABLE_BB_CZ(name) \
+ REGISTER_TABLE_DIMENSIONS(name, FR_BZ_ ## name, B, B, \
+ FR_BZ_ ## name ## _STEP, \
+ FR_BB_ ## name ## _ROWS), \
+ REGISTER_TABLE_DIMENSIONS(name, FR_BZ_ ## name, C, Z, \
+ FR_BZ_ ## name ## _STEP, \
+ FR_CZ_ ## name ## _ROWS)
+#define REGISTER_TABLE_CZ(name) REGISTER_TABLE(name, C, Z)
+
+static const struct efx_nic_reg_table efx_nic_reg_tables[] = {
+ /* DRIVER is not used */
+ /* EVQ_RPTR, TIMER_COMMAND, USR_EV and {RX,TX}_DESC_UPD are WO */
+ REGISTER_TABLE_BB(TX_IPFIL_TBL),
+ REGISTER_TABLE_BB(TX_SRC_MAC_TBL),
+ REGISTER_TABLE_AA(RX_DESC_PTR_TBL_KER),
+ REGISTER_TABLE_BB_CZ(RX_DESC_PTR_TBL),
+ REGISTER_TABLE_AA(TX_DESC_PTR_TBL_KER),
+ REGISTER_TABLE_BB_CZ(TX_DESC_PTR_TBL),
+ REGISTER_TABLE_AA(EVQ_PTR_TBL_KER),
+ REGISTER_TABLE_BB_CZ(EVQ_PTR_TBL),
+ /* We can't reasonably read all of the buffer table (up to 8MB!).
+ * However this driver will only use a few entries. Reading
+ * 1K entries allows for some expansion of queue count and
+ * size before we need to change the version. */
+ REGISTER_TABLE_DIMENSIONS(BUF_FULL_TBL_KER, FR_AA_BUF_FULL_TBL_KER,
+ A, A, 8, 1024),
+ REGISTER_TABLE_DIMENSIONS(BUF_FULL_TBL, FR_BZ_BUF_FULL_TBL,
+ B, Z, 8, 1024),
+ REGISTER_TABLE_CZ(RX_MAC_FILTER_TBL0),
+ REGISTER_TABLE_BB_CZ(TIMER_TBL),
+ REGISTER_TABLE_BB_CZ(TX_PACE_TBL),
+ REGISTER_TABLE_BZ(RX_INDIRECTION_TBL),
+ /* TX_FILTER_TBL0 is huge and not used by this driver */
+ REGISTER_TABLE_CZ(TX_MAC_FILTER_TBL0),
+ REGISTER_TABLE_CZ(MC_TREG_SMEM),
+ /* MSIX_PBA_TABLE is not mapped */
+ /* SRM_DBG is not mapped (and is redundant with BUF_FLL_TBL) */
+ REGISTER_TABLE_BZ(RX_FILTER_TBL0),
+};
+
+size_t efx_nic_get_regs_len(struct efx_nic *efx)
+{
+ const struct efx_nic_reg *reg;
+ const struct efx_nic_reg_table *table;
+ size_t len = 0;
+
+ for (reg = efx_nic_regs;
+ reg < efx_nic_regs + ARRAY_SIZE(efx_nic_regs);
+ reg++)
+ if (efx->type->revision >= reg->min_revision &&
+ efx->type->revision <= reg->max_revision)
+ len += sizeof(efx_oword_t);
+
+ for (table = efx_nic_reg_tables;
+ table < efx_nic_reg_tables + ARRAY_SIZE(efx_nic_reg_tables);
+ table++)
+ if (efx->type->revision >= table->min_revision &&
+ efx->type->revision <= table->max_revision)
+ len += table->rows * min_t(size_t, table->step, 16);
+
+ return len;
+}
+
+void efx_nic_get_regs(struct efx_nic *efx, void *buf)
+{
+ const struct efx_nic_reg *reg;
+ const struct efx_nic_reg_table *table;
+
+ for (reg = efx_nic_regs;
+ reg < efx_nic_regs + ARRAY_SIZE(efx_nic_regs);
+ reg++) {
+ if (efx->type->revision >= reg->min_revision &&
+ efx->type->revision <= reg->max_revision) {
+ efx_reado(efx, (efx_oword_t *)buf, reg->offset);
+ buf += sizeof(efx_oword_t);
+ }
+ }
+
+ for (table = efx_nic_reg_tables;
+ table < efx_nic_reg_tables + ARRAY_SIZE(efx_nic_reg_tables);
+ table++) {
+ size_t size, i;
+
+ if (!(efx->type->revision >= table->min_revision &&
+ efx->type->revision <= table->max_revision))
+ continue;
+
+ size = min_t(size_t, table->step, 16);
+
+ for (i = 0; i < table->rows; i++) {
+ switch (table->step) {
+ case 4: /* 32-bit register or SRAM */
+ efx_readd_table(efx, buf, table->offset, i);
+ break;
+ case 8: /* 64-bit SRAM */
+ efx_sram_readq(efx,
+ efx->membase + table->offset,
+ buf, i);
+ break;
+ case 16: /* 128-bit register */
+ efx_reado_table(efx, buf, table->offset, i);
+ break;
+ case 32: /* 128-bit register, interleaved */
+ efx_reado_table(efx, buf, table->offset, 2 * i);
+ break;
+ default:
+ WARN_ON(1);
+ return;
+ }
+ buf += size;
+ }
+ }
+}
diff --git a/drivers/net/sfc/nic.h b/drivers/net/sfc/nic.h
index bbc2c0c2f843..0438dc98722d 100644
--- a/drivers/net/sfc/nic.h
+++ b/drivers/net/sfc/nic.h
@@ -142,7 +142,6 @@ struct siena_nic_data {
u32 fw_build;
struct efx_mcdi_iface mcdi;
int wol_filter_id;
- u8 ipv6_rss_key[40];
};
extern void siena_print_fwver(struct efx_nic *efx, char *buf, size_t len);
@@ -190,8 +189,8 @@ extern int efx_nic_rx_xoff_thresh, efx_nic_rx_xon_thresh;
/* Interrupts and test events */
extern int efx_nic_init_interrupt(struct efx_nic *efx);
extern void efx_nic_enable_interrupts(struct efx_nic *efx);
-extern void efx_nic_generate_test_event(struct efx_channel *channel,
- unsigned int magic);
+extern void efx_nic_generate_test_event(struct efx_channel *channel);
+extern void efx_nic_generate_fill_event(struct efx_channel *channel);
extern void efx_nic_generate_interrupt(struct efx_nic *efx);
extern void efx_nic_disable_interrupts(struct efx_nic *efx);
extern void efx_nic_fini_interrupt(struct efx_nic *efx);
@@ -208,6 +207,7 @@ extern void falcon_stop_nic_stats(struct efx_nic *efx);
extern void falcon_setup_xaui(struct efx_nic *efx);
extern int falcon_reset_xaui(struct efx_nic *efx);
extern void efx_nic_init_common(struct efx_nic *efx);
+extern void efx_nic_push_rx_indir_table(struct efx_nic *efx);
int efx_nic_alloc_buffer(struct efx_nic *efx, struct efx_buffer *buffer,
unsigned int len);
@@ -222,6 +222,9 @@ extern int efx_nic_test_registers(struct efx_nic *efx,
const struct efx_nic_register_test *regs,
size_t n_regs);
+extern size_t efx_nic_get_regs_len(struct efx_nic *efx);
+extern void efx_nic_get_regs(struct efx_nic *efx, void *buf);
+
/**************************************************************************
*
* Falcon MAC stats
diff --git a/drivers/net/sfc/phy.h b/drivers/net/sfc/phy.h
index 5bc26137257b..1dab609757fb 100644
--- a/drivers/net/sfc/phy.h
+++ b/drivers/net/sfc/phy.h
@@ -11,17 +11,12 @@
#define EFX_PHY_H
/****************************************************************************
- * 10Xpress (SFX7101 and SFT9001) PHYs
+ * 10Xpress (SFX7101) PHY
*/
extern struct efx_phy_operations falcon_sfx7101_phy_ops;
-extern struct efx_phy_operations falcon_sft9001_phy_ops;
extern void tenxpress_set_id_led(struct efx_nic *efx, enum efx_led_mode mode);
-/* Wait for the PHY to boot. Return 0 on success, -EINVAL if the PHY failed
- * to boot due to corrupt flash, or some other negative error code. */
-extern int sft9001_wait_boot(struct efx_nic *efx);
-
/****************************************************************************
* AMCC/Quake QT202x PHYs
*/
@@ -42,6 +37,17 @@ extern struct efx_phy_operations falcon_qt202x_phy_ops;
extern void falcon_qt202x_set_led(struct efx_nic *p, int led, int state);
/****************************************************************************
+* Transwitch CX4 retimer
+*/
+extern struct efx_phy_operations falcon_txc_phy_ops;
+
+#define TXC_GPIO_DIR_INPUT 0
+#define TXC_GPIO_DIR_OUTPUT 1
+
+extern void falcon_txc_set_gpio_dir(struct efx_nic *efx, int pin, int dir);
+extern void falcon_txc_set_gpio_val(struct efx_nic *efx, int pin, int val);
+
+/****************************************************************************
* Siena managed PHYs
*/
extern struct efx_phy_operations efx_mcdi_phy_ops;
diff --git a/drivers/net/sfc/qt202x_phy.c b/drivers/net/sfc/qt202x_phy.c
index e077bef08a50..68813d1d85f3 100644
--- a/drivers/net/sfc/qt202x_phy.c
+++ b/drivers/net/sfc/qt202x_phy.c
@@ -91,9 +91,10 @@ static int qt2025c_wait_heartbeat(struct efx_nic *efx)
if (time_after(jiffies, timeout)) {
/* Some cables have EEPROMs that conflict with the
* PHY's on-board EEPROM so it cannot load firmware */
- EFX_ERR(efx, "If an SFP+ direct attach cable is"
- " connected, please check that it complies"
- " with the SFP+ specification\n");
+ netif_err(efx, hw, efx->net_dev,
+ "If an SFP+ direct attach cable is"
+ " connected, please check that it complies"
+ " with the SFP+ specification\n");
return -ETIMEDOUT;
}
msleep(QT2025C_HEARTB_WAIT);
@@ -145,7 +146,8 @@ static int qt2025c_wait_reset(struct efx_nic *efx)
/* Bug 17689: occasionally heartbeat starts but firmware status
* code never progresses beyond 0x00. Try again, once, after
* restarting execution of the firmware image. */
- EFX_LOG(efx, "bashing QT2025C microcontroller\n");
+ netif_dbg(efx, hw, efx->net_dev,
+ "bashing QT2025C microcontroller\n");
qt2025c_restart_firmware(efx);
rc = qt2025c_wait_heartbeat(efx);
if (rc != 0)
@@ -165,11 +167,12 @@ static void qt2025c_firmware_id(struct efx_nic *efx)
for (i = 0; i < sizeof(firmware_id); i++)
firmware_id[i] = efx_mdio_read(efx, MDIO_MMD_PCS,
PCS_FW_PRODUCT_CODE_1 + i);
- EFX_INFO(efx, "QT2025C firmware %xr%d v%d.%d.%d.%d [20%02d-%02d-%02d]\n",
- (firmware_id[0] << 8) | firmware_id[1], firmware_id[2],
- firmware_id[3] >> 4, firmware_id[3] & 0xf,
- firmware_id[4], firmware_id[5],
- firmware_id[6], firmware_id[7], firmware_id[8]);
+ netif_info(efx, probe, efx->net_dev,
+ "QT2025C firmware %xr%d v%d.%d.%d.%d [20%02d-%02d-%02d]\n",
+ (firmware_id[0] << 8) | firmware_id[1], firmware_id[2],
+ firmware_id[3] >> 4, firmware_id[3] & 0xf,
+ firmware_id[4], firmware_id[5],
+ firmware_id[6], firmware_id[7], firmware_id[8]);
phy_data->firmware_ver = ((firmware_id[3] & 0xf0) << 20) |
((firmware_id[3] & 0x0f) << 16) |
(firmware_id[4] << 8) | firmware_id[5];
@@ -198,7 +201,7 @@ static void qt2025c_bug17190_workaround(struct efx_nic *efx)
}
if (time_after_eq(jiffies, phy_data->bug17190_timer)) {
- EFX_LOG(efx, "bashing QT2025C PMA/PMD\n");
+ netif_dbg(efx, hw, efx->net_dev, "bashing QT2025C PMA/PMD\n");
efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, MDIO_CTRL1,
MDIO_PMA_CTRL1_LOOPBACK, true);
msleep(100);
@@ -231,7 +234,8 @@ static int qt2025c_select_phy_mode(struct efx_nic *efx)
reg = efx_mdio_read(efx, 1, 0xc319);
if ((reg & 0x0038) == phy_op_mode)
return 0;
- EFX_LOG(efx, "Switching PHY to mode 0x%04x\n", phy_op_mode);
+ netif_dbg(efx, hw, efx->net_dev, "Switching PHY to mode 0x%04x\n",
+ phy_op_mode);
/* This sequence replicates the register writes configured in the boot
* EEPROM (including the differences between board revisions), except
@@ -287,8 +291,9 @@ static int qt2025c_select_phy_mode(struct efx_nic *efx)
/* Wait for the microcontroller to be ready again */
rc = qt2025c_wait_reset(efx);
if (rc < 0) {
- EFX_ERR(efx, "PHY microcontroller reset during mode switch "
- "timed out\n");
+ netif_err(efx, hw, efx->net_dev,
+ "PHY microcontroller reset during mode switch "
+ "timed out\n");
return rc;
}
@@ -324,7 +329,7 @@ static int qt202x_reset_phy(struct efx_nic *efx)
return 0;
fail:
- EFX_ERR(efx, "PHY reset timed out\n");
+ netif_err(efx, hw, efx->net_dev, "PHY reset timed out\n");
return rc;
}
@@ -353,14 +358,15 @@ static int qt202x_phy_init(struct efx_nic *efx)
rc = qt202x_reset_phy(efx);
if (rc) {
- EFX_ERR(efx, "PHY init failed\n");
+ netif_err(efx, probe, efx->net_dev, "PHY init failed\n");
return rc;
}
devid = efx_mdio_read_id(efx, MDIO_MMD_PHYXS);
- EFX_INFO(efx, "PHY ID reg %x (OUI %06x model %02x revision %x)\n",
- devid, efx_mdio_id_oui(devid), efx_mdio_id_model(devid),
- efx_mdio_id_rev(devid));
+ netif_info(efx, probe, efx->net_dev,
+ "PHY ID reg %x (OUI %06x model %02x revision %x)\n",
+ devid, efx_mdio_id_oui(devid), efx_mdio_id_model(devid),
+ efx_mdio_id_rev(devid));
if (efx->phy_type == PHY_TYPE_QT2025C)
qt2025c_firmware_id(efx);
diff --git a/drivers/net/sfc/regs.h b/drivers/net/sfc/regs.h
index 18a3be428348..96430ed81c36 100644
--- a/drivers/net/sfc/regs.h
+++ b/drivers/net/sfc/regs.h
@@ -2893,6 +2893,20 @@
#define FRF_AB_XX_FORCE_SIG_WIDTH 8
#define FFE_AB_XX_FORCE_SIG_ALL_LANES 0xff
+/* RX_MAC_FILTER_TBL0 */
+/* RMFT_DEST_MAC is wider than 32 bits */
+#define FRF_CZ_RMFT_DEST_MAC_LO_LBN 12
+#define FRF_CZ_RMFT_DEST_MAC_LO_WIDTH 32
+#define FRF_CZ_RMFT_DEST_MAC_HI_LBN 44
+#define FRF_CZ_RMFT_DEST_MAC_HI_WIDTH 16
+
+/* TX_MAC_FILTER_TBL0 */
+/* TMFT_SRC_MAC is wider than 32 bits */
+#define FRF_CZ_TMFT_SRC_MAC_LO_LBN 12
+#define FRF_CZ_TMFT_SRC_MAC_LO_WIDTH 32
+#define FRF_CZ_TMFT_SRC_MAC_HI_LBN 44
+#define FRF_CZ_TMFT_SRC_MAC_HI_WIDTH 16
+
/* DRIVER_EV */
/* Sub-fields of an RX flush completion event */
#define FSF_AZ_DRIVER_EV_RX_FLUSH_FAIL_LBN 12
diff --git a/drivers/net/sfc/rx.c b/drivers/net/sfc/rx.c
index e308818b9f55..6d0959b5158e 100644
--- a/drivers/net/sfc/rx.c
+++ b/drivers/net/sfc/rx.c
@@ -25,6 +25,9 @@
/* Number of RX descriptors pushed at once. */
#define EFX_RX_BATCH 8
+/* Maximum size of a buffer sharing a page */
+#define EFX_RX_HALF_PAGE ((PAGE_SIZE >> 1) - sizeof(struct efx_rx_page_state))
+
/* Size of buffer allocated for skb header area. */
#define EFX_SKB_HEADERS 64u
@@ -98,155 +101,151 @@ static inline unsigned int efx_rx_buf_size(struct efx_nic *efx)
return PAGE_SIZE << efx->rx_buffer_order;
}
+static inline u32 efx_rx_buf_hash(struct efx_rx_buffer *buf)
+{
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) || NET_IP_ALIGN % 4 == 0
+ return __le32_to_cpup((const __le32 *)(buf->data - 4));
+#else
+ const u8 *data = (const u8 *)(buf->data - 4);
+ return ((u32)data[0] |
+ (u32)data[1] << 8 |
+ (u32)data[2] << 16 |
+ (u32)data[3] << 24);
+#endif
+}
/**
- * efx_init_rx_buffer_skb - create new RX buffer using skb-based allocation
+ * efx_init_rx_buffers_skb - create EFX_RX_BATCH skb-based RX buffers
*
* @rx_queue: Efx RX queue
- * @rx_buf: RX buffer structure to populate
*
- * This allocates memory for a new receive buffer, maps it for DMA,
- * and populates a struct efx_rx_buffer with the relevant
- * information. Return a negative error code or 0 on success.
+ * This allocates EFX_RX_BATCH skbs, maps them for DMA, and populates a
+ * struct efx_rx_buffer for each one. Return a negative error code or 0
+ * on success. May fail having only inserted fewer than EFX_RX_BATCH
+ * buffers.
*/
-static int efx_init_rx_buffer_skb(struct efx_rx_queue *rx_queue,
- struct efx_rx_buffer *rx_buf)
+static int efx_init_rx_buffers_skb(struct efx_rx_queue *rx_queue)
{
struct efx_nic *efx = rx_queue->efx;
struct net_device *net_dev = efx->net_dev;
+ struct efx_rx_buffer *rx_buf;
int skb_len = efx->rx_buffer_len;
+ unsigned index, count;
- rx_buf->skb = netdev_alloc_skb(net_dev, skb_len);
- if (unlikely(!rx_buf->skb))
- return -ENOMEM;
+ for (count = 0; count < EFX_RX_BATCH; ++count) {
+ index = rx_queue->added_count & rx_queue->ptr_mask;
+ rx_buf = efx_rx_buffer(rx_queue, index);
- /* Adjust the SKB for padding and checksum */
- skb_reserve(rx_buf->skb, NET_IP_ALIGN);
- rx_buf->len = skb_len - NET_IP_ALIGN;
- rx_buf->data = (char *)rx_buf->skb->data;
- rx_buf->skb->ip_summed = CHECKSUM_UNNECESSARY;
+ rx_buf->skb = netdev_alloc_skb(net_dev, skb_len);
+ if (unlikely(!rx_buf->skb))
+ return -ENOMEM;
+ rx_buf->page = NULL;
- rx_buf->dma_addr = pci_map_single(efx->pci_dev,
- rx_buf->data, rx_buf->len,
- PCI_DMA_FROMDEVICE);
+ /* Adjust the SKB for padding and checksum */
+ skb_reserve(rx_buf->skb, NET_IP_ALIGN);
+ rx_buf->len = skb_len - NET_IP_ALIGN;
+ rx_buf->data = (char *)rx_buf->skb->data;
+ rx_buf->skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+ rx_buf->dma_addr = pci_map_single(efx->pci_dev,
+ rx_buf->data, rx_buf->len,
+ PCI_DMA_FROMDEVICE);
+ if (unlikely(pci_dma_mapping_error(efx->pci_dev,
+ rx_buf->dma_addr))) {
+ dev_kfree_skb_any(rx_buf->skb);
+ rx_buf->skb = NULL;
+ return -EIO;
+ }
- if (unlikely(pci_dma_mapping_error(efx->pci_dev, rx_buf->dma_addr))) {
- dev_kfree_skb_any(rx_buf->skb);
- rx_buf->skb = NULL;
- return -EIO;
+ ++rx_queue->added_count;
+ ++rx_queue->alloc_skb_count;
}
return 0;
}
/**
- * efx_init_rx_buffer_page - create new RX buffer using page-based allocation
+ * efx_init_rx_buffers_page - create EFX_RX_BATCH page-based RX buffers
*
* @rx_queue: Efx RX queue
- * @rx_buf: RX buffer structure to populate
*
- * This allocates memory for a new receive buffer, maps it for DMA,
- * and populates a struct efx_rx_buffer with the relevant
- * information. Return a negative error code or 0 on success.
+ * This allocates memory for EFX_RX_BATCH receive buffers, maps them for DMA,
+ * and populates struct efx_rx_buffers for each one. Return a negative error
+ * code or 0 on success. If a single page can be split between two buffers,
+ * then the page will either be inserted fully, or not at at all.
*/
-static int efx_init_rx_buffer_page(struct efx_rx_queue *rx_queue,
- struct efx_rx_buffer *rx_buf)
+static int efx_init_rx_buffers_page(struct efx_rx_queue *rx_queue)
{
struct efx_nic *efx = rx_queue->efx;
- int bytes, space, offset;
-
- bytes = efx->rx_buffer_len - EFX_PAGE_IP_ALIGN;
-
- /* If there is space left in the previously allocated page,
- * then use it. Otherwise allocate a new one */
- rx_buf->page = rx_queue->buf_page;
- if (rx_buf->page == NULL) {
- dma_addr_t dma_addr;
-
- rx_buf->page = alloc_pages(__GFP_COLD | __GFP_COMP | GFP_ATOMIC,
- efx->rx_buffer_order);
- if (unlikely(rx_buf->page == NULL))
+ struct efx_rx_buffer *rx_buf;
+ struct page *page;
+ void *page_addr;
+ struct efx_rx_page_state *state;
+ dma_addr_t dma_addr;
+ unsigned index, count;
+
+ /* We can split a page between two buffers */
+ BUILD_BUG_ON(EFX_RX_BATCH & 1);
+
+ for (count = 0; count < EFX_RX_BATCH; ++count) {
+ page = alloc_pages(__GFP_COLD | __GFP_COMP | GFP_ATOMIC,
+ efx->rx_buffer_order);
+ if (unlikely(page == NULL))
return -ENOMEM;
-
- dma_addr = pci_map_page(efx->pci_dev, rx_buf->page,
- 0, efx_rx_buf_size(efx),
+ dma_addr = pci_map_page(efx->pci_dev, page, 0,
+ efx_rx_buf_size(efx),
PCI_DMA_FROMDEVICE);
-
if (unlikely(pci_dma_mapping_error(efx->pci_dev, dma_addr))) {
- __free_pages(rx_buf->page, efx->rx_buffer_order);
- rx_buf->page = NULL;
+ __free_pages(page, efx->rx_buffer_order);
return -EIO;
}
-
- rx_queue->buf_page = rx_buf->page;
- rx_queue->buf_dma_addr = dma_addr;
- rx_queue->buf_data = (page_address(rx_buf->page) +
- EFX_PAGE_IP_ALIGN);
- }
-
- rx_buf->len = bytes;
- rx_buf->data = rx_queue->buf_data;
- offset = efx_rx_buf_offset(rx_buf);
- rx_buf->dma_addr = rx_queue->buf_dma_addr + offset;
-
- /* Try to pack multiple buffers per page */
- if (efx->rx_buffer_order == 0) {
- /* The next buffer starts on the next 512 byte boundary */
- rx_queue->buf_data += ((bytes + 0x1ff) & ~0x1ff);
- offset += ((bytes + 0x1ff) & ~0x1ff);
-
- space = efx_rx_buf_size(efx) - offset;
- if (space >= bytes) {
- /* Refs dropped on kernel releasing each skb */
- get_page(rx_queue->buf_page);
- goto out;
+ page_addr = page_address(page);
+ state = page_addr;
+ state->refcnt = 0;
+ state->dma_addr = dma_addr;
+
+ page_addr += sizeof(struct efx_rx_page_state);
+ dma_addr += sizeof(struct efx_rx_page_state);
+
+ split:
+ index = rx_queue->added_count & rx_queue->ptr_mask;
+ rx_buf = efx_rx_buffer(rx_queue, index);
+ rx_buf->dma_addr = dma_addr + EFX_PAGE_IP_ALIGN;
+ rx_buf->skb = NULL;
+ rx_buf->page = page;
+ rx_buf->data = page_addr + EFX_PAGE_IP_ALIGN;
+ rx_buf->len = efx->rx_buffer_len - EFX_PAGE_IP_ALIGN;
+ ++rx_queue->added_count;
+ ++rx_queue->alloc_page_count;
+ ++state->refcnt;
+
+ if ((~count & 1) && (efx->rx_buffer_len <= EFX_RX_HALF_PAGE)) {
+ /* Use the second half of the page */
+ get_page(page);
+ dma_addr += (PAGE_SIZE >> 1);
+ page_addr += (PAGE_SIZE >> 1);
+ ++count;
+ goto split;
}
}
- /* This is the final RX buffer for this page, so mark it for
- * unmapping */
- rx_queue->buf_page = NULL;
- rx_buf->unmap_addr = rx_queue->buf_dma_addr;
-
- out:
return 0;
}
-/* This allocates memory for a new receive buffer, maps it for DMA,
- * and populates a struct efx_rx_buffer with the relevant
- * information.
- */
-static int efx_init_rx_buffer(struct efx_rx_queue *rx_queue,
- struct efx_rx_buffer *new_rx_buf)
-{
- int rc = 0;
-
- if (rx_queue->channel->rx_alloc_push_pages) {
- new_rx_buf->skb = NULL;
- rc = efx_init_rx_buffer_page(rx_queue, new_rx_buf);
- rx_queue->alloc_page_count++;
- } else {
- new_rx_buf->page = NULL;
- rc = efx_init_rx_buffer_skb(rx_queue, new_rx_buf);
- rx_queue->alloc_skb_count++;
- }
-
- if (unlikely(rc < 0))
- EFX_LOG_RL(rx_queue->efx, "%s RXQ[%d] =%d\n", __func__,
- rx_queue->queue, rc);
- return rc;
-}
-
static void efx_unmap_rx_buffer(struct efx_nic *efx,
struct efx_rx_buffer *rx_buf)
{
if (rx_buf->page) {
+ struct efx_rx_page_state *state;
+
EFX_BUG_ON_PARANOID(rx_buf->skb);
- if (rx_buf->unmap_addr) {
- pci_unmap_page(efx->pci_dev, rx_buf->unmap_addr,
+
+ state = page_address(rx_buf->page);
+ if (--state->refcnt == 0) {
+ pci_unmap_page(efx->pci_dev,
+ state->dma_addr,
efx_rx_buf_size(efx),
PCI_DMA_FROMDEVICE);
- rx_buf->unmap_addr = 0;
}
} else if (likely(rx_buf->skb)) {
pci_unmap_single(efx->pci_dev, rx_buf->dma_addr,
@@ -273,31 +272,84 @@ static void efx_fini_rx_buffer(struct efx_rx_queue *rx_queue,
efx_free_rx_buffer(rx_queue->efx, rx_buf);
}
+/* Attempt to resurrect the other receive buffer that used to share this page,
+ * which had previously been passed up to the kernel and freed. */
+static void efx_resurrect_rx_buffer(struct efx_rx_queue *rx_queue,
+ struct efx_rx_buffer *rx_buf)
+{
+ struct efx_rx_page_state *state = page_address(rx_buf->page);
+ struct efx_rx_buffer *new_buf;
+ unsigned fill_level, index;
+
+ /* +1 because efx_rx_packet() incremented removed_count. +1 because
+ * we'd like to insert an additional descriptor whilst leaving
+ * EFX_RXD_HEAD_ROOM for the non-recycle path */
+ fill_level = (rx_queue->added_count - rx_queue->removed_count + 2);
+ if (unlikely(fill_level > rx_queue->max_fill)) {
+ /* We could place "state" on a list, and drain the list in
+ * efx_fast_push_rx_descriptors(). For now, this will do. */
+ return;
+ }
+
+ ++state->refcnt;
+ get_page(rx_buf->page);
+
+ index = rx_queue->added_count & rx_queue->ptr_mask;
+ new_buf = efx_rx_buffer(rx_queue, index);
+ new_buf->dma_addr = rx_buf->dma_addr ^ (PAGE_SIZE >> 1);
+ new_buf->skb = NULL;
+ new_buf->page = rx_buf->page;
+ new_buf->data = (void *)
+ ((__force unsigned long)rx_buf->data ^ (PAGE_SIZE >> 1));
+ new_buf->len = rx_buf->len;
+ ++rx_queue->added_count;
+}
+
+/* Recycle the given rx buffer directly back into the rx_queue. There is
+ * always room to add this buffer, because we've just popped a buffer. */
+static void efx_recycle_rx_buffer(struct efx_channel *channel,
+ struct efx_rx_buffer *rx_buf)
+{
+ struct efx_nic *efx = channel->efx;
+ struct efx_rx_queue *rx_queue = efx_channel_get_rx_queue(channel);
+ struct efx_rx_buffer *new_buf;
+ unsigned index;
+
+ if (rx_buf->page != NULL && efx->rx_buffer_len <= EFX_RX_HALF_PAGE &&
+ page_count(rx_buf->page) == 1)
+ efx_resurrect_rx_buffer(rx_queue, rx_buf);
+
+ index = rx_queue->added_count & rx_queue->ptr_mask;
+ new_buf = efx_rx_buffer(rx_queue, index);
+
+ memcpy(new_buf, rx_buf, sizeof(*new_buf));
+ rx_buf->page = NULL;
+ rx_buf->skb = NULL;
+ ++rx_queue->added_count;
+}
+
/**
* efx_fast_push_rx_descriptors - push new RX descriptors quickly
* @rx_queue: RX descriptor queue
- * @retry: Recheck the fill level
* This will aim to fill the RX descriptor queue up to
* @rx_queue->@fast_fill_limit. If there is insufficient atomic
- * memory to do so, the caller should retry.
+ * memory to do so, a slow fill will be scheduled.
+ *
+ * The caller must provide serialisation (none is used here). In practise,
+ * this means this function must run from the NAPI handler, or be called
+ * when NAPI is disabled.
*/
-static int __efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue,
- int retry)
+void efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue)
{
- struct efx_rx_buffer *rx_buf;
- unsigned fill_level, index;
- int i, space, rc = 0;
+ struct efx_channel *channel = efx_rx_queue_channel(rx_queue);
+ unsigned fill_level;
+ int space, rc = 0;
- /* Calculate current fill level. Do this outside the lock,
- * because most of the time we'll end up not wanting to do the
- * fill anyway.
- */
+ /* Calculate current fill level, and exit if we don't need to fill */
fill_level = (rx_queue->added_count - rx_queue->removed_count);
- EFX_BUG_ON_PARANOID(fill_level > EFX_RXQ_SIZE);
-
- /* Don't fill if we don't need to */
+ EFX_BUG_ON_PARANOID(fill_level > rx_queue->efx->rxq_entries);
if (fill_level >= rx_queue->fast_fill_trigger)
- return 0;
+ goto out;
/* Record minimum fill level */
if (unlikely(fill_level < rx_queue->min_fill)) {
@@ -305,99 +357,48 @@ static int __efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue,
rx_queue->min_fill = fill_level;
}
- /* Acquire RX add lock. If this lock is contended, then a fast
- * fill must already be in progress (e.g. in the refill
- * tasklet), so we don't need to do anything
- */
- if (!spin_trylock_bh(&rx_queue->add_lock))
- return -1;
-
- retry:
- /* Recalculate current fill level now that we have the lock */
- fill_level = (rx_queue->added_count - rx_queue->removed_count);
- EFX_BUG_ON_PARANOID(fill_level > EFX_RXQ_SIZE);
space = rx_queue->fast_fill_limit - fill_level;
if (space < EFX_RX_BATCH)
- goto out_unlock;
+ goto out;
- EFX_TRACE(rx_queue->efx, "RX queue %d fast-filling descriptor ring from"
- " level %d to level %d using %s allocation\n",
- rx_queue->queue, fill_level, rx_queue->fast_fill_limit,
- rx_queue->channel->rx_alloc_push_pages ? "page" : "skb");
+ netif_vdbg(rx_queue->efx, rx_status, rx_queue->efx->net_dev,
+ "RX queue %d fast-filling descriptor ring from"
+ " level %d to level %d using %s allocation\n",
+ efx_rx_queue_index(rx_queue), fill_level,
+ rx_queue->fast_fill_limit,
+ channel->rx_alloc_push_pages ? "page" : "skb");
do {
- for (i = 0; i < EFX_RX_BATCH; ++i) {
- index = rx_queue->added_count & EFX_RXQ_MASK;
- rx_buf = efx_rx_buffer(rx_queue, index);
- rc = efx_init_rx_buffer(rx_queue, rx_buf);
- if (unlikely(rc))
- goto out;
- ++rx_queue->added_count;
+ if (channel->rx_alloc_push_pages)
+ rc = efx_init_rx_buffers_page(rx_queue);
+ else
+ rc = efx_init_rx_buffers_skb(rx_queue);
+ if (unlikely(rc)) {
+ /* Ensure that we don't leave the rx queue empty */
+ if (rx_queue->added_count == rx_queue->removed_count)
+ efx_schedule_slow_fill(rx_queue);
+ goto out;
}
} while ((space -= EFX_RX_BATCH) >= EFX_RX_BATCH);
- EFX_TRACE(rx_queue->efx, "RX queue %d fast-filled descriptor ring "
- "to level %d\n", rx_queue->queue,
- rx_queue->added_count - rx_queue->removed_count);
+ netif_vdbg(rx_queue->efx, rx_status, rx_queue->efx->net_dev,
+ "RX queue %d fast-filled descriptor ring "
+ "to level %d\n", efx_rx_queue_index(rx_queue),
+ rx_queue->added_count - rx_queue->removed_count);
out:
- /* Send write pointer to card. */
- efx_nic_notify_rx_desc(rx_queue);
-
- /* If the fast fill is running inside from the refill tasklet, then
- * for SMP systems it may be running on a different CPU to
- * RX event processing, which means that the fill level may now be
- * out of date. */
- if (unlikely(retry && (rc == 0)))
- goto retry;
-
- out_unlock:
- spin_unlock_bh(&rx_queue->add_lock);
-
- return rc;
-}
-
-/**
- * efx_fast_push_rx_descriptors - push new RX descriptors quickly
- * @rx_queue: RX descriptor queue
- *
- * This will aim to fill the RX descriptor queue up to
- * @rx_queue->@fast_fill_limit. If there is insufficient memory to do so,
- * it will schedule a work item to immediately continue the fast fill
- */
-void efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue)
-{
- int rc;
-
- rc = __efx_fast_push_rx_descriptors(rx_queue, 0);
- if (unlikely(rc)) {
- /* Schedule the work item to run immediately. The hope is
- * that work is immediately pending to free some memory
- * (e.g. an RX event or TX completion)
- */
- efx_schedule_slow_fill(rx_queue, 0);
- }
+ if (rx_queue->notified_count != rx_queue->added_count)
+ efx_nic_notify_rx_desc(rx_queue);
}
-void efx_rx_work(struct work_struct *data)
+void efx_rx_slow_fill(unsigned long context)
{
- struct efx_rx_queue *rx_queue;
- int rc;
-
- rx_queue = container_of(data, struct efx_rx_queue, work.work);
-
- if (unlikely(!rx_queue->channel->enabled))
- return;
-
- EFX_TRACE(rx_queue->efx, "RX queue %d worker thread executing on CPU "
- "%d\n", rx_queue->queue, raw_smp_processor_id());
+ struct efx_rx_queue *rx_queue = (struct efx_rx_queue *)context;
+ struct efx_channel *channel = efx_rx_queue_channel(rx_queue);
+ /* Post an event to cause NAPI to run and refill the queue */
+ efx_nic_generate_fill_event(channel);
++rx_queue->slow_fill_count;
- /* Push new RX descriptors, allowing at least 1 jiffy for
- * the kernel to free some more memory. */
- rc = __efx_fast_push_rx_descriptors(rx_queue, 1);
- if (rc)
- efx_schedule_slow_fill(rx_queue, 1);
}
static void efx_rx_packet__check_len(struct efx_rx_queue *rx_queue,
@@ -417,10 +418,12 @@ static void efx_rx_packet__check_len(struct efx_rx_queue *rx_queue,
*discard = true;
if ((len > rx_buf->len) && EFX_WORKAROUND_8071(efx)) {
- EFX_ERR_RL(efx, " RX queue %d seriously overlength "
- "RX event (0x%x > 0x%x+0x%x). Leaking\n",
- rx_queue->queue, len, max_len,
- efx->type->rx_buffer_padding);
+ if (net_ratelimit())
+ netif_err(efx, rx_err, efx->net_dev,
+ " RX queue %d seriously overlength "
+ "RX event (0x%x > 0x%x+0x%x). Leaking\n",
+ efx_rx_queue_index(rx_queue), len, max_len,
+ efx->type->rx_buffer_padding);
/* If this buffer was skb-allocated, then the meta
* data at the end of the skb will be trashed. So
* we have no choice but to leak the fragment.
@@ -428,11 +431,14 @@ static void efx_rx_packet__check_len(struct efx_rx_queue *rx_queue,
*leak_packet = (rx_buf->skb != NULL);
efx_schedule_reset(efx, RESET_TYPE_RX_RECOVERY);
} else {
- EFX_ERR_RL(efx, " RX queue %d overlength RX event "
- "(0x%x > 0x%x)\n", rx_queue->queue, len, max_len);
+ if (net_ratelimit())
+ netif_err(efx, rx_err, efx->net_dev,
+ " RX queue %d overlength RX event "
+ "(0x%x > 0x%x)\n",
+ efx_rx_queue_index(rx_queue), len, max_len);
}
- rx_queue->channel->n_rx_overlength++;
+ efx_rx_queue_channel(rx_queue)->n_rx_overlength++;
}
/* Pass a received packet up through the generic LRO stack
@@ -449,6 +455,7 @@ static void efx_rx_packet_lro(struct efx_channel *channel,
/* Pass the skb/page into the LRO engine */
if (rx_buf->page) {
+ struct efx_nic *efx = channel->efx;
struct page *page = rx_buf->page;
struct sk_buff *skb;
@@ -461,6 +468,9 @@ static void efx_rx_packet_lro(struct efx_channel *channel,
return;
}
+ if (efx->net_dev->features & NETIF_F_RXHASH)
+ skb->rxhash = efx_rx_buf_hash(rx_buf);
+
skb_shinfo(skb)->frags[0].page = page;
skb_shinfo(skb)->frags[0].page_offset =
efx_rx_buf_offset(rx_buf);
@@ -498,6 +508,7 @@ void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index,
unsigned int len, bool checksummed, bool discard)
{
struct efx_nic *efx = rx_queue->efx;
+ struct efx_channel *channel = efx_rx_queue_channel(rx_queue);
struct efx_rx_buffer *rx_buf;
bool leak_packet = false;
@@ -516,21 +527,23 @@ void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index,
efx_rx_packet__check_len(rx_queue, rx_buf, len,
&discard, &leak_packet);
- EFX_TRACE(efx, "RX queue %d received id %x at %llx+%x %s%s\n",
- rx_queue->queue, index,
- (unsigned long long)rx_buf->dma_addr, len,
- (checksummed ? " [SUMMED]" : ""),
- (discard ? " [DISCARD]" : ""));
+ netif_vdbg(efx, rx_status, efx->net_dev,
+ "RX queue %d received id %x at %llx+%x %s%s\n",
+ efx_rx_queue_index(rx_queue), index,
+ (unsigned long long)rx_buf->dma_addr, len,
+ (checksummed ? " [SUMMED]" : ""),
+ (discard ? " [DISCARD]" : ""));
/* Discard packet, if instructed to do so */
if (unlikely(discard)) {
if (unlikely(leak_packet))
- rx_queue->channel->n_skbuff_leaks++;
+ channel->n_skbuff_leaks++;
else
- /* We haven't called efx_unmap_rx_buffer yet,
- * so fini the entire rx_buffer here */
- efx_fini_rx_buffer(rx_queue, rx_buf);
- return;
+ efx_recycle_rx_buffer(channel, rx_buf);
+
+ /* Don't hold off the previous receive */
+ rx_buf = NULL;
+ goto out;
}
/* Release card resources - assumes all RX buffers consumed in-order
@@ -547,12 +560,12 @@ void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index,
* prefetched into cache.
*/
rx_buf->len = len;
- if (rx_queue->channel->rx_pkt)
- __efx_rx_packet(rx_queue->channel,
- rx_queue->channel->rx_pkt,
- rx_queue->channel->rx_pkt_csummed);
- rx_queue->channel->rx_pkt = rx_buf;
- rx_queue->channel->rx_pkt_csummed = checksummed;
+out:
+ if (channel->rx_pkt)
+ __efx_rx_packet(channel,
+ channel->rx_pkt, channel->rx_pkt_csummed);
+ channel->rx_pkt = rx_buf;
+ channel->rx_pkt_csummed = checksummed;
}
/* Handle a received packet. Second half: Touches packet payload. */
@@ -562,6 +575,9 @@ void __efx_rx_packet(struct efx_channel *channel,
struct efx_nic *efx = channel->efx;
struct sk_buff *skb;
+ rx_buf->data += efx->type->rx_buffer_hash_size;
+ rx_buf->len -= efx->type->rx_buffer_hash_size;
+
/* If we're in loopback test, then pass the packet directly to the
* loopback layer, and free the rx_buf here
*/
@@ -574,8 +590,12 @@ void __efx_rx_packet(struct efx_channel *channel,
if (rx_buf->skb) {
prefetch(skb_shinfo(rx_buf->skb));
+ skb_reserve(rx_buf->skb, efx->type->rx_buffer_hash_size);
skb_put(rx_buf->skb, rx_buf->len);
+ if (efx->net_dev->features & NETIF_F_RXHASH)
+ rx_buf->skb->rxhash = efx_rx_buf_hash(rx_buf);
+
/* Move past the ethernet header. rx_buf->data still points
* at the ethernet header */
rx_buf->skb->protocol = eth_type_trans(rx_buf->skb,
@@ -595,7 +615,7 @@ void __efx_rx_packet(struct efx_channel *channel,
EFX_BUG_ON_PARANOID(!skb);
/* Set the SKB flags */
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
/* Pass the packet up */
netif_receive_skb(skb);
@@ -630,14 +650,22 @@ void efx_rx_strategy(struct efx_channel *channel)
int efx_probe_rx_queue(struct efx_rx_queue *rx_queue)
{
struct efx_nic *efx = rx_queue->efx;
- unsigned int rxq_size;
+ unsigned int entries;
int rc;
- EFX_LOG(efx, "creating RX queue %d\n", rx_queue->queue);
+ /* Create the smallest power-of-two aligned ring */
+ entries = max(roundup_pow_of_two(efx->rxq_entries), EFX_MIN_DMAQ_SIZE);
+ EFX_BUG_ON_PARANOID(entries > EFX_MAX_DMAQ_SIZE);
+ rx_queue->ptr_mask = entries - 1;
+
+ netif_dbg(efx, probe, efx->net_dev,
+ "creating RX queue %d size %#x mask %#x\n",
+ efx_rx_queue_index(rx_queue), efx->rxq_entries,
+ rx_queue->ptr_mask);
/* Allocate RX buffers */
- rxq_size = EFX_RXQ_SIZE * sizeof(*rx_queue->buffer);
- rx_queue->buffer = kzalloc(rxq_size, GFP_KERNEL);
+ rx_queue->buffer = kzalloc(entries * sizeof(*rx_queue->buffer),
+ GFP_KERNEL);
if (!rx_queue->buffer)
return -ENOMEM;
@@ -651,19 +679,20 @@ int efx_probe_rx_queue(struct efx_rx_queue *rx_queue)
void efx_init_rx_queue(struct efx_rx_queue *rx_queue)
{
+ struct efx_nic *efx = rx_queue->efx;
unsigned int max_fill, trigger, limit;
- EFX_LOG(rx_queue->efx, "initialising RX queue %d\n", rx_queue->queue);
+ netif_dbg(rx_queue->efx, drv, rx_queue->efx->net_dev,
+ "initialising RX queue %d\n", efx_rx_queue_index(rx_queue));
/* Initialise ptr fields */
rx_queue->added_count = 0;
rx_queue->notified_count = 0;
rx_queue->removed_count = 0;
rx_queue->min_fill = -1U;
- rx_queue->min_overfill = -1U;
/* Initialise limit fields */
- max_fill = EFX_RXQ_SIZE - EFX_RXD_HEAD_ROOM;
+ max_fill = efx->rxq_entries - EFX_RXD_HEAD_ROOM;
trigger = max_fill * min(rx_refill_threshold, 100U) / 100U;
limit = max_fill * min(rx_refill_limit, 100U) / 100U;
@@ -680,32 +709,25 @@ void efx_fini_rx_queue(struct efx_rx_queue *rx_queue)
int i;
struct efx_rx_buffer *rx_buf;
- EFX_LOG(rx_queue->efx, "shutting down RX queue %d\n", rx_queue->queue);
+ netif_dbg(rx_queue->efx, drv, rx_queue->efx->net_dev,
+ "shutting down RX queue %d\n", efx_rx_queue_index(rx_queue));
+ del_timer_sync(&rx_queue->slow_fill);
efx_nic_fini_rx(rx_queue);
/* Release RX buffers NB start at index 0 not current HW ptr */
if (rx_queue->buffer) {
- for (i = 0; i <= EFX_RXQ_MASK; i++) {
+ for (i = 0; i <= rx_queue->ptr_mask; i++) {
rx_buf = efx_rx_buffer(rx_queue, i);
efx_fini_rx_buffer(rx_queue, rx_buf);
}
}
-
- /* For a page that is part-way through splitting into RX buffers */
- if (rx_queue->buf_page != NULL) {
- pci_unmap_page(rx_queue->efx->pci_dev, rx_queue->buf_dma_addr,
- efx_rx_buf_size(rx_queue->efx),
- PCI_DMA_FROMDEVICE);
- __free_pages(rx_queue->buf_page,
- rx_queue->efx->rx_buffer_order);
- rx_queue->buf_page = NULL;
- }
}
void efx_remove_rx_queue(struct efx_rx_queue *rx_queue)
{
- EFX_LOG(rx_queue->efx, "destroying RX queue %d\n", rx_queue->queue);
+ netif_dbg(rx_queue->efx, drv, rx_queue->efx->net_dev,
+ "destroying RX queue %d\n", efx_rx_queue_index(rx_queue));
efx_nic_remove_rx(rx_queue);
diff --git a/drivers/net/sfc/selftest.c b/drivers/net/sfc/selftest.c
index 371e86cc090f..0ebfb99f1299 100644
--- a/drivers/net/sfc/selftest.c
+++ b/drivers/net/sfc/selftest.c
@@ -38,7 +38,7 @@ struct efx_loopback_payload {
struct udphdr udp;
__be16 iteration;
const char msg[64];
-} __attribute__ ((packed));
+} __packed;
/* Loopback test source MAC address */
static const unsigned char payload_source[ETH_ALEN] = {
@@ -48,6 +48,16 @@ static const unsigned char payload_source[ETH_ALEN] = {
static const char payload_msg[] =
"Hello world! This is an Efx loopback test in progress!";
+/* Interrupt mode names */
+static const unsigned int efx_interrupt_mode_max = EFX_INT_MODE_MAX;
+static const char *efx_interrupt_mode_names[] = {
+ [EFX_INT_MODE_MSIX] = "MSI-X",
+ [EFX_INT_MODE_MSI] = "MSI",
+ [EFX_INT_MODE_LEGACY] = "legacy",
+};
+#define INT_MODE(efx) \
+ STRING_TABLE_LOOKUP(efx->interrupt_mode, efx_interrupt_mode)
+
/**
* efx_loopback_state - persistent state during a loopback selftest
* @flush: Drop all packets in efx_loopback_rx_packet
@@ -123,7 +133,7 @@ static int efx_test_interrupts(struct efx_nic *efx,
{
struct efx_channel *channel;
- EFX_LOG(efx, "testing interrupts\n");
+ netif_dbg(efx, drv, efx->net_dev, "testing interrupts\n");
tests->interrupt = -1;
/* Reset interrupt flag */
@@ -142,16 +152,17 @@ static int efx_test_interrupts(struct efx_nic *efx,
efx_nic_generate_interrupt(efx);
/* Wait for arrival of test interrupt. */
- EFX_LOG(efx, "waiting for test interrupt\n");
+ netif_dbg(efx, drv, efx->net_dev, "waiting for test interrupt\n");
schedule_timeout_uninterruptible(HZ / 10);
if (efx->last_irq_cpu >= 0)
goto success;
- EFX_ERR(efx, "timed out waiting for interrupt\n");
+ netif_err(efx, drv, efx->net_dev, "timed out waiting for interrupt\n");
return -ETIMEDOUT;
success:
- EFX_LOG(efx, "%s test interrupt seen on CPU%d\n", INT_MODE(efx),
+ netif_dbg(efx, drv, efx->net_dev, "%s test interrupt seen on CPU%d\n",
+ INT_MODE(efx),
efx->last_irq_cpu);
tests->interrupt = 1;
return 0;
@@ -161,23 +172,18 @@ static int efx_test_interrupts(struct efx_nic *efx,
static int efx_test_eventq_irq(struct efx_channel *channel,
struct efx_self_tests *tests)
{
- unsigned int magic, count;
-
- /* Channel specific code, limited to 20 bits */
- magic = (0x00010150 + channel->channel);
- EFX_LOG(channel->efx, "channel %d testing event queue with code %x\n",
- channel->channel, magic);
+ struct efx_nic *efx = channel->efx;
+ unsigned int magic_count, count;
tests->eventq_dma[channel->channel] = -1;
tests->eventq_int[channel->channel] = -1;
tests->eventq_poll[channel->channel] = -1;
- /* Reset flag and zero magic word */
+ magic_count = channel->magic_count;
channel->efx->last_irq_cpu = -1;
- channel->eventq_magic = 0;
smp_wmb();
- efx_nic_generate_test_event(channel, magic);
+ efx_nic_generate_test_event(channel);
/* Wait for arrival of interrupt */
count = 0;
@@ -187,33 +193,36 @@ static int efx_test_eventq_irq(struct efx_channel *channel,
if (channel->work_pending)
efx_process_channel_now(channel);
- if (channel->eventq_magic == magic)
+ if (channel->magic_count != magic_count)
goto eventq_ok;
} while (++count < 2);
- EFX_ERR(channel->efx, "channel %d timed out waiting for event queue\n",
- channel->channel);
+ netif_err(efx, drv, efx->net_dev,
+ "channel %d timed out waiting for event queue\n",
+ channel->channel);
/* See if interrupt arrived */
if (channel->efx->last_irq_cpu >= 0) {
- EFX_ERR(channel->efx, "channel %d saw interrupt on CPU%d "
- "during event queue test\n", channel->channel,
- raw_smp_processor_id());
+ netif_err(efx, drv, efx->net_dev,
+ "channel %d saw interrupt on CPU%d "
+ "during event queue test\n", channel->channel,
+ raw_smp_processor_id());
tests->eventq_int[channel->channel] = 1;
}
/* Check to see if event was received even if interrupt wasn't */
efx_process_channel_now(channel);
- if (channel->eventq_magic == magic) {
- EFX_ERR(channel->efx, "channel %d event was generated, but "
- "failed to trigger an interrupt\n", channel->channel);
+ if (channel->magic_count != magic_count) {
+ netif_err(efx, drv, efx->net_dev,
+ "channel %d event was generated, but "
+ "failed to trigger an interrupt\n", channel->channel);
tests->eventq_dma[channel->channel] = 1;
}
return -ETIMEDOUT;
eventq_ok:
- EFX_LOG(channel->efx, "channel %d event queue passed\n",
- channel->channel);
+ netif_dbg(efx, drv, efx->net_dev, "channel %d event queue passed\n",
+ channel->channel);
tests->eventq_dma[channel->channel] = 1;
tests->eventq_int[channel->channel] = 1;
tests->eventq_poll[channel->channel] = 1;
@@ -266,51 +275,57 @@ void efx_loopback_rx_packet(struct efx_nic *efx,
/* Check that header exists */
if (pkt_len < sizeof(received->header)) {
- EFX_ERR(efx, "saw runt RX packet (length %d) in %s loopback "
- "test\n", pkt_len, LOOPBACK_MODE(efx));
+ netif_err(efx, drv, efx->net_dev,
+ "saw runt RX packet (length %d) in %s loopback "
+ "test\n", pkt_len, LOOPBACK_MODE(efx));
goto err;
}
/* Check that the ethernet header exists */
if (memcmp(&received->header, &payload->header, ETH_HLEN) != 0) {
- EFX_ERR(efx, "saw non-loopback RX packet in %s loopback test\n",
- LOOPBACK_MODE(efx));
+ netif_err(efx, drv, efx->net_dev,
+ "saw non-loopback RX packet in %s loopback test\n",
+ LOOPBACK_MODE(efx));
goto err;
}
/* Check packet length */
if (pkt_len != sizeof(*payload)) {
- EFX_ERR(efx, "saw incorrect RX packet length %d (wanted %d) in "
- "%s loopback test\n", pkt_len, (int)sizeof(*payload),
- LOOPBACK_MODE(efx));
+ 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));
goto err;
}
/* Check that IP header matches */
if (memcmp(&received->ip, &payload->ip, sizeof(payload->ip)) != 0) {
- EFX_ERR(efx, "saw corrupted IP header in %s loopback test\n",
- LOOPBACK_MODE(efx));
+ netif_err(efx, drv, efx->net_dev,
+ "saw corrupted IP header in %s loopback test\n",
+ LOOPBACK_MODE(efx));
goto err;
}
/* Check that msg and padding matches */
if (memcmp(&received->msg, &payload->msg, sizeof(received->msg)) != 0) {
- EFX_ERR(efx, "saw corrupted RX packet in %s loopback test\n",
- LOOPBACK_MODE(efx));
+ netif_err(efx, drv, efx->net_dev,
+ "saw corrupted RX packet in %s loopback test\n",
+ LOOPBACK_MODE(efx));
goto err;
}
/* Check that iteration matches */
if (received->iteration != payload->iteration) {
- EFX_ERR(efx, "saw RX packet from iteration %d (wanted %d) in "
- "%s loopback test\n", ntohs(received->iteration),
- ntohs(payload->iteration), LOOPBACK_MODE(efx));
+ netif_err(efx, drv, efx->net_dev,
+ "saw RX packet from iteration %d (wanted %d) in "
+ "%s loopback test\n", ntohs(received->iteration),
+ ntohs(payload->iteration), LOOPBACK_MODE(efx));
goto err;
}
/* Increase correct RX count */
- EFX_TRACE(efx, "got loopback RX in %s loopback test\n",
- LOOPBACK_MODE(efx));
+ netif_vdbg(efx, drv, efx->net_dev,
+ "got loopback RX in %s loopback test\n", LOOPBACK_MODE(efx));
atomic_inc(&state->rx_good);
return;
@@ -318,10 +333,10 @@ void efx_loopback_rx_packet(struct efx_nic *efx,
err:
#ifdef EFX_ENABLE_DEBUG
if (atomic_read(&state->rx_bad) == 0) {
- EFX_ERR(efx, "received packet:\n");
+ netif_err(efx, drv, efx->net_dev, "received packet:\n");
print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 0x10, 1,
buf_ptr, pkt_len, 0);
- EFX_ERR(efx, "expected packet:\n");
+ 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);
}
@@ -402,9 +417,11 @@ static int efx_begin_loopback(struct efx_tx_queue *tx_queue)
netif_tx_unlock_bh(efx->net_dev);
if (rc != NETDEV_TX_OK) {
- EFX_ERR(efx, "TX queue %d could not transmit packet %d "
- "of %d in %s loopback test\n", tx_queue->queue,
- i + 1, state->packet_count, LOOPBACK_MODE(efx));
+ 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,
+ i + 1, state->packet_count,
+ LOOPBACK_MODE(efx));
/* Defer cleaning up the other skbs for the caller */
kfree_skb(skb);
@@ -460,20 +477,22 @@ static int efx_end_loopback(struct efx_tx_queue *tx_queue,
/* Don't free the skbs; they will be picked up on TX
* overflow or channel teardown.
*/
- EFX_ERR(efx, "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,
- LOOPBACK_MODE(efx));
+ 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,
+ LOOPBACK_MODE(efx));
rc = -ETIMEDOUT;
/* Allow to fall through so we see the RX errors as well */
}
/* We may always be up to a flush away from our desired packet total */
if (rx_good != state->packet_count) {
- EFX_LOG(efx, "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,
- LOOPBACK_MODE(efx));
+ 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,
+ LOOPBACK_MODE(efx));
rc = -ETIMEDOUT;
/* Fall through */
}
@@ -497,7 +516,7 @@ efx_test_loopback(struct efx_tx_queue *tx_queue,
for (i = 0; i < 3; i++) {
/* Determine how many packets to send */
- state->packet_count = EFX_TXQ_SIZE / 3;
+ state->packet_count = efx->txq_entries / 3;
state->packet_count = min(1 << (i << 2), state->packet_count);
state->skbs = kzalloc(sizeof(state->skbs[0]) *
state->packet_count, GFP_KERNEL);
@@ -505,9 +524,10 @@ efx_test_loopback(struct efx_tx_queue *tx_queue,
return -ENOMEM;
state->flush = false;
- EFX_LOG(efx, "TX queue %d testing %s loopback with %d "
- "packets\n", tx_queue->queue, LOOPBACK_MODE(efx),
- state->packet_count);
+ netif_dbg(efx, drv, efx->net_dev,
+ "TX queue %d testing %s loopback with %d packets\n",
+ tx_queue->queue, LOOPBACK_MODE(efx),
+ state->packet_count);
efx_iterate_state(efx);
begin_rc = efx_begin_loopback(tx_queue);
@@ -531,9 +551,10 @@ efx_test_loopback(struct efx_tx_queue *tx_queue,
}
}
- EFX_LOG(efx, "TX queue %d passed %s loopback test with a burst length "
- "of %d packets\n", tx_queue->queue, LOOPBACK_MODE(efx),
- state->packet_count);
+ 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),
+ state->packet_count);
return 0;
}
@@ -545,7 +566,7 @@ efx_test_loopback(struct efx_tx_queue *tx_queue,
static int efx_wait_for_link(struct efx_nic *efx)
{
struct efx_link_state *link_state = &efx->link_state;
- int count;
+ int count, link_up_count = 0;
bool link_up;
for (count = 0; count < 40; count++) {
@@ -556,7 +577,7 @@ static int efx_wait_for_link(struct efx_nic *efx)
efx->type->monitor(efx);
mutex_unlock(&efx->mac_lock);
} else {
- struct efx_channel *channel = &efx->channel[0];
+ struct efx_channel *channel = efx_get_channel(efx, 0);
if (channel->work_pending)
efx_process_channel_now(channel);
}
@@ -567,8 +588,12 @@ static int efx_wait_for_link(struct efx_nic *efx)
link_up = !efx->mac_op->check_fault(efx);
mutex_unlock(&efx->mac_lock);
- if (link_up)
- return 0;
+ if (link_up) {
+ if (++link_up_count == 2)
+ return 0;
+ } else {
+ link_up_count = 0;
+ }
}
return -ETIMEDOUT;
@@ -579,6 +604,7 @@ static int efx_test_loopbacks(struct efx_nic *efx, struct efx_self_tests *tests,
{
enum efx_loopback_mode mode;
struct efx_loopback_state *state;
+ struct efx_channel *channel = efx_get_channel(efx, 0);
struct efx_tx_queue *tx_queue;
int rc = 0;
@@ -604,20 +630,22 @@ static int efx_test_loopbacks(struct efx_nic *efx, struct efx_self_tests *tests,
rc = __efx_reconfigure_port(efx);
mutex_unlock(&efx->mac_lock);
if (rc) {
- EFX_ERR(efx, "unable to move into %s loopback\n",
- LOOPBACK_MODE(efx));
+ netif_err(efx, drv, efx->net_dev,
+ "unable to move into %s loopback\n",
+ LOOPBACK_MODE(efx));
goto out;
}
rc = efx_wait_for_link(efx);
if (rc) {
- EFX_ERR(efx, "loopback %s never came up\n",
- LOOPBACK_MODE(efx));
+ netif_err(efx, drv, efx->net_dev,
+ "loopback %s never came up\n",
+ LOOPBACK_MODE(efx));
goto out;
}
/* Test both types of TX queue */
- efx_for_each_channel_tx_queue(tx_queue, &efx->channel[0]) {
+ efx_for_each_channel_tx_queue(tx_queue, channel) {
state->offload_csum = (tx_queue->queue &
EFX_TXQ_TYPE_OFFLOAD);
rc = efx_test_loopback(tx_queue,
@@ -720,7 +748,8 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests,
rc_reset = rc;
if (rc_reset) {
- EFX_ERR(efx, "Unable to recover from chip test\n");
+ netif_err(efx, drv, efx->net_dev,
+ "Unable to recover from chip test\n");
efx_schedule_reset(efx, RESET_TYPE_DISABLE);
return rc_reset;
}
diff --git a/drivers/net/sfc/siena.c b/drivers/net/sfc/siena.c
index f2b1e6180753..45236f58a258 100644
--- a/drivers/net/sfc/siena.c
+++ b/drivers/net/sfc/siena.c
@@ -118,17 +118,18 @@ static int siena_probe_port(struct efx_nic *efx)
MC_CMD_MAC_NSTATS * sizeof(u64));
if (rc)
return rc;
- EFX_LOG(efx, "stats buffer at %llx (virt %p phys %llx)\n",
- (u64)efx->stats_buffer.dma_addr,
- efx->stats_buffer.addr,
- (u64)virt_to_phys(efx->stats_buffer.addr));
+ netif_dbg(efx, probe, efx->net_dev,
+ "stats buffer at %llx (virt %p phys %llx)\n",
+ (u64)efx->stats_buffer.dma_addr,
+ efx->stats_buffer.addr,
+ (u64)virt_to_phys(efx->stats_buffer.addr));
efx_mcdi_mac_stats(efx, efx->stats_buffer.dma_addr, 0, 0, 1);
return 0;
}
-void siena_remove_port(struct efx_nic *efx)
+static void siena_remove_port(struct efx_nic *efx)
{
efx->phy_op->remove(efx);
efx_nic_free_buffer(efx, &efx->stats_buffer);
@@ -216,7 +217,8 @@ static int siena_probe_nic(struct efx_nic *efx)
efx->nic_data = nic_data;
if (efx_nic_fpga_ver(efx) != 0) {
- EFX_ERR(efx, "Siena FPGA not supported\n");
+ netif_err(efx, probe, efx->net_dev,
+ "Siena FPGA not supported\n");
rc = -ENODEV;
goto fail1;
}
@@ -233,8 +235,8 @@ static int siena_probe_nic(struct efx_nic *efx)
rc = efx_mcdi_fwver(efx, &nic_data->fw_version, &nic_data->fw_build);
if (rc) {
- EFX_ERR(efx, "Failed to read MCPU firmware version - "
- "rc %d\n", rc);
+ netif_err(efx, probe, efx->net_dev,
+ "Failed to read MCPU firmware version - rc %d\n", rc);
goto fail1; /* MCPU absent? */
}
@@ -242,17 +244,19 @@ static int siena_probe_nic(struct efx_nic *efx)
* filter settings. We must do this before we reset the NIC */
rc = efx_mcdi_drv_attach(efx, true, &already_attached);
if (rc) {
- EFX_ERR(efx, "Unable to register driver with MCPU\n");
+ netif_err(efx, probe, efx->net_dev,
+ "Unable to register driver with MCPU\n");
goto fail2;
}
if (already_attached)
/* Not a fatal error */
- EFX_ERR(efx, "Host already registered with MCPU\n");
+ netif_err(efx, probe, efx->net_dev,
+ "Host already registered with MCPU\n");
/* Now we can reset the NIC */
rc = siena_reset_hw(efx, RESET_TYPE_ALL);
if (rc) {
- EFX_ERR(efx, "failed to reset NIC\n");
+ netif_err(efx, probe, efx->net_dev, "failed to reset NIC\n");
goto fail3;
}
@@ -264,24 +268,23 @@ static int siena_probe_nic(struct efx_nic *efx)
goto fail4;
BUG_ON(efx->irq_status.dma_addr & 0x0f);
- EFX_LOG(efx, "INT_KER at %llx (virt %p phys %llx)\n",
- (unsigned long long)efx->irq_status.dma_addr,
- efx->irq_status.addr,
- (unsigned long long)virt_to_phys(efx->irq_status.addr));
+ netif_dbg(efx, probe, efx->net_dev,
+ "INT_KER at %llx (virt %p phys %llx)\n",
+ (unsigned long long)efx->irq_status.dma_addr,
+ efx->irq_status.addr,
+ (unsigned long long)virt_to_phys(efx->irq_status.addr));
/* Read in the non-volatile configuration */
rc = siena_probe_nvconfig(efx);
if (rc == -EINVAL) {
- EFX_ERR(efx, "NVRAM is invalid therefore using defaults\n");
+ netif_err(efx, probe, efx->net_dev,
+ "NVRAM is invalid therefore using defaults\n");
efx->phy_type = PHY_TYPE_NONE;
efx->mdio.prtad = MDIO_PRTAD_NONE;
} else if (rc) {
goto fail5;
}
- get_random_bytes(&nic_data->ipv6_rss_key,
- sizeof(nic_data->ipv6_rss_key));
-
return 0;
fail5:
@@ -301,7 +304,6 @@ fail1:
*/
static int siena_init_nic(struct efx_nic *efx)
{
- struct siena_nic_data *nic_data = efx->nic_data;
efx_oword_t temp;
int rc;
@@ -326,25 +328,36 @@ static int siena_init_nic(struct efx_nic *efx)
efx_reado(efx, &temp, FR_AZ_RX_CFG);
EFX_SET_OWORD_FIELD(temp, FRF_BZ_RX_DESC_PUSH_EN, 0);
EFX_SET_OWORD_FIELD(temp, FRF_BZ_RX_INGR_EN, 1);
+ /* Enable hash insertion. This is broken for the 'Falcon' hash
+ * if IPv6 hashing is also enabled, so also select Toeplitz
+ * TCP/IPv4 and IPv4 hashes. */
+ EFX_SET_OWORD_FIELD(temp, FRF_BZ_RX_HASH_INSRT_HDR, 1);
+ EFX_SET_OWORD_FIELD(temp, FRF_BZ_RX_HASH_ALG, 1);
+ EFX_SET_OWORD_FIELD(temp, FRF_BZ_RX_IP_HASH, 1);
efx_writeo(efx, &temp, FR_AZ_RX_CFG);
+ /* Set hash key for IPv4 */
+ memcpy(&temp, efx->rx_hash_key, sizeof(temp));
+ efx_writeo(efx, &temp, FR_BZ_RX_RSS_TKEY);
+
/* Enable IPv6 RSS */
- BUILD_BUG_ON(sizeof(nic_data->ipv6_rss_key) !=
+ BUILD_BUG_ON(sizeof(efx->rx_hash_key) <
2 * sizeof(temp) + FRF_CZ_RX_RSS_IPV6_TKEY_HI_WIDTH / 8 ||
FRF_CZ_RX_RSS_IPV6_TKEY_HI_LBN != 0);
- memcpy(&temp, nic_data->ipv6_rss_key, sizeof(temp));
+ memcpy(&temp, efx->rx_hash_key, sizeof(temp));
efx_writeo(efx, &temp, FR_CZ_RX_RSS_IPV6_REG1);
- memcpy(&temp, nic_data->ipv6_rss_key + sizeof(temp), sizeof(temp));
+ memcpy(&temp, efx->rx_hash_key + sizeof(temp), sizeof(temp));
efx_writeo(efx, &temp, FR_CZ_RX_RSS_IPV6_REG2);
EFX_POPULATE_OWORD_2(temp, FRF_CZ_RX_RSS_IPV6_THASH_ENABLE, 1,
FRF_CZ_RX_RSS_IPV6_IP_THASH_ENABLE, 1);
- memcpy(&temp, nic_data->ipv6_rss_key + 2 * sizeof(temp),
+ memcpy(&temp, efx->rx_hash_key + 2 * sizeof(temp),
FRF_CZ_RX_RSS_IPV6_TKEY_HI_WIDTH / 8);
efx_writeo(efx, &temp, FR_CZ_RX_RSS_IPV6_REG3);
if (efx_nic_rx_xoff_thresh >= 0 || efx_nic_rx_xon_thresh >= 0)
/* No MCDI operation has been defined to set thresholds */
- EFX_ERR(efx, "ignoring RX flow control thresholds\n");
+ netif_err(efx, hw, efx->net_dev,
+ "ignoring RX flow control thresholds\n");
/* Enable event logging */
rc = efx_mcdi_log_ctrl(efx, true, false, 0);
@@ -437,7 +450,7 @@ static int siena_try_update_nic_stats(struct efx_nic *efx)
mac_stats->rx_bad_bytes);
MAC_STAT(rx_packets, RX_PKTS);
MAC_STAT(rx_good, RX_GOOD_PKTS);
- mac_stats->rx_bad = mac_stats->rx_packets - mac_stats->rx_good;
+ MAC_STAT(rx_bad, RX_BAD_FCS_PKTS);
MAC_STAT(rx_pause, RX_PAUSE_PKTS);
MAC_STAT(rx_control, RX_CONTROL_PKTS);
MAC_STAT(rx_unicast, RX_UNICAST_PKTS);
@@ -565,7 +578,8 @@ static int siena_set_wol(struct efx_nic *efx, u32 type)
return 0;
fail:
- EFX_ERR(efx, "%s failed: type=%d rc=%d\n", __func__, type, rc);
+ netif_err(efx, hw, efx->net_dev, "%s failed: type=%d rc=%d\n",
+ __func__, type, rc);
return rc;
}
@@ -628,6 +642,7 @@ struct efx_nic_type siena_a0_nic_type = {
.evq_ptr_tbl_base = FR_BZ_EVQ_PTR_TBL,
.evq_rptr_tbl_base = FR_BZ_EVQ_RPTR,
.max_dma_mask = DMA_BIT_MASK(FSF_AZ_TX_KER_BUF_ADDR_WIDTH),
+ .rx_buffer_hash_size = 0x10,
.rx_buffer_padding = 0,
.max_interrupt_mode = EFX_INT_MODE_MSIX,
.phys_addr_channels = 32, /* Hardware limit is 64, but the legacy
@@ -635,6 +650,7 @@ struct efx_nic_type siena_a0_nic_type = {
* channels */
.tx_dc_base = 0x88000,
.rx_dc_base = 0x68000,
- .offload_features = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM,
+ .offload_features = (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
+ NETIF_F_RXHASH | NETIF_F_NTUPLE),
.reset_world_flags = ETH_RESET_MGMT << ETH_RESET_SHARED_SHIFT,
};
diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c
index f21efe7bd316..1bc6c48c96ee 100644
--- a/drivers/net/sfc/tenxpress.c
+++ b/drivers/net/sfc/tenxpress.c
@@ -19,10 +19,7 @@
#include "workarounds.h"
#include "selftest.h"
-/* We expect these MMDs to be in the package. SFT9001 also has a
- * clause 22 extension MMD, but since it doesn't have all the generic
- * MMD registers it is pointless to include it here.
- */
+/* We expect these MMDs to be in the package. */
#define TENXPRESS_REQUIRED_DEVS (MDIO_DEVS_PMAPMD | \
MDIO_DEVS_PCS | \
MDIO_DEVS_PHYXS | \
@@ -33,12 +30,6 @@
(1 << LOOPBACK_PMAPMD) | \
(1 << LOOPBACK_PHYXS_WS))
-#define SFT9001_LOOPBACKS ((1 << LOOPBACK_GPHY) | \
- (1 << LOOPBACK_PHYXS) | \
- (1 << LOOPBACK_PCS) | \
- (1 << LOOPBACK_PMAPMD) | \
- (1 << LOOPBACK_PHYXS_WS))
-
/* We complain if we fail to see the link partner as 10G capable this many
* times in a row (must be > 1 as sampling the autoneg. registers is racy)
*/
@@ -50,9 +41,8 @@
#define PMA_PMD_EXT_GMII_EN_WIDTH 1
#define PMA_PMD_EXT_CLK_OUT_LBN 2
#define PMA_PMD_EXT_CLK_OUT_WIDTH 1
-#define PMA_PMD_LNPGA_POWERDOWN_LBN 8 /* SFX7101 only */
+#define PMA_PMD_LNPGA_POWERDOWN_LBN 8
#define PMA_PMD_LNPGA_POWERDOWN_WIDTH 1
-#define PMA_PMD_EXT_CLK312_LBN 8 /* SFT9001 only */
#define PMA_PMD_EXT_CLK312_WIDTH 1
#define PMA_PMD_EXT_LPOWER_LBN 12
#define PMA_PMD_EXT_LPOWER_WIDTH 1
@@ -84,7 +74,6 @@
#define PMA_PMD_LED_FLASH (3)
#define PMA_PMD_LED_MASK 3
/* All LEDs under hardware control */
-#define SFT9001_PMA_PMD_LED_DEFAULT 0
/* Green and Amber under hardware control, Red off */
#define SFX7101_PMA_PMD_LED_DEFAULT (PMA_PMD_LED_OFF << PMA_PMD_LED_RX_LBN)
@@ -98,31 +87,7 @@
#define PMA_PMD_SPEED_LBN 4
#define PMA_PMD_SPEED_WIDTH 4
-/* Cable diagnostics - SFT9001 only */
-#define PMA_PMD_CDIAG_CTRL_REG 49213
-#define CDIAG_CTRL_IMMED_LBN 15
-#define CDIAG_CTRL_BRK_LINK_LBN 12
-#define CDIAG_CTRL_IN_PROG_LBN 11
-#define CDIAG_CTRL_LEN_UNIT_LBN 10
-#define CDIAG_CTRL_LEN_METRES 1
-#define PMA_PMD_CDIAG_RES_REG 49174
-#define CDIAG_RES_A_LBN 12
-#define CDIAG_RES_B_LBN 8
-#define CDIAG_RES_C_LBN 4
-#define CDIAG_RES_D_LBN 0
-#define CDIAG_RES_WIDTH 4
-#define CDIAG_RES_OPEN 2
-#define CDIAG_RES_OK 1
-#define CDIAG_RES_INVALID 0
-/* Set of 4 registers for pairs A-D */
-#define PMA_PMD_CDIAG_LEN_REG 49175
-
-/* Serdes control registers - SFT9001 only */
-#define PMA_PMD_CSERDES_CTRL_REG 64258
-/* Set the 156.25 MHz output to 312.5 MHz to drive Falcon's XMAC */
-#define PMA_PMD_CSERDES_DEFAULT 0x000f
-
-/* Misc register defines - SFX7101 only */
+/* Misc register defines */
#define PCS_CLOCK_CTRL_REG 55297
#define PLL312_RST_N_LBN 2
@@ -185,120 +150,17 @@ struct tenxpress_phy_data {
int bad_lp_tries;
};
-static ssize_t show_phy_short_reach(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev));
- int reg;
-
- reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, MDIO_PMA_10GBT_TXPWR);
- return sprintf(buf, "%d\n", !!(reg & MDIO_PMA_10GBT_TXPWR_SHORT));
-}
-
-static ssize_t set_phy_short_reach(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev));
- int rc;
-
- rtnl_lock();
- if (efx->state != STATE_RUNNING) {
- rc = -EBUSY;
- } else {
- efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, MDIO_PMA_10GBT_TXPWR,
- MDIO_PMA_10GBT_TXPWR_SHORT,
- count != 0 && *buf != '0');
- rc = efx_reconfigure_port(efx);
- }
- rtnl_unlock();
-
- return rc < 0 ? rc : (ssize_t)count;
-}
-
-static DEVICE_ATTR(phy_short_reach, 0644, show_phy_short_reach,
- set_phy_short_reach);
-
-int sft9001_wait_boot(struct efx_nic *efx)
-{
- unsigned long timeout = jiffies + HZ + 1;
- int boot_stat;
-
- for (;;) {
- boot_stat = efx_mdio_read(efx, MDIO_MMD_PCS,
- PCS_BOOT_STATUS_REG);
- if (boot_stat >= 0) {
- EFX_LOG(efx, "PHY boot status = %#x\n", boot_stat);
- switch (boot_stat &
- ((1 << PCS_BOOT_FATAL_ERROR_LBN) |
- (3 << PCS_BOOT_PROGRESS_LBN) |
- (1 << PCS_BOOT_DOWNLOAD_WAIT_LBN) |
- (1 << PCS_BOOT_CODE_STARTED_LBN))) {
- case ((1 << PCS_BOOT_FATAL_ERROR_LBN) |
- (PCS_BOOT_PROGRESS_CHECKSUM <<
- PCS_BOOT_PROGRESS_LBN)):
- case ((1 << PCS_BOOT_FATAL_ERROR_LBN) |
- (PCS_BOOT_PROGRESS_INIT <<
- PCS_BOOT_PROGRESS_LBN) |
- (1 << PCS_BOOT_DOWNLOAD_WAIT_LBN)):
- return -EINVAL;
- case ((PCS_BOOT_PROGRESS_WAIT_MDIO <<
- PCS_BOOT_PROGRESS_LBN) |
- (1 << PCS_BOOT_DOWNLOAD_WAIT_LBN)):
- return (efx->phy_mode & PHY_MODE_SPECIAL) ?
- 0 : -EIO;
- case ((PCS_BOOT_PROGRESS_JUMP <<
- PCS_BOOT_PROGRESS_LBN) |
- (1 << PCS_BOOT_CODE_STARTED_LBN)):
- case ((PCS_BOOT_PROGRESS_JUMP <<
- PCS_BOOT_PROGRESS_LBN) |
- (1 << PCS_BOOT_DOWNLOAD_WAIT_LBN) |
- (1 << PCS_BOOT_CODE_STARTED_LBN)):
- return (efx->phy_mode & PHY_MODE_SPECIAL) ?
- -EIO : 0;
- default:
- if (boot_stat & (1 << PCS_BOOT_FATAL_ERROR_LBN))
- return -EIO;
- break;
- }
- }
-
- if (time_after_eq(jiffies, timeout))
- return -ETIMEDOUT;
-
- msleep(50);
- }
-}
-
static int tenxpress_init(struct efx_nic *efx)
{
- int reg;
-
- if (efx->phy_type == PHY_TYPE_SFX7101) {
- /* Enable 312.5 MHz clock */
- efx_mdio_write(efx, MDIO_MMD_PCS, PCS_TEST_SELECT_REG,
- 1 << CLK312_EN_LBN);
- } else {
- /* Enable 312.5 MHz clock and GMII */
- reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG);
- reg |= ((1 << PMA_PMD_EXT_GMII_EN_LBN) |
- (1 << PMA_PMD_EXT_CLK_OUT_LBN) |
- (1 << PMA_PMD_EXT_CLK312_LBN) |
- (1 << PMA_PMD_EXT_ROBUST_LBN));
-
- efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG, reg);
- efx_mdio_set_flag(efx, MDIO_MMD_C22EXT,
- GPHY_XCONTROL_REG, 1 << GPHY_ISOLATE_LBN,
- false);
- }
+ /* Enable 312.5 MHz clock */
+ efx_mdio_write(efx, MDIO_MMD_PCS, PCS_TEST_SELECT_REG,
+ 1 << CLK312_EN_LBN);
/* Set the LEDs up as: Green = Link, Amber = Link/Act, Red = Off */
- if (efx->phy_type == PHY_TYPE_SFX7101) {
- efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_CTRL_REG,
- 1 << PMA_PMA_LED_ACTIVITY_LBN, true);
- efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_OVERR_REG,
- SFX7101_PMA_PMD_LED_DEFAULT);
- }
+ efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_CTRL_REG,
+ 1 << PMA_PMA_LED_ACTIVITY_LBN, true);
+ efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_OVERR_REG,
+ SFX7101_PMA_PMD_LED_DEFAULT);
return 0;
}
@@ -306,7 +168,6 @@ static int tenxpress_init(struct efx_nic *efx)
static int tenxpress_phy_probe(struct efx_nic *efx)
{
struct tenxpress_phy_data *phy_data;
- int rc;
/* Allocate phy private storage */
phy_data = kzalloc(sizeof(*phy_data), GFP_KERNEL);
@@ -315,42 +176,15 @@ static int tenxpress_phy_probe(struct efx_nic *efx)
efx->phy_data = phy_data;
phy_data->phy_mode = efx->phy_mode;
- /* Create any special files */
- if (efx->phy_type == PHY_TYPE_SFT9001B) {
- rc = device_create_file(&efx->pci_dev->dev,
- &dev_attr_phy_short_reach);
- if (rc)
- goto fail;
- }
-
- if (efx->phy_type == PHY_TYPE_SFX7101) {
- efx->mdio.mmds = TENXPRESS_REQUIRED_DEVS;
- efx->mdio.mode_support = MDIO_SUPPORTS_C45;
-
- efx->loopback_modes = SFX7101_LOOPBACKS | FALCON_XMAC_LOOPBACKS;
+ efx->mdio.mmds = TENXPRESS_REQUIRED_DEVS;
+ efx->mdio.mode_support = MDIO_SUPPORTS_C45;
- efx->link_advertising = (ADVERTISED_TP | ADVERTISED_Autoneg |
- ADVERTISED_10000baseT_Full);
- } else {
- efx->mdio.mmds = TENXPRESS_REQUIRED_DEVS;
- efx->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22;
+ efx->loopback_modes = SFX7101_LOOPBACKS | FALCON_XMAC_LOOPBACKS;
- efx->loopback_modes = (SFT9001_LOOPBACKS |
- FALCON_XMAC_LOOPBACKS |
- FALCON_GMAC_LOOPBACKS);
-
- efx->link_advertising = (ADVERTISED_TP | ADVERTISED_Autoneg |
- ADVERTISED_10000baseT_Full |
- ADVERTISED_1000baseT_Full |
- ADVERTISED_100baseT_Full);
- }
+ efx->link_advertising = (ADVERTISED_TP | ADVERTISED_Autoneg |
+ ADVERTISED_10000baseT_Full);
return 0;
-
-fail:
- kfree(efx->phy_data);
- efx->phy_data = NULL;
- return rc;
}
static int tenxpress_phy_init(struct efx_nic *efx)
@@ -360,16 +194,6 @@ static int tenxpress_phy_init(struct efx_nic *efx)
falcon_board(efx)->type->init_phy(efx);
if (!(efx->phy_mode & PHY_MODE_SPECIAL)) {
- if (efx->phy_type == PHY_TYPE_SFT9001A) {
- int reg;
- reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD,
- PMA_PMD_XCONTROL_REG);
- reg |= (1 << PMA_PMD_EXT_SSR_LBN);
- efx_mdio_write(efx, MDIO_MMD_PMAPMD,
- PMA_PMD_XCONTROL_REG, reg);
- mdelay(200);
- }
-
rc = efx_mdio_wait_reset_mmds(efx, TENXPRESS_REQUIRED_DEVS);
if (rc < 0)
return rc;
@@ -402,7 +226,7 @@ static int tenxpress_special_reset(struct efx_nic *efx)
{
int rc, reg;
- /* The XGMAC clock is driven from the SFC7101/SFT9001 312MHz clock, so
+ /* The XGMAC clock is driven from the SFX7101 312MHz clock, so
* a special software reset can glitch the XGMAC sufficiently for stats
* requests to fail. */
falcon_stop_nic_stats(efx);
@@ -463,10 +287,11 @@ static void sfx7101_check_bad_lp(struct efx_nic *efx, bool link_ok)
reg |= PMA_PMD_LED_OFF << PMA_PMD_LED_RX_LBN;
} else {
reg |= PMA_PMD_LED_FLASH << PMA_PMD_LED_RX_LBN;
- EFX_ERR(efx, "appears to be plugged into a port"
- " that is not 10GBASE-T capable. The PHY"
- " supports 10GBASE-T ONLY, so no link can"
- " be established\n");
+ netif_err(efx, link, efx->net_dev,
+ "appears to be plugged into a port"
+ " that is not 10GBASE-T capable. The PHY"
+ " supports 10GBASE-T ONLY, so no link can"
+ " be established\n");
}
efx_mdio_write(efx, MDIO_MMD_PMAPMD,
PMA_PMD_LED_OVERR_REG, reg);
@@ -482,53 +307,18 @@ static bool sfx7101_link_ok(struct efx_nic *efx)
MDIO_DEVS_PHYXS);
}
-static bool sft9001_link_ok(struct efx_nic *efx, struct ethtool_cmd *ecmd)
-{
- u32 reg;
-
- if (efx_phy_mode_disabled(efx->phy_mode))
- return false;
- else if (efx->loopback_mode == LOOPBACK_GPHY)
- return true;
- else if (efx->loopback_mode)
- return efx_mdio_links_ok(efx,
- MDIO_DEVS_PMAPMD |
- MDIO_DEVS_PHYXS);
-
- /* We must use the same definition of link state as LASI,
- * otherwise we can miss a link state transition
- */
- if (ecmd->speed == 10000) {
- reg = efx_mdio_read(efx, MDIO_MMD_PCS, MDIO_PCS_10GBRT_STAT1);
- return reg & MDIO_PCS_10GBRT_STAT1_BLKLK;
- } else {
- reg = efx_mdio_read(efx, MDIO_MMD_C22EXT, C22EXT_STATUS_REG);
- return reg & (1 << C22EXT_STATUS_LINK_LBN);
- }
-}
-
static void tenxpress_ext_loopback(struct efx_nic *efx)
{
efx_mdio_set_flag(efx, MDIO_MMD_PHYXS, PHYXS_TEST1,
1 << LOOPBACK_NEAR_LBN,
efx->loopback_mode == LOOPBACK_PHYXS);
- if (efx->phy_type != PHY_TYPE_SFX7101)
- efx_mdio_set_flag(efx, MDIO_MMD_C22EXT, GPHY_XCONTROL_REG,
- 1 << GPHY_LOOPBACK_NEAR_LBN,
- efx->loopback_mode == LOOPBACK_GPHY);
}
static void tenxpress_low_power(struct efx_nic *efx)
{
- if (efx->phy_type == PHY_TYPE_SFX7101)
- efx_mdio_set_mmds_lpower(
- efx, !!(efx->phy_mode & PHY_MODE_LOW_POWER),
- TENXPRESS_REQUIRED_DEVS);
- else
- efx_mdio_set_flag(
- efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG,
- 1 << PMA_PMD_EXT_LPOWER_LBN,
- !!(efx->phy_mode & PHY_MODE_LOW_POWER));
+ efx_mdio_set_mmds_lpower(
+ efx, !!(efx->phy_mode & PHY_MODE_LOW_POWER),
+ TENXPRESS_REQUIRED_DEVS);
}
static int tenxpress_phy_reconfigure(struct efx_nic *efx)
@@ -548,12 +338,7 @@ static int tenxpress_phy_reconfigure(struct efx_nic *efx)
if (loop_reset || phy_mode_change) {
tenxpress_special_reset(efx);
-
- /* Reset XAUI if we were in 10G, and are staying
- * in 10G. If we're moving into and out of 10G
- * then xaui will be reset anyway */
- if (EFX_IS10G(efx))
- falcon_reset_xaui(efx);
+ falcon_reset_xaui(efx);
}
tenxpress_low_power(efx);
@@ -576,29 +361,12 @@ static bool tenxpress_phy_poll(struct efx_nic *efx)
{
struct efx_link_state old_state = efx->link_state;
- if (efx->phy_type == PHY_TYPE_SFX7101) {
- efx->link_state.up = sfx7101_link_ok(efx);
- efx->link_state.speed = 10000;
- efx->link_state.fd = true;
- efx->link_state.fc = efx_mdio_get_pause(efx);
-
- sfx7101_check_bad_lp(efx, efx->link_state.up);
- } else {
- struct ethtool_cmd ecmd;
-
- /* Check the LASI alarm first */
- if (efx->loopback_mode == LOOPBACK_NONE &&
- !(efx_mdio_read(efx, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_STAT) &
- MDIO_PMA_LASI_LSALARM))
- return false;
+ efx->link_state.up = sfx7101_link_ok(efx);
+ efx->link_state.speed = 10000;
+ efx->link_state.fd = true;
+ efx->link_state.fc = efx_mdio_get_pause(efx);
- tenxpress_get_settings(efx, &ecmd);
-
- efx->link_state.up = sft9001_link_ok(efx, &ecmd);
- efx->link_state.speed = ecmd.speed;
- efx->link_state.fd = (ecmd.duplex == DUPLEX_FULL);
- efx->link_state.fc = efx_mdio_get_pause(efx);
- }
+ sfx7101_check_bad_lp(efx, efx->link_state.up);
return !efx_link_state_equal(&efx->link_state, &old_state);
}
@@ -619,10 +387,6 @@ static void sfx7101_phy_fini(struct efx_nic *efx)
static void tenxpress_phy_remove(struct efx_nic *efx)
{
- if (efx->phy_type == PHY_TYPE_SFT9001B)
- device_remove_file(&efx->pci_dev->dev,
- &dev_attr_phy_short_reach);
-
kfree(efx->phy_data);
efx->phy_data = NULL;
}
@@ -645,10 +409,7 @@ void tenxpress_set_id_led(struct efx_nic *efx, enum efx_led_mode mode)
(PMA_PMD_LED_ON << PMA_PMD_LED_LINK_LBN);
break;
default:
- if (efx->phy_type == PHY_TYPE_SFX7101)
- reg = SFX7101_PMA_PMD_LED_DEFAULT;
- else
- reg = SFT9001_PMA_PMD_LED_DEFAULT;
+ reg = SFX7101_PMA_PMD_LED_DEFAULT;
break;
}
@@ -683,102 +444,12 @@ sfx7101_run_tests(struct efx_nic *efx, int *results, unsigned flags)
return rc;
}
-static const char *const sft9001_test_names[] = {
- "bist",
- "cable.pairA.status",
- "cable.pairB.status",
- "cable.pairC.status",
- "cable.pairD.status",
- "cable.pairA.length",
- "cable.pairB.length",
- "cable.pairC.length",
- "cable.pairD.length",
-};
-
-static const char *sft9001_test_name(struct efx_nic *efx, unsigned int index)
-{
- if (index < ARRAY_SIZE(sft9001_test_names))
- return sft9001_test_names[index];
- return NULL;
-}
-
-static int sft9001_run_tests(struct efx_nic *efx, int *results, unsigned flags)
-{
- int rc = 0, rc2, i, ctrl_reg, res_reg;
-
- /* Initialise cable diagnostic results to unknown failure */
- for (i = 1; i < 9; ++i)
- results[i] = -1;
-
- /* Run cable diagnostics; wait up to 5 seconds for them to complete.
- * A cable fault is not a self-test failure, but a timeout is. */
- ctrl_reg = ((1 << CDIAG_CTRL_IMMED_LBN) |
- (CDIAG_CTRL_LEN_METRES << CDIAG_CTRL_LEN_UNIT_LBN));
- if (flags & ETH_TEST_FL_OFFLINE) {
- /* Break the link in order to run full diagnostics. We
- * must reset the PHY to resume normal service. */
- ctrl_reg |= (1 << CDIAG_CTRL_BRK_LINK_LBN);
- }
- efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_CDIAG_CTRL_REG,
- ctrl_reg);
- i = 0;
- while (efx_mdio_read(efx, MDIO_MMD_PMAPMD, PMA_PMD_CDIAG_CTRL_REG) &
- (1 << CDIAG_CTRL_IN_PROG_LBN)) {
- if (++i == 50) {
- rc = -ETIMEDOUT;
- goto out;
- }
- msleep(100);
- }
- res_reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, PMA_PMD_CDIAG_RES_REG);
- for (i = 0; i < 4; i++) {
- int pair_res =
- (res_reg >> (CDIAG_RES_A_LBN - i * CDIAG_RES_WIDTH))
- & ((1 << CDIAG_RES_WIDTH) - 1);
- int len_reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD,
- PMA_PMD_CDIAG_LEN_REG + i);
- if (pair_res == CDIAG_RES_OK)
- results[1 + i] = 1;
- else if (pair_res == CDIAG_RES_INVALID)
- results[1 + i] = -1;
- else
- results[1 + i] = -pair_res;
- if (pair_res != CDIAG_RES_INVALID &&
- pair_res != CDIAG_RES_OPEN &&
- len_reg != 0xffff)
- results[5 + i] = len_reg;
- }
-
-out:
- if (flags & ETH_TEST_FL_OFFLINE) {
- /* Reset, running the BIST and then resuming normal service. */
- rc2 = tenxpress_special_reset(efx);
- results[0] = rc2 ? -1 : 1;
- if (!rc)
- rc = rc2;
-
- efx_mdio_an_reconfigure(efx);
- }
-
- return rc;
-}
-
static void
tenxpress_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
{
u32 adv = 0, lpa = 0;
int reg;
- if (efx->phy_type != PHY_TYPE_SFX7101) {
- reg = efx_mdio_read(efx, MDIO_MMD_C22EXT, C22EXT_MSTSLV_CTRL);
- if (reg & (1 << C22EXT_MSTSLV_CTRL_ADV_1000_FD_LBN))
- adv |= ADVERTISED_1000baseT_Full;
- reg = efx_mdio_read(efx, MDIO_MMD_C22EXT, C22EXT_MSTSLV_STATUS);
- if (reg & (1 << C22EXT_MSTSLV_STATUS_LP_1000_HD_LBN))
- lpa |= ADVERTISED_1000baseT_Half;
- if (reg & (1 << C22EXT_MSTSLV_STATUS_LP_1000_FD_LBN))
- lpa |= ADVERTISED_1000baseT_Full;
- }
reg = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL);
if (reg & MDIO_AN_10GBT_CTRL_ADV10G)
adv |= ADVERTISED_10000baseT_Full;
@@ -788,23 +459,9 @@ tenxpress_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
mdio45_ethtool_gset_npage(&efx->mdio, ecmd, adv, lpa);
- if (efx->phy_type != PHY_TYPE_SFX7101) {
- ecmd->supported |= (SUPPORTED_100baseT_Full |
- SUPPORTED_1000baseT_Full);
- if (ecmd->speed != SPEED_10000) {
- ecmd->eth_tp_mdix =
- (efx_mdio_read(efx, MDIO_MMD_PMAPMD,
- PMA_PMD_XSTATUS_REG) &
- (1 << PMA_PMD_XSTAT_MDIX_LBN))
- ? ETH_TP_MDI_X : ETH_TP_MDI;
- }
- }
-
/* In loopback, the PHY automatically brings up the correct interface,
* but doesn't advertise the correct speed. So override it */
- if (efx->loopback_mode == LOOPBACK_GPHY)
- ecmd->speed = SPEED_1000;
- else if (LOOPBACK_EXTERNAL(efx))
+ if (LOOPBACK_EXTERNAL(efx))
ecmd->speed = SPEED_10000;
}
@@ -823,16 +480,6 @@ static void sfx7101_set_npage_adv(struct efx_nic *efx, u32 advertising)
advertising & ADVERTISED_10000baseT_Full);
}
-static void sft9001_set_npage_adv(struct efx_nic *efx, u32 advertising)
-{
- efx_mdio_set_flag(efx, MDIO_MMD_C22EXT, C22EXT_MSTSLV_CTRL,
- 1 << C22EXT_MSTSLV_CTRL_ADV_1000_FD_LBN,
- advertising & ADVERTISED_1000baseT_Full);
- efx_mdio_set_flag(efx, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL,
- MDIO_AN_10GBT_CTRL_ADV10G,
- advertising & ADVERTISED_10000baseT_Full);
-}
-
struct efx_phy_operations falcon_sfx7101_phy_ops = {
.probe = tenxpress_phy_probe,
.init = tenxpress_phy_init,
@@ -847,18 +494,3 @@ struct efx_phy_operations falcon_sfx7101_phy_ops = {
.test_name = sfx7101_test_name,
.run_tests = sfx7101_run_tests,
};
-
-struct efx_phy_operations falcon_sft9001_phy_ops = {
- .probe = tenxpress_phy_probe,
- .init = tenxpress_phy_init,
- .reconfigure = tenxpress_phy_reconfigure,
- .poll = tenxpress_phy_poll,
- .fini = efx_port_dummy_op_void,
- .remove = tenxpress_phy_remove,
- .get_settings = tenxpress_get_settings,
- .set_settings = tenxpress_set_settings,
- .set_npage_adv = sft9001_set_npage_adv,
- .test_alive = efx_mdio_test_alive,
- .test_name = sft9001_test_name,
- .run_tests = sft9001_run_tests,
-};
diff --git a/drivers/net/sfc/tx.c b/drivers/net/sfc/tx.c
index 6bb12a87ef2d..11726989fe2d 100644
--- a/drivers/net/sfc/tx.c
+++ b/drivers/net/sfc/tx.c
@@ -28,7 +28,7 @@
* The tx_queue descriptor ring fill-level must fall below this value
* before we restart the netif queue
*/
-#define EFX_TXQ_THRESHOLD (EFX_TXQ_MASK / 2u)
+#define EFX_TXQ_THRESHOLD(_efx) ((_efx)->txq_entries / 2u)
/* We need to be able to nest calls to netif_tx_stop_queue(), partly
* because of the 2 hardware queues associated with each core queue,
@@ -37,18 +37,18 @@
void efx_stop_queue(struct efx_channel *channel)
{
struct efx_nic *efx = channel->efx;
+ struct efx_tx_queue *tx_queue = efx_channel_get_tx_queue(channel, 0);
- if (!channel->tx_queue)
+ if (!tx_queue)
return;
spin_lock_bh(&channel->tx_stop_lock);
- EFX_TRACE(efx, "stop TX queue\n");
+ netif_vdbg(efx, tx_queued, efx->net_dev, "stop TX queue\n");
atomic_inc(&channel->tx_stop_count);
netif_tx_stop_queue(
- netdev_get_tx_queue(
- efx->net_dev,
- channel->tx_queue->queue / EFX_TXQ_TYPES));
+ netdev_get_tx_queue(efx->net_dev,
+ tx_queue->queue / EFX_TXQ_TYPES));
spin_unlock_bh(&channel->tx_stop_lock);
}
@@ -57,18 +57,18 @@ void efx_stop_queue(struct efx_channel *channel)
void efx_wake_queue(struct efx_channel *channel)
{
struct efx_nic *efx = channel->efx;
+ struct efx_tx_queue *tx_queue = efx_channel_get_tx_queue(channel, 0);
- if (!channel->tx_queue)
+ if (!tx_queue)
return;
local_bh_disable();
if (atomic_dec_and_lock(&channel->tx_stop_count,
&channel->tx_stop_lock)) {
- EFX_TRACE(efx, "waking TX queue\n");
+ netif_vdbg(efx, tx_queued, efx->net_dev, "waking TX queue\n");
netif_tx_wake_queue(
- netdev_get_tx_queue(
- efx->net_dev,
- channel->tx_queue->queue / EFX_TXQ_TYPES));
+ netdev_get_tx_queue(efx->net_dev,
+ tx_queue->queue / EFX_TXQ_TYPES));
spin_unlock(&channel->tx_stop_lock);
}
local_bh_enable();
@@ -94,8 +94,9 @@ static void efx_dequeue_buffer(struct efx_tx_queue *tx_queue,
if (buffer->skb) {
dev_kfree_skb_any((struct sk_buff *) buffer->skb);
buffer->skb = NULL;
- EFX_TRACE(tx_queue->efx, "TX queue %d transmission id %x "
- "complete\n", tx_queue->queue, read_ptr);
+ netif_vdbg(tx_queue->efx, tx_done, tx_queue->efx->net_dev,
+ "TX queue %d transmission id %x complete\n",
+ tx_queue->queue, tx_queue->read_count);
}
}
@@ -206,7 +207,7 @@ netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
}
fill_level = tx_queue->insert_count - tx_queue->old_read_count;
- q_space = EFX_TXQ_MASK - 1 - fill_level;
+ q_space = efx->txq_entries - 1 - fill_level;
/* Map for DMA. Use pci_map_single rather than pci_map_page
* since this is more efficient on machines with sparse
@@ -243,14 +244,14 @@ netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
&tx_queue->read_count;
fill_level = (tx_queue->insert_count
- tx_queue->old_read_count);
- q_space = EFX_TXQ_MASK - 1 - fill_level;
+ q_space = efx->txq_entries - 1 - fill_level;
if (unlikely(q_space-- <= 0))
goto stop;
smp_mb();
--tx_queue->stopped;
}
- insert_ptr = tx_queue->insert_count & EFX_TXQ_MASK;
+ insert_ptr = tx_queue->insert_count & tx_queue->ptr_mask;
buffer = &tx_queue->buffer[insert_ptr];
efx_tsoh_free(tx_queue, buffer);
EFX_BUG_ON_PARANOID(buffer->tsoh);
@@ -300,9 +301,10 @@ netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
return NETDEV_TX_OK;
pci_err:
- EFX_ERR_RL(efx, " TX queue %d could not map skb with %d bytes %d "
- "fragments for DMA\n", tx_queue->queue, skb->len,
- skb_shinfo(skb)->nr_frags + 1);
+ netif_err(efx, tx_err, efx->net_dev,
+ " TX queue %d could not map skb with %d bytes %d "
+ "fragments for DMA\n", tx_queue->queue, skb->len,
+ skb_shinfo(skb)->nr_frags + 1);
/* Mark the packet as transmitted, and free the SKB ourselves */
dev_kfree_skb_any(skb);
@@ -318,7 +320,7 @@ netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
/* Work backwards until we hit the original insert pointer value */
while (tx_queue->insert_count != tx_queue->write_count) {
--tx_queue->insert_count;
- insert_ptr = tx_queue->insert_count & EFX_TXQ_MASK;
+ insert_ptr = tx_queue->insert_count & tx_queue->ptr_mask;
buffer = &tx_queue->buffer[insert_ptr];
efx_dequeue_buffer(tx_queue, buffer);
buffer->len = 0;
@@ -348,15 +350,15 @@ static void efx_dequeue_buffers(struct efx_tx_queue *tx_queue,
struct efx_nic *efx = tx_queue->efx;
unsigned int stop_index, read_ptr;
- stop_index = (index + 1) & EFX_TXQ_MASK;
- read_ptr = tx_queue->read_count & EFX_TXQ_MASK;
+ stop_index = (index + 1) & tx_queue->ptr_mask;
+ read_ptr = tx_queue->read_count & tx_queue->ptr_mask;
while (read_ptr != stop_index) {
struct efx_tx_buffer *buffer = &tx_queue->buffer[read_ptr];
if (unlikely(buffer->len == 0)) {
- EFX_ERR(tx_queue->efx, "TX queue %d spurious TX "
- "completion id %x\n", tx_queue->queue,
- read_ptr);
+ netif_err(efx, tx_err, efx->net_dev,
+ "TX queue %d spurious TX completion id %x\n",
+ tx_queue->queue, read_ptr);
efx_schedule_reset(efx, RESET_TYPE_TX_SKIP);
return;
}
@@ -366,7 +368,7 @@ static void efx_dequeue_buffers(struct efx_tx_queue *tx_queue,
buffer->len = 0;
++tx_queue->read_count;
- read_ptr = tx_queue->read_count & EFX_TXQ_MASK;
+ read_ptr = tx_queue->read_count & tx_queue->ptr_mask;
}
}
@@ -388,9 +390,9 @@ netdev_tx_t efx_hard_start_xmit(struct sk_buff *skb,
if (unlikely(efx->port_inhibited))
return NETDEV_TX_BUSY;
- tx_queue = &efx->tx_queue[EFX_TXQ_TYPES * skb_get_queue_mapping(skb)];
- if (likely(skb->ip_summed == CHECKSUM_PARTIAL))
- tx_queue += EFX_TXQ_TYPE_OFFLOAD;
+ tx_queue = efx_get_tx_queue(efx, skb_get_queue_mapping(skb),
+ skb->ip_summed == CHECKSUM_PARTIAL ?
+ EFX_TXQ_TYPE_OFFLOAD : 0);
return efx_enqueue_skb(tx_queue, skb);
}
@@ -400,7 +402,7 @@ void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index)
unsigned fill_level;
struct efx_nic *efx = tx_queue->efx;
- EFX_BUG_ON_PARANOID(index > EFX_TXQ_MASK);
+ EFX_BUG_ON_PARANOID(index > tx_queue->ptr_mask);
efx_dequeue_buffers(tx_queue, index);
@@ -410,7 +412,7 @@ void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index)
smp_mb();
if (unlikely(tx_queue->stopped) && likely(efx->port_enabled)) {
fill_level = tx_queue->insert_count - tx_queue->read_count;
- if (fill_level < EFX_TXQ_THRESHOLD) {
+ if (fill_level < EFX_TXQ_THRESHOLD(efx)) {
EFX_BUG_ON_PARANOID(!efx_dev_registered(efx));
/* Do this under netif_tx_lock(), to avoid racing
@@ -428,17 +430,24 @@ void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index)
int efx_probe_tx_queue(struct efx_tx_queue *tx_queue)
{
struct efx_nic *efx = tx_queue->efx;
- unsigned int txq_size;
+ unsigned int entries;
int i, rc;
- EFX_LOG(efx, "creating TX queue %d\n", tx_queue->queue);
+ /* Create the smallest power-of-two aligned ring */
+ entries = max(roundup_pow_of_two(efx->txq_entries), EFX_MIN_DMAQ_SIZE);
+ EFX_BUG_ON_PARANOID(entries > EFX_MAX_DMAQ_SIZE);
+ tx_queue->ptr_mask = entries - 1;
+
+ netif_dbg(efx, probe, efx->net_dev,
+ "creating TX queue %d size %#x mask %#x\n",
+ tx_queue->queue, efx->txq_entries, tx_queue->ptr_mask);
/* Allocate software ring */
- txq_size = EFX_TXQ_SIZE * sizeof(*tx_queue->buffer);
- tx_queue->buffer = kzalloc(txq_size, GFP_KERNEL);
+ tx_queue->buffer = kzalloc(entries * sizeof(*tx_queue->buffer),
+ GFP_KERNEL);
if (!tx_queue->buffer)
return -ENOMEM;
- for (i = 0; i <= EFX_TXQ_MASK; ++i)
+ for (i = 0; i <= tx_queue->ptr_mask; ++i)
tx_queue->buffer[i].continuation = true;
/* Allocate hardware ring */
@@ -456,7 +465,8 @@ int efx_probe_tx_queue(struct efx_tx_queue *tx_queue)
void efx_init_tx_queue(struct efx_tx_queue *tx_queue)
{
- EFX_LOG(tx_queue->efx, "initialising TX queue %d\n", tx_queue->queue);
+ netif_dbg(tx_queue->efx, drv, tx_queue->efx->net_dev,
+ "initialising TX queue %d\n", tx_queue->queue);
tx_queue->insert_count = 0;
tx_queue->write_count = 0;
@@ -477,7 +487,7 @@ void efx_release_tx_buffers(struct efx_tx_queue *tx_queue)
/* Free any buffers left in the ring */
while (tx_queue->read_count != tx_queue->write_count) {
- buffer = &tx_queue->buffer[tx_queue->read_count & EFX_TXQ_MASK];
+ buffer = &tx_queue->buffer[tx_queue->read_count & tx_queue->ptr_mask];
efx_dequeue_buffer(tx_queue, buffer);
buffer->continuation = true;
buffer->len = 0;
@@ -488,7 +498,8 @@ void efx_release_tx_buffers(struct efx_tx_queue *tx_queue)
void efx_fini_tx_queue(struct efx_tx_queue *tx_queue)
{
- EFX_LOG(tx_queue->efx, "shutting down TX queue %d\n", tx_queue->queue);
+ netif_dbg(tx_queue->efx, drv, tx_queue->efx->net_dev,
+ "shutting down TX queue %d\n", tx_queue->queue);
/* Flush TX queue, remove descriptor ring */
efx_nic_fini_tx(tx_queue);
@@ -507,7 +518,8 @@ void efx_fini_tx_queue(struct efx_tx_queue *tx_queue)
void efx_remove_tx_queue(struct efx_tx_queue *tx_queue)
{
- EFX_LOG(tx_queue->efx, "destroying TX queue %d\n", tx_queue->queue);
+ netif_dbg(tx_queue->efx, drv, tx_queue->efx->net_dev,
+ "destroying TX queue %d\n", tx_queue->queue);
efx_nic_remove_tx(tx_queue);
kfree(tx_queue->buffer);
@@ -639,8 +651,8 @@ static int efx_tsoh_block_alloc(struct efx_tx_queue *tx_queue)
base_kva = pci_alloc_consistent(pci_dev, PAGE_SIZE, &dma_addr);
if (base_kva == NULL) {
- EFX_ERR(tx_queue->efx, "Unable to allocate page for TSO"
- " headers\n");
+ netif_err(tx_queue->efx, tx_err, tx_queue->efx->net_dev,
+ "Unable to allocate page for TSO headers\n");
return -ENOMEM;
}
@@ -735,7 +747,7 @@ static int efx_tx_queue_insert(struct efx_tx_queue *tx_queue,
fill_level = tx_queue->insert_count - tx_queue->old_read_count;
/* -1 as there is no way to represent all descriptors used */
- q_space = EFX_TXQ_MASK - 1 - fill_level;
+ q_space = efx->txq_entries - 1 - fill_level;
while (1) {
if (unlikely(q_space-- <= 0)) {
@@ -751,7 +763,7 @@ static int efx_tx_queue_insert(struct efx_tx_queue *tx_queue,
*(volatile unsigned *)&tx_queue->read_count;
fill_level = (tx_queue->insert_count
- tx_queue->old_read_count);
- q_space = EFX_TXQ_MASK - 1 - fill_level;
+ q_space = efx->txq_entries - 1 - fill_level;
if (unlikely(q_space-- <= 0)) {
*final_buffer = NULL;
return 1;
@@ -760,13 +772,13 @@ static int efx_tx_queue_insert(struct efx_tx_queue *tx_queue,
--tx_queue->stopped;
}
- insert_ptr = tx_queue->insert_count & EFX_TXQ_MASK;
+ insert_ptr = tx_queue->insert_count & tx_queue->ptr_mask;
buffer = &tx_queue->buffer[insert_ptr];
++tx_queue->insert_count;
EFX_BUG_ON_PARANOID(tx_queue->insert_count -
- tx_queue->read_count >
- EFX_TXQ_MASK);
+ tx_queue->read_count >=
+ efx->txq_entries);
efx_tsoh_free(tx_queue, buffer);
EFX_BUG_ON_PARANOID(buffer->len);
@@ -807,7 +819,7 @@ static void efx_tso_put_header(struct efx_tx_queue *tx_queue,
{
struct efx_tx_buffer *buffer;
- buffer = &tx_queue->buffer[tx_queue->insert_count & EFX_TXQ_MASK];
+ buffer = &tx_queue->buffer[tx_queue->insert_count & tx_queue->ptr_mask];
efx_tsoh_free(tx_queue, buffer);
EFX_BUG_ON_PARANOID(buffer->len);
EFX_BUG_ON_PARANOID(buffer->unmap_len);
@@ -832,7 +844,7 @@ static void efx_enqueue_unwind(struct efx_tx_queue *tx_queue)
while (tx_queue->insert_count != tx_queue->write_count) {
--tx_queue->insert_count;
buffer = &tx_queue->buffer[tx_queue->insert_count &
- EFX_TXQ_MASK];
+ tx_queue->ptr_mask];
efx_tsoh_free(tx_queue, buffer);
EFX_BUG_ON_PARANOID(buffer->skb);
if (buffer->unmap_len) {
@@ -1124,7 +1136,8 @@ static int efx_enqueue_skb_tso(struct efx_tx_queue *tx_queue,
return NETDEV_TX_OK;
mem_err:
- EFX_ERR(efx, "Out of memory for TSO headers, or PCI mapping error\n");
+ netif_err(efx, tx_err, efx->net_dev,
+ "Out of memory for TSO headers, or PCI mapping error\n");
dev_kfree_skb_any(skb);
goto unwind;
@@ -1161,7 +1174,7 @@ static void efx_fini_tso(struct efx_tx_queue *tx_queue)
unsigned i;
if (tx_queue->buffer) {
- for (i = 0; i <= EFX_TXQ_MASK; ++i)
+ for (i = 0; i <= tx_queue->ptr_mask; ++i)
efx_tsoh_free(tx_queue, &tx_queue->buffer[i]);
}
diff --git a/drivers/net/sfc/txc43128_phy.c b/drivers/net/sfc/txc43128_phy.c
new file mode 100644
index 000000000000..351794a79215
--- /dev/null
+++ b/drivers/net/sfc/txc43128_phy.c
@@ -0,0 +1,560 @@
+/****************************************************************************
+ * Driver for Solarflare Solarstorm network controllers and boards
+ * Copyright 2006-2010 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.
+ */
+
+/*
+ * Driver for Transwitch/Mysticom CX4 retimer
+ * see www.transwitch.com, part is TXC-43128
+ */
+
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include "efx.h"
+#include "mdio_10g.h"
+#include "phy.h"
+#include "nic.h"
+
+/* We expect these MMDs to be in the package */
+#define TXC_REQUIRED_DEVS (MDIO_DEVS_PCS | \
+ MDIO_DEVS_PMAPMD | \
+ MDIO_DEVS_PHYXS)
+
+#define TXC_LOOPBACKS ((1 << LOOPBACK_PCS) | \
+ (1 << LOOPBACK_PMAPMD) | \
+ (1 << LOOPBACK_PHYXS_WS))
+
+/**************************************************************************
+ *
+ * Compile-time config
+ *
+ **************************************************************************
+ */
+#define TXCNAME "TXC43128"
+/* Total length of time we'll wait for the PHY to come out of reset (ms) */
+#define TXC_MAX_RESET_TIME 500
+/* Interval between checks (ms) */
+#define TXC_RESET_WAIT 10
+/* How long to run BIST (us) */
+#define TXC_BIST_DURATION 50
+
+/**************************************************************************
+ *
+ * Register definitions
+ *
+ **************************************************************************
+ */
+
+/* Command register */
+#define TXC_GLRGS_GLCMD 0xc004
+/* Useful bits in command register */
+/* Lane power-down */
+#define TXC_GLCMD_L01PD_LBN 5
+#define TXC_GLCMD_L23PD_LBN 6
+/* Limited SW reset: preserves configuration but
+ * initiates a logic reset. Self-clearing */
+#define TXC_GLCMD_LMTSWRST_LBN 14
+
+/* Signal Quality Control */
+#define TXC_GLRGS_GSGQLCTL 0xc01a
+/* Enable bit */
+#define TXC_GSGQLCT_SGQLEN_LBN 15
+/* Lane selection */
+#define TXC_GSGQLCT_LNSL_LBN 13
+#define TXC_GSGQLCT_LNSL_WIDTH 2
+
+/* Analog TX control */
+#define TXC_ALRGS_ATXCTL 0xc040
+/* Lane power-down */
+#define TXC_ATXCTL_TXPD3_LBN 15
+#define TXC_ATXCTL_TXPD2_LBN 14
+#define TXC_ATXCTL_TXPD1_LBN 13
+#define TXC_ATXCTL_TXPD0_LBN 12
+
+/* Amplitude on lanes 0, 1 */
+#define TXC_ALRGS_ATXAMP0 0xc041
+/* Amplitude on lanes 2, 3 */
+#define TXC_ALRGS_ATXAMP1 0xc042
+/* Bit position of value for lane 0 (or 2) */
+#define TXC_ATXAMP_LANE02_LBN 3
+/* Bit position of value for lane 1 (or 3) */
+#define TXC_ATXAMP_LANE13_LBN 11
+
+#define TXC_ATXAMP_1280_mV 0
+#define TXC_ATXAMP_1200_mV 8
+#define TXC_ATXAMP_1120_mV 12
+#define TXC_ATXAMP_1060_mV 14
+#define TXC_ATXAMP_0820_mV 25
+#define TXC_ATXAMP_0720_mV 26
+#define TXC_ATXAMP_0580_mV 27
+#define TXC_ATXAMP_0440_mV 28
+
+#define TXC_ATXAMP_0820_BOTH \
+ ((TXC_ATXAMP_0820_mV << TXC_ATXAMP_LANE02_LBN) \
+ | (TXC_ATXAMP_0820_mV << TXC_ATXAMP_LANE13_LBN))
+
+#define TXC_ATXAMP_DEFAULT 0x6060 /* From databook */
+
+/* Preemphasis on lanes 0, 1 */
+#define TXC_ALRGS_ATXPRE0 0xc043
+/* Preemphasis on lanes 2, 3 */
+#define TXC_ALRGS_ATXPRE1 0xc044
+
+#define TXC_ATXPRE_NONE 0
+#define TXC_ATXPRE_DEFAULT 0x1010 /* From databook */
+
+#define TXC_ALRGS_ARXCTL 0xc045
+/* Lane power-down */
+#define TXC_ARXCTL_RXPD3_LBN 15
+#define TXC_ARXCTL_RXPD2_LBN 14
+#define TXC_ARXCTL_RXPD1_LBN 13
+#define TXC_ARXCTL_RXPD0_LBN 12
+
+/* Main control */
+#define TXC_MRGS_CTL 0xc340
+/* Bits in main control */
+#define TXC_MCTL_RESET_LBN 15 /* Self clear */
+#define TXC_MCTL_TXLED_LBN 14 /* 1 to show align status */
+#define TXC_MCTL_RXLED_LBN 13 /* 1 to show align status */
+
+/* GPIO output */
+#define TXC_GPIO_OUTPUT 0xc346
+#define TXC_GPIO_DIR 0xc348
+
+/* Vendor-specific BIST registers */
+#define TXC_BIST_CTL 0xc280
+#define TXC_BIST_TXFRMCNT 0xc281
+#define TXC_BIST_RX0FRMCNT 0xc282
+#define TXC_BIST_RX1FRMCNT 0xc283
+#define TXC_BIST_RX2FRMCNT 0xc284
+#define TXC_BIST_RX3FRMCNT 0xc285
+#define TXC_BIST_RX0ERRCNT 0xc286
+#define TXC_BIST_RX1ERRCNT 0xc287
+#define TXC_BIST_RX2ERRCNT 0xc288
+#define TXC_BIST_RX3ERRCNT 0xc289
+
+/* BIST type (controls bit patter in test) */
+#define TXC_BIST_CTRL_TYPE_LBN 10
+#define TXC_BIST_CTRL_TYPE_TSD 0 /* TranSwitch Deterministic */
+#define TXC_BIST_CTRL_TYPE_CRP 1 /* CRPAT standard */
+#define TXC_BIST_CTRL_TYPE_CJP 2 /* CJPAT standard */
+#define TXC_BIST_CTRL_TYPE_TSR 3 /* TranSwitch pseudo-random */
+/* Set this to 1 for 10 bit and 0 for 8 bit */
+#define TXC_BIST_CTRL_B10EN_LBN 12
+/* Enable BIST (write 0 to disable) */
+#define TXC_BIST_CTRL_ENAB_LBN 13
+/* Stop BIST (self-clears when stop complete) */
+#define TXC_BIST_CTRL_STOP_LBN 14
+/* Start BIST (cleared by writing 1 to STOP) */
+#define TXC_BIST_CTRL_STRT_LBN 15
+
+/* Mt. Diablo test configuration */
+#define TXC_MTDIABLO_CTRL 0xc34f
+#define TXC_MTDIABLO_CTRL_PMA_LOOP_LBN 10
+
+struct txc43128_data {
+ unsigned long bug10934_timer;
+ enum efx_phy_mode phy_mode;
+ enum efx_loopback_mode loopback_mode;
+};
+
+/* The PHY sometimes needs a reset to bring the link back up. So long as
+ * it reports link down, we reset it every 5 seconds.
+ */
+#define BUG10934_RESET_INTERVAL (5 * HZ)
+
+/* Perform a reset that doesn't clear configuration changes */
+static void txc_reset_logic(struct efx_nic *efx);
+
+/* Set the output value of a gpio */
+void falcon_txc_set_gpio_val(struct efx_nic *efx, int pin, int on)
+{
+ efx_mdio_set_flag(efx, MDIO_MMD_PHYXS, TXC_GPIO_OUTPUT, 1 << pin, on);
+}
+
+/* Set up the GPIO direction register */
+void falcon_txc_set_gpio_dir(struct efx_nic *efx, int pin, int dir)
+{
+ efx_mdio_set_flag(efx, MDIO_MMD_PHYXS, TXC_GPIO_DIR, 1 << pin, dir);
+}
+
+/* Reset the PMA/PMD MMD. The documentation is explicit that this does a
+ * global reset (it's less clear what reset of other MMDs does).*/
+static int txc_reset_phy(struct efx_nic *efx)
+{
+ int rc = efx_mdio_reset_mmd(efx, MDIO_MMD_PMAPMD,
+ TXC_MAX_RESET_TIME / TXC_RESET_WAIT,
+ TXC_RESET_WAIT);
+ if (rc < 0)
+ goto fail;
+
+ /* Check that all the MMDs we expect are present and responding. */
+ rc = efx_mdio_check_mmds(efx, TXC_REQUIRED_DEVS, 0);
+ if (rc < 0)
+ goto fail;
+
+ return 0;
+
+fail:
+ netif_err(efx, hw, efx->net_dev, TXCNAME ": reset timed out!\n");
+ return rc;
+}
+
+/* Run a single BIST on one MMD */
+static int txc_bist_one(struct efx_nic *efx, int mmd, int test)
+{
+ int ctrl, bctl;
+ int lane;
+ int rc = 0;
+
+ /* Set PMA to test into loopback using Mt Diablo reg as per app note */
+ ctrl = efx_mdio_read(efx, MDIO_MMD_PCS, TXC_MTDIABLO_CTRL);
+ ctrl |= (1 << TXC_MTDIABLO_CTRL_PMA_LOOP_LBN);
+ efx_mdio_write(efx, MDIO_MMD_PCS, TXC_MTDIABLO_CTRL, ctrl);
+
+ /* The BIST app. note lists these as 3 distinct steps. */
+ /* Set the BIST type */
+ bctl = (test << TXC_BIST_CTRL_TYPE_LBN);
+ efx_mdio_write(efx, mmd, TXC_BIST_CTL, bctl);
+
+ /* Set the BSTEN bit in the BIST Control register to enable */
+ bctl |= (1 << TXC_BIST_CTRL_ENAB_LBN);
+ efx_mdio_write(efx, mmd, TXC_BIST_CTL, bctl);
+
+ /* Set the BSTRT bit in the BIST Control register */
+ efx_mdio_write(efx, mmd, TXC_BIST_CTL,
+ bctl | (1 << TXC_BIST_CTRL_STRT_LBN));
+
+ /* Wait. */
+ udelay(TXC_BIST_DURATION);
+
+ /* Set the BSTOP bit in the BIST Control register */
+ bctl |= (1 << TXC_BIST_CTRL_STOP_LBN);
+ efx_mdio_write(efx, mmd, TXC_BIST_CTL, bctl);
+
+ /* The STOP bit should go off when things have stopped */
+ while (bctl & (1 << TXC_BIST_CTRL_STOP_LBN))
+ bctl = efx_mdio_read(efx, mmd, TXC_BIST_CTL);
+
+ /* Check all the error counts are 0 and all the frame counts are
+ non-zero */
+ for (lane = 0; lane < 4; lane++) {
+ int count = efx_mdio_read(efx, mmd, TXC_BIST_RX0ERRCNT + lane);
+ if (count != 0) {
+ netif_err(efx, hw, efx->net_dev, TXCNAME": BIST error. "
+ "Lane %d had %d errs\n", lane, count);
+ rc = -EIO;
+ }
+ count = efx_mdio_read(efx, mmd, TXC_BIST_RX0FRMCNT + lane);
+ if (count == 0) {
+ netif_err(efx, hw, efx->net_dev, TXCNAME": BIST error. "
+ "Lane %d got 0 frames\n", lane);
+ rc = -EIO;
+ }
+ }
+
+ if (rc == 0)
+ netif_info(efx, hw, efx->net_dev, TXCNAME": BIST pass\n");
+
+ /* Disable BIST */
+ efx_mdio_write(efx, mmd, TXC_BIST_CTL, 0);
+
+ /* Turn off loopback */
+ ctrl &= ~(1 << TXC_MTDIABLO_CTRL_PMA_LOOP_LBN);
+ efx_mdio_write(efx, MDIO_MMD_PCS, TXC_MTDIABLO_CTRL, ctrl);
+
+ return rc;
+}
+
+static int txc_bist(struct efx_nic *efx)
+{
+ return txc_bist_one(efx, MDIO_MMD_PCS, TXC_BIST_CTRL_TYPE_TSD);
+}
+
+/* Push the non-configurable defaults into the PHY. This must be
+ * done after every full reset */
+static void txc_apply_defaults(struct efx_nic *efx)
+{
+ int mctrl;
+
+ /* Turn amplitude down and preemphasis off on the host side
+ * (PHY<->MAC) as this is believed less likely to upset Falcon
+ * and no adverse effects have been noted. It probably also
+ * saves a picowatt or two */
+
+ /* Turn off preemphasis */
+ efx_mdio_write(efx, MDIO_MMD_PHYXS, TXC_ALRGS_ATXPRE0, TXC_ATXPRE_NONE);
+ efx_mdio_write(efx, MDIO_MMD_PHYXS, TXC_ALRGS_ATXPRE1, TXC_ATXPRE_NONE);
+
+ /* Turn down the amplitude */
+ efx_mdio_write(efx, MDIO_MMD_PHYXS,
+ TXC_ALRGS_ATXAMP0, TXC_ATXAMP_0820_BOTH);
+ efx_mdio_write(efx, MDIO_MMD_PHYXS,
+ TXC_ALRGS_ATXAMP1, TXC_ATXAMP_0820_BOTH);
+
+ /* Set the line side amplitude and preemphasis to the databook
+ * defaults as an erratum causes them to be 0 on at least some
+ * PHY rev.s */
+ efx_mdio_write(efx, MDIO_MMD_PMAPMD,
+ TXC_ALRGS_ATXPRE0, TXC_ATXPRE_DEFAULT);
+ efx_mdio_write(efx, MDIO_MMD_PMAPMD,
+ TXC_ALRGS_ATXPRE1, TXC_ATXPRE_DEFAULT);
+ efx_mdio_write(efx, MDIO_MMD_PMAPMD,
+ TXC_ALRGS_ATXAMP0, TXC_ATXAMP_DEFAULT);
+ efx_mdio_write(efx, MDIO_MMD_PMAPMD,
+ TXC_ALRGS_ATXAMP1, TXC_ATXAMP_DEFAULT);
+
+ /* Set up the LEDs */
+ mctrl = efx_mdio_read(efx, MDIO_MMD_PHYXS, TXC_MRGS_CTL);
+
+ /* Set the Green and Red LEDs to their default modes */
+ mctrl &= ~((1 << TXC_MCTL_TXLED_LBN) | (1 << TXC_MCTL_RXLED_LBN));
+ efx_mdio_write(efx, MDIO_MMD_PHYXS, TXC_MRGS_CTL, mctrl);
+
+ /* Databook recommends doing this after configuration changes */
+ txc_reset_logic(efx);
+
+ falcon_board(efx)->type->init_phy(efx);
+}
+
+static int txc43128_phy_probe(struct efx_nic *efx)
+{
+ struct txc43128_data *phy_data;
+
+ /* Allocate phy private storage */
+ phy_data = kzalloc(sizeof(*phy_data), GFP_KERNEL);
+ if (!phy_data)
+ return -ENOMEM;
+ efx->phy_data = phy_data;
+ phy_data->phy_mode = efx->phy_mode;
+
+ efx->mdio.mmds = TXC_REQUIRED_DEVS;
+ efx->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22;
+
+ efx->loopback_modes = TXC_LOOPBACKS | FALCON_XMAC_LOOPBACKS;
+
+ return 0;
+}
+
+/* Initialisation entry point for this PHY driver */
+static int txc43128_phy_init(struct efx_nic *efx)
+{
+ int rc;
+
+ rc = txc_reset_phy(efx);
+ if (rc < 0)
+ return rc;
+
+ rc = txc_bist(efx);
+ if (rc < 0)
+ return rc;
+
+ txc_apply_defaults(efx);
+
+ return 0;
+}
+
+/* Set the lane power down state in the global registers */
+static void txc_glrgs_lane_power(struct efx_nic *efx, int mmd)
+{
+ int pd = (1 << TXC_GLCMD_L01PD_LBN) | (1 << TXC_GLCMD_L23PD_LBN);
+ int ctl = efx_mdio_read(efx, mmd, TXC_GLRGS_GLCMD);
+
+ if (!(efx->phy_mode & PHY_MODE_LOW_POWER))
+ ctl &= ~pd;
+ else
+ ctl |= pd;
+
+ efx_mdio_write(efx, mmd, TXC_GLRGS_GLCMD, ctl);
+}
+
+/* Set the lane power down state in the analog control registers */
+static void txc_analog_lane_power(struct efx_nic *efx, int mmd)
+{
+ int txpd = (1 << TXC_ATXCTL_TXPD3_LBN) | (1 << TXC_ATXCTL_TXPD2_LBN)
+ | (1 << TXC_ATXCTL_TXPD1_LBN) | (1 << TXC_ATXCTL_TXPD0_LBN);
+ int rxpd = (1 << TXC_ARXCTL_RXPD3_LBN) | (1 << TXC_ARXCTL_RXPD2_LBN)
+ | (1 << TXC_ARXCTL_RXPD1_LBN) | (1 << TXC_ARXCTL_RXPD0_LBN);
+ int txctl = efx_mdio_read(efx, mmd, TXC_ALRGS_ATXCTL);
+ int rxctl = efx_mdio_read(efx, mmd, TXC_ALRGS_ARXCTL);
+
+ if (!(efx->phy_mode & PHY_MODE_LOW_POWER)) {
+ txctl &= ~txpd;
+ rxctl &= ~rxpd;
+ } else {
+ txctl |= txpd;
+ rxctl |= rxpd;
+ }
+
+ efx_mdio_write(efx, mmd, TXC_ALRGS_ATXCTL, txctl);
+ efx_mdio_write(efx, mmd, TXC_ALRGS_ARXCTL, rxctl);
+}
+
+static void txc_set_power(struct efx_nic *efx)
+{
+ /* According to the data book, all the MMDs can do low power */
+ efx_mdio_set_mmds_lpower(efx,
+ !!(efx->phy_mode & PHY_MODE_LOW_POWER),
+ TXC_REQUIRED_DEVS);
+
+ /* Global register bank is in PCS, PHY XS. These control the host
+ * side and line side settings respectively. */
+ txc_glrgs_lane_power(efx, MDIO_MMD_PCS);
+ txc_glrgs_lane_power(efx, MDIO_MMD_PHYXS);
+
+ /* Analog register bank in PMA/PMD, PHY XS */
+ txc_analog_lane_power(efx, MDIO_MMD_PMAPMD);
+ txc_analog_lane_power(efx, MDIO_MMD_PHYXS);
+}
+
+static void txc_reset_logic_mmd(struct efx_nic *efx, int mmd)
+{
+ int val = efx_mdio_read(efx, mmd, TXC_GLRGS_GLCMD);
+ int tries = 50;
+
+ val |= (1 << TXC_GLCMD_LMTSWRST_LBN);
+ efx_mdio_write(efx, mmd, TXC_GLRGS_GLCMD, val);
+ while (tries--) {
+ val = efx_mdio_read(efx, mmd, TXC_GLRGS_GLCMD);
+ if (!(val & (1 << TXC_GLCMD_LMTSWRST_LBN)))
+ break;
+ udelay(1);
+ }
+ if (!tries)
+ netif_info(efx, hw, efx->net_dev,
+ TXCNAME " Logic reset timed out!\n");
+}
+
+/* Perform a logic reset. This preserves the configuration registers
+ * and is needed for some configuration changes to take effect */
+static void txc_reset_logic(struct efx_nic *efx)
+{
+ /* The data sheet claims we can do the logic reset on either the
+ * PCS or the PHYXS and the result is a reset of both host- and
+ * line-side logic. */
+ txc_reset_logic_mmd(efx, MDIO_MMD_PCS);
+}
+
+static bool txc43128_phy_read_link(struct efx_nic *efx)
+{
+ return efx_mdio_links_ok(efx, TXC_REQUIRED_DEVS);
+}
+
+static int txc43128_phy_reconfigure(struct efx_nic *efx)
+{
+ struct txc43128_data *phy_data = efx->phy_data;
+ enum efx_phy_mode mode_change = efx->phy_mode ^ phy_data->phy_mode;
+ bool loop_change = LOOPBACK_CHANGED(phy_data, efx, TXC_LOOPBACKS);
+
+ if (efx->phy_mode & mode_change & PHY_MODE_TX_DISABLED) {
+ txc_reset_phy(efx);
+ txc_apply_defaults(efx);
+ falcon_reset_xaui(efx);
+ mode_change &= ~PHY_MODE_TX_DISABLED;
+ }
+
+ efx_mdio_transmit_disable(efx);
+ efx_mdio_phy_reconfigure(efx);
+ if (mode_change & PHY_MODE_LOW_POWER)
+ txc_set_power(efx);
+
+ /* The data sheet claims this is required after every reconfiguration
+ * (note at end of 7.1), but we mustn't do it when nothing changes as
+ * it glitches the link, and reconfigure gets called on link change,
+ * so we get an IRQ storm on link up. */
+ if (loop_change || mode_change)
+ txc_reset_logic(efx);
+
+ phy_data->phy_mode = efx->phy_mode;
+ phy_data->loopback_mode = efx->loopback_mode;
+
+ return 0;
+}
+
+static void txc43128_phy_fini(struct efx_nic *efx)
+{
+ /* Disable link events */
+ efx_mdio_write(efx, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_CTRL, 0);
+}
+
+static void txc43128_phy_remove(struct efx_nic *efx)
+{
+ kfree(efx->phy_data);
+ efx->phy_data = NULL;
+}
+
+/* Periodic callback: this exists mainly to poll link status as we
+ * don't use LASI interrupts */
+static bool txc43128_phy_poll(struct efx_nic *efx)
+{
+ struct txc43128_data *data = efx->phy_data;
+ bool was_up = efx->link_state.up;
+
+ efx->link_state.up = txc43128_phy_read_link(efx);
+ efx->link_state.speed = 10000;
+ efx->link_state.fd = true;
+ efx->link_state.fc = efx->wanted_fc;
+
+ if (efx->link_state.up || (efx->loopback_mode != LOOPBACK_NONE)) {
+ data->bug10934_timer = jiffies;
+ } else {
+ if (time_after_eq(jiffies, (data->bug10934_timer +
+ BUG10934_RESET_INTERVAL))) {
+ data->bug10934_timer = jiffies;
+ txc_reset_logic(efx);
+ }
+ }
+
+ return efx->link_state.up != was_up;
+}
+
+static const char *txc43128_test_names[] = {
+ "bist"
+};
+
+static const char *txc43128_test_name(struct efx_nic *efx, unsigned int index)
+{
+ if (index < ARRAY_SIZE(txc43128_test_names))
+ return txc43128_test_names[index];
+ return NULL;
+}
+
+static int txc43128_run_tests(struct efx_nic *efx, int *results, unsigned flags)
+{
+ int rc;
+
+ if (!(flags & ETH_TEST_FL_OFFLINE))
+ return 0;
+
+ rc = txc_reset_phy(efx);
+ if (rc < 0)
+ return rc;
+
+ rc = txc_bist(efx);
+ txc_apply_defaults(efx);
+ results[0] = rc ? -1 : 1;
+ return rc;
+}
+
+static void txc43128_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
+{
+ mdio45_ethtool_gset(&efx->mdio, ecmd);
+}
+
+struct efx_phy_operations falcon_txc_phy_ops = {
+ .probe = txc43128_phy_probe,
+ .init = txc43128_phy_init,
+ .reconfigure = txc43128_phy_reconfigure,
+ .poll = txc43128_phy_poll,
+ .fini = txc43128_phy_fini,
+ .remove = txc43128_phy_remove,
+ .get_settings = txc43128_get_settings,
+ .set_settings = efx_mdio_set_settings,
+ .test_alive = efx_mdio_test_alive,
+ .run_tests = txc43128_run_tests,
+ .test_name = txc43128_test_name,
+};
diff --git a/drivers/net/sfc/workarounds.h b/drivers/net/sfc/workarounds.h
index 518f7fc91473..e0d63083c3a8 100644
--- a/drivers/net/sfc/workarounds.h
+++ b/drivers/net/sfc/workarounds.h
@@ -19,9 +19,7 @@
#define EFX_WORKAROUND_FALCON_A(efx) (efx_nic_rev(efx) <= EFX_REV_FALCON_A1)
#define EFX_WORKAROUND_FALCON_AB(efx) (efx_nic_rev(efx) <= EFX_REV_FALCON_B0)
#define EFX_WORKAROUND_SIENA(efx) (efx_nic_rev(efx) == EFX_REV_SIENA_A0)
-#define EFX_WORKAROUND_10G(efx) EFX_IS10G(efx)
-#define EFX_WORKAROUND_SFT9001(efx) ((efx)->phy_type == PHY_TYPE_SFT9001A || \
- (efx)->phy_type == PHY_TYPE_SFT9001B)
+#define EFX_WORKAROUND_10G(efx) 1
/* XAUI resets if link not detected */
#define EFX_WORKAROUND_5147 EFX_WORKAROUND_ALWAYS
@@ -54,13 +52,8 @@
/* Increase filter depth to avoid RX_RESET */
#define EFX_WORKAROUND_7244 EFX_WORKAROUND_FALCON_A
/* Flushes may never complete */
-#define EFX_WORKAROUND_7803 EFX_WORKAROUND_FALCON_A
+#define EFX_WORKAROUND_7803 EFX_WORKAROUND_FALCON_AB
/* Leak overlength packets rather than free */
#define EFX_WORKAROUND_8071 EFX_WORKAROUND_FALCON_A
-/* Need to send XNP pages for 100BaseT */
-#define EFX_WORKAROUND_13204 EFX_WORKAROUND_SFT9001
-/* Don't restart AN in near-side loopback */
-#define EFX_WORKAROUND_15195 EFX_WORKAROUND_SFT9001
-
#endif /* EFX_WORKAROUNDS_H */