diff options
author | Matt Carlson <mcarlson@broadcom.com> | 2011-07-27 10:20:51 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-07-28 01:39:31 -0400 |
commit | d1a3b7377d3b6a01ec5f70adb32173b13233aabf (patch) | |
tree | ad1d5204140560a8724a104bbc1dccbc0704307d | |
parent | e01ee14d499e5d09c0a9db0cac2545a018849e3d (diff) |
tg3: Consolidate code that calls tg3_tx_set_bd()
This patch consolidates all code that populates tx BDs into a single
routine. Setting tx BDs needs to be more carefully controlled to see if
workarounds need to be applied.
Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Reviewed-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/tg3.c | 79 |
1 files changed, 42 insertions, 37 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 90b68a229745..7f816a0ee421 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c | |||
@@ -5914,18 +5914,37 @@ static inline int tg3_40bit_overflow_test(struct tg3 *tp, dma_addr_t mapping, | |||
5914 | #endif | 5914 | #endif |
5915 | } | 5915 | } |
5916 | 5916 | ||
5917 | static inline void tg3_tx_set_bd(struct tg3_napi *tnapi, u32 entry, | 5917 | static inline void tg3_tx_set_bd(struct tg3_tx_buffer_desc *txbd, |
5918 | dma_addr_t mapping, u32 len, u32 flags, | 5918 | dma_addr_t mapping, u32 len, u32 flags, |
5919 | u32 mss, u32 vlan) | 5919 | u32 mss, u32 vlan) |
5920 | { | 5920 | { |
5921 | struct tg3_tx_buffer_desc *txbd = &tnapi->tx_ring[entry]; | ||
5922 | |||
5923 | txbd->addr_hi = ((u64) mapping >> 32); | 5921 | txbd->addr_hi = ((u64) mapping >> 32); |
5924 | txbd->addr_lo = ((u64) mapping & 0xffffffff); | 5922 | txbd->addr_lo = ((u64) mapping & 0xffffffff); |
5925 | txbd->len_flags = (len << TXD_LEN_SHIFT) | (flags & 0x0000ffff); | 5923 | txbd->len_flags = (len << TXD_LEN_SHIFT) | (flags & 0x0000ffff); |
5926 | txbd->vlan_tag = (mss << TXD_MSS_SHIFT) | (vlan << TXD_VLAN_TAG_SHIFT); | 5924 | txbd->vlan_tag = (mss << TXD_MSS_SHIFT) | (vlan << TXD_VLAN_TAG_SHIFT); |
5927 | } | 5925 | } |
5928 | 5926 | ||
5927 | static bool tg3_tx_frag_set(struct tg3_napi *tnapi, u32 entry, | ||
5928 | dma_addr_t map, u32 len, u32 flags, | ||
5929 | u32 mss, u32 vlan) | ||
5930 | { | ||
5931 | struct tg3 *tp = tnapi->tp; | ||
5932 | bool hwbug = false; | ||
5933 | |||
5934 | if (tg3_flag(tp, SHORT_DMA_BUG) && len <= 8) | ||
5935 | hwbug = 1; | ||
5936 | |||
5937 | if (tg3_4g_overflow_test(map, len)) | ||
5938 | hwbug = 1; | ||
5939 | |||
5940 | if (tg3_40bit_overflow_test(tp, map, len)) | ||
5941 | hwbug = 1; | ||
5942 | |||
5943 | tg3_tx_set_bd(&tnapi->tx_ring[entry], map, len, flags, mss, vlan); | ||
5944 | |||
5945 | return hwbug; | ||
5946 | } | ||
5947 | |||
5929 | static void tg3_tx_skb_unmap(struct tg3_napi *tnapi, u32 entry, int last) | 5948 | static void tg3_tx_skb_unmap(struct tg3_napi *tnapi, u32 entry, int last) |
5930 | { | 5949 | { |
5931 | int i; | 5950 | int i; |
@@ -5993,17 +6012,8 @@ static int tigon3_dma_hwbug_workaround(struct tg3_napi *tnapi, | |||
5993 | PCI_DMA_TODEVICE); | 6012 | PCI_DMA_TODEVICE); |
5994 | /* Make sure the mapping succeeded */ | 6013 | /* Make sure the mapping succeeded */ |
5995 | if (pci_dma_mapping_error(tp->pdev, new_addr)) { | 6014 | if (pci_dma_mapping_error(tp->pdev, new_addr)) { |
5996 | ret = -1; | ||
5997 | dev_kfree_skb(new_skb); | 6015 | dev_kfree_skb(new_skb); |
5998 | |||
5999 | /* Make sure new skb does not cross any 4G boundaries. | ||
6000 | * Drop the packet if it does. | ||
6001 | */ | ||
6002 | } else if (tg3_4g_overflow_test(new_addr, new_skb->len)) { | ||
6003 | pci_unmap_single(tp->pdev, new_addr, new_skb->len, | ||
6004 | PCI_DMA_TODEVICE); | ||
6005 | ret = -1; | 6016 | ret = -1; |
6006 | dev_kfree_skb(new_skb); | ||
6007 | } else { | 6017 | } else { |
6008 | base_flags |= TXD_FLAG_END; | 6018 | base_flags |= TXD_FLAG_END; |
6009 | 6019 | ||
@@ -6011,8 +6021,13 @@ static int tigon3_dma_hwbug_workaround(struct tg3_napi *tnapi, | |||
6011 | dma_unmap_addr_set(&tnapi->tx_buffers[entry], | 6021 | dma_unmap_addr_set(&tnapi->tx_buffers[entry], |
6012 | mapping, new_addr); | 6022 | mapping, new_addr); |
6013 | 6023 | ||
6014 | tg3_tx_set_bd(tnapi, entry, new_addr, new_skb->len, | 6024 | if (tg3_tx_frag_set(tnapi, entry, new_addr, |
6015 | base_flags, mss, vlan); | 6025 | new_skb->len, base_flags, |
6026 | mss, vlan)) { | ||
6027 | tg3_tx_skb_unmap(tnapi, entry, 0); | ||
6028 | dev_kfree_skb(new_skb); | ||
6029 | ret = -1; | ||
6030 | } | ||
6016 | } | 6031 | } |
6017 | } | 6032 | } |
6018 | 6033 | ||
@@ -6196,18 +6211,13 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
6196 | 6211 | ||
6197 | would_hit_hwbug = 0; | 6212 | would_hit_hwbug = 0; |
6198 | 6213 | ||
6199 | if (tg3_4g_overflow_test(mapping, len)) | ||
6200 | would_hit_hwbug = 1; | ||
6201 | |||
6202 | if (tg3_40bit_overflow_test(tp, mapping, len)) | ||
6203 | would_hit_hwbug = 1; | ||
6204 | |||
6205 | if (tg3_flag(tp, 5701_DMA_BUG)) | 6214 | if (tg3_flag(tp, 5701_DMA_BUG)) |
6206 | would_hit_hwbug = 1; | 6215 | would_hit_hwbug = 1; |
6207 | 6216 | ||
6208 | tg3_tx_set_bd(tnapi, entry, mapping, len, base_flags | | 6217 | if (tg3_tx_frag_set(tnapi, entry, mapping, len, base_flags | |
6209 | ((skb_shinfo(skb)->nr_frags == 0) ? TXD_FLAG_END : 0), | 6218 | ((skb_shinfo(skb)->nr_frags == 0) ? TXD_FLAG_END : 0), |
6210 | mss, vlan); | 6219 | mss, vlan)) |
6220 | would_hit_hwbug = 1; | ||
6211 | 6221 | ||
6212 | entry = NEXT_TX(entry); | 6222 | entry = NEXT_TX(entry); |
6213 | 6223 | ||
@@ -6236,20 +6246,11 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
6236 | if (pci_dma_mapping_error(tp->pdev, mapping)) | 6246 | if (pci_dma_mapping_error(tp->pdev, mapping)) |
6237 | goto dma_error; | 6247 | goto dma_error; |
6238 | 6248 | ||
6239 | if (tg3_flag(tp, SHORT_DMA_BUG) && | 6249 | if (tg3_tx_frag_set(tnapi, entry, mapping, len, |
6240 | len <= 8) | 6250 | base_flags | ((i == last) ? TXD_FLAG_END : 0), |
6241 | would_hit_hwbug = 1; | 6251 | tmp_mss, vlan)) |
6242 | |||
6243 | if (tg3_4g_overflow_test(mapping, len)) | ||
6244 | would_hit_hwbug = 1; | ||
6245 | |||
6246 | if (tg3_40bit_overflow_test(tp, mapping, len)) | ||
6247 | would_hit_hwbug = 1; | 6252 | would_hit_hwbug = 1; |
6248 | 6253 | ||
6249 | tg3_tx_set_bd(tnapi, entry, mapping, len, base_flags | | ||
6250 | ((i == last) ? TXD_FLAG_END : 0), | ||
6251 | tmp_mss, vlan); | ||
6252 | |||
6253 | entry = NEXT_TX(entry); | 6254 | entry = NEXT_TX(entry); |
6254 | } | 6255 | } |
6255 | } | 6256 | } |
@@ -11375,8 +11376,12 @@ static int tg3_run_loopback(struct tg3 *tp, u32 pktsz, int loopback_mode) | |||
11375 | 11376 | ||
11376 | rx_start_idx = rnapi->hw_status->idx[0].rx_producer; | 11377 | rx_start_idx = rnapi->hw_status->idx[0].rx_producer; |
11377 | 11378 | ||
11378 | tg3_tx_set_bd(tnapi, tnapi->tx_prod, map, tx_len, | 11379 | if (tg3_tx_frag_set(tnapi, tnapi->tx_prod, map, tx_len, |
11379 | base_flags | TXD_FLAG_END, mss, 0); | 11380 | base_flags | TXD_FLAG_END, mss, 0)) { |
11381 | tnapi->tx_buffers[val].skb = NULL; | ||
11382 | dev_kfree_skb(skb); | ||
11383 | return -EIO; | ||
11384 | } | ||
11380 | 11385 | ||
11381 | tnapi->tx_prod++; | 11386 | tnapi->tx_prod++; |
11382 | 11387 | ||