net/qede/base: changes for 100G
authorRasesh Mody <rasesh.mody@cavium.com>
Sat, 29 Sep 2018 08:14:35 +0000 (08:14 +0000)
committerFerruh Yigit <ferruh.yigit@intel.com>
Thu, 11 Oct 2018 16:53:48 +0000 (18:53 +0200)
Change details:

 - Get engine affinity from the management FW and configure accordingly
 - Add an LLH filter with the primary MAC address in QPAR/NPAR
 - Move some of the LLH APIs around
 - Add PPFID APIs
 - Update all allocated ppfids with the same value for the
   following PORT_PF registers:
   NIG_REG_DSCP_TO_TC_MAP_ENABLE
 - Add port_id, src_pfid and dst_pfid to DMA engine params

Signed-off-by: Rasesh Mody <rasesh.mody@cavium.com>
15 files changed:
drivers/net/qede/base/ecore.h
drivers/net/qede/base/ecore_cxt.c
drivers/net/qede/base/ecore_dcbx.c
drivers/net/qede/base/ecore_dev.c
drivers/net/qede/base/ecore_dev_api.h
drivers/net/qede/base/ecore_hw.c
drivers/net/qede/base/ecore_hw.h
drivers/net/qede/base/ecore_init_ops.c
drivers/net/qede/base/ecore_int.c
drivers/net/qede/base/ecore_l2.c
drivers/net/qede/base/ecore_mcp.c
drivers/net/qede/base/ecore_mcp.h
drivers/net/qede/base/ecore_sriov.c
drivers/net/qede/base/mcp_public.h
drivers/net/qede/base/reg_addr.h

index b9f5993..524a1dd 100644 (file)
@@ -19,6 +19,7 @@
 #include <zlib.h>
 #endif
 
+#include "ecore_status.h"
 #include "ecore_hsi_common.h"
 #include "ecore_hsi_debug_tools.h"
 #include "ecore_hsi_init_func.h"
@@ -207,6 +208,7 @@ struct ecore_l2_info;
 struct ecore_igu_info;
 struct ecore_mcp_info;
 struct ecore_dcbx_info;
