]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - drivers/net/sfc/efx.c
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[net-next-2.6.git] / drivers / net / sfc / efx.c
index 649a264d6a81b80ee35f54850fce49a4545565c1..26b0cc2192047fd1263f4874fc349780564e79f8 100644 (file)
@@ -27,6 +27,7 @@
 #include "nic.h"
 
 #include "mcdi.h"
+#include "workarounds.h"
 
 /**************************************************************************
  *
@@ -92,13 +93,6 @@ const char *efx_reset_type_names[] = {
 
 #define EFX_MAX_MTU (9 * 1024)
 
-/* RX slow fill workqueue. If memory allocation fails in the fast path,
- * a work item is pushed onto this work queue to retry the allocation later,
- * to avoid the NIC being starved of RX buffers. Since this is a per cpu
- * workqueue, there is nothing to be gained in making it per NIC
- */
-static struct workqueue_struct *refill_workqueue;
-
 /* Reset workqueue. If any NIC has a hardware failure then a reset will be
  * queued onto this work queue. This is not a per-nic work queue, because
  * efx_reset_work() acquires the rtnl lock, so resets are naturally serialised.
@@ -225,17 +219,17 @@ 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 int efx_process_channel(struct efx_channel *channel, int rx_quota)
+static int efx_process_channel(struct efx_channel *channel, int budget)
 {
        struct efx_nic *efx = channel->efx;
-       int rx_packets;
+       int spent;
 
        if (unlikely(efx->reset_pending != RESET_TYPE_NONE ||
                     !channel->enabled))
                return 0;
 
-       rx_packets = efx_nic_process_eventq(channel, rx_quota);
-       if (rx_packets == 0)
+       spent = efx_nic_process_eventq(channel, budget);
+       if (spent == 0)
                return 0;
 
        /* Deliver last RX packet. */
@@ -249,7 +243,7 @@ static int efx_process_channel(struct efx_channel *channel, int rx_quota)
 
        efx_fast_push_rx_descriptors(&efx->rx_queue[channel->channel]);
 
-       return rx_packets;
+       return spent;
 }
 
 /* Mark channel as finished processing
@@ -278,17 +272,17 @@ static int efx_poll(struct napi_struct *napi, int budget)
 {
        struct efx_channel *channel =
                container_of(napi, struct efx_channel, napi_str);
-       int rx_packets;
+       int spent;
 
        EFX_TRACE(channel->efx, "channel %d NAPI poll executing on CPU %d\n",
                  channel->channel, raw_smp_processor_id());
 
-       rx_packets = efx_process_channel(channel, budget);
+       spent = efx_process_channel(channel, budget);
 
-       if (rx_packets < budget) {
+       if (spent < budget) {
                struct efx_nic *efx = channel->efx;
 
-               if (channel->used_flags & EFX_USED_BY_RX &&
+               if (channel->channel < efx->n_rx_channels &&
                    efx->irq_rx_adaptive &&
                    unlikely(++channel->irq_count == 1000)) {
                        if (unlikely(channel->irq_mod_score <
@@ -318,7 +312,7 @@ static int efx_poll(struct napi_struct *napi, int budget)
                efx_channel_processed(channel);
        }
 
-       return rx_packets;
+       return spent;
 }
 
 /* Process the eventq of the specified channel immediately on this CPU
@@ -333,7 +327,6 @@ void efx_process_channel_now(struct efx_channel *channel)
 {
        struct efx_nic *efx = channel->efx;
 
-       BUG_ON(!channel->used_flags);
        BUG_ON(!channel->enabled);
 
        /* Disable interrupts and wait for ISRs to complete */
