netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH,RFT] 8139cp TSO support
@ 2004-08-29 21:22 Jeff Garzik
  2004-08-29 22:28 ` Francois Romieu
  0 siblings, 1 reply; 8+ messages in thread
From: Jeff Garzik @ 2004-08-29 21:22 UTC (permalink / raw)
  To: netdev; +Cc: linux-kernel, romieu


Just added TSO support to the 8139cp driver, as it looked fairly
straightforward.

Anyone willing to give this some testing?

Also, the r8169 implementation should be similar, if someone (Francois?)
wants to tackle it.

	Jeff




# ChangeSet
#   2004/08/29 17:19:44-04:00 jgarzik@pobox.com 
#   [netdrvr 8139cp] TSO support
# 
diff -Nru a/drivers/net/8139cp.c b/drivers/net/8139cp.c
--- a/drivers/net/8139cp.c	2004-08-29 17:19:59 -04:00
+++ b/drivers/net/8139cp.c	2004-08-29 17:19:59 -04:00
@@ -185,6 +185,9 @@
 	RingEnd		= (1 << 30), /* End of descriptor ring */
 	FirstFrag	= (1 << 29), /* First segment of a packet */
 	LastFrag	= (1 << 28), /* Final segment of a packet */
+	LargeSend	= (1 << 27), /* TCP Large Send Offload (TSO) */
+	MSSShift	= 16,	     /* MSS value position */
+	MSSMask		= 0xfff,     /* MSS value: 11 bits */
 	TxError		= (1 << 23), /* Tx error summary */
 	RxError		= (1 << 20), /* Rx error summary */
 	IPCS		= (1 << 18), /* Calculate IP checksum */
@@ -747,10 +750,11 @@
 {
 	struct cp_private *cp = netdev_priv(dev);
 	unsigned entry;
-	u32 eor;
+	u32 eor, flags;
 #if CP_VLAN_TAG_USED
 	u32 vlan_tag = 0;
 #endif
+	int mss = 0;
 
 	spin_lock_irq(&cp->lock);
 
@@ -770,6 +774,9 @@
 
 	entry = cp->tx_head;
 	eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0;
+	if (dev->features & NETIF_F_TSO)
+		mss = skb_shinfo(skb)->tso_size;
+
 	if (skb_shinfo(skb)->nr_frags == 0) {
 		struct cp_desc *txd = &cp->tx_ring[entry];
 		u32 len;
@@ -781,21 +788,21 @@
 		txd->addr = cpu_to_le64(mapping);
 		wmb();
 
-		if (skb->ip_summed == CHECKSUM_HW) {
+		flags = eor | len | DescOwn | FirstFrag | LastFrag;
+
+		if (mss)
+			flags |= LargeSend | ((mss & MSSMask) << MSSShift);
+		else if (skb->ip_summed == CHECKSUM_HW) {
 			const struct iphdr *ip = skb->nh.iph;
 			if (ip->protocol == IPPROTO_TCP)
-				txd->opts1 = cpu_to_le32(eor | len | DescOwn |
-							 FirstFrag | LastFrag |
-							 IPCS | TCPCS);
+				flags |= IPCS | TCPCS;
 			else if (ip->protocol == IPPROTO_UDP)
-				txd->opts1 = cpu_to_le32(eor | len | DescOwn |
-							 FirstFrag | LastFrag |
-							 IPCS | UDPCS);
+				flags |= IPCS | UDPCS;
 			else
 				BUG();
-		} else
-			txd->opts1 = cpu_to_le32(eor | len | DescOwn |
-						 FirstFrag | LastFrag);
+		}
+
+		txd->opts1 = cpu_to_le32(flags);
 		wmb();
 
 		cp->tx_skb[entry].skb = skb;
@@ -834,16 +841,19 @@
 						 len, PCI_DMA_TODEVICE);
 			eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0;
 
-			if (skb->ip_summed == CHECKSUM_HW) {
-				ctrl = eor | len | DescOwn | IPCS;
+			ctrl = eor | len | DescOwn;
+
+			if (mss)
+				ctrl |= LargeSend |
+					((mss & MSSMask) << MSSShift);
+			else if (skb->ip_summed == CHECKSUM_HW) {
 				if (ip->protocol == IPPROTO_TCP)
-					ctrl |= TCPCS;
+					ctrl |= IPCS | TCPCS;
 				else if (ip->protocol == IPPROTO_UDP)
-					ctrl |= UDPCS;
+					ctrl |= IPCS | UDPCS;
 				else
 					BUG();
-			} else
-				ctrl = eor | len | DescOwn;
+			}
 
 			if (frag == skb_shinfo(skb)->nr_frags - 1)
 				ctrl |= LastFrag;
@@ -1536,6 +1546,8 @@
 	.set_tx_csum		= ethtool_op_set_tx_csum, /* local! */
 	.get_sg			= ethtool_op_get_sg,
 	.set_sg			= ethtool_op_set_sg,
+	.get_tso		= ethtool_op_get_tso,
+	.set_tso		= ethtool_op_set_tso,
 	.get_regs		= cp_get_regs,
 	.get_wol		= cp_get_wol,
 	.set_wol		= cp_set_wol,
@@ -1765,6 +1777,10 @@
 
 	if (pci_using_dac)
 		dev->features |= NETIF_F_HIGHDMA;
+
+#if 0 /* disabled by default until verified */
+	dev->features |= NETIF_F_TSO;
+#endif
 
 	dev->irq = pdev->irq;
 

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH,RFT] 8139cp TSO support
  2004-08-29 21:22 [PATCH,RFT] 8139cp TSO support Jeff Garzik
@ 2004-08-29 22:28 ` Francois Romieu
  2004-08-29 23:02   ` Jeff Garzik
  0 siblings, 1 reply; 8+ messages in thread
From: Francois Romieu @ 2004-08-29 22:28 UTC (permalink / raw)
  To: netdev; +Cc: linux-kernel, jgarzik

Jeff Garzik <jgarzik@pobox.com> :
[...]
> Also, the r8169 implementation should be similar, if someone (Francois?)
> wants to tackle it.

I'll copy and test it tomorrow on r8169 if nobody beats me.

On a related note, 8139cp probably wants something like the patch below for
the usual SG handling (on top of 2.6.9-rc1 + -mm1 + TSO patch):

- suspicious length in pci_unmap_single;
- wait for the last frag before freeing the relevant skb;
- no need to crash when facing some unexpected csum combination.

diff -puN drivers/net/8139cp.c~8139cp-010 drivers/net/8139cp.c
--- linux-2.6.9-rc1/drivers/net/8139cp.c~8139cp-010	2004-08-29 23:47:07.000000000 +0200
+++ linux-2.6.9-rc1-fr/drivers/net/8139cp.c	2004-08-30 00:16:13.000000000 +0200
@@ -314,7 +314,7 @@ struct cp_desc {
 struct ring_info {
 	struct sk_buff		*skb;
 	dma_addr_t		mapping;
-	unsigned		frag;
+	u32			len;
 };
 
 struct cp_dma_stats {
@@ -708,7 +708,7 @@ static void cp_tx (struct cp_private *cp
 			BUG();
 
 		pci_unmap_single(cp->pdev, cp->tx_skb[tx_tail].mapping,
-					skb->len, PCI_DMA_TODEVICE);
+				 cp->tx_skb[tx_tail].len, PCI_DMA_TODEVICE);
 
 		if (status & LastFrag) {
 			if (status & (TxError | TxFIFOUnder)) {
@@ -799,7 +799,7 @@ static int cp_start_xmit (struct sk_buff
 			else if (ip->protocol == IPPROTO_UDP)
 				flags |= IPCS | UDPCS;
 			else
-				BUG();
+				WARN_ON(1);	/* we need a WARN() */
 		}
 
 		txd->opts1 = cpu_to_le32(flags);
@@ -807,7 +807,6 @@ static int cp_start_xmit (struct sk_buff
 
 		cp->tx_skb[entry].skb = skb;
 		cp->tx_skb[entry].mapping = mapping;
-		cp->tx_skb[entry].frag = 0;
 		entry = NEXT_TX(entry);
 	} else {
 		struct cp_desc *txd;
@@ -824,8 +823,8 @@ static int cp_start_xmit (struct sk_buff
 		first_mapping = pci_map_single(cp->pdev, skb->data,
 					       first_len, PCI_DMA_TODEVICE);
 		cp->tx_skb[entry].skb = skb;
+		cp->tx_skb[entry].len = first_len;
 		cp->tx_skb[entry].mapping = first_mapping;
-		cp->tx_skb[entry].frag = 1;
 		entry = NEXT_TX(entry);
 
 		for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) {
@@ -868,7 +867,7 @@ static int cp_start_xmit (struct sk_buff
 
 			cp->tx_skb[entry].skb = skb;
 			cp->tx_skb[entry].mapping = mapping;
-			cp->tx_skb[entry].frag = frag + 2;
+			cp->tx_skb[entry].len = len;
 			entry = NEXT_TX(entry);
 		}
 
@@ -1082,7 +1081,6 @@ static int cp_refill_rx (struct cp_priva
 		cp->rx_skb[i].mapping = pci_map_single(cp->pdev,
 			skb->tail, cp->rx_buf_sz, PCI_DMA_FROMDEVICE);
 		cp->rx_skb[i].skb = skb;
-		cp->rx_skb[i].frag = 0;
 
 		cp->rx_ring[i].opts2 = 0;
 		cp->rx_ring[i].addr = cpu_to_le64(cp->rx_skb[i].mapping);
@@ -1134,9 +1132,6 @@ static void cp_clean_rings (struct cp_pr
 {
 	unsigned i;
 
-	memset(cp->rx_ring, 0, sizeof(struct cp_desc) * CP_RX_RING_SIZE);
-	memset(cp->tx_ring, 0, sizeof(struct cp_desc) * CP_TX_RING_SIZE);
-
 	for (i = 0; i < CP_RX_RING_SIZE; i++) {
 		if (cp->rx_skb[i].skb) {
 			pci_unmap_single(cp->pdev, cp->rx_skb[i].mapping,
@@ -1148,13 +1143,18 @@ static void cp_clean_rings (struct cp_pr
 	for (i = 0; i < CP_TX_RING_SIZE; i++) {
 		if (cp->tx_skb[i].skb) {
 			struct sk_buff *skb = cp->tx_skb[i].skb;
+
 			pci_unmap_single(cp->pdev, cp->tx_skb[i].mapping,
-					 skb->len, PCI_DMA_TODEVICE);
-			dev_kfree_skb(skb);
+				 	 cp->tx_skb[i].len, PCI_DMA_TODEVICE);
+			if (le32_to_cpu(cp->tx_ring[i].opts1) & LastFrag)
+				dev_kfree_skb(skb);
 			cp->net_stats.tx_dropped++;
 		}
 	}
 
+	memset(cp->rx_ring, 0, sizeof(struct cp_desc) * CP_RX_RING_SIZE);
+	memset(cp->tx_ring, 0, sizeof(struct cp_desc) * CP_TX_RING_SIZE);
+
 	memset(&cp->rx_skb, 0, sizeof(struct ring_info) * CP_RX_RING_SIZE);
 	memset(&cp->tx_skb, 0, sizeof(struct ring_info) * CP_TX_RING_SIZE);
 }

_

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH,RFT] 8139cp TSO support
  2004-08-29 22:28 ` Francois Romieu
