diff options
author | Matt Carlson <mcarlson@broadcom.com> | 2009-11-02 09:23:27 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-11-03 02:39:00 -0500 |
commit | 92c6b8d16a36df3f28b2537bed2a56491fb08f11 (patch) | |
tree | 13f89b031c7c82163233963c24bfe20312ba901e | |
parent | 0e1406dd404ce55dbe8d68b4b5e2aed7e5c75fdb (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.c | 26 | ||||
-rw-r--r-- | drivers/net/tg3.h | 1 |
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; |