@@ -446,12 +439,12 @@ static void efx_set_channel_names(struct efx_nic *efx)
 
        efx_for_each_channel(channel, efx) {
                number = channel->channel;
-               if (efx->n_channels > efx->n_rx_queues) {
-                       if (channel->channel < efx->n_rx_queues) {
+               if (efx->n_channels > efx->n_rx_channels) {
+                       if (channel->channel < efx->n_rx_channels) {
                                type = "-rx";
                        } else {
                                type = "-tx";
-                               number -= efx->n_rx_queues;
+                               number -= efx->n_rx_channels;
                        }
                }
                snprintf(channel->name, sizeof(channel->name),
@@ -476,7 +469,8 @@ static void efx_init_channels(struct efx_nic *efx)
        efx->rx_buffer_len = (max(EFX_PAGE_IP_ALIGN, NET_IP_ALIGN) +
                              EFX_MAX_FRAME_LEN(efx->net_dev->mtu) +
                              efx->type->rx_buffer_padding);
-       efx->rx_buffer_order = get_order(efx->rx_buffer_len);
+       efx->rx_buffer_order = get_order(efx->rx_buffer_len +
+                                        sizeof(struct efx_rx_page_state));
 
        /* Initialise the channels */
        efx_for_each_channel(channel, efx) {
@@ -516,11 +510,11 @@ static void efx_start_channel(struct efx_channel *channel)
        channel->enabled = true;
        smp_wmb();
 
-       napi_enable(&channel->napi_str);
-
-       /* Load up RX descriptors */
+       /* Fill the queues before enabling NAPI */
        efx_for_each_channel_rx_queue(rx_queue, channel)
                efx_fast_push_rx_descriptors(rx_queue);
+
+       napi_enable(&channel->napi_str);
 }
 
 /* This disables event queue processing and packet transmission.
@@ -529,8 +523,6 @@ static void efx_start_channel(struct efx_channel *channel)
  */
 static void efx_stop_channel(struct efx_channel *channel)
 {
-       struct efx_rx_queue *rx_queue;
-
        if (!channel->enabled)
                return;
 
@@ -538,12 +530,6 @@ static void efx_stop_channel(struct efx_channel *channel)
 
        channel->enabled = false;
        napi_disable(&channel->napi_str);
-
-       /* Ensure that any worker threads have exited or will be no-ops */
-       efx_for_each_channel_rx_queue(rx_queue, channel) {
-               spin_lock_bh(&rx_queue->add_lock);
-               spin_unlock_bh(&rx_queue->add_lock);
-       }
 }
 
 static void efx_fini_channels(struct efx_nic *efx)
@@ -557,10 +543,18 @@ static void efx_fini_channels(struct efx_nic *efx)
        BUG_ON(efx->port_enabled);
 
        rc = efx_nic_flush_queues(efx);
-       if (rc)
+       if (rc && EFX_WORKAROUND_7803(efx)) {
+               /* Schedule a reset to recover from the flush failure. The
+                * descriptor caches reference memory we're about to free,
+                * but falcon_reconfigure_mac_wrapper() won't reconnect
+                * the MACs because of the pending reset. */
+               EFX_ERR(efx, "Resetting to recover from flush failure\n");
+               efx_schedule_reset(efx, RESET_TYPE_ALL);
+       } else if (rc) {
                EFX_ERR(efx, "failed to flush queues\n");
-       else
+       } 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);
@@ -585,13 +579,11 @@ static void efx_remove_channel(struct efx_channel *channel)
        efx_for_each_channel_tx_queue(tx_queue, channel)
                efx_remove_tx_queue(tx_queue);
        efx_remove_eventq(channel);
-
-       channel->used_flags = 0;
 }
 
-void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue, int delay)
+void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue)
 {
-       queue_delayed_work(refill_workqueue, &rx_queue->work, delay);
+       mod_timer(&rx_queue->slow_fill, jiffies + msecs_to_jiffies(100));
 }
 
 /**************************************************************************
@@ -956,10 +948,9 @@ static void efx_fini_io(struct efx_nic *efx)
        pci_disable_device(efx->pci_dev);
 }
 
-/* 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)
+/* 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)
 {
        cpumask_var_t core_mask;
        int count;
@@ -995,34 +986,39 @@ static void efx_probe_interrupts(struct efx_nic *efx)
 
        if (efx->interrupt_mode == EFX_INT_MODE_MSIX) {
                struct msix_entry xentries[EFX_MAX_CHANNELS];
-               int wanted_ints;
-               int rx_queues;
+               int n_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.
-                */
-               rx_queues = rss_cpus ? rss_cpus : efx_wanted_rx_queues();
-               wanted_ints = rx_queues + (separate_tx_channels ? 1 : 0);
-               wanted_ints = min(wanted_ints, max_channels);
+               n_channels = efx_wanted_channels();
+               if (separate_tx_channels)
+                       n_channels *= 2;
+               n_channels = min(n_channels, max_channels);
 