@ 2004-08-29 23:02   ` Jeff Garzik
  2004-08-30 21:52     ` Francois Romieu
  0 siblings, 1 reply; 8+ messages in thread
From: Jeff Garzik @ 2004-08-29 23:02 UTC (permalink / raw)
  To: Francois Romieu; +Cc: netdev, linux-kernel

Francois Romieu wrote:
> Jeff Garzik <jgarzik@pobox.com> :
> [...]
> 
>>Also, the r8169 implementation should be similar, if someone (Francois?)
>>wants to tackle it.
> 
> 
> I'll copy and test it tomorrow on r8169 if nobody beats me.
> 
> On a related note, 8139cp probably wants something like the patch below for
> the usual SG handling (on top of 2.6.9-rc1 + -mm1 + TSO patch):
> 
> - suspicious length in pci_unmap_single;
> - wait for the last frag before freeing the relevant skb;
> - no need to crash when facing some unexpected csum combination.

Looks OK except for


> diff -puN drivers/net/8139cp.c~8139cp-010 drivers/net/8139cp.c
> --- linux-2.6.9-rc1/drivers/net/8139cp.c~8139cp-010	2004-08-29 23:47:07.000000000 +0200
> +++ linux-2.6.9-rc1-fr/drivers/net/8139cp.c	2004-08-30 00:16:13.000000000 +0200
> @@ -807,7 +807,6 @@ static int cp_start_xmit (struct sk_buff
>  
>  		cp->tx_skb[entry].skb = skb;
>  		cp->tx_skb[entry].mapping = mapping;
> -		cp->tx_skb[entry].frag = 0;
>  		entry = NEXT_TX(entry);
>  	} else {
>  		struct cp_desc *txd;

You definitely want to set .len on the no-frags path...

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH,RFT] 8139cp TSO support
  2004-08-29 23:02   ` Jeff Garzik
@ 2004-08-30 21:52     ` Francois Romieu
  2004-08-30 21:56       ` [PATCH 2.6.9-rc1-mm1-tso 1/2] 8139cp: SG support fixes Francois Romieu
  0 siblings, 1 reply; 8+ messages in thread
From: Francois Romieu @ 2004-08-30 21:52 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: netdev, linux-kernel

Jeff Garzik <jgarzik@pobox.com> :
[...]
> You definitely want to set .len on the no-frags path...

Oops.. Patch follows.

I won't have a neat tso enabled r8169 driver today. Something goes wrong.

--
Ueimor

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 2.6.9-rc1-mm1-tso 1/2] 8139cp: SG support fixes
  2004-08-30 21:52     ` Francois Romieu
