This parameter allows the user to prevent live reset of the device
temporarily by setting it to false.
For example, if the host is running a mission critical application,
user can set this parameter to false until the application has
completed, to avoid a potential device reset disrupting it.

Signed-off-by: Vasundhara Volam <vasundhara-v.vo...@broadcom.com>
Signed-off-by: Michael Chan <michael.c...@broadcom.com>
---
v2->v3: Rename parameter name to "allow_live_dev_reset".
- Moved permanent configuration mode code to a separate patch as the
param is renamed to "enable_live_dev_reset".
- Rename the get/set callbacks of the param accordingly.
- Moved the documentation completely to devlink-params.rst file.
---
 Documentation/networking/devlink/bnxt.rst         |  2 ++
 drivers/net/ethernet/broadcom/bnxt/bnxt.c         | 28 ++++++++++++++-
 drivers/net/ethernet/broadcom/bnxt/bnxt.h         |  2 ++
 drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c | 43 +++++++++++++++++++++++
 4 files changed, 74 insertions(+), 1 deletion(-)

diff --git a/Documentation/networking/devlink/bnxt.rst 
b/Documentation/networking/devlink/bnxt.rst
index ae0a69d..5573663 100644
--- a/Documentation/networking/devlink/bnxt.rst
+++ b/Documentation/networking/devlink/bnxt.rst
@@ -24,6 +24,8 @@ Parameters
      - Permanent
    * - ``enable_live_dev_reset``
      - Permanent
+   * - ``allow_live_dev_reset``
+     - Runtime
 
 The ``bnxt`` driver also implements the following driver-specific
 parameters.
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c 
b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index f86b621..535fe8f 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -6955,7 +6955,7 @@ static int __bnxt_hwrm_func_qcaps(struct bnxt *bp)
        struct hwrm_func_qcaps_input req = {0};
        struct hwrm_func_qcaps_output *resp = bp->hwrm_cmd_resp_addr;
        struct bnxt_hw_resc *hw_resc = &bp->hw_resc;
-       u32 flags;
+       u32 flags, flags_ext;
 
        bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_QCAPS, -1, -1);
        req.fid = cpu_to_le16(0xffff);
@@ -6985,6 +6985,10 @@ static int __bnxt_hwrm_func_qcaps(struct bnxt *bp)
        if (flags & FUNC_QCAPS_RESP_FLAGS_PUSH_MODE_SUPPORTED)
                bp->tx_push_thresh = BNXT_TX_PUSH_THRESH;
 
+       flags_ext = le32_to_cpu(resp->flags_ext);
+       if (flags_ext & FUNC_QCAPS_RESP_FLAGS_EXT_HOT_RESET_IF_SUPPORT)
+               bp->fw_cap |= BNXT_FW_CAP_HOT_RESET_IF_SUPPORT;
+
        hw_resc->max_rsscos_ctxs = le16_to_cpu(resp->max_rsscos_ctx);
        hw_resc->max_cp_rings = le16_to_cpu(resp->max_cmpl_rings);
        hw_resc->max_tx_rings = le16_to_cpu(resp->max_tx_rings);
@@ -8773,6 +8777,28 @@ static int bnxt_hwrm_shutdown_link(struct bnxt *bp)
 
 static int bnxt_fw_init_one(struct bnxt *bp);
 
