From 3eed444a9621026ae8a28d2d9ca1b0aff4aae8bd Mon Sep 17 00:00:00 2001 From: Rasesh Mody Date: Sat, 29 Sep 2018 08:14:35 +0000 Subject: [PATCH] net/qede/base: changes for 100G 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 --- drivers/net/qede/base/ecore.h | 49 +- drivers/net/qede/base/ecore_cxt.c | 4 +- drivers/net/qede/base/ecore_dcbx.c | 11 +- drivers/net/qede/base/ecore_dev.c | 1740 +++++++++++++++++------- drivers/net/qede/base/ecore_dev_api.h | 161 ++- drivers/net/qede/base/ecore_hw.c | 103 +- drivers/net/qede/base/ecore_hw.h | 28 +- drivers/net/qede/base/ecore_init_ops.c | 14 +- drivers/net/qede/base/ecore_int.c | 13 +- drivers/net/qede/base/ecore_l2.c | 6 +- drivers/net/qede/base/ecore_mcp.c | 69 + drivers/net/qede/base/ecore_mcp.h | 21 +- drivers/net/qede/base/ecore_sriov.c | 4 +- drivers/net/qede/base/mcp_public.h | 15 + drivers/net/qede/base/reg_addr.h | 4 + 15 files changed, 1684 insertions(+), 558 deletions(-) diff --git a/drivers/net/qede/base/ecore.h b/drivers/net/qede/base/ecore.h index b9f5993c00..524a1dd467 100644 --- a/drivers/net/qede/base/ecore.h +++ b/drivers/net/qede/base/ecore.h @@ -19,6 +19,7 @@ #include #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 */ diff --git a/drivers/net/qede/base/ecore_cxt.c b/drivers/net/qede/base/ecore_cxt.c index 6bc63484bc..5c3370e102 100644 --- a/drivers/net/qede/base/ecore_cxt.c +++ b/drivers/net/qede/base/ecore_cxt.c @@ -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); diff --git a/drivers/net/qede/base/ecore_dcbx.c b/drivers/net/qede/base/ecore_dcbx.c index 96678745fd..7668ad6428 100644 --- a/drivers/net/qede/base/ecore_dcbx.c +++ b/drivers/net/qede/base/ecore_dcbx.c @@ -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; } diff --git a/drivers/net/qede/base/ecore_dev.c b/drivers/net/qede/base/ecore_dev.c index 30e12e9e68..cf454b19bb 100644 --- a/drivers/net/qede/base/ecore_dev.c +++ b/drivers/net/qede/base/ecore_dev.c @@ -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(¶ms, 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 */, ¶ms); + } 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 */, ¶ms); + } + + 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) diff --git a/drivers/net/qede/base/ecore_dev_api.h b/drivers/net/qede/base/ecore_dev_api.h index ab80b527dd..7308063218 100644 --- a/drivers/net/qede/base/ecore_dev_api.h +++ b/drivers/net/qede/base/ecore_dev_api.h @@ -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 */ -void ecore_llh_remove_mac_filter(struct ecore_hwfn *p_hwfn, - struct ecore_ptt *p_ptt, - u8 *p_filter); +enum ecore_eng ecore_llh_get_l2_affinity_hint(struct ecore_dev *p_dev); -enum ecore_llh_port_filter_type_t { +/** + * @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 + */ +enum _ecore_status_t ecore_llh_set_ppfid_affinity(struct ecore_dev *p_dev, + u8 ppfid, enum ecore_eng eng); + +/** + * @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_all_filters(struct ecore_hwfn *p_hwfn, - struct ecore_ptt *p_ptt); +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_dev *p_dev); /** * @brief ecore_llh_set_function_as_default - set function as default per port diff --git a/drivers/net/qede/base/ecore_hw.c b/drivers/net/qede/base/ecore_hw.c index 6cfbbab26d..72cd7e9c32 100644 --- a/drivers/net/qede/base/ecore_hw.c +++ b/drivers/net/qede/base/ecore_hw.c @@ -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(¶ms, 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, ¶ms); + 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(¶ms, 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, ¶ms); + 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(¶ms, 0, sizeof(params)); rc = ecore_dmae_host2host(p_hwfn, p_ptt, p_phys, p_phys + size, - size / 4 /* size_in_dwords */, ¶ms); + 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 @@ enum _ecore_status_t ecore_dmae_sanity(struct ecore_hwfn *p_hwfn, 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; +} diff --git a/drivers/net/qede/base/ecore_hw.h b/drivers/net/qede/base/ecore_hw.h index a62ba39787..0b5b40c468 100644 --- a/drivers/net/qede/base/ecore_hw.h +++ b/drivers/net/qede/base/ecore_hw.h @@ -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__ */ diff --git a/drivers/net/qede/base/ecore_init_ops.c b/drivers/net/qede/base/ecore_init_ops.c index b7636f3659..47c1be2d51 100644 --- a/drivers/net/qede/base/ecore_init_ops.c +++ b/drivers/net/qede/base/ecore_init_ops.c @@ -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(¶ms, 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, ¶ms); } static void ecore_init_fill(struct ecore_hwfn *p_hwfn, diff --git a/drivers/net/qede/base/ecore_int.c b/drivers/net/qede/base/ecore_int.c index fd8f657235..e48a7bc0d2 100644 --- a/drivers/net/qede/base/ecore_int.c +++ b/drivers/net/qede/base/ecore_int.c @@ -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; diff --git a/drivers/net/qede/base/ecore_l2.c b/drivers/net/qede/base/ecore_l2.c index c17082eb9d..5a0905ec72 100644 --- a/drivers/net/qede/base/ecore_l2.c +++ b/drivers/net/qede/base/ecore_l2.c @@ -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; diff --git a/drivers/net/qede/base/ecore_mcp.c b/drivers/net/qede/base/ecore_mcp.c index 3811d27789..202db13a2b 100644 --- a/drivers/net/qede/base/ecore_mcp.c +++ b/drivers/net/qede/base/ecore_mcp.c @@ -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) { diff --git a/drivers/net/qede/base/ecore_mcp.h b/drivers/net/qede/base/ecore_mcp.h index 8e125310e8..2c052b7fa0 100644 --- a/drivers/net/qede/base/ecore_mcp.h +++ b/drivers/net/qede/base/ecore_mcp.h @@ -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__ */ diff --git a/drivers/net/qede/base/ecore_sriov.c b/drivers/net/qede/base/ecore_sriov.c index 3ac10859ba..9e937e2a34 100644 --- a/drivers/net/qede/base/ecore_sriov.c +++ b/drivers/net/qede/base/ecore_sriov.c @@ -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; diff --git a/drivers/net/qede/base/mcp_public.h b/drivers/net/qede/base/mcp_public.h index 46ec984b99..13c2e2d116 100644 --- a/drivers/net/qede/base/mcp_public.h +++ b/drivers/net/qede/base/mcp_public.h @@ -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 diff --git a/drivers/net/qede/base/reg_addr.h b/drivers/net/qede/base/reg_addr.h index c3e0bd2ded..612337fcde 100644 --- a/drivers/net/qede/base/reg_addr.h +++ b/drivers/net/qede/base/reg_addr.h @@ -1235,3 +1235,7 @@ #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