]> nv-tegra.nvidia Code Review - linux-2.6.git/blobdiff - drivers/net/sfc/efx.c
net: convert print_mac to %pM
[linux-2.6.git] / drivers / net / sfc / efx.c
index 7eb11d32debf9261eb695fbb85f07d7aeade14dd..5b05789f0b7934f836be336701dffc0bcfa11180 100644 (file)
@@ -140,8 +140,7 @@ static void efx_fini_channels(struct efx_nic *efx);
 
 #define EFX_ASSERT_RESET_SERIALISED(efx)               \
        do {                                            \
-               if ((efx->state == STATE_RUNNING) ||    \
-                   (efx->state == STATE_RESETTING))    \
+               if (efx->state == STATE_RUNNING)        \
                        ASSERT_RTNL();                  \
        } while (0)
 
@@ -158,16 +157,18 @@ static void efx_fini_channels(struct efx_nic *efx);
  * never be concurrently called more than once on the same channel,
  * though different channels may be being processed concurrently.
  */
-static inline int efx_process_channel(struct efx_channel *channel, int rx_quota)
+static int efx_process_channel(struct efx_channel *channel, int rx_quota)
 {
-       int rxdmaqs;
-       struct efx_rx_queue *rx_queue;
+       struct efx_nic *efx = channel->efx;
+       int rx_packets;
 
-       if (unlikely(channel->efx->reset_pending != RESET_TYPE_NONE ||
+       if (unlikely(efx->reset_pending != RESET_TYPE_NONE ||
                     !channel->enabled))
-               return rx_quota;
+               return 0;
 
-       rxdmaqs = falcon_process_eventq(channel, &rx_quota);
+       rx_packets = falcon_process_eventq(channel, rx_quota);
+       if (rx_packets == 0)
+               return 0;
 
        /* Deliver last RX packet. */
        if (channel->rx_pkt) {
@@ -179,16 +180,9 @@ static inline int efx_process_channel(struct efx_channel *channel, int rx_quota)
        efx_flush_lro(channel);
        efx_rx_strategy(channel);
 
-       /* Refill descriptor rings as necessary */
-       rx_queue = &channel->efx->rx_queue[0];
-       while (rxdmaqs) {
-               if (rxdmaqs & 0x01)
-                       efx_fast_push_rx_descriptors(rx_queue);
-               rx_queue++;
-               rxdmaqs >>= 1;
-       }
+       efx_fast_push_rx_descriptors(&efx->rx_queue[channel->channel]);
 
-       return rx_quota;
+       return rx_packets;
 }
 
 /* Mark channel as finished processing
@@ -218,14 +212,12 @@ static int efx_poll(struct napi_struct *napi, int budget)
        struct efx_channel *channel =
                container_of(napi, struct efx_channel, napi_str);
        struct net_device *napi_dev = channel->napi_dev;
-       int unused;
        int rx_packets;
 
        EFX_TRACE(channel->efx, "channel %d NAPI poll executing on CPU %d\n",
                  channel->channel, raw_smp_processor_id());
 
-       unused = efx_process_channel(channel, budget);
-       rx_packets = (budget - unused);
+       rx_packets = efx_process_channel(channel, budget);
 
        if (rx_packets < budget) {
                /* There is no race here; although napi_disable() will
@@ -259,7 +251,7 @@ void efx_process_channel_now(struct efx_channel *channel)
        falcon_disable_interrupts(efx);
        if (efx->legacy_irq)
                synchronize_irq(efx->legacy_irq);
-       if (channel->has_interrupt && channel->irq)
+       if (channel->irq)
                synchronize_irq(channel->irq);
 
        /* Wait for any NAPI processing to complete */
@@ -289,13 +281,13 @@ static int efx_probe_eventq(struct efx_channel *channel)
 }
 
 /* Prepare channel's event queue */
-static int efx_init_eventq(struct efx_channel *channel)
+static void efx_init_eventq(struct efx_channel *channel)
 {
        EFX_LOG(channel->efx, "chan %d init event queue\n", channel->channel);
 
        channel->eventq_read_ptr = 0;
 
-       return falcon_init_eventq(channel);
+       falcon_init_eventq(channel);
 }
 
 static void efx_fini_eventq(struct efx_channel *channel)
@@ -361,12 +353,11 @@ static int efx_probe_channel(struct efx_channel *channel)
  * to propagate configuration changes (mtu, checksum offload), or
  * to clear hardware error conditions
  */
-static int efx_init_channels(struct efx_nic *efx)
+static void efx_init_channels(struct efx_nic *efx)
 {
        struct efx_tx_queue *tx_queue;
        struct efx_rx_queue *rx_queue;
        struct efx_channel *channel;
-       int rc = 0;
 
        /* Calculate the rx buffer allocation parameters required to
         * support the current MTU, including padding for header
@@ -381,36 +372,20 @@ static int efx_init_channels(struct efx_nic *efx)
        efx_for_each_channel(channel, efx) {
                EFX_LOG(channel->efx, "init chan %d\n", channel->channel);
 
-               rc = efx_init_eventq(channel);
-               if (rc)
-                       goto err;
+               efx_init_eventq(channel);
 
-               efx_for_each_channel_tx_queue(tx_queue, channel) {
-                       rc = efx_init_tx_queue(tx_queue);
-                       if (rc)
-                               goto err;
-               }
+               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) {
-                       rc = efx_init_rx_queue(rx_queue);
-                       if (rc)
-                               goto err;
-               }
+               efx_for_each_channel_rx_queue(rx_queue, channel)
+                       efx_init_rx_queue(rx_queue);
 
                WARN_ON(channel->rx_pkt != NULL);
                efx_rx_strategy(channel);
        }
-
-       return 0;
-
- err:
-       EFX_ERR(efx, "failed to initialise channel %d\n",
-               channel ? channel->channel : -1);
-       efx_fini_channels(efx);
-       return rc;
 }
 
 /* This enables event queue processing and packet transmission.
@@ -470,10 +445,17 @@ static void efx_fini_channels(struct efx_nic *efx)
        struct efx_channel *channel;
        struct efx_tx_queue *tx_queue;
        struct efx_rx_queue *rx_queue;
+       int rc;
 
        EFX_ASSERT_RESET_SERIALISED(efx);
        BUG_ON(efx->port_enabled);
 
+       rc = falcon_flush_queues(efx);
+       if (rc)
+               EFX_ERR(efx, "failed to flush queues\n");
+       else
+               EFX_LOG(efx, "successfully flushed all queues\n");
+
        efx_for_each_channel(channel, efx) {
                EFX_LOG(channel->efx, "shut down chan %d\n", channel->channel);
 
@@ -481,13 +463,6 @@ static void efx_fini_channels(struct efx_nic *efx)
                        efx_fini_rx_queue(rx_queue);
                efx_for_each_channel_tx_queue(tx_queue, channel)
                        efx_fini_tx_queue(tx_queue);
-       }
-
-       /* Do the event queues last so that we can handle flush events
-        * for all DMA queues. */
-       efx_for_each_channel(channel, efx) {
-               EFX_LOG(channel->efx, "shut down evq %d\n", channel->channel);
-
                efx_fini_eventq(channel);
        }
 }
@@ -532,6 +507,11 @@ static void efx_link_status_changed(struct efx_nic *efx)
        if (!netif_running(efx->net_dev))
                return;
 
+       if (efx->port_inhibited) {
+               netif_carrier_off(efx->net_dev);
+               return;
+       }
+
        if (efx->link_up != netif_carrier_ok(efx->net_dev)) {
                efx->n_link_state_changes++;
 
@@ -573,13 +553,19 @@ static void efx_link_status_changed(struct efx_nic *efx)
 
 /* This call reinitialises the MAC to pick up new PHY settings. The
  * caller must hold the mac_lock */
-static void __efx_reconfigure_port(struct efx_nic *efx)
+void __efx_reconfigure_port(struct efx_nic *efx)
 {
        WARN_ON(!mutex_is_locked(&efx->mac_lock));
 
        EFX_LOG(efx, "reconfiguring MAC from PHY settings on CPU %d\n",
                raw_smp_processor_id());
 
+       /* 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);
+       }
+
        falcon_reconfigure_xmac(efx);
 
        /* Inform kernel of loss/gain of carrier */
@@ -626,17 +612,15 @@ static int efx_probe_port(struct efx_nic *efx)
        if (is_valid_ether_addr(efx->mac_address)) {
                memcpy(efx->net_dev->dev_addr, efx->mac_address, ETH_ALEN);
        } else {
-               DECLARE_MAC_BUF(mac);
-
-               EFX_ERR(efx, "invalid MAC address %s\n",
-                       print_mac(mac, efx->mac_address));
+               EFX_ERR(efx, "invalid MAC address %pM\n",
+                       efx->mac_address);
                if (!allow_bad_hwaddr) {
                        rc = -EINVAL;
                        goto err;
                }
                random_ether_addr(efx->net_dev->dev_addr);
-               EFX_INFO(efx, "using locally-generated MAC %s\n",
-                        print_mac(mac, efx->net_dev->dev_addr));
+               EFX_INFO(efx, "using locally-generated MAC %pM\n",
+                        efx->net_dev->dev_addr);
        }
 
        return 0;
@@ -658,6 +642,7 @@ static int efx_init_port(struct efx_nic *efx)
                return rc;
 
        efx->port_initialized = true;
+       efx->stats_enabled = true;
 
        /* Reconfigure port to program MAC registers */
        falcon_reconfigure_xmac(efx);
@@ -793,7 +778,7 @@ static int efx_init_io(struct efx_nic *efx)
        return 0;
 
  fail4:
-       release_mem_region(efx->membase_phys, efx->type->mem_map_size);
+       pci_release_region(efx->pci_dev, efx->type->mem_bar);
  fail3:
        efx->membase_phys = 0;
  fail2:
@@ -819,53 +804,61 @@ static void efx_fini_io(struct efx_nic *efx)
        pci_disable_device(efx->pci_dev);
 }
 
-/* Probe the number and type of interrupts we are able to obtain. */
+/* Get number of RX queues wanted.  Return number of online CPU
+ * packages in the expectation that an IRQ balancer will spread
+ * interrupts across them. */
+static int efx_wanted_rx_queues(void)
+{
+       cpumask_t core_mask;
+       int count;
+       int cpu;
+
+       cpus_clear(core_mask);
+       count = 0;
+       for_each_online_cpu(cpu) {
+               if (!cpu_isset(cpu, core_mask)) {
+                       ++count;
+                       cpus_or(core_mask, core_mask,
+                               topology_core_siblings(cpu));
+               }
+       }
+
+       return count;
+}
+
+/* Probe the number and type of interrupts we are able to obtain, and
+ * the resulting numbers of channels and RX queues.
+ */
 static void efx_probe_interrupts(struct efx_nic *efx)
 {
-       int max_channel = efx->type->phys_addr_channels - 1;
-       struct msix_entry xentries[EFX_MAX_CHANNELS];
+       int max_channels =
+               min_t(int, efx->type->phys_addr_channels, EFX_MAX_CHANNELS);
        int rc, i;
 
        if (efx->interrupt_mode == EFX_INT_MODE_MSIX) {
-               BUG_ON(!pci_find_capability(efx->pci_dev, PCI_CAP_ID_MSIX));
-
-               if (rss_cpus == 0) {
-                       cpumask_t core_mask;
-                       int cpu;
-
-                       cpus_clear(core_mask);
-                       efx->rss_queues = 0;
-                       for_each_online_cpu(cpu) {
-                               if (!cpu_isset(cpu, core_mask)) {
-                                       ++efx->rss_queues;
-                                       cpus_or(core_mask, core_mask,
-                                               topology_core_siblings(cpu));
-                               }
-                       }
-               } else {
-                       efx->rss_queues = rss_cpus;
-               }
+               struct msix_entry xentries[EFX_MAX_CHANNELS];
+               int wanted_ints;
 
-               efx->rss_queues = min(efx->rss_queues, max_channel + 1);
-               efx->rss_queues = min(efx->rss_queues, EFX_MAX_CHANNELS);
+               /* We want one RX queue and interrupt per CPU package
+                * (or as specified by the rss_cpus module parameter).
+                * We will need one channel per interrupt.
+                */
+               wanted_ints = rss_cpus ? rss_cpus : efx_wanted_rx_queues();
+               efx->n_rx_queues = min(wanted_ints, max_channels);
 
-               /* Request maximum number of MSI interrupts, and fill out
-                * the channel interrupt information the allowed allocation */
-               for (i = 0; i < efx->rss_queues; i++)
+               for (i = 0; i < efx->n_rx_queues; i++)
                        xentries[i].entry = i;
-               rc = pci_enable_msix(efx->pci_dev, xentries, efx->rss_queues);
+               rc = pci_enable_msix(efx->pci_dev, xentries, efx->n_rx_queues);
                if (rc > 0) {
-                       EFX_BUG_ON_PARANOID(rc >= efx->rss_queues);
-                       efx->rss_queues = rc;
+                       EFX_BUG_ON_PARANOID(rc >= efx->n_rx_queues);
+                       efx->n_rx_queues = rc;
                        rc = pci_enable_msix(efx->pci_dev, xentries,
-                                            efx->rss_queues);
+                                            efx->n_rx_queues);
                }
 
                if (rc == 0) {
-                       for (i = 0; i < efx->rss_queues; i++) {
-                               efx->channel[i].has_interrupt = true;
+                       for (i = 0; i < efx->n_rx_queues; i++)
                                efx->channel[i].irq = xentries[i].vector;
-                       }
                } else {
                        /* Fall back to single channel MSI */
                        efx->interrupt_mode = EFX_INT_MODE_MSI;
@@ -875,11 +868,10 @@ static void efx_probe_interrupts(struct efx_nic *efx)
 
        /* Try single interrupt MSI */
        if (efx->interrupt_mode == EFX_INT_MODE_MSI) {
-               efx->rss_queues = 1;
+               efx->n_rx_queues = 1;
                rc = pci_enable_msi(efx->pci_dev);
                if (rc == 0) {
                        efx->channel[0].irq = efx->pci_dev->irq;
-                       efx->channel[0].has_interrupt = true;
                } else {
                        EFX_ERR(efx, "could not enable MSI\n");
                        efx->interrupt_mode = EFX_INT_MODE_LEGACY;
@@ -888,10 +880,7 @@ static void efx_probe_interrupts(struct efx_nic *efx)
 
        /* Assume legacy interrupts */
        if (efx->interrupt_mode == EFX_INT_MODE_LEGACY) {
-               efx->rss_queues = 1;
-               /* Every channel is interruptible */
-               for (i = 0; i < EFX_MAX_CHANNELS; i++)
-                       efx->channel[i].has_interrupt = true;
+               efx->n_rx_queues = 1;
                efx->legacy_irq = efx->pci_dev->irq;
        }
 }
@@ -901,7 +890,7 @@ static void efx_remove_interrupts(struct efx_nic *efx)
        struct efx_channel *channel;
 
        /* Remove MSI/MSI-X interrupts */
-       efx_for_each_channel_with_interrupt(channel, efx)
+       efx_for_each_channel(channel, efx)
                channel->irq = 0;
        pci_disable_msi(efx->pci_dev);
        pci_disable_msix(efx->pci_dev);
@@ -910,14 +899,10 @@ static void efx_remove_interrupts(struct efx_nic *efx)
        efx->legacy_irq = 0;
 }
 
-/* Select number of used resources
- * Should be called after probe_interrupts()
- */
-static void efx_select_used(struct efx_nic *efx)
+static void efx_set_channels(struct efx_nic *efx)
 {
        struct efx_tx_queue *tx_queue;
        struct efx_rx_queue *rx_queue;
-       int i;
 
        efx_for_each_tx_queue(tx_queue, efx) {
                if (!EFX_INT_MODE_USE_MSI(efx) && separate_tx_and_rx_channels)
@@ -927,19 +912,9 @@ static void efx_select_used(struct efx_nic *efx)
                tx_queue->channel->used_flags |= EFX_USED_BY_TX;
        }
 
-       /* RX queues.  Each has a dedicated channel. */
-       for (i = 0; i < EFX_MAX_RX_QUEUES; i++) {
-               rx_queue = &efx->rx_queue[i];
-
-               if (i < efx->rss_queues) {
-                       rx_queue->used = true;
-                       /* If we allow multiple RX queues per channel
-                        * we need to decide that here
-                        */
-                       rx_queue->channel = &efx->channel[rx_queue->queue];
-                       rx_queue->channel->used_flags |= EFX_USED_BY_RX;
-                       rx_queue++;
-               }
+       efx_for_each_rx_queue(rx_queue, efx) {
+               rx_queue->channel = &efx->channel[rx_queue->queue];
+               rx_queue->channel->used_flags |= EFX_USED_BY_RX;
        }
 }
 
@@ -958,8 +933,7 @@ static int efx_probe_nic(struct efx_nic *efx)
         * in MSI-X interrupts. */
        efx_probe_interrupts(efx);
 
-       /* Determine number of RX queues and TX queues */
-       efx_select_used(efx);
+       efx_set_channels(efx);
 
        /* Initialise the interrupt moderation settings */
        efx_init_irq_moderation(efx, tx_irq_mod_usec, rx_irq_mod_usec);
@@ -1045,7 +1019,8 @@ static void efx_start_all(struct efx_nic *efx)
        /* 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);
-       efx_wake_queue(efx);
+       if (efx_dev_registered(efx))
+               efx_wake_queue(efx);
 
        efx_for_each_channel(channel, efx)
                efx_start_channel(channel);
@@ -1096,7 +1071,7 @@ static void efx_stop_all(struct efx_nic *efx)
        falcon_disable_interrupts(efx);
        if (efx->legacy_irq)
                synchronize_irq(efx->legacy_irq);
-       efx_for_each_channel_with_interrupt(channel, efx) {
+       efx_for_each_channel(channel, efx) {
                if (channel->irq)
                        synchronize_irq(channel->irq);
        }
@@ -1115,13 +1090,12 @@ static void efx_stop_all(struct efx_nic *efx)
 
        /* Isolate the MAC from the TX and RX engines, so that queue
         * flushes will complete in a timely fashion. */
-       falcon_deconfigure_mac_wrapper(efx);
        falcon_drain_tx_fifo(efx);
 
        /* Stop the kernel transmit interface late, so the watchdog
         * timer isn't ticking over the flush */
-       efx_stop_queue(efx);
        if (efx_dev_registered(efx)) {
+               efx_stop_queue(efx);
                netif_tx_lock_bh(efx->net_dev);
                netif_tx_unlock_bh(efx->net_dev);
        }
@@ -1138,24 +1112,16 @@ static void efx_remove_all(struct efx_nic *efx)
 }
 
 /* A convinience function to safely flush all the queues */
-int efx_flush_queues(struct efx_nic *efx)
+void efx_flush_queues(struct efx_nic *efx)
 {
-       int rc;
-
        EFX_ASSERT_RESET_SERIALISED(efx);
 
        efx_stop_all(efx);
 
        efx_fini_channels(efx);
-       rc = efx_init_channels(efx);
-       if (rc) {
-               efx_schedule_reset(efx, RESET_TYPE_DISABLE);
-               return rc;
-       }
+       efx_init_channels(efx);
 
        efx_start_all(efx);
-
-       return 0;
 }
 
 /**************************************************************************
@@ -1293,7 +1259,7 @@ static void efx_netpoll(struct net_device *net_dev)
        struct efx_nic *efx = netdev_priv(net_dev);
        struct efx_channel *channel;
 
-       efx_for_each_channel_with_interrupt(channel, efx)
+       efx_for_each_channel(channel, efx)
                efx_schedule_channel(channel);
 }
 
@@ -1314,6 +1280,9 @@ static int efx_net_open(struct net_device *net_dev)
        EFX_LOG(efx, "opening device %s on CPU %d\n", net_dev->name,
                raw_smp_processor_id());
 
+       if (efx->phy_mode & PHY_MODE_SPECIAL)
+               return -EBUSY;
+
        efx_start_all(efx);
        return 0;
 }
@@ -1325,7 +1294,6 @@ static int efx_net_open(struct net_device *net_dev)
 static int efx_net_stop(struct net_device *net_dev)
 {
        struct efx_nic *efx = netdev_priv(net_dev);
-       int rc;
 
        EFX_LOG(efx, "closing %s on CPU %d\n", net_dev->name,
                raw_smp_processor_id());
@@ -1333,9 +1301,7 @@ static int efx_net_stop(struct net_device *net_dev)
        /* Stop the device and flush all the channels */
        efx_stop_all(efx);
        efx_fini_channels(efx);
-       rc = efx_init_channels(efx);
-       if (rc)
-               efx_schedule_reset(efx, RESET_TYPE_DISABLE);
+       efx_init_channels(efx);
 
        return 0;
 }
@@ -1353,7 +1319,7 @@ static struct net_device_stats *efx_net_stats(struct net_device *net_dev)
         */
        if (!spin_trylock(&efx->stats_lock))
                return stats;
-       if (efx->state == STATE_RUNNING) {
+       if (efx->stats_enabled) {
                falcon_update_stats_xmac(efx);
                falcon_update_nic_stats(efx);
        }
@@ -1418,16 +1384,10 @@ static int efx_change_mtu(struct net_device *net_dev, int new_mtu)
 
        efx_fini_channels(efx);
        net_dev->mtu = new_mtu;
-       rc = efx_init_channels(efx);
-       if (rc)
-               goto fail;
+       efx_init_channels(efx);
 
        efx_start_all(efx);
        return rc;
-
- fail:
-       efx_schedule_reset(efx, RESET_TYPE_DISABLE);
-       return rc;
 }
 
 static int efx_set_mac_address(struct net_device *net_dev, void *data)
@@ -1439,9 +1399,8 @@ static int efx_set_mac_address(struct net_device *net_dev, void *data)
        EFX_ASSERT_RESET_SERIALISED(efx);
 
        if (!is_valid_ether_addr(new_addr)) {
-               DECLARE_MAC_BUF(mac);
-               EFX_ERR(efx, "invalid ethernet MAC address requested: %s\n",
-                       print_mac(mac, new_addr));
+               EFX_ERR(efx, "invalid ethernet MAC address requested: %pM\n",
+                       new_addr);
                return -EINVAL;
        }
 
@@ -1453,26 +1412,19 @@ static int efx_set_mac_address(struct net_device *net_dev, void *data)
        return 0;
 }
 
-/* Context: netif_tx_lock held, BHs disabled. */
+/* Context: netif_addr_lock held, BHs disabled. */
 static void efx_set_multicast_list(struct net_device *net_dev)
 {
        struct efx_nic *efx = netdev_priv(net_dev);
        struct dev_mc_list *mc_list = net_dev->mc_list;
        union efx_multicast_hash *mc_hash = &efx->multicast_hash;
-       bool promiscuous;
+       bool promiscuous = !!(net_dev->flags & IFF_PROMISC);
+       bool changed = (efx->promiscuous != promiscuous);
        u32 crc;
        int bit;
        int i;
 
-       /* Set per-MAC promiscuity flag and reconfigure MAC if necessary */
-       promiscuous = !!(net_dev->flags & IFF_PROMISC);
-       if (efx->promiscuous != promiscuous) {
-               efx->promiscuous = promiscuous;
-               /* Close the window between efx_stop_port() and efx_flush_all()
-                * by only queuing work when the port is enabled. */
-               if (efx->port_enabled)
-                       queue_work(efx->workqueue, &efx->reconfigure_work);
-       }
+       efx->promiscuous = promiscuous;
 
        /* Build multicast hash table */
        if (promiscuous || (net_dev->flags & IFF_ALLMULTI)) {
@@ -1487,6 +1439,13 @@ static void efx_set_multicast_list(struct net_device *net_dev)
                }
        }
 
+       if (!efx->port_enabled)
+               /* Delay pushing settings until efx_start_port() */
+               return;
+
+       if (changed)
+               queue_work(efx->workqueue, &efx->reconfigure_work);
+
        /* Create and activate new global multicast hash table */
        falcon_set_multicast_hash(efx);
 }
@@ -1575,49 +1534,60 @@ static void efx_unregister_netdev(struct efx_nic *efx)
  *
  **************************************************************************/
 
-/* The final hardware and software finalisation before reset. */
-static int efx_reset_down(struct efx_nic *efx, struct ethtool_cmd *ecmd)
+/* Tears down the entire software state and most of the hardware state
+ * before reset.  */
+void efx_reset_down(struct efx_nic *efx, struct ethtool_cmd *ecmd)
 {
        int rc;
 
        EFX_ASSERT_RESET_SERIALISED(efx);
 
+       /* The net_dev->get_stats handler is quite slow, and will fail
+        * if a fetch is pending over reset. Serialise against it. */
+       spin_lock(&efx->stats_lock);
+       efx->stats_enabled = false;
+       spin_unlock(&efx->stats_lock);
+
+       efx_stop_all(efx);
+       mutex_lock(&efx->mac_lock);
+
        rc = falcon_xmac_get_settings(efx, ecmd);
-       if (rc) {
+       if (rc)
                EFX_ERR(efx, "could not back up PHY settings\n");
-               goto fail;
-       }
 
        efx_fini_channels(efx);
-       return 0;
-
- fail:
-       return rc;
 }
 
-/* The first part of software initialisation after a hardware reset
- * This function does not handle serialisation with the kernel, it
- * assumes the caller has done this */
-static int efx_reset_up(struct efx_nic *efx, struct ethtool_cmd *ecmd)
+/* This function will always ensure that the locks acquired in
+ * efx_reset_down() are released. A failure return code indicates
+ * that we were unable to reinitialise the hardware, and the
+ * driver should be disabled. If ok is false, then the rx and tx
+ * engines are not restarted, pending a RESET_DISABLE. */
+int efx_reset_up(struct efx_nic *efx, struct ethtool_cmd *ecmd, bool ok)
 {
        int rc;
 
-       rc = efx_init_channels(efx);
-       if (rc)
-               goto fail1;
+       EFX_ASSERT_RESET_SERIALISED(efx);
 
-       /* Restore MAC and PHY settings. */
-       rc = falcon_xmac_set_settings(efx, ecmd);
+       rc = falcon_init_nic(efx);
        if (rc) {
-               EFX_ERR(efx, "could not restore PHY settings\n");
-               goto fail2;
+               EFX_ERR(efx, "failed to initialise NIC\n");
+               ok = false;
        }
 
-       return 0;
+       if (ok) {
+               efx_init_channels(efx);
 
- fail2:
-       efx_fini_channels(efx);
- fail1:
+               if (falcon_xmac_set_settings(efx, ecmd))
+                       EFX_ERR(efx, "could not restore PHY settings\n");
+       }
+
+       mutex_unlock(&efx->mac_lock);
+
+       if (ok) {
+               efx_start_all(efx);
+               efx->stats_enabled = true;
+       }
        return rc;
 }
 
@@ -1646,25 +1616,14 @@ static int efx_reset(struct efx_nic *efx)
                goto unlock_rtnl;
        }
 
-       efx->state = STATE_RESETTING;
        EFX_INFO(efx, "resetting (%d)\n", method);
 
-       /* The net_dev->get_stats handler is quite slow, and will fail
-        * if a fetch is pending over reset. Serialise against it. */
-       spin_lock(&efx->stats_lock);
-       spin_unlock(&efx->stats_lock);
-
-       efx_stop_all(efx);
-       mutex_lock(&efx->mac_lock);
-
-       rc = efx_reset_down(efx, &ecmd);
-       if (rc)
-               goto fail1;
+       efx_reset_down(efx, &ecmd);
 
        rc = falcon_reset_hw(efx, method);
        if (rc) {
                EFX_ERR(efx, "failed to reset hardware\n");
-               goto fail2;
+               goto fail;
        }
 
        /* Allow resets to be rescheduled. */
@@ -1676,46 +1635,27 @@ static int efx_reset(struct efx_nic *efx)
         * can respond to requests. */
        pci_set_master(efx->pci_dev);
 
-       /* Reinitialise device. This is appropriate in the RESET_TYPE_DISABLE
-        * case so the driver can talk to external SRAM */
-       rc = falcon_init_nic(efx);
-       if (rc) {
-               EFX_ERR(efx, "failed to initialise NIC\n");
-               goto fail3;
-       }
-
        /* Leave device stopped if necessary */
        if (method == RESET_TYPE_DISABLE) {
-               /* Reinitialise the device anyway so the driver unload sequence
-                * can talk to the external SRAM */
-               falcon_init_nic(efx);
                rc = -EIO;
-               goto fail4;
+               goto fail;
        }
 
-       rc = efx_reset_up(efx, &ecmd);
+       rc = efx_reset_up(efx, &ecmd, true);
        if (rc)
-               goto fail5;
+               goto disable;
 
-       mutex_unlock(&efx->mac_lock);
        EFX_LOG(efx, "reset complete\n");
-
-       efx->state = STATE_RUNNING;
-       efx_start_all(efx);
-
  unlock_rtnl:
        rtnl_unlock();
        return 0;
 
- fail5:
- fail4:
- fail3:
- fail2:
- fail1:
+ fail:
+       efx_reset_up(efx, &ecmd, false);
+ disable:
        EFX_ERR(efx, "has been disabled\n");
        efx->state = STATE_DISABLED;
 
-       mutex_unlock(&efx->mac_lock);
        rtnl_unlock();
        efx_unregister_netdev(efx);
        efx_fini_port(efx);
@@ -1788,7 +1728,7 @@ static struct pci_device_id efx_pci_table[] __devinitdata = {
  *
  * Dummy PHY/MAC/Board operations
  *
- * Can be used where the MAC does not implement this operation
+ * Can be used for some unimplemented operations
  * Needed so all function pointers are valid and do not have to be tested
  * before use
  *
@@ -1806,20 +1746,14 @@ static struct efx_phy_operations efx_dummy_phy_operations = {
        .check_hw        = efx_port_dummy_op_int,
        .fini            = efx_port_dummy_op_void,
        .clear_interrupt = efx_port_dummy_op_void,
-       .reset_xaui      = efx_port_dummy_op_void,
 };
 
-/* Dummy board operations */
-static int efx_nic_dummy_op_int(struct efx_nic *nic)
-{
-       return 0;
-}
-
 static struct efx_board efx_dummy_board_info = {
-       .init    = efx_nic_dummy_op_int,
-       .init_leds = efx_port_dummy_op_int,
-       .set_fault_led = efx_port_dummy_op_blink,
-       .fini   = efx_port_dummy_op_void,
+       .init           = efx_port_dummy_op_int,
+       .init_leds      = efx_port_dummy_op_int,
+       .set_fault_led  = efx_port_dummy_op_blink,
+       .blink          = efx_port_dummy_op_blink,
+       .fini           = efx_port_dummy_op_void,
 };
 
 /**************************************************************************
@@ -1865,7 +1799,6 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type,
                channel = &efx->channel[i];
                channel->efx = efx;
                channel->channel = i;
-               channel->evqnum = i;
                channel->work_pending = false;
        }
        for (i = 0; i < EFX_TX_QUEUE_COUNT; i++) {
@@ -2043,19 +1976,16 @@ static int efx_pci_probe_main(struct efx_nic *efx)
                goto fail5;
        }
 
-       rc = efx_init_channels(efx);
-       if (rc)
-               goto fail6;
+       efx_init_channels(efx);
 
        rc = falcon_init_interrupt(efx);
        if (rc)
-               goto fail7;
+               goto fail6;
 
        return 0;
 
- fail7:
-       efx_fini_channels(efx);
  fail6:
+       efx_fini_channels(efx);
        efx_fini_port(efx);
  fail5:
  fail4:
@@ -2092,6 +2022,9 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev,
                              NETIF_F_HIGHDMA | NETIF_F_TSO);
        if (lro)
                net_dev->features |= NETIF_F_LRO;
+       /* Mask for features that also apply to VLAN devices */
+       net_dev->vlan_features |= (NETIF_F_ALL_CSUM | NETIF_F_SG |
+                                  NETIF_F_HIGHDMA | NETIF_F_TSO);
        efx = netdev_priv(net_dev);
        pci_set_drvdata(pci_dev, efx);
        rc = efx_init_struct(efx, type, pci_dev, net_dev);