@ 2004-08-30 21:56       ` Francois Romieu
  2004-08-30 21:58         ` [PATCH 2.6.9-rc1-mm1-tso 2/2] 8139cp: DAC support fix Francois Romieu
  2004-08-31  7:20         ` [PATCH 2.6.9-rc1-mm1-tso 1/2] 8139cp: SG support fixes Jeff Garzik
  0 siblings, 2 replies; 8+ messages in thread
From: Francois Romieu @ 2004-08-30 21:56 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: netdev, linux-kernel


- suspicious length in pci_unmap_single;
- wait for the last frag before freeing the relevant skb;
- no need to crash when facing some unexpected csum combination.

diff -puN drivers/net/8139cp.c~8139cp-010 drivers/net/8139cp.c
--- linux-2.6.9-rc1/drivers/net/8139cp.c~8139cp-010	2004-08-29 23:47:07.000000000 +0200
+++ linux-2.6.9-rc1-fr/drivers/net/8139cp.c	2004-08-30 21:21:23.000000000 +0200
@@ -314,7 +314,7 @@ struct cp_desc {
 struct ring_info {
 	struct sk_buff		*skb;
 	dma_addr_t		mapping;
-	unsigned		frag;
+	u32			len;
 };
 
 struct cp_dma_stats {
@@ -708,7 +708,7 @@ static void cp_tx (struct cp_private *cp
 			BUG();
 
 		pci_unmap_single(cp->pdev, cp->tx_skb[tx_tail].mapping,
-					skb->len, PCI_DMA_TODEVICE);
+				 cp->tx_skb[tx_tail].len, PCI_DMA_TODEVICE);
 
 		if (status & LastFrag) {
 			if (status & (TxError | TxFIFOUnder)) {
@@ -799,7 +799,7 @@ static int cp_start_xmit (struct sk_buff
 			else if (ip->protocol == IPPROTO_UDP)
 				flags |= IPCS | UDPCS;
 			else
-				BUG();
+				WARN_ON(1);	/* we need a WARN() */
 		}
 
 		txd->opts1 = cpu_to_le32(flags);
@@ -807,7 +807,7 @@ static int cp_start_xmit (struct sk_buff
 
 		cp->tx_skb[entry].skb = skb;
 		cp->tx_skb[entry].mapping = mapping;
-		cp->tx_skb[entry].frag = 0;
+		cp->tx_skb[entry].len = len;
 		entry = NEXT_TX(entry);
 	} else {
 		struct cp_desc *txd;
@@ -825,7 +825,7 @@ static int cp_start_xmit (struct sk_buff
 					       first_len, PCI_DMA_TODEVICE);
 		cp->tx_skb[entry].skb = skb;
 		cp->tx_skb[entry].mapping = first_mapping;
-		cp->tx_skb[entry].frag = 1;
+		cp->tx_skb[entry].len = first_len;
 		entry = NEXT_TX(entry);
 
 		for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) {
@@ -868,7 +868,7 @@ static int cp_start_xmit (struct sk_buff
 
 			cp->tx_skb[entry].skb = skb;
 			cp->tx_skb[entry].mapping = mapping;
-			cp->tx_skb[entry].frag = frag + 2;
+			cp->tx_skb[entry].len = len;
 			entry = NEXT_TX(entry);
 		}
 
@@ -1082,7 +1082,6 @@ static int cp_refill_rx (struct cp_priva
 		cp->rx_skb[i].mapping = pci_map_single(cp->pdev,
 			skb->tail, cp->rx_buf_sz, PCI_DMA_FROMDEVICE);
 		cp->rx_skb[i].skb = skb;
-		cp->rx_skb[i].frag = 0;
 
 		cp->rx_ring[i].opts2 = 0;
 		cp->rx_ring[i].addr = cpu_to_le64(cp->rx_skb[i].mapping);
@@ -1134,9 +1133,6 @@ static void cp_clean_rings (struct cp_pr
 {
 	unsigned i;
 
-	memset(cp->rx_ring, 0, sizeof(struct cp_desc) * CP_RX_RING_SIZE);
-	memset(cp->tx_ring, 0, sizeof(struct cp_desc) * CP_TX_RING_SIZE);
-
 	for (i = 0; i < CP_RX_RING_SIZE; i++) {
 		if (cp->rx_skb[i].skb) {
 			pci_unmap_single(cp->pdev, cp->rx_skb[i].mapping,
@@ -1148,13 +1144,18 @@ static void cp_clean_rings (struct cp_pr
 	for (i = 0; i < CP_TX_RING_SIZE; i++) {
 		if (cp->tx_skb[i].skb) {
 			struct sk_buff *skb = cp->tx_skb[i].skb;
+
 			pci_unmap_single(cp->pdev, cp->tx_skb[i].mapping,
-					 skb->len, PCI_DMA_TODEVICE);
-			dev_kfree_skb(skb);
+				 	 cp->tx_skb[i].len, PCI_DMA_TODEVICE);
+			if (le32_to_cpu(cp->tx_ring[i].opts1) & LastFrag)
+				dev_kfree_skb(skb);
 			cp->net_stats.tx_dropped++;
 		}
 	}
 
+	memset(cp->rx_ring, 0, sizeof(struct cp_desc) * CP_RX_RING_SIZE);
+	memset(cp->tx_ring, 0, sizeof(struct cp_desc) * CP_TX_RING_SIZE);
+
 	memset(&cp->rx_skb, 0, sizeof(struct ring_info) * CP_RX_RING_SIZE);
 	memset(&cp->tx_skb, 0, sizeof(struct ring_info) * CP_TX_RING_SIZE);
 }

_

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 2.6.9-rc1-mm1-tso 2/2] 8139cp: DAC support fix
  2004-08-30 21:56       ` [PATCH 2.6.9-rc1-mm1-tso 1/2] 8139cp: SG support fixes Francois Romieu
