You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
204 lines
6.9 KiB
204 lines
6.9 KiB
From 4eb487db76c9385d110d31f0b4b9e5c4f2393f5d Mon Sep 17 00:00:00 2001
|
|
From: Jonathan Toppins <jtoppins@redhat.com>
|
|
Date: Wed, 2 Oct 2019 18:23:22 -0400
|
|
Subject: [PATCH 67/96] [netdrv] bnxt_en: Discover firmware error recovery
|
|
capabilities
|
|
|
|
Message-id: <a51cd180b9f902d3548f54f26f56012fac00ce6c.1570027456.git.jtoppins@redhat.com>
|
|
Patchwork-id: 276487
|
|
O-Subject: [RHEL-8.2 PATCH 60/78] bnxt_en: Discover firmware error recovery capabilities.
|
|
Bugzilla: 1724766
|
|
RH-Acked-by: John Linville <linville@redhat.com>
|
|
RH-Acked-by: Jarod Wilson <jarod@redhat.com>
|
|
|
|
Call the new firmware API HWRM_ERROR_RECOVERY_QCFG if it is supported
|
|
to discover the firmware health and recovery capabilities and settings.
|
|
This feature allows the driver to reset the chip if firmware crashes and
|
|
becomes unresponsive.
|
|
|
|
Signed-off-by: Michael Chan <michael.chan@broadcom.com>
|
|
Signed-off-by: David S. Miller <davem@davemloft.net>
|
|
(cherry picked from commit 07f83d72d238f5d41b03d6142641129e8a7a0ec4)
|
|
Bugzilla: 1724766
|
|
Build Info: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=23809532
|
|
Tested: build, boot, basic ping
|
|
Signed-off-by: Jonathan Toppins <jtoppins@redhat.com>
|
|
Signed-off-by: Bruno Meneguele <bmeneg@redhat.com>
|
|
---
|
|
drivers/net/ethernet/broadcom/bnxt/bnxt.c | 77 +++++++++++++++++++++++++++++++
|
|
drivers/net/ethernet/broadcom/bnxt/bnxt.h | 38 +++++++++++++++
|
|
2 files changed, 115 insertions(+)
|
|
|
|
Index: src/drivers/net/ethernet/broadcom/bnxt/bnxt.c
|
|
===================================================================
|
|
--- src.orig/drivers/net/ethernet/broadcom/bnxt/bnxt.c 2020-02-06 16:23:19.143481640 +0100
|
|
+++ src/drivers/net/ethernet/broadcom/bnxt/bnxt.c 2020-02-06 16:23:19.289480300 +0100
|
|
@@ -6852,6 +6852,8 @@
|
|
bp->fw_cap |= BNXT_FW_CAP_PCIE_STATS_SUPPORTED;
|
|
if (flags & FUNC_QCAPS_RESP_FLAGS_EXT_STATS_SUPPORTED)
|
|
bp->fw_cap |= BNXT_FW_CAP_EXT_STATS_SUPPORTED;
|
|
+ if (flags & FUNC_QCAPS_RESP_FLAGS_ERROR_RECOVERY_CAPABLE)
|
|
+ bp->fw_cap |= BNXT_FW_CAP_ERROR_RECOVERY;
|
|
|
|
bp->tx_push_thresh = 0;
|
|
if (flags & FUNC_QCAPS_RESP_FLAGS_PUSH_MODE_SUPPORTED)
|
|
@@ -6953,6 +6955,74 @@
|
|
return rc;
|
|
}
|
|
|
|
+static int bnxt_hwrm_error_recovery_qcfg(struct bnxt *bp)
|
|
+{
|
|
+ struct hwrm_error_recovery_qcfg_output *resp = bp->hwrm_cmd_resp_addr;
|
|
+ struct bnxt_fw_health *fw_health = bp->fw_health;
|
|
+ struct hwrm_error_recovery_qcfg_input req = {0};
|
|
+ int rc, i;
|
|
+
|
|
+ if (!(bp->fw_cap & BNXT_FW_CAP_ERROR_RECOVERY))
|
|
+ return 0;
|
|
+
|
|
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_ERROR_RECOVERY_QCFG, -1, -1);
|
|
+ mutex_lock(&bp->hwrm_cmd_lock);
|
|
+ rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
|
|
+ if (rc)
|
|
+ goto err_recovery_out;
|
|
+ if (!fw_health) {
|
|
+ fw_health = kzalloc(sizeof(*fw_health), GFP_KERNEL);
|
|
+ bp->fw_health = fw_health;
|
|
+ if (!fw_health) {
|
|
+ rc = -ENOMEM;
|
|
+ goto err_recovery_out;
|
|
+ }
|
|
+ }
|
|
+ fw_health->flags = le32_to_cpu(resp->flags);
|
|
+ if ((fw_health->flags & ERROR_RECOVERY_QCFG_RESP_FLAGS_CO_CPU) &&
|
|
+ !(bp->fw_cap & BNXT_FW_CAP_KONG_MB_CHNL)) {
|
|
+ rc = -EINVAL;
|
|
+ goto err_recovery_out;
|
|
+ }
|
|
+ fw_health->polling_dsecs = le32_to_cpu(resp->driver_polling_freq);
|
|
+ fw_health->master_func_wait_dsecs =
|
|
+ le32_to_cpu(resp->master_func_wait_period);
|
|
+ fw_health->normal_func_wait_dsecs =
|
|
+ le32_to_cpu(resp->normal_func_wait_period);
|
|
+ fw_health->post_reset_wait_dsecs =
|
|
+ le32_to_cpu(resp->master_func_wait_period_after_reset);
|
|
+ fw_health->post_reset_max_wait_dsecs =
|
|
+ le32_to_cpu(resp->max_bailout_time_after_reset);
|
|
+ fw_health->regs[BNXT_FW_HEALTH_REG] =
|
|
+ le32_to_cpu(resp->fw_health_status_reg);
|
|
+ fw_health->regs[BNXT_FW_HEARTBEAT_REG] =
|
|
+ le32_to_cpu(resp->fw_heartbeat_reg);
|
|
+ fw_health->regs[BNXT_FW_RESET_CNT_REG] =
|
|
+ le32_to_cpu(resp->fw_reset_cnt_reg);
|
|
+ fw_health->regs[BNXT_FW_RESET_INPROG_REG] =
|
|
+ le32_to_cpu(resp->reset_inprogress_reg);
|
|
+ fw_health->fw_reset_inprog_reg_mask =
|
|
+ le32_to_cpu(resp->reset_inprogress_reg_mask);
|
|
+ fw_health->fw_reset_seq_cnt = resp->reg_array_cnt;
|
|
+ if (fw_health->fw_reset_seq_cnt >= 16) {
|
|
+ rc = -EINVAL;
|
|
+ goto err_recovery_out;
|
|
+ }
|
|
+ for (i = 0; i < fw_health->fw_reset_seq_cnt; i++) {
|
|
+ fw_health->fw_reset_seq_regs[i] =
|
|
+ le32_to_cpu(resp->reset_reg[i]);
|
|
+ fw_health->fw_reset_seq_vals[i] =
|
|
+ le32_to_cpu(resp->reset_reg_val[i]);
|
|
+ fw_health->fw_reset_seq_delay_msec[i] =
|
|
+ resp->delay_after_reset[i];
|
|
+ }
|
|
+err_recovery_out:
|
|
+ mutex_unlock(&bp->hwrm_cmd_lock);
|
|
+ if (rc)
|
|
+ bp->fw_cap &= ~BNXT_FW_CAP_ERROR_RECOVERY;
|
|
+ return rc;
|
|
+}
|
|
+
|
|
static int bnxt_hwrm_func_reset(struct bnxt *bp)
|
|
{
|
|
struct hwrm_func_reset_input req = {0};
|
|
@@ -10063,6 +10133,11 @@
|
|
netdev_warn(bp->dev, "hwrm query adv flow mgnt failure rc: %d\n",
|
|
rc);
|
|
|
|
+ rc = bnxt_hwrm_error_recovery_qcfg(bp);
|
|
+ if (rc)
|
|
+ netdev_warn(bp->dev, "hwrm query error recovery failure rc: %d\n",
|
|
+ rc);
|
|
+
|
|
rc = bnxt_hwrm_func_drv_rgtr(bp);
|
|
if (rc)
|
|
return -ENODEV;
|
|
@@ -11267,6 +11342,8 @@
|
|
bnxt_free_ctx_mem(bp);
|
|
kfree(bp->ctx);
|
|
bp->ctx = NULL;
|
|
+ kfree(bp->fw_health);
|
|
+ bp->fw_health = NULL;
|
|
bnxt_cleanup_pci(bp);
|
|
|
|
init_err_free:
|
|
Index: src/drivers/net/ethernet/broadcom/bnxt/bnxt.h
|
|
===================================================================
|
|
--- src.orig/drivers/net/ethernet/broadcom/bnxt/bnxt.h 2020-02-06 16:23:19.143481640 +0100
|
|
+++ src/drivers/net/ethernet/broadcom/bnxt/bnxt.h 2020-02-06 16:23:19.289480300 +0100
|
|
@@ -1333,6 +1333,41 @@
|
|
struct bnxt_ctx_pg_info *tqm_mem[9];
|
|
};
|
|
|
|
+struct bnxt_fw_health {
|
|
+ u32 flags;
|
|
+ u32 polling_dsecs;
|
|
+ u32 master_func_wait_dsecs;
|
|
+ u32 normal_func_wait_dsecs;
|
|
+ u32 post_reset_wait_dsecs;
|
|
+ u32 post_reset_max_wait_dsecs;
|
|
+ u32 regs[4];
|
|
+ u32 mapped_regs[4];
|
|
+#define BNXT_FW_HEALTH_REG 0
|
|
+#define BNXT_FW_HEARTBEAT_REG 1
|
|
+#define BNXT_FW_RESET_CNT_REG 2
|
|
+#define BNXT_FW_RESET_INPROG_REG 3
|
|
+ u32 fw_reset_inprog_reg_mask;
|
|
+ u32 last_fw_heartbeat;
|
|
+ u32 last_fw_reset_cnt;
|
|
+ u8 enabled:1;
|
|
+ u8 master:1;
|
|
+ u8 tmr_multiplier;
|
|
+ u8 tmr_counter;
|
|
+ u8 fw_reset_seq_cnt;
|
|
+ u32 fw_reset_seq_regs[16];
|
|
+ u32 fw_reset_seq_vals[16];
|
|
+ u32 fw_reset_seq_delay_msec[16];
|
|
+};
|
|
+
|
|
+#define BNXT_FW_HEALTH_REG_TYPE_MASK 3
|
|
+#define BNXT_FW_HEALTH_REG_TYPE_CFG 0
|
|
+#define BNXT_FW_HEALTH_REG_TYPE_GRC 1
|
|
+#define BNXT_FW_HEALTH_REG_TYPE_BAR0 2
|
|
+#define BNXT_FW_HEALTH_REG_TYPE_BAR1 3
|
|
+
|
|
+#define BNXT_FW_HEALTH_REG_TYPE(reg) ((reg) & BNXT_FW_HEALTH_REG_TYPE_MASK)
|
|
+#define BNXT_FW_HEALTH_REG_OFF(reg) ((reg) & ~BNXT_FW_HEALTH_REG_TYPE_MASK)
|
|
+
|
|
struct bnxt {
|
|
void __iomem *bar0;
|
|
void __iomem *bar1;
|
|
@@ -1581,6 +1616,7 @@
|
|
#define BNXT_FW_CAP_KONG_MB_CHNL 0x00000080
|
|
#define BNXT_FW_CAP_OVS_64BIT_HANDLE 0x00000400
|
|
#define BNXT_FW_CAP_TRUSTED_VF 0x00000800
|
|
+ #define BNXT_FW_CAP_ERROR_RECOVERY 0x00002000
|
|
#define BNXT_FW_CAP_PKG_VER 0x00004000
|
|
#define BNXT_FW_CAP_CFA_ADV_FLOW 0x00008000
|
|
#define BNXT_FW_CAP_CFA_RFS_RING_TBL_IDX 0x00010000
|
|
@@ -1666,6 +1702,8 @@
|
|
#define BNXT_UPDATE_PHY_SP_EVENT 16
|
|
#define BNXT_RING_COAL_NOW_SP_EVENT 17
|
|
|
|
+ struct bnxt_fw_health *fw_health;
|
|
+
|
|
struct bnxt_hw_resc hw_resc;
|
|
struct bnxt_pf_info pf;
|
|
struct bnxt_ctx_mem_info *ctx;
|