These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / net / ethernet / sfc / efx.c
index 4b00545..a3c42a3 100644 (file)
@@ -26,6 +26,7 @@
 #include "efx.h"
 #include "nic.h"
 #include "selftest.h"
+#include "sriov.h"
 
 #include "mcdi.h"
 #include "workarounds.h"
@@ -76,6 +77,7 @@ const char *const efx_reset_type_names[] = {
        [RESET_TYPE_RECOVER_OR_ALL]     = "RECOVER_OR_ALL",
        [RESET_TYPE_WORLD]              = "WORLD",
        [RESET_TYPE_RECOVER_OR_DISABLE] = "RECOVER_OR_DISABLE",
+       [RESET_TYPE_DATAPATH]           = "DATAPATH",
        [RESET_TYPE_MC_BIST]            = "MC_BIST",
        [RESET_TYPE_DISABLE]            = "DISABLE",
        [RESET_TYPE_TX_WATCHDOG]        = "TX_WATCHDOG",
@@ -113,9 +115,9 @@ static struct workqueue_struct *reset_workqueue;
  *
  * This is only used in MSI-X interrupt mode
  */
-static bool separate_tx_channels;
-module_param(separate_tx_channels, bool, 0444);
-MODULE_PARM_DESC(separate_tx_channels,
+bool efx_separate_tx_channels;
+module_param(efx_separate_tx_channels, bool, 0444);
+MODULE_PARM_DESC(efx_separate_tx_channels,
                 "Use separate channels for TX and RX");
 
 /* This is the weight assigned to each of the (per-channel) virtual
@@ -243,11 +245,17 @@ static int efx_check_disabled(struct efx_nic *efx)
  */
 static int efx_process_channel(struct efx_channel *channel, int budget)
 {
+       struct efx_tx_queue *tx_queue;
        int spent;
 
        if (unlikely(!channel->enabled))
                return 0;
 
+       efx_for_each_channel_tx_queue(tx_queue, channel) {
+               tx_queue->pkts_compl = 0;
+               tx_queue->bytes_compl = 0;
+       }
+
        spent = efx_nic_process_eventq(channel, budget);
        if (spent && efx_channel_has_rx_queue(channel)) {
                struct efx_rx_queue *rx_queue =
@@ -257,6 +265,14 @@ static int efx_process_channel(struct efx_channel *channel, int budget)
                efx_fast_push_rx_descriptors(rx_queue, true);
        }
 
+       /* Update BQL */
+       efx_for_each_channel_tx_queue(tx_queue, channel) {
+               if (tx_queue->bytes_compl) {
+                       netdev_tx_completed_queue(tx_queue->core_txq,
+                               tx_queue->pkts_compl, tx_queue->bytes_compl);
+               }
+       }
+
        return spent;
 }
 
@@ -948,6 +964,16 @@ void efx_link_set_wanted_fc(struct efx_nic *efx, u8 wanted_fc)
 
 static void efx_fini_port(struct efx_nic *efx);
 
+/* We assume that efx->type->reconfigure_mac will always try to sync RX
+ * filters and therefore needs to read-lock the filter table against freeing
+ */
+void efx_mac_reconfigure(struct efx_nic *efx)
+{
+       down_read(&efx->filter_sem);
+       efx->type->reconfigure_mac(efx);
+       up_read(&efx->filter_sem);
+}
+
 /* Push loopback/power/transmit disable settings to the PHY, and reconfigure
  * the MAC appropriately. All other PHY configuration changes are pushed
  * through phy_op->set_settings(), and pushed asynchronously to the MAC
@@ -1001,7 +1027,7 @@ static void efx_mac_work(struct work_struct *data)
 
        mutex_lock(&efx->mac_lock);
        if (efx->port_enabled)
-               efx->type->reconfigure_mac(efx);
+               efx_mac_reconfigure(efx);
        mutex_unlock(&efx->mac_lock);
 }
 
@@ -1041,11 +1067,11 @@ 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->type->reconfigure_mac(efx);
+       efx_mac_reconfigure(efx);
 
        /* Ensure the PHY advertises the correct flow control settings */
        rc = efx->phy_op->reconfigure(efx);
-       if (rc)
+       if (rc && rc != -EPERM)
                goto fail2;
 
        mutex_unlock(&efx->mac_lock);
@@ -1067,7 +1093,7 @@ static void efx_start_port(struct efx_nic *efx)
        efx->port_enabled = true;
 
        /* Ensure MAC ingress/egress is enabled */
-       efx->type->reconfigure_mac(efx);
+       efx_mac_reconfigure(efx);
 
        mutex_unlock(&efx->mac_lock);
 }
@@ -1200,10 +1226,12 @@ static int efx_init_io(struct efx_nic *efx)
        struct pci_dev *pci_dev = efx->pci_dev;
        dma_addr_t dma_mask = efx->type->max_dma_mask;
        unsigned int mem_map_size = efx->type->mem_map_size(efx);
-       int rc;
+       int rc, bar;
 
        netif_dbg(efx, probe, efx->net_dev, "initialising I/O\n");
 
+       bar = efx->type->mem_bar;
+
        rc = pci_enable_device(pci_dev);
        if (rc) {
                netif_err(efx, probe, efx->net_dev,
@@ -1219,11 +1247,9 @@ static int efx_init_io(struct efx_nic *efx)
         * masks event though they reject 46 bit masks.
         */
        while (dma_mask > 0x7fffffffUL) {
-               if (dma_supported(&pci_dev->dev, dma_mask)) {
-                       rc = dma_set_mask_and_coherent(&pci_dev->dev, dma_mask);
-                       if (rc == 0)
-                               break;
-               }
+               rc = dma_set_mask_and_coherent(&pci_dev->dev, dma_mask);
+               if (rc == 0)
+                       break;
                dma_mask >>= 1;
        }
        if (rc) {
@@ -1234,8 +1260,8 @@ static int efx_init_io(struct efx_nic *efx)
        netif_dbg(efx, probe, efx->net_dev,
                  "using DMA mask %llx\n", (unsigned long long) dma_mask);
 
-       efx->membase_phys = pci_resource_start(efx->pci_dev, EFX_MEM_BAR);
-       rc = pci_request_region(pci_dev, EFX_MEM_BAR, "sfc");
+       efx->membase_phys = pci_resource_start(efx->pci_dev, bar);
+       rc = pci_request_region(pci_dev, bar, "sfc");
        if (rc) {
                netif_err(efx, probe, efx->net_dev,
                          "request for memory BAR failed\n");
@@ -1258,7 +1284,7 @@ static int efx_init_io(struct efx_nic *efx)
        return 0;
 
  fail4:
-       pci_release_region(efx->pci_dev, EFX_MEM_BAR);
+       pci_release_region(efx->pci_dev, bar);
  fail3:
        efx->membase_phys = 0;
  fail2:
@@ -1269,6 +1295,8 @@ static int efx_init_io(struct efx_nic *efx)
 
 static void efx_fini_io(struct efx_nic *efx)
 {
+       int bar;
+
        netif_dbg(efx, drv, efx->net_dev, "shutting down I/O\n");
 
        if (efx->membase) {
@@ -1277,11 +1305,23 @@ static void efx_fini_io(struct efx_nic *efx)
        }
 
        if (efx->membase_phys) {
-               pci_release_region(efx->pci_dev, EFX_MEM_BAR);
+               bar = efx->type->mem_bar;
+               pci_release_region(efx->pci_dev, bar);
                efx->membase_phys = 0;
        }
 
-       pci_disable_device(efx->pci_dev);
+       /* Don't disable bus-mastering if VFs are assigned */
+       if (!pci_vfs_assigned(efx->pci_dev))
+               pci_disable_device(efx->pci_dev);
+}
+
+void efx_set_default_rx_indir_table(struct efx_nic *efx)
+{
+       size_t i;
+
+       for (i = 0; i < ARRAY_SIZE(efx->rx_indir_table); i++)
+               efx->rx_indir_table[i] =
+                       ethtool_rxfh_indir_default(i, efx->rss_spread);
 }
 
 static unsigned int efx_wanted_parallelism(struct efx_nic *efx)
@@ -1304,7 +1344,7 @@ static unsigned int efx_wanted_parallelism(struct efx_nic *efx)
                        if (!cpumask_test_cpu(cpu, thread_mask)) {
                                ++count;
                                cpumask_or(thread_mask, thread_mask,
-                                          topology_thread_cpumask(cpu));
+                                          topology_sibling_cpumask(cpu));
                        }
                }
 
@@ -1314,15 +1354,19 @@ static unsigned int efx_wanted_parallelism(struct efx_nic *efx)
        /* If RSS is requested for the PF *and* VFs then we can't write RSS
         * table entries that are inaccessible to VFs
         */
-       if (efx->type->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);
+#ifdef CONFIG_SFC_SRIOV
+       if (efx->type->sriov_wanted) {
+               if (efx->type->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);
+               }
        }
+#endif
 
        return count;
 }
@@ -1345,7 +1389,7 @@ static int efx_probe_interrupts(struct efx_nic *efx)
                unsigned int n_channels;
 
                n_channels = efx_wanted_parallelism(efx);
-               if (separate_tx_channels)
+               if (efx_separate_tx_channels)
                        n_channels *= 2;
                n_channels += extra_channels;
                n_channels = min(n_channels, efx->max_channels);
@@ -1372,13 +1416,16 @@ static int efx_probe_interrupts(struct efx_nic *efx)
                        efx->n_channels = n_channels;
                        if (n_channels > extra_channels)
                                n_channels -= extra_channels;
-                       if (separate_tx_channels) {
-                               efx->n_tx_channels = max(n_channels / 2, 1U);
+                       if (efx_separate_tx_channels) {
+                               efx->n_tx_channels = min(max(n_channels / 2,
+                                                            1U),
+                                                        efx->max_tx_channels);
                                efx->n_rx_channels = max(n_channels -
                                                         efx->n_tx_channels,
                                                         1U);
                        } else {
-                               efx->n_tx_channels = n_channels;
+                               efx->n_tx_channels = min(n_channels,
+                                                        efx->max_tx_channels);
                                efx->n_rx_channels = n_channels;
                        }
                        for (i = 0; i < efx->n_channels; i++)
@@ -1404,7 +1451,7 @@ static int efx_probe_interrupts(struct efx_nic *efx)
 
        /* Assume legacy interrupts */
        if (efx->interrupt_mode == EFX_INT_MODE_LEGACY) {
-               efx->n_channels = 1 + (separate_tx_channels ? 1 : 0);
+               efx->n_channels = 1 + (efx_separate_tx_channels ? 1 : 0);
                efx->n_rx_channels = 1;
                efx->n_tx_channels = 1;
                efx->legacy_irq = efx->pci_dev->irq;
@@ -1426,10 +1473,15 @@ static int efx_probe_interrupts(struct efx_nic *efx)
        }
 
        /* RSS might be usable on VFs even if it is disabled on the PF */
-
-       efx->rss_spread = ((efx->n_rx_channels > 1 ||
-                           !efx->type->sriov_wanted(efx)) ?
-                          efx->n_rx_channels : efx_vf_size(efx));
+#ifdef CONFIG_SFC_SRIOV
+       if (efx->type->sriov_wanted) {
+               efx->rss_spread = ((efx->n_rx_channels > 1 ||
+                                   !efx->type->sriov_wanted(efx)) ?
+                                  efx->n_rx_channels : efx_vf_size(efx));
+               return 0;
+       }
+#endif
+       efx->rss_spread = efx->n_rx_channels;
 
        return 0;
 }
@@ -1573,7 +1625,8 @@ static void efx_set_channels(struct efx_nic *efx)
        struct efx_tx_queue *tx_queue;
 
        efx->tx_channel_offset =
-               separate_tx_channels ? efx->n_channels - efx->n_tx_channels : 0;
+               efx_separate_tx_channels ?
+               efx->n_channels - efx->n_tx_channels : 0;
 
        /* We need to mark which channels really have RX and TX
         * queues, and adjust the TX queue numbers if we have separate
@@ -1593,7 +1646,6 @@ static void efx_set_channels(struct efx_nic *efx)
 
 static int efx_probe_nic(struct efx_nic *efx)
 {
-       size_t i;
        int rc;
 
        netif_dbg(efx, probe, efx->net_dev, "creating NIC\n");
@@ -1603,23 +1655,39 @@ static int efx_probe_nic(struct efx_nic *efx)
        if (rc)
                return rc;
 
-       /* Determine the number of channels and queues by trying to hook
-        * in MSI-X interrupts. */
-       rc = efx_probe_interrupts(efx);
-       if (rc)
-               goto fail1;
+       do {
+               if (!efx->max_channels || !efx->max_tx_channels) {
+                       netif_err(efx, drv, efx->net_dev,
+                                 "Insufficient resources to allocate"
+                                 " any channels\n");
+                       rc = -ENOSPC;
+                       goto fail1;
+               }
+
+               /* Determine the number of channels and queues by trying
+                * to hook in MSI-X interrupts.
+                */
+               rc = efx_probe_interrupts(efx);
+               if (rc)
+                       goto fail1;
 
-       efx_set_channels(efx);
+               efx_set_channels(efx);
 
-       rc = efx->type->dimension_resources(efx);
-       if (rc)
-               goto fail2;
+               /* dimension_resources can fail with EAGAIN */
+               rc = efx->type->dimension_resources(efx);
+               if (rc != 0 && rc != -EAGAIN)
+                       goto fail2;
+
+               if (rc == -EAGAIN)
+                       /* try again with new max_channels */
+                       efx_remove_interrupts(efx);
+
+       } while (rc == -EAGAIN);
 
        if (efx->n_channels > 1)
-               netdev_rss_key_fill(&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->rss_spread);
+               netdev_rss_key_fill(&efx->rx_hash_key,
+                                   sizeof(efx->rx_hash_key));
+       efx_set_default_rx_indir_table(efx);
 
        netif_set_real_num_tx_queues(efx->net_dev, efx->n_tx_channels);
        netif_set_real_num_rx_queues(efx->net_dev, efx->n_rx_channels);
@@ -1650,10 +1718,11 @@ static int efx_probe_filters(struct efx_nic *efx)
        int rc;
 
        spin_lock_init(&efx->filter_lock);
-
+       init_rwsem(&efx->filter_sem);
+       down_write(&efx->filter_sem);
        rc = efx->type->filter_table_probe(efx);
        if (rc)
-               return rc;
+               goto out_unlock;
 
 #ifdef CONFIG_RFS_ACCEL
        if (efx->type->offload_features & NETIF_F_NTUPLE) {
@@ -1662,12 +1731,14 @@ static int efx_probe_filters(struct efx_nic *efx)
                                           GFP_KERNEL);
                if (!efx->rps_flow_id) {
                        efx->type->filter_table_remove(efx);
-                       return -ENOMEM;
+                       rc = -ENOMEM;
+                       goto out_unlock;
                }
        }
 #endif
