summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Carlson <mcarlson@broadcom.com>2010-01-12 13:11:37 +0300
committerDavid S. Miller <davem@davemloft.net>2010-01-14 04:18:53 +0300
commit86cfe4ff02a51294cb2c974a8bedc7f648491df9 (patch)
treed2241293b99f32b07ec339ae7c05d96717fea8e4
parent13fa95b0398d65885a79c6e95a09976ee9f8c009 (diff)
downloadlinux-86cfe4ff02a51294cb2c974a8bedc7f648491df9.tar.xz
tg3: Fix std rx prod ring handling
There are some tg3 devices that require the driver to post new rx buffers in smaller increments. Commit 4361935afe3abc3e5a93006b99197fac1fabbd50, "tg3: Consider rx_std_prod_idx a hw mailbox" changed how the driver tracks the rx producer ring updates, but it does not make any special considerations for the above-mentioned devices. For those devices, it is possible for the driver to hit the special case path, which updates the hardware mailbox register but skips updating the shadow software mailbox member. If the special case path represents the final mailbox update for this ISR iteration, the hardware and software mailbox values will be out of sync. Ultimately, this will cause the driver to use a stale mailbox value on the next iteration, which will appear to the hardware as a large rx buffer update. Bad things ensue. The fix is to update the software shadow mailbox member when the special case path is taken. Signed-off-by: Matt Carlson <mcarlson@broadcom.com> Reviewed-by: Michael Chan <mchan@broadcom.com> Reported-by: Dmitry Torokhov <dmitry.torokhov@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/tg3.c5
1 files changed, 3 insertions, 2 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 5c77e6a48705..4e8b87d1ffa9 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -4693,8 +4693,9 @@ next_pkt:
(*post_ptr)++;
if (unlikely(rx_std_posted >= tp->rx_std_max_post)) {
- u32 idx = *post_ptr % TG3_RX_RING_SIZE;
- tw32_rx_mbox(TG3_RX_STD_PROD_IDX_REG, idx);
+ tpr->rx_std_prod_idx = std_prod_idx % TG3_RX_RING_SIZE;
+ tw32_rx_mbox(TG3_RX_STD_PROD_IDX_REG,
+ tpr->rx_std_prod_idx);
work_mask &= ~RXD_OPAQUE_RING_STD;
rx_std_posted = 0;
}