Skip to contentSkip to conversation

make tg3 NAPI support configurable

PATCH New Greg Banks 3 participants 5 messages Dec 19, 2003 – Jan 13, 2004

Subsystems (3)
lore
Share & tools
lore

Greg Banks

author
#0 lore raw

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.
#1 lore raw

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
#2 lore raw
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->poll even 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

author
#3 lore raw
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.
#4 lore raw
In reply to Jeff Garzik
Quoted 5 lines · Jeff Garzik
Quoted 3 lines

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.

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