+struct ecore_llh_info;
 
 struct ecore_rt_data {
        u32     *init_val;
@@ -743,6 +745,7 @@ struct ecore_dev {
 #endif
 #define ECORE_IS_AH(dev)       ((dev)->type == ECORE_DEV_TYPE_AH)
 #define ECORE_IS_K2(dev)       ECORE_IS_AH(dev)
+#define ECORE_IS_E4(dev)       (ECORE_IS_BB(dev) || ECORE_IS_AH(dev))
 
        u16 vendor_id;
        u16 device_id;
@@ -837,8 +840,26 @@ struct ecore_dev {
        /* HW functions */
        u8                              num_hwfns;
        struct ecore_hwfn               hwfns[MAX_HWFNS_PER_DEVICE];
+#define ECORE_LEADING_HWFN(dev)                (&dev->hwfns[0])
 #define ECORE_IS_CMT(dev)              ((dev)->num_hwfns > 1)
 
+       /* Engine affinity */
+       u8                              l2_affin_hint;
+       u8                              fir_affin;
+       u8                              iwarp_affin;
+       /* Macro for getting the engine-affinitized hwfn for FCoE/iSCSI/RoCE */
+#define ECORE_FIR_AFFIN_HWFN(dev)      (&dev->hwfns[dev->fir_affin])
+       /* Macro for getting the engine-affinitized hwfn for iWARP */
+#define ECORE_IWARP_AFFIN_HWFN(dev)    (&dev->hwfns[dev->iwarp_affin])
+       /* Generic macro for getting the engine-affinitized hwfn */
+#define ECORE_AFFIN_HWFN(dev) \
+       (ECORE_IS_IWARP_PERSONALITY(ECORE_LEADING_HWFN(dev)) ? \
+        ECORE_IWARP_AFFIN_HWFN(dev) : \
+        ECORE_FIR_AFFIN_HWFN(dev))
+       /* Macro for getting the index (0/1) of the engine-affinitized hwfn */
+#define ECORE_AFFIN_HWFN_IDX(dev) \
+       (IS_LEAD_HWFN(ECORE_AFFIN_HWFN(dev)) ? 0 : 1)
+
        /* SRIOV */
        struct ecore_hw_sriov_info      *p_iov_info;
 #define IS_ECORE_SRIOV(p_dev)          (!!(p_dev)->p_iov_info)
@@ -873,6 +894,9 @@ struct ecore_dev {
 #ifndef ASIC_ONLY
        bool                            b_is_emul_full;
 #endif
+       /* LLH info */
+       u8                              ppfid_bitmap;
+       struct ecore_llh_info           *p_llh_info;
 
        /* Indicates whether this PF serves a storage target */
        bool                            b_is_target;
@@ -974,6 +998,29 @@ u16 ecore_init_qm_get_num_pf_rls(struct ecore_hwfn *p_hwfn);
 u16 ecore_init_qm_get_num_vports(struct ecore_hwfn *p_hwfn);
 u16 ecore_init_qm_get_num_pqs(struct ecore_hwfn *p_hwfn);
 
-#define ECORE_LEADING_HWFN(dev)        (&dev->hwfns[0])
+#define MFW_PORT(_p_hwfn)      ((_p_hwfn)->abs_pf_id % \
+                                ecore_device_num_ports((_p_hwfn)->p_dev))
+
+/* The PFID<->PPFID calculation is based on the relative index of a PF on its
+ * port. In BB there is a bug in the LLH in which the PPFID is actually engine
+ * based, and thus it equals the PFID.
+ */
+#define ECORE_PFID_BY_PPFID(_p_hwfn, abs_ppfid) \
+       (ECORE_IS_BB((_p_hwfn)->p_dev) ? \
+        (abs_ppfid) : \
+        (abs_ppfid) * (_p_hwfn)->p_dev->num_ports_in_engine + \
+        MFW_PORT(_p_hwfn))
+#define ECORE_PPFID_BY_PFID(_p_hwfn) \
+       (ECORE_IS_BB((_p_hwfn)->p_dev) ? \
+        (_p_hwfn)->rel_pf_id : \
+        (_p_hwfn)->rel_pf_id / (_p_hwfn)->p_dev->num_ports_in_engine)
+
+enum _ecore_status_t ecore_all_ppfids_wr(struct ecore_hwfn *p_hwfn,
+                                        struct ecore_ptt *p_ptt, u32 addr,
+                                        u32 val);
+
+/* Utility functions for dumping the content of the NIG LLH filters */
+enum _ecore_status_t ecore_llh_dump_ppfid(struct ecore_dev *p_dev, u8 ppfid);
+enum _ecore_status_t ecore_llh_dump_all(struct ecore_dev *p_dev);
 
 #endif /* __ECORE_H */
index 6bc6348..5c3370e 100644 (file)
@@ -2114,7 +2114,7 @@ ecore_cxt_dynamic_ilt_alloc(struct ecore_hwfn *p_hwfn,
 
        ecore_dmae_host2grc(p_hwfn, p_ptt, (u64)(osal_uintptr_t)&ilt_hw_entry,
                            reg_offset, sizeof(ilt_hw_entry) / sizeof(u32),
-                           0 /* no flags */);
+                           OSAL_NULL /* default parameters */);
 
        if (elem_type == ECORE_ELEM_CXT) {
                u32 last_cid_allocated = (1 + (iid / elems_per_p)) *
@@ -2221,7 +2221,7 @@ ecore_cxt_free_ilt_range(struct ecore_hwfn *p_hwfn,
                                    (u64)(osal_uintptr_t)&ilt_hw_entry,
                                    reg_offset,
                                    sizeof(ilt_hw_entry) / sizeof(u32),
-                                   0 /* no flags */);
+                                   OSAL_NULL /* default parameters */);
        }
 
        ecore_ptt_release(p_hwfn, p_ptt);
index 9667874..7668ad6 100644 (file)
@@ -893,12 +893,19 @@ ecore_dcbx_mib_update_event(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
 
        ecore_dcbx_get_params(p_hwfn, &p_hwfn->p_dcbx_info->get, type);
 
-       /* Update the DSCP to TC mapping bit if required */
+       /* Update the DSCP to TC mapping enable bit if required */
        if ((type == ECORE_DCBX_OPERATIONAL_MIB) &&
            p_hwfn->p_dcbx_info->dscp_nig_update) {
                u8 val = !!p_hwfn->p_dcbx_info->get.dscp.enabled;
+               u32 addr = NIG_REG_DSCP_TO_TC_MAP_ENABLE;
+
+               rc = ecore_all_ppfids_wr(p_hwfn, p_ptt, addr, val);
+               if (rc != ECORE_SUCCESS) {
+                       DP_NOTICE(p_hwfn, false,
+                                 "Failed to update the DSCP to TC mapping enable bit\n");
+                       return rc;
+               }
 
-               ecore_wr(p_hwfn, p_ptt, NIG_REG_DSCP_TO_TC_MAP_ENABLE, val);
                p_hwfn->p_dcbx_info->dscp_nig_update = false;
        }
 
index 30e12e9..cf454b1 100644 (file)
@@ -352,6 +352,1189 @@ void ecore_db_recovery_execute(struct ecore_hwfn *p_hwfn,
 }
 /******************** Doorbell Recovery end ****************/
 
+/********************************** NIG LLH ***********************************/
+
+enum ecore_llh_filter_type {
+       ECORE_LLH_FILTER_TYPE_MAC,
+       ECORE_LLH_FILTER_TYPE_PROTOCOL,
+};
+
+struct ecore_llh_mac_filter {
+       u8 addr[ETH_ALEN];
+};
+
+struct ecore_llh_protocol_filter {
+       enum ecore_llh_prot_filter_type_t type;
+       u16 source_port_or_eth_type;
+       u16 dest_port;
+};
+
+union ecore_llh_filter {
+       struct ecore_llh_mac_filter mac;
+       struct ecore_llh_protocol_filter protocol;
+};
+
+struct ecore_llh_filter_info {
+       bool b_enabled;
+       u32 ref_cnt;
+       enum ecore_llh_filter_type type;
+       union ecore_llh_filter filter;
+};
+
+struct ecore_llh_info {
+       /* Number of LLH filters banks */
+       u8 num_ppfid;
+
+#define MAX_NUM_PPFID  8
+       u8 ppfid_array[MAX_NUM_PPFID];
+
+       /* Array of filters arrays:
+        * "num_ppfid" elements of filters banks, where each is an array of
+        * "NIG_REG_LLH_FUNC_FILTER_EN_SIZE" filters.
+        */
+       struct ecore_llh_filter_info **pp_filters;
+};
+
+static void ecore_llh_free(struct ecore_dev *p_dev)
+{
+       struct ecore_llh_info *p_llh_info = p_dev->p_llh_info;
+       u32 i;
+
+       if (p_llh_info != OSAL_NULL) {
+               if (p_llh_info->pp_filters != OSAL_NULL) {
+                       for (i = 0; i < p_llh_info->num_ppfid; i++)
+                               OSAL_FREE(p_dev, p_llh_info->pp_filters[i]);
+               }
+
+               OSAL_FREE(p_dev, p_llh_info->pp_filters);
+       }
+
+       OSAL_FREE(p_dev, p_llh_info);
+       p_dev->p_llh_info = OSAL_NULL;
+}
+
+static enum _ecore_status_t ecore_llh_alloc(struct ecore_dev *p_dev)
+{
+       struct ecore_llh_info *p_llh_info;
+       u32 size;
+       u8 i;
+
+       p_llh_info = OSAL_ZALLOC(p_dev, GFP_KERNEL, sizeof(*p_llh_info));
+       if (!p_llh_info)
+               return ECORE_NOMEM;
+       p_dev->p_llh_info = p_llh_info;
+
+       for (i = 0; i < MAX_NUM_PPFID; i++) {
+               if (!(p_dev->ppfid_bitmap & (0x1 << i)))
+                       continue;
+
+               p_llh_info->ppfid_array[p_llh_info->num_ppfid] = i;
+               DP_VERBOSE(p_dev, ECORE_MSG_SP, "ppfid_array[%d] = %hhd\n",
+                          p_llh_info->num_ppfid, i);
+               p_llh_info->num_ppfid++;
+       }
+
+       size = p_llh_info->num_ppfid * sizeof(*p_llh_info->pp_filters);
+       p_llh_info->pp_filters = OSAL_ZALLOC(p_dev, GFP_KERNEL, size);
+       if (!p_llh_info->pp_filters)
+               return ECORE_NOMEM;
+
+       size = NIG_REG_LLH_FUNC_FILTER_EN_SIZE *
+              sizeof(**p_llh_info->pp_filters);
+       for (i = 0; i < p_llh_info->num_ppfid; i++) {
+               p_llh_info->pp_filters[i] = OSAL_ZALLOC(p_dev, GFP_KERNEL,
+                                                       size);
+               if (!p_llh_info->pp_filters[i])
+                       return ECORE_NOMEM;
+       }
+
+       return ECORE_SUCCESS;
+}
+
+static enum _ecore_status_t ecore_llh_shadow_sanity(struct ecore_dev *p_dev,
+                                                   u8 ppfid, u8 filter_idx,
+                                                   const char *action)
+{
+       struct ecore_llh_info *p_llh_info = p_dev->p_llh_info;
+
+       if (ppfid >= p_llh_info->num_ppfid) {
+               DP_NOTICE(p_dev, false,
+                         "LLH shadow [%s]: using ppfid %d while only %d ppfids are available\n",
+                         action, ppfid, p_llh_info->num_ppfid);
+               return ECORE_INVAL;
+       }
+
+       if (filter_idx >= NIG_REG_LLH_FUNC_FILTER_EN_SIZE) {
+               DP_NOTICE(p_dev, false,
+                         "LLH shadow [%s]: using filter_idx %d while only %d filters are available\n",
+                         action, filter_idx, NIG_REG_LLH_FUNC_FILTER_EN_SIZE);
+               return ECORE_INVAL;
+       }
+
+       return ECORE_SUCCESS;
+}
+
+#define ECORE_LLH_INVALID_FILTER_IDX   0xff
+
+static enum _ecore_status_t
+ecore_llh_shadow_search_filter(struct ecore_dev *p_dev, u8 ppfid,
+                              union ecore_llh_filter *p_filter,
+                              u8 *p_filter_idx)
+{
+       struct ecore_llh_info *p_llh_info = p_dev->p_llh_info;
+       struct ecore_llh_filter_info *p_filters;
+       enum _ecore_status_t rc;
+       u8 i;
+
+       rc = ecore_llh_shadow_sanity(p_dev, ppfid, 0, "search");
+       if (rc != ECORE_SUCCESS)
+               return rc;
+
+       *p_filter_idx = ECORE_LLH_INVALID_FILTER_IDX;
+
+       p_filters = p_llh_info->pp_filters[ppfid];
+       for (i = 0; i < NIG_REG_LLH_FUNC_FILTER_EN_SIZE; i++) {
+               if (!OSAL_MEMCMP(p_filter, &p_filters[i].filter,
+                                sizeof(*p_filter))) {
+                       *p_filter_idx = i;
+                       break;
+               }
+       }
+
+       return ECORE_SUCCESS;
+}
+
+static enum _ecore_status_t
+ecore_llh_shadow_get_free_idx(struct ecore_dev *p_dev, u8 ppfid,
+                             u8 *p_filter_idx)
+{
+       struct ecore_llh_info *p_llh_info = p_dev->p_llh_info;
+       struct ecore_llh_filter_info *p_filters;
+       enum _ecore_status_t rc;
+       u8 i;
+
+       rc = ecore_llh_shadow_sanity(p_dev, ppfid, 0, "get_free_idx");
+       if (rc != ECORE_SUCCESS)
+               return rc;
+
+       *p_filter_idx = ECORE_LLH_INVALID_FILTER_IDX;
+
+       p_filters = p_llh_info->pp_filters[ppfid];
+       for (i = 0; i < NIG_REG_LLH_FUNC_FILTER_EN_SIZE; i++) {
+               if (!p_filters[i].b_enabled) {
+                       *p_filter_idx = i;
+                       break;
+               }
+       }
+
+       return ECORE_SUCCESS;
+}
+
+static enum _ecore_status_t
+__ecore_llh_shadow_add_filter(struct ecore_dev *p_dev, u8 ppfid, u8 filter_idx,
+                             enum ecore_llh_filter_type type,
+                             union ecore_llh_filter *p_filter, u32 *p_ref_cnt)
+{
+       struct ecore_llh_info *p_llh_info = p_dev->p_llh_info;
+       struct ecore_llh_filter_info *p_filters;
+       enum _ecore_status_t rc;
+
+       rc = ecore_llh_shadow_sanity(p_dev, ppfid, filter_idx, "add");
+       if (rc != ECORE_SUCCESS)
+               return rc;
+
+       p_filters = p_llh_info->pp_filters[ppfid];
+       if (!p_filters[filter_idx].ref_cnt) {
+               p_filters[filter_idx].b_enabled = true;
+               p_filters[filter_idx].type = type;
+               OSAL_MEMCPY(&p_filters[filter_idx].filter, p_filter,
+                           sizeof(p_filters[filter_idx].filter));
+       }
+
+       *p_ref_cnt = ++p_filters[filter_idx].ref_cnt;
+
+       return ECORE_SUCCESS;
+}
+
+static enum _ecore_status_t
+ecore_llh_shadow_add_filter(struct ecore_dev *p_dev, u8 ppfid,
+                           enum ecore_llh_filter_type type,
+                           union ecore_llh_filter *p_filter,
+                           u8 *p_filter_idx, u32 *p_ref_cnt)
+{
+       enum _ecore_status_t rc;
+
+       /* Check if the same filter already exist */
+       rc = ecore_llh_shadow_search_filter(p_dev, ppfid, p_filter,
+                                           p_filter_idx);
+       if (rc != ECORE_SUCCESS)
+               return rc;
+
+       /* Find a new entry in case of a new filter */
+       if (*p_filter_idx == ECORE_LLH_INVALID_FILTER_IDX) {
+               rc = ecore_llh_shadow_get_free_idx(p_dev, ppfid, p_filter_idx);
+               if (rc != ECORE_SUCCESS)
+                       return rc;
+       }
+
+       /* No free entry was found */
+       if (*p_filter_idx == ECORE_LLH_INVALID_FILTER_IDX) {
+               DP_NOTICE(p_dev, false,
+                         "Failed to find an empty LLH filter to utilize [ppfid %d]\n",
+                         ppfid);
+               return ECORE_NORESOURCES;
+       }
+
+       return __ecore_llh_shadow_add_filter(p_dev, ppfid, *p_filter_idx, type,
+                                            p_filter, p_ref_cnt);
+}
+
+static enum _ecore_status_t
+__ecore_llh_shadow_remove_filter(struct ecore_dev *p_dev, u8 ppfid,
+                                u8 filter_idx, u32 *p_ref_cnt)
+{
+       struct ecore_llh_info *p_llh_info = p_dev->p_llh_info;
+       struct ecore_llh_filter_info *p_filters;
+       enum _ecore_status_t rc;
+
+       rc = ecore_llh_shadow_sanity(p_dev, ppfid, filter_idx, "remove");
+       if (rc != ECORE_SUCCESS)
+               return rc;
+
+       p_filters = p_llh_info->pp_filters[ppfid];
+       if (!p_filters[filter_idx].ref_cnt) {
+               DP_NOTICE(p_dev, false,
+                         "LLH shadow: trying to remove a filter with ref_cnt=0\n");
+               return ECORE_INVAL;
+       }
+
+       *p_ref_cnt = --p_filters[filter_idx].ref_cnt;
+       if (!p_filters[filter_idx].ref_cnt)
+               OSAL_MEM_ZERO(&p_filters[filter_idx],
+                             sizeof(p_filters[filter_idx]));
+
+       return ECORE_SUCCESS;
+}
+
+static enum _ecore_status_t
+ecore_llh_shadow_remove_filter(struct ecore_dev *p_dev, u8 ppfid,
+                              union ecore_llh_filter *p_filter,
+                              u8 *p_filter_idx, u32 *p_ref_cnt)
+{
+       enum _ecore_status_t rc;
+
+       rc = ecore_llh_shadow_search_filter(p_dev, ppfid, p_filter,
+                                           p_filter_idx);
+       if (rc != ECORE_SUCCESS)
+               return rc;
+
+       /* No matching filter was found */
+       if (*p_filter_idx == ECORE_LLH_INVALID_FILTER_IDX) {
+               DP_NOTICE(p_dev, false,
+                         "Failed to find a filter in the LLH shadow\n");
+               return ECORE_INVAL;
+       }
+
+       return __ecore_llh_shadow_remove_filter(p_dev, ppfid, *p_filter_idx,
+                                               p_ref_cnt);
+}
+
+static enum _ecore_status_t
+ecore_llh_shadow_remove_all_filters(struct ecore_dev *p_dev, u8 ppfid)
+{
+       struct ecore_llh_info *p_llh_info = p_dev->p_llh_info;
+       struct ecore_llh_filter_info *p_filters;
+       enum _ecore_status_t rc;
+
+       rc = ecore_llh_shadow_sanity(p_dev, ppfid, 0, "remove_all");
+       if (rc != ECORE_SUCCESS)
+               return rc;
+
+       p_filters = p_llh_info->pp_filters[ppfid];
+       OSAL_MEM_ZERO(p_filters,
+                     NIG_REG_LLH_FUNC_FILTER_EN_SIZE * sizeof(*p_filters));
+
+       return ECORE_SUCCESS;
+}
+
+static enum _ecore_status_t ecore_abs_ppfid(struct ecore_dev *p_dev,
+                                           u8 rel_ppfid, u8 *p_abs_ppfid)
+{
+       struct ecore_llh_info *p_llh_info = p_dev->p_llh_info;
+       u8 ppfids = p_llh_info->num_ppfid - 1;
+
+       if (rel_ppfid >= p_llh_info->num_ppfid) {
+               DP_NOTICE(p_dev, false,
+                         "rel_ppfid %d is not valid, available indices are 0..%hhd\n",
+                         rel_ppfid, ppfids);
+               return ECORE_INVAL;
+       }
+
+       *p_abs_ppfid = p_llh_info->ppfid_array[rel_ppfid];
+
+       return ECORE_SUCCESS;
+}
+
+static enum _ecore_status_t
+__ecore_llh_set_engine_affin(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt)
+{
+       struct ecore_dev *p_dev = p_hwfn->p_dev;
+       enum ecore_eng eng;
+       u8 ppfid;
+       enum _ecore_status_t rc;
+
+       rc = ecore_mcp_get_engine_config(p_hwfn, p_ptt);
+       if (rc != ECORE_SUCCESS && rc != ECORE_NOTIMPL) {
+               DP_NOTICE(p_hwfn, false,
+                         "Failed to get the engine affinity configuration\n");
+               return rc;
+       }
+
+       /* RoCE PF is bound to a single engine */
+       if (ECORE_IS_ROCE_PERSONALITY(p_hwfn)) {
+               eng = p_dev->fir_affin ? ECORE_ENG1 : ECORE_ENG0;
+               rc = ecore_llh_set_roce_affinity(p_dev, eng);
+               if (rc != ECORE_SUCCESS) {
+                       DP_NOTICE(p_dev, false,
+                                 "Failed to set the RoCE engine affinity\n");
+                       return rc;
+               }
+
+               DP_VERBOSE(p_dev, ECORE_MSG_SP,
+                          "LLH: Set the engine affinity of RoCE packets as %d\n",
+                          eng);
+       }
+
+       /* Storage PF is bound to a single engine while L2 PF uses both */
+       if (ECORE_IS_FCOE_PERSONALITY(p_hwfn) ||
+           ECORE_IS_ISCSI_PERSONALITY(p_hwfn))
+               eng = p_dev->fir_affin ? ECORE_ENG1 : ECORE_ENG0;
+       else /* L2_PERSONALITY */
+               eng = ECORE_BOTH_ENG;
+
+       for (ppfid = 0; ppfid < p_dev->p_llh_info->num_ppfid; ppfid++) {
+               rc = ecore_llh_set_ppfid_affinity(p_dev, ppfid, eng);
+               if (rc != ECORE_SUCCESS) {
+                       DP_NOTICE(p_dev, false,
+                                 "Failed to set the engine affinity of ppfid %d\n",
+                                 ppfid);
+                       return rc;
+               }
+       }
+
+       DP_VERBOSE(p_dev, ECORE_MSG_SP,
+                  "LLH: Set the engine affinity of non-RoCE packets as %d\n",
+                  eng);
+
+       return ECORE_SUCCESS;
+}
+
+static enum _ecore_status_t
+ecore_llh_set_engine_affin(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
+                          bool avoid_eng_affin)
+{
+       struct ecore_dev *p_dev = p_hwfn->p_dev;
+       enum _ecore_status_t rc;
+
+       /* Backwards compatible mode:
+        * - RoCE packets     - Use engine 0.
+        * - Non-RoCE packets - Use connection based classification for L2 PFs,
+        *                      and engine 0 otherwise.
+        */
+       if (avoid_eng_affin) {
+               enum ecore_eng eng;
+               u8 ppfid;
+
+               if (ECORE_IS_ROCE_PERSONALITY(p_hwfn)) {
+                       eng = ECORE_ENG0;
+                       rc = ecore_llh_set_roce_affinity(p_dev, eng);
+                       if (rc != ECORE_SUCCESS) {
+                               DP_NOTICE(p_dev, false,
+                                         "Failed to set the RoCE engine affinity\n");
+                               return rc;
+                       }
+
+                       DP_VERBOSE(p_dev, ECORE_MSG_SP,
+                                  "LLH [backwards compatible mode]: Set the engine affinity of RoCE packets as %d\n",
+                                  eng);
+               }
+
+               eng = (ECORE_IS_FCOE_PERSONALITY(p_hwfn) ||
+                      ECORE_IS_ISCSI_PERSONALITY(p_hwfn)) ? ECORE_ENG0
+                                                          : ECORE_BOTH_ENG;
+               for (ppfid = 0; ppfid < p_dev->p_llh_info->num_ppfid; ppfid++) {
+                       rc = ecore_llh_set_ppfid_affinity(p_dev, ppfid, eng);
+                       if (rc != ECORE_SUCCESS) {
+                               DP_NOTICE(p_dev, false,
+                                         "Failed to set the engine affinity of ppfid %d\n",
+                                         ppfid);
+                               return rc;
+                       }
+               }
+
+               DP_VERBOSE(p_dev, ECORE_MSG_SP,
+                          "LLH [backwards compatible mode]: Set the engine affinity of non-RoCE packets as %d\n",
+                          eng);
+
+               return ECORE_SUCCESS;
+       }
+
+       return __ecore_llh_set_engine_affin(p_hwfn, p_ptt);
+}
+
+static enum _ecore_status_t ecore_llh_hw_init_pf(struct ecore_hwfn *p_hwfn,
+                                                struct ecore_ptt *p_ptt,
+                                                bool avoid_eng_affin)
+{
+       struct ecore_dev *p_dev = p_hwfn->p_dev;
+       u8 ppfid, abs_ppfid;
+       enum _ecore_status_t rc;
+
+       for (ppfid = 0; ppfid < p_dev->p_llh_info->num_ppfid; ppfid++) {
+               u32 addr;
+
+               rc = ecore_abs_ppfid(p_dev, ppfid, &abs_ppfid);
+               if (rc != ECORE_SUCCESS)
+                       return rc;
+
+               addr = NIG_REG_LLH_PPFID2PFID_TBL_0 + abs_ppfid * 0x4;
+               ecore_wr(p_hwfn, p_ptt, addr, p_hwfn->rel_pf_id);
+       }
+
+       if (OSAL_TEST_BIT(ECORE_MF_LLH_MAC_CLSS, &p_dev->mf_bits) &&
+           !ECORE_IS_FCOE_PERSONALITY(p_hwfn)) {
+               rc = ecore_llh_add_mac_filter(p_dev, 0,
+                                             p_hwfn->hw_info.hw_mac_addr);
+               if (rc != ECORE_SUCCESS)
+                       DP_NOTICE(p_dev, false,
+                                 "Failed to add an LLH filter with the primary MAC\n");
+       }
+
+       if (ECORE_IS_CMT(p_dev)) {
+               rc = ecore_llh_set_engine_affin(p_hwfn, p_ptt, avoid_eng_affin);
+               if (rc != ECORE_SUCCESS)
+                       return rc;
+       }
+
+       return ECORE_SUCCESS;
+}
+
+u8 ecore_llh_get_num_ppfid(struct ecore_dev *p_dev)
+{
+       return p_dev->p_llh_info->num_ppfid;
+}
+
+enum ecore_eng ecore_llh_get_l2_affinity_hint(struct ecore_dev *p_dev)
+{
+       return p_dev->l2_affin_hint ? ECORE_ENG1 : ECORE_ENG0;
+}
+
+/* TBD - should be removed when these definitions are available in reg_addr.h */
+#define NIG_REG_PPF_TO_ENGINE_SEL_ROCE_MASK            0x3
+#define NIG_REG_PPF_TO_ENGINE_SEL_ROCE_SHIFT           0
+#define NIG_REG_PPF_TO_ENGINE_SEL_NON_ROCE_MASK                0x3
+#define NIG_REG_PPF_TO_ENGINE_SEL_NON_ROCE_SHIFT       2
+
+enum _ecore_status_t ecore_llh_set_ppfid_affinity(struct ecore_dev *p_dev,
+                                                 u8 ppfid, enum ecore_eng eng)
+{
+       struct ecore_hwfn *p_hwfn = ECORE_LEADING_HWFN(p_dev);
+       struct ecore_ptt *p_ptt = ecore_ptt_acquire(p_hwfn);
+       u32 addr, val, eng_sel;
+       enum _ecore_status_t rc = ECORE_SUCCESS;
+       u8 abs_ppfid;
+
+       if (p_ptt == OSAL_NULL)
+               return ECORE_AGAIN;
+
+       if (!ECORE_IS_CMT(p_dev))
+               goto out;
+
+       rc = ecore_abs_ppfid(p_dev, ppfid, &abs_ppfid);
+       if (rc != ECORE_SUCCESS)
+               goto out;
+
+       switch (eng) {
+       case ECORE_ENG0:
+               eng_sel = 0;
+               break;
+       case ECORE_ENG1:
+               eng_sel = 1;
+               break;
+       case ECORE_BOTH_ENG:
+               eng_sel = 2;
+               break;
+       default:
+               DP_NOTICE(p_dev, false,
+                         "Invalid affinity value for ppfid [%d]\n", eng);
+               rc = ECORE_INVAL;
+               goto out;
+       }
+
+       addr = NIG_REG_PPF_TO_ENGINE_SEL + abs_ppfid * 0x4;
+       val = ecore_rd(p_hwfn, p_ptt, addr);
+       SET_FIELD(val, NIG_REG_PPF_TO_ENGINE_SEL_NON_ROCE, eng_sel);
+       ecore_wr(p_hwfn, p_ptt, addr, val);
+
+       /* The iWARP affinity is set as the affinity of ppfid 0 */
+       if (!ppfid && ECORE_IS_IWARP_PERSONALITY(p_hwfn))
+               p_dev->iwarp_affin = (eng == ECORE_ENG1) ? 1 : 0;
+out:
+       ecore_ptt_release(p_hwfn, p_ptt);
+
+       return rc;
+}
+
+enum _ecore_status_t ecore_llh_set_roce_affinity(struct ecore_dev *p_dev,
+                                                enum ecore_eng eng)
+{
+       struct ecore_hwfn *p_hwfn = ECORE_LEADING_HWFN(p_dev);
+       struct ecore_ptt *p_ptt = ecore_ptt_acquire(p_hwfn);
+       u32 addr, val, eng_sel;
+       enum _ecore_status_t rc = ECORE_SUCCESS;
+       u8 ppfid, abs_ppfid;
+
+       if (p_ptt == OSAL_NULL)
+               return ECORE_AGAIN;
+
+       if (!ECORE_IS_CMT(p_dev))
+               goto out;
+
+       switch (eng) {
+       case ECORE_ENG0:
+               eng_sel = 0;
+               break;
+       case ECORE_ENG1:
+               eng_sel = 1;
+               break;
+       case ECORE_BOTH_ENG:
+               eng_sel = 2;
+               ecore_wr(p_hwfn, p_ptt, NIG_REG_LLH_ENG_CLS_ROCE_QP_SEL,
+                        0xf /* QP bit 15 */);
+               break;
+       default:
+               DP_NOTICE(p_dev, false,
+                         "Invalid affinity value for RoCE [%d]\n", eng);
+               rc = ECORE_INVAL;
+               goto out;
+       }
+
+       for (ppfid = 0; ppfid < p_dev->p_llh_info->num_ppfid; ppfid++) {
+               rc = ecore_abs_ppfid(p_dev, ppfid, &abs_ppfid);
+               if (rc != ECORE_SUCCESS)
+                       goto out;
+
+               addr = NIG_REG_PPF_TO_ENGINE_SEL + abs_ppfid * 0x4;
+               val = ecore_rd(p_hwfn, p_ptt, addr);
+               SET_FIELD(val, NIG_REG_PPF_TO_ENGINE_SEL_ROCE, eng_sel);
+               ecore_wr(p_hwfn, p_ptt, addr, val);
+       }
+out:
+       ecore_ptt_release(p_hwfn, p_ptt);
+
+       return rc;
+}
+
+struct ecore_llh_filter_e4_details {
+       u64 value;
+       u32 mode;
+       u32 protocol_type;
+       u32 hdr_sel;
+       u32 enable;
+};
+
+static enum _ecore_status_t
+ecore_llh_access_filter_e4(struct ecore_hwfn *p_hwfn,
+                          struct ecore_ptt *p_ptt, u8 abs_ppfid, u8 filter_idx,
+                          struct ecore_llh_filter_e4_details *p_details,
+                          bool b_write_access)
+{
+       u8 pfid = ECORE_PFID_BY_PPFID(p_hwfn, abs_ppfid);
+       struct ecore_dmae_params params;
+       enum _ecore_status_t rc;
+       u32 addr;
+
+       /* The NIG/LLH registers that are accessed in this function have only 16
+        * rows which are exposed to a PF. I.e. only the 16 filters of its
+        * default ppfid
+        * Accessing filters of other ppfids requires pretending to other PFs,
+        * and thus the usage of the ecore_ppfid_rd/wr() functions.
+        */
+
+       /* Filter enable - should be done first when removing a filter */
+       if (b_write_access && !p_details->enable) {
+               addr = NIG_REG_LLH_FUNC_FILTER_EN_BB_K2 + filter_idx * 0x4;
+               ecore_ppfid_wr(p_hwfn, p_ptt, abs_ppfid, addr,
+                              p_details->enable);
+       }
+
+       /* Filter value */
+       addr = NIG_REG_LLH_FUNC_FILTER_VALUE_BB_K2 + 2 * filter_idx * 0x4;
+       OSAL_MEMSET(&params, 0, sizeof(params));
+
+       if (b_write_access) {
+               params.flags = ECORE_DMAE_FLAG_PF_DST;
+               params.dst_pfid = pfid;
+               rc = ecore_dmae_host2grc(p_hwfn, p_ptt,
+                                        (u64)(osal_uintptr_t)&p_details->value,
+                                        addr, 2 /* size_in_dwords */, &params);
+       } else {
+               params.flags = ECORE_DMAE_FLAG_PF_SRC |
+                              ECORE_DMAE_FLAG_COMPLETION_DST;
+               params.src_pfid = pfid;
+               rc = ecore_dmae_grc2host(p_hwfn, p_ptt, addr,
+                                        (u64)(osal_uintptr_t)&p_details->value,
+                                        2 /* size_in_dwords */, &params);
+       }
+
+       if (rc != ECORE_SUCCESS)
+               return rc;
+
+       /* Filter mode */
+       addr = NIG_REG_LLH_FUNC_FILTER_MODE_BB_K2 + filter_idx * 0x4;
+       if (b_write_access)
+               ecore_ppfid_wr(p_hwfn, p_ptt, abs_ppfid, addr, p_details->mode);
+       else
+               p_details->mode = ecore_ppfid_rd(p_hwfn, p_ptt, abs_ppfid,
+                                                addr);
+
+       /* Filter protocol type */
+       addr = NIG_REG_LLH_FUNC_FILTER_PROTOCOL_TYPE_BB_K2 + filter_idx * 0x4;
+       if (b_write_access)
+               ecore_ppfid_wr(p_hwfn, p_ptt, abs_ppfid, addr,
+                              p_details->protocol_type);
+       else
+               p_details->protocol_type = ecore_ppfid_rd(p_hwfn, p_ptt,
+                                                         abs_ppfid, addr);
+
+       /* Filter header select */
+       addr = NIG_REG_LLH_FUNC_FILTER_HDR_SEL_BB_K2 + filter_idx * 0x4;
+       if (b_write_access)
+               ecore_ppfid_wr(p_hwfn, p_ptt, abs_ppfid, addr,
+                              p_details->hdr_sel);
+       else
+               p_details->hdr_sel = ecore_ppfid_rd(p_hwfn, p_ptt, abs_ppfid,
+                                                   addr);
+
+       /* Filter enable - should be done last when adding a filter */
+       if (!b_write_access || p_details->enable) {
+               addr = NIG_REG_LLH_FUNC_FILTER_EN_BB_K2 + filter_idx * 0x4;
+               if (b_write_access)
+                       ecore_ppfid_wr(p_hwfn, p_ptt, abs_ppfid, addr,
+                                      p_details->enable);
+               else
+                       p_details->enable = ecore_ppfid_rd(p_hwfn, p_ptt,
+                                                          abs_ppfid, addr);
+       }
+
+       return ECORE_SUCCESS;
+}
+
+static enum _ecore_status_t
+ecore_llh_add_filter_e4(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
+                       u8 abs_ppfid, u8 filter_idx, u8 filter_prot_type,
+                       u32 high, u32 low)
+{
+       struct ecore_llh_filter_e4_details filter_details;
+
+       filter_details.enable = 1;
+       filter_details.value = ((u64)high << 32) | low;
+       filter_details.hdr_sel =
+               OSAL_TEST_BIT(ECORE_MF_OVLAN_CLSS, &p_hwfn->p_dev->mf_bits) ?
+               1 : /* inner/encapsulated header */
+               0;  /* outer/tunnel header */
+       filter_details.protocol_type = filter_prot_type;
+       filter_details.mode = filter_prot_type ?
+                             1 : /* protocol-based classification */
+                             0;  /* MAC-address based classification */
+
+       return ecore_llh_access_filter_e4(p_hwfn, p_ptt, abs_ppfid, filter_idx,
+                                         &filter_details,
+                                         true /* write access */);
+}
+
+static enum _ecore_status_t
+ecore_llh_remove_filter_e4(struct ecore_hwfn *p_hwfn,
+                          struct ecore_ptt *p_ptt, u8 abs_ppfid, u8 filter_idx)
+{
+       struct ecore_llh_filter_e4_details filter_details;
+
+       OSAL_MEMSET(&filter_details, 0, sizeof(filter_details));
+
+       return ecore_llh_access_filter_e4(p_hwfn, p_ptt, abs_ppfid, filter_idx,
+                                         &filter_details,
+                                         true /* write access */);
+}
+
+static enum _ecore_status_t
+ecore_llh_add_filter(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
+                    u8 abs_ppfid, u8 filter_idx, u8 filter_prot_type, u32 high,
+                    u32 low)
+{
+       return ecore_llh_add_filter_e4(p_hwfn, p_ptt, abs_ppfid,
+                                      filter_idx, filter_prot_type,
+                                      high, low);
+}
+
+static enum _ecore_status_t
+ecore_llh_remove_filter(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
+                       u8 abs_ppfid, u8 filter_idx)
+{
+       return ecore_llh_remove_filter_e4(p_hwfn, p_ptt, abs_ppfid,
+                                         filter_idx);
+}
+
+enum _ecore_status_t ecore_llh_add_mac_filter(struct ecore_dev *p_dev, u8 ppfid,
+                                             u8 mac_addr[ETH_ALEN])
+{
+       struct ecore_hwfn *p_hwfn = ECORE_LEADING_HWFN(p_dev);
+       struct ecore_ptt *p_ptt = ecore_ptt_acquire(p_hwfn);
+       union ecore_llh_filter filter;
+       u8 filter_idx, abs_ppfid;
+       u32 high, low, ref_cnt;
+       enum _ecore_status_t rc = ECORE_SUCCESS;
+
+       if (p_ptt == OSAL_NULL)
+               return ECORE_AGAIN;
+
+       if (!OSAL_TEST_BIT(ECORE_MF_LLH_MAC_CLSS, &p_dev->mf_bits))
+               goto out;
+
+       OSAL_MEM_ZERO(&filter, sizeof(filter));
+       OSAL_MEMCPY(filter.mac.addr, mac_addr, ETH_ALEN);
+       rc = ecore_llh_shadow_add_filter(p_dev, ppfid,
+                                        ECORE_LLH_FILTER_TYPE_MAC,
+                                        &filter, &filter_idx, &ref_cnt);
+       if (rc != ECORE_SUCCESS)
+               goto err;
+
+       rc = ecore_abs_ppfid(p_dev, ppfid, &abs_ppfid);
+       if (rc != ECORE_SUCCESS)
+               goto err;
+
+       /* Configure the LLH only in case of a new the filter */
+       if (ref_cnt == 1) {
+               high = mac_addr[1] | (mac_addr[0] << 8);
+               low = mac_addr[5] | (mac_addr[4] << 8) | (mac_addr[3] << 16) |
+                     (mac_addr[2] << 24);
+               rc = ecore_llh_add_filter(p_hwfn, p_ptt, abs_ppfid, filter_idx,
+                                         0, high, low);
+               if (rc != ECORE_SUCCESS)
+                       goto err;
+       }
+
+       DP_VERBOSE(p_dev, ECORE_MSG_SP,
+                  "LLH: Added MAC filter [%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx] to ppfid %hhd [abs %hhd] at idx %hhd [ref_cnt %d]\n",
+                  mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3],
+                  mac_addr[4], mac_addr[5], ppfid, abs_ppfid, filter_idx,
+                  ref_cnt);
+
+       goto out;
+
+err:
+       DP_NOTICE(p_dev, false,
+                 "LLH: Failed to add MAC filter [%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx] to ppfid %hhd\n",
+                 mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3],
+                 mac_addr[4], mac_addr[5], ppfid);
+out:
+       ecore_ptt_release(p_hwfn, p_ptt);
+
+       return rc;
+}
+
+static enum _ecore_status_t
+ecore_llh_protocol_filter_stringify(struct ecore_dev *p_dev,
+                                   enum ecore_llh_prot_filter_type_t type,
+                                   u16 source_port_or_eth_type, u16 dest_port,
+                                   char *str, osal_size_t str_len)
+{
+       switch (type) {
+       case ECORE_LLH_FILTER_ETHERTYPE:
+               OSAL_SNPRINTF(str, str_len, "Ethertype 0x%04x",
+                             source_port_or_eth_type);
+               break;
+       case ECORE_LLH_FILTER_TCP_SRC_PORT:
+               OSAL_SNPRINTF(str, str_len, "TCP src port 0x%04x",
+                             source_port_or_eth_type);
+               break;
+       case ECORE_LLH_FILTER_UDP_SRC_PORT:
+               OSAL_SNPRINTF(str, str_len, "UDP src port 0x%04x",
+                             source_port_or_eth_type);
+               break;
+       case ECORE_LLH_FILTER_TCP_DEST_PORT:
+               OSAL_SNPRINTF(str, str_len, "TCP dst port 0x%04x", dest_port);
+               break;
+       case ECORE_LLH_FILTER_UDP_DEST_PORT:
+               OSAL_SNPRINTF(str, str_len, "UDP dst port 0x%04x", dest_port);
+               break;
+       case ECORE_LLH_FILTER_TCP_SRC_AND_DEST_PORT:
+               OSAL_SNPRINTF(str, str_len, "TCP src/dst ports 0x%04x/0x%04x",
+                             source_port_or_eth_type, dest_port);
+               break;
+       case ECORE_LLH_FILTER_UDP_SRC_AND_DEST_PORT:
+               OSAL_SNPRINTF(str, str_len, "UDP src/dst ports 0x%04x/0x%04x",
+                             source_port_or_eth_type, dest_port);
+               break;
+       default:
+               DP_NOTICE(p_dev, true,
+                         "Non valid LLH protocol filter type %d\n", type);
+               return ECORE_INVAL;
+       }
+
+       return ECORE_SUCCESS;
+}
+
+static enum _ecore_status_t
+ecore_llh_protocol_filter_to_hilo(struct ecore_dev *p_dev,
+                                 enum ecore_llh_prot_filter_type_t type,
+                                 u16 source_port_or_eth_type, u16 dest_port,
+                                 u32 *p_high, u32 *p_low)
+{
+       *p_high = 0;
+       *p_low = 0;
+
+       switch (type) {
+       case ECORE_LLH_FILTER_ETHERTYPE:
+               *p_high = source_port_or_eth_type;
+               break;
+       case ECORE_LLH_FILTER_TCP_SRC_PORT:
+       case ECORE_LLH_FILTER_UDP_SRC_PORT:
+               *p_low = source_port_or_eth_type << 16;
+               break;
+       case ECORE_LLH_FILTER_TCP_DEST_PORT:
+       case ECORE_LLH_FILTER_UDP_DEST_PORT:
+               *p_low = dest_port;
+               break;
+       case ECORE_LLH_FILTER_TCP_SRC_AND_DEST_PORT:
+       case ECORE_LLH_FILTER_UDP_SRC_AND_DEST_PORT:
+               *p_low = (source_port_or_eth_type << 16) | dest_port;
+               break;
+       default:
+               DP_NOTICE(p_dev, true,
+                         "Non valid LLH protocol filter type %d\n", type);
+               return ECORE_INVAL;
+       }
+
+       return ECORE_SUCCESS;
+}
+
+enum _ecore_status_t
+ecore_llh_add_protocol_filter(struct ecore_dev *p_dev, u8 ppfid,
+                             enum ecore_llh_prot_filter_type_t type,
+                             u16 source_port_or_eth_type, u16 dest_port)
+{
+       struct ecore_hwfn *p_hwfn = ECORE_LEADING_HWFN(p_dev);
+       struct ecore_ptt *p_ptt = ecore_ptt_acquire(p_hwfn);
+       u8 filter_idx, abs_ppfid, type_bitmap;
+       char str[32];
+       union ecore_llh_filter filter;
+       u32 high, low, ref_cnt;
+       enum _ecore_status_t rc = ECORE_SUCCESS;
+
+       if (p_ptt == OSAL_NULL)
+               return ECORE_AGAIN;
+
+       if (!OSAL_TEST_BIT(ECORE_MF_LLH_PROTO_CLSS, &p_dev->mf_bits))
+               goto out;
+
+       rc = ecore_llh_protocol_filter_stringify(p_dev, type,
+                                                source_port_or_eth_type,
+                                                dest_port, str, sizeof(str));
+       if (rc != ECORE_SUCCESS)
+               goto err;
+
+       OSAL_MEM_ZERO(&filter, sizeof(filter));
+       filter.protocol.type = type;
+       filter.protocol.source_port_or_eth_type = source_port_or_eth_type;
+       filter.protocol.dest_port = dest_port;
+       rc = ecore_llh_shadow_add_filter(p_dev, ppfid,
+                                        ECORE_LLH_FILTER_TYPE_PROTOCOL,
+                                        &filter, &filter_idx, &ref_cnt);
+       if (rc != ECORE_SUCCESS)
+               goto err;
+
+       rc = ecore_abs_ppfid(p_dev, ppfid, &abs_ppfid);
+       if (rc != ECORE_SUCCESS)
+               goto err;
+
+       /* Configure the LLH only in case of a new the filter */
+       if (ref_cnt == 1) {
+               rc = ecore_llh_protocol_filter_to_hilo(p_dev, type,
+                                                      source_port_or_eth_type,
+                                                      dest_port, &high, &low);
+               if (rc != ECORE_SUCCESS)
+                       goto err;
+
+               type_bitmap = 0x1 << type;
+               rc = ecore_llh_add_filter(p_hwfn, p_ptt, abs_ppfid, filter_idx,
+                                         type_bitmap, high, low);
+               if (rc != ECORE_SUCCESS)
+                       goto err;
+       }
+
+       DP_VERBOSE(p_dev, ECORE_MSG_SP,
+                  "LLH: Added protocol filter [%s] to ppfid %hhd [abs %hhd] at idx %hhd [ref_cnt %d]\n",
+                  str, ppfid, abs_ppfid, filter_idx, ref_cnt);
+
+       goto out;
+
+err:
+       DP_NOTICE(p_hwfn, false,
+                 "LLH: Failed to add protocol filter [%s] to ppfid %hhd\n",
+                 str, ppfid);
+out:
+       ecore_ptt_release(p_hwfn, p_ptt);
+
+       return rc;
+}
+
+void ecore_llh_remove_mac_filter(struct ecore_dev *p_dev, u8 ppfid,
+                                u8 mac_addr[ETH_ALEN])
+{
+       struct ecore_hwfn *p_hwfn = ECORE_LEADING_HWFN(p_dev);
+       struct ecore_ptt *p_ptt = ecore_ptt_acquire(p_hwfn);
+       union ecore_llh_filter filter;
+       u8 filter_idx, abs_ppfid;
+       enum _ecore_status_t rc = ECORE_SUCCESS;
+       u32 ref_cnt;
+
+       if (p_ptt == OSAL_NULL)
+               return;
+
+       if (!OSAL_TEST_BIT(ECORE_MF_LLH_MAC_CLSS, &p_dev->mf_bits))
+               goto out;
+
+       OSAL_MEM_ZERO(&filter, sizeof(filter));
+       OSAL_MEMCPY(filter.mac.addr, mac_addr, ETH_ALEN);
+       rc = ecore_llh_shadow_remove_filter(p_dev, ppfid, &filter, &filter_idx,
+                                           &ref_cnt);
+       if (rc != ECORE_SUCCESS)
+               goto err;
+
+       rc = ecore_abs_ppfid(p_dev, ppfid, &abs_ppfid);
+       if (rc != ECORE_SUCCESS)
+               goto err;
+
+       /* Remove from the LLH in case the filter is not in use */
+       if (!ref_cnt) {
+               rc = ecore_llh_remove_filter(p_hwfn, p_ptt, abs_ppfid,
+                                            filter_idx);
+               if (rc != ECORE_SUCCESS)
+                       goto err;
+       }
+
+       DP_VERBOSE(p_dev, ECORE_MSG_SP,
+                  "LLH: Removed MAC filter [%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx] from ppfid %hhd [abs %hhd] at idx %hhd [ref_cnt %d]\n",
+                  mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3],
+                  mac_addr[4], mac_addr[5], ppfid, abs_ppfid, filter_idx,
+                  ref_cnt);
+
+       goto out;
+
+err:
+       DP_NOTICE(p_dev, false,
+                 "LLH: Failed to remove MAC filter [%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx] from ppfid %hhd\n",
+                 mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3],
+                 mac_addr[4], mac_addr[5], ppfid);
+out:
+       ecore_ptt_release(p_hwfn, p_ptt);
+}
+
+void ecore_llh_remove_protocol_filter(struct ecore_dev *p_dev, u8 ppfid,
+                                     enum ecore_llh_prot_filter_type_t type,
+                                     u16 source_port_or_eth_type,
+                                     u16 dest_port)
+{
+       struct ecore_hwfn *p_hwfn = ECORE_LEADING_HWFN(p_dev);
+       struct ecore_ptt *p_ptt = ecore_ptt_acquire(p_hwfn);
+       u8 filter_idx, abs_ppfid;
+       char str[32];
+       union ecore_llh_filter filter;
+       enum _ecore_status_t rc = ECORE_SUCCESS;
+       u32 ref_cnt;
+
+       if (p_ptt == OSAL_NULL)
+               return;
+
+       if (!OSAL_TEST_BIT(ECORE_MF_LLH_PROTO_CLSS, &p_dev->mf_bits))
+               goto out;
+
+       rc = ecore_llh_protocol_filter_stringify(p_dev, type,
+                                                source_port_or_eth_type,
+                                                dest_port, str, sizeof(str));
+       if (rc != ECORE_SUCCESS)
+               goto err;
+
+       OSAL_MEM_ZERO(&filter, sizeof(filter));
+       filter.protocol.type = type;
+       filter.protocol.source_port_or_eth_type = source_port_or_eth_type;
+       filter.protocol.dest_port = dest_port;
+       rc = ecore_llh_shadow_remove_filter(p_dev, ppfid, &filter, &filter_idx,
+                                           &ref_cnt);
+       if (rc != ECORE_SUCCESS)
+               goto err;
+
+       rc = ecore_abs_ppfid(p_dev, ppfid, &abs_ppfid);
+       if (rc != ECORE_SUCCESS)
+               goto err;
+
+       /* Remove from the LLH in case the filter is not in use */
+       if (!ref_cnt) {
+               rc = ecore_llh_remove_filter(p_hwfn, p_ptt, abs_ppfid,
+                                            filter_idx);
+               if (rc != ECORE_SUCCESS)
+                       goto err;
+       }
+
+       DP_VERBOSE(p_dev, ECORE_MSG_SP,
+                  "LLH: Removed protocol filter [%s] from ppfid %hhd [abs %hhd] at idx %hhd [ref_cnt %d]\n",
+                  str, ppfid, abs_ppfid, filter_idx, ref_cnt);
+
+       goto out;
+
+err:
+       DP_NOTICE(p_dev, false,
+                 "LLH: Failed to remove protocol filter [%s] from ppfid %hhd\n",
+                 str, ppfid);
+out:
+       ecore_ptt_release(p_hwfn, p_ptt);
+}
+
+void ecore_llh_clear_ppfid_filters(struct ecore_dev *p_dev, u8 ppfid)
+{
+       struct ecore_hwfn *p_hwfn = ECORE_LEADING_HWFN(p_dev);
+       struct ecore_ptt *p_ptt = ecore_ptt_acquire(p_hwfn);
+       u8 filter_idx, abs_ppfid;
+       enum _ecore_status_t rc = ECORE_SUCCESS;
+
+       if (p_ptt == OSAL_NULL)
+               return;
+
+       if (!OSAL_TEST_BIT(ECORE_MF_LLH_PROTO_CLSS, &p_dev->mf_bits) &&
+           !OSAL_TEST_BIT(ECORE_MF_LLH_MAC_CLSS, &p_dev->mf_bits))
+               goto out;
+
+       rc = ecore_abs_ppfid(p_dev, ppfid, &abs_ppfid);
+       if (rc != ECORE_SUCCESS)
+               goto out;
+
+       rc = ecore_llh_shadow_remove_all_filters(p_dev, ppfid);
+       if (rc != ECORE_SUCCESS)
+               goto out;
+
+       for (filter_idx = 0; filter_idx < NIG_REG_LLH_FUNC_FILTER_EN_SIZE;
+            filter_idx++) {
+               rc = ecore_llh_remove_filter_e4(p_hwfn, p_ptt,
+                                               abs_ppfid, filter_idx);
+               if (rc != ECORE_SUCCESS)
+                       goto out;
+       }
+out:
+       ecore_ptt_release(p_hwfn, p_ptt);
+}
+
+void ecore_llh_clear_all_filters(struct ecore_dev *p_dev)
+{
+       u8 ppfid;
+
+       if (!OSAL_TEST_BIT(ECORE_MF_LLH_PROTO_CLSS, &p_dev->mf_bits) &&
+           !OSAL_TEST_BIT(ECORE_MF_LLH_MAC_CLSS, &p_dev->mf_bits))
+               return;
+
+       for (ppfid = 0; ppfid < p_dev->p_llh_info->num_ppfid; ppfid++)
+               ecore_llh_clear_ppfid_filters(p_dev, ppfid);
+}
+
+enum _ecore_status_t ecore_all_ppfids_wr(struct ecore_hwfn *p_hwfn,
+                                        struct ecore_ptt *p_ptt, u32 addr,
+                                        u32 val)
+{
+       struct ecore_dev *p_dev = p_hwfn->p_dev;
+       u8 ppfid, abs_ppfid;
+       enum _ecore_status_t rc;
+
+       for (ppfid = 0; ppfid < p_dev->p_llh_info->num_ppfid; ppfid++) {
+               rc = ecore_abs_ppfid(p_dev, ppfid, &abs_ppfid);
+               if (rc != ECORE_SUCCESS)
+                       return rc;
+
+               ecore_ppfid_wr(p_hwfn, p_ptt, abs_ppfid, addr, val);
+       }
+
+       return ECORE_SUCCESS;
+}
+
+static enum _ecore_status_t
+ecore_llh_dump_ppfid_e4(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
+                       u8 ppfid)
+{
+       struct ecore_llh_filter_e4_details filter_details;
+       u8 abs_ppfid, filter_idx;
+       u32 addr;
+       enum _ecore_status_t rc;
+
+       rc = ecore_abs_ppfid(p_hwfn->p_dev, ppfid, &abs_ppfid);
+       if (rc != ECORE_SUCCESS)
+               return rc;
+
+       addr = NIG_REG_PPF_TO_ENGINE_SEL + abs_ppfid * 0x4;
+       DP_NOTICE(p_hwfn, false,
+                 "[rel_pf_id %hhd, ppfid={rel %hhd, abs %hhd}, engine_sel 0x%x]\n",
+                 p_hwfn->rel_pf_id, ppfid, abs_ppfid,
+                 ecore_rd(p_hwfn, p_ptt, addr));
+
+       for (filter_idx = 0; filter_idx < NIG_REG_LLH_FUNC_FILTER_EN_SIZE;
+            filter_idx++) {
+               OSAL_MEMSET(&filter_details, 0, sizeof(filter_details));
+               rc =  ecore_llh_access_filter_e4(p_hwfn, p_ptt, abs_ppfid,
+                                                filter_idx, &filter_details,
+                                                false /* read access */);
+               if (rc != ECORE_SUCCESS)
+                       return rc;
+
+               DP_NOTICE(p_hwfn, false,
+                         "filter %2hhd: enable %d, value 0x%016lx, mode %d, protocol_type 0x%x, hdr_sel 0x%x\n",
+                         filter_idx, filter_details.enable,
+                         (unsigned long)filter_details.value,
+                         filter_details.mode,
+                         filter_details.protocol_type, filter_details.hdr_sel);
+       }
+
+       return ECORE_SUCCESS;
+}
+
+enum _ecore_status_t ecore_llh_dump_ppfid(struct ecore_dev *p_dev, u8 ppfid)
+{
+       struct ecore_hwfn *p_hwfn = ECORE_LEADING_HWFN(p_dev);
+       struct ecore_ptt *p_ptt = ecore_ptt_acquire(p_hwfn);
+       enum _ecore_status_t rc;
+
+       if (p_ptt == OSAL_NULL)
+               return ECORE_AGAIN;
+
+       rc = ecore_llh_dump_ppfid_e4(p_hwfn, p_ptt, ppfid);
+
+       ecore_ptt_release(p_hwfn, p_ptt);
+
+       return rc;
+}
+
+enum _ecore_status_t ecore_llh_dump_all(struct ecore_dev *p_dev)
+{
+       u8 ppfid;
+       enum _ecore_status_t rc;
+
+       for (ppfid = 0; ppfid < p_dev->p_llh_info->num_ppfid; ppfid++) {
+               rc = ecore_llh_dump_ppfid(p_dev, ppfid);
+               if (rc != ECORE_SUCCESS)
+                       return rc;
+       }
+
+       return ECORE_SUCCESS;
+}
+
+/******************************* NIG LLH - End ********************************/
+
 /* Configurable */
 #define ECORE_MIN_DPIS         (4)     /* The minimal num of DPIs required to
                                         * load the driver. The number was
