be2net: Implement initiate FW dump feature for Lancer
authorSomnath Kotur <somnath.kotur@emulex.com>
Thu, 30 May 2013 02:52:23 +0000 (02:52 +0000)
committerDavid S. Miller <davem@davemloft.net>
Sat, 1 Jun 2013 00:25:43 +0000 (17:25 -0700)
Added code to initiate FW dump via ethtool. Driver checks if the previous dump
has been cleared before initiating the dump. It doesn't initiate the dump
if it is not cleared.

Signed-off-by: Kalesh AP <kalesh.purayil@emulex.com>
Signed-off-by: Somnath Kotur <somnath.kotur@emulex.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/emulex/benet/be.h
drivers/net/ethernet/emulex/benet/be_cmds.c
drivers/net/ethernet/emulex/benet/be_cmds.h
drivers/net/ethernet/emulex/benet/be_ethtool.c
drivers/net/ethernet/emulex/benet/be_hw.h
drivers/net/ethernet/emulex/benet/be_main.c

index edce38bf83c9d6481a8998ec7653051ff620b315..fcc30a2d831b8dbdbd9a7cecff2e815a6d97abd2 100644 (file)
@@ -332,6 +332,9 @@ enum vf_state {
 #define BE_VF_UC_PMAC_COUNT            2
 #define BE_FLAGS_QNQ_ASYNC_EVT_RCVD            (1 << 11)
 
+/* Ethtool set_dump flags */
+#define LANCER_INITIATE_FW_DUMP                        0x1
+
 struct phy_info {
        u8 transceiver;
        u8 autoneg;
index a236ecd27cf384dea6af9e0a992a075dab306a5d..4d0ec3649a632dcb9e6fcf67eb638823f281b094 100644 (file)
@@ -3255,6 +3255,72 @@ err:
        return status;
 }
 
+static int lancer_wait_idle(struct be_adapter *adapter)
+{
+#define SLIPORT_IDLE_TIMEOUT 30
+       u32 reg_val;
+       int status = 0, i;
+
+       for (i = 0; i < SLIPORT_IDLE_TIMEOUT; i++) {
+               reg_val = ioread32(adapter->db + PHYSDEV_CONTROL_OFFSET);
+               if ((reg_val & PHYSDEV_CONTROL_INP_MASK) == 0)
+                       break;
+
+               ssleep(1);
+       }
+
+       if (i == SLIPORT_IDLE_TIMEOUT)
+               status = -1;
+
+       return status;
+}
+
+int lancer_physdev_ctrl(struct be_adapter *adapter, u32 mask)
+{
+       int status = 0;
+
+       status = lancer_wait_idle(adapter);
+       if (status)
+               return status;
+
+       iowrite32(mask, adapter->db + PHYSDEV_CONTROL_OFFSET);
+
+       return status;
+}
+
+/* Routine to check whether dump image is present or not */
+bool dump_present(struct be_adapter *adapter)
+{
+       u32 sliport_status = 0;
+
+       sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET);
+       return !!(sliport_status & SLIPORT_STATUS_DIP_MASK);
+}
+
+int lancer_initiate_dump(struct be_adapter *adapter)
+{
+       int status;
+
+       /* give firmware reset and diagnostic dump */
+       status = lancer_physdev_ctrl(adapter, PHYSDEV_CONTROL_FW_RESET_MASK |
+                                    PHYSDEV_CONTROL_DD_MASK);
+       if (status < 0) {
+               dev_err(&adapter->pdev->dev, "Firmware reset failed\n");
+               return status;
+       }
+
+       status = lancer_wait_idle(adapter);
+       if (status)
+               return status;
+
+       if (!dump_present(adapter)) {
+               dev_err(&adapter->pdev->dev, "Dump image not present\n");
+               return -1;
+       }
+
+       return 0;
+}
+
 /* Uses sync mcc */
 int be_cmd_enable_vf(struct be_adapter *adapter, u8 domain)
 {
index 025bdb0d1764e29ed92948a920a4273cf1172a35..5228d88c5a024e8e20be18e4f9fec69de7865e42 100644 (file)
@@ -1937,6 +1937,9 @@ extern int be_cmd_set_ext_fat_capabilites(struct be_adapter *adapter,
                                          struct be_dma_mem *cmd,
                                          struct be_fat_conf_params *cfgs);
 extern int lancer_wait_ready(struct be_adapter *adapter);
+extern int lancer_physdev_ctrl(struct be_adapter *adapter, u32 mask);
+extern int lancer_initiate_dump(struct be_adapter *adapter);
+extern bool dump_present(struct be_adapter *adapter);
 extern int lancer_test_and_set_rdy_state(struct be_adapter *adapter);
 extern int be_cmd_query_port_name(struct be_adapter *adapter, u8 *port_name);
 extern int be_cmd_get_func_config(struct be_adapter *adapter);
index f3ee07758198cef3f3e7053cff4ce9986102e756..4f8c941217cc017495736129373fe5d2ba40db60 100644 (file)
@@ -669,6 +669,34 @@ be_set_phys_id(struct net_device *netdev,
        return 0;
 }
 
+static int be_set_dump(struct net_device *netdev, struct ethtool_dump *dump)
+{
+       struct be_adapter *adapter = netdev_priv(netdev);
+       struct device *dev = &adapter->pdev->dev;
+       int status;
+
+       if (!lancer_chip(adapter)) {
+               dev_err(dev, "FW dump not supported\n");
+               return -EOPNOTSUPP;
+       }
+
+       if (dump_present(adapter)) {
+               dev_err(dev, "Previous dump not cleared, not forcing dump\n");
+               return 0;
+       }
+
+       switch (dump->flag) {
+       case LANCER_INITIATE_FW_DUMP:
+               status = lancer_initiate_dump(adapter);
+               if (!status)
+                       dev_info(dev, "F/w dump initiated successfully\n");
+               break;
+       default:
+               dev_err(dev, "Invalid dump level: 0x%x\n", dump->flag);
+               return -EINVAL;
+       }
+       return status;
+}
 
 static void
 be_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
@@ -1106,6 +1134,7 @@ const struct ethtool_ops be_ethtool_ops = {
        .set_pauseparam = be_set_pauseparam,
        .get_strings = be_get_stat_strings,
        .set_phys_id = be_set_phys_id,
+       .set_dump = be_set_dump,
        .get_msglevel = be_get_msg_level,
        .set_msglevel = be_set_msg_level,
        .get_sset_count = be_get_sset_count,
index 3c1099b47f2a7013da331c9e5b00dca0f0b80946..0311d9bfe8585742ff339e4a9c5098351b78e34f 100644 (file)
 #define PHYSDEV_CONTROL_OFFSET         0x414
 
 #define SLIPORT_STATUS_ERR_MASK                0x80000000
+#define SLIPORT_STATUS_DIP_MASK                0x02000000
 #define SLIPORT_STATUS_RN_MASK         0x01000000
 #define SLIPORT_STATUS_RDY_MASK                0x00800000
 #define SLI_PORT_CONTROL_IP_MASK       0x08000000
 #define PHYSDEV_CONTROL_FW_RESET_MASK  0x00000002
+#define PHYSDEV_CONTROL_DD_MASK                0x00000004
 #define PHYSDEV_CONTROL_INP_MASK       0x40000000
 
 #define SLIPORT_ERROR_NO_RESOURCE1     0x2
index 1140a86ff5eab656d5b1b313b8fe08927ed210e7..5d9044e4afe23c3236405ac55c3ff7a3b32f1260 100644 (file)
@@ -3551,40 +3551,6 @@ static int be_flash_skyhawk(struct be_adapter *adapter,
        return 0;
 }
 
-static int lancer_wait_idle(struct be_adapter *adapter)
-{
-#define SLIPORT_IDLE_TIMEOUT 30
-       u32 reg_val;
-       int status = 0, i;
-
-       for (i = 0; i < SLIPORT_IDLE_TIMEOUT; i++) {
-               reg_val = ioread32(adapter->db + PHYSDEV_CONTROL_OFFSET);
-               if ((reg_val & PHYSDEV_CONTROL_INP_MASK) == 0)
-                       break;
-
-               ssleep(1);
-       }
-
-       if (i == SLIPORT_IDLE_TIMEOUT)
-               status = -1;
-
-       return status;
-}
-
-static int lancer_fw_reset(struct be_adapter *adapter)
-{
-       int status = 0;
-
-       status = lancer_wait_idle(adapter);
-       if (status)
-               return status;
-
-       iowrite32(PHYSDEV_CONTROL_FW_RESET_MASK, adapter->db +
-                 PHYSDEV_CONTROL_OFFSET);
-
-       return status;
-}
-
 static int lancer_fw_download(struct be_adapter *adapter,
                                const struct firmware *fw)
 {
@@ -3662,7 +3628,8 @@ static int lancer_fw_download(struct be_adapter *adapter,
        }
 
        if (change_status == LANCER_FW_RESET_NEEDED) {
-               status = lancer_fw_reset(adapter);
+               status = lancer_physdev_ctrl(adapter,
+                                            PHYSDEV_CONTROL_FW_RESET_MASK);
                if (status) {
                        dev_err(&adapter->pdev->dev,
                                "Adapter busy for FW reset.\n"