make tg3 NAPI support configurable
Subsystems (3)
PATCH 1/1 make tg3 NAPI support configurable
G'day,
I've been having some issues with irq rates and cpu usage in the tg3 driver. In short, on Altix machines they're far too high. It turned out that reverting the driver to its pre-NAPI interrupt coalescing scheme made the situation a lot better.
How much better? Running 8192 byte UDP packets across gige with NAPI takes 99.5% of a CPU to service 29,100 irqs per second. With the pre-NAPI code the figures are 36.0% CPU and 4880 irq/sec. Similar improvements are seen for non-fragmented UDP and for TCP.
So, this patch against 2.6.0-test11 makes NAPI support in the tg3 driver selectable with a config option. The default value is to enable NAPI, on the assumption that NAPI must be working for most people. The non-NAPI case is the code from before NAPI was added, with tweaks for locking and ethtool_ops.
The patch also applies against 2.6.0 with a few offsets.
===========================================================================
linux/drivers/net/Kconfig
===========================================================================
drivers/net/Kconfig renamed from usr/tmp/TmpDir.7858-0/linux/drivers/net/Kconfig_1.22 +8 -0
@@ -2017,6 +2017,14 @@ To compile this driver as a module, choose M here: the module will be called tg3. This is recommended. +config TIGON3_NAPI + bool "Use Rx Polling (NAPI)" + default y + depends on TIGON3 + help + NAPI is a new driver API designed to reduce CPU and interrupt load + when the driver is receiving lots of packets from the card. + endmenu #
===========================================================================linux/drivers/net/tg3.c
===========================================================================
drivers/net/tg3.c renamed from usr/tmp/TmpDir.26498-0/linux/drivers/net/tg3.c_1.20 +393 -2
459 lines not on this page · raw message
*ering)
{
struct tg3 *tp = dev->priv;
@@ -6245,6 +6636,10 @@
.set_msglevel = tg3_set_msglevel,
.nway_reset = tg3_nway_reset,
.get_link = ethtool_op_get_link,
+#ifndef CONFIG_TIGON3_NAPI
+ .get_coalesce = tg3_get_coalesce,
+ .set_coalesce = tg3_set_coalesce,
+#endif
.get_ringparam = tg3_get_ringparam,
.set_ringparam = tg3_set_ringparam,
.get_pauseparam = tg3_get_pauseparam,
@@ -6889,6 +7284,7 @@
(tp->pci_chip_rev_id != CHIPREV_ID_5705_A1)))
tp->tg3_flags2 |= TG3_FLG2_NO_ETH_WIRE_SPEED;
+#ifdef CONFIG_TIGON3_NAPI
/* Only 5701 and later support tagged irq status mode.
* Also, 5788 chips cannot use tagged irq status. *
@@ -6897,6 +7293,10 @@
* fully clear in that mode.
*/
tp->coalesce_mode = 0;
+#else
+ tp->coalesce_mode = (HOSTCC_MODE_CLRTICK_RXBD |
+ HOSTCC_MODE_CLRTICK_TXBD);
+#endif
if (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5700_AX &&
GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5700_BX)
@@ -7424,6 +7824,63 @@
tp->link_config.orig_autoneg = AUTONEG_INVALID;
}
+#ifndef CONFIG_TIGON3_NAPI
+static void __devinit tg3_init_coalesce_config(struct tg3 *tp) +{
+ tp->coalesce_config.rx_coalesce_ticks_def = DEFAULT_RXCOL_TICKS;
+ tp->coalesce_config.rx_max_coalesced_frames_def = DEFAULT_RXMAX_FRAMES;
+ tp->coalesce_config.rx_coalesce_ticks_during_int_def =
+ DEFAULT_RXCOAL_TICK_INT;
+ tp->coalesce_config.rx_max_coalesced_frames_during_int_def =
+ DEFAULT_RXCOAL_MAXF_INT;
+ tp->coalesce_config.tx_coalesce_ticks_def = DEFAULT_TXCOL_TICKS;
+ tp->coalesce_config.tx_max_coalesced_frames_def = DEFAULT_TXMAX_FRAMES;
+ tp->coalesce_config.tx_coalesce_ticks_during_int_def =
+ DEFAULT_TXCOAL_TICK_INT;
+ tp->coalesce_config.tx_max_coalesced_frames_during_int_def =
+ DEFAULT_TXCOAL_MAXF_INT;
+ tp->coalesce_config.stats_coalesce_ticks_def =
+ DEFAULT_STAT_COAL_TICKS;
+
+ tp->coalesce_config.rx_coalesce_ticks_low =
+ LOW_RXCOL_TICKS;
+ tp->coalesce_config.rx_max_coalesced_frames_low =
+ LOW_RXMAX_FRAMES;
+ tp->coalesce_config.tx_coalesce_ticks_low =
+ LOW_TXCOL_TICKS;
+ tp->coalesce_config.tx_max_coalesced_frames_low =
+ LOW_TXMAX_FRAMES;
+
+ tp->coalesce_config.rx_coalesce_ticks_high =
+ HIGH_RXCOL_TICKS;
+ tp->coalesce_config.rx_max_coalesced_frames_high =
+ HIGH_RXMAX_FRAMES;
+ tp->coalesce_config.tx_coalesce_ticks_high =
+ HIGH_TXCOL_TICKS;
+ tp->coalesce_config.tx_max_coalesced_frames_high =
+ HIGH_TXMAX_FRAMES;
+
+ /* Active == default */
+ tp->coalesce_config.rx_coalesce_ticks =
+ tp->coalesce_config.rx_coalesce_ticks_def;
+ tp->coalesce_config.rx_max_coalesced_frames =
+ tp->coalesce_config.rx_max_coalesced_frames_def;
+ tp->coalesce_config.tx_coalesce_ticks =
+ tp->coalesce_config.tx_coalesce_ticks_def;
+ tp->coalesce_config.tx_max_coalesced_frames =
+ tp->coalesce_config.tx_max_coalesced_frames_def;
+ tp->coalesce_config.stats_coalesce_ticks =
+ tp->coalesce_config.stats_coalesce_ticks_def;
+
+ tp->coalesce_config.rate_sample_jiffies = (1 * HZ);
+ tp->coalesce_config.pkt_rate_low = 22000;
+ tp->coalesce_config.pkt_rate_high = 61000;
+
+ tp->tg3_flags2 |= TG3_FLG2_ADAPTIVE_RX;
+ tp->tg3_flags2 &= ~(TG3_FLG2_ADAPTIVE_TX);
+}
+#endif /* !CONFIG_TIGON3_NAPI */
+
static void __devinit tg3_init_bufmgr_config(struct tg3 *tp) {
tp->bufmgr_config.mbuf_read_dma_low_water =
@@ -7613,6 +8070,10 @@
tg3_init_link_config(tp);
+#ifndef CONFIG_TIGON3_NAPI
+ tg3_init_coalesce_config(tp);
+#endif /* !CONFIG_TIGON3_NAPI */
+
tg3_init_bufmgr_config(tp);
tp->rx_pending = TG3_DEF_RX_RING_PENDING;
@@ -7626,9 +8087,11 @@
dev->set_mac_address = tg3_set_mac_addr; dev->do_ioctl = tg3_ioctl; dev->tx_timeout = tg3_tx_timeout;
- dev->poll = tg3_poll;
dev->ethtool_ops = &tg3_ethtool_ops;
+#ifdef CONFIG_TIGON3_NAPI
+ dev->poll = tg3_poll;
dev->weight = 64;
+#endif /* CONFIG_TIGON3_NAPI */
dev->watchdog_timeo = TG3_TX_TIMEOUT; dev->change_mtu = tg3_change_mtu; dev->irq = pdev->irq;
@@ -7718,7 +8181,7 @@
*/
pci_save_state(tp->pdev, tp->pci_cfg_state);
- printk(KERN_INFO "%s: Tigon3 [partno(%s) rev %04x PHY(%s)] (PCI%s:%s:%s) %sBaseT
Ethernet ",
+ printk(KERN_INFO "%s: Tigon3 [partno(%s) rev %04x PHY(%s)] (PCI%s:%s:%s) %sBaseT
Ethernet (%s) ",
dev->name,
tp->board_part_number,
tp->pci_chip_rev_id,
@@ -7728,7 +8191,13 @@
((tp->tg3_flags & TG3_FLAG_PCIX_MODE) ? "133MHz" : "66MHz") :
((tp->tg3_flags & TG3_FLAG_PCIX_MODE) ? "100MHz" : "33MHz")),
((tp->tg3_flags & TG3_FLAG_PCI_32BIT) ? "32-bit" : "64-bit"),
- (tp->tg3_flags & TG3_FLAG_10_100_ONLY) ? "10/100" : "10/100/1000");
+ (tp->tg3_flags & TG3_FLAG_10_100_ONLY) ? "10/100" : "10/100/1000",
+#ifdef CONFIG_TIGON3_NAPI
+ "NAPI"
+#else
+ "no NAPI"
+#endif
+ );
for (i = 0; i < 6; i++)
printk("%2.2x%c", dev->dev_addr[i],
===========================================================================linux/drivers/net/tg3.h
===========================================================================
drivers/net/tg3.h renamed from usr/tmp/TmpDir.26498-0/linux/drivers/net/tg3.h_1.9 +53 -0
77 lines not on this page · raw message
Greg.
Signature · 2 lines
Greg Banks, R&D Software Engineer, SGI Australian Software Group. I don't speak for SGI.
PATCH 1/1 make tg3 NAPI support configurable
Quoted 9 lines · Greg Banks
I've been having some issues with irq rates and cpu usage in the tg3 driver. In short, on Altix machines they're far too high. It turned out that reverting the driver to its pre-NAPI interrupt coalescing scheme made the situation a lot better.
How much better? Running 8192 byte UDP packets across gige with NAPI takes 99.5% of a CPU to service 29,100 irqs per second. With the pre-NAPI code the figures are 36.0% CPU and 4880 irq/sec. Similar improvements are seen for non-fragmented UDP and for TCP.
Hello!
You can use coalescing with NAPI as well, e1000 and other drivers are doing this. This will give you same interrupt rates as non- NAPI at low load and "polling" without any interrupts at high load.
Furthermore NAPI can be extended to schedule dev->poll even for TX- interrupts. There is pacth for e1000 doing this. We see about 5-8% overall system packet improvement with this.
Cheers.
--ro
Quoted 12 lines · Robert Olsson
Quoted 9 lines · Greg Banks
I've been having some issues with irq rates and cpu usage in the tg3 driver. In short, on Altix machines they're far too high. It turned out that reverting the driver to its pre-NAPI interrupt coalescing scheme made the situation a lot better.
How much better? Running 8192 byte UDP packets across gige with NAPI takes 99.5% of a CPU to service 29,100 irqs per second. With the pre-NAPI code the figures are 36.0% CPU and 4880 irq/sec. Similar improvements are seen for non-fragmented UDP and for TCP.
Quoted 5 lines
Hello!
You can use coalescing with NAPI as well, e1000 and other drivers are doing this. This will give you same interrupt rates as non- NAPI at low load and "polling" without any interrupts at high load.
Yes, this is something I've been meaning to add to tg3 for months now. Adding some about of hardware intr mitigation -in addition to- NAPI will not only help on the NAPI "hard case" of moderate load and a super-fast CPU, but also help avoid certain silicon bugs...
Quoted 3 lines
Furthermore NAPI can be extended to schedule
dev->polleven for TX- interrupts. There is pacth for e1000 doing this. We see about 5-8% overall system packet improvement with this.
tg3 already schedules for TX, so we've got that part covered :)
Jeff
Quoted 7 lines · Jeff Garzik
Quoted 3 lines · Robert Olsson
You can use coalescing with NAPI as well, e1000 and other drivers are doing this. This will give you same interrupt rates as non- NAPI at low load and "polling" without any interrupts at high load.
Yes, this is something I've been meaning to add to tg3 for months now.
I'd be very happy to test patches on an Altix, where this issue is a significant networking scaling limitation.
Greg.
Signature · 2 lines
Greg Banks, R&D Software Engineer, SGI Australian Software Group. I don't speak for SGI.
Quoted 5 lines · Jeff Garzik
Quoted 3 lines
Furthermore NAPI can be extended to schedule
dev->polleven for TX- interrupts. There is pacth for e1000 doing this. We see about 5-8% overall system packet improvement with this.tg3 already schedules for TX, so we've got that part covered :)
Hello!
I was thinking of a variant JC [[email protected]] mentioned on this list some time ago. He also sent me the patch for e1000. A test and the patch is below.
Routing test.
============
2 * 10 Million pkts @ 2*783 kpps into eth0, eth2 routed to eth1, eth3. (TX-OK is the number to look for)
Iface MTU Met RX-OK RX-ERR RX-DRP RX-OVR TX-OK TX-ERR TX-DRP TX-OVR Flags
eth0 1500 0 3494625 8258316 8258316 6505378 24 0 0 0 BRU eth1 1500 0 45 0 0 0 3494627 0 0 0 BRU eth2 1500 0 3493930 8270692 8270692 6506073 21 0 0 0 BRU eth3 1500 0 1 0 0 0 3493929 0 0 0 BRU
CPU0
26: 74 IO-APIC-level eth0 27: 48617 IO-APIC-level eth1 28: 71 IO-APIC-level eth2 29: 48659 IO-APIC-level eth3
-------------------------------------------------------------------------------
With patch.
Iface MTU Met RX-OK RX-ERR RX-DRP RX-OVR TX-OK TX-ERR TX-DRP TX-OVR Flags
eth0 1500 0 3752858 8151787 8151787 6247146 23 0 0 0 BRU eth1 1500 0 47 0 0 0 3751676 0 0 0 BRU eth2 1500 0 3751226 8191511 8191511 6248777 21 0 0 0 BRU eth3 1500 0 1 0 0 0 3750490 0 0 0 BRU
CPU0
26: 125 IO-APIC-level eth0 27: 127 IO-APIC-level eth1 28: 122 IO-APIC-level eth2 29: 137 IO-APIC-level eth3
TX interrupts alone now schedules consecutive polls. We route 7.5 Million pkts w/o any interrupts. Total throughput from 0.349% to 0.375% (~580 kpps) Of course having having RX-only and TX-only is special case...
TCP-stream test.
================
Netperf w. single TCP-stream recv showed 938 Mbit/s both with and without patch and interrupts rates were the same. XEON @ 2.66 GHz w. e1000 4-port board. Linux 2.6.0-test11/UP
e1000_main.c renamed from e1000_main.c.orig +9 -7
@@ -2061,19 +2061,21 @@struct e1000_adapter *adapter = netdev->priv;int work_to_do =min (*budget, netdev->quota);int work_done =0 ; - -e1000_clean_tx_irq (adapter); +boolean_t tx_cleaned; + + tx_cleaned =e1000_clean_tx_irq (adapter);e1000_clean_rx_irq (adapter, &work_done, work_to_do); - *budget -= work_done; - netdev->quota -= work_done; - -if (work_done < work_to_do) { +if (!tx_cleaned && (work_done ==0 )) {netif_rx_complete (netdev);e1000_irq_enable (adapter); +return 0 ; } - return (work_done >= work_to_do); + *budget -= work_done; + netdev->quota -= work_done; + + return 1; }#endif
Cheers.
--ro