@ 2004-08-30 21:58         ` Francois Romieu
  2004-08-31  7:19           ` Jeff Garzik
  2004-08-31  7:20         ` [PATCH 2.6.9-rc1-mm1-tso 1/2] 8139cp: SG support fixes Jeff Garzik
  1 sibling, 1 reply; 8+ messages in thread
From: Francois Romieu @ 2004-08-30 21:58 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: netdev, linux-kernel


Wrong unit for sizeof().

diff -puN drivers/net/8139cp.c~8139cp-020 drivers/net/8139cp.c
--- linux-2.6.9-rc1/drivers/net/8139cp.c~8139cp-020	2004-08-30 23:34:16.000000000 +0200
+++ linux-2.6.9-rc1-fr/drivers/net/8139cp.c	2004-08-30 23:35:09.000000000 +0200
@@ -1711,7 +1711,7 @@ static int cp_init_one (struct pci_dev *
 	}
 
 	/* Configure DMA attributes. */
-	if ((sizeof(dma_addr_t) > 32) &&
+	if ((sizeof(dma_addr_t) > 4) &&
 	    !pci_set_consistent_dma_mask(pdev, 0xffffffffffffffffULL) &&
 	    !pci_set_dma_mask(pdev, 0xffffffffffffffffULL)) {
 		pci_using_dac = 1;

_

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 2.6.9-rc1-mm1-tso 2/2] 8139cp: DAC support fix
  2004-08-30 21:58         ` [PATCH 2.6.9-rc1-mm1-tso 2/2] 8139cp: DAC support fix Francois Romieu
