bnxt_en: update RSS config using difference algorithm
authorEdwin Peer <edwin.peer@broadcom.com>
Mon, 7 Nov 2022 00:16:31 +0000 (19:16 -0500)
committerPaolo Abeni <pabeni@redhat.com>
Tue, 8 Nov 2022 11:39:02 +0000 (12:39 +0100)
Hardware is unable to realize all legal firmware interface state values
for hash_type.  For example, if 4-tuple TCP_IPV4 hash is enabled,
4-tuple UDP_IPV4 hash must also be enabled.  By providing the bits the
user intended to change instead of the possible illegal intermediate
states, the firmware is able to make better compromises when deciding
which bits to ignore.

With this new mechansim, we can now report the actual configured hash
back to the user.  Add bnxt_hwrm_update_rss_hash_cfg() to report the
actual hash after user configuration.

Signed-off-by: Edwin Peer <edwin.peer@broadcom.com>
Signed-off-by: Michael Chan <michael.chan@broadcom.com>
Reviewed-by: Leon Romanovsky <leonro@nvidia.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/bnxt/bnxt.h
drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h

index 15edb6c..d18e55b 100644 (file)
@@ -5294,7 +5294,15 @@ __bnxt_hwrm_vnic_set_rss(struct bnxt *bp, struct hwrm_vnic_rss_cfg_input *req,
        else
                bnxt_fill_hw_rss_tbl(bp, vnic);
 
-       req->hash_type = cpu_to_le32(bp->rss_hash_cfg);
+       if (bp->rss_hash_delta) {
+               req->hash_type = cpu_to_le32(bp->rss_hash_delta);
+               if (bp->rss_hash_cfg & bp->rss_hash_delta)
+                       req->flags |= VNIC_RSS_CFG_REQ_FLAGS_HASH_TYPE_INCLUDE;
+               else
+                       req->flags |= VNIC_RSS_CFG_REQ_FLAGS_HASH_TYPE_EXCLUDE;
+       } else {
+               req->hash_type = cpu_to_le32(bp->rss_hash_cfg);
+       }
        req->hash_mode_flags = VNIC_RSS_CFG_REQ_HASH_MODE_FLAGS_DEFAULT;
        req->ring_grp_tbl_addr = cpu_to_le64(vnic->rss_table_dma_addr);
        req->hash_key_tbl_addr = cpu_to_le64(vnic->rss_hash_key_dma_addr);
@@ -5355,6 +5363,25 @@ exit:
        return rc;
 }
 
+static void bnxt_hwrm_update_rss_hash_cfg(struct bnxt *bp)
+{
+       struct bnxt_vnic_info *vnic = &bp->vnic_info[0];
+       struct hwrm_vnic_rss_qcfg_output *resp;
+       struct hwrm_vnic_rss_qcfg_input *req;
+
+       if (hwrm_req_init(bp, req, HWRM_VNIC_RSS_QCFG))
+               return;
+
+       /* all contexts configured to same hash_type, zero always exists */
+       req->rss_ctx_idx = cpu_to_le16(vnic->fw_rss_cos_lb_ctx[0]);
+       resp = hwrm_req_hold(bp, req);
+       if (!hwrm_req_send(bp, req)) {
+               bp->rss_hash_cfg = le32_to_cpu(resp->hash_type) ?: bp->rss_hash_cfg;
+               bp->rss_hash_delta = 0;
+       }
+       hwrm_req_drop(bp, req);
+}
+
 static int bnxt_hwrm_vnic_set_hds(struct bnxt *bp, u16 vnic_id)
 {
        struct bnxt_vnic_info *vnic = &bp->vnic_info[vnic_id];
@@ -5612,6 +5639,8 @@ static int bnxt_hwrm_vnic_qcaps(struct bnxt *bp)
                    (BNXT_CHIP_P5_THOR(bp) &&
                     !(bp->fw_cap & BNXT_FW_CAP_EXT_HW_STATS_SUPPORTED)))
                        bp->fw_cap |= BNXT_FW_CAP_VLAN_RX_STRIP;
