--- linux-2.6.18.noarch/drivers/net/ixgb/ixgb_main.c.orig 2006-09-19 23:42:06.000000000 -0400 +++ linux-2.6.18.noarch/drivers/net/ixgb/ixgb_main.c 2006-11-01 11:17:24.000000000 -0500 @@ -1271,6 +1271,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; @@ -1282,6 +1285,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_single(adapter->pdev, @@ -1307,6 +1317,14 @@ 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 && (f == (nr_frags-1)) && (size == len) + && (size > 8))) + size -= 4; + +#endif buffer_info->length = size; buffer_info->dma = pci_map_page(adapter->pdev, @@ -1385,7 +1403,8 @@ 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 /* for context */ \ + + 1 /* one more needed for sentinel TSO workaround */ static int ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev)