Subject: [PATCH 01/22] e1000: Fix early TSO completion

From: "Kok, Auke" <[email-masked]>
Date: Fri, 08 Dec 2006 15:02:46 -0800

This fix was already merged in commit 96f9c2e277768099479fbed7c3b69c294b1fadef
but reverted in commit 989316ddfeafd0e8fb51a4d811383769ad62637a. After
stresstesting we found that the fix does not add new regressions and
works around a TX hang spotted by several users.

Signed-off-by: Jesse Brandeburg <[email-masked]>
Signed-off-by: Auke Kok <[email-masked]>
---

 drivers/net/ixgb/ixgb_main.c |   21 +++++++++++++++++++--
 1 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
index e628126..ebc9d71 100644
--- a/drivers/net/ixgb/ixgb_main.c
+++ b/drivers/net/ixgb/ixgb_main.c
@@ -1287,6 +1287,9 @@ ixgb_tx_map(struct ixgb_adapter *adapter
 	struct ixgb_buffer *buffer_info;
 	int len = skb->len;
 	unsigned int offset = 0, size, count = 0, i;
+#ifdef NETIF_F_TSO
+	unsigned int mss = skb_shinfo(skb)->gso_size;
+#endif
 
 	unsigned int nr_frags = skb_shinfo(skb)->nr_frags;
 	unsigned int f;
@@ -1298,6 +1301,12 @@ ixgb_tx_map(struct ixgb_adapter *adapter
 	while(len) {
 		buffer_info = &tx_ring->buffer_info[i];
 		size = min(len, IXGB_MAX_DATA_PER_TXD);
+#ifdef NETIF_F_TSO
+		/* 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;
+#endif
 		buffer_info->length = size;
 		WARN_ON(buffer_info->dma != 0);
 		buffer_info->dma =
@@ -1324,6 +1333,13 @@ ixgb_tx_map(struct ixgb_adapter *adapter
 		while(len) {
 			buffer_info = &tx_ring->buffer_info[i];
 			size = min(len, IXGB_MAX_DATA_PER_TXD);
+#ifdef NETIF_F_TSO
+			/* 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;
+#endif
 			buffer_info->length = size;
 			buffer_info->dma =
 				pci_map_page(adapter->pdev,
@@ -1401,8 +1417,9 @@ ixgb_tx_queue(struct ixgb_adapter *adapt
 /* Tx Descriptors needed, worst case */
 #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
+#define DESC_NEEDED TXD_USE_COUNT(IXGB_MAX_DATA_PER_TXD) /* skb->date */ + \
+	MAX_SKB_FRAGS * TXD_USE_COUNT(PAGE_SIZE) + 1 /* for context */ \
+	+ 1 /* one more needed for sentinel TSO workaround */
 
 static int
 ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev)

---
Auke Kok <[email-masked]>