-               for (i = 0; i < wanted_ints; i++)
+               for (i = 0; i < n_channels; i++)
                        xentries[i].entry = i;
-               rc = pci_enable_msix(efx->pci_dev, xentries, wanted_ints);
+               rc = pci_enable_msix(efx->pci_dev, xentries, n_channels);
                if (rc > 0) {
                        EFX_ERR(efx, "WARNING: Insufficient MSI-X vectors"
-                               " available (%d < %d).\n", rc, wanted_ints);
+                               " available (%d < %d).\n", rc, n_channels);
                        EFX_ERR(efx, "WARNING: Performance may be reduced.\n");
-                       EFX_BUG_ON_PARANOID(rc >= wanted_ints);
-                       wanted_ints = rc;
+                       EFX_BUG_ON_PARANOID(rc >= n_channels);
+                       n_channels = rc;
                        rc = pci_enable_msix(efx->pci_dev, xentries,
-                                            wanted_ints);
+                                            n_channels);
                }
 
                if (rc == 0) {
-                       efx->n_rx_queues = min(rx_queues, wanted_ints);
-                       efx->n_channels = wanted_ints;
-                       for (i = 0; i < wanted_ints; i++)
+                       efx->n_channels = n_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);
+                       } else {
+                               efx->n_tx_channels = efx->n_channels;
+                               efx->n_rx_channels = efx->n_channels;
+                       }
+                       for (i = 0; i < n_channels; i++)
                                efx->channel[i].irq = xentries[i].vector;
                } else {
                        /* Fall back to single channel MSI */
@@ -1033,8 +1029,9 @@ static void efx_probe_interrupts(struct efx_nic *efx)
 
        /* Try single interrupt MSI */
        if (efx->interrupt_mode == EFX_INT_MODE_MSI) {
-               efx->n_rx_queues = 1;
                efx->n_channels = 1;
+               efx->n_rx_channels = 1;
+               efx->n_tx_channels = 1;
                rc = pci_enable_msi(efx->pci_dev);
                if (rc == 0) {
                        efx->channel[0].irq = efx->pci_dev->irq;
@@ -1046,8 +1043,9 @@ static void efx_probe_interrupts(struct efx_nic *efx)
 
        /* Assume legacy interrupts */
        if (efx->interrupt_mode == EFX_INT_MODE_LEGACY) {
-               efx->n_rx_queues = 1;
                efx->n_channels = 1 + (separate_tx_channels ? 1 : 0);
+               efx->n_rx_channels = 1;
+               efx->n_tx_channels = 1;
                efx->legacy_irq = efx->pci_dev->irq;
        }
 }
@@ -1068,21 +1066,24 @@ static void efx_remove_interrupts(struct efx_nic *efx)
 
 static void efx_set_channels(struct efx_nic *efx)
 {
+       struct efx_channel *channel;
        struct efx_tx_queue *tx_queue;
        struct efx_rx_queue *rx_queue;
+       unsigned tx_channel_offset =
+               separate_tx_channels ? efx->n_channels - efx->n_tx_channels : 0;
 
-       efx_for_each_tx_queue(tx_queue, efx) {
-               if (separate_tx_channels)
-                       tx_queue->channel = &efx->channel[efx->n_channels-1];
-               else
-                       tx_queue->channel = &efx->channel[0];
-               tx_queue->channel->used_flags |= EFX_USED_BY_TX;
+       efx_for_each_channel(channel, efx) {
+               if (channel->channel - tx_channel_offset < efx->n_tx_channels) {
+                       channel->tx_queue = &efx->tx_queue[
+                               (channel->channel - tx_channel_offset) *
+                               EFX_TXQ_TYPES];
+                       efx_for_each_channel_tx_queue(tx_queue, channel)
+                               tx_queue->channel = channel;
+               }
        }
 
-       efx_for_each_rx_queue(rx_queue, efx) {
+       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;
-       }
 }
 
 static int efx_probe_nic(struct efx_nic *efx)
@@ -1096,11 +1097,12 @@ static int efx_probe_nic(struct efx_nic *efx)
        if (rc)
                return rc;
 
-       /* Determine the number of channels and RX queues by trying to hook
+       /* Determine the number of channels and queues by trying to hook
         * in MSI-X interrupts. */
        efx_probe_interrupts(efx);
 
        efx_set_channels(efx);
+       efx->net_dev->real_num_tx_queues = efx->n_tx_channels;
 
        /* Initialise the interrupt moderation settings */
        efx_init_irq_moderation(efx, tx_irq_mod_usec, rx_irq_mod_usec, true);
@@ -1187,11 +1189,12 @@ 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);
-       if (efx_dev_registered(efx))
-               efx_wake_queue(efx);
 
-       efx_for_each_channel(channel, efx)
+       efx_for_each_channel(channel, efx) {
+               if (efx_dev_registered(efx))
+                       efx_wake_queue(channel);
                efx_start_channel(channel);
+       }
 
        efx_nic_enable_interrupts(efx);
 
@@ -1225,15 +1228,8 @@ static void efx_start_all(struct efx_nic *efx)
  * since we're holding the rtnl_lock at this point. */
 static void efx_flush_all(struct efx_nic *efx)
 {
-       struct efx_rx_queue *rx_queue;
-
        /* Make sure the hardware monitor is stopped */
        cancel_delayed_work_sync(&efx->monitor_work);
-
-       /* Ensure that all RX slow refills are complete. */
-       efx_for_each_rx_queue(rx_queue, efx)
-               cancel_delayed_work_sync(&rx_queue->work);
-
        /* Stop scheduled port reconfigurations */
        cancel_work_sync(&efx->mac_work);
 }
@@ -1282,7 +1278,9 @@ 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)) {
-               efx_stop_queue(efx);
+               struct efx_channel *channel;
+               efx_for_each_channel(channel, efx)
+                       efx_stop_queue(channel);
                netif_tx_lock_bh(efx->net_dev);
                netif_tx_unlock_bh(efx->net_dev);
        }
