Commit f92905de authored by Michael Chan's avatar Michael Chan Committed by David S. Miller

[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: default avatarMichael Chan <mchan@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 29315e87
...@@ -3195,7 +3195,7 @@ static int tg3_vlan_rx(struct tg3 *tp, struct sk_buff *skb, u16 vlan_tag) ...@@ -3195,7 +3195,7 @@ static int tg3_vlan_rx(struct tg3 *tp, struct sk_buff *skb, u16 vlan_tag)
*/ */
static int tg3_rx(struct tg3 *tp, int budget) static int tg3_rx(struct tg3 *tp, int budget)
{ {
u32 work_mask; u32 work_mask, rx_std_posted = 0;
u32 sw_idx = tp->rx_rcb_ptr; u32 sw_idx = tp->rx_rcb_ptr;
u16 hw_idx; u16 hw_idx;
int received; int received;
...@@ -3222,6 +3222,7 @@ static int tg3_rx(struct tg3 *tp, int budget) ...@@ -3222,6 +3222,7 @@ static int tg3_rx(struct tg3 *tp, int budget)
mapping); mapping);
skb = tp->rx_std_buffers[desc_idx].skb; skb = tp->rx_std_buffers[desc_idx].skb;
post_ptr = &tp->rx_std_ptr; post_ptr = &tp->rx_std_ptr;
rx_std_posted++;
} else if (opaque_key == RXD_OPAQUE_RING_JUMBO) { } else if (opaque_key == RXD_OPAQUE_RING_JUMBO) {
dma_addr = pci_unmap_addr(&tp->rx_jumbo_buffers[desc_idx], dma_addr = pci_unmap_addr(&tp->rx_jumbo_buffers[desc_idx],
mapping); mapping);
...@@ -3309,6 +3310,15 @@ static int tg3_rx(struct tg3 *tp, int budget) ...@@ -3309,6 +3310,15 @@ static int tg3_rx(struct tg3 *tp, int budget)
next_pkt: next_pkt:
(*post_ptr)++; (*post_ptr)++;
if (unlikely(rx_std_posted >= tp->rx_std_max_post)) {
u32 idx = *post_ptr % TG3_RX_RING_SIZE;
tw32_rx_mbox(MAILBOX_RCV_STD_PROD_IDX +
TG3_64BIT_REG_LOW, idx);
work_mask &= ~RXD_OPAQUE_RING_STD;
rx_std_posted = 0;
}
next_pkt_nopost: next_pkt_nopost:
sw_idx++; sw_idx++;
sw_idx %= TG3_RX_RCB_RING_SIZE(tp); sw_idx %= TG3_RX_RCB_RING_SIZE(tp);
...@@ -5981,7 +5991,13 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) ...@@ -5981,7 +5991,13 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
} }
/* Setup replenish threshold. */ /* Setup replenish threshold. */
tw32(RCVBDI_STD_THRESH, tp->rx_pending / 8); val = tp->rx_pending / 8;
if (val == 0)
val = 1;
else if (val > tp->rx_std_max_post)
val = tp->rx_std_max_post;
tw32(RCVBDI_STD_THRESH, val);
/* Initialize TG3_BDINFO's at: /* Initialize TG3_BDINFO's at:
* RCVDBDI_STD_BD: standard eth size rx ring * RCVDBDI_STD_BD: standard eth size rx ring
...@@ -10545,6 +10561,16 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) ...@@ -10545,6 +10561,16 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
(tp->tg3_flags & TG3_FLAG_PCIX_MODE) != 0) (tp->tg3_flags & TG3_FLAG_PCIX_MODE) != 0)
tp->rx_offset = 0; tp->rx_offset = 0;
tp->rx_std_max_post = TG3_RX_RING_SIZE;
/* Increment the rx prod index on the rx std ring by at most
* 8 for these chips to workaround hw errata.
*/
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755)
tp->rx_std_max_post = 8;
/* By default, disable wake-on-lan. User can change this /* By default, disable wake-on-lan. User can change this
* using ETHTOOL_SWOL. * using ETHTOOL_SWOL.
*/ */
......
...@@ -2137,6 +2137,7 @@ struct tg3 { ...@@ -2137,6 +2137,7 @@ struct tg3 {
struct tg3_rx_buffer_desc *rx_std; struct tg3_rx_buffer_desc *rx_std;
struct ring_info *rx_std_buffers; struct ring_info *rx_std_buffers;
dma_addr_t rx_std_mapping; dma_addr_t rx_std_mapping;
u32 rx_std_max_post;
struct tg3_rx_buffer_desc *rx_jumbo; struct tg3_rx_buffer_desc *rx_jumbo;
struct ring_info *rx_jumbo_buffers; struct ring_info *rx_jumbo_buffers;
......
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