@ 2004-08-31  7:19           ` Jeff Garzik
  0 siblings, 0 replies; 8+ messages in thread
From: Jeff Garzik @ 2004-08-31  7:19 UTC (permalink / raw)
  To: Francois Romieu; +Cc: netdev, linux-kernel

applied

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 2.6.9-rc1-mm1-tso 1/2] 8139cp: SG support fixes
  2004-08-30 21:56       ` [PATCH 2.6.9-rc1-mm1-tso 1/2] 8139cp: SG support fixes Francois Romieu
  2004-08-30 21:58         ` [PATCH 2.6.9-rc1-mm1-tso 2/2] 8139cp: DAC support fix Francois Romieu
@ 2004-08-31  7:20         ` Jeff Garzik
  1 sibling, 0 replies; 8+ messages in thread
From: Jeff Garzik @ 2004-08-31  7:20 UTC (permalink / raw)
  To: Francois Romieu; +Cc: netdev, linux-kernel

applied

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2004-08-31  7:20 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-08-29 21:22 [PATCH,RFT] 8139cp TSO support Jeff Garzik
2004-08-29 22:28 ` Francois Romieu
2004-08-29 23:02   ` Jeff Garzik
2004-08-30 21:52     ` Francois Romieu
2004-08-30 21:56       ` [PATCH 2.6.9-rc1-mm1-tso 1/2] 8139cp: SG support fixes Francois Romieu
2004-08-30 21:58         ` [PATCH 2.6.9-rc1-mm1-tso 2/2] 8139cp: DAC support fix Francois Romieu
2004-08-31  7:19           ` Jeff Garzik
2004-08-31  7:20         ` [PATCH 2.6.9-rc1-mm1-tso 1/2] 8139cp: SG support fixes Jeff Garzik

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).