+               if (flags & VNIC_QCAPS_RESP_FLAGS_RSS_HASH_TYPE_DELTA_CAP)
+                       bp->fw_cap |= BNXT_FW_CAP_RSS_HASH_TYPE_DELTA;
                bp->max_tpa_v2 = le16_to_cpu(resp->max_aggs_supported);
                if (bp->max_tpa_v2) {
                        if (BNXT_CHIP_P5_THOR(bp))
@@ -8806,6 +8835,8 @@ static int bnxt_init_chip(struct bnxt *bp, bool irq_re_init)
        rc = bnxt_setup_vnic(bp, 0);
        if (rc)
                goto err_out;
+       if (bp->fw_cap & BNXT_FW_CAP_RSS_HASH_TYPE_DELTA)
+               bnxt_hwrm_update_rss_hash_cfg(bp);
 
        if (bp->flags & BNXT_FLAG_RFS) {
                rc = bnxt_alloc_rfs_vnics(bp);
@@ -12241,6 +12272,8 @@ static void bnxt_set_dflt_rss_hash_type(struct bnxt *bp)
                           VNIC_RSS_CFG_REQ_HASH_TYPE_TCP_IPV4 |
                           VNIC_RSS_CFG_REQ_HASH_TYPE_IPV6 |
                           VNIC_RSS_CFG_REQ_HASH_TYPE_TCP_IPV6;
+       if (bp->fw_cap & BNXT_FW_CAP_RSS_HASH_TYPE_DELTA)
+               bp->rss_hash_delta = bp->rss_hash_cfg;
        if (BNXT_CHIP_P4_PLUS(bp) && bp->hwrm_spec_code >= 0x10501) {
                bp->flags |= BNXT_FLAG_UDP_RSS_CAP;
                bp->rss_hash_cfg |= VNIC_RSS_CFG_REQ_HASH_TYPE_UDP_IPV4 |
index 91a1ba0..7611bed 100644 (file)
@@ -1900,6 +1900,7 @@ struct bnxt {
        u16                     *rss_indir_tbl;
        u16                     rss_indir_tbl_entries;
        u32                     rss_hash_cfg;
+       u32                     rss_hash_delta;
 
        u16                     max_mtu;
        u8                      max_tc;
@@ -1965,6 +1966,7 @@ struct bnxt {
        #define BNXT_FW_CAP_CFA_RFS_RING_TBL_IDX_V2     0x00010000
        #define BNXT_FW_CAP_PCIE_STATS_SUPPORTED        0x00020000
        #define BNXT_FW_CAP_EXT_STATS_SUPPORTED         0x00040000
+       #define BNXT_FW_CAP_RSS_HASH_TYPE_DELTA         0x00080000
        #define BNXT_FW_CAP_ERR_RECOVER_RELOAD          0x00100000
        #define BNXT_FW_CAP_HOT_RESET                   0x00200000
        #define BNXT_FW_CAP_PTP_RTC                     0x00400000
index d8f0351..132e4f5 100644 (file)
@@ -1234,6 +1234,8 @@ static int bnxt_srxfh(struct bnxt *bp, struct ethtool_rxnfc *cmd)
        if (bp->rss_hash_cfg == rss_hash_cfg)
                return 0;
 
+       if (bp->fw_cap & BNXT_FW_CAP_RSS_HASH_TYPE_DELTA)
+               bp->rss_hash_delta = bp->rss_hash_cfg ^ rss_hash_cfg;
        bp->rss_hash_cfg = rss_hash_cfg;
        if (netif_running(bp->dev)) {
                bnxt_close_nic(bp, false, false);
index 184dd8d..2686a71 100644 (file)
@@ -6768,6 +6768,53 @@ struct hwrm_vnic_rss_cfg_cmd_err {
        u8      unused_0[7];
 };
 
+/* hwrm_vnic_rss_qcfg_input (size:192b/24B) */
+struct hwrm_vnic_rss_qcfg_input {
+       __le16  req_type;
+       __le16  cmpl_ring;
+       __le16  seq_id;
+       __le16  target_id;
+       __le64  resp_addr;
+       __le16  rss_ctx_idx;
+       __le16  vnic_id;
+       u8      unused_0[4];
+};
+
+/* hwrm_vnic_rss_qcfg_output (size:512b/64B) */
+struct hwrm_vnic_rss_qcfg_output {
+       __le16  error_code;
+       __le16  req_type;
+       __le16  seq_id;
+       __le16  resp_len;
+       __le32  hash_type;
+       #define VNIC_RSS_QCFG_RESP_HASH_TYPE_IPV4                0x1UL
+       #define VNIC_RSS_QCFG_RESP_HASH_TYPE_TCP_IPV4            0x2UL
+       #define VNIC_RSS_QCFG_RESP_HASH_TYPE_UDP_IPV4            0x4UL
+       #define VNIC_RSS_QCFG_RESP_HASH_TYPE_IPV6                0x8UL
+       #define VNIC_RSS_QCFG_RESP_HASH_TYPE_TCP_IPV6            0x10UL
+       #define VNIC_RSS_QCFG_RESP_HASH_TYPE_UDP_IPV6            0x20UL
+       #define VNIC_RSS_QCFG_RESP_HASH_TYPE_IPV6_FLOW_LABEL     0x40UL
+       #define VNIC_RSS_QCFG_RESP_HASH_TYPE_AH_SPI_IPV4         0x80UL
+       #define VNIC_RSS_QCFG_RESP_HASH_TYPE_ESP_SPI_IPV4        0x100UL
+       #define VNIC_RSS_QCFG_RESP_HASH_TYPE_AH_SPI_IPV6         0x200UL
+       #define VNIC_RSS_QCFG_RESP_HASH_TYPE_ESP_SPI_IPV6        0x400UL
+       u8      unused_0[4];
+       __le32  hash_key[10];
+       u8      hash_mode_flags;
+       #define VNIC_RSS_QCFG_RESP_HASH_MODE_FLAGS_DEFAULT         0x1UL
+       #define VNIC_RSS_QCFG_RESP_HASH_MODE_FLAGS_INNERMOST_4     0x2UL
+       #define VNIC_RSS_QCFG_RESP_HASH_MODE_FLAGS_INNERMOST_2     0x4UL
+       #define VNIC_RSS_QCFG_RESP_HASH_MODE_FLAGS_OUTERMOST_4     0x8UL
+       #define VNIC_RSS_QCFG_RESP_HASH_MODE_FLAGS_OUTERMOST_2     0x10UL
+       u8      ring_select_mode;
+       #define VNIC_RSS_QCFG_RESP_RING_SELECT_MODE_TOEPLITZ          0x0UL
+       #define VNIC_RSS_QCFG_RESP_RING_SELECT_MODE_XOR               0x1UL
+       #define VNIC_RSS_QCFG_RESP_RING_SELECT_MODE_TOEPLITZ_CHECKSUM 0x2UL
+       #define VNIC_RSS_QCFG_RESP_RING_SELECT_MODE_LAST             VNIC_RSS_QCFG_RESP_RING_SELECT_MODE_TOEPLITZ_CHECKSUM
+       u8      unused_1[5];
+       u8      valid;
+};
+
 /* hwrm_vnic_plcmodes_cfg_input (size:320b/40B) */
 struct hwrm_vnic_plcmodes_cfg_input {
        __le16  req_type;