-
-       return 0;
+out_unlock:
+       up_write(&efx->filter_sem);
+       return rc;
 }
 
 static void efx_remove_filters(struct efx_nic *efx)
@@ -1675,12 +1746,16 @@ static void efx_remove_filters(struct efx_nic *efx)
 #ifdef CONFIG_RFS_ACCEL
        kfree(efx->rps_flow_id);
 #endif
+       down_write(&efx->filter_sem);
        efx->type->filter_table_remove(efx);
+       up_write(&efx->filter_sem);
 }
 
 static void efx_restore_filters(struct efx_nic *efx)
 {
+       down_read(&efx->filter_sem);
        efx->type->filter_table_restore(efx);
+       up_read(&efx->filter_sem);
 }
 
 /**************************************************************************
@@ -1712,21 +1787,33 @@ static int efx_probe_all(struct efx_nic *efx)
        }
        efx->rxq_entries = efx->txq_entries = EFX_DEFAULT_DMAQ_SIZE;
 
+#ifdef CONFIG_SFC_SRIOV
+       rc = efx->type->vswitching_probe(efx);
+       if (rc) /* not fatal; the PF will still work fine */
+               netif_warn(efx, probe, efx->net_dev,
+                          "failed to setup vswitching rc=%d;"
+                          " VFs may not function\n", rc);
+#endif
+
        rc = efx_probe_filters(efx);
        if (rc) {
                netif_err(efx, probe, efx->net_dev,
                          "failed to create filter tables\n");
-               goto fail3;
+               goto fail4;
        }
 
        rc = efx_probe_channels(efx);
        if (rc)