@@ -1520,11 +1518,8 @@ static struct net_device_stats *efx_net_stats(struct net_device *net_dev)
        stats->tx_window_errors = mac_stats->tx_late_collision;
 
        stats->rx_errors = (stats->rx_length_errors +
-                           stats->rx_over_errors +
                            stats->rx_crc_errors +
                            stats->rx_frame_errors +
-                           stats->rx_fifo_errors +
-                           stats->rx_missed_errors +
                            mac_stats->rx_symbol_error);
        stats->tx_errors = (stats->tx_window_errors +
                            mac_stats->tx_bad);
@@ -1537,9 +1532,8 @@ static void efx_watchdog(struct net_device *net_dev)
 {
        struct efx_nic *efx = netdev_priv(net_dev);
 
-       EFX_ERR(efx, "TX stuck with stop_count=%d port_enabled=%d:"
-               " resetting channels\n",
-               atomic_read(&efx->netif_stop_count), efx->port_enabled);
+       EFX_ERR(efx, "TX stuck with port_enabled=%d: resetting channels\n",
+               efx->port_enabled);
 
        efx_schedule_reset(efx, RESET_TYPE_TX_WATCHDOG);
 }
@@ -1603,7 +1597,7 @@ static int efx_set_mac_address(struct net_device *net_dev, void *data)
 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;
+       struct netdev_hw_addr *ha;
        union efx_multicast_hash *mc_hash = &efx->multicast_hash;
        u32 crc;
        int bit;
