aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Carlson <mcarlson@broadcom.com>2011-07-27 10:20:53 -0400
committerDavid S. Miller <davem@davemloft.net>2011-07-28 01:39:32 -0400
commite31aa9870627106aebddd280aab8ecb2f493246a (patch)
treec771dda9a09b07382947da52b82d093de9b951ea
parent84b67b27e9531e9a70c9e8cd952d66c55f4d0ddb (diff)
tg3: Break larger frags into 4k chunks for 5719
The 5719 has bug where RDMAs larger than 4k can cause problems. This patch works around the problem by dividing larger DMA requests into something the hardware can handle. 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.c52
-rw-r--r--drivers/net/tg3.h1
2 files changed, 47 insertions, 6 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index b93ba3d2192..c77a39d6cd1 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -190,6 +190,7 @@ static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits)
190 190
191/* minimum number of free TX descriptors required to wake up TX process */ 191/* minimum number of free TX descriptors required to wake up TX process */
192#define TG3_TX_WAKEUP_THRESH(tnapi) ((tnapi)->tx_pending / 4) 192#define TG3_TX_WAKEUP_THRESH(tnapi) ((tnapi)->tx_pending / 4)
193#define TG3_TX_BD_DMA_MAX 4096
193 194
194#define TG3_RAW_IP_ALIGN 2 195#define TG3_RAW_IP_ALIGN 2
195 196
@@ -5940,14 +5941,50 @@ static bool tg3_tx_frag_set(struct tg3_napi *tnapi, u32 *entry, u32 *budget,
5940 if (tg3_40bit_overflow_test(tp, map, len)) 5941 if (tg3_40bit_overflow_test(tp, map, len))
5941 hwbug = 1; 5942 hwbug = 1;
5942 5943
5943 if (*budget) { 5944 if (tg3_flag(tp, 4K_FIFO_LIMIT)) {
5945 u32 tmp_flag = flags & ~TXD_FLAG_END;
5946 while (len > TG3_TX_BD_DMA_MAX) {
5947 u32 frag_len = TG3_TX_BD_DMA_MAX;
5948 len -= TG3_TX_BD_DMA_MAX;
5949
5950 if (len) {
5951 tnapi->tx_buffers[*entry].fragmented = true;
5952 /* Avoid the 8byte DMA problem */
5953 if (len <= 8) {
5954 len += TG3_TX_BD_DMA_MAX / 2;
5955 frag_len = TG3_TX_BD_DMA_MAX / 2;
5956 }
5957 } else
5958 tmp_flag = flags;
5959
5960 if (*budget) {
5961 tg3_tx_set_bd(&tnapi->tx_ring[*entry], map,
5962 frag_len, tmp_flag, mss, vlan);
5963 (*budget)--;
5964 *entry = NEXT_TX(*entry);
5965 } else {
5966 hwbug = 1;
5967 break;
5968 }
5969
5970 map += frag_len;
5971 }
5972
5973 if (len) {
5974 if (*budget) {
5975 tg3_tx_set_bd(&tnapi->tx_ring[*entry], map,
5976 len, flags, mss, vlan);
5977 (*budget)--;
5978 *entry = NEXT_TX(*entry);
5979 } else {
5980 hwbug = 1;
5981 }
5982 }
5983 } else {
5944 tg3_tx_set_bd(&tnapi->tx_ring[*entry], map, 5984 tg3_tx_set_bd(&tnapi->tx_ring[*entry], map,
5945 len, flags, mss, vlan); 5985 len, flags, mss, vlan);
5946 (*budget)--; 5986 *entry = NEXT_TX(*entry);
5947 } else 5987 }
5948 hwbug = 1;
5949
5950 *entry = NEXT_TX(*entry);
5951 5988
5952 return hwbug; 5989 return hwbug;
5953} 5990}
@@ -13899,6 +13936,9 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
13899 if (tg3_flag(tp, 5755_PLUS)) 13936 if (tg3_flag(tp, 5755_PLUS))
13900 tg3_flag_set(tp, SHORT_DMA_BUG); 13937 tg3_flag_set(tp, SHORT_DMA_BUG);
13901 13938
13939 if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719)
13940 tg3_flag_set(tp, 4K_FIFO_LIMIT);
13941
13902 if (tg3_flag(tp, 5717_PLUS)) 13942 if (tg3_flag(tp, 5717_PLUS))
13903 tg3_flag_set(tp, LRG_PROD_RING_CAP); 13943 tg3_flag_set(tp, LRG_PROD_RING_CAP);
13904 13944
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index 466dd7add12..2ea456dd588 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -2905,6 +2905,7 @@ enum TG3_FLAGS {
2905 TG3_FLAG_57765_PLUS, 2905 TG3_FLAG_57765_PLUS,
2906 TG3_FLAG_APE_HAS_NCSI, 2906 TG3_FLAG_APE_HAS_NCSI,
2907 TG3_FLAG_5717_PLUS, 2907 TG3_FLAG_5717_PLUS,
2908 TG3_FLAG_4K_FIFO_LIMIT,
2908 2909
2909 /* Add new flags before this comment and TG3_FLAG_NUMBER_OF_FLAGS */ 2910 /* Add new flags before this comment and TG3_FLAG_NUMBER_OF_FLAGS */
2910 TG3_FLAG_NUMBER_OF_FLAGS, /* Last entry in enum TG3_FLAGS */ 2911 TG3_FLAG_NUMBER_OF_FLAGS, /* Last entry in enum TG3_FLAGS */