]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
qed: Wait for MCP halt and resume commands to take place
authorTomer Tayar <Tomer.Tayar@cavium.com>
Sun, 19 Aug 2018 21:01:43 +0000 (00:01 +0300)
committerJuerg Haefliger <juergh@canonical.com>
Wed, 24 Jul 2019 01:51:25 +0000 (19:51 -0600)
BugLink: https://bugs.launchpad.net/bugs/1836287
[ Upstream commit 76271809f49056f079e202bf6513d17b0d6dd34d ]

Successive iterations of halting and resuming the management chip (MCP)
might fail, since currently the driver doesn't wait for these operations to
actually take place.
This patch prevents the driver from moving forward before the operations
are reflected in the state register.

Signed-off-by: Tomer Tayar <Tomer.Tayar@cavium.com>
Signed-off-by: Ariel Elior <Ariel.Elior@cavium.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <alexander.levin@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Kamal Mostafa <kamal@canonical.com>
Signed-off-by: Khalid Elmously <khalid.elmously@canonical.com>
drivers/net/ethernet/qlogic/qed/qed_mcp.c
drivers/net/ethernet/qlogic/qed/qed_reg_addr.h

index 873cb2267d7988c517c857dccb4f21d15c838970..0f57060a50a1d276e2a643eb109702e05c967654 100644 (file)
@@ -1998,31 +1998,61 @@ qed_mcp_send_drv_version(struct qed_hwfn *p_hwfn,
        return rc;
 }
 
+/* A maximal 100 msec waiting time for the MCP to halt */
+#define QED_MCP_HALT_SLEEP_MS          10
+#define QED_MCP_HALT_MAX_RETRIES       10
+
 int qed_mcp_halt(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
 {
-       u32 resp = 0, param = 0;
+       u32 resp = 0, param = 0, cpu_state, cnt = 0;
        int rc;
 
        rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_MCP_HALT, 0, &resp,
                         &param);
-       if (rc)
+       if (rc) {
                DP_ERR(p_hwfn, "MCP response failure, aborting\n");
+               return rc;
+       }
 
-       return rc;
+       do {
+               msleep(QED_MCP_HALT_SLEEP_MS);
+               cpu_state = qed_rd(p_hwfn, p_ptt, MCP_REG_CPU_STATE);
+               if (cpu_state & MCP_REG_CPU_STATE_SOFT_HALTED)
+                       break;
+       } while (++cnt < QED_MCP_HALT_MAX_RETRIES);
+
+       if (cnt == QED_MCP_HALT_MAX_RETRIES) {
+               DP_NOTICE(p_hwfn,
+                         "Failed to halt the MCP [CPU_MODE = 0x%08x, CPU_STATE = 0x%08x]\n",
+                         qed_rd(p_hwfn, p_ptt, MCP_REG_CPU_MODE), cpu_state);
+               return -EBUSY;
+       }
+
+       return 0;
 }
 
+#define QED_MCP_RESUME_SLEEP_MS        10
+
 int qed_mcp_resume(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
 {
-       u32 value, cpu_mode;
+       u32 cpu_mode, cpu_state;
 
        qed_wr(p_hwfn, p_ptt, MCP_REG_CPU_STATE, 0xffffffff);
 
-       value = qed_rd(p_hwfn, p_ptt, MCP_REG_CPU_MODE);
-       value &= ~MCP_REG_CPU_MODE_SOFT_HALT;
-       qed_wr(p_hwfn, p_ptt, MCP_REG_CPU_MODE, value);
        cpu_mode = qed_rd(p_hwfn, p_ptt, MCP_REG_CPU_MODE);
+       cpu_mode &= ~MCP_REG_CPU_MODE_SOFT_HALT;
+       qed_wr(p_hwfn, p_ptt, MCP_REG_CPU_MODE, cpu_mode);
+       msleep(QED_MCP_RESUME_SLEEP_MS);
+       cpu_state = qed_rd(p_hwfn, p_ptt, MCP_REG_CPU_STATE);
 
-       return (cpu_mode & MCP_REG_CPU_MODE_SOFT_HALT) ? -EAGAIN : 0;
+       if (cpu_state & MCP_REG_CPU_STATE_SOFT_HALTED) {
+               DP_NOTICE(p_hwfn,
+                         "Failed to resume the MCP [CPU_MODE = 0x%08x, CPU_STATE = 0x%08x]\n",
+                         cpu_mode, cpu_state);
+               return -EBUSY;
+       }
+
+       return 0;
 }
 
 int qed_mcp_ov_update_current_config(struct qed_hwfn *p_hwfn,
index 0cdb4337b3a057befc98b3c69c0d65085d81b918..887cfb16b53e2d22a2b86d0a73d70ebcd6476547 100644 (file)
        0
 #define MCP_REG_CPU_STATE \
        0xe05004UL
+#define MCP_REG_CPU_STATE_SOFT_HALTED  (0x1UL << 10)
 #define MCP_REG_CPU_EVENT_MASK \
        0xe05008UL
 #define PGLUE_B_REG_PF_BAR0_SIZE \