bnxt_en: Reply to firmware's echo request async message.
authorMichael Chan <michael.chan@broadcom.com>
Sun, 14 Feb 2021 23:05:00 +0000 (18:05 -0500)
committerDavid S. Miller <davem@davemloft.net>
Mon, 15 Feb 2021 01:27:51 +0000 (17:27 -0800)
This is a new async message that the firmware can send to check if it
can communicate with the driver.  This is an added error detection
scheme that firmware can use if it suspects errors in the PCIe
interface.  When the driver receives this async message, it will reply
back echoing some data in the async message.  If the firmware is not
getting the reply with the proper data after some retries, error
recovery will kick in.

Reviewed-by: Andy Gospodarek <gospo@broadcom.com>
Reviewed-by: Edwin Peer <edwin.peer@broadcom.com>
Reviewed-by: Vasundhara Volam <vasundhara-v.volam@broadcom.com>
Signed-off-by: Michael Chan <michael.chan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/bnxt/bnxt.h

index 2bd9358..65771be 100644 (file)
@@ -257,6 +257,7 @@ static const u16 bnxt_async_events_arr[] = {
        ASYNC_EVENT_CMPL_EVENT_ID_ERROR_RECOVERY,
        ASYNC_EVENT_CMPL_EVENT_ID_DEBUG_NOTIFICATION,
        ASYNC_EVENT_CMPL_EVENT_ID_RING_MONITOR_MSG,
+       ASYNC_EVENT_CMPL_EVENT_ID_ECHO_REQUEST,
 };
 
 static struct workqueue_struct *bnxt_pf_wq;
@@ -2099,6 +2100,20 @@ static int bnxt_async_event_process(struct bnxt *bp,
                bnxt_sched_reset(bp, rxr);
                goto async_event_process_exit;
        }
+       case ASYNC_EVENT_CMPL_EVENT_ID_ECHO_REQUEST: {
+               struct bnxt_fw_health *fw_health = bp->fw_health;
+
+               netif_notice(bp, hw, bp->dev,
+                            "Received firmware echo request, data1: 0x%x, data2: 0x%x\n",
+                            data1, data2);
+               if (fw_health) {
+                       fw_health->echo_req_data1 = data1;
+                       fw_health->echo_req_data2 = data2;
+                       set_bit(BNXT_FW_ECHO_REQUEST_SP_EVENT, &bp->sp_event);
+                       break;
+               }
+               goto async_event_process_exit;
+       }
        default:
                goto async_event_process_exit;
        }
@@ -11208,6 +11223,17 @@ static void bnxt_init_ethtool_link_settings(struct bnxt *bp)
                link_info->req_flow_ctrl = link_info->force_pause_setting;
 }
 
+static void bnxt_fw_echo_reply(struct bnxt *bp)
+{
+       struct bnxt_fw_health *fw_health = bp->fw_health;
+       struct hwrm_func_echo_response_input req = {0};
+
+       bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_ECHO_RESPONSE, -1, -1);
+       req.event_data1 = cpu_to_le32(fw_health->echo_req_data1);
+       req.event_data2 = cpu_to_le32(fw_health->echo_req_data2);
+       hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+}
+
 static void bnxt_sp_task(struct work_struct *work)
 {
        struct bnxt *bp = container_of(work, struct bnxt, sp_task);
@@ -11275,6 +11301,9 @@ static void bnxt_sp_task(struct work_struct *work)
        if (test_and_clear_bit(BNXT_RING_COAL_NOW_SP_EVENT, &bp->sp_event))
                bnxt_chk_missed_irq(bp);
 
+       if (test_and_clear_bit(BNXT_FW_ECHO_REQUEST_SP_EVENT, &bp->sp_event))
+               bnxt_fw_echo_reply(bp);
+
        /* These functions below will clear BNXT_STATE_IN_SP_TASK.  They
         * must be the last functions to be called before exiting.
         */
index f5c45ea..1259e68 100644 (file)
@@ -1531,6 +1531,8 @@ struct bnxt_fw_health {
        u32 fw_reset_seq_regs[16];
        u32 fw_reset_seq_vals[16];
        u32 fw_reset_seq_delay_msec[16];
+       u32 echo_req_data1;
+       u32 echo_req_data2;
        struct devlink_health_reporter  *fw_reporter;
        struct devlink_health_reporter *fw_reset_reporter;
        struct devlink_health_reporter *fw_fatal_reporter;
@@ -1940,6 +1942,7 @@ struct bnxt {
 #define BNXT_FW_RESET_NOTIFY_SP_EVENT  18
 #define BNXT_FW_EXCEPTION_SP_EVENT     19
 #define BNXT_LINK_CFG_CHANGE_SP_EVENT  21
+#define BNXT_FW_ECHO_REQUEST_SP_EVENT  23
 
        struct delayed_work     fw_reset_task;
        int                     fw_reset_state;