qlge: Restore promiscuous setting after reset.
[linux-2.6.git] / drivers / net / qlge / qlge_dbg.c
index 87e50d9..68a1c9b 100644 (file)
@@ -1,3 +1,5 @@
+#include <linux/slab.h>
+
 #include "qlge.h"
 
 /* Read a NIC register from the alternate function. */
@@ -331,6 +333,76 @@ static int ql_get_serdes_regs(struct ql_adapter *qdev,
        return 0;
 }
 
+static int ql_read_other_func_xgmac_reg(struct ql_adapter *qdev, u32 reg,
+                                                       u32 *data)
+{
+       int status = 0;
+
+       /* wait for reg to come ready */
+       status = ql_wait_other_func_reg_rdy(qdev, XGMAC_ADDR / 4,
+                                               XGMAC_ADDR_RDY, XGMAC_ADDR_XME);
+       if (status)
+               goto exit;
+
+       /* set up for reg read */
+       ql_write_other_func_reg(qdev, XGMAC_ADDR / 4, reg | XGMAC_ADDR_R);
+
+       /* wait for reg to come ready */
+       status = ql_wait_other_func_reg_rdy(qdev, XGMAC_ADDR / 4,
+                                               XGMAC_ADDR_RDY, XGMAC_ADDR_XME);
+       if (status)
+               goto exit;
+
+       /* get the data */
+       *data = ql_read_other_func_reg(qdev, XGMAC_DATA / 4);
+exit:
+       return status;
+}
+
+/* Read the 400 xgmac control/statistics registers
+ * skipping unused locations.
+ */
+static int ql_get_xgmac_regs(struct ql_adapter *qdev, u32 * buf,
+                                       unsigned int other_function)
+{
+       int status = 0;
+       int i;
+
+       for (i = PAUSE_SRC_LO; i < XGMAC_REGISTER_END; i += 4, buf++) {
+               /* We're reading 400 xgmac registers, but we filter out
+                * serveral locations that are non-responsive to reads.
+                */
+               if ((i == 0x00000114) ||
+                       (i == 0x00000118) ||
+                       (i == 0x0000013c) ||
+                       (i == 0x00000140) ||
+                       (i > 0x00000150 && i < 0x000001fc) ||
+                       (i > 0x00000278 && i < 0x000002a0) ||
+                       (i > 0x000002c0 && i < 0x000002cf) ||
+                       (i > 0x000002dc && i < 0x000002f0) ||
+                       (i > 0x000003c8 && i < 0x00000400) ||
+                       (i > 0x00000400 && i < 0x00000410) ||
+                       (i > 0x00000410 && i < 0x00000420) ||
+                       (i > 0x00000420 && i < 0x00000430) ||
+                       (i > 0x00000430 && i < 0x00000440) ||
+                       (i > 0x00000440 && i < 0x00000450) ||
+                       (i > 0x00000450 && i < 0x00000500) ||
+                       (i > 0x0000054c && i < 0x00000568) ||
+                       (i > 0x000005c8 && i < 0x00000600)) {
+                       if (other_function)
+                               status =
+                               ql_read_other_func_xgmac_reg(qdev, i, buf);
+                       else
+                               status = ql_read_xgmac_reg(qdev, i, buf);
+
+                       if (status)
+                               *buf = 0xdeadbeef;
+                       break;
+               }
+       }
+       return status;
+}
+
 static int ql_get_ets_regs(struct ql_adapter *qdev, u32 * buf)
 {
        int status = 0;
@@ -373,8 +445,8 @@ static int ql_get_cam_entries(struct ql_adapter *qdev, u32 * buf)
                status = ql_get_mac_addr_reg(qdev,
                                        MAC_ADDR_TYPE_CAM_MAC, i, value);
                if (status) {
-                       QPRINTK(qdev, DRV, ERR,
-                               "Failed read of mac index register.\n");
+                       netif_err(qdev, drv, qdev->ndev,
+                                 "Failed read of mac index register.\n");
                        goto err;
                }
                *buf++ = value[0];      /* lower MAC address */
@@ -385,8 +457,8 @@ static int ql_get_cam_entries(struct ql_adapter *qdev, u32 * buf)
                status = ql_get_mac_addr_reg(qdev,
                                        MAC_ADDR_TYPE_MULTI_MAC, i, value);
                if (status) {
-                       QPRINTK(qdev, DRV, ERR,
-                               "Failed read of mac index register.\n");
+                       netif_err(qdev, drv, qdev->ndev,
+                                 "Failed read of mac index register.\n");
                        goto err;
                }
                *buf++ = value[0];      /* lower Mcast address */
@@ -409,8 +481,8 @@ static int ql_get_routing_entries(struct ql_adapter *qdev, u32 * buf)
        for (i = 0; i < 16; i++) {
                status = ql_get_routing_reg(qdev, i, &value);
                if (status) {
-                       QPRINTK(qdev, DRV, ERR,
-                               "Failed read of routing index register.\n");
+                       netif_err(qdev, drv, qdev->ndev,
+                                 "Failed read of routing index register.\n");
                        goto err;
                } else {
                        *buf++ = value;
@@ -666,8 +738,7 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump)
        int i;
 
        if (!mpi_coredump) {
-               QPRINTK(qdev, DRV, ERR,
-                       "No memory available.\n");
+               netif_err(qdev, drv, qdev->ndev, "No memory available.\n");
                return -ENOMEM;
        }
 
@@ -679,8 +750,8 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump)
 
        status = ql_pause_mpi_risc(qdev);
        if (status) {
-               QPRINTK(qdev, DRV, ERR,
-                       "Failed RISC pause. Status = 0x%.08x\n", status);
+               netif_err(qdev, drv, qdev->ndev,
+                         "Failed RISC pause. Status = 0x%.08x\n", status);
                goto err;
        }
 
@@ -706,6 +777,17 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump)
                        sizeof(struct mpi_coredump_segment_header) +
                        sizeof(mpi_coredump->nic2_regs), "NIC2 Registers");
 
