+static inline void tg3_rd32_loop(struct tg3 *tp, u32 *dst, u32 off, u32 len)
+{
+ int i;
+
+ dst = (u32 *)((u8 *)dst + off);
+ for (i = 0; i < len; i += sizeof(u32))
+ *dst++ = tr32(off + i);
+}
+
+static void tg3_dump_legacy_regs(struct tg3 *tp, u32 *regs)
+{
+ tg3_rd32_loop(tp, regs, TG3PCI_VENDOR, 0xb0);
+ tg3_rd32_loop(tp, regs, MAILBOX_INTERRUPT_0, 0x200);
+ tg3_rd32_loop(tp, regs, MAC_MODE, 0x4f0);
+ tg3_rd32_loop(tp, regs, SNDDATAI_MODE, 0xe0);
+ tg3_rd32_loop(tp, regs, SNDDATAC_MODE, 0x04);
+ tg3_rd32_loop(tp, regs, SNDBDS_MODE, 0x80);
+ tg3_rd32_loop(tp, regs, SNDBDI_MODE, 0x48);
+ tg3_rd32_loop(tp, regs, SNDBDC_MODE, 0x04);
+ tg3_rd32_loop(tp, regs, RCVLPC_MODE, 0x20);
+ tg3_rd32_loop(tp, regs, RCVLPC_SELLST_BASE, 0x15c);
+ tg3_rd32_loop(tp, regs, RCVDBDI_MODE, 0x0c);
+ tg3_rd32_loop(tp, regs, RCVDBDI_JUMBO_BD, 0x3c);
+ tg3_rd32_loop(tp, regs, RCVDBDI_BD_PROD_IDX_0, 0x44);
+ tg3_rd32_loop(tp, regs, RCVDCC_MODE, 0x04);
+ tg3_rd32_loop(tp, regs, RCVBDI_MODE, 0x20);
+ tg3_rd32_loop(tp, regs, RCVCC_MODE, 0x14);
+ tg3_rd32_loop(tp, regs, RCVLSC_MODE, 0x08);
+ tg3_rd32_loop(tp, regs, MBFREE_MODE, 0x08);
+ tg3_rd32_loop(tp, regs, HOSTCC_MODE, 0x100);
+
+ if (tg3_flag(tp, SUPPORT_MSIX))
+ tg3_rd32_loop(tp, regs, HOSTCC_RXCOL_TICKS_VEC1, 0x180);
+
+ tg3_rd32_loop(tp, regs, MEMARB_MODE, 0x10);
+ tg3_rd32_loop(tp, regs, BUFMGR_MODE, 0x58);
+ tg3_rd32_loop(tp, regs, RDMAC_MODE, 0x08);
+ tg3_rd32_loop(tp, regs, WDMAC_MODE, 0x08);
+ tg3_rd32_loop(tp, regs, RX_CPU_MODE, 0x04);
+ tg3_rd32_loop(tp, regs, RX_CPU_STATE, 0x04);
+ tg3_rd32_loop(tp, regs, RX_CPU_PGMCTR, 0x04);
+ tg3_rd32_loop(tp, regs, RX_CPU_HWBKPT, 0x04);
+
+ if (!tg3_flag(tp, 5705_PLUS)) {
+ tg3_rd32_loop(tp, regs, TX_CPU_MODE, 0x04);
+ tg3_rd32_loop(tp, regs, TX_CPU_STATE, 0x04);
+ tg3_rd32_loop(tp, regs, TX_CPU_PGMCTR, 0x04);
+ }
+
+ tg3_rd32_loop(tp, regs, GRCMBOX_INTERRUPT_0, 0x110);
+ tg3_rd32_loop(tp, regs, FTQ_RESET, 0x120);
+ tg3_rd32_loop(tp, regs, MSGINT_MODE, 0x0c);
+ tg3_rd32_loop(tp, regs, DMAC_MODE, 0x04);
+ tg3_rd32_loop(tp, regs, GRC_MODE, 0x4c);
+
+ if (tg3_flag(tp, NVRAM))
+ tg3_rd32_loop(tp, regs, NVRAM_CMD, 0x24);
+}
+
+static void tg3_dump_state(struct tg3 *tp)
+{
+ int i;
+ u32 *regs;
+
+ regs = kzalloc(TG3_REG_BLK_SIZE, GFP_ATOMIC);
+ if (!regs) {
+ netdev_err(tp->dev, "Failed allocating register dump buffer\n");
+ return;
+ }
+
+ if (tg3_flag(tp, PCI_EXPRESS)) {
+ /* Read up to but not including private PCI registers */
+ for (i = 0; i < TG3_PCIE_TLDLPL_PORT; i += sizeof(u32))
+ regs[i / sizeof(u32)] = tr32(i);
+ } else
+ tg3_dump_legacy_regs(tp, regs);
+
+ for (i = 0; i < TG3_REG_BLK_SIZE / sizeof(u32); i += 4) {
+ if (!regs[i + 0] && !regs[i + 1] &&
+ !regs[i + 2] && !regs[i + 3])
+ continue;
+
+ netdev_err(tp->dev, "0x%08x: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
+ i * 4,
+ regs[i + 0], regs[i + 1], regs[i + 2], regs[i + 3]);
+ }
+
+ kfree(regs);
+
+ for (i = 0; i < tp->irq_cnt; i++) {
+ struct tg3_napi *tnapi = &tp->napi[i];
+
+ /* SW status block */
+ netdev_err(tp->dev,
+ "%d: Host status block [%08x:%08x:(%04x:%04x:%04x):(%04x:%04x)]\n",
+ i,
+ tnapi->hw_status->status,
+ tnapi->hw_status->status_tag,
+ tnapi->hw_status->rx_jumbo_consumer,
+ tnapi->hw_status->rx_consumer,
+ tnapi->hw_status->rx_mini_consumer,
+ tnapi->hw_status->idx[0].rx_producer,
+ tnapi->hw_status->idx[0].tx_consumer);
+
+ netdev_err(tp->dev,
+ "%d: NAPI info [%08x:%08x:(%04x:%04x:%04x):%04x:(%04x:%04x:%04x:%04x)]\n",
+ i,
+ tnapi->last_tag, tnapi->last_irq_tag,
+ tnapi->tx_prod, tnapi->tx_cons, tnapi->tx_pending,
+ tnapi->rx_rcb_ptr,
+ tnapi->prodring.rx_std_prod_idx,
+ tnapi->prodring.rx_std_cons_idx,
+ tnapi->prodring.rx_jmb_prod_idx,
+ tnapi->prodring.rx_jmb_cons_idx);
+ }
+}
+