@@ -1615,8 +1609,8 @@ static void efx_set_multicast_list(struct net_device *net_dev)
                memset(mc_hash, 0xff, sizeof(*mc_hash));
        } else {
                memset(mc_hash, 0x00, sizeof(*mc_hash));
-               netdev_for_each_mc_addr(mc_list, net_dev) {
-                       crc = ether_crc_le(ETH_ALEN, mc_list->dmi_addr);
+               netdev_for_each_mc_addr(ha, net_dev) {
+                       crc = ether_crc_le(ETH_ALEN, ha->addr);
                        bit = crc & (EFX_MCAST_HASH_ENTRIES - 1);
                        set_bit_le(bit, mc_hash->byte);
                }
@@ -1877,6 +1871,9 @@ static void efx_reset_work(struct work_struct *data)
 {
        struct efx_nic *efx = container_of(data, struct efx_nic, reset_work);
 
+       if (efx->reset_pending == RESET_TYPE_NONE)
+               return;
+
        /* If we're not RUNNING then don't reset. Leave the reset_pending
         * flag set so that efx_pci_probe_main will be retried */
        if (efx->state != STATE_RUNNING) {
@@ -2014,22 +2011,22 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type,
 
        efx->net_dev = net_dev;
        efx->rx_checksum_enabled = true;
-       spin_lock_init(&efx->netif_stop_lock);
        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);
-       atomic_set(&efx->netif_stop_count, 1);
 
        for (i = 0; i < EFX_MAX_CHANNELS; i++) {
                channel = &efx->channel[i];
                channel->efx = efx;
                channel->channel = i;
                channel->work_pending = false;
+               spin_lock_init(&channel->tx_stop_lock);
+               atomic_set(&channel->tx_stop_count, 1);
        }
-       for (i = 0; i < EFX_TX_QUEUE_COUNT; i++) {
+       for (i = 0; i < EFX_MAX_TX_QUEUES; i++) {
                tx_queue = &efx->tx_queue[i];
                tx_queue->efx = efx;
                tx_queue->queue = i;
@@ -2043,8 +2040,8 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type,
                rx_queue->queue = i;
                rx_queue->channel = &efx->channel[0]; /* for safety */
                rx_queue->buffer = NULL;
-               spin_lock_init(&rx_queue->add_lock);
-               INIT_DELAYED_WORK(&rx_queue->work, efx_rx_work);
+               setup_timer(&rx_queue->slow_fill, efx_rx_slow_fill,
+                           (unsigned long)rx_queue);
        }
 
        efx->type = type;
@@ -2201,7 +2198,7 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev,
        int i, rc;
 
        /* Allocate and initialise a struct net_device and struct efx_nic */
-       net_dev = alloc_etherdev(sizeof(*efx));
+       net_dev = alloc_etherdev_mq(sizeof(*efx), EFX_MAX_CORE_TX_QUEUES);
        if (!net_dev)
                return -ENOMEM;
        net_dev->features |= (type->offload_features | NETIF_F_SG |
@@ -2323,6 +2320,9 @@ static int efx_pm_thaw(struct device *dev)
 
        efx->type->resume_wol(efx);
 
+       /* Reschedule any quenched resets scheduled during efx_pm_freeze() */
+       queue_work(reset_workqueue, &efx->reset_work);
+
        return 0;
 }
 
@@ -2412,11 +2412,6 @@ static int __init efx_init_module(void)
        if (rc)
                goto err_notifier;
 
-       refill_workqueue = create_workqueue("sfc_refill");
-       if (!refill_workqueue) {
-               rc = -ENOMEM;
-               goto err_refill;
-       }
        reset_workqueue = create_singlethread_workqueue("sfc_reset");
        if (!reset_workqueue) {
                rc = -ENOMEM;
@@ -2432,8 +2427,6 @@ static int __init efx_init_module(void)
  err_pci:
        destroy_workqueue(reset_workqueue);
  err_reset:
-       destroy_workqueue(refill_workqueue);
- err_refill:
        unregister_netdevice_notifier(&efx_netdev_notifier);
  err_notifier:
        return rc;
@@ -2445,7 +2438,6 @@ static void __exit efx_exit_module(void)
 
        pci_unregister_driver(&efx_pci_driver);
        destroy_workqueue(reset_workqueue);
-       destroy_workqueue(refill_workqueue);
        unregister_netdevice_notifier(&efx_netdev_notifier);
 
 }