ethernet: unify return value of .ndo_set_mac_address if address is invalid
[deliverable/linux.git] / drivers / net / ethernet / sfc / efx.c
index e43702f33b62932ace48dd4c613f34c497c20944..1908ba7ca7e6a0c5c3765e1d8ffeab3ec9be02f4 100644 (file)
 
 /* Loopback mode names (see LOOPBACK_MODE()) */
 const unsigned int efx_loopback_mode_max = LOOPBACK_MAX;
-const char *efx_loopback_mode_names[] = {
+const char *const efx_loopback_mode_names[] = {
        [LOOPBACK_NONE]         = "NONE",
        [LOOPBACK_DATA]         = "DATAPATH",
        [LOOPBACK_GMAC]         = "GMAC",
        [LOOPBACK_XGMII]        = "XGMII",
        [LOOPBACK_XGXS]         = "XGXS",
-       [LOOPBACK_XAUI]         = "XAUI",
-       [LOOPBACK_GMII]         = "GMII",
-       [LOOPBACK_SGMII]        = "SGMII",
+       [LOOPBACK_XAUI]         = "XAUI",
+       [LOOPBACK_GMII]         = "GMII",
+       [LOOPBACK_SGMII]        = "SGMII",
        [LOOPBACK_XGBR]         = "XGBR",
        [LOOPBACK_XFI]          = "XFI",
        [LOOPBACK_XAUI_FAR]     = "XAUI_FAR",
@@ -55,21 +55,21 @@ const char *efx_loopback_mode_names[] = {
        [LOOPBACK_XFI_FAR]      = "XFI_FAR",
        [LOOPBACK_GPHY]         = "GPHY",
        [LOOPBACK_PHYXS]        = "PHYXS",
-       [LOOPBACK_PCS]          = "PCS",
-       [LOOPBACK_PMAPMD]       = "PMA/PMD",
+       [LOOPBACK_PCS]          = "PCS",
+       [LOOPBACK_PMAPMD]       = "PMA/PMD",
        [LOOPBACK_XPORT]        = "XPORT",
        [LOOPBACK_XGMII_WS]     = "XGMII_WS",
-       [LOOPBACK_XAUI_WS]      = "XAUI_WS",
+       [LOOPBACK_XAUI_WS]      = "XAUI_WS",
        [LOOPBACK_XAUI_WS_FAR]  = "XAUI_WS_FAR",
        [LOOPBACK_XAUI_WS_NEAR] = "XAUI_WS_NEAR",
-       [LOOPBACK_GMII_WS]      = "GMII_WS",
+       [LOOPBACK_GMII_WS]      = "GMII_WS",
        [LOOPBACK_XFI_WS]       = "XFI_WS",
        [LOOPBACK_XFI_WS_FAR]   = "XFI_WS_FAR",
-       [LOOPBACK_PHYXS_WS]     = "PHYXS_WS",
+       [LOOPBACK_PHYXS_WS]     = "PHYXS_WS",
 };
 
 const unsigned int efx_reset_type_max = RESET_TYPE_MAX;
-const char *efx_reset_type_names[] = {
+const char *const efx_reset_type_names[] = {
        [RESET_TYPE_INVISIBLE]     = "INVISIBLE",
        [RESET_TYPE_ALL]           = "ALL",
        [RESET_TYPE_WORLD]         = "WORLD",
@@ -122,15 +122,6 @@ static int napi_weight = 64;
  */
 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,
- * such devices will be initialised with a random locally-generated
- * MAC address.  This allows for loading the sfc_mtd driver to
- * reprogram the flash, even if the flash contents (including the MAC
- * address) have previously been erased.
- */
-static unsigned int allow_bad_hwaddr;
-
 /* Initial interrupt moderation settings.  They can be modified after
  * module load with ethtool.
  *
@@ -162,7 +153,7 @@ static unsigned int interrupt_mode;
  * interrupt handling.
  *
  * Cards without MSI-X will only target one CPU via legacy or MSI interrupt.
- * The default (0) means to assign an interrupt to each package (level II cache)
+ * The default (0) means to assign an interrupt to each core.
  */
 static unsigned int rss_cpus;
 module_param(rss_cpus, uint, 0444);
@@ -195,9 +186,13 @@ MODULE_PARM_DESC(debug, "Bitmapped debugging message enable value");
  *
  *************************************************************************/
 
+static void efx_start_interrupts(struct efx_nic *efx, bool may_keep_eventq);
+static void efx_stop_interrupts(struct efx_nic *efx, bool may_keep_eventq);
+static void efx_remove_channel(struct efx_channel *channel);
 static void efx_remove_channels(struct efx_nic *efx);
+static const struct efx_channel_type efx_default_channel_type;
 static void efx_remove_port(struct efx_nic *efx);
-static void efx_init_napi(struct efx_nic *efx);
+static void efx_init_napi_channel(struct efx_channel *channel);
 static void efx_fini_napi(struct efx_nic *efx);
 static void efx_fini_napi_channel(struct efx_channel *channel);
 static void efx_fini_struct(struct efx_nic *efx);
@@ -226,27 +221,27 @@ static void efx_stop_all(struct efx_nic *efx);
  */
 static int efx_process_channel(struct efx_channel *channel, int budget)
 {
-       struct efx_nic *efx = channel->efx;
        int spent;
 
-       if (unlikely(efx->reset_pending || !channel->enabled))
+       if (unlikely(!channel->enabled))
                return 0;
 
        spent = efx_nic_process_eventq(channel, budget);
-       if (spent == 0)
-               return 0;
-
-       /* Deliver last RX packet. */
-       if (channel->rx_pkt) {
-               __efx_rx_packet(channel, channel->rx_pkt,
-                               channel->rx_pkt_csummed);
-               channel->rx_pkt = NULL;
+       if (spent && efx_channel_has_rx_queue(channel)) {
+               struct efx_rx_queue *rx_queue =
+                       efx_channel_get_rx_queue(channel);
+
+               /* Deliver last RX packet. */
+               if (channel->rx_pkt) {
+                       __efx_rx_packet(channel, channel->rx_pkt);
+                       channel->rx_pkt = NULL;
+               }
+               if (rx_queue->enabled) {
+                       efx_rx_strategy(channel);
+                       efx_fast_push_rx_descriptors(rx_queue);
+               }
        }
 
-       efx_rx_strategy(channel);
-
-       efx_fast_push_rx_descriptors(efx_channel_get_rx_queue(channel));
-
        return spent;
 }
 
@@ -286,7 +281,7 @@ static int efx_poll(struct napi_struct *napi, int budget)
        spent = efx_process_channel(channel, budget);
 
        if (spent < budget) {
-               if (channel->channel < efx->n_rx_channels &&
+               if (efx_channel_has_rx_queue(channel) &&
                    efx->irq_rx_adaptive &&
                    unlikely(++channel->irq_count == 1000)) {
                        if (unlikely(channel->irq_mod_score <
@@ -373,7 +368,7 @@ static int efx_probe_eventq(struct efx_channel *channel)
        struct efx_nic *efx = channel->efx;
        unsigned long entries;
 
-       netif_dbg(channel->efx, probe, channel->efx->net_dev,
+       netif_dbg(efx, probe, 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,
@@ -396,6 +391,34 @@ static void efx_init_eventq(struct efx_channel *channel)
        efx_nic_init_eventq(channel);
 }
 
+/* Enable event queue processing and NAPI */
+static void efx_start_eventq(struct efx_channel *channel)
+{
+       netif_dbg(channel->efx, ifup, channel->efx->net_dev,
+                 "chan %d start event queue\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
+        * then.  Similarly, make sure it sees the enabled flag set.
+        */
+       channel->work_pending = false;
+       channel->enabled = true;
+       smp_wmb();
+
+       napi_enable(&channel->napi_str);
+       efx_nic_eventq_read_ack(channel);
+}
+
+/* Disable event queue processing and NAPI */
+static void efx_stop_eventq(struct efx_channel *channel)
+{
+       if (!channel->enabled)
+               return;
+
+       napi_disable(&channel->napi_str);
+       channel->enabled = false;
+}
+
 static void efx_fini_eventq(struct efx_channel *channel)
 {
        netif_dbg(channel->efx, drv, channel->efx->net_dev,
@@ -418,8 +441,7 @@ 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. */
+/* Allocate and initialise a channel structure. */
 static struct efx_channel *
 efx_alloc_channel(struct efx_nic *efx, int i, struct efx_channel *old_channel)
 {
@@ -428,45 +450,60 @@ efx_alloc_channel(struct efx_nic *efx, int i, struct efx_channel *old_channel)
        struct efx_tx_queue *tx_queue;
        int j;
 
-       if (old_channel) {
-               channel = kmalloc(sizeof(*channel), GFP_KERNEL);
-               if (!channel)
-                       return NULL;
+       channel = kzalloc(sizeof(*channel), GFP_KERNEL);
+       if (!channel)
+               return NULL;
 
-               *channel = *old_channel;
+       channel->efx = efx;
+       channel->channel = i;
+       channel->type = &efx_default_channel_type;
 
-               channel->napi_dev = NULL;
-               memset(&channel->eventq, 0, sizeof(channel->eventq));
+       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;
+       }
 
-               rx_queue = &channel->rx_queue;
-               rx_queue->buffer = NULL;
-               memset(&rx_queue->rxd, 0, sizeof(rx_queue->rxd));
+       rx_queue = &channel->rx_queue;
+       rx_queue->efx = efx;
+       setup_timer(&rx_queue->slow_fill, efx_rx_slow_fill,
+                   (unsigned long)rx_queue);
 
-               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;
+       return channel;
+}
+
+/* Allocate and initialise a channel structure, copying parameters
+ * (but not resources) from an old channel structure.
+ */
+static struct efx_channel *
+efx_copy_channel(const struct efx_channel *old_channel)
+{
+       struct efx_channel *channel;
+       struct efx_rx_queue *rx_queue;
+       struct efx_tx_queue *tx_queue;
+       int j;
+
+       channel = kmalloc(sizeof(*channel), GFP_KERNEL);
+       if (!channel)
+               return NULL;
 
-               channel->efx = efx;
-               channel->channel = i;
+       *channel = *old_channel;
 
-               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;
+       channel->napi_dev = NULL;
+       memset(&channel->eventq, 0, sizeof(channel->eventq));
+
+       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));
        }
 
        rx_queue = &channel->rx_queue;
-       rx_queue->efx = efx;
+       rx_queue->buffer = NULL;
+       memset(&rx_queue->rxd, 0, sizeof(rx_queue->rxd));
        setup_timer(&rx_queue->slow_fill, efx_rx_slow_fill,
                    (unsigned long)rx_queue);
 
@@ -482,57 +519,62 @@ static int efx_probe_channel(struct efx_channel *channel)
        netif_dbg(channel->efx, probe, channel->efx->net_dev,
                  "creating channel %d\n", channel->channel);
 
+       rc = channel->type->pre_probe(channel);
+       if (rc)
+               goto fail;
+
        rc = efx_probe_eventq(channel);
        if (rc)
-               goto fail1;
+               goto fail;
 
        efx_for_each_channel_tx_queue(tx_queue, channel) {
                rc = efx_probe_tx_queue(tx_queue);
                if (rc)
-                       goto fail2;
+                       goto fail;
        }
 
        efx_for_each_channel_rx_queue(rx_queue, channel) {
                rc = efx_probe_rx_queue(rx_queue);
                if (rc)
-                       goto fail3;
+                       goto fail;
        }
 
        channel->n_rx_frm_trunc = 0;
 
        return 0;
 
- fail3:
-       efx_for_each_channel_rx_queue(rx_queue, channel)
-               efx_remove_rx_queue(rx_queue);
- fail2:
-       efx_for_each_channel_tx_queue(tx_queue, channel)
-               efx_remove_tx_queue(tx_queue);
- fail1:
+fail:
+       efx_remove_channel(channel);
        return rc;
 }
 
+static void
+efx_get_channel_name(struct efx_channel *channel, char *buf, size_t len)
+{
+       struct efx_nic *efx = channel->efx;
+       const char *type;
+       int number;
+
+       number = channel->channel;
+       if (efx->tx_channel_offset == 0) {
+               type = "";
+       } else if (channel->channel < efx->tx_channel_offset) {
+               type = "-rx";
+       } else {
+               type = "-tx";
+               number -= efx->tx_channel_offset;
+       }
+       snprintf(buf, len, "%s%s-%d", efx->name, type, number);
+}
 
 static void efx_set_channel_names(struct efx_nic *efx)
 {
        struct efx_channel *channel;
-       const char *type = "";
-       int number;
 
-       efx_for_each_channel(channel, efx) {
-               number = channel->channel;
-               if (efx->n_channels > efx->n_rx_channels) {
-                       if (channel->channel < efx->n_rx_channels) {
-                               type = "-rx";
-                       } else {
-                               type = "-tx";
-                               number -= efx->n_rx_channels;
-                       }
-               }
-               snprintf(efx->channel_name[channel->channel],
-                        sizeof(efx->channel_name[0]),
-                        "%s%s-%d", efx->name, type, number);
-       }
+       efx_for_each_channel(channel, efx)
+               channel->type->get_name(channel,
+                                       efx->channel_name[channel->channel],
+                                       sizeof(efx->channel_name[0]));
 }
 
 static int efx_probe_channels(struct efx_nic *efx)
@@ -543,7 +585,12 @@ static int efx_probe_channels(struct efx_nic *efx)
        /* Restart special buffer allocation */
        efx->next_buffer_table = 0;
 
-       efx_for_each_channel(channel, efx) {
+       /* Probe channels in reverse, so that any 'extra' channels
+        * use the start of the buffer table. This allows the traffic
+        * channels to be resized without moving them or wasting the
+        * entries before them.
+        */
+       efx_for_each_channel_rev(channel, efx) {
                rc = efx_probe_channel(channel);
                if (rc) {
                        netif_err(efx, probe, efx->net_dev,
@@ -565,7 +612,7 @@ fail:
  * to propagate configuration changes (mtu, checksum offload), or
  * to clear hardware error conditions
  */
-static void efx_init_channels(struct efx_nic *efx)
+static void efx_start_datapath(struct efx_nic *efx)
 {
        struct efx_tx_queue *tx_queue;
        struct efx_rx_queue *rx_queue;
@@ -584,68 +631,26 @@ static void efx_init_channels(struct efx_nic *efx)
 
        /* Initialise the channels */
        efx_for_each_channel(channel, efx) {
-               netif_dbg(channel->efx, drv, channel->efx->net_dev,
-                         "init chan %d\n", channel->channel);
-
-               efx_init_eventq(channel);
-
                efx_for_each_channel_tx_queue(tx_queue, channel)
                        efx_init_tx_queue(tx_queue);
 
                /* The rx buffer allocation strategy is MTU dependent */
                efx_rx_strategy(channel);
 
-               efx_for_each_channel_rx_queue(rx_queue, channel)
+               efx_for_each_channel_rx_queue(rx_queue, channel) {
                        efx_init_rx_queue(rx_queue);
+                       efx_nic_generate_fill_event(rx_queue);
+               }
 
                WARN_ON(channel->rx_pkt != NULL);
                efx_rx_strategy(channel);
        }
-}
-
-/* This enables event queue processing and packet transmission.
- *
- * Note that this function is not allowed to fail, since that would
- * introduce too much complexity into the suspend/resume path.
- */
-static void efx_start_channel(struct efx_channel *channel)
-{
-       struct efx_rx_queue *rx_queue;
 
-       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
-        * then.  Similarly, make sure it sees the enabled flag set. */
-       channel->work_pending = false;
-       channel->enabled = true;
-       smp_wmb();
-
-       /* 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.
- * This function does not guarantee that all queue processing
- * (e.g. RX refill) is complete.
- */
-static void efx_stop_channel(struct efx_channel *channel)
-{
-       if (!channel->enabled)
-               return;
-
-       netif_dbg(channel->efx, ifdown, channel->efx->net_dev,
-                 "stop chan %d\n", channel->channel);
-
-       channel->enabled = false;
-       napi_disable(&channel->napi_str);
+       if (netif_device_present(efx->net_dev))
+               netif_tx_wake_all_queues(efx->net_dev);
 }
 
-static void efx_fini_channels(struct efx_nic *efx)
+static void efx_stop_datapath(struct efx_nic *efx)
 {
        struct efx_channel *channel;
        struct efx_tx_queue *tx_queue;
@@ -672,14 +677,21 @@ static void efx_fini_channels(struct efx_nic *efx)
        }
 
        efx_for_each_channel(channel, efx) {
-               netif_dbg(channel->efx, drv, channel->efx->net_dev,
-                         "shut down chan %d\n", channel->channel);
+               /* RX packet processing is pipelined, so wait for the
+                * NAPI handler to complete.  At least event queue 0
+                * might be kept active by non-data events, so don't
+                * use napi_synchronize() but actually disable NAPI
+                * temporarily.
+                */
+               if (efx_channel_has_rx_queue(channel)) {
+                       efx_stop_eventq(channel);
+                       efx_start_eventq(channel);
+               }
 
                efx_for_each_channel_rx_queue(rx_queue, channel)
                        efx_fini_rx_queue(rx_queue);
                efx_for_each_possible_channel_tx_queue(tx_queue, channel)
                        efx_fini_tx_queue(tx_queue);
-               efx_fini_eventq(channel);
        }
 }
 
@@ -711,16 +723,40 @@ 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;
+       unsigned i, next_buffer_table = 0;
+       int rc = 0;
+
+       /* Not all channels should be reallocated. We must avoid
+        * reallocating their buffer table entries.
+        */
+       efx_for_each_channel(channel, efx) {
+               struct efx_rx_queue *rx_queue;
+               struct efx_tx_queue *tx_queue;
+
+               if (channel->type->copy)
+                       continue;
+               next_buffer_table = max(next_buffer_table,
+                                       channel->eventq.index +
+                                       channel->eventq.entries);
+               efx_for_each_channel_rx_queue(rx_queue, channel)
+                       next_buffer_table = max(next_buffer_table,
+                                               rx_queue->rxd.index +
+                                               rx_queue->rxd.entries);
+               efx_for_each_channel_tx_queue(tx_queue, channel)
+                       next_buffer_table = max(next_buffer_table,
+                                               tx_queue->txd.index +
+                                               tx_queue->txd.entries);
+       }
 
        efx_stop_all(efx);
-       efx_fini_channels(efx);
+       efx_stop_interrupts(efx, true);
 
-       /* Clone channels */
+       /* Clone channels (where possible) */
        memset(other_channel, 0, sizeof(other_channel));
        for (i = 0; i < efx->n_channels; i++) {
-               channel = efx_alloc_channel(efx, i, efx->channel[i]);
+               channel = efx->channel[i];
+               if (channel->type->copy)
+                       channel = channel->type->copy(channel);
                if (!channel) {
                        rc = -ENOMEM;
                        goto out;
@@ -739,23 +775,31 @@ efx_realloc_channels(struct efx_nic *efx, u32 rxq_entries, u32 txq_entries)
                other_channel[i] = channel;
        }
 
-       rc = efx_probe_channels(efx);
-       if (rc)
-               goto rollback;
+       /* Restart buffer table allocation */
+       efx->next_buffer_table = next_buffer_table;
 
-       efx_init_napi(efx);
-
-       /* Destroy old channels */
        for (i = 0; i < efx->n_channels; i++) {
-               efx_fini_napi_channel(other_channel[i]);
-               efx_remove_channel(other_channel[i]);
+               channel = efx->channel[i];
+               if (!channel->type->copy)
+                       continue;
+               rc = efx_probe_channel(channel);
+               if (rc)
+                       goto rollback;
+               efx_init_napi_channel(efx->channel[i]);
        }
+
 out:
-       /* Free unused channel structures */
-       for (i = 0; i < efx->n_channels; i++)
-               kfree(other_channel[i]);
+       /* Destroy unused channel structures */
+       for (i = 0; i < efx->n_channels; i++) {
+               channel = other_channel[i];
+               if (channel && channel->type->copy) {
+                       efx_fini_napi_channel(channel);
+                       efx_remove_channel(channel);
+                       kfree(channel);
+               }
+       }
 
-       efx_init_channels(efx);
+       efx_start_interrupts(efx, true);
        efx_start_all(efx);
        return rc;
 
@@ -776,6 +820,18 @@ void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue)
        mod_timer(&rx_queue->slow_fill, jiffies + msecs_to_jiffies(100));
 }
 
+static const struct efx_channel_type efx_default_channel_type = {
+       .pre_probe              = efx_channel_dummy_op_int,
+       .get_name               = efx_get_channel_name,
+       .copy                   = efx_copy_channel,
+       .keep_eventq            = false,
+};
+
+int efx_channel_dummy_op_int(struct efx_channel *channel)
+{
+       return 0;
+}
+
 /**************************************************************************
  *
  * Port handling
@@ -807,16 +863,14 @@ void efx_link_status_changed(struct efx_nic *efx)
        }
 
        /* Status message for kernel log */
-       if (link_state->up) {
+       if (link_state->up)
                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 {
+       else
                netif_info(efx, link, efx->net_dev, "link down\n");
-       }
-
 }
 
 void efx_link_set_advertising(struct efx_nic *efx, u32 advertising)
@@ -863,11 +917,9 @@ int __efx_reconfigure_port(struct efx_nic *efx)
 
        WARN_ON(!mutex_is_locked(&efx->mac_lock));
 
-       /* Serialise the promiscuous flag with efx_set_multicast_list. */
-       if (efx_dev_registered(efx)) {
-               netif_addr_lock_bh(efx->net_dev);
-               netif_addr_unlock_bh(efx->net_dev);
-       }
+       /* Serialise the promiscuous flag with efx_set_rx_mode. */
+       netif_addr_lock_bh(efx->net_dev);
+       netif_addr_unlock_bh(efx->net_dev);
 
        /* Disable PHY transmit in mac level loopbacks */
        phy_mode = efx->phy_mode;
@@ -907,16 +959,13 @@ static void efx_mac_work(struct work_struct *data)
        struct efx_nic *efx = container_of(data, struct efx_nic, mac_work);
 
        mutex_lock(&efx->mac_lock);
-       if (efx->port_enabled) {
-               efx->type->push_multicast_hash(efx);
-               efx->mac_op->reconfigure(efx);
-       }
+       if (efx->port_enabled)
+               efx->type->reconfigure_mac(efx);
        mutex_unlock(&efx->mac_lock);
 }
 
 static int efx_probe_port(struct efx_nic *efx)
 {
-       unsigned char *perm_addr;
        int rc;
 
        netif_dbg(efx, probe, efx->net_dev, "create port\n");
@@ -929,28 +978,10 @@ static int efx_probe_port(struct efx_nic *efx)
        if (rc)
                return rc;
 
-       /* Sanity check MAC address */
-       perm_addr = efx->net_dev->perm_addr;
-       if (is_valid_ether_addr(perm_addr)) {
-               memcpy(efx->net_dev->dev_addr, perm_addr, ETH_ALEN);
-       } else {
-               netif_err(efx, probe, efx->net_dev, "invalid MAC address %pM\n",
-                         perm_addr);
-               if (!allow_bad_hwaddr) {
-                       rc = -EINVAL;
-                       goto err;
-               }
-               random_ether_addr(efx->net_dev->dev_addr);
-               netif_info(efx, probe, efx->net_dev,
-                          "using locally-generated MAC %pM\n",
-                          efx->net_dev->dev_addr);
-       }
+       /* Initialise MAC address to permanent address */
+       memcpy(efx->net_dev->dev_addr, efx->net_dev->perm_addr, ETH_ALEN);
 
        return 0;
-
- err:
-       efx->type->remove_port(efx);
-       return rc;
 }
 
 static int efx_init_port(struct efx_nic *efx)
@@ -969,7 +1000,7 @@ static int efx_init_port(struct efx_nic *efx)
 
        /* Reconfigure the MAC before creating dma queues (required for
         * Falcon/A1 where RX_INGR_EN/TX_DRAIN_EN isn't supported) */
-       efx->mac_op->reconfigure(efx);
+       efx->type->reconfigure_mac(efx);
 
        /* Ensure the PHY advertises the correct flow control settings */
        rc = efx->phy_op->reconfigure(efx);
@@ -996,8 +1027,7 @@ static void efx_start_port(struct efx_nic *efx)
 
        /* efx_mac_work() might have been scheduled after efx_stop_port(),
         * and then cancelled by efx_flush_all() */
-       efx->type->push_multicast_hash(efx);
-       efx->mac_op->reconfigure(efx);
+       efx->type->reconfigure_mac(efx);
 
        mutex_unlock(&efx->mac_lock);
 }
@@ -1012,10 +1042,8 @@ static void efx_stop_port(struct efx_nic *efx)
        mutex_unlock(&efx->mac_lock);
 
        /* Serialise against efx_set_multicast_list() */
-       if (efx_dev_registered(efx)) {
-               netif_addr_lock_bh(efx->net_dev);
-               netif_addr_unlock_bh(efx->net_dev);
-       }
+       netif_addr_lock_bh(efx->net_dev);
+       netif_addr_unlock_bh(efx->net_dev);
 }
 
 static void efx_fini_port(struct efx_nic *efx)
@@ -1069,9 +1097,11 @@ static int efx_init_io(struct efx_nic *efx)
         * masks event though they reject 46 bit masks.
         */
        while (dma_mask > 0x7fffffffUL) {
-               if (pci_dma_supported(pci_dev, dma_mask) &&
-                   ((rc = pci_set_dma_mask(pci_dev, dma_mask)) == 0))
-                       break;
+               if (pci_dma_supported(pci_dev, dma_mask)) {
+                       rc = pci_set_dma_mask(pci_dev, dma_mask);
+                       if (rc == 0)
+                               break;
+               }
                dma_mask >>= 1;
        }
        if (rc) {
@@ -1144,33 +1174,46 @@ static void efx_fini_io(struct efx_nic *efx)
        pci_disable_device(efx->pci_dev);
 }
 
-/* Get number of channels wanted.  Each channel will have its own IRQ,
- * 1 RX queue and/or 2 TX queues. */
-static int efx_wanted_channels(void)
+static unsigned int efx_wanted_parallelism(struct efx_nic *efx)
 {
-       cpumask_var_t core_mask;
-       int count;
+       cpumask_var_t thread_mask;
+       unsigned int count;
        int cpu;
 
-       if (rss_cpus)
-               return rss_cpus;
+       if (rss_cpus) {
+               count = rss_cpus;
+       } else {
+               if (unlikely(!zalloc_cpumask_var(&thread_mask, GFP_KERNEL))) {
+                       netif_warn(efx, probe, efx->net_dev,
+                                  "RSS disabled due to allocation failure\n");
+                       return 1;
+               }
+
+               count = 0;
+               for_each_online_cpu(cpu) {
+                       if (!cpumask_test_cpu(cpu, thread_mask)) {
+                               ++count;
+                               cpumask_or(thread_mask, thread_mask,
+                                          topology_thread_cpumask(cpu));
+                       }
+               }
 
-       if (unlikely(!zalloc_cpumask_var(&core_mask, GFP_KERNEL))) {
-               printk(KERN_WARNING
-                      "sfc: RSS disabled due to allocation failure\n");
-               return 1;
+               free_cpumask_var(thread_mask);
        }
 
-       count = 0;
-       for_each_online_cpu(cpu) {
-               if (!cpumask_test_cpu(cpu, core_mask)) {
-                       ++count;
-                       cpumask_or(core_mask, core_mask,
-                                  topology_core_cpumask(cpu));
-               }
+       /* If RSS is requested for the PF *and* VFs then we can't write RSS
+        * table entries that are inaccessible to VFs
+        */
+       if (efx_sriov_wanted(efx) && efx_vf_size(efx) > 1 &&
+           count > efx_vf_size(efx)) {
+               netif_warn(efx, probe, efx->net_dev,
+                          "Reducing number of RSS channels from %u to %u for "
+                          "VF support. Increase vf-msix-limit to use more "
+                          "channels on the PF.\n",
+                          count, efx_vf_size(efx));
+               count = efx_vf_size(efx);
        }
 
-       free_cpumask_var(core_mask);
        return count;
 }
 
@@ -1178,7 +1221,8 @@ static int
 efx_init_rx_cpu_rmap(struct efx_nic *efx, struct msix_entry *xentries)
 {
 #ifdef CONFIG_RFS_ACCEL
-       int i, rc;
+       unsigned int i;
+       int rc;
 
        efx->net_dev->rx_cpu_rmap = alloc_irq_cpu_rmap(efx->n_rx_channels);
        if (!efx->net_dev->rx_cpu_rmap)
@@ -1201,17 +1245,24 @@ efx_init_rx_cpu_rmap(struct efx_nic *efx, struct msix_entry *xentries)
  */
 static int efx_probe_interrupts(struct efx_nic *efx)
 {
-       int max_channels =
-               min_t(int, efx->type->phys_addr_channels, EFX_MAX_CHANNELS);
-       int rc, i;
+       unsigned int max_channels =
+               min(efx->type->phys_addr_channels, EFX_MAX_CHANNELS);
+       unsigned int extra_channels = 0;
+       unsigned int i, j;
+       int rc;
+
+       for (i = 0; i < EFX_MAX_EXTRA_CHANNELS; i++)
+               if (efx->extra_channel_type[i])
+                       ++extra_channels;
 
        if (efx->interrupt_mode == EFX_INT_MODE_MSIX) {
                struct msix_entry xentries[EFX_MAX_CHANNELS];
-               int n_channels;
+               unsigned int n_channels;
 
-               n_channels = efx_wanted_channels();
+               n_channels = efx_wanted_parallelism(efx);
                if (separate_tx_channels)
                        n_channels *= 2;
+               n_channels += extra_channels;
                n_channels = min(n_channels, max_channels);
 
                for (i = 0; i < n_channels; i++)
@@ -1220,7 +1271,7 @@ static int efx_probe_interrupts(struct efx_nic *efx)
                if (rc > 0) {
                        netif_err(efx, drv, efx->net_dev,
                                  "WARNING: Insufficient MSI-X vectors"
-                                 " available (%d < %d).\n", rc, n_channels);
+                                 " available (%d < %u).\n", rc, n_channels);
                        netif_err(efx, drv, efx->net_dev,
                                  "WARNING: Performance may be reduced.\n");
                        EFX_BUG_ON_PARANOID(rc >= n_channels);
@@ -1231,22 +1282,23 @@ static int efx_probe_interrupts(struct efx_nic *efx)
 
                if (rc == 0) {
                        efx->n_channels = n_channels;
+                       if (n_channels > extra_channels)
+                               n_channels -= extra_channels;
                        if (separate_tx_channels) {
-                               efx->n_tx_channels =
-                                       max(efx->n_channels / 2, 1U);
-                               efx->n_rx_channels =
-                                       max(efx->n_channels -
-                                           efx->n_tx_channels, 1U);
+                               efx->n_tx_channels = max(n_channels / 2, 1U);
+                               efx->n_rx_channels = max(n_channels -
+                                                        efx->n_tx_channels,
+                                                        1U);
                        } else {
-                               efx->n_tx_channels = efx->n_channels;
-                               efx->n_rx_channels = efx->n_channels;
+                               efx->n_tx_channels = n_channels;
+                               efx->n_rx_channels = n_channels;
                        }
                        rc = efx_init_rx_cpu_rmap(efx, xentries);
                        if (rc) {
                                pci_disable_msix(efx->pci_dev);
                                return rc;
                        }
-                       for (i = 0; i < n_channels; i++)
+                       for (i = 0; i < efx->n_channels; i++)
                                efx_get_channel(efx, i)->irq =
                                        xentries[i].vector;
                } else {
@@ -1280,9 +1332,68 @@ static int efx_probe_interrupts(struct efx_nic *efx)
                efx->legacy_irq = efx->pci_dev->irq;
        }
 
+       /* Assign extra channels if possible */
+       j = efx->n_channels;
+       for (i = 0; i < EFX_MAX_EXTRA_CHANNELS; i++) {
+               if (!efx->extra_channel_type[i])
+                       continue;
+               if (efx->interrupt_mode != EFX_INT_MODE_MSIX ||
+                   efx->n_channels <= extra_channels) {
+                       efx->extra_channel_type[i]->handle_no_channel(efx);
+               } else {
+                       --j;
+                       efx_get_channel(efx, j)->type =
+                               efx->extra_channel_type[i];
+               }
+       }
+
+       /* RSS might be usable on VFs even if it is disabled on the PF */
+       efx->rss_spread = (efx->n_rx_channels > 1 ?
+                          efx->n_rx_channels : efx_vf_size(efx));
+
        return 0;
 }
 
+/* Enable interrupts, then probe and start the event queues */
+static void efx_start_interrupts(struct efx_nic *efx, bool may_keep_eventq)
+{
+       struct efx_channel *channel;
+
+       if (efx->legacy_irq)
+               efx->legacy_irq_enabled = true;
+       efx_nic_enable_interrupts(efx);
+
+       efx_for_each_channel(channel, efx) {
+               if (!channel->type->keep_eventq || !may_keep_eventq)
+                       efx_init_eventq(channel);
+               efx_start_eventq(channel);
+       }
+
+       efx_mcdi_mode_event(efx);
+}
+
+static void efx_stop_interrupts(struct efx_nic *efx, bool may_keep_eventq)
+{
+       struct efx_channel *channel;
+
+       efx_mcdi_mode_poll(efx);
+
+       efx_nic_disable_interrupts(efx);
+       if (efx->legacy_irq) {
+               synchronize_irq(efx->legacy_irq);
+               efx->legacy_irq_enabled = false;
+       }
+
+       efx_for_each_channel(channel, efx) {
+               if (channel->irq)
+                       synchronize_irq(channel->irq);
+
+               efx_stop_eventq(channel);
+               if (!channel->type->keep_eventq || !may_keep_eventq)
+                       efx_fini_eventq(channel);
+       }
+}
+
 static void efx_remove_interrupts(struct efx_nic *efx)
 {
        struct efx_channel *channel;
@@ -1333,11 +1444,13 @@ static int efx_probe_nic(struct efx_nic *efx)
        if (rc)
                goto fail;
 
+       efx->type->dimension_resources(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] =
-                       ethtool_rxfh_indir_default(i, efx->n_rx_channels);
+                       ethtool_rxfh_indir_default(i, efx->rss_spread);
 
        efx_set_channels(efx);
        netif_set_real_num_tx_queues(efx->net_dev, efx->n_tx_channels);
@@ -1385,21 +1498,22 @@ static int efx_probe_all(struct efx_nic *efx)
        }
 
        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;
+               goto fail3;
        }
 
+       rc = efx_probe_channels(efx);
+       if (rc)
+               goto fail4;
+
        return 0;
 
  fail4:
-       efx_remove_channels(efx);
+       efx_remove_filters(efx);
  fail3:
        efx_remove_port(efx);
  fail2:
@@ -1408,15 +1522,13 @@ static int efx_probe_all(struct efx_nic *efx)
        return rc;
 }
 
-/* Called after previous invocation(s) of efx_stop_all, restarts the
- * port, kernel transmit queue, NAPI processing and hardware interrupts,
- * and ensures that the port is scheduled to be reconfigured.
- * This function is safe to call multiple times when the NIC is in any
- * state. */
+/* Called after previous invocation(s) of efx_stop_all, restarts the port,
+ * kernel transmit queues and NAPI processing, and ensures that the port is
+ * scheduled to be reconfigured. This function is safe to call multiple
+ * times when the NIC is in any state.
+ */
 static void efx_start_all(struct efx_nic *efx)
 {
-       struct efx_channel *channel;
-
        EFX_ASSERT_RESET_SERIALISED(efx);
 
        /* Check that it is appropriate to restart the interface. All
@@ -1425,31 +1537,11 @@ static void efx_start_all(struct efx_nic *efx)
                return;
        if ((efx->state != STATE_RUNNING) && (efx->state != STATE_INIT))
                return;
-       if (efx_dev_registered(efx) && !netif_running(efx->net_dev))
+       if (!netif_running(efx->net_dev))
                return;
 
-       /* Mark the port as enabled so port reconfigurations can start, then
-        * restart the transmit interface early so the watchdog timer stops */
        efx_start_port(efx);
-
-       if (efx_dev_registered(efx) && netif_device_present(efx->net_dev))
-               netif_tx_wake_all_queues(efx->net_dev);
-
-       efx_for_each_channel(channel, efx)
-               efx_start_channel(channel);
-
-       if (efx->legacy_irq)
-               efx->legacy_irq_enabled = true;
-       efx_nic_enable_interrupts(efx);
-
-       /* Switch to event based MCDI completions after enabling interrupts.
-        * If a reset has been scheduled, then we need to stay in polled mode.
-        * Rather than serialising efx_mcdi_mode_event() [which sleeps] and
-        * reset_pending [modified from an atomic context], we instead guarantee
-        * that efx_mcdi_mode_poll() isn't reverted erroneously */
-       efx_mcdi_mode_event(efx);
-       if (efx->reset_pending)
-               efx_mcdi_mode_poll(efx);
+       efx_start_datapath(efx);
 
        /* Start the hardware monitor if there is one. Otherwise (we're link
         * event driven), we have to poll the PHY because after an event queue
@@ -1485,8 +1577,6 @@ static void efx_flush_all(struct efx_nic *efx)
  * taking locks. */
 static void efx_stop_all(struct efx_nic *efx)
 {
-       struct efx_channel *channel;
-
        EFX_ASSERT_RESET_SERIALISED(efx);
 
        /* port_enabled can be read safely under the rtnl lock */
@@ -1494,28 +1584,6 @@ static void efx_stop_all(struct efx_nic *efx)
                return;
 
        efx->type->stop_stats(efx);
-
-       /* Switch to MCDI polling on Siena before disabling interrupts */
-       efx_mcdi_mode_poll(efx);
-
-       /* Disable interrupts and wait for ISR to complete */
-       efx_nic_disable_interrupts(efx);
-       if (efx->legacy_irq) {
-               synchronize_irq(efx->legacy_irq);
-               efx->legacy_irq_enabled = false;
-       }
-       efx_for_each_channel(channel, efx) {
-               if (channel->irq)
-                       synchronize_irq(channel->irq);
-       }
-
-       /* Stop all NAPI processing and synchronous rx refills */
-       efx_for_each_channel(channel, efx)
-               efx_stop_channel(channel);
-
-       /* Stop all asynchronous port reconfigurations. Since all
-        * event processing has already been stopped, there is no
-        * window to loose phy events */
        efx_stop_port(efx);
 
        /* Flush efx_mac_work(), refill_workqueue, monitor_work */
@@ -1523,17 +1591,15 @@ static void efx_stop_all(struct efx_nic *efx)
 
        /* Stop the kernel transmit interface late, so the watchdog
         * timer isn't ticking over the flush */
-       if (efx_dev_registered(efx)) {
-               netif_tx_stop_all_queues(efx->net_dev);
-               netif_tx_lock_bh(efx->net_dev);
-               netif_tx_unlock_bh(efx->net_dev);
-       }
+       netif_tx_disable(efx->net_dev);
+
+       efx_stop_datapath(efx);
 }
 
 static void efx_remove_all(struct efx_nic *efx)
 {
-       efx_remove_filters(efx);
        efx_remove_channels(efx);
+       efx_remove_filters(efx);
        efx_remove_port(efx);
        efx_remove_nic(efx);
 }
@@ -1544,13 +1610,13 @@ static void efx_remove_all(struct efx_nic *efx)
  *
  **************************************************************************/
 
-static unsigned int irq_mod_ticks(unsigned int usecs, unsigned int resolution)
+static unsigned int irq_mod_ticks(unsigned int usecs, unsigned int quantum_ns)
 {
        if (usecs == 0)
                return 0;
-       if (usecs < resolution)
+       if (usecs * 1000 < quantum_ns)
                return 1; /* never round down to 0 */
-       return usecs / resolution;
+       return usecs * 1000 / quantum_ns;
 }
 
 /* Set interrupt moderation parameters */
@@ -1559,14 +1625,20 @@ int efx_init_irq_moderation(struct efx_nic *efx, unsigned int tx_usecs,
                            bool rx_may_override_tx)
 {
        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);
+       unsigned int irq_mod_max = DIV_ROUND_UP(efx->type->timer_period_max *
+                                               efx->timer_quantum_ns,
+                                               1000);
+       unsigned int tx_ticks;
+       unsigned int rx_ticks;
 
        EFX_ASSERT_RESET_SERIALISED(efx);
 
-       if (tx_ticks > EFX_IRQ_MOD_MAX || rx_ticks > EFX_IRQ_MOD_MAX)
+       if (tx_usecs > irq_mod_max || rx_usecs > irq_mod_max)
                return -EINVAL;
 
+       tx_ticks = irq_mod_ticks(tx_usecs, efx->timer_quantum_ns);
+       rx_ticks = irq_mod_ticks(rx_usecs, efx->timer_quantum_ns);
+
        if (tx_ticks != rx_ticks && efx->tx_channel_offset == 0 &&
            !rx_may_override_tx) {
                netif_err(efx, drv, efx->net_dev, "Channels are shared. "
@@ -1589,8 +1661,14 @@ int efx_init_irq_moderation(struct efx_nic *efx, unsigned int tx_usecs,
 void efx_get_irq_moderation(struct efx_nic *efx, unsigned int *tx_usecs,
                            unsigned int *rx_usecs, bool *rx_adaptive)
 {
+       /* We must round up when converting ticks to microseconds
+        * because we round down when converting the other way.
+        */
+
        *rx_adaptive = efx->irq_rx_adaptive;
-       *rx_usecs = efx->irq_rx_moderation * EFX_IRQ_MOD_RESOLUTION;
+       *rx_usecs = DIV_ROUND_UP(efx->irq_rx_moderation *
+                                efx->timer_quantum_ns,
+                                1000);
 
        /* If channels are shared between RX and TX, so is IRQ
         * moderation.  Otherwise, IRQ moderation is the same for all
@@ -1599,9 +1677,10 @@ void efx_get_irq_moderation(struct efx_nic *efx, unsigned int *tx_usecs,
        if (efx->tx_channel_offset == 0)
                *tx_usecs = *rx_usecs;
        else
-               *tx_usecs =
+               *tx_usecs = DIV_ROUND_UP(
                        efx->channel[efx->tx_channel_offset]->irq_moderation *
-                       EFX_IRQ_MOD_RESOLUTION;
+                       efx->timer_quantum_ns,
+                       1000);
 }
 
 /**************************************************************************
@@ -1664,15 +1743,21 @@ static int efx_ioctl(struct net_device *net_dev, struct ifreq *ifr, int cmd)
  *
  **************************************************************************/
 
+static void efx_init_napi_channel(struct efx_channel *channel)
+{
+       struct efx_nic *efx = channel->efx;
+
+       channel->napi_dev = efx->net_dev;
+       netif_napi_add(channel->napi_dev, &channel->napi_str,
+                      efx_poll, napi_weight);
+}
+
 static void efx_init_napi(struct efx_nic *efx)
 {
        struct efx_channel *channel;
 
-       efx_for_each_channel(channel, efx) {
-               channel->napi_dev = efx->net_dev;
-               netif_napi_add(channel->napi_dev, &channel->napi_str,
-                              efx_poll, napi_weight);
-       }
+       efx_for_each_channel(channel, efx)
+               efx_init_napi_channel(channel);
 }
 
 static void efx_fini_napi_channel(struct efx_channel *channel)
@@ -1757,22 +1842,21 @@ static int efx_net_stop(struct net_device *net_dev)
        if (efx->state != STATE_DISABLED) {
                /* Stop the device and flush all the channels */
                efx_stop_all(efx);
-               efx_fini_channels(efx);
-               efx_init_channels(efx);
        }
 
        return 0;
 }
 
 /* Context: process, dev_base_lock or RTNL held, non-blocking. */
-static struct rtnl_link_stats64 *efx_net_stats(struct net_device *net_dev, struct rtnl_link_stats64 *stats)
+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;
 
        spin_lock_bh(&efx->stats_lock);
+
        efx->type->update_stats(efx);
-       spin_unlock_bh(&efx->stats_lock);
 
        stats->rx_packets = mac_stats->rx_packets;
        stats->tx_packets = mac_stats->tx_packets;
@@ -1796,6 +1880,8 @@ static struct rtnl_link_stats64 *efx_net_stats(struct net_device *net_dev, struc
        stats->tx_errors = (stats->tx_window_errors +
                            mac_stats->tx_bad);
 
+       spin_unlock_bh(&efx->stats_lock);
+
        return stats;
 }
 
@@ -1816,7 +1902,6 @@ static void efx_watchdog(struct net_device *net_dev)
 static int efx_change_mtu(struct net_device *net_dev, int new_mtu)
 {
        struct efx_nic *efx = netdev_priv(net_dev);
-       int rc = 0;
 
        EFX_ASSERT_RESET_SERIALISED(efx);
 
@@ -1827,19 +1912,15 @@ static int efx_change_mtu(struct net_device *net_dev, int new_mtu)
 
        netif_dbg(efx, drv, efx->net_dev, "changing MTU to %d\n", new_mtu);
 
-       efx_fini_channels(efx);
-
        mutex_lock(&efx->mac_lock);
        /* Reconfigure the MAC before enabling the dma queues so that
         * the RX buffers don't overflow */
        net_dev->mtu = new_mtu;
-       efx->mac_op->reconfigure(efx);
+       efx->type->reconfigure_mac(efx);
        mutex_unlock(&efx->mac_lock);
 
-       efx_init_channels(efx);
-
        efx_start_all(efx);
-       return rc;
+       return 0;
 }
 
 static int efx_set_mac_address(struct net_device *net_dev, void *data)
@@ -1854,21 +1935,22 @@ static int efx_set_mac_address(struct net_device *net_dev, void *data)
                netif_err(efx, drv, efx->net_dev,
                          "invalid ethernet MAC address requested: %pM\n",
                          new_addr);
-               return -EINVAL;
+               return -EADDRNOTAVAIL;
        }
 
        memcpy(net_dev->dev_addr, new_addr, net_dev->addr_len);
+       efx_sriov_mac_address_changed(efx);
 
        /* Reconfigure the MAC */
        mutex_lock(&efx->mac_lock);
-       efx->mac_op->reconfigure(efx);
+       efx->type->reconfigure_mac(efx);
        mutex_unlock(&efx->mac_lock);
 
        return 0;
 }
 
 /* Context: netif_addr_lock held, BHs disabled. */
-static void efx_set_multicast_list(struct net_device *net_dev)
+static void efx_set_rx_mode(struct net_device *net_dev)
 {
        struct efx_nic *efx = netdev_priv(net_dev);
        struct netdev_hw_addr *ha;
@@ -1922,8 +2004,14 @@ static const struct net_device_ops efx_netdev_ops = {
        .ndo_do_ioctl           = efx_ioctl,
        .ndo_change_mtu         = efx_change_mtu,
        .ndo_set_mac_address    = efx_set_mac_address,
-       .ndo_set_rx_mode        = efx_set_multicast_list,
+       .ndo_set_rx_mode        = efx_set_rx_mode,
        .ndo_set_features       = efx_set_features,
+#ifdef CONFIG_SFC_SRIOV
+       .ndo_set_vf_mac         = efx_sriov_set_vf_mac,
+       .ndo_set_vf_vlan        = efx_sriov_set_vf_vlan,
+       .ndo_set_vf_spoofchk    = efx_sriov_set_vf_spoofchk,
+       .ndo_get_vf_config      = efx_sriov_get_vf_config,
+#endif
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller = efx_netpoll,
 #endif
@@ -1975,10 +2063,6 @@ static int efx_register_netdev(struct efx_nic *efx)
        net_dev->netdev_ops = &efx_netdev_ops;
        SET_ETHTOOL_OPS(net_dev, &efx_ethtool_ops);
 
-       /* Clear MAC statistics */
-       efx->mac_op->update_stats(efx);
-       memset(&efx->mac_stats, 0, sizeof(efx->mac_stats));
-
        rtnl_lock();
 
        rc = dev_alloc_name(net_dev, net_dev->name);
@@ -1997,7 +2081,7 @@ static int efx_register_netdev(struct efx_nic *efx)
        }
 
        /* Always start with carrier off; PHY events will detect the link */
-       netif_carrier_off(efx->net_dev);
+       netif_carrier_off(net_dev);
 
        rtnl_unlock();
 
@@ -2038,11 +2122,9 @@ static void efx_unregister_netdev(struct efx_nic *efx)
                        efx_release_tx_buffers(tx_queue);
        }
 
-       if (efx_dev_registered(efx)) {
-               strlcpy(efx->name, pci_name(efx->pci_dev), sizeof(efx->name));
-               device_remove_file(&efx->pci_dev->dev, &dev_attr_phy_type);
-               unregister_netdev(efx->net_dev);
-       }
+       strlcpy(efx->name, pci_name(efx->pci_dev), sizeof(efx->name));
+       device_remove_file(&efx->pci_dev->dev, &dev_attr_phy_type);
+       unregister_netdev(efx->net_dev);
 }
 
 /**************************************************************************
@@ -2060,7 +2142,7 @@ void efx_reset_down(struct efx_nic *efx, enum reset_type method)
        efx_stop_all(efx);
        mutex_lock(&efx->mac_lock);
 
-       efx_fini_channels(efx);
+       efx_stop_interrupts(efx, false);
        if (efx->port_initialized && method != RESET_TYPE_INVISIBLE)
                efx->phy_op->fini(efx);
        efx->type->fini(efx);
@@ -2095,10 +2177,11 @@ int efx_reset_up(struct efx_nic *efx, enum reset_type method, bool ok)
                                  "could not restore PHY settings\n");
        }
 
-       efx->mac_op->reconfigure(efx);
+       efx->type->reconfigure_mac(efx);
 
-       efx_init_channels(efx);
+       efx_start_interrupts(efx, false);
        efx_restore_filters(efx);
+       efx_sriov_reset(efx);
 
        mutex_unlock(&efx->mac_lock);
 
@@ -2300,10 +2383,10 @@ static int efx_init_struct(struct efx_nic *efx, const struct efx_nic_type *type,
        efx->net_dev = net_dev;
        spin_lock_init(&efx->stats_lock);
        mutex_init(&efx->mac_lock);
-       efx->mac_op = type->default_mac_ops;
        efx->phy_op = &efx_dummy_phy_operations;
        efx->mdio.dev = net_dev;
        INIT_WORK(&efx->mac_work, efx_mac_work);
+       init_waitqueue_head(&efx->flush_wq);
 
        for (i = 0; i < EFX_MAX_CHANNELS; i++) {
                efx->channel[i] = efx_alloc_channel(efx, i, NULL);
@@ -2361,8 +2444,8 @@ static void efx_pci_remove_main(struct efx_nic *efx)
        free_irq_cpu_rmap(efx->net_dev->rx_cpu_rmap);
        efx->net_dev->rx_cpu_rmap = NULL;
 #endif
+       efx_stop_interrupts(efx, false);
        efx_nic_fini_interrupt(efx);
-       efx_fini_channels(efx);
        efx_fini_port(efx);
        efx->type->fini(efx);
        efx_fini_napi(efx);
@@ -2388,6 +2471,8 @@ static void efx_pci_remove(struct pci_dev *pci_dev)
        /* Allow any queued efx_resets() to complete */
        rtnl_unlock();
 
+       efx_stop_interrupts(efx, false);
+       efx_sriov_fini(efx);
        efx_unregister_netdev(efx);
 
        efx_mtd_remove(efx);
@@ -2436,16 +2521,14 @@ static int efx_pci_probe_main(struct efx_nic *efx)
                goto fail4;
        }
 
-       efx_init_channels(efx);
-
        rc = efx_nic_init_interrupt(efx);
        if (rc)
                goto fail5;
+       efx_start_interrupts(efx, false);
 
        return 0;
 
  fail5:
-       efx_fini_channels(efx);
        efx_fini_port(efx);
  fail4:
        efx->type->fini(efx);
@@ -2459,7 +2542,7 @@ static int efx_pci_probe_main(struct efx_nic *efx)
 /* NIC initialisation
  *
  * This is called at module load (or hotplug insertion,
- * theoretically).  It sets up PCI mappings, tests and resets the NIC,
+ * theoretically).  It sets up PCI mappings, resets the NIC,
  * sets up and registers the network devices with the kernel and hooks
  * the interrupt service routine.  It does not prepare the device for
  * transmission; this is left to the first time one of the network
@@ -2471,7 +2554,7 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev,
        const struct efx_nic_type *type = (const struct efx_nic_type *) entry->driver_data;
        struct net_device *net_dev;
        struct efx_nic *efx;
-       int i, rc;
+       int rc;
 
        /* Allocate and initialise a struct net_device and struct efx_nic */
        net_dev = alloc_etherdev_mqs(sizeof(*efx), EFX_MAX_CORE_TX_QUEUES,
@@ -2504,39 +2587,22 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev,
        if (rc)
                goto fail2;
 
-       /* No serialisation is required with the reset path because
-        * we're in STATE_INIT. */
-       for (i = 0; i < 5; i++) {
-               rc = efx_pci_probe_main(efx);
-
-               /* Serialise against efx_reset(). No more resets will be
-                * scheduled since efx_stop_all() has been called, and we
-                * have not and never have been registered with either
-                * the rtnetlink or driverlink layers. */
-               cancel_work_sync(&efx->reset_work);
+       rc = efx_pci_probe_main(efx);
 
-               if (rc == 0) {
-                       if (efx->reset_pending) {
-                               /* If there was a scheduled reset during
-                                * probe, the NIC is probably hosed anyway */
-                               efx_pci_remove_main(efx);
-                               rc = -EIO;
-                       } else {
-                               break;
-                       }
-               }
-
-               /* Retry if a recoverably reset event has been scheduled */
-               if (efx->reset_pending &
-                   ~(1 << RESET_TYPE_INVISIBLE | 1 << RESET_TYPE_ALL) ||
-                   !efx->reset_pending)
-                       goto fail3;
+       /* Serialise against efx_reset(). No more resets will be
+        * scheduled since efx_stop_all() has been called, and we have
+        * not and never have been registered.
+        */
+       cancel_work_sync(&efx->reset_work);
 
-               efx->reset_pending = 0;
-       }
+       if (rc)
+               goto fail3;
 
-       if (rc) {
-               netif_err(efx, probe, efx->net_dev, "Could not reset NIC\n");
+       /* If there was a scheduled reset during probe, the NIC is
+        * probably hosed anyway.
+        */
+       if (efx->reset_pending) {
+               rc = -EIO;
                goto fail4;
        }
 
@@ -2546,18 +2612,27 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev,
 
        rc = efx_register_netdev(efx);
        if (rc)
-               goto fail5;
+               goto fail4;
+
+       rc = efx_sriov_init(efx);
+       if (rc)
+               netif_err(efx, probe, efx->net_dev,
+                         "SR-IOV can't be enabled rc %d\n", rc);
 
        netif_dbg(efx, probe, efx->net_dev, "initialisation successful\n");
 
+       /* Try to create MTDs, but allow this to fail */
        rtnl_lock();
-       efx_mtd_probe(efx); /* allowed to fail */
+       rc = efx_mtd_probe(efx);
        rtnl_unlock();
+       if (rc)
+               netif_warn(efx, probe, efx->net_dev,
+                          "failed to create MTDs (%d)\n", rc);
+
        return 0;
 
- fail5:
-       efx_pci_remove_main(efx);
  fail4:
+       efx_pci_remove_main(efx);
  fail3:
        efx_fini_io(efx);
  fail2:
@@ -2578,7 +2653,7 @@ static int efx_pm_freeze(struct device *dev)
        netif_device_detach(efx->net_dev);
 
        efx_stop_all(efx);
-       efx_fini_channels(efx);
+       efx_stop_interrupts(efx, false);
 
        return 0;
 }
@@ -2589,7 +2664,7 @@ static int efx_pm_thaw(struct device *dev)
 
        efx->state = STATE_INIT;
 
-       efx_init_channels(efx);
+       efx_start_interrupts(efx, false);
 
        mutex_lock(&efx->mac_lock);
        efx->phy_op->reconfigure(efx);
@@ -2658,7 +2733,7 @@ static int efx_pm_suspend(struct device *dev)
        return rc;
 }
 
-static struct dev_pm_ops efx_pm_ops = {
+static const struct dev_pm_ops efx_pm_ops = {
        .suspend        = efx_pm_suspend,
        .resume         = efx_pm_resume,
        .freeze         = efx_pm_freeze,
@@ -2695,6 +2770,10 @@ static int __init efx_init_module(void)
        if (rc)
                goto err_notifier;
 
+       rc = efx_init_sriov();
+       if (rc)
+               goto err_sriov;
+
        reset_workqueue = create_singlethread_workqueue("sfc_reset");
        if (!reset_workqueue) {
                rc = -ENOMEM;
@@ -2710,6 +2789,8 @@ static int __init efx_init_module(void)
  err_pci:
        destroy_workqueue(reset_workqueue);
  err_reset:
+       efx_fini_sriov();
+ err_sriov:
        unregister_netdevice_notifier(&efx_netdev_notifier);
  err_notifier:
        return rc;
@@ -2721,6 +2802,7 @@ static void __exit efx_exit_module(void)
 
        pci_unregister_driver(&efx_pci_driver);
        destroy_workqueue(reset_workqueue);
+       efx_fini_sriov();
        unregister_netdevice_notifier(&efx_netdev_notifier);
 
 }
This page took 0.04495 seconds and 5 git commands to generate.