]> git.baikalelectronics.ru Git - kernel.git/commitdiff
bnxt_en: Add new FW devlink_health_reporter
authorVasundhara Volam <vasundhara-v.volam@broadcom.com>
Fri, 30 Aug 2019 03:54:57 +0000 (23:54 -0400)
committerDavid S. Miller <davem@davemloft.net>
Fri, 30 Aug 2019 21:02:19 +0000 (14:02 -0700)
Create new FW devlink_health_reporter, to know the current health
status of FW.

Command example and output:
$ devlink health show pci/0000:af:00.0 reporter fw

pci/0000:af:00.0:
  name fw
    state healthy error 0 recover 0

 FW status: Healthy; Reset count: 1

Cc: Jiri Pirko <jiri@mellanox.com>
Signed-off-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.h
drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c

index 6f7aa7ca94006b669f6400a365b6542fff25da8d..a75fe16cf2e61817cf1cd1f0ad72389d33ddf269 100644 (file)
@@ -1368,6 +1368,7 @@ struct bnxt_fw_health {
        u32 fw_reset_seq_regs[16];
        u32 fw_reset_seq_vals[16];
        u32 fw_reset_seq_delay_msec[16];
+       struct devlink_health_reporter  *fw_reporter;
 };
 
 #define BNXT_FW_HEALTH_REG_TYPE_MASK   3
@@ -1382,6 +1383,8 @@ struct bnxt_fw_health {
 #define BNXT_FW_HEALTH_WIN_BASE                0x3000
 #define BNXT_FW_HEALTH_WIN_MAP_OFF     8
 
+#define BNXT_FW_STATUS_HEALTHY         0x8000
+
 struct bnxt {
        void __iomem            *bar0;
        void __iomem            *bar1;
index 7d9a8c4be18224d660523891130c83f6544b92e2..e15d5dc78725c6c13cd6a2e97bfa81132008cf9c 100644 (file)
 #include "bnxt_vfr.h"
 #include "bnxt_devlink.h"
 
+static int bnxt_fw_reporter_diagnose(struct devlink_health_reporter *reporter,
+                                    struct devlink_fmsg *fmsg)
+{
+       struct bnxt *bp = devlink_health_reporter_priv(reporter);
+       struct bnxt_fw_health *health = bp->fw_health;
+       u32 val, health_status;
+       int rc;
+
+       if (!health || test_bit(BNXT_STATE_IN_FW_RESET, &bp->state))
+               return 0;
+
+       val = bnxt_fw_health_readl(bp, BNXT_FW_HEALTH_REG);
+       health_status = val & 0xffff;
+
+       if (health_status == BNXT_FW_STATUS_HEALTHY) {
+               rc = devlink_fmsg_string_pair_put(fmsg, "FW status",
+                                                 "Healthy;");
+               if (rc)
+                       return rc;
+       } else if (health_status < BNXT_FW_STATUS_HEALTHY) {
+               rc = devlink_fmsg_string_pair_put(fmsg, "FW status",
+                                                 "Not yet completed initialization;");
+               if (rc)
+                       return rc;
+       } else if (health_status > BNXT_FW_STATUS_HEALTHY) {
+               rc = devlink_fmsg_string_pair_put(fmsg, "FW status",
+                                                 "Encountered fatal error and cannot recover;");
+               if (rc)
+                       return rc;
+       }
+
+       if (val >> 16) {
+               rc = devlink_fmsg_u32_pair_put(fmsg, "Error", val >> 16);
+               if (rc)
+                       return rc;
+       }
+
+       val = bnxt_fw_health_readl(bp, BNXT_FW_RESET_CNT_REG);
+       rc = devlink_fmsg_u32_pair_put(fmsg, "Reset count", val);
+       if (rc)
+               return rc;
+
+       return 0;
+}
+
+static const struct devlink_health_reporter_ops bnxt_dl_fw_reporter_ops = {
+       .name = "fw",
+       .diagnose = bnxt_fw_reporter_diagnose,
+};
+
+static void bnxt_dl_fw_reporters_create(struct bnxt *bp)
+{
+       struct bnxt_fw_health *health = bp->fw_health;
+
+       if (!health)
+               return;
+
+       health->fw_reporter =
+               devlink_health_reporter_create(bp->dl, &bnxt_dl_fw_reporter_ops,
+                                              0, false, bp);
+       if (IS_ERR(health->fw_reporter)) {
+               netdev_warn(bp->dev, "Failed to create FW health reporter, rc = %ld\n",
+                           PTR_ERR(health->fw_reporter));
+               health->fw_reporter = NULL;
+       }
+}
+
+static void bnxt_dl_fw_reporters_destroy(struct bnxt *bp)
+{
+       struct bnxt_fw_health *health = bp->fw_health;
+
+       if (!health)
+               return;
+
+       if (health->fw_reporter)
+               devlink_health_reporter_destroy(health->fw_reporter);
+}
+
 static const struct devlink_ops bnxt_dl_ops = {
 #ifdef CONFIG_BNXT_SRIOV
        .eswitch_mode_set = bnxt_dl_eswitch_mode_set,
@@ -247,6 +325,8 @@ int bnxt_dl_register(struct bnxt *bp)
 
        devlink_params_publish(dl);
 
+       bnxt_dl_fw_reporters_create(bp);
+
        return 0;
 
 err_dl_port_unreg:
@@ -269,6 +349,7 @@ void bnxt_dl_unregister(struct bnxt *bp)
        if (!dl)
                return;
 
+       bnxt_dl_fw_reporters_destroy(bp);
        devlink_port_params_unregister(&bp->dl_port, bnxt_dl_port_params,
                                       ARRAY_SIZE(bnxt_dl_port_params));
        devlink_port_unregister(&bp->dl_port);