Merge branch 'core/percpu' into percpu-cpumask-x86-for-linus-2
[linux-2.6.git] / drivers / net / sfc / efx.c
index 847e9bb..00c23b1 100644 (file)
@@ -133,6 +133,16 @@ static int phy_flash_cfg;
 module_param(phy_flash_cfg, int, 0644);
 MODULE_PARM_DESC(phy_flash_cfg, "Set PHYs into reflash mode initially");
 
+static unsigned irq_adapt_low_thresh = 10000;
+module_param(irq_adapt_low_thresh, uint, 0644);
+MODULE_PARM_DESC(irq_adapt_low_thresh,
+                "Threshold score for reducing IRQ moderation");
+
+static unsigned irq_adapt_high_thresh = 20000;
+module_param(irq_adapt_high_thresh, uint, 0644);
+MODULE_PARM_DESC(irq_adapt_high_thresh,
+                "Threshold score for increasing IRQ moderation");
+
 /**************************************************************************
  *
  * Utility functions and prototypes
@@ -182,7 +192,6 @@ static int efx_process_channel(struct efx_channel *channel, int rx_quota)
                channel->rx_pkt = NULL;
        }
 
-       efx_flush_lro(channel);
        efx_rx_strategy(channel);
 
        efx_fast_push_rx_descriptors(&efx->rx_queue[channel->channel]);
@@ -224,12 +233,41 @@ static int efx_poll(struct napi_struct *napi, int budget)
        rx_packets = efx_process_channel(channel, budget);
 
        if (rx_packets < budget) {
+               struct efx_nic *efx = channel->efx;
+
+               if (channel->used_flags & EFX_USED_BY_RX &&
+                   efx->irq_rx_adaptive &&
+                   unlikely(++channel->irq_count == 1000)) {
+                       unsigned old_irq_moderation = channel->irq_moderation;
+
+                       if (unlikely(channel->irq_mod_score <
+                                    irq_adapt_low_thresh)) {
+                               channel->irq_moderation =
+                                       max_t(int,
+                                             channel->irq_moderation -
+                                             FALCON_IRQ_MOD_RESOLUTION,
+                                             FALCON_IRQ_MOD_RESOLUTION);
+                       } else if (unlikely(channel->irq_mod_score >
+                                           irq_adapt_high_thresh)) {
+                               channel->irq_moderation =
+                                       min(channel->irq_moderation +
+                                           FALCON_IRQ_MOD_RESOLUTION,
+                                           efx->irq_rx_moderation);
+                       }
+
+                       if (channel->irq_moderation != old_irq_moderation)
+                               falcon_set_int_moderation(channel);
+
+                       channel->irq_count = 0;
+                       channel->irq_mod_score = 0;
+               }
+
                /* There is no race here; although napi_disable() will
-                * only wait for netif_rx_complete(), this isn't a problem
+                * only wait for napi_complete(), this isn't a problem
                 * since efx_channel_processed() will have no effect if
                 * interrupts have already been disabled.
                 */
-               netif_rx_complete(napi);
+               napi_complete(napi);
                efx_channel_processed(channel);
        }
 
@@ -558,6 +596,8 @@ static void efx_link_status_changed(struct efx_nic *efx)
 
 }
 
+static void efx_fini_port(struct efx_nic *efx);
+
 /* This call reinitialises the MAC to pick up new PHY settings. The
  * caller must hold the mac_lock */
 void __efx_reconfigure_port(struct efx_nic *efx)
@@ -593,8 +633,8 @@ void __efx_reconfigure_port(struct efx_nic *efx)
 
 fail:
        EFX_ERR(efx, "failed to reconfigure MAC\n");
-       efx->phy_op->fini(efx);
-       efx->port_initialized = false;
+       efx->port_enabled = false;
+       efx_fini_port(efx);
 }
 
 /* Reinitialise the MAC to pick up new PHY settings, even if the port is
@@ -997,7 +1037,7 @@ static int efx_probe_nic(struct efx_nic *efx)
        efx_set_channels(efx);
 
        /* Initialise the interrupt moderation settings */
-       efx_init_irq_moderation(efx, tx_irq_mod_usec, rx_irq_mod_usec);
+       efx_init_irq_moderation(efx, tx_irq_mod_usec, rx_irq_mod_usec, true);
 
        return 0;
 }
@@ -1194,7 +1234,8 @@ void efx_flush_queues(struct efx_nic *efx)
  **************************************************************************/
 
 /* Set interrupt moderation parameters */
-void efx_init_irq_moderation(struct efx_nic *efx, int tx_usecs, int rx_usecs)
+void efx_init_irq_moderation(struct efx_nic *efx, int tx_usecs, int rx_usecs,
+                            bool rx_adaptive)
 {
        struct efx_tx_queue *tx_queue;
        struct efx_rx_queue *rx_queue;
@@ -1204,6 +1245,8 @@ void efx_init_irq_moderation(struct efx_nic *efx, int tx_usecs, int rx_usecs)
        efx_for_each_tx_queue(tx_queue, efx)
                tx_queue->channel->irq_moderation = tx_usecs;
 
+       efx->irq_rx_adaptive = rx_adaptive;
+       efx->irq_rx_moderation = rx_usecs;
        efx_for_each_rx_queue(rx_queue, efx)
                rx_queue->channel->irq_moderation = rx_usecs;
 }
@@ -1276,18 +1319,11 @@ static int efx_ioctl(struct net_device *net_dev, struct ifreq *ifr, int cmd)
 static int efx_init_napi(struct efx_nic *efx)
 {
        struct efx_channel *channel;
-       int rc;
 
        efx_for_each_channel(channel, efx) {
                channel->napi_dev = efx->net_dev;
-               rc = efx_lro_init(&channel->lro_mgr, efx);
-               if (rc)
-                       goto err;
        }
        return 0;
- err:
-       efx_fini_napi(efx);
-       return rc;
 }
 
 static void efx_fini_napi(struct efx_nic *efx)
@@ -1295,7 +1331,6 @@ static void efx_fini_napi(struct efx_nic *efx)
        struct efx_channel *channel;
 
        efx_for_each_channel(channel, efx) {
-               efx_lro_fini(&channel->lro_mgr);
                channel->napi_dev = NULL;
        }
 }
@@ -1683,7 +1718,8 @@ int efx_reset_up(struct efx_nic *efx, enum reset_type method,
                        rc = efx->phy_op->init(efx);
                        if (rc)
                                ok = false;
-               } else
+               }
+               if (!ok)
                        efx->port_initialized = false;
        }
 
@@ -1864,8 +1900,8 @@ static struct efx_phy_operations efx_dummy_phy_operations = {
 
 static struct efx_board efx_dummy_board_info = {
        .init           = efx_port_dummy_op_int,
-       .init_leds      = efx_port_dummy_op_int,
-       .set_fault_led  = efx_port_dummy_op_blink,
+       .init_leds      = efx_port_dummy_op_void,
+       .set_id_led     = efx_port_dummy_op_blink,
        .monitor        = efx_port_dummy_op_int,
        .blink          = efx_port_dummy_op_blink,
        .fini           = efx_port_dummy_op_void,
@@ -2127,7 +2163,7 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev,
        net_dev->features |= (NETIF_F_IP_CSUM | NETIF_F_SG |
                              NETIF_F_HIGHDMA | NETIF_F_TSO);
        if (lro)
-               net_dev->features |= NETIF_F_LRO;
+               net_dev->features |= NETIF_F_GRO;
        /* 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);