All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] tg3: Separate TSO setup logic.
@ 2008-06-20  3:04 Michael Chan
  2008-06-20  3:07 ` David Miller
  0 siblings, 1 reply; 2+ messages in thread
From: Michael Chan @ 2008-06-20  3:04 UTC (permalink / raw)
  To: davem; +Cc: netdev, mcarlson, Michael Chan

David, this goes on top of the 3rd patch to manage TX backlog.

tg3: Separate TSO setup logic.

Different TG3 chips require slightly different ways of setting up the
TX descriptor and different initial values for some IP/TCP header
fields.  It is cleaner to have dedicated TSO setup methods for the
different chips and to call the proper one using a function pointer.
The missing logic for TG3_FLG2_HW_TSO_2 has also been added.

Signed-off-by: Michael Chan <mchan@broadcom.com>
---
 drivers/net/tg3.c |  133 ++++++++++++++++++++++++++++++++++++-----------------
 drivers/net/tg3.h |    3 +
 2 files changed, 94 insertions(+), 42 deletions(-)

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index db960f8..f1cdee7 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -4767,6 +4767,93 @@ tg3_tso_bug_end:
 	return entry;
 }
 
+static int tg3_setup_fw_tso(struct tg3 *tp, struct sk_buff *skb, u32 *mss,
+			    u32 *base_flags)
+{
+	int tcp_opt_len, ip_tcp_len, hdr_len;
+	struct iphdr *iph;
+
+	tcp_opt_len = tcp_optlen(skb);
+	ip_tcp_len = ip_hdrlen(skb) + sizeof(struct tcphdr);
+
+	hdr_len = ip_tcp_len + tcp_opt_len;
+
+	if (unlikely((ETH_HLEN + hdr_len) > 80))
+		return -E2BIG;
+
+	*base_flags |= (TXD_FLAG_CPU_PRE_DMA | TXD_FLAG_CPU_POST_DMA);
+
+	iph = ip_hdr(skb);
+	iph->check = 0;
+	iph->tot_len = htons(*mss + hdr_len);
+
+	tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, 0,
+						 IPPROTO_TCP, 0);
+
+	if (tcp_opt_len || iph->ihl > 5) {
+		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705)
+			*mss |= ((iph->ihl - 5) + (tcp_opt_len >> 2)) << 11;
+		else
+			*base_flags |= ((iph->ihl - 5) + (tcp_opt_len >> 2)) <<
+				       12;
+	}
+
+	return 0;
+}
+
+static int tg3_setup_hw1_tso(struct tg3 *tp, struct sk_buff *skb, u32 *mss,
+			     u32 *base_flags)
+{
+	int tcp_opt_len, ip_tcp_len, hdr_len;
+	struct iphdr *iph;
+
+	tcp_opt_len = tcp_optlen(skb);
+	ip_tcp_len = ip_hdrlen(skb) + sizeof(struct tcphdr);
+
+	hdr_len = ip_tcp_len + tcp_opt_len;
+
+	if (unlikely((ETH_HLEN + hdr_len) > 80) &&
+		     (tp->tg3_flags2 & TG3_FLG2_TSO_BUG))
+		return -E2BIG;
+
+	*base_flags |= (TXD_FLAG_CPU_PRE_DMA | TXD_FLAG_CPU_POST_DMA);
+	*base_flags &= ~TXD_FLAG_TCPUDP_CSUM;
+
+	iph = ip_hdr(skb);
+	iph->check = 0;
+	iph->tot_len = htons(*mss + hdr_len);
+
+	tcp_hdr(skb)->check = 0;
+
+	if (tcp_opt_len || iph->ihl > 5)
+		*mss |= ((iph->ihl - 5) + (tcp_opt_len >> 2)) << 11;
+
+	return 0;
+}
+
+static int tg3_setup_hw2_tso(struct tg3 *tp, struct sk_buff *skb, u32 *mss,
+			     u32 *base_flags)
+{
+	if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6)
+		*mss |= (skb_headlen(skb) - ETH_HLEN) << 9;
+	else {
+		int tcp_opt_len, ip_tcp_len;
+		struct iphdr *iph = ip_hdr(skb);
+
+		tcp_opt_len = tcp_optlen(skb);
+		ip_tcp_len = ip_hdrlen(skb) + sizeof(struct tcphdr);
+
+		iph->check = 0;
+		iph->tot_len = htons(*mss + ip_tcp_len + tcp_opt_len);
+		*mss |= (ip_tcp_len + tcp_opt_len) << 9;
+	}
+	*base_flags |= (TXD_FLAG_CPU_PRE_DMA | TXD_FLAG_CPU_POST_DMA);
+	*base_flags &= ~TXD_FLAG_TCPUDP_CSUM;
+
+	tcp_hdr(skb)->check = 0;
+	return 0;
+}
+
 /* Transmit one SKB, return the final TX descriptor slot used.
  * No errors may be returned.  If something occurs which prevents
  * sending this packet, it will be dropped.
@@ -4784,55 +4871,14 @@ static u32 __tg3_xmit_one(struct tg3 *tp, struct net_device *dev,
 		base_flags |= TXD_FLAG_TCPUDP_CSUM;
 
 	if ((mss = skb_shinfo(skb)->gso_size) != 0) {
-		int tcp_opt_len, ip_tcp_len, hdr_len;
-		struct iphdr *iph;
-
 		if (skb_header_cloned(skb) &&
 		    pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) {
 			dev_kfree_skb(skb);
 			goto out;
 		}
 
-		tcp_opt_len = tcp_optlen(skb);
-		ip_tcp_len = ip_hdrlen(skb) + sizeof(struct tcphdr);
-
-		hdr_len = ip_tcp_len + tcp_opt_len;
-
-		if (unlikely((ETH_HLEN + hdr_len) > 80) &&
-			     (tp->tg3_flags2 & TG3_FLG2_TSO_BUG))
+		if (unlikely(tp->setup_tso(tp, skb, &mss, &base_flags)))
 			return tg3_tso_bug(tp, dev, skb, entry);
-
-		base_flags |= (TXD_FLAG_CPU_PRE_DMA |
-			       TXD_FLAG_CPU_POST_DMA);
-
-		iph = ip_hdr(skb);
-		iph->check = 0;
-		iph->tot_len = htons(mss + hdr_len);
-		if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) {
-			tcp_hdr(skb)->check = 0;
-			base_flags &= ~TXD_FLAG_TCPUDP_CSUM;
-		} else
-			tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr,
-								 iph->daddr, 0,
-								 IPPROTO_TCP,
-								 0);
-
-		if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO) ||
-		    (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705)) {
-			if (tcp_opt_len || iph->ihl > 5) {
-				int tsflags;
-
-				tsflags = (iph->ihl - 5) + (tcp_opt_len >> 2);
-				mss |= (tsflags << 11);
-			}
-		} else {
-			if (tcp_opt_len || iph->ihl > 5) {
-				int tsflags;
-
-				tsflags = (iph->ihl - 5) + (tcp_opt_len >> 2);
-				base_flags |= tsflags << 12;
-			}
-		}
 	}
 #if TG3_VLAN_TAG_USED
 	if (tp->vlgrp != NULL && vlan_tx_tag_present(skb))
@@ -11969,6 +12015,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 	    (tp->tg3_flags2 & TG3_FLG2_5750_PLUS))
 		tp->tg3_flags2 |= TG3_FLG2_5705_PLUS;
 
+	tp->setup_tso = tg3_setup_fw_tso;
 	if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) {
 		tp->tg3_flags |= TG3_FLAG_SUPPORT_MSI;
 		if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5750_AX ||
@@ -11986,8 +12033,10 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 		    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
 			tp->tg3_flags2 |= TG3_FLG2_HW_TSO_2;
 			tp->tg3_flags2 |= TG3_FLG2_1SHOT_MSI;
+			tp->setup_tso = tg3_setup_hw2_tso;
 		} else {
 			tp->tg3_flags2 |= TG3_FLG2_HW_TSO_1 | TG3_FLG2_TSO_BUG;
+			tp->setup_tso = tg3_setup_hw1_tso;
 			if (GET_ASIC_REV(tp->pci_chip_rev_id) ==
 				ASIC_REV_5750 &&
 	     		    tp->pci_chip_rev_id >= CHIPREV_ID_5750_C2)
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index d396c87..1792d47 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -2388,6 +2388,9 @@ struct tg3 {
 	/* begin "tx thread" cacheline section */
 	void				(*write32_tx_mbox) (struct tg3 *, u32,
 							    u32);
+	int				(*setup_tso) (struct tg3 *,
+						      struct sk_buff *,
+						      u32 *, u32 *);
 	u32				tx_prod;
 	u32				tx_cons;
 	u32				tx_pending;
-- 
1.5.5.GIT



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

* Re: [PATCH] tg3: Separate TSO setup logic.
  2008-06-20  3:04 [PATCH] tg3: Separate TSO setup logic Michael Chan
@ 2008-06-20  3:07 ` David Miller
  0 siblings, 0 replies; 2+ messages in thread
From: David Miller @ 2008-06-20  3:07 UTC (permalink / raw)
  To: mchan; +Cc: netdev, mcarlson

From: "Michael Chan" <mchan@broadcom.com>
Date: Thu, 19 Jun 2008 20:04:48 -0700

> David, this goes on top of the 3rd patch to manage TX backlog.
> 
> tg3: Separate TSO setup logic.
> 
> Different TG3 chips require slightly different ways of setting up the
> TX descriptor and different initial values for some IP/TCP header
> fields.  It is cleaner to have dedicated TSO setup methods for the
> different chips and to call the proper one using a function pointer.
> The missing logic for TG3_FLG2_HW_TSO_2 has also been added.
> 
> Signed-off-by: Michael Chan <mchan@broadcom.com>

Thanks for doing this work michael.

If we put this at the end, it means we have a point in the series
where things are broken, and this makes "git bisect" unusable which
we try to avoid.

Therefore I'll try to integrate this work into my first patch.

Thanks again.

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

end of thread, other threads:[~2008-06-20  3:07 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-06-20  3:04 [PATCH] tg3: Separate TSO setup logic Michael Chan
2008-06-20  3:07 ` David Miller

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.