bnxt_en: Fix the logic that creates the health reporters.
authorVasundhara Volam <vasundhara-v.volam@broadcom.com>
Tue, 10 Dec 2019 07:49:12 +0000 (02:49 -0500)
committerDavid S. Miller <davem@davemloft.net>
Wed, 11 Dec 2019 01:37:14 +0000 (17:37 -0800)
Fix the logic to properly check the fw capabilities and create the
devlink health reporters only when needed.  The current code creates
the reporters unconditionally as long as bp->fw_health is valid, and
that's not correct.

Call bnxt_dl_fw_reporters_create() directly from the init and reset
code path instead of from bnxt_dl_register().  This allows the
reporters to be adjusted when capabilities change.  The same
applies to bnxt_dl_fw_reporters_destroy().

Fixes: 6763c779c2d8 ("bnxt_en: Add new FW devlink_health_reporter")
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.c
drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.h

index 2a100ff3da8b60e4c8aaaa5c87f2213c3e754f27..819b7d72f9de5caffa720ed7e58008943721c843 100644 (file)
@@ -10625,6 +10625,12 @@ static int bnxt_fw_init_one(struct bnxt *bp)
        rc = bnxt_approve_mac(bp, bp->dev->dev_addr, false);
        if (rc)
                return rc;
+
+       /* In case fw capabilities have changed, destroy the unneeded
+        * reporters and create newly capable ones.
+        */
+       bnxt_dl_fw_reporters_destroy(bp, false);
+       bnxt_dl_fw_reporters_create(bp);
        bnxt_fw_init_one_p3(bp);
        return 0;
 }
@@ -11413,6 +11419,7 @@ static void bnxt_remove_one(struct pci_dev *pdev)
 
        if (BNXT_PF(bp)) {
                bnxt_sriov_disable(bp);
+               bnxt_dl_fw_reporters_destroy(bp, true);
                bnxt_dl_unregister(bp);
        }
 
@@ -11892,8 +11899,10 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (rc)
                goto init_err_cleanup_tc;
 
-       if (BNXT_PF(bp))
+       if (BNXT_PF(bp)) {
                bnxt_dl_register(bp);
+               bnxt_dl_fw_reporters_create(bp);
+       }
 
        netdev_info(dev, "%s found at mem %lx, node addr %pM\n",
                    board_info[ent->driver_data].name,
index 1e7c7c39718c8453b580ed0ec06997874c9828a9..136953a0ecaa15af60543d4e07855e853f3933f9 100644 (file)
@@ -125,21 +125,15 @@ struct devlink_health_reporter_ops bnxt_dl_fw_fatal_reporter_ops = {
        .recover = bnxt_fw_fatal_recover,
 };
 
-static void bnxt_dl_fw_reporters_create(struct bnxt *bp)
+void bnxt_dl_fw_reporters_create(struct bnxt *bp)
 {
        struct bnxt_fw_health *health = bp->fw_health;
 
-       if (!health)
+       if (!bp->dl || !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;
-       }
+       if (!(bp->fw_cap & BNXT_FW_CAP_HOT_RESET) || health->fw_reset_reporter)
+               goto err_recovery;
 
        health->fw_reset_reporter =
                devlink_health_reporter_create(bp->dl,
@@ -149,8 +143,30 @@ static void bnxt_dl_fw_reporters_create(struct bnxt *bp)
                netdev_warn(bp->dev, "Failed to create FW fatal health reporter, rc = %ld\n",
                            PTR_ERR(health->fw_reset_reporter));
                health->fw_reset_reporter = NULL;
+               bp->fw_cap &= ~BNXT_FW_CAP_HOT_RESET;
        }
 
+err_recovery:
+       if (!(bp->fw_cap & BNXT_FW_CAP_ERROR_RECOVERY))
+               return;
+
+       if (!health->fw_reporter) {
+               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;
+                       bp->fw_cap &= ~BNXT_FW_CAP_ERROR_RECOVERY;
+                       return;
+               }
+       }
+
+       if (health->fw_fatal_reporter)
+               return;
+
        health->fw_fatal_reporter =
                devlink_health_reporter_create(bp->dl,
                                               &bnxt_dl_fw_fatal_reporter_ops,
@@ -159,24 +175,35 @@ static void bnxt_dl_fw_reporters_create(struct bnxt *bp)
                netdev_warn(bp->dev, "Failed to create FW fatal health reporter, rc = %ld\n",
                            PTR_ERR(health->fw_fatal_reporter));
                health->fw_fatal_reporter = NULL;
+               bp->fw_cap &= ~BNXT_FW_CAP_ERROR_RECOVERY;
        }
 }
 
-static void bnxt_dl_fw_reporters_destroy(struct bnxt *bp)
+void bnxt_dl_fw_reporters_destroy(struct bnxt *bp, bool all)
 {
        struct bnxt_fw_health *health = bp->fw_health;
 
-       if (!health)
+       if (!bp->dl || !health)
                return;
 
-       if (health->fw_reporter)
-               devlink_health_reporter_destroy(health->fw_reporter);
-
-       if (health->fw_reset_reporter)
+       if ((all || !(bp->fw_cap & BNXT_FW_CAP_HOT_RESET)) &&
+           health->fw_reset_reporter) {
                devlink_health_reporter_destroy(health->fw_reset_reporter);
+               health->fw_reset_reporter = NULL;
+       }
 
-       if (health->fw_fatal_reporter)
+       if ((bp->fw_cap & BNXT_FW_CAP_ERROR_RECOVERY) && !all)
+               return;
+
+       if (health->fw_reporter) {
+               devlink_health_reporter_destroy(health->fw_reporter);
+               health->fw_reporter = NULL;
+       }
+
+       if (health->fw_fatal_reporter) {
                devlink_health_reporter_destroy(health->fw_fatal_reporter);
+               health->fw_fatal_reporter = NULL;
+       }
 }
 
 void bnxt_devlink_health_report(struct bnxt *bp, unsigned long event)
@@ -502,8 +529,6 @@ int bnxt_dl_register(struct bnxt *bp)
 
        devlink_params_publish(dl);
 
-       bnxt_dl_fw_reporters_create(bp);
-
        return 0;
 
 err_dl_port_unreg:
@@ -526,7 +551,6 @@ 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);
index 665d4bdcd8c0269421003dd7ee66bc167d586017..6db6c3dac4728de4e51d513111d06a11f7f5fd39 100644 (file)
@@ -58,6 +58,8 @@ struct bnxt_dl_nvm_param {
 
 void bnxt_devlink_health_report(struct bnxt *bp, unsigned long event);
 void bnxt_dl_health_status_update(struct bnxt *bp, bool healthy);
+void bnxt_dl_fw_reporters_create(struct bnxt *bp);
+void bnxt_dl_fw_reporters_destroy(struct bnxt *bp, bool all);
 int bnxt_dl_register(struct bnxt *bp);
 void bnxt_dl_unregister(struct bnxt *bp);