+int bnxt_hwrm_get_hot_reset(struct bnxt *bp, bool *hot_reset_allowed)
+{
+       struct hwrm_func_qcfg_output *resp = bp->hwrm_cmd_resp_addr;
+       struct hwrm_func_qcfg_input req = {0};
+       int rc;
+
+       if (!(bp->fw_cap & BNXT_FW_CAP_HOT_RESET_IF_SUPPORT)) {
+               *hot_reset_allowed = !!(bp->fw_cap & BNXT_FW_CAP_HOT_RESET);
+               return 0;
+       }
+
+       bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_QCFG, -1, -1);
+       req.fid = cpu_to_le16(0xffff);
+       mutex_lock(&bp->hwrm_cmd_lock);
+       rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+       if (!rc)
+               *hot_reset_allowed = !!(le16_to_cpu(resp->flags) &
+                                       FUNC_QCFG_RESP_FLAGS_HOT_RESET_ALLOWED);
+       mutex_unlock(&bp->hwrm_cmd_lock);
+       return rc;
+}
+
 static int bnxt_hwrm_if_change(struct bnxt *bp, bool up)
 {
        struct hwrm_func_drv_if_change_output *resp = bp->hwrm_cmd_resp_addr;
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h 
b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
index c04ac4a..fd6592e 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
@@ -1710,6 +1710,7 @@ struct bnxt {
        #define BNXT_FW_CAP_ERR_RECOVER_RELOAD          0x00100000
        #define BNXT_FW_CAP_HOT_RESET                   0x00200000
        #define BNXT_FW_CAP_SHARED_PORT_CFG             0x00400000
+       #define BNXT_FW_CAP_HOT_RESET_IF_SUPPORT        0x08000000
 
 #define BNXT_NEW_RM(bp)                ((bp)->fw_cap & BNXT_FW_CAP_NEW_RM)
        u32                     hwrm_spec_code;
@@ -2062,5 +2063,6 @@ int bnxt_get_port_parent_id(struct net_device *dev,
                            struct netdev_phys_item_id *ppid);
 void bnxt_dim_work(struct work_struct *work);
 int bnxt_hwrm_set_ring_coal(struct bnxt *bp, struct bnxt_napi *bnapi);
+int bnxt_hwrm_get_hot_reset(struct bnxt *bp, bool *hot_reset_allowed);
 
 #endif
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c 
b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
index 3e1a4ef..da31351 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
@@ -620,6 +620,45 @@ static int bnxt_dl_msix_validate(struct devlink *dl, u32 
id,
        return 0;
 }
 
+static int bnxt_live_dev_reset_get(struct devlink *dl, u32 id,
+                                  struct devlink_param_gset_ctx *ctx)
+{
+       struct bnxt *bp = bnxt_get_bp_from_dl(dl);
+
+       return bnxt_hwrm_get_hot_reset(bp, &ctx->val.vbool);
+}
+
+static int bnxt_live_dev_reset_set(struct devlink *dl, u32 id,
+                                  struct devlink_param_gset_ctx *ctx)
+{
+       struct bnxt *bp = bnxt_get_bp_from_dl(dl);
+       struct hwrm_func_cfg_input req = {0};
+       bool hot_reset_allowed;
+       int rc;
+
+       if (!(bp->fw_cap & BNXT_FW_CAP_HOT_RESET_IF_SUPPORT))
+               return -EOPNOTSUPP;
+
+       bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_CFG, -1, -1);
+       req.fid = cpu_to_le16(0xffff);
+       req.enables = cpu_to_le32(FUNC_CFG_REQ_ENABLES_HOT_RESET_IF_SUPPORT);
+       if (ctx->val.vbool)
+               req.flags = cpu_to_le32(FUNC_CFG_REQ_FLAGS_HOT_RESET_IF_EN_DIS);
+
+       rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+       if (rc)
+               return rc;
+
+       rc = bnxt_hwrm_get_hot_reset(bp, &hot_reset_allowed);
+       if (rc)
+               return rc;
+
+       if (ctx->val.vbool && !hot_reset_allowed)
+               netdev_info(bp->dev, "Live reset enabled, but is disallowed as 
it is disabled on other interface(s) of this device.\n");
+
+       return 0;
+}
+
 static const struct devlink_param bnxt_dl_params[] = {
        DEVLINK_PARAM_GENERIC(ENABLE_SRIOV,
                              BIT(DEVLINK_PARAM_CMODE_PERMANENT),
@@ -646,6 +685,10 @@ static int bnxt_dl_msix_validate(struct devlink *dl, u32 
id,
                              BIT(DEVLINK_PARAM_CMODE_PERMANENT),
                              bnxt_dl_nvm_param_get, bnxt_dl_nvm_param_set,
                              NULL),
+       DEVLINK_PARAM_GENERIC(ALLOW_LIVE_DEV_RESET,
+                             BIT(DEVLINK_PARAM_CMODE_RUNTIME),
+                             bnxt_live_dev_reset_get, bnxt_live_dev_reset_set,
+                             NULL),
 };
 
 static const struct devlink_param bnxt_dl_port_params[] = {
-- 
1.8.3.1

Reply via email to