-               goto fail4;
+               goto fail5;
 
        return 0;
 
- fail4:
+ fail5:
        efx_remove_filters(efx);
+ fail4:
+#ifdef CONFIG_SFC_SRIOV
+       efx->type->vswitching_remove(efx);
+#endif
  fail3:
        efx_remove_port(efx);
  fail2:
@@ -1816,6 +1903,9 @@ static void efx_remove_all(struct efx_nic *efx)
 {
        efx_remove_channels(efx);
        efx_remove_filters(efx);
+#ifdef CONFIG_SFC_SRIOV
+       efx->type->vswitching_remove(efx);
+#endif
        efx_remove_port(efx);
        efx_remove_nic(efx);
 }
@@ -1970,7 +2060,7 @@ static void efx_init_napi_channel(struct efx_channel *channel)
        netif_napi_add(channel->napi_dev, &channel->napi_str,
                       efx_poll, napi_weight);
        napi_hash_add(&channel->napi_str);
-       efx_channel_init_lock(channel);
+       efx_channel_busy_poll_init(channel);
 }
 
 static void efx_init_napi(struct efx_nic *efx)
@@ -2033,7 +2123,7 @@ static int efx_busy_poll(struct napi_struct *napi)
        if (!netif_running(efx->net_dev))
                return LL_FLUSH_FAILED;
 
