qlge: Add module param to force firmware core dump.
authorRon Mercer <ron.mercer@qlogic.com>
Fri, 15 Jan 2010 13:31:34 +0000 (13:31 +0000)
committerDavid S. Miller <davem@davemloft.net>
Sat, 16 Jan 2010 09:01:55 +0000 (01:01 -0800)
Default setting is 'off', don't allow force firmware dump.

Signed-off-by: Ron Mercer <ron.mercer@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/qlge/qlge.h
drivers/net/qlge/qlge_dbg.c
drivers/net/qlge/qlge_main.c
drivers/net/qlge/qlge_mpi.c

index 05feb03..9169c4c 100644 (file)
@@ -2004,6 +2004,7 @@ enum {
        QL_CAM_RT_SET = 8,
        QL_SELFTEST = 9,
        QL_LB_LINK_UP = 10,
+       QL_FRC_COREDUMP = 11,
 };
 
 /* link_status bit definitions */
@@ -2230,6 +2231,7 @@ int ql_dump_risc_ram_area(struct ql_adapter *qdev, void *buf,
                u32 ram_addr, int word_count);
 int ql_core_dump(struct ql_adapter *qdev,
                struct ql_mpi_coredump *mpi_coredump);
+int ql_mb_sys_err(struct ql_adapter *qdev);
 int ql_mb_about_fw(struct ql_adapter *qdev);
 int ql_wol(struct ql_adapter *qdev);
 int ql_mb_wol_set_magic(struct ql_adapter *qdev, u32 enable_wol);
@@ -2246,6 +2248,7 @@ void ql_gen_reg_dump(struct ql_adapter *qdev,
                        struct ql_reg_dump *mpi_coredump);
 netdev_tx_t ql_lb_send(struct sk_buff *skb, struct net_device *ndev);
 void ql_check_lb_frame(struct ql_adapter *, struct sk_buff *);
+int ql_own_firmware(struct ql_adapter *qdev);
 int ql_clean_lb_rx_ring(struct rx_ring *rx_ring, int budget);
 
 #if 1
index ec4349a..57df835 100644 (file)
@@ -1222,6 +1222,28 @@ err:
 
 }
 
+static void ql_get_core_dump(struct ql_adapter *qdev)
+{
+       if (!ql_own_firmware(qdev)) {
+               QPRINTK(qdev, DRV, ERR, "%s: Don't own firmware!\n",
+                                       qdev->ndev->name);
+               return;
+       }
+
+       if (!netif_running(qdev->ndev)) {
+               QPRINTK(qdev, IFUP, ERR,
+                       "Force Coredump can only be done from interface "
+                       "that is up.\n");
+               return;
+       }
+
+       if (ql_mb_sys_err(qdev)) {
+               QPRINTK(qdev, IFUP, ERR,
+                       "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)
 {
@@ -1297,6 +1319,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 */
index e588923..95fb63d 100644 (file)
@@ -77,8 +77,13 @@ static int qlge_mpi_coredump;
 module_param(qlge_mpi_coredump, int, 0);
 MODULE_PARM_DESC(qlge_mpi_coredump,
                "Option to enable MPI firmware dump. "
-               "Default is OFF - Do Not allocate memory. "
-               "Do not perform firmware coredump.");
+               "Default is OFF - Do Not allocate memory. ");
+
+static int qlge_force_coredump;
+module_param(qlge_force_coredump, int, 0);
+MODULE_PARM_DESC(qlge_force_coredump,
+               "Option to allow force of firmware core dump. "
+               "Default is OFF - Do not allow.");
 
 static DEFINE_PCI_DEVICE_TABLE(qlge_pci_tbl) = {
        {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, QLGE_DEVICE_ID_8012)},
@@ -4496,6 +4501,8 @@ static int __devinit ql_init_device(struct pci_dev *pdev,
                        err = -ENOMEM;
                        goto err_out;
                }
+               if (qlge_force_coredump)
+                       set_bit(QL_FRC_COREDUMP, &qdev->flags);
        }
        /* make sure the EEPROM is good */
        err = qdev->nic_ops->get_flash(qdev);
index 3304eb7..e2c846f 100644 (file)
@@ -607,6 +607,22 @@ end:
        return status;
 }
 
+int ql_mb_sys_err(struct ql_adapter *qdev)
+{
+       struct mbox_params mbc;
+       struct mbox_params *mbcp = &mbc;
+       int status;
+
+       memset(mbcp, 0, sizeof(struct mbox_params));
+
+       mbcp->in_count = 1;
+       mbcp->out_count = 0;
+
+       mbcp->mbox_in[0] = MB_CMD_MAKE_SYS_ERR;
+
+       status = ql_mailbox_command(qdev, mbcp);
+       return status;
+}
 
 /* Get MPI firmware version. This will be used for
  * driver banner and for ethtool info.