+       /* Get XGMac registers. (Segment 18, Rev C. step 21) */
+       ql_build_coredump_seg_header(&mpi_coredump->xgmac1_seg_hdr,
+                       NIC1_XGMAC_SEG_NUM,
+                       sizeof(struct mpi_coredump_segment_header) +
+                       sizeof(mpi_coredump->xgmac1), "NIC1 XGMac Registers");
+
+       ql_build_coredump_seg_header(&mpi_coredump->xgmac2_seg_hdr,
+                       NIC2_XGMAC_SEG_NUM,
+                       sizeof(struct mpi_coredump_segment_header) +
+                       sizeof(mpi_coredump->xgmac2), "NIC2 XGMac Registers");
+
        if (qdev->func & 1) {
                /* Odd means our function is NIC 2 */
                for (i = 0; i < NIC_REGS_DUMP_WORD_COUNT; i++)
@@ -715,6 +797,9 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump)
                for (i = 0; i < NIC_REGS_DUMP_WORD_COUNT; i++)
                        mpi_coredump->nic_regs[i] =
                        ql_read_other_func_reg(qdev, (i * sizeof(u32)) / 4);
+
+               ql_get_xgmac_regs(qdev, &mpi_coredump->xgmac2[0], 0);
+               ql_get_xgmac_regs(qdev, &mpi_coredump->xgmac1[0], 1);
        } else {
                /* Even means our function is NIC 1 */
                for (i = 0; i < NIC_REGS_DUMP_WORD_COUNT; i++)
@@ -723,6 +808,9 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump)
                for (i = 0; i < NIC_REGS_DUMP_WORD_COUNT; i++)
                        mpi_coredump->nic2_regs[i] =
                        ql_read_other_func_reg(qdev, (i * sizeof(u32)) / 4);
+
+               ql_get_xgmac_regs(qdev, &mpi_coredump->xgmac1[0], 0);
+               ql_get_xgmac_regs(qdev, &mpi_coredump->xgmac2[0], 1);
        }
 
        /* Rev C. Step 20a */
@@ -824,9 +912,9 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump)
 
        status = ql_get_serdes_regs(qdev, mpi_coredump);
        if (status) {
-               QPRINTK(qdev, DRV, ERR,
-                       "Failed Dump of Serdes Registers. Status = 0x%.08x\n",
-                       status);
+               netif_err(qdev, drv, qdev->ndev,
+                         "Failed Dump of Serdes Registers. Status = 0x%.08x\n",
+                         status);
                goto err;
        }
 
@@ -1090,16 +1178,16 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump)
        /* clear the pause */
        status = ql_unpause_mpi_risc(qdev);
        if (status) {
-               QPRINTK(qdev, DRV, ERR,
-                       "Failed RISC unpause. Status = 0x%.08x\n", status);
+               netif_err(qdev, drv, qdev->ndev,
+                         "Failed RISC unpause. Status = 0x%.08x\n", status);
                goto err;
        }
 
        /* Reset the RISC so we can dump RAM */
        status = ql_hard_reset_mpi_risc(qdev);
        if (status) {
-               QPRINTK(qdev, DRV, ERR,
-                       "Failed RISC reset. Status = 0x%.08x\n", status);
+               netif_err(qdev, drv, qdev->ndev,
+                         "Failed RISC reset. Status = 0x%.08x\n", status);
                goto err;
        }
 
