tg3: Fix 5906 transmit hangs
Subsystems (2)
PATCH 2/20 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 <[email protected]>
Signed-off-by Michael Chan <[email protected]>
--- drivers/net/tg3.c | 26 +++++++++++++++++++------- drivers/net/tg3.h | 1 + 2 files changed, 20 insertions(+), 7 deletions(-)
drivers/net/tg3.c +19 -7
@@ -5393,7 +5393,7 @@ static netdev_tx_t tg3_start_xmit_dma_bug(struct sk_buff *skb, mss =0 ;if ((mss =skb_shinfo (skb)->gso_size) !=0 ) {struct iphdr *iph; -int tcp_opt_len, ip_tcp_len, hdr_len; +u32 tcp_opt_len, ip_tcp_len, hdr_len;if (skb_header_cloned (skb) &&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,IPPROTO_TCP , 0); -if ((tp->tg3_flags2 &TG3_FLG2_HW_TSO ) || - (GET_ASIC_REV (tp->pci_chip_rev_id) ==ASIC_REV_5705 )) { +if (tp->tg3_flags2 &TG3_FLG2_HW_TSO_2 ) + mss |= hdr_len <<9 ; +else if ((tp->tg3_flags2 &TG3_FLG2_HW_TSO_1 ) || +GET_ASIC_REV (tp->pci_chip_rev_id) ==ASIC_REV_5705 ) {if (tcp_opt_len || iph->ihl >5 ) {int tsflags;
@@ -5460,6 +5462,9 @@ static netdev_tx_t tg3_start_xmit_dma_bug(struct sk_buff *skb, would_hit_hwbug =0 ; +if ((tp->tg3_flags3 &TG3_FLG3_SHORT_DMA_BUG ) && len <=8 ) + would_hit_hwbug =1 ; +if ((tp->tg3_flags3 &TG3_FLG3_4G_DMA_BNDRY_BUG ) &&tg3_4g_overflow_test (mapping, len)) would_hit_hwbug =1 ;
@@ -5489,6 +5494,10 @@ static netdev_tx_t tg3_start_xmit_dma_bug(struct sk_buff *skb, tnapi->tx_buffers[entry].skb =NULL ; +if ((tp->tg3_flags3 &TG3_FLG3_SHORT_DMA_BUG ) && + len <=8 ) + would_hit_hwbug =1 ; +if ((tp->tg3_flags3 &TG3_FLG3_4G_DMA_BNDRY_BUG ) &&tg3_4g_overflow_test (mapping, len)) would_hit_hwbug =1 ;
@@ -12625,8 +12634,12 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) }if (!(tp->tg3_flags3 &TG3_FLG3_5755_PLUS )) { - tp->tg3_flags3 |=TG3_FLG3_4G_DMA_BNDRY_BUG ; - tp->tg3_flags3 |=TG3_FLG3_40BIT_DMA_LIMIT_BUG ; +if (GET_ASIC_REV (tp->pci_chip_rev_id) ==ASIC_REV_5906 ) + tp->tg3_flags3 |=TG3_FLG3_SHORT_DMA_BUG ; +else { + tp->tg3_flags3 |=TG3_FLG3_4G_DMA_BNDRY_BUG ; + tp->tg3_flags3 |=TG3_FLG3_40BIT_DMA_LIMIT_BUG ; + } } if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) ||
@@ -13987,8 +14000,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, goto err_out_iounmap; } -if ((tp->tg3_flags3 &TG3_FLG3_5755_PLUS ) || -GET_ASIC_REV (tp->pci_chip_rev_id) ==ASIC_REV_5906 ) +if (tp->tg3_flags3 &TG3_FLG3_5755_PLUS ) dev->netdev_ops = &tg3_netdev_ops;else dev->netdev_ops = &tg3_netdev_ops_dma_bug;
drivers/net/tg3.h +1 -0
@@ -2761,6 +2761,7 @@ struct tg3 {#define TG3_FLG3_ENABLE_RSS 0x00020000#define TG3_FLG3_4G_DMA_BNDRY_BUG 0x00080000#define TG3_FLG3_40BIT_DMA_LIMIT_BUG 0x00100000 +#define TG3_FLG3_SHORT_DMA_BUG 0x00200000struct timer_list timer;u16 timer_counter;
Signature · 1 line
1.6.4.4