X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fbnxt%2Ftf_ulp%2Fulp_mark_mgr.c;h=89c08ab259ddf0b7f6391f713ff6f2a267dff858;hb=eee264adc95ed049642a9c7d0e4b897d51ccaccf;hp=3f28a73f6b983859deb46cdaf3ed0eac91a452a4;hpb=313ac35ac70112fc86703d76a65e0e252dca6590;p=dpdk.git diff --git a/drivers/net/bnxt/tf_ulp/ulp_mark_mgr.c b/drivers/net/bnxt/tf_ulp/ulp_mark_mgr.c index 3f28a73f6b..89c08ab259 100644 --- a/drivers/net/bnxt/tf_ulp/ulp_mark_mgr.c +++ b/drivers/net/bnxt/tf_ulp/ulp_mark_mgr.c @@ -6,14 +6,42 @@ #include #include #include +#include "bnxt.h" #include "bnxt_ulp.h" #include "tf_ext_flow_handle.h" #include "ulp_mark_mgr.h" #include "bnxt_tf_common.h" -#include "../bnxt.h" -#include "ulp_template_db.h" +#include "ulp_template_db_enum.h" #include "ulp_template_struct.h" +#define ULP_MARK_DB_ENTRY_SET_VALID(mark_info) ((mark_info)->flags |=\ + BNXT_ULP_MARK_VALID) +#define ULP_MARK_DB_ENTRY_IS_INVALID(mark_info) (!((mark_info)->flags &\ + BNXT_ULP_MARK_VALID)) +#define ULP_MARK_DB_ENTRY_IS_VFR_ID(mark_info) ((mark_info)->flags &\ + BNXT_ULP_MARK_VFR_ID) +#define ULP_MARK_DB_ENTRY_IS_GLOBAL_HW_FID(mark_info) ((mark_info)->flags &\ + BNXT_ULP_MARK_GLOBAL_HW_FID) + +static inline uint32_t +ulp_mark_db_idx_get(bool is_gfid, uint32_t fid, struct bnxt_ulp_mark_tbl *mtbl) +{ + uint32_t idx = 0, hashtype = 0; + + if (is_gfid) { + TF_GET_HASH_TYPE_FROM_GFID(fid, hashtype); + TF_GET_HASH_INDEX_FROM_GFID(fid, idx); + + /* Need to truncate anything beyond supported flows */ + idx &= mtbl->gfid_mask; + if (hashtype) + idx |= mtbl->gfid_type_bit; + } else { + idx = fid; + } + return idx; +} + /* * Allocate and Initialize all Mark Manager resources for this ulp context. * @@ -48,47 +76,243 @@ ulp_mark_db_init(struct bnxt_ulp_context *ctxt) if (!mark_tbl) goto mem_error; - /* Need to allocate 2 * Num flows to account for hash type bit. */ + /* Need to allocate 2 * Num flows to account for hash type bit.*/ + mark_tbl->lfid_num_entries = dparms->mark_db_lfid_entries; mark_tbl->lfid_tbl = rte_zmalloc("ulp_rx_em_flow_mark_table", - dparms->lfid_entries * - sizeof(struct bnxt_lfid_mark_info), + mark_tbl->lfid_num_entries * + sizeof(struct bnxt_lfid_mark_info), 0); - if (!mark_tbl->lfid_tbl) goto mem_error; - /* Need to allocate 2 * Num flows to account for hash type bit. */ + /* Need to allocate 2 * Num flows to account for hash type bit */ + mark_tbl->gfid_num_entries = dparms->mark_db_gfid_entries; mark_tbl->gfid_tbl = rte_zmalloc("ulp_rx_eem_flow_mark_table", - 2 * dparms->num_flows * - sizeof(struct bnxt_gfid_mark_info), + mark_tbl->gfid_num_entries * + sizeof(struct bnxt_gfid_mark_info), 0); if (!mark_tbl->gfid_tbl) goto mem_error; /* - * TBD: This needs to be generalized for better mark handling * These values are used to compress the FID to the allowable index - * space. The FID from hw may be the full hash. + * space. The FID from hw may be the full hash which may be a big + * value to allocate and so allocate only needed hash values. + * gfid mask is the number of flow entries for the each left/right + * hash The gfid type bit is used to get to the higher or lower hash + * entries. */ - mark_tbl->gfid_max = dparms->gfid_entries - 1; - mark_tbl->gfid_mask = (dparms->gfid_entries / 2) - 1; - mark_tbl->gfid_type_bit = (dparms->gfid_entries / 2); + mark_tbl->gfid_mask = (mark_tbl->gfid_num_entries / 2) - 1; + mark_tbl->gfid_type_bit = (mark_tbl->gfid_num_entries / 2); BNXT_TF_DBG(DEBUG, "GFID Max = 0x%08x\nGFID MASK = 0x%08x\n", - mark_tbl->gfid_max, + mark_tbl->gfid_num_entries - 1, mark_tbl->gfid_mask); - /* Add the mart tbl to the ulp context. */ + /* Add the mark tbl to the ulp context. */ bnxt_ulp_cntxt_ptr2_mark_db_set(ctxt, mark_tbl); - return 0; mem_error: rte_free(mark_tbl->gfid_tbl); rte_free(mark_tbl->lfid_tbl); rte_free(mark_tbl); - BNXT_TF_DBG(DEBUG, - "Failed to allocate memory for mark mgr\n"); - + BNXT_TF_DBG(DEBUG, "Failed to allocate memory for mark mgr\n"); return -ENOMEM; } + +/* + * Release all resources in the Mark Manager for this ulp context + * + * ctxt [in] The ulp context for the mark manager + * + */ +int32_t +ulp_mark_db_deinit(struct bnxt_ulp_context *ctxt) +{ + struct bnxt_ulp_mark_tbl *mtbl; + + mtbl = bnxt_ulp_cntxt_ptr2_mark_db_get(ctxt); + + if (mtbl) { + rte_free(mtbl->gfid_tbl); + rte_free(mtbl->lfid_tbl); + rte_free(mtbl); + + /* Safe to ignore on deinit */ + (void)bnxt_ulp_cntxt_ptr2_mark_db_set(ctxt, NULL); + } + + return 0; +} + +/* + * Get a Mark from the Mark Manager + * + * ctxt [in] The ulp context for the mark manager + * + * is_gfid [in] The type of fid (GFID or LFID) + * + * fid [in] The flow id that is returned by HW in BD + * + * vfr_flag [out].it indicatesif mark is vfr_id or mark id + * + * mark [out] The mark that is associated with the FID + * + */ +int32_t +ulp_mark_db_mark_get(struct bnxt_ulp_context *ctxt, + bool is_gfid, + uint32_t fid, + uint32_t *vfr_flag, + uint32_t *mark) +{ + struct bnxt_ulp_mark_tbl *mtbl; + uint32_t idx = 0; + + if (!ctxt || !mark) + return -EINVAL; + + mtbl = bnxt_ulp_cntxt_ptr2_mark_db_get(ctxt); + if (!mtbl) { + BNXT_TF_DBG(ERR, "Unable to get Mark Table\n"); + return -EINVAL; + } + + idx = ulp_mark_db_idx_get(is_gfid, fid, mtbl); + + if (is_gfid) { + if (idx >= mtbl->gfid_num_entries || + ULP_MARK_DB_ENTRY_IS_INVALID(&mtbl->gfid_tbl[idx])) + return -EINVAL; + + BNXT_TF_DBG(DEBUG, "Get GFID[0x%0x] = 0x%0x\n", + idx, mtbl->gfid_tbl[idx].mark_id); + + *vfr_flag = ULP_MARK_DB_ENTRY_IS_VFR_ID(&mtbl->gfid_tbl[idx]); + *mark = mtbl->gfid_tbl[idx].mark_id; + } else { + if (idx >= mtbl->lfid_num_entries || + ULP_MARK_DB_ENTRY_IS_INVALID(&mtbl->lfid_tbl[idx])) + return -EINVAL; + + BNXT_TF_DBG(DEBUG, "Get LFID[0x%0x] = 0x%0x\n", + idx, mtbl->lfid_tbl[idx].mark_id); + + *vfr_flag = ULP_MARK_DB_ENTRY_IS_VFR_ID(&mtbl->lfid_tbl[idx]); + *mark = mtbl->lfid_tbl[idx].mark_id; + } + + return 0; +} + +/* + * Adds a Mark to the Mark Manager + * + * ctxt [in] The ulp context for the mark manager + * + * mark_flag [in] mark flags. + * + * fid [in] The flow id that is returned by HW in BD + * + * mark [in] The mark to be associated with the FID + * + */ +int32_t +ulp_mark_db_mark_add(struct bnxt_ulp_context *ctxt, + uint32_t mark_flag, + uint32_t fid, + uint32_t mark) +{ + struct bnxt_ulp_mark_tbl *mtbl; + uint32_t idx = 0; + bool is_gfid; + + if (!ctxt) { + BNXT_TF_DBG(ERR, "Invalid ulp context\n"); + return -EINVAL; + } + + mtbl = bnxt_ulp_cntxt_ptr2_mark_db_get(ctxt); + if (!mtbl) { + BNXT_TF_DBG(ERR, "Unable to get Mark DB\n"); + return -EINVAL; + } + + is_gfid = (mark_flag & BNXT_ULP_MARK_GLOBAL_HW_FID); + if (is_gfid) { + idx = ulp_mark_db_idx_get(is_gfid, fid, mtbl); + if (idx >= mtbl->gfid_num_entries) { + BNXT_TF_DBG(ERR, "Mark index greater than allocated\n"); + return -EINVAL; + } + BNXT_TF_DBG(DEBUG, "Set GFID[0x%0x] = 0x%0x\n", idx, mark); + mtbl->gfid_tbl[idx].mark_id = mark; + ULP_MARK_DB_ENTRY_SET_VALID(&mtbl->gfid_tbl[idx]); + + } else { + /* For the LFID, the FID is used as the index */ + if (fid >= mtbl->lfid_num_entries) { + BNXT_TF_DBG(ERR, "Mark index greater than allocated\n"); + return -EINVAL; + } + mtbl->lfid_tbl[fid].mark_id = mark; + ULP_MARK_DB_ENTRY_SET_VALID(&mtbl->lfid_tbl[fid]); + } + + return 0; +} + +/* + * Removes a Mark from the Mark Manager + * + * ctxt [in] The ulp context for the mark manager + * + * mark_flag [in] mark flags. + * + * fid [in] The flow id that is returned by HW in BD + * + */ +int32_t +ulp_mark_db_mark_del(struct bnxt_ulp_context *ctxt, + uint32_t mark_flag, + uint32_t fid) +{ + struct bnxt_ulp_mark_tbl *mtbl; + uint32_t idx = 0; + bool is_gfid; + + if (!ctxt) { + BNXT_TF_DBG(ERR, "Invalid ulp context\n"); + return -EINVAL; + } + + mtbl = bnxt_ulp_cntxt_ptr2_mark_db_get(ctxt); + if (!mtbl) { + BNXT_TF_DBG(ERR, "Unable to get Mark DB\n"); + return -EINVAL; + } + + is_gfid = (mark_flag & BNXT_ULP_MARK_GLOBAL_HW_FID); + if (is_gfid) { + idx = ulp_mark_db_idx_get(is_gfid, fid, mtbl); + if (idx >= mtbl->gfid_num_entries) { + BNXT_TF_DBG(ERR, "Mark index greater than allocated\n"); + return -EINVAL; + } + BNXT_TF_DBG(DEBUG, "Reset GFID[0x%0x]\n", idx); + memset(&mtbl->gfid_tbl[idx], 0, + sizeof(struct bnxt_gfid_mark_info)); + + } else { + /* For the LFID, the FID is used as the index */ + if (fid >= mtbl->lfid_num_entries) { + BNXT_TF_DBG(ERR, "Mark index greater than allocated\n"); + return -EINVAL; + } + memset(&mtbl->lfid_tbl[fid], 0, + sizeof(struct bnxt_lfid_mark_info)); + } + + return 0; +}