aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Carlson <mcarlson@broadcom.com>2009-11-02 09:23:27 -0500
committerDavid S. Miller <davem@davemloft.net>2009-11-03 02:39:00 -0500
commit92c6b8d16a36df3f28b2537bed2a56491fb08f11 (patch)
tree13f89b031c7c82163233963c24bfe20312ba901e
parent0e1406dd404ce55dbe8d68b4b5e2aed7e5c75fdb (diff)
tg3: Fix 5906 transmit hangs
The 5906 has trouble with fragments that are less than 8 bytes in size. This patch works around the problem by pivoting the 5906's transmit routine to tg3_start_xmit_dma_bug() and introducing a new SHORT_DMA_BUG flag that enables code to detect and react to the problematic condition. Signed-off-by: Matt Carlson <mcarlson@broadcom.com> Signed-off-by: Michael Chan <mchan@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/tg3.c26
-rw-r--r--drivers/net/tg3.h1
2 files changed, 20 insertions, 7 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index da808250c866..a7a582e37469 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -5393,7 +5393,7 @@ static netdev_tx_t tg3_start_xmit_dma_bug(struct sk_buff *skb,
5393 mss = 0; 5393 mss = 0;
5394 if ((mss = skb_shinfo(skb)->gso_size) != 0) { 5394 if ((mss = skb_shinfo(skb)->gso_size) != 0) {
5395 struct iphdr *iph; 5395 struct iphdr *iph;
5396 int tcp_opt_len, ip_tcp_len, hdr_len; 5396 u32 tcp_opt_len, ip_tcp_len, hdr_len;
5397 5397
5398 if (skb_header_cloned(skb) && 5398 if (skb_header_cloned(skb) &&
5399 pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) { 5399 pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) {
@@ -5424,8 +5424,10 @@ static netdev_tx_t tg3_start_xmit_dma_bug(struct sk_buff *skb,
5424 IPPROTO_TCP, 5424 IPPROTO_TCP,
5425 0); 5425 0);
5426 5426
5427 if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO) || 5427 if (tp->tg3_flags2 & TG3_FLG2_HW_TSO_2)
5428 (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705)) { 5428 mss |= hdr_len << 9;
5429 else if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_1) ||
5430 GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
5429 if (tcp_opt_len || iph->ihl > 5) { 5431 if (tcp_opt_len || iph->ihl > 5) {
5430 int tsflags; 5432 int tsflags;
5431 5433
@@ -5460,6 +5462,9 @@ static netdev_tx_t tg3_start_xmit_dma_bug(struct sk_buff *skb,
5460 5462
5461 would_hit_hwbug = 0; 5463 would_hit_hwbug = 0;
5462 5464
5465 if ((tp->tg3_flags3 & TG3_FLG3_SHORT_DMA_BUG) && len <= 8)
5466 would_hit_hwbug = 1;
5467
5463 if ((tp->tg3_flags3 & TG3_FLG3_4G_DMA_BNDRY_BUG) && 5468 if ((tp->tg3_flags3 & TG3_FLG3_4G_DMA_BNDRY_BUG) &&
5464 tg3_4g_overflow_test(mapping, len)) 5469 tg3_4g_overflow_test(mapping, len))
5465 would_hit_hwbug = 1; 5470 would_hit_hwbug = 1;
@@ -5489,6 +5494,10 @@ static netdev_tx_t tg3_start_xmit_dma_bug(struct sk_buff *skb,
5489 5494
5490 tnapi->tx_buffers[entry].skb = NULL; 5495 tnapi->tx_buffers[entry].skb = NULL;
5491 5496
5497 if ((tp->tg3_flags3 & TG3_FLG3_SHORT_DMA_BUG) &&
5498 len <= 8)
5499 would_hit_hwbug = 1;
5500
5492 if ((tp->tg3_flags3 & TG3_FLG3_4G_DMA_BNDRY_BUG) && 5501 if ((tp->tg3_flags3 & TG3_FLG3_4G_DMA_BNDRY_BUG) &&
5493 tg3_4g_overflow_test(mapping, len)) 5502 tg3_4g_overflow_test(mapping, len))
5494 would_hit_hwbug = 1; 5503 would_hit_hwbug = 1;
@@ -12625,8 +12634,12 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
12625 } 12634 }
12626 12635
12627 if (!(tp->tg3_flags3 & TG3_FLG3_5755_PLUS)) { 12636 if (!(tp->tg3_flags3 & TG3_FLG3_5755_PLUS)) {
12628 tp->tg3_flags3 |= TG3_FLG3_4G_DMA_BNDRY_BUG; 12637 if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
12629 tp->tg3_flags3 |= TG3_FLG3_40BIT_DMA_LIMIT_BUG; 12638 tp->tg3_flags3 |= TG3_FLG3_SHORT_DMA_BUG;
12639 else {
12640 tp->tg3_flags3 |= TG3_FLG3_4G_DMA_BNDRY_BUG;
12641 tp->tg3_flags3 |= TG3_FLG3_40BIT_DMA_LIMIT_BUG;
12642 }
12630 } 12643 }
12631 12644
12632 if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) || 12645 if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) ||
@@ -13987,8 +14000,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
13987 goto err_out_iounmap; 14000 goto err_out_iounmap;
13988 } 14001 }
13989 14002
13990 if ((tp->tg3_flags3 & TG3_FLG3_5755_PLUS) || 14003 if (tp->tg3_flags3 & TG3_FLG3_5755_PLUS)
13991 GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
13992 dev->netdev_ops = &tg3_netdev_ops; 14004 dev->netdev_ops = &tg3_netdev_ops;
13993 else 14005 else
13994 dev->netdev_ops = &tg3_netdev_ops_dma_bug; 14006 dev->netdev_ops = &tg3_netdev_ops_dma_bug;
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index b603810b4e9b..a5568a149748 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -2761,6 +2761,7 @@ struct tg3 {
2761#define TG3_FLG3_ENABLE_RSS 0x00020000 2761#define TG3_FLG3_ENABLE_RSS 0x00020000
2762#define TG3_FLG3_4G_DMA_BNDRY_BUG 0x00080000 2762#define TG3_FLG3_4G_DMA_BNDRY_BUG 0x00080000
2763#define TG3_FLG3_40BIT_DMA_LIMIT_BUG 0x00100000 2763#define TG3_FLG3_40BIT_DMA_LIMIT_BUG 0x00100000
2764#define TG3_FLG3_SHORT_DMA_BUG 0x00200000
2764 2765
2765 struct timer_list timer; 2766 struct timer_list timer;
2766 u16 timer_counter; 2767 u16 timer_counter;