@@ -1111,8 +1199,9 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump)
        status = ql_dump_risc_ram_area(qdev, &mpi_coredump->code_ram[0],
                                        CODE_RAM_ADDR, CODE_RAM_CNT);
        if (status) {
-               QPRINTK(qdev, DRV, ERR,
-                       "Failed Dump of CODE RAM. Status = 0x%.08x\n", status);
+               netif_err(qdev, drv, qdev->ndev,
+                         "Failed Dump of CODE RAM. Status = 0x%.08x\n",
+                         status);
                goto err;
        }
 
@@ -1125,8 +1214,9 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump)
        status = ql_dump_risc_ram_area(qdev, &mpi_coredump->memc_ram[0],
                                        MEMC_RAM_ADDR, MEMC_RAM_CNT);
        if (status) {
-               QPRINTK(qdev, DRV, ERR,
-                       "Failed Dump of MEMC RAM. Status = 0x%.08x\n", status);
+               netif_err(qdev, drv, qdev->ndev,
+                         "Failed Dump of MEMC RAM. Status = 0x%.08x\n",
+                         status);
                goto err;
        }
 err:
@@ -1135,6 +1225,26 @@ err:
 
 }
 
+static void ql_get_core_dump(struct ql_adapter *qdev)
+{
+       if (!ql_own_firmware(qdev)) {
+               netif_err(qdev, drv, qdev->ndev, "Don't own firmware!\n");
+               return;
+       }
+
+       if (!netif_running(qdev->ndev)) {
+               netif_err(qdev, ifup, qdev->ndev,
+                         "Force Coredump can only be done from interface that is up.\n");
+               return;
+       }
+
+       if (ql_mb_sys_err(qdev)) {
+               netif_err(qdev, ifup, qdev->ndev,
+                         "Fail force coredump with ql_mb_sys_err().\n");
+               return;
+       }
+}
+
 void ql_gen_reg_dump(struct ql_adapter *qdev,
                        struct ql_reg_dump *mpi_coredump)
 {
@@ -1210,6 +1320,9 @@ void ql_gen_reg_dump(struct ql_adapter *qdev,
        status = ql_get_ets_regs(qdev, &mpi_coredump->ets[0]);
        if (status)
                return;
+
+       if (test_bit(QL_FRC_COREDUMP, &qdev->flags))
+               ql_get_core_dump(qdev);
 }
 
 /* Coredump to messages log file using separate worker thread */
@@ -1222,11 +1335,12 @@ void ql_mpi_core_to_log(struct work_struct *work)
 
        count = sizeof(struct ql_mpi_coredump) / sizeof(u32);
        tmp = (u32 *)qdev->mpi_coredump;
-       QPRINTK(qdev, DRV, DEBUG, "Core is dumping to log file!\n");
+       netif_printk(qdev, drv, KERN_DEBUG, qdev->ndev,
+                    "Core is dumping to log file!\n");
 
        for (i = 0; i < count; i += 8) {
                printk(KERN_ERR "%.08x: %.08x %.08x %.08x %.08x %.08x "
-                       "%.08x %.08x %.08x \n", i,
+                       "%.08x %.08x %.08x\n", i,
                        tmp[i + 0],
                        tmp[i + 1],
                        tmp[i + 2],
@@ -1944,7 +2058,7 @@ void ql_dump_ob_mac_iocb(struct ob_mac_iocb_req *ob_mac_iocb)
               ob_mac_tso_iocb->flags2 & OB_MAC_TSO_IOCB_LSO ? "LSO" : "",
               ob_mac_tso_iocb->flags2 & OB_MAC_TSO_IOCB_UC ? "UC" : "",
               ob_mac_tso_iocb->flags2 & OB_MAC_TSO_IOCB_TC ? "TC" : "");
-       printk(KERN_ERR PFX "flags3          = %s %s %s \n",
+       printk(KERN_ERR PFX "flags3          = %s %s %s\n",
               ob_mac_tso_iocb->flags3 & OB_MAC_TSO_IOCB_IC ? "IC" : "",
               ob_mac_tso_iocb->flags3 & OB_MAC_TSO_IOCB_DFP ? "DFP" : "",
               ob_mac_tso_iocb->flags3 & OB_MAC_TSO_IOCB_V ? "V" : "");