summaryrefslogtreecommitdiff
path: root/drivers/net/tg3.c
diff options
context:
space:
mode:
authorMatt Carlson <mcarlson@broadcom.com>2011-04-13 11:05:05 +0000
committerDavid S. Miller <davem@davemloft.net>2011-04-13 17:10:06 -0700
commite64de4e6c660dae6d6370b3acb59d5d5cc9ecf20 (patch)
treebbe7e74f51c2085ce0a3c9e8536a48061647d3b8 /drivers/net/tg3.c
parent97bd8e491d1786f0020372a5a470bb8b3184856f (diff)
downloadlwn-e64de4e6c660dae6d6370b3acb59d5d5cc9ecf20.tar.gz
lwn-e64de4e6c660dae6d6370b3acb59d5d5cc9ecf20.zip
tg3: Dump registers when status block shows errors
This patch monitors the error bit of the status word within the status block. If it is set, the driver will dump the driver state after validating the error and then reset the chip. Signed-off-by: Matt Carlson <mcarlson@broadcom.com> Signed-off-by: Michael Chan <mchan@broadcom.com> Reviewed-by: Benjamin Li <benli@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/tg3.c')
-rw-r--r--drivers/net/tg3.c40
1 files changed, 39 insertions, 1 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 72744353b1cb..b61b52f0a9fb 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -5259,6 +5259,40 @@ tx_recovery:
return work_done;
}
+static void tg3_process_error(struct tg3 *tp)
+{
+ u32 val;
+ bool real_error = false;
+
+ if (tp->tg3_flags & TG3_FLAG_ERROR_PROCESSED)
+ return;
+
+ /* Check Flow Attention register */
+ val = tr32(HOSTCC_FLOW_ATTN);
+ if (val & ~HOSTCC_FLOW_ATTN_MBUF_LWM) {
+ netdev_err(tp->dev, "FLOW Attention error. Resetting chip.\n");
+ real_error = true;
+ }
+
+ if (tr32(MSGINT_STATUS) & ~MSGINT_STATUS_MSI_REQ) {
+ netdev_err(tp->dev, "MSI Status error. Resetting chip.\n");
+ real_error = true;
+ }
+
+ if (tr32(RDMAC_STATUS) || tr32(WDMAC_STATUS)) {
+ netdev_err(tp->dev, "DMA Status error. Resetting chip.\n");
+ real_error = true;
+ }
+
+ if (!real_error)
+ return;
+
+ tg3_dump_state(tp);
+
+ tp->tg3_flags |= TG3_FLAG_ERROR_PROCESSED;
+ schedule_work(&tp->reset_task);
+}
+
static int tg3_poll(struct napi_struct *napi, int budget)
{
struct tg3_napi *tnapi = container_of(napi, struct tg3_napi, napi);
@@ -5267,6 +5301,9 @@ static int tg3_poll(struct napi_struct *napi, int budget)
struct tg3_hw_status *sblk = tnapi->hw_status;
while (1) {
+ if (sblk->status & SD_STATUS_ERROR)
+ tg3_process_error(tp);
+
tg3_poll_link(tp);
work_done = tg3_poll_work(tnapi, work_done, budget);
@@ -7316,7 +7353,8 @@ static int tg3_chip_reset(struct tg3 *tp)
tg3_restore_pci_state(tp);
- tp->tg3_flags &= ~TG3_FLAG_CHIP_RESETTING;
+ tp->tg3_flags &= ~(TG3_FLAG_CHIP_RESETTING |
+ TG3_FLAG_ERROR_PROCESSED);
val = 0;
if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)