@@ -476,6 +1659,8 @@ void ecore_resc_free(struct ecore_dev *p_dev)
 
        OSAL_FREE(p_dev, p_dev->reset_stats);
 
+       ecore_llh_free(p_dev);
+
        for_each_hwfn(p_dev, i) {
                struct ecore_hwfn *p_hwfn = &p_dev->hwfns[i];
 
@@ -1349,6 +2534,13 @@ enum _ecore_status_t ecore_resc_alloc(struct ecore_dev *p_dev)
                }
        } /* hwfn loop */
 
+       rc = ecore_llh_alloc(p_dev);
+       if (rc != ECORE_SUCCESS) {
+               DP_NOTICE(p_dev, true,
+                         "Failed to allocate memory for the llh_info structure\n");
+               goto alloc_err;
+       }
+
        p_dev->reset_stats = OSAL_ZALLOC(p_dev, GFP_KERNEL,
                                         sizeof(*p_dev->reset_stats));
        if (!p_dev->reset_stats) {
@@ -1489,8 +2681,7 @@ static enum _ecore_status_t ecore_calc_hw_mode(struct ecore_hwfn *p_hwfn)
                return ECORE_INVAL;
        }
 
-       if (OSAL_TEST_BIT(ECORE_MF_OVLAN_CLSS,
-                         &p_hwfn->p_dev->mf_bits))
+       if (OSAL_TEST_BIT(ECORE_MF_OVLAN_CLSS, &p_hwfn->p_dev->mf_bits))
                hw_mode |= 1 << MODE_MF_SD;
        else
                hw_mode |= 1 << MODE_MF_SI;
@@ -2094,17 +3285,7 @@ static enum _ecore_status_t ecore_hw_init_port(struct ecore_hwfn *p_hwfn,
                                               struct ecore_ptt *p_ptt,
                                               int hw_mode)
 {
-       u32 ppf_to_eng_sel[NIG_REG_PPF_TO_ENGINE_SEL_RT_SIZE];
-       u32 val;
        enum _ecore_status_t rc = ECORE_SUCCESS;
-       u8 i;
-
-       /* In CMT for non-RoCE packets - use connection based classification */
-       val = ECORE_IS_CMT(p_hwfn->p_dev) ? 0x8 : 0x0;
-       for (i = 0; i < NIG_REG_PPF_TO_ENGINE_SEL_RT_SIZE; i++)
-               ppf_to_eng_sel[i] = val;
-       STORE_RT_REG_AGG(p_hwfn, NIG_REG_PPF_TO_ENGINE_SEL_RT_OFFSET,
-                        ppf_to_eng_sel);
 
        /* In CMT the gate should be cleared by the 2nd hwfn */
        if (!ECORE_IS_CMT(p_hwfn->p_dev) || !IS_LEAD_HWFN(p_hwfn))
@@ -2156,12 +3337,8 @@ static enum _ecore_status_t ecore_hw_init_port(struct ecore_hwfn *p_hwfn,
 }
 
 static enum _ecore_status_t
-ecore_hw_init_pf(struct ecore_hwfn *p_hwfn,
-                struct ecore_ptt *p_ptt,
-                struct ecore_tunnel_info *p_tunn,
-                int hw_mode,
-                bool b_hw_start,
-                enum ecore_int_mode int_mode, bool allow_npar_tx_switch)
+ecore_hw_init_pf(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
+                int hw_mode, struct ecore_hw_init_params *p_params)
 {
        u8 rel_pf_id = p_hwfn->rel_pf_id;
        u32 prs_reg;
@@ -2249,17 +3426,18 @@ ecore_hw_init_pf(struct ecore_hwfn *p_hwfn,
        */
 
        rc = ecore_hw_init_pf_doorbell_bar(p_hwfn, p_ptt);
-       if (rc)
+       if (rc != ECORE_SUCCESS)
                return rc;
-       if (b_hw_start) {
+
+       if (p_params->b_hw_start) {
                /* enable interrupts */
-               rc = ecore_int_igu_enable(p_hwfn, p_ptt, int_mode);
+               rc = ecore_int_igu_enable(p_hwfn, p_ptt, p_params->int_mode);
                if (rc != ECORE_SUCCESS)
                        return rc;
 
                /* send function start command */
-               rc = ecore_sp_pf_start(p_hwfn, p_ptt, p_tunn,
-                                      allow_npar_tx_switch);
+               rc = ecore_sp_pf_start(p_hwfn, p_ptt, p_params->p_tunn,
+                                      p_params->allow_npar_tx_switch);
                if (rc) {
                        DP_NOTICE(p_hwfn, true,
                                  "Function start ramrod failed\n");
@@ -2583,11 +3761,8 @@ enum _ecore_status_t ecore_hw_init(struct ecore_dev *p_dev,
                        /* Fall into */
                case FW_MSG_CODE_DRV_LOAD_FUNCTION:
                        rc = ecore_hw_init_pf(p_hwfn, p_hwfn->p_main_ptt,
-                                             p_params->p_tunn,
                                              p_hwfn->hw_info.hw_mode,
-                                             p_params->b_hw_start,
-                                             p_params->int_mode,
-                                             p_params->allow_npar_tx_switch);
+                                             p_params);
                        break;
                default:
                        DP_NOTICE(p_hwfn, false,
@@ -2859,6 +4034,12 @@ enum _ecore_status_t ecore_hw_stop(struct ecore_dev *p_dev)
                /* Need to wait 1ms to guarantee SBs are cleared */
                OSAL_MSLEEP(1);
 
+               if (IS_LEAD_HWFN(p_hwfn) &&
+                   OSAL_TEST_BIT(ECORE_MF_LLH_MAC_CLSS, &p_dev->mf_bits) &&
+                   !ECORE_IS_FCOE_PERSONALITY(p_hwfn))
+                       ecore_llh_remove_mac_filter(p_dev, 0,
+                                                  p_hwfn->hw_info.hw_mac_addr);
+
                if (!p_dev->recov_in_prog) {
                        ecore_verify_reg_val(p_hwfn, p_ptt,
                                             QM_REG_USG_CNT_PF_TX, 0);
@@ -3372,6 +4553,59 @@ static enum _ecore_status_t ecore_hw_set_resc_info(struct ecore_hwfn *p_hwfn,
        return ECORE_SUCCESS;
 }
 
+#define ECORE_NONUSED_PPFID_MASK_BB_4P_LO_PORTS        0xaa
+#define ECORE_NONUSED_PPFID_MASK_BB_4P_HI_PORTS        0x55
+#define ECORE_NONUSED_PPFID_MASK_AH_4P         0xf0
+
+static enum _ecore_status_t ecore_hw_get_ppfid_bitmap(struct ecore_hwfn *p_hwfn,
+                                                     struct ecore_ptt *p_ptt)
+{
+       u8 native_ppfid_idx = ECORE_PPFID_BY_PFID(p_hwfn), new_bitmap;
+       struct ecore_dev *p_dev = p_hwfn->p_dev;
+       enum _ecore_status_t rc;
+
+       rc = ecore_mcp_get_ppfid_bitmap(p_hwfn, p_ptt);
+       if (rc != ECORE_SUCCESS && rc != ECORE_NOTIMPL)
+               return rc;
+       else if (rc == ECORE_NOTIMPL)
+               p_dev->ppfid_bitmap = 0x1 << native_ppfid_idx;
+
+       /* 4-ports mode has limitations that should be enforced:
+        * - BB: the MFW can access only PPFIDs which their corresponding PFIDs
+        *       belong to this certain port.
+        * - AH/E5: only 4 PPFIDs per port are available.
+        */
+       if (ecore_device_num_ports(p_dev) == 4) {
+               u8 mask;
+
+               if (ECORE_IS_BB(p_dev))
+                       mask = MFW_PORT(p_hwfn) > 1 ?
+                              ECORE_NONUSED_PPFID_MASK_BB_4P_HI_PORTS :
+                              ECORE_NONUSED_PPFID_MASK_BB_4P_LO_PORTS;
+               else
+                       mask = ECORE_NONUSED_PPFID_MASK_AH_4P;
+
+               if (p_dev->ppfid_bitmap & mask) {
+                       new_bitmap = p_dev->ppfid_bitmap & ~mask;
+                       DP_INFO(p_hwfn,
+                               "Fix the PPFID bitmap for 4-ports mode: 0x%hhx -> 0x%hhx\n",
+                               p_dev->ppfid_bitmap, new_bitmap);
+                       p_dev->ppfid_bitmap = new_bitmap;
+               }
+       }
+
+       /* The native PPFID is expected to be part of the allocated bitmap */
+       if (!(p_dev->ppfid_bitmap & (0x1 << native_ppfid_idx))) {
+               new_bitmap = 0x1 << native_ppfid_idx;
+               DP_INFO(p_hwfn,
+                       "Fix the PPFID bitmap to inculde the native PPFID: %hhd -> 0x%hhx\n",
+                       p_dev->ppfid_bitmap, new_bitmap);
+               p_dev->ppfid_bitmap = new_bitmap;
+       }
+
+       return ECORE_SUCCESS;
+}
+
 static enum _ecore_status_t ecore_hw_get_resc(struct ecore_hwfn *p_hwfn,
                                              struct ecore_ptt *p_ptt,
                                              bool drv_resc_alloc)
@@ -3446,6 +4680,13 @@ static enum _ecore_status_t ecore_hw_get_resc(struct ecore_hwfn *p_hwfn,
                                "Failed to release the resource lock for the resource allocation commands\n");
        }
 
+       /* PPFID bitmap */
+       if (IS_LEAD_HWFN(p_hwfn)) {
+               rc = ecore_hw_get_ppfid_bitmap(p_hwfn, p_ptt);
+               if (rc != ECORE_SUCCESS)
+                       return rc;
+       }
+
 #ifndef ASIC_ONLY
        if (CHIP_REV_IS_SLOW(p_hwfn->p_dev)) {
                /* Reduced build contains less PQs */
@@ -4236,9 +5477,8 @@ void ecore_prepare_hibernate(struct ecore_dev *p_dev)
 #endif
 
 static enum _ecore_status_t
-ecore_hw_prepare_single(struct ecore_hwfn *p_hwfn,
-                       void OSAL_IOMEM * p_regview,
-                       void OSAL_IOMEM * p_doorbells,
+ecore_hw_prepare_single(struct ecore_hwfn *p_hwfn, void OSAL_IOMEM *p_regview,
+                       void OSAL_IOMEM *p_doorbells, u64 db_phys_addr,
                        struct ecore_hw_prepare_params *p_params)
 {
        struct ecore_mdump_retain_data mdump_retain;
@@ -4249,6 +5489,7 @@ ecore_hw_prepare_single(struct ecore_hwfn *p_hwfn,
        /* Split PCI bars evenly between hwfns */
        p_hwfn->regview = p_regview;
        p_hwfn->doorbells = p_doorbells;
+       p_hwfn->db_phys_addr = db_phys_addr;
 
        if (IS_VF(p_dev))
                return ecore_vf_hw_prepare(p_hwfn);
@@ -4401,9 +5642,9 @@ enum _ecore_status_t ecore_hw_prepare(struct ecore_dev *p_dev,
                ecore_init_iro_array(p_dev);
 
        /* Initialize the first hwfn - will learn number of hwfns */
-       rc = ecore_hw_prepare_single(p_hwfn,
-                                    p_dev->regview,
-                                    p_dev->doorbells, p_params);
+       rc = ecore_hw_prepare_single(p_hwfn, p_dev->regview,
+                                    p_dev->doorbells, p_dev->db_phys_addr,
+                                    p_params);
        if (rc != ECORE_SUCCESS)
                return rc;
 
@@ -4413,24 +5654,26 @@ enum _ecore_status_t ecore_hw_prepare(struct ecore_dev *p_dev,
        if (ECORE_IS_CMT(p_dev)) {
                void OSAL_IOMEM *p_regview, *p_doorbell;
                u8 OSAL_IOMEM *addr;
+               u64 db_phys_addr;
+               u32 offset;
 
                /* adjust bar offset for second engine */
-               addr = (u8 OSAL_IOMEM *)p_dev->regview +
-                                       ecore_hw_bar_size(p_hwfn,
-                                                         p_hwfn->p_main_ptt,
-                                                         BAR_ID_0) / 2;
+               offset = ecore_hw_bar_size(p_hwfn, p_hwfn->p_main_ptt,
+                                          BAR_ID_0) / 2;
+               addr = (u8 OSAL_IOMEM *)p_dev->regview + offset;
                p_regview = (void OSAL_IOMEM *)addr;
 
-               addr = (u8 OSAL_IOMEM *)p_dev->doorbells +
-                                       ecore_hw_bar_size(p_hwfn,
-                                                         p_hwfn->p_main_ptt,
-                                                         BAR_ID_1) / 2;
+               offset = ecore_hw_bar_size(p_hwfn, p_hwfn->p_main_ptt,
+                                          BAR_ID_1) / 2;
+               addr = (u8 OSAL_IOMEM *)p_dev->doorbells + offset;
                p_doorbell = (void OSAL_IOMEM *)addr;
+               db_phys_addr = p_dev->db_phys_addr + offset;
 
                p_dev->hwfns[1].b_en_pacing = p_params->b_en_pacing;
                /* prepare second hw function */
                rc = ecore_hw_prepare_single(&p_dev->hwfns[1], p_regview,
-                                            p_doorbell, p_params);
+                                            p_doorbell, db_phys_addr,
+                                            p_params);
 
                /* in case of error, need to free the previously
                 * initiliazed hwfn 0.
@@ -4827,419 +6070,6 @@ enum _ecore_status_t ecore_fw_rss_eng(struct ecore_hwfn *p_hwfn,
        return ECORE_SUCCESS;
 }
 
-static enum _ecore_status_t
-ecore_llh_add_mac_filter_bb_ah(struct ecore_hwfn *p_hwfn,
-                              struct ecore_ptt *p_ptt, u32 high, u32 low,
-                              u32 *p_entry_num)
-{
-       u32 en;
-       int i;
-
-       /* Find a free entry and utilize it */
-       for (i = 0; i < NIG_REG_LLH_FUNC_FILTER_EN_SIZE; i++) {
-               en = ecore_rd(p_hwfn, p_ptt,
-                             NIG_REG_LLH_FUNC_FILTER_EN_BB_K2 +
-                             i * sizeof(u32));
-               if (en)
-                       continue;
-               ecore_wr(p_hwfn, p_ptt,
-                        NIG_REG_LLH_FUNC_FILTER_VALUE_BB_K2 +
-                        2 * i * sizeof(u32), low);
-               ecore_wr(p_hwfn, p_ptt,
-                        NIG_REG_LLH_FUNC_FILTER_VALUE_BB_K2 +
-                        (2 * i + 1) * sizeof(u32), high);
-               ecore_wr(p_hwfn, p_ptt,
-                        NIG_REG_LLH_FUNC_FILTER_MODE_BB_K2 +
-                        i * sizeof(u32), 0);
-               ecore_wr(p_hwfn, p_ptt,
-                        NIG_REG_LLH_FUNC_FILTER_PROTOCOL_TYPE_BB_K2 +
-                        i * sizeof(u32), 0);
-               ecore_wr(p_hwfn, p_ptt,
-                        NIG_REG_LLH_FUNC_FILTER_EN_BB_K2 +
-                        i * sizeof(u32), 1);
-               break;
-       }
-
-       if (i >= NIG_REG_LLH_FUNC_FILTER_EN_SIZE)
-               return ECORE_NORESOURCES;
-
-       *p_entry_num = i;
-
-       return ECORE_SUCCESS;
-}
-
-enum _ecore_status_t ecore_llh_add_mac_filter(struct ecore_hwfn *p_hwfn,
-                                         struct ecore_ptt *p_ptt, u8 *p_filter)
-{
-       u32 high, low, entry_num;
-       enum _ecore_status_t rc = ECORE_SUCCESS;
-
-       if (!OSAL_TEST_BIT(ECORE_MF_LLH_MAC_CLSS,
-                          &p_hwfn->p_dev->mf_bits))
-               return ECORE_SUCCESS;
-
-       high = p_filter[1] | (p_filter[0] << 8);
-       low = p_filter[5] | (p_filter[4] << 8) |
-             (p_filter[3] << 16) | (p_filter[2] << 24);
-
-       if (ECORE_IS_BB(p_hwfn->p_dev) || ECORE_IS_AH(p_hwfn->p_dev))
-               rc = ecore_llh_add_mac_filter_bb_ah(p_hwfn, p_ptt, high, low,
-                                                   &entry_num);
-       if (rc != ECORE_SUCCESS) {
-               DP_NOTICE(p_hwfn, false,
-                         "Failed to find an empty LLH filter to utilize\n");
-               return rc;
-       }
-
-       DP_VERBOSE(p_hwfn, ECORE_MSG_HW,
-                  "MAC: %02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx is added at %d\n",
-                  p_filter[0], p_filter[1], p_filter[2], p_filter[3],
-                  p_filter[4], p_filter[5], entry_num);
-
-       return rc;
-}
-
-static enum _ecore_status_t
-ecore_llh_remove_mac_filter_bb_ah(struct ecore_hwfn *p_hwfn,
-                                 struct ecore_ptt *p_ptt, u32 high, u32 low,
-                                 u32 *p_entry_num)
-{
-       int i;
-
-       /* Find the entry and clean it */
-       for (i = 0; i < NIG_REG_LLH_FUNC_FILTER_EN_SIZE; i++) {
-               if (ecore_rd(p_hwfn, p_ptt,
-                            NIG_REG_LLH_FUNC_FILTER_VALUE_BB_K2 +
-                            2 * i * sizeof(u32)) != low)
-                       continue;
-               if (ecore_rd(p_hwfn, p_ptt,
-                            NIG_REG_LLH_FUNC_FILTER_VALUE_BB_K2 +
-                            (2 * i + 1) * sizeof(u32)) != high)
-                       continue;
-
-               ecore_wr(p_hwfn, p_ptt,
-                        NIG_REG_LLH_FUNC_FILTER_EN_BB_K2 + i * sizeof(u32), 0);
-               ecore_wr(p_hwfn, p_ptt,
-                        NIG_REG_LLH_FUNC_FILTER_VALUE_BB_K2 +
-                        2 * i * sizeof(u32), 0);
-               ecore_wr(p_hwfn, p_ptt,
-                        NIG_REG_LLH_FUNC_FILTER_VALUE_BB_K2 +
-                        (2 * i + 1) * sizeof(u32), 0);
-               break;
-       }
-
-       if (i >= NIG_REG_LLH_FUNC_FILTER_EN_SIZE)
-               return ECORE_INVAL;
-
-       *p_entry_num = i;
-
-       return ECORE_SUCCESS;
-}
-
-void ecore_llh_remove_mac_filter(struct ecore_hwfn *p_hwfn,
-                            struct ecore_ptt *p_ptt, u8 *p_filter)
-{
-       u32 high, low, entry_num;
-       enum _ecore_status_t rc = ECORE_SUCCESS;
-
-       if (!OSAL_TEST_BIT(ECORE_MF_LLH_MAC_CLSS,
-                          &p_hwfn->p_dev->mf_bits))
-               return;
-
-       high = p_filter[1] | (p_filter[0] << 8);
-       low = p_filter[5] | (p_filter[4] << 8) |
-             (p_filter[3] << 16) | (p_filter[2] << 24);
-
-       if (ECORE_IS_BB(p_hwfn->p_dev) || ECORE_IS_AH(p_hwfn->p_dev))
-               rc = ecore_llh_remove_mac_filter_bb_ah(p_hwfn, p_ptt, high,
-                                                      low, &entry_num);
-       if (rc != ECORE_SUCCESS) {
-               DP_NOTICE(p_hwfn, false,
-                         "Tried to remove a non-configured filter\n");
-               return;
-       }
-
-
-       DP_VERBOSE(p_hwfn, ECORE_MSG_HW,
-                  "MAC: %02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx was removed from %d\n",
-                  p_filter[0], p_filter[1], p_filter[2], p_filter[3],
-                  p_filter[4], p_filter[5], entry_num);
-}
-
-static enum _ecore_status_t
-ecore_llh_add_protocol_filter_bb_ah(struct ecore_hwfn *p_hwfn,
-                                   struct ecore_ptt *p_ptt,
-                                   enum ecore_llh_port_filter_type_t type,
-                                   u32 high, u32 low, u32 *p_entry_num)
-{
-       u32 en;
-       int i;
-
-       /* Find a free entry and utilize it */
-       for (i = 0; i < NIG_REG_LLH_FUNC_FILTER_EN_SIZE; i++) {
-               en = ecore_rd(p_hwfn, p_ptt,
-                             NIG_REG_LLH_FUNC_FILTER_EN_BB_K2 +
-                             i * sizeof(u32));
-               if (en)
-                       continue;
-               ecore_wr(p_hwfn, p_ptt,
-                        NIG_REG_LLH_FUNC_FILTER_VALUE_BB_K2 +
-                        2 * i * sizeof(u32), low);
-               ecore_wr(p_hwfn, p_ptt,
-                        NIG_REG_LLH_FUNC_FILTER_VALUE_BB_K2 +
-                        (2 * i + 1) * sizeof(u32), high);
-               ecore_wr(p_hwfn, p_ptt,
-                        NIG_REG_LLH_FUNC_FILTER_MODE_BB_K2 +
-                        i * sizeof(u32), 1);
-               ecore_wr(p_hwfn, p_ptt,
-                        NIG_REG_LLH_FUNC_FILTER_PROTOCOL_TYPE_BB_K2 +
-                        i * sizeof(u32), 1 << type);
-               ecore_wr(p_hwfn, p_ptt,
-                        NIG_REG_LLH_FUNC_FILTER_EN_BB_K2 + i * sizeof(u32), 1);
-               break;
-       }
-
-       if (i >= NIG_REG_LLH_FUNC_FILTER_EN_SIZE)
-               return ECORE_NORESOURCES;
-
-       *p_entry_num = i;
-
-       return ECORE_SUCCESS;
-}
-
-enum _ecore_status_t
-ecore_llh_add_protocol_filter(struct ecore_hwfn *p_hwfn,
-                             struct ecore_ptt *p_ptt,
-                             u16 source_port_or_eth_type,
-                             u16 dest_port,
-                             enum ecore_llh_port_filter_type_t type)
-{
-       u32 high, low, entry_num;
-       enum _ecore_status_t rc = ECORE_SUCCESS;
-
-       if (!OSAL_TEST_BIT(ECORE_MF_LLH_PROTO_CLSS,
-                          &p_hwfn->p_dev->mf_bits))
-               return rc;
-
-       high = 0;
-       low = 0;
-
-       switch (type) {
-       case ECORE_LLH_FILTER_ETHERTYPE:
-               high = source_port_or_eth_type;
-               break;
-       case ECORE_LLH_FILTER_TCP_SRC_PORT:
-       case ECORE_LLH_FILTER_UDP_SRC_PORT:
-               low = source_port_or_eth_type << 16;
-               break;
-       case ECORE_LLH_FILTER_TCP_DEST_PORT:
-       case ECORE_LLH_FILTER_UDP_DEST_PORT:
-               low = dest_port;
-               break;
-       case ECORE_LLH_FILTER_TCP_SRC_AND_DEST_PORT:
-       case ECORE_LLH_FILTER_UDP_SRC_AND_DEST_PORT:
-               low = (source_port_or_eth_type << 16) | dest_port;
-               break;
-       default:
-               DP_NOTICE(p_hwfn, true,
-                         "Non valid LLH protocol filter type %d\n", type);
-               return ECORE_INVAL;
-       }
-
-       if (ECORE_IS_BB(p_hwfn->p_dev) || ECORE_IS_AH(p_hwfn->p_dev))
-               rc = ecore_llh_add_protocol_filter_bb_ah(p_hwfn, p_ptt, type,
-                                                        high, low, &entry_num);
-       if (rc != ECORE_SUCCESS) {
-               DP_NOTICE(p_hwfn, false,
-                         "Failed to find an empty LLH filter to utilize\n");
-               return rc;
-       }
-       switch (type) {
-       case ECORE_LLH_FILTER_ETHERTYPE:
-               DP_VERBOSE(p_hwfn, ECORE_MSG_HW,
-                          "ETH type %x is added at %d\n",
-                          source_port_or_eth_type, entry_num);
-               break;
-       case ECORE_LLH_FILTER_TCP_SRC_PORT:
-               DP_VERBOSE(p_hwfn, ECORE_MSG_HW,
-                          "TCP src port %x is added at %d\n",
-                          source_port_or_eth_type, entry_num);
-               break;
-       case ECORE_LLH_FILTER_UDP_SRC_PORT:
-               DP_VERBOSE(p_hwfn, ECORE_MSG_HW,
-                          "UDP src port %x is added at %d\n",
-                          source_port_or_eth_type, entry_num);
-               break;
-       case ECORE_LLH_FILTER_TCP_DEST_PORT:
-               DP_VERBOSE(p_hwfn, ECORE_MSG_HW,
-                          "TCP dst port %x is added at %d\n", dest_port,
-                          entry_num);
-               break;
-       case ECORE_LLH_FILTER_UDP_DEST_PORT:
-               DP_VERBOSE(p_hwfn, ECORE_MSG_HW,
-                          "UDP dst port %x is added at %d\n", dest_port,
-                          entry_num);
-               break;
-       case ECORE_LLH_FILTER_TCP_SRC_AND_DEST_PORT:
-               DP_VERBOSE(p_hwfn, ECORE_MSG_HW,
-                          "TCP src/dst ports %x/%x are added at %d\n",
-                          source_port_or_eth_type, dest_port, entry_num);
-               break;
-       case ECORE_LLH_FILTER_UDP_SRC_AND_DEST_PORT:
-               DP_VERBOSE(p_hwfn, ECORE_MSG_HW,
-                          "UDP src/dst ports %x/%x are added at %d\n",
-                          source_port_or_eth_type, dest_port, entry_num);
-               break;
-       }
-
-       return rc;
-}
-
-static enum _ecore_status_t
-ecore_llh_remove_protocol_filter_bb_ah(struct ecore_hwfn *p_hwfn,
-                                      struct ecore_ptt *p_ptt,
-                                      enum ecore_llh_port_filter_type_t type,
-                                      u32 high, u32 low, u32 *p_entry_num)
-{
-       int i;
-
-       /* Find the entry and clean it */
-       for (i = 0; i < NIG_REG_LLH_FUNC_FILTER_EN_SIZE; i++) {
-               if (!ecore_rd(p_hwfn, p_ptt,
-                             NIG_REG_LLH_FUNC_FILTER_EN_BB_K2 +
-                             i * sizeof(u32)))
-                       continue;
-               if (!ecore_rd(p_hwfn, p_ptt,
-                             NIG_REG_LLH_FUNC_FILTER_MODE_BB_K2 +
-                             i * sizeof(u32)))
-                       continue;
-               if (!(ecore_rd(p_hwfn, p_ptt,
-                              NIG_REG_LLH_FUNC_FILTER_PROTOCOL_TYPE_BB_K2 +
-                              i * sizeof(u32)) & (1 << type)))
-                       continue;
-               if (ecore_rd(p_hwfn, p_ptt,
-                            NIG_REG_LLH_FUNC_FILTER_VALUE_BB_K2 +
-                            2 * i * sizeof(u32)) != low)
-                       continue;
-               if (ecore_rd(p_hwfn, p_ptt,
-                            NIG_REG_LLH_FUNC_FILTER_VALUE_BB_K2 +
-                            (2 * i + 1) * sizeof(u32)) != high)
-                       continue;
-
-               ecore_wr(p_hwfn, p_ptt,
-                        NIG_REG_LLH_FUNC_FILTER_EN_BB_K2 + i * sizeof(u32), 0);
-               ecore_wr(p_hwfn, p_ptt,
-                        NIG_REG_LLH_FUNC_FILTER_MODE_BB_K2 +
-                        i * sizeof(u32), 0);
-               ecore_wr(p_hwfn, p_ptt,
-                        NIG_REG_LLH_FUNC_FILTER_PROTOCOL_TYPE_BB_K2 +
-                        i * sizeof(u32), 0);
-               ecore_wr(p_hwfn, p_ptt,
-                        NIG_REG_LLH_FUNC_FILTER_VALUE_BB_K2 +
-                        2 * i * sizeof(u32), 0);
-               ecore_wr(p_hwfn, p_ptt,
-                        NIG_REG_LLH_FUNC_FILTER_VALUE_BB_K2 +
-                        (2 * i + 1) * sizeof(u32), 0);
-               break;
-       }
-
-       if (i >= NIG_REG_LLH_FUNC_FILTER_EN_SIZE)
-               return ECORE_INVAL;
-
-       *p_entry_num = i;
-
-       return ECORE_SUCCESS;
-}
-
-void
-ecore_llh_remove_protocol_filter(struct ecore_hwfn *p_hwfn,
-                                struct ecore_ptt *p_ptt,
-                                u16 source_port_or_eth_type,
-                                u16 dest_port,
-                                enum ecore_llh_port_filter_type_t type)
-{
-       u32 high, low, entry_num;
-       enum _ecore_status_t rc = ECORE_SUCCESS;
-
-       if (!OSAL_TEST_BIT(ECORE_MF_LLH_PROTO_CLSS,
-                          &p_hwfn->p_dev->mf_bits))
-               return;
-
-       high = 0;
-       low = 0;
-
-       switch (type) {
-       case ECORE_LLH_FILTER_ETHERTYPE:
-               high = source_port_or_eth_type;
-               break;
-       case ECORE_LLH_FILTER_TCP_SRC_PORT:
-       case ECORE_LLH_FILTER_UDP_SRC_PORT:
-               low = source_port_or_eth_type << 16;
-               break;
-       case ECORE_LLH_FILTER_TCP_DEST_PORT:
-       case ECORE_LLH_FILTER_UDP_DEST_PORT:
-               low = dest_port;
-               break;
-       case ECORE_LLH_FILTER_TCP_SRC_AND_DEST_PORT:
-       case ECORE_LLH_FILTER_UDP_SRC_AND_DEST_PORT:
-               low = (source_port_or_eth_type << 16) | dest_port;
-               break;
-       default:
-               DP_NOTICE(p_hwfn, true,
-                         "Non valid LLH protocol filter type %d\n", type);
-               return;
-       }
-
-       if (ECORE_IS_BB(p_hwfn->p_dev) || ECORE_IS_AH(p_hwfn->p_dev))
-               rc = ecore_llh_remove_protocol_filter_bb_ah(p_hwfn, p_ptt, type,
-                                                           high, low,
-                                                           &entry_num);
-       if (rc != ECORE_SUCCESS) {
-               DP_NOTICE(p_hwfn, false,
-                         "Tried to remove a non-configured filter [type %d, source_port_or_eth_type 0x%x, dest_port 0x%x]\n",
-                         type, source_port_or_eth_type, dest_port);
-               return;
-       }
-
-       DP_VERBOSE(p_hwfn, ECORE_MSG_HW,
-                  "Protocol filter [type %d, source_port_or_eth_type 0x%x, dest_port 0x%x] was removed from %d\n",
-                  type, source_port_or_eth_type, dest_port, entry_num);
-}
-
-static void ecore_llh_clear_all_filters_bb_ah(struct ecore_hwfn *p_hwfn,
-                                             struct ecore_ptt *p_ptt)
-{
-       int i;
-
-       if (!(IS_MF_SI(p_hwfn) || IS_MF_DEFAULT(p_hwfn)))
-               return;
-
-       for (i = 0; i < NIG_REG_LLH_FUNC_FILTER_EN_SIZE; i++) {
-               ecore_wr(p_hwfn, p_ptt,
-                        NIG_REG_LLH_FUNC_FILTER_EN_BB_K2  +
-                        i * sizeof(u32), 0);
-               ecore_wr(p_hwfn, p_ptt,
-                        NIG_REG_LLH_FUNC_FILTER_VALUE_BB_K2 +
-                        2 * i * sizeof(u32), 0);
-               ecore_wr(p_hwfn, p_ptt,
-                        NIG_REG_LLH_FUNC_FILTER_VALUE_BB_K2 +
-                        (2 * i + 1) * sizeof(u32), 0);
-       }
-}
-
-void ecore_llh_clear_all_filters(struct ecore_hwfn *p_hwfn,
-                            struct ecore_ptt *p_ptt)
-{
-       if (!OSAL_TEST_BIT(ECORE_MF_LLH_PROTO_CLSS,
-                          &p_hwfn->p_dev->mf_bits) &&
-           !OSAL_TEST_BIT(ECORE_MF_LLH_MAC_CLSS,
-                          &p_hwfn->p_dev->mf_bits))
-               return;
-
-       if (ECORE_IS_BB(p_hwfn->p_dev) || ECORE_IS_AH(p_hwfn->p_dev))
-               ecore_llh_clear_all_filters_bb_ah(p_hwfn, p_ptt);
-}
-
 enum _ecore_status_t
 ecore_llh_set_function_as_default(struct ecore_hwfn *p_hwfn,
                                  struct ecore_ptt *p_ptt)
index ab80b52..7308063 100644 (file)
@@ -114,6 +114,9 @@ struct ecore_hw_init_params {
        /* Driver load parameters */
        struct ecore_drv_load_params *p_drv_load_params;
 
+       /* Avoid engine affinity for RoCE/storage in case of CMT mode */
+       bool avoid_eng_affin;
+
        /* SPQ block timeout in msec */
        u32 spq_timeout_ms;
 };
@@ -428,11 +431,17 @@ enum ecore_dmae_address_type_t {
 #define ECORE_DMAE_FLAG_VF_SRC         0x00000002
 #define ECORE_DMAE_FLAG_VF_DST         0x00000004
 #define ECORE_DMAE_FLAG_COMPLETION_DST 0x00000008
+#define ECORE_DMAE_FLAG_PORT           0x00000010
+#define ECORE_DMAE_FLAG_PF_SRC         0x00000020
+#define ECORE_DMAE_FLAG_PF_DST         0x00000040
 
 struct ecore_dmae_params {
        u32 flags; /* consists of ECORE_DMAE_FLAG_* values */
        u8 src_vfid;
        u8 dst_vfid;
+       u8 port_id;
+       u8 src_pfid;
+       u8 dst_pfid;
 };
 
 /**
@@ -444,7 +453,9 @@ struct ecore_dmae_params {
  * @param source_addr
  * @param grc_addr (dmae_data_offset)
  * @param size_in_dwords
- * @param flags (one of the flags defined above)
+ * @param p_params (default parameters will be used in case of OSAL_NULL)
+ *
+ * @return enum _ecore_status_t
  */
 enum _ecore_status_t
 ecore_dmae_host2grc(struct ecore_hwfn *p_hwfn,
@@ -452,7 +463,7 @@ ecore_dmae_host2grc(struct ecore_hwfn *p_hwfn,
                    u64 source_addr,
                    u32 grc_addr,
                    u32 size_in_dwords,
-                   u32 flags);
+                   struct ecore_dmae_params *p_params);
 
 /**
  * @brief ecore_dmae_grc2host - Read data from dmae data offset
@@ -462,7 +473,9 @@ ecore_dmae_host2grc(struct ecore_hwfn *p_hwfn,
  * @param grc_addr (dmae_data_offset)
  * @param dest_addr
  * @param size_in_dwords
- * @param flags - one of the flags defined above
+ * @param p_params (default parameters will be used in case of OSAL_NULL)
+ *
+ * @return enum _ecore_status_t
  */
 enum _ecore_status_t
 ecore_dmae_grc2host(struct ecore_hwfn *p_hwfn,
@@ -470,7 +483,7 @@ ecore_dmae_grc2host(struct ecore_hwfn *p_hwfn,
                    u32 grc_addr,
                    dma_addr_t dest_addr,
                    u32 size_in_dwords,
-                   u32 flags);
+                   struct ecore_dmae_params *p_params);
 
 /**
  * @brief ecore_dmae_host2host - copy data from to source address
@@ -481,7 +494,9 @@ ecore_dmae_grc2host(struct ecore_hwfn *p_hwfn,
  * @param source_addr
  * @param dest_addr
  * @param size_in_dwords
- * @param params
+ * @param p_params (default parameters will be used in case of OSAL_NULL)
+ *
+ * @return enum _ecore_status_t
  */
 enum _ecore_status_t
 ecore_dmae_host2host(struct ecore_hwfn *p_hwfn,
@@ -562,28 +577,79 @@ enum _ecore_status_t ecore_fw_rss_eng(struct ecore_hwfn *p_hwfn,
                                      u8 *dst_id);
 
 /**
- * @brief ecore_llh_add_mac_filter - configures a MAC filter in llh
+ * @brief ecore_llh_get_num_ppfid - Return the allocated number of LLH filter
+ *     banks that are allocated to the PF.
  *
- * @param p_hwfn
- * @param p_ptt
- * @param p_filter - MAC to add
+ * @param p_dev
+ *
+ * @return u8 - Number of LLH filter banks
  */
-enum _ecore_status_t ecore_llh_add_mac_filter(struct ecore_hwfn *p_hwfn,
-                                         struct ecore_ptt *p_ptt,
-                                         u8 *p_filter);
+u8 ecore_llh_get_num_ppfid(struct ecore_dev *p_dev);
+
+enum ecore_eng {
+       ECORE_ENG0,
+       ECORE_ENG1,
+       ECORE_BOTH_ENG,
+};
 
 /**
- * @brief ecore_llh_remove_mac_filter - removes a MAC filtre from llh
+ * @brief ecore_llh_get_l2_affinity_hint - Return the hint for the L2 affinity
  *
- * @param p_hwfn
- * @param p_ptt
- * @param p_filter - MAC to remove
+ * @param p_dev
+ *
+ * @return enum ecore_eng - L2 affintiy hint
+ */
+enum ecore_eng ecore_llh_get_l2_affinity_hint(struct ecore_dev *p_dev);
+
+/**
+ * @brief ecore_llh_set_ppfid_affinity - Set the engine affinity for the given
+ *     LLH filter bank.
+ *
+ * @param p_dev
+ * @param ppfid - relative within the allocated ppfids ('0' is the default one).
+ * @param eng
+ *
+ * @return enum _ecore_status_t
  */
-void ecore_llh_remove_mac_filter(struct ecore_hwfn *p_hwfn,
-                            struct ecore_ptt *p_ptt,
-                            u8 *p_filter);
+enum _ecore_status_t ecore_llh_set_ppfid_affinity(struct ecore_dev *p_dev,
+                                                 u8 ppfid, enum ecore_eng eng);
 
-enum ecore_llh_port_filter_type_t {
+/**
+ * @brief ecore_llh_set_roce_affinity - Set the RoCE engine affinity
+ *
+ * @param p_dev
+ * @param eng
+ *
+ * @return enum _ecore_status_t
+ */
+enum _ecore_status_t ecore_llh_set_roce_affinity(struct ecore_dev *p_dev,
+                                                enum ecore_eng eng);
+
+/**
+ * @brief ecore_llh_add_mac_filter - Add a LLH MAC filter into the given filter
+ *     bank.
+ *
+ * @param p_dev
+ * @param ppfid - relative within the allocated ppfids ('0' is the default one).
+ * @param mac_addr - MAC to add
+ *
+ * @return enum _ecore_status_t
+ */
+enum _ecore_status_t ecore_llh_add_mac_filter(struct ecore_dev *p_dev, u8 ppfid,
+                                             u8 mac_addr[ETH_ALEN]);
+
+/**
+ * @brief ecore_llh_remove_mac_filter - Remove a LLH MAC filter from the given
+ *     filter bank.
+ *
+ * @param p_dev
+ * @param ppfid - relative within the allocated ppfids ('0' is the default one).
+ * @param mac_addr - MAC to remove
+ */
+void ecore_llh_remove_mac_filter(struct ecore_dev *p_dev, u8 ppfid,
+                                u8 mac_addr[ETH_ALEN]);
+
+enum ecore_llh_prot_filter_type_t {
        ECORE_LLH_FILTER_ETHERTYPE,
        ECORE_LLH_FILTER_TCP_SRC_PORT,
        ECORE_LLH_FILTER_TCP_DEST_PORT,
@@ -594,45 +660,52 @@ enum ecore_llh_port_filter_type_t {
 };
 
 /**
- * @brief ecore_llh_add_protocol_filter - configures a protocol filter in llh
+ * @brief ecore_llh_add_protocol_filter - Add a LLH protocol filter into the
+ *     given filter bank.
  *
- * @param p_hwfn
- * @param p_ptt
+ * @param p_dev
+ * @param ppfid - relative within the allocated ppfids ('0' is the default one).
+ * @param type - type of filters and comparing
  * @param source_port_or_eth_type - source port or ethertype to add
  * @param dest_port - destination port to add
- * @param type - type of filters and comparing
+ *
+ * @return enum _ecore_status_t
  */
 enum _ecore_status_t
-ecore_llh_add_protocol_filter(struct ecore_hwfn *p_hwfn,
-                             struct ecore_ptt *p_ptt,
-                             u16 source_port_or_eth_type,
-                             u16 dest_port,
-                             enum ecore_llh_port_filter_type_t type);
+ecore_llh_add_protocol_filter(struct ecore_dev *p_dev, u8 ppfid,
+                             enum ecore_llh_prot_filter_type_t type,
+                             u16 source_port_or_eth_type, u16 dest_port);
 
 /**
- * @brief ecore_llh_remove_protocol_filter - remove a protocol filter in llh
+ * @brief ecore_llh_remove_protocol_filter - Remove a LLH protocol filter from
+ *     the given filter bank.
  *
- * @param p_hwfn
- * @param p_ptt
+ * @param p_dev
+ * @param ppfid - relative within the allocated ppfids ('0' is the default one).
+ * @param type - type of filters and comparing
  * @param source_port_or_eth_type - source port or ethertype to add
  * @param dest_port - destination port to add
- * @param type - type of filters and comparing
  */
-void
-ecore_llh_remove_protocol_filter(struct ecore_hwfn *p_hwfn,
-                                struct ecore_ptt *p_ptt,
-                                u16 source_port_or_eth_type,
-                                u16 dest_port,
-                                enum ecore_llh_port_filter_type_t type);
+void ecore_llh_remove_protocol_filter(struct ecore_dev *p_dev, u8 ppfid,
+                                     enum ecore_llh_prot_filter_type_t type,
+                                     u16 source_port_or_eth_type,
+                                     u16 dest_port);
 
 /**
- * @brief ecore_llh_clear_all_filters - removes all MAC filters from llh
+ * @brief ecore_llh_clear_ppfid_filters - Remove all LLH filters from the given
+ *     filter bank.
  *
- * @param p_hwfn
- * @param p_ptt
+ * @param p_dev
+ * @param ppfid - relative within the allocated ppfids ('0' is the default one).
+ */
+void ecore_llh_clear_ppfid_filters(struct ecore_dev *p_dev, u8 ppfid);
+
+/**
+ * @brief ecore_llh_clear_all_filters - Remove all LLH filters
+ *
+ * @param p_dev
  */
-void ecore_llh_clear_all_filters(struct ecore_hwfn *p_hwfn,
-                            struct ecore_ptt *p_ptt);
+void ecore_llh_clear_all_filters(struct ecore_dev *p_dev);
 
 /**
  * @brief ecore_llh_set_function_as_default - set function as default per port
index 6cfbbab..72cd7e9 100644 (file)
@@ -450,14 +450,17 @@ u32 ecore_vfid_to_concrete(struct ecore_hwfn *p_hwfn, u8 vfid)
  * If this changes, this needs to be revisted.
  */
 
-/* Ecore DMAE
- * =============
- */
+/* DMAE */
+
+#define ECORE_DMAE_FLAGS_IS_SET(params, flag)  \
+       ((params) != OSAL_NULL && ((params)->flags & ECORE_DMAE_FLAG_##flag))
+
 static void ecore_dmae_opcode(struct ecore_hwfn *p_hwfn,
                              const u8 is_src_type_grc,
                              const u8 is_dst_type_grc,
                              struct ecore_dmae_params *p_params)
 {
+       u8 src_pfid, dst_pfid, port_id;
        u16 opcode_b = 0;
        u32 opcode = 0;
 
@@ -467,16 +470,20 @@ static void ecore_dmae_opcode(struct ecore_hwfn *p_hwfn,
         */
        opcode |= (is_src_type_grc ? DMAE_CMD_SRC_MASK_GRC
                   : DMAE_CMD_SRC_MASK_PCIE) << DMAE_CMD_SRC_SHIFT;
-       opcode |= (p_hwfn->rel_pf_id & DMAE_CMD_SRC_PF_ID_MASK) <<
-           DMAE_CMD_SRC_PF_ID_SHIFT;
+       src_pfid = ECORE_DMAE_FLAGS_IS_SET(p_params, PF_SRC) ?
+                  p_params->src_pfid : p_hwfn->rel_pf_id;
+       opcode |= (src_pfid & DMAE_CMD_SRC_PF_ID_MASK) <<
+                 DMAE_CMD_SRC_PF_ID_SHIFT;
 
        /* The destination of the DMA can be: 0-None 1-PCIe 2-GRC 3-None */
        opcode |= (is_dst_type_grc ? DMAE_CMD_DST_MASK_GRC
                   : DMAE_CMD_DST_MASK_PCIE) << DMAE_CMD_DST_SHIFT;
-       opcode |= (p_hwfn->rel_pf_id & DMAE_CMD_DST_PF_ID_MASK) <<
-           DMAE_CMD_DST_PF_ID_SHIFT;
+       dst_pfid = ECORE_DMAE_FLAGS_IS_SET(p_params, PF_DST) ?
+                  p_params->dst_pfid : p_hwfn->rel_pf_id;
+       opcode |= (dst_pfid & DMAE_CMD_DST_PF_ID_MASK) <<
+                 DMAE_CMD_DST_PF_ID_SHIFT;
 
-       /* DMAE_E4_TODO need to check which value to specifiy here. */
+       /* DMAE_E4_TODO need to check which value to specify here. */
        /* opcode |= (!b_complete_to_host)<< DMAE_CMD_C_DST_SHIFT; */
 
        /* Whether to write a completion word to the completion destination:
@@ -486,7 +493,7 @@ static void ecore_dmae_opcode(struct ecore_hwfn *p_hwfn,
        opcode |= DMAE_CMD_COMP_WORD_EN_MASK << DMAE_CMD_COMP_WORD_EN_SHIFT;
        opcode |= DMAE_CMD_SRC_ADDR_RESET_MASK << DMAE_CMD_SRC_ADDR_RESET_SHIFT;
 
-       if (p_params->flags & ECORE_DMAE_FLAG_COMPLETION_DST)
+       if (ECORE_DMAE_FLAGS_IS_SET(p_params, COMPLETION_DST))
                opcode |= 1 << DMAE_CMD_COMP_FUNC_SHIFT;
 
        /* swapping mode 3 - big endian there should be a define ifdefed in
@@ -494,7 +501,9 @@ static void ecore_dmae_opcode(struct ecore_hwfn *p_hwfn,
         */
        opcode |= DMAE_CMD_ENDIANITY << DMAE_CMD_ENDIANITY_MODE_SHIFT;
 
-       opcode |= p_hwfn->port_id << DMAE_CMD_PORT_ID_SHIFT;
+       port_id = (ECORE_DMAE_FLAGS_IS_SET(p_params, PORT)) ?
+                 p_params->port_id : p_hwfn->port_id;
+       opcode |= port_id << DMAE_CMD_PORT_ID_SHIFT;
 
        /* reset source address in next go */
        opcode |= DMAE_CMD_SRC_ADDR_RESET_MASK << DMAE_CMD_SRC_ADDR_RESET_SHIFT;
@@ -503,14 +512,14 @@ static void ecore_dmae_opcode(struct ecore_hwfn *p_hwfn,
        opcode |= DMAE_CMD_DST_ADDR_RESET_MASK << DMAE_CMD_DST_ADDR_RESET_SHIFT;
 
        /* SRC/DST VFID: all 1's - pf, otherwise VF id */
-       if (p_params->flags & ECORE_DMAE_FLAG_VF_SRC) {
+       if (ECORE_DMAE_FLAGS_IS_SET(p_params, VF_SRC)) {
                opcode |= (1 << DMAE_CMD_SRC_VF_ID_VALID_SHIFT);
                opcode_b |= (p_params->src_vfid << DMAE_CMD_SRC_VF_ID_SHIFT);
        } else {
                opcode_b |= (DMAE_CMD_SRC_VF_ID_MASK <<
                             DMAE_CMD_SRC_VF_ID_SHIFT);
        }
-       if (p_params->flags & ECORE_DMAE_FLAG_VF_DST) {
+       if (ECORE_DMAE_FLAGS_IS_SET(p_params, VF_DST)) {
                opcode |= 1 << DMAE_CMD_DST_VF_ID_VALID_SHIFT;
                opcode_b |= p_params->dst_vfid << DMAE_CMD_DST_VF_ID_SHIFT;
        } else {
@@ -855,7 +864,7 @@ ecore_dmae_execute_command(struct ecore_hwfn *p_hwfn,
        for (i = 0; i <= cnt_split; i++) {
                offset = length_limit * i;
 
-               if (!(p_params->flags & ECORE_DMAE_FLAG_RW_REPL_SRC)) {
+               if (!ECORE_DMAE_FLAGS_IS_SET(p_params, RW_REPL_SRC)) {
                        if (src_type == ECORE_DMAE_ADDRESS_GRC)
                                src_addr_split = src_addr + offset;
                        else
@@ -896,51 +905,45 @@ ecore_dmae_execute_command(struct ecore_hwfn *p_hwfn,
        return ecore_status;
 }
 
-enum _ecore_status_t
-ecore_dmae_host2grc(struct ecore_hwfn *p_hwfn,
-                   struct ecore_ptt *p_ptt,
-                   u64 source_addr,
-                   u32 grc_addr, u32 size_in_dwords, u32 flags)
+enum _ecore_status_t ecore_dmae_host2grc(struct ecore_hwfn *p_hwfn,
+                                        struct ecore_ptt *p_ptt,
+                                        u64 source_addr,
+                                        u32 grc_addr,
+                                        u32 size_in_dwords,
+                                        struct ecore_dmae_params *p_params)
 {
        u32 grc_addr_in_dw = grc_addr / sizeof(u32);
-       struct ecore_dmae_params params;
        enum _ecore_status_t rc;
 
-       OSAL_MEMSET(&params, 0, sizeof(struct ecore_dmae_params));
-       params.flags = flags;
-
        OSAL_SPIN_LOCK(&p_hwfn->dmae_info.lock);
 
        rc = ecore_dmae_execute_command(p_hwfn, p_ptt, source_addr,
                                        grc_addr_in_dw,
                                        ECORE_DMAE_ADDRESS_HOST_VIRT,
                                        ECORE_DMAE_ADDRESS_GRC,
-                                       size_in_dwords, &params);
+                                       size_in_dwords, p_params);
 
        OSAL_SPIN_UNLOCK(&p_hwfn->dmae_info.lock);
 
        return rc;
 }
 
-enum _ecore_status_t
-ecore_dmae_grc2host(struct ecore_hwfn *p_hwfn,
-                   struct ecore_ptt *p_ptt,
-                   u32 grc_addr,
-                   dma_addr_t dest_addr, u32 size_in_dwords, u32 flags)
+enum _ecore_status_t ecore_dmae_grc2host(struct ecore_hwfn *p_hwfn,
+                                        struct ecore_ptt *p_ptt,
+                                        u32 grc_addr,
+                                        dma_addr_t dest_addr,
+                                        u32 size_in_dwords,
+                                        struct ecore_dmae_params *p_params)
 {
        u32 grc_addr_in_dw = grc_addr / sizeof(u32);
-       struct ecore_dmae_params params;
        enum _ecore_status_t rc;
 
-       OSAL_MEMSET(&params, 0, sizeof(struct ecore_dmae_params));
-       params.flags = flags;
-
        OSAL_SPIN_LOCK(&p_hwfn->dmae_info.lock);
 
        rc = ecore_dmae_execute_command(p_hwfn, p_ptt, grc_addr_in_dw,
                                        dest_addr, ECORE_DMAE_ADDRESS_GRC,
                                        ECORE_DMAE_ADDRESS_HOST_VIRT,
-                                       size_in_dwords, &params);
+                                       size_in_dwords, p_params);
 
        OSAL_SPIN_UNLOCK(&p_hwfn->dmae_info.lock);
 
@@ -989,7 +992,6 @@ enum _ecore_status_t ecore_dmae_sanity(struct ecore_hwfn *p_hwfn,
                                       const char *phase)
 {
        u32 size = OSAL_PAGE_SIZE / 2, val;
-       struct ecore_dmae_params params;
        enum _ecore_status_t rc = ECORE_SUCCESS;
        dma_addr_t p_phys;
        void *p_virt;
@@ -1021,9 +1023,9 @@ enum _ecore_status_t ecore_dmae_sanity(struct ecore_hwfn *p_hwfn,
                   (unsigned long)(p_phys + size),
                   (u8 *)p_virt + size, size);
 
-       OSAL_MEMSET(&params, 0, sizeof(params));
        rc = ecore_dmae_host2host(p_hwfn, p_ptt, p_phys, p_phys + size,
-                                 size / 4 /* size_in_dwords */, &params);
+                                 size / 4 /* size_in_dwords */,
+                                 OSAL_NULL /* default parameters */);
        if (rc != ECORE_SUCCESS) {
                DP_NOTICE(p_hwfn, false,
                          "DMAE sanity [%s]: ecore_dmae_host2host() failed. rc = %d.\n",
@@ -1054,3 +1056,32 @@ out:
        OSAL_DMA_FREE_COHERENT(p_hwfn->p_dev, p_virt, p_phys, 2 * size);
        return rc;
 }
+
+void ecore_ppfid_wr(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
+                   u8 abs_ppfid, u32 hw_addr, u32 val)
+{
+       u8 pfid = ECORE_PFID_BY_PPFID(p_hwfn, abs_ppfid);
+
+       ecore_fid_pretend(p_hwfn, p_ptt,
+                         pfid << PXP_PRETEND_CONCRETE_FID_PFID_SHIFT);
+       ecore_wr(p_hwfn, p_ptt, hw_addr, val);
+       ecore_fid_pretend(p_hwfn, p_ptt,
+                         p_hwfn->rel_pf_id <<
+                         PXP_PRETEND_CONCRETE_FID_PFID_SHIFT);
+}
+
+u32 ecore_ppfid_rd(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
+                  u8 abs_ppfid, u32 hw_addr)
+{
+       u8 pfid = ECORE_PFID_BY_PPFID(p_hwfn, abs_ppfid);
+       u32 val;
+
+       ecore_fid_pretend(p_hwfn, p_ptt,
+                         pfid << PXP_PRETEND_CONCRETE_FID_PFID_SHIFT);
+       val = ecore_rd(p_hwfn, p_ptt, hw_addr);
+       ecore_fid_pretend(p_hwfn, p_ptt,
+                         p_hwfn->rel_pf_id <<
+                         PXP_PRETEND_CONCRETE_FID_PFID_SHIFT);
+
+       return val;
+}
index a62ba39..0b5b40c 100644 (file)
@@ -134,8 +134,8 @@ struct ecore_ptt *ecore_get_reserved_ptt(struct ecore_hwfn  *p_hwfn,
  *
  * @param p_hwfn
  * @param p_ptt
- * @param val
  * @param hw_addr
+ * @param val
  */
 void ecore_wr(struct ecore_hwfn        *p_hwfn,
              struct ecore_ptt  *p_ptt,
@@ -147,7 +147,6 @@ void ecore_wr(struct ecore_hwfn     *p_hwfn,
  *
  * @param p_hwfn
  * @param p_ptt
- * @param val
  * @param hw_addr
  */
 u32 ecore_rd(struct ecore_hwfn *p_hwfn,
@@ -269,4 +268,29 @@ enum _ecore_status_t ecore_dmae_sanity(struct ecore_hwfn *p_hwfn,
                                       struct ecore_ptt *p_ptt,
                                       const char *phase);
 
+/**
+ * @brief ecore_ppfid_wr - Write value to BAR using the given ptt while
+ *     pretending to a PF to which the given PPFID pertains.
+ *
+ * @param p_hwfn
+ * @param p_ptt
+ * @param abs_ppfid
+ * @param hw_addr
+ * @param val
+ */
+void ecore_ppfid_wr(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
+                   u8 abs_ppfid, u32 hw_addr, u32 val);
+
+/**
+ * @brief ecore_ppfid_rd - Read value from BAR using the given ptt while
+ *      pretending to a PF to which the given PPFID pertains.
+ *
+ * @param p_hwfn
+ * @param p_ptt
+ * @param abs_ppfid
+ * @param hw_addr
+ */
+u32 ecore_ppfid_rd(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
+                  u8 abs_ppfid, u32 hw_addr);
+
 #endif /* __ECORE_HW_H__ */
index b7636f3..47c1be2 100644 (file)
@@ -101,7 +101,8 @@ static enum _ecore_status_t ecore_init_rt(struct ecore_hwfn *p_hwfn,
 
                rc = ecore_dmae_host2grc(p_hwfn, p_ptt,
                                         (osal_uintptr_t)(p_init_val + i),
-                                        addr + (i << 2), segment, 0);
+                                        addr + (i << 2), segment,
+                                        OSAL_NULL /* default parameters */);
                if (rc != ECORE_SUCCESS)
                        return rc;
 
@@ -165,8 +166,9 @@ static enum _ecore_status_t ecore_init_array_dmae(struct ecore_hwfn *p_hwfn,
        } else {
                rc = ecore_dmae_host2grc(p_hwfn, p_ptt,
                                         (osal_uintptr_t)(p_buf +
-                                                          dmae_data_offset),
-                                        addr, size, 0);
+                                                         dmae_data_offset),
+                                        addr, size,
+                                        OSAL_NULL /* default parameters */);
        }
 
        return rc;
@@ -177,13 +179,15 @@ static enum _ecore_status_t ecore_init_fill_dmae(struct ecore_hwfn *p_hwfn,
                                                 u32 addr, u32 fill_count)
 {
        static u32 zero_buffer[DMAE_MAX_RW_SIZE];
+       struct ecore_dmae_params params;
 
        OSAL_MEMSET(zero_buffer, 0, sizeof(u32) * DMAE_MAX_RW_SIZE);
 
+       OSAL_MEMSET(&params, 0, sizeof(params));
+       params.flags = ECORE_DMAE_FLAG_RW_REPL_SRC;
        return ecore_dmae_host2grc(p_hwfn, p_ptt,
                                   (osal_uintptr_t)&zero_buffer[0],
-                                  addr, fill_count,
-                                  ECORE_DMAE_FLAG_RW_REPL_SRC);
+                                  addr, fill_count, &params);
 }
 
 static void ecore_init_fill(struct ecore_hwfn *p_hwfn,
index fd8f657..e48a7bc 100644 (file)
@@ -1561,11 +1561,13 @@ void ecore_int_cau_conf_sb(struct ecore_hwfn *p_hwfn,
                ecore_dmae_host2grc(p_hwfn, p_ptt,
                                    (u64)(osal_uintptr_t)&phys_addr,
                                    CAU_REG_SB_ADDR_MEMORY +
-                                   igu_sb_id * sizeof(u64), 2, 0);
+                                   igu_sb_id * sizeof(u64), 2,
+                                   OSAL_NULL /* default parameters */);
                ecore_dmae_host2grc(p_hwfn, p_ptt,
                                    (u64)(osal_uintptr_t)&sb_entry,
                                    CAU_REG_SB_VAR_MEMORY +
-                                   igu_sb_id * sizeof(u64), 2, 0);
+                                   igu_sb_id * sizeof(u64), 2,
+                                   OSAL_NULL /* default parameters */);
        } else {
                /* Initialize Status Block Address */
                STORE_RT_REG_AGG(p_hwfn,
@@ -2646,7 +2648,8 @@ enum _ecore_status_t ecore_int_set_timer_res(struct ecore_hwfn *p_hwfn,
 
        rc = ecore_dmae_grc2host(p_hwfn, p_ptt, CAU_REG_SB_VAR_MEMORY +
                                 sb_id * sizeof(u64),
-                                (u64)(osal_uintptr_t)&sb_entry, 2, 0);
+                                (u64)(osal_uintptr_t)&sb_entry, 2,
+                                OSAL_NULL /* default parameters */);
        if (rc != ECORE_SUCCESS) {
                DP_ERR(p_hwfn, "dmae_grc2host failed %d\n", rc);
                return rc;
@@ -2659,8 +2662,8 @@ enum _ecore_status_t ecore_int_set_timer_res(struct ecore_hwfn *p_hwfn,
 
        rc = ecore_dmae_host2grc(p_hwfn, p_ptt,
                                 (u64)(osal_uintptr_t)&sb_entry,
-                                CAU_REG_SB_VAR_MEMORY +
-                                sb_id * sizeof(u64), 2, 0);
+                                CAU_REG_SB_VAR_MEMORY + sb_id * sizeof(u64), 2,
+                                OSAL_NULL /* default parameters */);
        if (rc != ECORE_SUCCESS) {
                DP_ERR(p_hwfn, "dmae_host2grc failed %d\n", rc);
                return rc;
index c17082e..5a0905e 100644 (file)
@@ -2217,7 +2217,8 @@ int ecore_get_rxq_coalesce(struct ecore_hwfn *p_hwfn,
 
        rc = ecore_dmae_grc2host(p_hwfn, p_ptt, CAU_REG_SB_VAR_MEMORY +
                                 p_cid->sb_igu_id * sizeof(u64),
-                                (u64)(osal_uintptr_t)&sb_entry, 2, 0);
+                                (u64)(osal_uintptr_t)&sb_entry, 2,
+                                OSAL_NULL /* default parameters */);
        if (rc != ECORE_SUCCESS) {
                DP_ERR(p_hwfn, "dmae_grc2host failed %d\n", rc);
                return rc;
@@ -2251,7 +2252,8 @@ int ecore_get_txq_coalesce(struct ecore_hwfn *p_hwfn,
 
        rc = ecore_dmae_grc2host(p_hwfn, p_ptt, CAU_REG_SB_VAR_MEMORY +
                                 p_cid->sb_igu_id * sizeof(u64),
-                                (u64)(osal_uintptr_t)&sb_entry, 2, 0);
+                                (u64)(osal_uintptr_t)&sb_entry, 2,
+                                OSAL_NULL /* default parameters */);
        if (rc != ECORE_SUCCESS) {
                DP_ERR(p_hwfn, "dmae_grc2host failed %d\n", rc);
                return rc;
index 3811d27..202db13 100644 (file)
@@ -4144,6 +4144,75 @@ ecore_mcp_drv_attribute(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
        return ECORE_SUCCESS;
 }
 
+enum _ecore_status_t ecore_mcp_get_engine_config(struct ecore_hwfn *p_hwfn,
+                                                struct ecore_ptt *p_ptt)
+{
+       struct ecore_dev *p_dev = p_hwfn->p_dev;
+       struct ecore_mcp_mb_params mb_params;
+       u8 fir_valid, l2_valid;
+       enum _ecore_status_t rc;
+
+       OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
+       mb_params.cmd = DRV_MSG_CODE_GET_ENGINE_CONFIG;
+       rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
+       if (rc != ECORE_SUCCESS)
+               return rc;
+
+       if (mb_params.mcp_resp == FW_MSG_CODE_UNSUPPORTED) {
+               DP_INFO(p_hwfn,
+                       "The get_engine_config command is unsupported by the MFW\n");
+               return ECORE_NOTIMPL;
+       }
+
+       fir_valid = GET_MFW_FIELD(mb_params.mcp_param,
+                                 FW_MB_PARAM_ENG_CFG_FIR_AFFIN_VALID);
+       if (fir_valid)
+               p_dev->fir_affin =
+                       GET_MFW_FIELD(mb_params.mcp_param,
+                                     FW_MB_PARAM_ENG_CFG_FIR_AFFIN_VALUE);
+
+       l2_valid = GET_MFW_FIELD(mb_params.mcp_param,
+                                FW_MB_PARAM_ENG_CFG_L2_AFFIN_VALID);
+       if (l2_valid)
+               p_dev->l2_affin_hint =
+                       GET_MFW_FIELD(mb_params.mcp_param,
+                                     FW_MB_PARAM_ENG_CFG_L2_AFFIN_VALUE);
+
+       DP_INFO(p_hwfn,
+               "Engine affinity config: FIR={valid %hhd, value %hhd}, L2_hint={valid %hhd, value %hhd}\n",
+               fir_valid, p_dev->fir_affin, l2_valid, p_dev->l2_affin_hint);
+
+       return ECORE_SUCCESS;
+}
+
+enum _ecore_status_t ecore_mcp_get_ppfid_bitmap(struct ecore_hwfn *p_hwfn,
+                                               struct ecore_ptt *p_ptt)
+{
+       struct ecore_dev *p_dev = p_hwfn->p_dev;
+       struct ecore_mcp_mb_params mb_params;
+       enum _ecore_status_t rc;
+
+       OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
+       mb_params.cmd = DRV_MSG_CODE_GET_PPFID_BITMAP;
+       rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
+       if (rc != ECORE_SUCCESS)
+               return rc;
+
+       if (mb_params.mcp_resp == FW_MSG_CODE_UNSUPPORTED) {
+               DP_INFO(p_hwfn,
+                       "The get_ppfid_bitmap command is unsupported by the MFW\n");
+               return ECORE_NOTIMPL;
+       }
+
+       p_dev->ppfid_bitmap = GET_MFW_FIELD(mb_params.mcp_param,
+                                           FW_MB_PARAM_PPFID_BITMAP);
+
+       DP_VERBOSE(p_hwfn, ECORE_MSG_SP, "PPFID bitmap 0x%hhx\n",
+                  p_dev->ppfid_bitmap);
+
+       return ECORE_SUCCESS;
+}
+
 void ecore_mcp_wol_wr(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
                      u32 offset, u32 val)
 {
index 8e12531..2c052b7 100644 (file)
@@ -25,9 +25,6 @@
                                             rel_pfid)
 #define MCP_PF_ID(p_hwfn)      MCP_PF_ID_BY_REL(p_hwfn, (p_hwfn)->rel_pf_id)
 
-#define MFW_PORT(_p_hwfn)      ((_p_hwfn)->abs_pf_id % \
-                                ecore_device_num_ports((_p_hwfn)->p_dev))
-
 struct ecore_mcp_info {
        /* List for mailbox commands which were sent and wait for a response */
        osal_list_t cmd_list;
@@ -566,4 +563,22 @@ ecore_mcp_read_ufp_config(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt);
 void ecore_mcp_wol_wr(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
                      u32 offset, u32 val);
 
+/**
+ * @brief Get the engine affinity configuration.
+ *
+ * @param p_hwfn
+ * @param p_ptt
+ */
+enum _ecore_status_t ecore_mcp_get_engine_config(struct ecore_hwfn *p_hwfn,
+                                                struct ecore_ptt *p_ptt);
+
+/**
+ * @brief Get the PPFID bitmap.
+ *
+ * @param p_hwfn
+ * @param p_ptt
+ */
+enum _ecore_status_t ecore_mcp_get_ppfid_bitmap(struct ecore_hwfn *p_hwfn,
+                                               struct ecore_ptt *p_ptt);
+
 #endif /* __ECORE_MCP_H__ */
index 3ac1085..9e937e2 100644 (file)
@@ -979,10 +979,12 @@ static u8 ecore_iov_alloc_vf_igu_sbs(struct ecore_hwfn *p_hwfn,
                ecore_init_cau_sb_entry(p_hwfn, &sb_entry,
                                        p_hwfn->rel_pf_id,
                                        vf->abs_vf_id, 1);
+
                ecore_dmae_host2grc(p_hwfn, p_ptt,
                                    (u64)(osal_uintptr_t)&sb_entry,
                                    CAU_REG_SB_VAR_MEMORY +
-                                   p_block->igu_sb_id * sizeof(u64), 2, 0);
+                                   p_block->igu_sb_id * sizeof(u64), 2,
+                                   OSAL_NULL /* default parameters */);
        }
 
        vf->num_sbs = (u8)num_rx_queues;
index 46ec984..13c2e2d 100644 (file)
@@ -1267,6 +1267,8 @@ struct public_drv_mb {
 #define DRV_MSG_CODE_OEM_RESET_TO_DEFAULT      0x3f000000
 #define DRV_MSG_CODE_OV_GET_CURR_CFG           0x40000000
 #define DRV_MSG_CODE_GET_OEM_UPDATES           0x41000000
+/* params [31:8] - reserved, [7:0] - bitmap */
+#define DRV_MSG_CODE_GET_PPFID_BITMAP          0x43000000
 
 /*deprecated don't use*/
 #define DRV_MSG_CODE_INITIATE_FLR_DEPRECATED    0x02000000
@@ -1476,6 +1478,7 @@ struct public_drv_mb {
 
 /* Param: Password len. Union: Plain Password */
 #define DRV_MSG_CODE_ENCRYPT_PASSWORD          0x00360000
+#define DRV_MSG_CODE_GET_ENGINE_CONFIG         0x00370000 /* Param: None */
 
 #define DRV_MSG_SEQ_NUMBER_MASK                 0x0000ffff
 
@@ -1812,6 +1815,18 @@ struct public_drv_mb {
 #define FW_MB_PARAM_OEM_UPDATE_S_TAG           0x02
 #define FW_MB_PARAM_OEM_UPDATE_CFG             0x04
 
+#define FW_MB_PARAM_ENG_CFG_FIR_AFFIN_VALID_MASK   0x00000001
+#define FW_MB_PARAM_ENG_CFG_FIR_AFFIN_VALID_OFFSET 0
+#define FW_MB_PARAM_ENG_CFG_FIR_AFFIN_VALUE_MASK   0x00000002
+#define FW_MB_PARAM_ENG_CFG_FIR_AFFIN_VALUE_OFFSET 1
+#define FW_MB_PARAM_ENG_CFG_L2_AFFIN_VALID_MASK    0x00000004
+#define FW_MB_PARAM_ENG_CFG_L2_AFFIN_VALID_OFFSET  2
+#define FW_MB_PARAM_ENG_CFG_L2_AFFIN_VALUE_MASK    0x00000008
+#define FW_MB_PARAM_ENG_CFG_L2_AFFIN_VALUE_OFFSET  3
+
+#define FW_MB_PARAM_PPFID_BITMAP_MASK   0xFF
+#define FW_MB_PARAM_PPFID_BITMAP_OFFSET    0
+
        u32 drv_pulse_mb;
 #define DRV_PULSE_SEQ_MASK                      0x00007fff
 #define DRV_PULSE_SYSTEM_TIME_MASK              0xffff0000
index c3e0bd2..612337f 100644 (file)
 #define DORQ_REG_TAG1_OVRD_MODE 0x1008b4UL
 #define DORQ_REG_PF_EXT_VID_BB_K2 0x1008c8UL
 #define PRS_REG_SEARCH_NON_IP_AS_GFT 0x1f11c0UL
+#define NIG_REG_LLH_PPFID2PFID_TBL_0 0x501970UL
+#define NIG_REG_PPF_TO_ENGINE_SEL 0x508900UL
+#define NIG_REG_LLH_ENG_CLS_ROCE_QP_SEL 0x501b98UL
+#define NIG_REG_LLH_FUNC_FILTER_HDR_SEL_BB_K2 0x501b40UL