aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/tg3.c
diff options
context:
space:
mode:
authorMichael Chan <mchan@broadcom.com>2006-06-29 23:14:29 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-06-30 17:11:52 -0400
commitf92905deb9bc89834dac247ca1a0d905ebcf629b (patch)
tree63d3eb18e3dd5426791726eed8004087cfa7fbb4 /drivers/net/tg3.c
parent29315e8770c20cbfe607ad962d87867115a44555 (diff)
[TG3]: Add rx BD workaround
Add workaround to limit the burst size of rx BDs being DMA'ed to the chip. This works around hardware errata on a number of 5750, 5752, and 5755 chips. Signed-off-by: Michael Chan <mchan@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/tg3.c')
-rw-r--r--drivers/net/tg3.c30
1 files changed, 28 insertions, 2 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 2447fa3b471b..c32655ca3c46 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -3195,7 +3195,7 @@ static int tg3_vlan_rx(struct tg3 *tp, struct sk_buff *skb, u16 vlan_tag)
3195 */ 3195 */
3196static int tg3_rx(struct tg3 *tp, int budget) 3196static int tg3_rx(struct tg3 *tp, int budget)
3197{ 3197{
3198 u32 work_mask; 3198 u32 work_mask, rx_std_posted = 0;
3199 u32 sw_idx = tp->rx_rcb_ptr; 3199 u32 sw_idx = tp->rx_rcb_ptr;
3200 u16 hw_idx; 3200 u16 hw_idx;
3201 int received; 3201 int received;
@@ -3222,6 +3222,7 @@ static int tg3_rx(struct tg3 *tp, int budget)
3222 mapping); 3222 mapping);
3223 skb = tp->rx_std_buffers[desc_idx].skb; 3223 skb = tp->rx_std_buffers[desc_idx].skb;
3224 post_ptr = &tp->rx_std_ptr; 3224 post_ptr = &tp->rx_std_ptr;
3225 rx_std_posted++;
3225 } else if (opaque_key == RXD_OPAQUE_RING_JUMBO) { 3226 } else if (opaque_key == RXD_OPAQUE_RING_JUMBO) {
3226 dma_addr = pci_unmap_addr(&tp->rx_jumbo_buffers[desc_idx], 3227 dma_addr = pci_unmap_addr(&tp->rx_jumbo_buffers[desc_idx],
3227 mapping); 3228 mapping);
@@ -3309,6 +3310,15 @@ static int tg3_rx(struct tg3 *tp, int budget)
3309 3310
3310next_pkt: 3311next_pkt:
3311 (*post_ptr)++; 3312 (*post_ptr)++;
3313
3314 if (unlikely(rx_std_posted >= tp->rx_std_max_post)) {
3315 u32 idx = *post_ptr % TG3_RX_RING_SIZE;
3316
3317 tw32_rx_mbox(MAILBOX_RCV_STD_PROD_IDX +
3318 TG3_64BIT_REG_LOW, idx);
3319 work_mask &= ~RXD_OPAQUE_RING_STD;
3320 rx_std_posted = 0;
3321 }
3312next_pkt_nopost: 3322next_pkt_nopost:
3313 sw_idx++; 3323 sw_idx++;
3314 sw_idx %= TG3_RX_RCB_RING_SIZE(tp); 3324 sw_idx %= TG3_RX_RCB_RING_SIZE(tp);
@@ -5981,7 +5991,13 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
5981 } 5991 }
5982 5992
5983 /* Setup replenish threshold. */ 5993 /* Setup replenish threshold. */
5984 tw32(RCVBDI_STD_THRESH, tp->rx_pending / 8); 5994 val = tp->rx_pending / 8;
5995 if (val == 0)
5996 val = 1;
5997 else if (val > tp->rx_std_max_post)
5998 val = tp->rx_std_max_post;
5999
6000 tw32(RCVBDI_STD_THRESH, val);
5985 6001
5986 /* Initialize TG3_BDINFO's at: 6002 /* Initialize TG3_BDINFO's at:
5987 * RCVDBDI_STD_BD: standard eth size rx ring 6003 * RCVDBDI_STD_BD: standard eth size rx ring
@@ -10545,6 +10561,16 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
10545 (tp->tg3_flags & TG3_FLAG_PCIX_MODE) != 0) 10561 (tp->tg3_flags & TG3_FLAG_PCIX_MODE) != 0)
10546 tp->rx_offset = 0; 10562 tp->rx_offset = 0;
10547 10563
10564 tp->rx_std_max_post = TG3_RX_RING_SIZE;
10565
10566 /* Increment the rx prod index on the rx std ring by at most
10567 * 8 for these chips to workaround hw errata.
10568 */
10569 if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 ||
10570 GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 ||
10571 GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755)
10572 tp->rx_std_max_post = 8;
10573
10548 /* By default, disable wake-on-lan. User can change this 10574 /* By default, disable wake-on-lan. User can change this
10549 * using ETHTOOL_SWOL. 10575 * using ETHTOOL_SWOL.
10550 */ 10576 */