Recent FW interface update bumped the size of struct hwrm_func_cfg_input
above 128B which is the max some devices support.
Probe on Stratus (BCM957452) with FW 20.8.3.11 fails with:
   bnxt_en ...: Unable to reserve tx rings
   bnxt_en ...: 2nd rings reservation failed.
   bnxt_en ...: Not enough rings available.
Once probe is fixed other errors pop up:
   bnxt_en ...: Failed to set async event completion ring.
This is because __hwrm_send() rejects requests larger than
bp->hwrm_max_ext_req_len with -E2BIG. Since the driver doesn't
actually access any of the new fields, yet, trim the length.
It should be safe.
Similar workaround exists for backing_store_cfg_input.
Although that one mins() to a constant of 256, not 128
we'll effectively use here. Michael explains: "the backing
store cfg command is supported by relatively newer firmware
that will accept 256 bytes at least."
To make debugging easier in the future add a warning
for oversized requests.
Fixes: 754fbf604ff6 ("bnxt_en: Update firmware interface to 1.10.2.171")
Reviewed-by: Michael Chan <michael.chan@broadcom.com>
Link: https://lore.kernel.org/r/20231016171640.1481493-1-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
        if (BNXT_PF(bp)) {
                struct hwrm_func_cfg_input *req;
 
-               rc = hwrm_req_init(bp, req, HWRM_FUNC_CFG);
+               rc = bnxt_hwrm_func_cfg_short_req_init(bp, &req);
                if (rc)
                        return rc;
 
        struct hwrm_func_cfg_input *req;
        u32 enables = 0;
 
-       if (hwrm_req_init(bp, req, HWRM_FUNC_CFG))
+       if (bnxt_hwrm_func_cfg_short_req_init(bp, &req))
                return NULL;
 
        req->fid = cpu_to_le16(0xffff);
        else
                return -EINVAL;
 
-       rc = hwrm_req_init(bp, req, HWRM_FUNC_CFG);
+       rc = bnxt_hwrm_func_cfg_short_req_init(bp, &req);
        if (rc)
                return rc;
 
        if (BNXT_VF(bp) || bp->hwrm_spec_code < 0x10803)
                return 0;
 
-       rc = hwrm_req_init(bp, req, HWRM_FUNC_CFG);
+       rc = bnxt_hwrm_func_cfg_short_req_init(bp, &req);
        if (rc)
                return rc;
 
 
        if (~bp->fw_cap & BNXT_FW_CAP_HOT_RESET_IF)
                return -EOPNOTSUPP;
 
-       rc = hwrm_req_init(bp, req, HWRM_FUNC_CFG);
+       rc = bnxt_hwrm_func_cfg_short_req_init(bp, &req);
        if (rc)
                return rc;
 
 
 
        if (msg_len > BNXT_HWRM_MAX_REQ_LEN &&
            msg_len > bp->hwrm_max_ext_req_len) {
+               netdev_warn(bp->dev, "oversized hwrm request, req_type 0x%x",
+                           req_type);
                rc = -E2BIG;
                goto exit;
        }
 
 int hwrm_req_replace(struct bnxt *bp, void *req, void *new_req, u32 len);
 void hwrm_req_alloc_flags(struct bnxt *bp, void *req, gfp_t flags);
 void *hwrm_req_dma_slice(struct bnxt *bp, void *req, u32 size, dma_addr_t *dma);
+
+/* Older devices can only support req length of 128.
+ * HWRM_FUNC_CFG requests which don't need fields starting at
+ * num_quic_tx_key_ctxs can use this helper to avoid getting -E2BIG.
+ */
+static inline int
+bnxt_hwrm_func_cfg_short_req_init(struct bnxt *bp,
+                                 struct hwrm_func_cfg_input **req)
+{
+       u32 req_len;
+
+       req_len = min_t(u32, sizeof(**req), bp->hwrm_max_ext_req_len);
+       return __hwrm_req_init(bp, (void **)req, HWRM_FUNC_CFG, req_len);
+}
 #endif
 
        /*TODO: if the driver supports VLAN filter on guest VLAN,
         * the spoof check should also include vlan anti-spoofing
         */
-       rc = hwrm_req_init(bp, req, HWRM_FUNC_CFG);
+       rc = bnxt_hwrm_func_cfg_short_req_init(bp, &req);
        if (!rc) {
                req->fid = cpu_to_le16(vf->fw_fid);
                req->flags = cpu_to_le32(func_flags);
        if (!(bp->fw_cap & BNXT_FW_CAP_TRUSTED_VF))
                return 0;
 
-       rc = hwrm_req_init(bp, req, HWRM_FUNC_CFG);
+       rc = bnxt_hwrm_func_cfg_short_req_init(bp, &req);
        if (rc)
                return rc;
 
        }
        vf = &bp->pf.vf[vf_id];
 
-       rc = hwrm_req_init(bp, req, HWRM_FUNC_CFG);
+       rc = bnxt_hwrm_func_cfg_short_req_init(bp, &req);
        if (rc)
                return rc;
 
        if (vlan_tag == vf->vlan)
                return 0;
 
-       rc = hwrm_req_init(bp, req, HWRM_FUNC_CFG);
+       rc = bnxt_hwrm_func_cfg_short_req_init(bp, &req);
        if (!rc) {
                req->fid = cpu_to_le16(vf->fw_fid);
                req->dflt_vlan = cpu_to_le16(vlan_tag);
        }
        if (min_tx_rate == vf->min_tx_rate && max_tx_rate == vf->max_tx_rate)
                return 0;
-       rc = hwrm_req_init(bp, req, HWRM_FUNC_CFG);
+       rc = bnxt_hwrm_func_cfg_short_req_init(bp, &req);
        if (!rc) {
                req->fid = cpu_to_le16(vf->fw_fid);
                req->enables = cpu_to_le32(FUNC_CFG_REQ_ENABLES_MAX_BW |
        struct bnxt_vf_info *vf;
        int rc;
 
-       rc = hwrm_req_init(bp, req, HWRM_FUNC_CFG);
+       rc = bnxt_hwrm_func_cfg_short_req_init(bp, &req);
        if (rc)
                return rc;
 
        u32 mtu, i;
        int rc;
 
-       rc = hwrm_req_init(bp, req, HWRM_FUNC_CFG);
+       rc = bnxt_hwrm_func_cfg_short_req_init(bp, &req);
        if (rc)
                return rc;