Commit e31aa987 authored by Matt Carlson's avatar Matt Carlson Committed by David S. Miller

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: default avatarMatt Carlson <mcarlson@broadcom.com>
Reviewed-by: default avatarMichael Chan <mchan@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 84b67b27
...@@ -190,6 +190,7 @@ static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits) ...@@ -190,6 +190,7 @@ static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits)
/* minimum number of free TX descriptors required to wake up TX process */ /* minimum number of free TX descriptors required to wake up TX process */
#define TG3_TX_WAKEUP_THRESH(tnapi) ((tnapi)->tx_pending / 4) #define TG3_TX_WAKEUP_THRESH(tnapi) ((tnapi)->tx_pending / 4)
#define TG3_TX_BD_DMA_MAX 4096
#define TG3_RAW_IP_ALIGN 2 #define TG3_RAW_IP_ALIGN 2
...@@ -5940,14 +5941,50 @@ static bool tg3_tx_frag_set(struct tg3_napi *tnapi, u32 *entry, u32 *budget, ...@@ -5940,14 +5941,50 @@ static bool tg3_tx_frag_set(struct tg3_napi *tnapi, u32 *entry, u32 *budget,
if (tg3_40bit_overflow_test(tp, map, len)) if (tg3_40bit_overflow_test(tp, map, len))
hwbug = 1; hwbug = 1;
if (tg3_flag(tp, 4K_FIFO_LIMIT)) {
u32 tmp_flag = flags & ~TXD_FLAG_END;
while (len > TG3_TX_BD_DMA_MAX) {
u32 frag_len = TG3_TX_BD_DMA_MAX;
len -= TG3_TX_BD_DMA_MAX;
if (len) {
tnapi->tx_buffers[*entry].fragmented = true;
/* Avoid the 8byte DMA problem */
if (len <= 8) {
len += TG3_TX_BD_DMA_MAX / 2;
frag_len = TG3_TX_BD_DMA_MAX / 2;
}
} else
tmp_flag = flags;
if (*budget) { if (*budget) {
tg3_tx_set_bd(&tnapi->tx_ring[*entry], map, tg3_tx_set_bd(&tnapi->tx_ring[*entry], map,
len, flags, mss, vlan); frag_len, tmp_flag, mss, vlan);
(*budget)--; (*budget)--;
} else *entry = NEXT_TX(*entry);
} else {
hwbug = 1; hwbug = 1;
break;
}
map += frag_len;
}
if (len) {
if (*budget) {
tg3_tx_set_bd(&tnapi->tx_ring[*entry], map,
len, flags, mss, vlan);
(*budget)--;
*entry = NEXT_TX(*entry); *entry = NEXT_TX(*entry);
} else {
hwbug = 1;
}
}
} else {
tg3_tx_set_bd(&tnapi->tx_ring[*entry], map,
len, flags, mss, vlan);
*entry = NEXT_TX(*entry);
}
return hwbug; return hwbug;
} }
...@@ -13899,6 +13936,9 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) ...@@ -13899,6 +13936,9 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
if (tg3_flag(tp, 5755_PLUS)) if (tg3_flag(tp, 5755_PLUS))
tg3_flag_set(tp, SHORT_DMA_BUG); tg3_flag_set(tp, SHORT_DMA_BUG);
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719)
tg3_flag_set(tp, 4K_FIFO_LIMIT);
if (tg3_flag(tp, 5717_PLUS)) if (tg3_flag(tp, 5717_PLUS))
tg3_flag_set(tp, LRG_PROD_RING_CAP); tg3_flag_set(tp, LRG_PROD_RING_CAP);
......
...@@ -2905,6 +2905,7 @@ enum TG3_FLAGS { ...@@ -2905,6 +2905,7 @@ enum TG3_FLAGS {
TG3_FLAG_57765_PLUS, TG3_FLAG_57765_PLUS,
TG3_FLAG_APE_HAS_NCSI, TG3_FLAG_APE_HAS_NCSI,
TG3_FLAG_5717_PLUS, TG3_FLAG_5717_PLUS,
TG3_FLAG_4K_FIFO_LIMIT,
/* Add new flags before this comment and TG3_FLAG_NUMBER_OF_FLAGS */ /* Add new flags before this comment and TG3_FLAG_NUMBER_OF_FLAGS */
TG3_FLAG_NUMBER_OF_FLAGS, /* Last entry in enum TG3_FLAGS */ TG3_FLAG_NUMBER_OF_FLAGS, /* Last entry in enum TG3_FLAGS */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment