net/ice/base: introduce some new macros
[dpdk.git] / drivers / net / ice / base / ice_flow.c
index f1bf5b5..36d31fa 100644 (file)
@@ -26,8 +26,8 @@
  * protocol headers. Displacement values are expressed in number of bits.
  */
 #define ICE_FLOW_FLD_IPV6_TTL_DSCP_DISP        (-4)
-#define ICE_FLOW_FLD_IPV6_TTL_PROT_DISP        ((-2) * 8)
-#define ICE_FLOW_FLD_IPV6_TTL_TTL_DISP ((-1) * 8)
+#define ICE_FLOW_FLD_IPV6_TTL_PROT_DISP        ((-2) * BITS_PER_BYTE)
+#define ICE_FLOW_FLD_IPV6_TTL_TTL_DISP ((-1) * BITS_PER_BYTE)
 
 /* Describe properties of a protocol header field */
 struct ice_flow_field_info {
@@ -36,70 +36,76 @@ struct ice_flow_field_info {
        u16 size;       /* Size of fields in bits */
 };
 
+#define ICE_FLOW_FLD_INFO(_hdr, _offset_bytes, _size_bytes) { \
+       .hdr = _hdr, \
+       .off = _offset_bytes * BITS_PER_BYTE, \
+       .size = _size_bytes * BITS_PER_BYTE, \
+}
+
 /* Table containing properties of supported protocol header fields */
 static const
 struct ice_flow_field_info ice_flds_info[ICE_FLOW_FIELD_IDX_MAX] = {
        /* Ether */
        /* ICE_FLOW_FIELD_IDX_ETH_DA */
-       { ICE_FLOW_SEG_HDR_ETH, 0, ETH_ALEN * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 0, ETH_ALEN),
        /* ICE_FLOW_FIELD_IDX_ETH_SA */
-       { ICE_FLOW_SEG_HDR_ETH, ETH_ALEN * 8, ETH_ALEN * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, ETH_ALEN, ETH_ALEN),
        /* ICE_FLOW_FIELD_IDX_S_VLAN */
-       { ICE_FLOW_SEG_HDR_VLAN, 12 * 8, ICE_FLOW_FLD_SZ_VLAN * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 12, ICE_FLOW_FLD_SZ_VLAN),
        /* ICE_FLOW_FIELD_IDX_C_VLAN */
-       { ICE_FLOW_SEG_HDR_VLAN, 14 * 8, ICE_FLOW_FLD_SZ_VLAN * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 14, ICE_FLOW_FLD_SZ_VLAN),
        /* ICE_FLOW_FIELD_IDX_ETH_TYPE */
-       { ICE_FLOW_SEG_HDR_ETH, 12 * 8, ICE_FLOW_FLD_SZ_ETH_TYPE * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 12, ICE_FLOW_FLD_SZ_ETH_TYPE),
        /* IPv4 */
        /* ICE_FLOW_FIELD_IDX_IP_DSCP */
-       { ICE_FLOW_SEG_HDR_IPV4, 1 * 8, 1 * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 1, 1),
        /* ICE_FLOW_FIELD_IDX_IP_TTL */
-       { ICE_FLOW_SEG_HDR_NONE, 8 * 8, 1 * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NONE, 8, 1),
        /* ICE_FLOW_FIELD_IDX_IP_PROT */
-       { ICE_FLOW_SEG_HDR_NONE, 9 * 8, ICE_FLOW_FLD_SZ_IP_PROT * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NONE, 9, ICE_FLOW_FLD_SZ_IP_PROT),
        /* ICE_FLOW_FIELD_IDX_IPV4_SA */
-       { ICE_FLOW_SEG_HDR_IPV4, 12 * 8, ICE_FLOW_FLD_SZ_IPV4_ADDR * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 12, ICE_FLOW_FLD_SZ_IPV4_ADDR),
        /* ICE_FLOW_FIELD_IDX_IPV4_DA */
-       { ICE_FLOW_SEG_HDR_IPV4, 16 * 8, ICE_FLOW_FLD_SZ_IPV4_ADDR * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 16, ICE_FLOW_FLD_SZ_IPV4_ADDR),
        /* IPv6 */
        /* ICE_FLOW_FIELD_IDX_IPV6_SA */
-       { ICE_FLOW_SEG_HDR_IPV6, 8 * 8, ICE_FLOW_FLD_SZ_IPV6_ADDR * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8, ICE_FLOW_FLD_SZ_IPV6_ADDR),
        /* ICE_FLOW_FIELD_IDX_IPV6_DA */
-       { ICE_FLOW_SEG_HDR_IPV6, 24 * 8, ICE_FLOW_FLD_SZ_IPV6_ADDR * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24, ICE_FLOW_FLD_SZ_IPV6_ADDR),
        /* Transport */
        /* ICE_FLOW_FIELD_IDX_TCP_SRC_PORT */
-       { ICE_FLOW_SEG_HDR_TCP, 0 * 8, ICE_FLOW_FLD_SZ_PORT * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 0, ICE_FLOW_FLD_SZ_PORT),
        /* ICE_FLOW_FIELD_IDX_TCP_DST_PORT */
-       { ICE_FLOW_SEG_HDR_TCP, 2 * 8, ICE_FLOW_FLD_SZ_PORT * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 2, ICE_FLOW_FLD_SZ_PORT),
        /* ICE_FLOW_FIELD_IDX_UDP_SRC_PORT */
-       { ICE_FLOW_SEG_HDR_UDP, 0 * 8, ICE_FLOW_FLD_SZ_PORT * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 0, ICE_FLOW_FLD_SZ_PORT),
        /* ICE_FLOW_FIELD_IDX_UDP_DST_PORT */
-       { ICE_FLOW_SEG_HDR_UDP, 2 * 8, ICE_FLOW_FLD_SZ_PORT * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 2, ICE_FLOW_FLD_SZ_PORT),
        /* ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT */
-       { ICE_FLOW_SEG_HDR_SCTP, 0 * 8, ICE_FLOW_FLD_SZ_PORT * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 0, ICE_FLOW_FLD_SZ_PORT),
        /* ICE_FLOW_FIELD_IDX_SCTP_DST_PORT */
-       { ICE_FLOW_SEG_HDR_SCTP, 2 * 8, ICE_FLOW_FLD_SZ_PORT * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 2, ICE_FLOW_FLD_SZ_PORT),
        /* ICE_FLOW_FIELD_IDX_TCP_FLAGS */
-       { ICE_FLOW_SEG_HDR_TCP, 13 * 8, ICE_FLOW_FLD_SZ_TCP_FLAGS * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 13, ICE_FLOW_FLD_SZ_TCP_FLAGS),
        /* ARP */
        /* ICE_FLOW_FIELD_IDX_ARP_SIP */
-       { ICE_FLOW_SEG_HDR_ARP, 14 * 8, ICE_FLOW_FLD_SZ_IPV4_ADDR * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 14, ICE_FLOW_FLD_SZ_IPV4_ADDR),
        /* ICE_FLOW_FIELD_IDX_ARP_DIP */
-       { ICE_FLOW_SEG_HDR_ARP, 24 * 8, ICE_FLOW_FLD_SZ_IPV4_ADDR * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 24, ICE_FLOW_FLD_SZ_IPV4_ADDR),
        /* ICE_FLOW_FIELD_IDX_ARP_SHA */
-       { ICE_FLOW_SEG_HDR_ARP, 8 * 8, ETH_ALEN * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 8, ETH_ALEN),
        /* ICE_FLOW_FIELD_IDX_ARP_DHA */
-       { ICE_FLOW_SEG_HDR_ARP, 18 * 8, ETH_ALEN * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 18, ETH_ALEN),
        /* ICE_FLOW_FIELD_IDX_ARP_OP */
-       { ICE_FLOW_SEG_HDR_ARP, 6 * 8, ICE_FLOW_FLD_SZ_ARP_OPER * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 6, ICE_FLOW_FLD_SZ_ARP_OPER),
        /* ICMP */
        /* ICE_FLOW_FIELD_IDX_ICMP_TYPE */
-       { ICE_FLOW_SEG_HDR_ICMP, 0 * 8, ICE_FLOW_FLD_SZ_ICMP_TYPE * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 0, ICE_FLOW_FLD_SZ_ICMP_TYPE),
        /* ICE_FLOW_FIELD_IDX_ICMP_CODE */
-       { ICE_FLOW_SEG_HDR_ICMP, 1 * 8, ICE_FLOW_FLD_SZ_ICMP_CODE * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 1, ICE_FLOW_FLD_SZ_ICMP_CODE),
        /* GRE */
        /* ICE_FLOW_FIELD_IDX_GRE_KEYID */
-       { ICE_FLOW_SEG_HDR_GRE, 12 * 8, ICE_FLOW_FLD_SZ_GRE_KEYID * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GRE, 12, ICE_FLOW_FLD_SZ_GRE_KEYID),
 };
 
 /* Bitmaps indicating relevant packet types for a particular protocol header
@@ -189,21 +195,11 @@ static const u32 ice_ptypes_arp_of[] = {
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
 };
 
-/* Packet types for packets with an Outermost/First UDP header */
-static const u32 ice_ptypes_udp_of[] = {
-       0x81000000, 0x00000000, 0x04000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000,
-};
-
-/* Packet types for packets with an Innermost/Last UDP header */
+/* UDP Packet types for non-tunneled packets or tunneled
+ * packets with inner UDP.
+ */
 static const u32 ice_ptypes_udp_il[] = {
-       0x80000000, 0x20204040, 0x00081010, 0x80810102,
+       0x81000000, 0x20204040, 0x04081010, 0x80810102,
        0x00204040, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
@@ -216,7 +212,7 @@ static const u32 ice_ptypes_udp_il[] = {
 /* Packet types for packets with an Innermost/Last TCP header */
 static const u32 ice_ptypes_tcp_il[] = {
        0x04000000, 0x80810102, 0x10204040, 0x42040408,
-       0x00810002, 0x00000000, 0x00000000, 0x00000000,
+       0x00810102, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
@@ -288,10 +284,10 @@ static const u32 ice_ptypes_mac_il[] = {
 /* Manage parameters and info. used during the creation of a flow profile */
 struct ice_flow_prof_params {
        enum ice_block blk;
-       struct ice_flow_prof *prof;
-
        u16 entry_length; /* # of bytes formatted entry will require */
        u8 es_cnt;
+       struct ice_flow_prof *prof;
+
        /* For ACL, the es[0] will have the data of ICE_RX_MDID_PKT_FLAGS_15_0
         * This will give us the direction flags.
         */
@@ -419,9 +415,6 @@ ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params)
                const ice_bitmap_t *src;
                u32 hdrs;
 
-               if (i > 0 && (i + 1) < prof->segs_cnt)
-                       continue;
-
                hdrs = prof->segs[i].hdrs;
 
                if (hdrs & ICE_FLOW_SEG_HDR_ETH) {
@@ -467,8 +460,7 @@ ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params)
                                       ICE_FLOW_PTYPE_MAX);
                        hdrs &= ~ICE_FLOW_SEG_HDR_ICMP;
                } else if (hdrs & ICE_FLOW_SEG_HDR_UDP) {
-                       src = !i ? (const ice_bitmap_t *)ice_ptypes_udp_of :
-                               (const ice_bitmap_t *)ice_ptypes_udp_il;
+                       src = (const ice_bitmap_t *)ice_ptypes_udp_il;
                        ice_and_bitmap(params->ptypes, params->ptypes, src,
                                       ICE_FLOW_PTYPE_MAX);
                        hdrs &= ~ICE_FLOW_SEG_HDR_UDP;
@@ -644,7 +636,7 @@ ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
        /* Each extraction sequence entry is a word in size, and extracts a
         * word-aligned offset from a protocol header.
         */
-       ese_bits = ICE_FLOW_FV_EXTRACT_SZ * 8;
+       ese_bits = ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE;
 
        flds[fld].xtrct.prot_id = prot_id;
        flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) *
@@ -737,15 +729,17 @@ ice_flow_xtract_raws(struct ice_hw *hw, struct ice_flow_prof_params *params,
                raw->info.xtrct.prot_id = ICE_PROT_PAY;
                raw->info.xtrct.off = (off / ICE_FLOW_FV_EXTRACT_SZ) *
                        ICE_FLOW_FV_EXTRACT_SZ;
-               raw->info.xtrct.disp = (off % ICE_FLOW_FV_EXTRACT_SZ) * 8;
+               raw->info.xtrct.disp = (off % ICE_FLOW_FV_EXTRACT_SZ) *
+                       BITS_PER_BYTE;
                raw->info.xtrct.idx = params->es_cnt;
 
                /* Determine the number of field vector entries this raw field
                 * consumes.
                 */
                cnt = DIVIDE_AND_ROUND_UP(raw->info.xtrct.disp +
-                                         (raw->info.src.last * 8),
-                                         ICE_FLOW_FV_EXTRACT_SZ * 8);
+                                         (raw->info.src.last * BITS_PER_BYTE),
+                                         (ICE_FLOW_FV_EXTRACT_SZ *
+                                          BITS_PER_BYTE));
                off = raw->info.xtrct.off;
                for (j = 0; j < cnt; j++) {
                        /* Make sure the number of extraction sequence required
@@ -850,6 +844,7 @@ ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params)
 
 #define ICE_FLOW_FIND_PROF_CHK_FLDS    0x00000001
 #define ICE_FLOW_FIND_PROF_CHK_VSI     0x00000002
+#define ICE_FLOW_FIND_PROF_NOT_CHK_DIR 0x00000004
 
 /**
  * ice_flow_find_prof_conds - Find a profile matching headers and conditions
@@ -869,7 +864,8 @@ ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk,
        struct ice_flow_prof *p;
 
        LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
-               if (p->dir == dir && segs_cnt && segs_cnt == p->segs_cnt) {
+               if ((p->dir == dir || conds & ICE_FLOW_FIND_PROF_NOT_CHK_DIR) &&
+                   segs_cnt && segs_cnt == p->segs_cnt) {
                        u8 i;
 
                        /* Check for profile-VSI association if specified */
@@ -938,17 +934,15 @@ ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
 }
 
 /**
- * ice_flow_rem_entry_sync - Remove a flow entry
+ * ice_dealloc_flow_entry - Deallocate flow entry memory
  * @hw: pointer to the HW struct
  * @entry: flow entry to be removed
  */
-static enum ice_status
-ice_flow_rem_entry_sync(struct ice_hw *hw, struct ice_flow_entry *entry)
+static void
+ice_dealloc_flow_entry(struct ice_hw *hw, struct ice_flow_entry *entry)
 {
        if (!entry)
-               return ICE_ERR_BAD_PTR;
-
-       LIST_DEL(&entry->l_entry);
+               return;
 
        if (entry->entry)
                ice_free(hw, entry->entry);
@@ -960,6 +954,22 @@ ice_flow_rem_entry_sync(struct ice_hw *hw, struct ice_flow_entry *entry)
        }
 
        ice_free(hw, entry);
+}
+
+/**
+ * ice_flow_rem_entry_sync - Remove a flow entry
+ * @hw: pointer to the HW struct
+ * @entry: flow entry to be removed
+ */
+static enum ice_status
+ice_flow_rem_entry_sync(struct ice_hw *hw, struct ice_flow_entry *entry)
+{
+       if (!entry)
+               return ICE_ERR_BAD_PTR;
+
+       LIST_DEL(&entry->l_entry);
+
+       ice_dealloc_flow_entry(hw, entry);
 
        return ICE_SUCCESS;
 }
@@ -1605,27 +1615,32 @@ ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u64 hash_fields,
 }
 
 /**
- * ice_rem_all_rss_vsi_ctx - remove all RSS configurations from VSI context
+ * ice_rem_vsi_rss_list - remove VSI from RSS list
  * @hw: pointer to the hardware structure
  * @vsi_handle: software VSI handle
  *
+ * Remove the VSI from all RSS configurations in the list.
  */