-       if (!efx_channel_lock_poll(channel))
+       if (!efx_channel_try_lock_poll(channel))
                return LL_FLUSH_BUSY;
 
        old_rx_packets = channel->rx_queue.rx_packets;
@@ -2059,7 +2149,7 @@ static int efx_busy_poll(struct napi_struct *napi)
  *************************************************************************/
 
 /* Context: process, rtnl_lock() held. */
-static int efx_net_open(struct net_device *net_dev)
+int efx_net_open(struct net_device *net_dev)
 {
        struct efx_nic *efx = netdev_priv(net_dev);
        int rc;
@@ -2088,7 +2178,7 @@ static int efx_net_open(struct net_device *net_dev)
  * Note that the kernel will ignore our return code; this method
  * should really be a void.
  */
-static int efx_net_stop(struct net_device *net_dev)
+int efx_net_stop(struct net_device *net_dev)
 {
        struct efx_nic *efx = netdev_priv(net_dev);
 
@@ -2146,7 +2236,7 @@ static int efx_change_mtu(struct net_device *net_dev, int new_mtu)
 
        mutex_lock(&efx->mac_lock);
        net_dev->mtu = new_mtu;
-       efx->type->reconfigure_mac(efx);
+       efx_mac_reconfigure(efx);
        mutex_unlock(&efx->mac_lock);
 
        efx_start_all(efx);
@@ -2159,6 +2249,8 @@ static int efx_set_mac_address(struct net_device *net_dev, void *data)
        struct efx_nic *efx = netdev_priv(net_dev);
        struct sockaddr *addr = data;
        u8 *new_addr = addr->sa_data;
+       u8 old_addr[6];
+       int rc;
 
        if (!is_valid_ether_addr(new_addr)) {
                netif_err(efx, drv, efx->net_dev,
@@ -2167,12 +2259,20 @@ static int efx_set_mac_address(struct net_device *net_dev, void *data)
                return -EADDRNOTAVAIL;
        }
 
+       /* save old address */
+       ether_addr_copy(old_addr, net_dev->dev_addr);
        ether_addr_copy(net_dev->dev_addr, new_addr);
-       efx->type->sriov_mac_address_changed(efx);
+       if (efx->type->set_mac_address) {
+               rc = efx->type->set_mac_address(efx);
+               if (rc) {
+                       ether_addr_copy(net_dev->dev_addr, old_addr);
+                       return rc;
+               }
+       }
 
        /* Reconfigure the MAC */
        mutex_lock(&efx->mac_lock);
-       efx->type->reconfigure_mac(efx);
+       efx_mac_reconfigure(efx);
        mutex_unlock(&efx->mac_lock);
 
        return 0;
@@ -2199,7 +2299,7 @@ static int efx_set_features(struct net_device *net_dev, netdev_features_t data)
        return 0;
 }
 
-static const struct net_device_ops efx_farch_netdev_ops = {
+static const struct net_device_ops efx_netdev_ops = {
        .ndo_open               = efx_net_open,
        .ndo_stop               = efx_net_stop,
        .ndo_get_stats64        = efx_net_stats,
@@ -2212,10 +2312,12 @@ static const struct net_device_ops efx_farch_netdev_ops = {
        .ndo_set_rx_mode        = efx_set_rx_mode,
        .ndo_set_features       = efx_set_features,
 #ifdef CONFIG_SFC_SRIOV
-       .ndo_set_vf_mac         = efx_siena_sriov_set_vf_mac,
-       .ndo_set_vf_vlan        = efx_siena_sriov_set_vf_vlan,
-       .ndo_set_vf_spoofchk    = efx_siena_sriov_set_vf_spoofchk,
-       .ndo_get_vf_config      = efx_siena_sriov_get_vf_config,
+       .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,
+       .ndo_set_vf_link_state  = efx_sriov_set_vf_link_state,
+       .ndo_get_phys_port_id   = efx_sriov_get_phys_port_id,
 #endif
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller = efx_netpoll,
@@ -2229,29 +2331,6 @@ static const struct net_device_ops efx_farch_netdev_ops = {
 #endif
 };
 
-static const struct net_device_ops efx_ef10_netdev_ops = {
-       .ndo_open               = efx_net_open,
-       .ndo_stop               = efx_net_stop,
-       .ndo_get_stats64        = efx_net_stats,
-       .ndo_tx_timeout         = efx_watchdog,
-       .ndo_start_xmit         = efx_hard_start_xmit,
-       .ndo_validate_addr      = eth_validate_addr,
-       .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_rx_mode,
-       .ndo_set_features       = efx_set_features,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-       .ndo_poll_controller    = efx_netpoll,
-#endif
-#ifdef CONFIG_NET_RX_BUSY_POLL
-       .ndo_busy_poll          = efx_busy_poll,
-#endif
-#ifdef CONFIG_RFS_ACCEL
-       .ndo_rx_flow_steer      = efx_filter_rfs,
-#endif
-};
-
 static void efx_update_name(struct efx_nic *efx)
 {
        strcpy(efx->name, efx->net_dev->name);
@@ -2264,8 +2343,7 @@ static int efx_netdev_event(struct notifier_block *this,
 {
        struct net_device *net_dev = netdev_notifier_info_to_dev(ptr);
 
-       if ((net_dev->netdev_ops == &efx_farch_netdev_ops ||
-            net_dev->netdev_ops == &efx_ef10_netdev_ops) &&
+       if ((net_dev->netdev_ops == &efx_netdev_ops) &&
            event == NETDEV_CHANGENAME)
                efx_update_name(netdev_priv(net_dev));
 
@@ -2284,6 +2362,28 @@ show_phy_type(struct device *dev, struct device_attribute *attr, char *buf)
 }
 static DEVICE_ATTR(phy_type, 0444, show_phy_type, NULL);
 
+#ifdef CONFIG_SFC_MCDI_LOGGING
+static ssize_t show_mcdi_log(struct device *dev, struct device_attribute *attr,
+                            char *buf)
+{
+       struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev));
+       struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
+
+       return scnprintf(buf, PAGE_SIZE, "%d\n", mcdi->logging_enabled);
+}
+static ssize_t set_mcdi_log(struct device *dev, struct device_attribute *attr,
+                           const char *buf, size_t count)
+{
+       struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev));
+       struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
+       bool enable = count > 0 && *buf != '0';
+
+       mcdi->logging_enabled = enable;
+       return count;
+}
+static DEVICE_ATTR(mcdi_logging, 0644, show_mcdi_log, set_mcdi_log);
+#endif
+
 static int efx_register_netdev(struct efx_nic *efx)
 {
        struct net_device *net_dev = efx->net_dev;
@@ -2292,12 +2392,9 @@ static int efx_register_netdev(struct efx_nic *efx)
 
        net_dev->watchdog_timeo = 5 * HZ;
        net_dev->irq = efx->pci_dev->irq;
-       if (efx_nic_rev(efx) >= EFX_REV_HUNT_A0) {
-               net_dev->netdev_ops = &efx_ef10_netdev_ops;
+       net_dev->netdev_ops = &efx_netdev_ops;
+       if (efx_nic_rev(efx) >= EFX_REV_HUNT_A0)
                net_dev->priv_flags |= IFF_UNICAST_FLT;
-       } else {
-               net_dev->netdev_ops = &efx_farch_netdev_ops;
-       }
        net_dev->ethtool_ops = &efx_ethtool_ops;
        net_dev->gso_max_segs = EFX_TSO_MAX_SEGS;
 
@@ -2344,9 +2441,21 @@ static int efx_register_netdev(struct efx_nic *efx)
                          "failed to init net dev attributes\n");
                goto fail_registered;
        }
+#ifdef CONFIG_SFC_MCDI_LOGGING
+       rc = device_create_file(&efx->pci_dev->dev, &dev_attr_mcdi_logging);
+       if (rc) {
+               netif_err(efx, drv, efx->net_dev,
+                         "failed to init net dev attributes\n");
+               goto fail_attr_mcdi_logging;
+       }
+#endif
 
        return 0;
 
+#ifdef CONFIG_SFC_MCDI_LOGGING
+fail_attr_mcdi_logging:
+       device_remove_file(&efx->pci_dev->dev, &dev_attr_phy_type);
+#endif
 fail_registered:
        rtnl_lock();
        efx_dissociate(efx);
@@ -2365,13 +2474,14 @@ static void efx_unregister_netdev(struct efx_nic *efx)
 
        BUG_ON(netdev_priv(efx->net_dev) != efx);
 
-       strlcpy(efx->name, pci_name(efx->pci_dev), sizeof(efx->name));
-       device_remove_file(&efx->pci_dev->dev, &dev_attr_phy_type);
-
-       rtnl_lock();
-       unregister_netdevice(efx->net_dev);
-       efx->state = STATE_UNINIT;
-       rtnl_unlock();
+       if (efx_dev_registered(efx)) {
+               strlcpy(efx->name, pci_name(efx->pci_dev), sizeof(efx->name));
+#ifdef CONFIG_SFC_MCDI_LOGGING
+               device_remove_file(&efx->pci_dev->dev, &dev_attr_mcdi_logging);
+#endif
+               device_remove_file(&efx->pci_dev->dev, &dev_attr_phy_type);
+               unregister_netdev(efx->net_dev);
+       }
 }
 
 /**************************************************************************
@@ -2393,7 +2503,8 @@ void efx_reset_down(struct efx_nic *efx, enum reset_type method)
        efx_disable_interrupts(efx);
 
        mutex_lock(&efx->mac_lock);
-       if (efx->port_initialized && method != RESET_TYPE_INVISIBLE)
+       if (efx->port_initialized && method != RESET_TYPE_INVISIBLE &&
+           method != RESET_TYPE_DATAPATH)
                efx->phy_op->fini(efx);
        efx->type->fini(efx);
 }
@@ -2422,11 +2533,13 @@ int efx_reset_up(struct efx_nic *efx, enum reset_type method, bool ok)
        if (!ok)
                goto fail;
 
-       if (efx->port_initialized && method != RESET_TYPE_INVISIBLE) {
+       if (efx->port_initialized && method != RESET_TYPE_INVISIBLE &&
+           method != RESET_TYPE_DATAPATH) {
                rc = efx->phy_op->init(efx);
                if (rc)
                        goto fail;
-               if (efx->phy_op->reconfigure(efx))
+               rc = efx->phy_op->reconfigure(efx);
+               if (rc && rc != -EPERM)
                        netif_err(efx, drv, efx->net_dev,
                                  "could not restore PHY settings\n");
        }
@@ -2434,8 +2547,20 @@ int efx_reset_up(struct efx_nic *efx, enum reset_type method, bool ok)
        rc = efx_enable_interrupts(efx);
        if (rc)
                goto fail;
+
+#ifdef CONFIG_SFC_SRIOV
+       rc = efx->type->vswitching_restore(efx);
+       if (rc) /* not fatal; the PF will still work fine */
+               netif_warn(efx, probe, efx->net_dev,
+                          "failed to restore vswitching rc=%d;"
+                          " VFs may not function\n", rc);
+#endif
+
+       down_read(&efx->filter_sem);
        efx_restore_filters(efx);
-       efx->type->sriov_reset(efx);
+       up_read(&efx->filter_sem);
+       if (efx->type->sriov_reset)
+               efx->type->sriov_reset(efx);
 
        mutex_unlock(&efx->mac_lock);
 
@@ -2605,6 +2730,7 @@ void efx_schedule_reset(struct efx_nic *efx, enum reset_type type)
        case RESET_TYPE_WORLD:
        case RESET_TYPE_DISABLE:
        case RESET_TYPE_RECOVER_OR_DISABLE:
+       case RESET_TYPE_DATAPATH:
        case RESET_TYPE_MC_BIST:
        case RESET_TYPE_MCDI_TIMEOUT:
                method = type;
@@ -2655,6 +2781,8 @@ static const struct pci_device_id efx_pci_table[] = {
         .driver_data = (unsigned long) &siena_a0_nic_type},
        {PCI_DEVICE(PCI_VENDOR_ID_SOLARFLARE, 0x0903),  /* SFC9120 PF */
         .driver_data = (unsigned long) &efx_hunt_a0_nic_type},
+       {PCI_DEVICE(PCI_VENDOR_ID_SOLARFLARE, 0x1903),  /* SFC9120 VF */
+        .driver_data = (unsigned long) &efx_hunt_a0_vf_nic_type},
        {PCI_DEVICE(PCI_VENDOR_ID_SOLARFLARE, 0x0923),  /* SFC9140 PF */
         .driver_data = (unsigned long) &efx_hunt_a0_nic_type},
        {0}                     /* end of list */
@@ -2809,7 +2937,8 @@ static void efx_pci_remove_main(struct efx_nic *efx)
 }
 
 /* Final NIC shutdown
- * This is called only at module unload (or hotplug removal).
+ * This is called only at module unload (or hotplug removal).  A PF can call
+ * this on its VFs to ensure they are unbound first.
  */
 static void efx_pci_remove(struct pci_dev *pci_dev)
 {
@@ -2824,9 +2953,12 @@ static void efx_pci_remove(struct pci_dev *pci_dev)
        efx_dissociate(efx);
        dev_close(efx->net_dev);
        efx_disable_interrupts(efx);
+       efx->state = STATE_UNINIT;
        rtnl_unlock();
 
-       efx->type->sriov_fini(efx);
+       if (efx->type->sriov_fini)
+               efx->type->sriov_fini(efx);
+
        efx_unregister_netdev(efx);
 
        efx_mtd_remove(efx);
@@ -3008,7 +3140,8 @@ static int efx_pci_probe(struct pci_dev *pci_dev,
        netif_info(efx, probe, efx->net_dev,
                   "Solarflare NIC detected\n");
 
-       efx_probe_vpd_strings(efx);
+       if (!efx->type->is_vf)
+               efx_probe_vpd_strings(efx);
 
        /* Set up basic I/O (BAR mappings etc) */
        rc = efx_init_io(efx);
@@ -3023,10 +3156,12 @@ static int efx_pci_probe(struct pci_dev *pci_dev,
        if (rc)
                goto fail4;
 
-       rc = efx->type->sriov_init(efx);
-       if (rc)
-               netif_err(efx, probe, efx->net_dev,
-                         "SR-IOV can't be enabled rc %d\n", rc);
+       if (efx->type->sriov_init) {
+               rc = efx->type->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");
 
@@ -3058,6 +3193,26 @@ static int efx_pci_probe(struct pci_dev *pci_dev,
        return rc;
 }
 
+/* efx_pci_sriov_configure returns the actual number of Virtual Functions
+ * enabled on success
+ */
+#ifdef CONFIG_SFC_SRIOV
+static int efx_pci_sriov_configure(struct pci_dev *dev, int num_vfs)
+{
+       int rc;
+       struct efx_nic *efx = pci_get_drvdata(dev);
+
+       if (efx->type->sriov_configure) {
+               rc = efx->type->sriov_configure(efx, num_vfs);
+               if (rc)
+                       return rc;
+               else
+                       return num_vfs;
+       } else
+               return -EOPNOTSUPP;
+}
+#endif
+
 static int efx_pm_freeze(struct device *dev)
 {
        struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev));
@@ -3267,7 +3422,7 @@ out:
  * with our request for slot reset the mmio_enabled callback will never be
  * called, and the link_reset callback is not used by AER or EEH mechanisms.
  */
-static struct pci_error_handlers efx_err_handlers = {
+static const struct pci_error_handlers efx_err_handlers = {
        .error_detected = efx_io_error_detected,
        .slot_reset     = efx_io_slot_reset,
        .resume         = efx_io_resume,
@@ -3280,6 +3435,9 @@ static struct pci_driver efx_pci_driver = {
        .remove         = efx_pci_remove,
        .driver.pm      = &efx_pm_ops,
        .err_handler    = &efx_err_handlers,
+#ifdef CONFIG_SFC_SRIOV
+       .sriov_configure = efx_pci_sriov_configure,
+#endif
 };
 
 /**************************************************************************
@@ -3302,9 +3460,11 @@ static int __init efx_init_module(void)
        if (rc)
                goto err_notifier;
 
+#ifdef CONFIG_SFC_SRIOV
        rc = efx_init_sriov();
        if (rc)
                goto err_sriov;
+#endif
 
        reset_workqueue = create_singlethread_workqueue("sfc_reset");
        if (!reset_workqueue) {
@@ -3321,8 +3481,10 @@ static int __init efx_init_module(void)
  err_pci:
        destroy_workqueue(reset_workqueue);
  err_reset:
+#ifdef CONFIG_SFC_SRIOV
        efx_fini_sriov();
  err_sriov:
+#endif
        unregister_netdevice_notifier(&efx_netdev_notifier);
  err_notifier:
        return rc;
@@ -3334,7 +3496,9 @@ static void __exit efx_exit_module(void)
 
        pci_unregister_driver(&efx_pci_driver);
        destroy_workqueue(reset_workqueue);
+#ifdef CONFIG_SFC_SRIOV
        efx_fini_sriov();
+#endif
        unregister_netdevice_notifier(&efx_netdev_notifier);
 
 }