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.
113 lines
4.1 KiB
113 lines
4.1 KiB
From c587c80cd46091f35a6d063dd4c515f600cc91b9 Mon Sep 17 00:00:00 2001
|
|
From: Jonathan Toppins <jtoppins@redhat.com>
|
|
Date: Wed, 2 Oct 2019 18:23:32 -0400
|
|
Subject: [PATCH 77/96] [netdrv] bnxt_en: Add RESET_FW state logic to
|
|
bnxt_fw_reset_task()
|
|
|
|
Message-id: <4dcd528def5dab7e4524d88a3aa5306d1e6d561f.1570027456.git.jtoppins@redhat.com>
|
|
Patchwork-id: 276490
|
|
O-Subject: [RHEL-8.2 PATCH 70/78] bnxt_en: Add RESET_FW state logic to bnxt_fw_reset_task().
|
|
Bugzilla: 1724766
|
|
RH-Acked-by: John Linville <linville@redhat.com>
|
|
RH-Acked-by: Jarod Wilson <jarod@redhat.com>
|
|
|
|
This state handles driver initiated chip reset during error recovery.
|
|
Only the master function will perform this step during error recovery.
|
|
The next patch will add code to initiate this reset from the master
|
|
function.
|
|
|
|
Signed-off-by: Michael Chan <michael.chan@broadcom.com>
|
|
Signed-off-by: David S. Miller <davem@davemloft.net>
|
|
(cherry picked from commit cbb51067a5f5fbae733283b67fc8013881eb4bb1)
|
|
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 | 64 +++++++++++++++++++++++++++++++
|
|
1 file changed, 64 insertions(+)
|
|
|
|
Index: src/drivers/net/ethernet/broadcom/bnxt/bnxt.c
|
|
===================================================================
|
|
--- src.orig/drivers/net/ethernet/broadcom/bnxt/bnxt.c 2020-02-06 16:23:20.602468248 +0100
|
|
+++ src/drivers/net/ethernet/broadcom/bnxt/bnxt.c 2020-02-06 16:23:20.736467018 +0100
|
|
@@ -10407,6 +10407,62 @@
|
|
return 0;
|
|
}
|
|
|
|
+static void bnxt_fw_reset_writel(struct bnxt *bp, int reg_idx)
|
|
+{
|
|
+ struct bnxt_fw_health *fw_health = bp->fw_health;
|
|
+ u32 reg = fw_health->fw_reset_seq_regs[reg_idx];
|
|
+ u32 val = fw_health->fw_reset_seq_vals[reg_idx];
|
|
+ u32 reg_type, reg_off, delay_msecs;
|
|
+
|
|
+ delay_msecs = fw_health->fw_reset_seq_delay_msec[reg_idx];
|
|
+ reg_type = BNXT_FW_HEALTH_REG_TYPE(reg);
|
|
+ reg_off = BNXT_FW_HEALTH_REG_OFF(reg);
|
|
+ switch (reg_type) {
|
|
+ case BNXT_FW_HEALTH_REG_TYPE_CFG:
|
|
+ pci_write_config_dword(bp->pdev, reg_off, val);
|
|
+ break;
|
|
+ case BNXT_FW_HEALTH_REG_TYPE_GRC:
|
|
+ writel(reg_off & BNXT_GRC_BASE_MASK,
|
|
+ bp->bar0 + BNXT_GRCPF_REG_WINDOW_BASE_OUT + 4);
|
|
+ reg_off = (reg_off & BNXT_GRC_OFFSET_MASK) + 0x2000;
|
|
+ /* fall through */
|
|
+ case BNXT_FW_HEALTH_REG_TYPE_BAR0:
|
|
+ writel(val, bp->bar0 + reg_off);
|
|
+ break;
|
|
+ case BNXT_FW_HEALTH_REG_TYPE_BAR1:
|
|
+ writel(val, bp->bar1 + reg_off);
|
|
+ break;
|
|
+ }
|
|
+ if (delay_msecs) {
|
|
+ pci_read_config_dword(bp->pdev, 0, &val);
|
|
+ msleep(delay_msecs);
|
|
+ }
|
|
+}
|
|
+
|
|
+static void bnxt_reset_all(struct bnxt *bp)
|
|
+{
|
|
+ struct bnxt_fw_health *fw_health = bp->fw_health;
|
|
+ int i;
|
|
+
|
|
+ if (fw_health->flags & ERROR_RECOVERY_QCFG_RESP_FLAGS_HOST) {
|
|
+ for (i = 0; i < fw_health->fw_reset_seq_cnt; i++)
|
|
+ bnxt_fw_reset_writel(bp, i);
|
|
+ } else if (fw_health->flags & ERROR_RECOVERY_QCFG_RESP_FLAGS_CO_CPU) {
|
|
+ struct hwrm_fw_reset_input req = {0};
|
|
+ int rc;
|
|
+
|
|
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FW_RESET, -1, -1);
|
|
+ req.resp_addr = cpu_to_le64(bp->hwrm_cmd_kong_resp_dma_addr);
|
|
+ req.embedded_proc_type = FW_RESET_REQ_EMBEDDED_PROC_TYPE_CHIP;
|
|
+ req.selfrst_status = FW_RESET_REQ_SELFRST_STATUS_SELFRSTASAP;
|
|
+ req.flags = FW_RESET_REQ_FLAGS_RESET_GRACEFUL;
|
|
+ rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
|
|
+ if (rc)
|
|
+ netdev_warn(bp->dev, "Unable to reset FW rc=%d\n", rc);
|
|
+ }
|
|
+ bp->fw_reset_timestamp = jiffies;
|
|
+}
|
|
+
|
|
static void bnxt_fw_reset_task(struct work_struct *work)
|
|
{
|
|
struct bnxt *bp = container_of(work, struct bnxt, fw_reset_task.work);
|
|
@@ -10446,6 +10502,14 @@
|
|
rtnl_unlock();
|
|
bnxt_queue_fw_reset_work(bp, bp->fw_reset_min_dsecs * HZ / 10);
|
|
return;
|
|
+ case BNXT_FW_RESET_STATE_RESET_FW: {
|
|
+ u32 wait_dsecs = bp->fw_health->post_reset_wait_dsecs;
|
|
+
|
|
+ bnxt_reset_all(bp);
|
|
+ bp->fw_reset_state = BNXT_FW_RESET_STATE_ENABLE_DEV;
|
|
+ bnxt_queue_fw_reset_work(bp, wait_dsecs * HZ / 10);
|
|
+ return;
|
|
+ }
|
|
case BNXT_FW_RESET_STATE_ENABLE_DEV:
|
|
clear_bit(BNXT_STATE_FW_FATAL_COND, &bp->state);
|
|
if (pci_enable_device(bp->pdev)) {
|