-void ice_rem_all_rss_vsi_ctx(struct ice_hw *hw, u16 vsi_handle)
+void ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle)
 {
        struct ice_rss_cfg *r, *tmp;
 
-       if (!ice_is_vsi_valid(hw, vsi_handle) ||
-           LIST_EMPTY(&hw->vsi_ctx[vsi_handle]->rss_list_head))
+       if (LIST_EMPTY(&hw->rss_list_head))
                return;
 
-       ice_acquire_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
-       LIST_FOR_EACH_ENTRY_SAFE(r, tmp,
-                                &hw->vsi_ctx[vsi_handle]->rss_list_head,
+       ice_acquire_lock(&hw->rss_locks);
+       LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
                                 ice_rss_cfg, l_entry) {
-               LIST_DEL(&r->l_entry);
-               ice_free(hw, r);
+               if (ice_is_bit_set(r->vsis, vsi_handle)) {
+                       ice_clear_bit(vsi_handle, r->vsis);
+
+                       if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
+                               LIST_DEL(&r->l_entry);
+                               ice_free(hw, r);
+                       }
+               }
        }
-       ice_release_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
+       ice_release_lock(&hw->rss_locks);
 }
 
 /**
@@ -1646,6 +1661,9 @@ enum ice_status ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
        if (!ice_is_vsi_valid(hw, vsi_handle))
                return ICE_ERR_PARAM;
 
+       if (LIST_EMPTY(&hw->fl_profs[blk]))
+               return ICE_SUCCESS;
+
        ice_acquire_lock(&hw->fl_profs_locks[blk]);
        LIST_FOR_EACH_ENTRY_SAFE(p, t, &hw->fl_profs[blk], ice_flow_prof,
                                 l_entry) {
@@ -1667,7 +1685,7 @@ enum ice_status ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
 }
 
 /**
- * ice_rem_rss_cfg_vsi_ctx - remove RSS configuration from VSI context
+ * ice_rem_rss_list - remove RSS configuration from list
  * @hw: pointer to the hardware structure
  * @vsi_handle: software VSI handle
  * @prof: pointer to flow profile
@@ -1675,8 +1693,7 @@ enum ice_status ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
  * Assumption: lock has already been acquired for RSS list
  */
 static void
-ice_rem_rss_cfg_vsi_ctx(struct ice_hw *hw, u16 vsi_handle,
-                       struct ice_flow_prof *prof)
+ice_rem_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
 {
        struct ice_rss_cfg *r, *tmp;
 
@@ -1684,20 +1701,22 @@ ice_rem_rss_cfg_vsi_ctx(struct ice_hw *hw, u16 vsi_handle,
         * hash configurations associated to the flow profile. If found
         * remove from the RSS entry list of the VSI context and delete entry.
         */
-       LIST_FOR_EACH_ENTRY_SAFE(r, tmp,
-                                &hw->vsi_ctx[vsi_handle]->rss_list_head,
+       LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
                                 ice_rss_cfg, l_entry) {
                if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
                    r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
-                       LIST_DEL(&r->l_entry);
-                       ice_free(hw, r);
+                       ice_clear_bit(vsi_handle, r->vsis);
+                       if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
+                               LIST_DEL(&r->l_entry);
+                               ice_free(hw, r);
+                       }
                        return;
                }
        }
 }
 
 /**
- * ice_add_rss_vsi_ctx - add RSS configuration to VSI context
+ * ice_add_rss_list - add RSS configuration to list
  * @hw: pointer to the hardware structure
  * @vsi_handle: software VSI handle
  * @prof: pointer to flow profile
@@ -1705,16 +1724,17 @@ ice_rem_rss_cfg_vsi_ctx(struct ice_hw *hw, u16 vsi_handle,
  * Assumption: lock has already been acquired for RSS list
  */
 static enum ice_status
-ice_add_rss_vsi_ctx(struct ice_hw *hw, u16 vsi_handle,
-                   struct ice_flow_prof *prof)
+ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
 {
        struct ice_rss_cfg *r, *rss_cfg;
 
-       LIST_FOR_EACH_ENTRY(r, &hw->vsi_ctx[vsi_handle]->rss_list_head,
+       LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
                            ice_rss_cfg, l_entry)
                if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
-                   r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs)
+                   r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
+                       ice_set_bit(vsi_handle, r->vsis);
                        return ICE_SUCCESS;
+               }
 
        rss_cfg = (struct ice_rss_cfg *)ice_malloc(hw, sizeof(*rss_cfg));
        if (!rss_cfg)
@@ -1722,8 +1742,9 @@ ice_add_rss_vsi_ctx(struct ice_hw *hw, u16 vsi_handle,
 
        rss_cfg->hashed_flds = prof->segs[prof->segs_cnt - 1].match;
        rss_cfg->packet_hdr = prof->segs[prof->segs_cnt - 1].hdrs;
-       LIST_ADD_TAIL(&rss_cfg->l_entry,
-                     &hw->vsi_ctx[vsi_handle]->rss_list_head);
+       ice_set_bit(vsi_handle, rss_cfg->vsis);
+
+       LIST_ADD_TAIL(&rss_cfg->l_entry, &hw->rss_list_head);
 
        return ICE_SUCCESS;
 }
@@ -1785,7 +1806,7 @@ ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
        if (prof) {
                status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
                if (!status)
-                       ice_rem_rss_cfg_vsi_ctx(hw, vsi_handle, prof);
+                       ice_rem_rss_list(hw, vsi_handle, prof);
                else
                        goto exit;
 
@@ -1806,7 +1827,7 @@ ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
        if (prof) {
                status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
                if (!status)
-                       status = ice_add_rss_vsi_ctx(hw, vsi_handle, prof);
+                       status = ice_add_rss_list(hw, vsi_handle, prof);
                goto exit;
        }
 
@@ -1828,7 +1849,7 @@ ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
                goto exit;
        }
 
-       status = ice_add_rss_vsi_ctx(hw, vsi_handle, prof);
+       status = ice_add_rss_list(hw, vsi_handle, prof);
 
 exit:
        ice_free(hw, segs);
@@ -1856,9 +1877,9 @@ ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
            !ice_is_vsi_valid(hw, vsi_handle))
                return ICE_ERR_PARAM;
 
-       ice_acquire_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
+       ice_acquire_lock(&hw->rss_locks);
        status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs);
-       ice_release_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
+       ice_release_lock(&hw->rss_locks);
 
        return status;
 }
@@ -1905,7 +1926,7 @@ ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
        /* Remove RSS configuration from VSI context before deleting
         * the flow profile.
         */
-       ice_rem_rss_cfg_vsi_ctx(hw, vsi_handle, prof);
+       ice_rem_rss_list(hw, vsi_handle, prof);
 
        if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI))
                status = ice_flow_rem_prof_sync(hw, blk, prof);
@@ -1915,6 +1936,134 @@ out:
        return status;
 }
 
+/* Mapping of AVF hash bit fields to an L3-L4 hash combination.
+ * As the ice_flow_avf_hdr_field represent individual bit shifts in a hash,
+ * convert its values to their appropriate flow L3, L4 values.
+ */
+#define ICE_FLOW_AVF_RSS_IPV4_MASKS \
+       (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_OTHER) | \
+        BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV4))
+#define ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS \
+       (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP_SYN_NO_ACK) | \
+        BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP))
+#define ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS \
+       (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV4_UDP) | \
+        BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV4_UDP) | \
+        BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_UDP))
+#define ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS \
+       (ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS | \
+        ICE_FLOW_AVF_RSS_IPV4_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP))
+
+#define ICE_FLOW_AVF_RSS_IPV6_MASKS \
+       (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_OTHER) | \
+        BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV6))
+#define ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS \
+       (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV6_UDP) | \
+        BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV6_UDP) | \
+        BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_UDP))
+#define ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS \
+       (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP_SYN_NO_ACK) | \
+        BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP))
+#define ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS \
+       (ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS | \
+        ICE_FLOW_AVF_RSS_IPV6_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP))
+
+#define ICE_FLOW_MAX_CFG       10
+
+/**
+ * ice_add_avf_rss_cfg - add an RSS configuration for AVF driver
+ * @hw: pointer to the hardware structure
+ * @vsi_handle: software VSI handle
+ * @avf_hash: hash bit fields (ICE_AVF_FLOW_FIELD_*) to configure
+ *
+ * This function will take the hash bitmap provided by the AVF driver via a
+ * message, convert it to ICE-compatible values, and configure RSS flow
+ * profiles.
+ */
+enum ice_status
+ice_add_avf_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 avf_hash)
+{
+       enum ice_status status = ICE_SUCCESS;
+       u64 hash_flds;
+
+       if (avf_hash == ICE_AVF_FLOW_FIELD_INVALID ||
+           !ice_is_vsi_valid(hw, vsi_handle))
+               return ICE_ERR_PARAM;
+
+       /* Make sure no unsupported bits are specified */
+       if (avf_hash & ~(ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS |
+                        ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS))
+               return ICE_ERR_CFG;
+
+       hash_flds = avf_hash;
+
+       /* Always create an L3 RSS configuration for any L4 RSS configuration */
+       if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS)
+               hash_flds |= ICE_FLOW_AVF_RSS_IPV4_MASKS;
+
+       if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS)
+               hash_flds |= ICE_FLOW_AVF_RSS_IPV6_MASKS;
+
+       /* Create the corresponding RSS configuration for each valid hash bit */
+       while (hash_flds) {
+               u64 rss_hash = ICE_HASH_INVALID;
+
+               if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS) {
+                       if (hash_flds & ICE_FLOW_AVF_RSS_IPV4_MASKS) {
+                               rss_hash = ICE_FLOW_HASH_IPV4;
+                               hash_flds &= ~ICE_FLOW_AVF_RSS_IPV4_MASKS;
+                       } else if (hash_flds &
+                                  ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS) {
+                               rss_hash = ICE_FLOW_HASH_IPV4 |
+                                       ICE_FLOW_HASH_TCP_PORT;
+                               hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS;
+                       } else if (hash_flds &
+                                  ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS) {
+                               rss_hash = ICE_FLOW_HASH_IPV4 |
+                                       ICE_FLOW_HASH_UDP_PORT;
+                               hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS;
+                       } else if (hash_flds &
+                                  BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP)) {
+                               rss_hash = ICE_FLOW_HASH_IPV4 |
+                                       ICE_FLOW_HASH_SCTP_PORT;
+                               hash_flds &=
+                                       ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP);
+                       }
+               } else if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS) {
+                       if (hash_flds & ICE_FLOW_AVF_RSS_IPV6_MASKS) {
+                               rss_hash = ICE_FLOW_HASH_IPV6;
+                               hash_flds &= ~ICE_FLOW_AVF_RSS_IPV6_MASKS;
+                       } else if (hash_flds &
+                                  ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS) {
+                               rss_hash = ICE_FLOW_HASH_IPV6 |
+                                       ICE_FLOW_HASH_TCP_PORT;
+                               hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS;
+                       } else if (hash_flds &
+                                  ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS) {
+                               rss_hash = ICE_FLOW_HASH_IPV6 |
+                                       ICE_FLOW_HASH_UDP_PORT;
+                               hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS;
+                       } else if (hash_flds &
+                                  BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP)) {
+                               rss_hash = ICE_FLOW_HASH_IPV6 |
+                                       ICE_FLOW_HASH_SCTP_PORT;
+                               hash_flds &=
+                                       ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP);
+                       }
+               }
+
+               if (rss_hash == ICE_HASH_INVALID)
+                       return ICE_ERR_OUT_OF_RANGE;
+
+               status = ice_add_rss_cfg(hw, vsi_handle, rss_hash,
+                                        ICE_FLOW_SEG_HDR_NONE);
+               if (status)
+                       break;
+       }
+
+       return status;
+}
+
 /**
  * ice_rem_rss_cfg - remove an existing RSS config with matching hashed fields
  * @hw: pointer to the hardware structure
@@ -1938,15 +2087,15 @@ ice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
            !ice_is_vsi_valid(hw, vsi_handle))
                return ICE_ERR_PARAM;
 
-       ice_acquire_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
+       ice_acquire_lock(&hw->rss_locks);
        status = ice_rem_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs);
-       ice_release_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
+       ice_release_lock(&hw->rss_locks);
 
        return status;
 }
 
 /**
- * ice_replay_rss_cfg - remove RSS configurations associated with VSI
+ * ice_replay_rss_cfg - replay RSS configurations associated with VSI
  * @hw: pointer to the hardware structure
  * @vsi_handle: software VSI handle
  */
@@ -1958,15 +2107,18 @@ enum ice_status ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
        if (!ice_is_vsi_valid(hw, vsi_handle))
                return ICE_ERR_PARAM;
 
-       ice_acquire_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
-       LIST_FOR_EACH_ENTRY(r, &hw->vsi_ctx[vsi_handle]->rss_list_head,
+       ice_acquire_lock(&hw->rss_locks);
+       LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
                            ice_rss_cfg, l_entry) {
-               status = ice_add_rss_cfg_sync(hw, vsi_handle, r->hashed_flds,
-                                             r->packet_hdr);
-               if (status)
-                       break;
+               if (ice_is_bit_set(r->vsis, vsi_handle)) {
+                       status = ice_add_rss_cfg_sync(hw, vsi_handle,
+                                                     r->hashed_flds,
+                                                     r->packet_hdr);
+                       if (status)
+                               break;
+               }
        }
-       ice_release_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
+       ice_release_lock(&hw->rss_locks);
 
        return status;
 }
@@ -1988,14 +2140,15 @@ u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs)
        if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle))
                return ICE_HASH_INVALID;
 
-       ice_acquire_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
-       LIST_FOR_EACH_ENTRY(r, &hw->vsi_ctx[vsi_handle]->rss_list_head,
+       ice_acquire_lock(&hw->rss_locks);
+       LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
                            ice_rss_cfg, l_entry)
-               if (r->packet_hdr == hdrs) {
+               if (ice_is_bit_set(r->vsis, vsi_handle) &&
+                   r->packet_hdr == hdrs) {
                        rss_cfg = r;
                        break;
                }
-       ice_release_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
+       ice_release_lock(&hw->rss_locks);
 
        return rss_cfg ? rss_cfg->hashed_flds : ICE_HASH_INVALID;
 }