Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 1657

kernel-2.6.18-238.el5.src.rpm

From: Bruce Allan <ballan@redhat.com>
Subject: [RHEL5 PATCH] ixgb: fix early TSO completion (bz213642)
Date: Wed, 13 Dec 2006 11:25:12 -0800
Bugzilla: 213642
Message-Id: <45805398.2050806@redhat.com>
Changelog: [net] ixgb: fix early TSO completion


The ixgb 10GbE driver may experience an early completion when using TSO 
(bz213642) which can lead to a Tx hang.  The attached patch against 
2.6.18-1.2839.el5 resolves this by appending a 4-byte "sentinel" 
descriptor. It has been tested at Intel.

A similar fix has been in the e1000 driver for sometime now and a patch 
for ixgb was committed to the netdev-2.6.git tree in May '06 [1] and 
shortly thereafter [2] reverted because of a suspicion it introduced 
another bug and performance problem.  That suspicion turned out to be 
incorrect and the patch was recently re-submitted and ACKed by 
jgarzik[3] (note, the thread at the last link mistakenly suggests the 
patch was for e1000 instead of ixgb; see the actual patch against ixgb 
by following the [prev in thread] link or access it directly at [4]).


-- 
Bruce Allan
Intel LAN Access Division
2111 NE 25th Avenue
Hillsboro, OR  97124
503-712-5943

diff -urp linux-2.6.18-1.2839.el5-vanilla/drivers/net/ixgb/ixgb_main.c linux-2.6.18-1.2839.el5/drivers/net/ixgb/ixgb_main.c
--- linux-2.6.18-1.2839.el5-vanilla/drivers/net/ixgb/ixgb_main.c	2006-09-19 20:42:06.000000000 -0700
+++ linux-2.6.18-1.2839.el5/drivers/net/ixgb/ixgb_main.c	2006-12-12 17:40:35.000000000 -0800
@@ -1271,6 +1271,7 @@ ixgb_tx_map(struct ixgb_adapter *adapter
 	struct ixgb_buffer *buffer_info;
 	int len = skb->len;
 	unsigned int offset = 0, size, count = 0, i;
+	unsigned int mss = skb_shinfo(skb)->gso_size;
 
 	unsigned int nr_frags = skb_shinfo(skb)->nr_frags;
 	unsigned int f;
@@ -1282,6 +1283,10 @@ ixgb_tx_map(struct ixgb_adapter *adapter
 	while(len) {
 		buffer_info = &tx_ring->buffer_info[i];
 		size = min(len, IXGB_MAX_DATA_PER_TXD);
+		/* Workaround for premature desc write-backs
+		 * in TSO mode.  Append 4-byte sentinel desc */
+		if (unlikely(mss && !nr_frags && size == len && size > 8))
+			size -= 4;
 		buffer_info->length = size;
 		buffer_info->dma =
 			pci_map_single(adapter->pdev,
@@ -1307,6 +1312,11 @@ ixgb_tx_map(struct ixgb_adapter *adapter
 		while(len) {
 			buffer_info = &tx_ring->buffer_info[i];
 			size = min(len, IXGB_MAX_DATA_PER_TXD);
+			/* Workaround for premature desc write-backs
+			 * in TSO mode.  Append 4-byte sentinel desc */
+			if (unlikely(mss && !nr_frags && size == len
+			             && size > 8))
+				size -= 4;
 			buffer_info->length = size;
 			buffer_info->dma =
 				pci_map_page(adapter->pdev,
@@ -1385,7 +1395,7 @@ ixgb_tx_queue(struct ixgb_adapter *adapt
 #define TXD_USE_COUNT(S) (((S) >> IXGB_MAX_TXD_PWR) + \
 			 (((S) & (IXGB_MAX_DATA_PER_TXD - 1)) ? 1 : 0))
 #define DESC_NEEDED TXD_USE_COUNT(IXGB_MAX_DATA_PER_TXD) + \
-	MAX_SKB_FRAGS * TXD_USE_COUNT(PAGE_SIZE) + 1
+	MAX_SKB_FRAGS * TXD_USE_COUNT(PAGE_SIZE) + 1 + 1
 
 static int
 ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev)