X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fice%2Fbase%2Fice_flex_pipe.c;h=14e632fab89f0a9fd44ede647f807290804b6a27;hb=7f9f46d6cef5b03681a3935b9a18378e08ca6f62;hp=900a1938779c03bfd78c8e46500d40e43826fd9d;hpb=f5041767fd0396b88037776dc0d0ba802756db9f;p=dpdk.git diff --git a/drivers/net/ice/base/ice_flex_pipe.c b/drivers/net/ice/base/ice_flex_pipe.c index 900a193877..14e632fab8 100644 --- a/drivers/net/ice/base/ice_flex_pipe.c +++ b/drivers/net/ice/base/ice_flex_pipe.c @@ -1274,6 +1274,25 @@ void ice_free_seg(struct ice_hw *hw) hw->seg = NULL; } +/** + * ice_init_fd_mask_regs - initialize Flow Director mask registers + * @hw: pointer to the HW struct + * + * This function sets up the Flow Director mask registers to allow for complete + * masking off of any of the 24 Field Vector words. After this call, mask 0 will + * mask off all of FV index 0, mask 1 will mask off all of FV index 1, etc. + */ +static void ice_init_fd_mask_regs(struct ice_hw *hw) +{ + u16 i; + + for (i = 0; i < hw->blk[ICE_BLK_FD].es.fvw; i++) { + wr32(hw, GLQF_FDMASK(i), i); + ice_debug(hw, ICE_DBG_INIT, "init fd mask(%d): %x = %x\n", i, + GLQF_FDMASK(i), i); + } +} + /** * ice_init_pkg_regs - initialize additional package registers * @hw: pointer to the hardware structure @@ -1287,6 +1306,8 @@ static void ice_init_pkg_regs(struct ice_hw *hw) /* setup Switch block input mask, which is 48-bits in two parts */ wr32(hw, GL_PREEXT_L2_PMASK0(ICE_SW_BLK_IDX), ICE_SW_BLK_INP_MASK_L); wr32(hw, GL_PREEXT_L2_PMASK1(ICE_SW_BLK_IDX), ICE_SW_BLK_INP_MASK_H); + /* setup default flow director masks */ + ice_init_fd_mask_regs(hw); } /** @@ -2281,21 +2302,23 @@ ice_vsig_free(struct ice_hw *hw, enum ice_block blk, u16 vsig) hw->blk[blk].xlt2.vsig_tbl[idx].in_use = false; vsi_cur = hw->blk[blk].xlt2.vsig_tbl[idx].first_vsi; - if (!vsi_cur) - return ICE_ERR_CFG; - - /* remove all vsis associated with this VSIG XLT2 entry */ - do { - struct ice_vsig_vsi *tmp = vsi_cur->next_vsi; - - vsi_cur->vsig = ICE_DEFAULT_VSIG; - vsi_cur->changed = 1; - vsi_cur->next_vsi = NULL; - vsi_cur = tmp; - } while (vsi_cur); - - /* NULL terminate head of vsi list */ - hw->blk[blk].xlt2.vsig_tbl[idx].first_vsi = NULL; + /* If the VSIG has at least 1 VSI then iterate through the + * list and remove the VSIs before deleting the group. + */ + if (vsi_cur) { + /* remove all vsis associated with this VSIG XLT2 entry */ + do { + struct ice_vsig_vsi *tmp = vsi_cur->next_vsi; + + vsi_cur->vsig = ICE_DEFAULT_VSIG; + vsi_cur->changed = 1; + vsi_cur->next_vsi = NULL; + vsi_cur = tmp; + } while (vsi_cur); + + /* NULL terminate head of VSI list */ + hw->blk[blk].xlt2.vsig_tbl[idx].first_vsi = NULL; + } /* free characteristic list */ LIST_FOR_EACH_ENTRY_SAFE(del, dtmp, @@ -2444,7 +2467,7 @@ ice_find_prof_id(struct ice_hw *hw, enum ice_block blk, for (i = 0; i < es->count; i++) { off = i * es->fvw; - if (memcmp(&es->t[off], fv, es->fvw * 2)) + if (memcmp(&es->t[off], fv, es->fvw * sizeof(*fv))) continue; *prof_id = i; @@ -2512,199 +2535,6 @@ static bool ice_tcam_ent_rsrc_type(enum ice_block blk, u16 *rsrc_type) return true; } -/** - * ice_workaround_get_res_blk - determine the block from a resource type - * @type: type of resource - * @blk: pointer to a enum that will receive the block type - * @tcam: pointer to variable that will be set to true for a TCAM resource type - */ -static enum -ice_status ice_workaround_get_res_blk(u16 type, enum ice_block *blk, bool *tcam) -{ - /* just need to support TCAM entries and Profile IDs for now */ - *tcam = false; - - switch (type) { - case ICE_AQC_RES_TYPE_SWITCH_PROF_BLDR_TCAM: - *blk = ICE_BLK_SW; - *tcam = true; - break; - case ICE_AQC_RES_TYPE_ACL_PROF_BLDR_TCAM: - *blk = ICE_BLK_ACL; - *tcam = true; - break; - case ICE_AQC_RES_TYPE_FD_PROF_BLDR_TCAM: - *blk = ICE_BLK_FD; - *tcam = true; - break; - case ICE_AQC_RES_TYPE_HASH_PROF_BLDR_TCAM: - *blk = ICE_BLK_RSS; - *tcam = true; - break; - case ICE_AQC_RES_TYPE_QHASH_PROF_BLDR_TCAM: - *blk = ICE_BLK_PE; - *tcam = true; - break; - case ICE_AQC_RES_TYPE_SWITCH_PROF_BLDR_PROFID: - *blk = ICE_BLK_SW; - break; - case ICE_AQC_RES_TYPE_ACL_PROF_BLDR_PROFID: - *blk = ICE_BLK_ACL; - break; - case ICE_AQC_RES_TYPE_FD_PROF_BLDR_PROFID: - *blk = ICE_BLK_FD; - break; - case ICE_AQC_RES_TYPE_HASH_PROF_BLDR_PROFID: - *blk = ICE_BLK_RSS; - break; - case ICE_AQC_RES_TYPE_QHASH_PROF_BLDR_PROFID: - *blk = ICE_BLK_PE; - break; - default: - return ICE_ERR_PARAM; - } - - return ICE_SUCCESS; -} - -/** - * ice_alloc_res_workaround - * @hw: pointer to the hw struct - * @type: type of resource - * @num: number of resources to allocate - * @res: pointer to array that will receive the resources - */ -static enum ice_status -ice_alloc_res_workaround(struct ice_hw *hw, u16 type, u16 num, u16 *res) -{ - enum ice_block blk; - u16 count = 0; - bool tcam; - u16 first; - u16 last; - u16 max; - u16 i; - -/* Number of PFs we support with this workaround */ -#define ICE_WA_PF_COUNT 4 -#define ICE_WA_1ST_TCAM 4 -#define ICE_WA_1ST_FV 4 - - /* Only allow our supported PFs */ - if (hw->pf_id >= ICE_WA_PF_COUNT) - return ICE_ERR_AQ_ERROR; - - if (ice_workaround_get_res_blk(type, &blk, &tcam)) - return ICE_ERR_AQ_ERROR; - - if (tcam) { - /* range of entries based on PF */ - max = hw->blk[blk].prof.count / ICE_WA_PF_COUNT; - first = max * hw->pf_id; - last = first + max; - - /* Profile IDs - start at non-zero index for PROF ID TCAM table - * The first few entries are for bypass, default and errors - * (only relevant for PF 0) - */ - first += hw->pf_id ? 0 : ICE_WA_1ST_TCAM; - - for (i = first; i < last && count < num; i++) { - if (!hw->blk[blk].prof.resource_used_hack[i]) { - res[count++] = i; - hw->blk[blk].prof.resource_used_hack[i] = true; - } - } - - /* handle failure case */ - if (count < num) { - for (i = 0; i < count; i++) { - hw->blk[blk].prof.resource_used_hack[res[i]] = - false; - res[i] = 0; - } - - return ICE_ERR_AQ_ERROR; - } - } else { - /* range of entries based on PF */ - max = hw->blk[blk].es.count / ICE_WA_PF_COUNT; - first = max * hw->pf_id; - last = first + max; - - /* FV index - start at non-zero index for Field vector table - * The first few entries are for bypass, default and errors - * (only relevant for PF 0) - */ - first += hw->pf_id ? 0 : ICE_WA_1ST_FV; - - for (i = first; i < last && count < num; i++) { - if (!hw->blk[blk].es.resource_used_hack[i]) { - res[count++] = i; - hw->blk[blk].es.resource_used_hack[i] = true; - } - } - - /* handle failure case */ - if (count < num) { - for (i = 0; i < count; i++) { - hw->blk[blk].es.resource_used_hack[res[i]] = - false; - res[i] = 0; - } - - return ICE_ERR_AQ_ERROR; - } - } - - return ICE_SUCCESS; -} - -/** - * ice_free_res_workaround - * @hw: pointer to the hw struct - * @type: type of resource to free - * @num: number of resources - * @res: array of resource ids to free - */ -static enum ice_status -ice_free_res_workaround(struct ice_hw *hw, u16 type, u16 num, u16 *res) -{ - enum ice_block blk; - bool tcam = false; - u16 i; - - if (ice_workaround_get_res_blk(type, &blk, &tcam)) - return ICE_ERR_AQ_ERROR; - - if (tcam) { - /* TCAM entries */ - for (i = 0; i < num; i++) { - if (res[i] < hw->blk[blk].prof.count) { - u16 idx = res[i]; - - ice_free_hw_res(hw, type, 1, &idx); - hw->blk[blk].prof.resource_used_hack[res[i]] = - false; - } - } - - } else { - /* Profile IDs */ - for (i = 0; i < num; i++) { - if (res[i] < hw->blk[blk].es.count) { - u16 idx = res[i]; - - ice_free_hw_res(hw, type, 1, &idx); - hw->blk[blk].es.resource_used_hack[res[i]] = - false; - } - } - } - - return ICE_SUCCESS; -} - /** * ice_alloc_tcam_ent - allocate hardware TCAM entry * @hw: pointer to the HW struct @@ -2722,7 +2552,7 @@ ice_alloc_tcam_ent(struct ice_hw *hw, enum ice_block blk, u16 *tcam_idx) if (!ice_tcam_ent_rsrc_type(blk, &res_type)) return ICE_ERR_PARAM; - return ice_alloc_res_workaround(hw, res_type, 1, tcam_idx); + return ice_alloc_hw_res(hw, res_type, 1, true, tcam_idx); } /** @@ -2741,7 +2571,7 @@ ice_free_tcam_ent(struct ice_hw *hw, enum ice_block blk, u16 tcam_idx) if (!ice_tcam_ent_rsrc_type(blk, &res_type)) return ICE_ERR_PARAM; - return ice_free_res_workaround(hw, res_type, 1, &tcam_idx); + return ice_free_hw_res(hw, res_type, 1, &tcam_idx); } /** @@ -2763,7 +2593,7 @@ ice_alloc_prof_id(struct ice_hw *hw, enum ice_block blk, u8 *prof_id) if (!ice_prof_id_rsrc_type(blk, &res_type)) return ICE_ERR_PARAM; - status = ice_alloc_res_workaround(hw, res_type, 1, &get_prof); + status = ice_alloc_hw_res(hw, res_type, 1, false, &get_prof); if (!status) *prof_id = (u8)get_prof; @@ -2787,15 +2617,7 @@ ice_free_prof_id(struct ice_hw *hw, enum ice_block blk, u8 prof_id) if (!ice_prof_id_rsrc_type(blk, &res_type)) return ICE_ERR_PARAM; - return ice_free_res_workaround(hw, res_type, 1, &tmp_prof_id); - /* The following code is a WORKAROUND until DCR 076 is available. - * DCR 076 - Update to Profile ID TCAM Resource Allocation - * - * Once the DCR 076 changes are available in FW, this code can be - * restored. Original code: - * - * return ice_free_res(hw, res_type, 1, &tmp_prof_id); - */ + return ice_free_hw_res(hw, res_type, 1, &tmp_prof_id); } /** @@ -2815,6 +2637,30 @@ ice_prof_inc_ref(struct ice_hw *hw, enum ice_block blk, u8 prof_id) return ICE_SUCCESS; } +/** + * ice_write_es - write an extraction sequence to hardware + * @hw: pointer to the HW struct + * @blk: the block in which to write the extraction sequence + * @prof_id: the profile ID to write + * @fv: pointer to the extraction sequence to write - NULL to clear extraction + */ +static void +ice_write_es(struct ice_hw *hw, enum ice_block blk, u8 prof_id, + struct ice_fv_word *fv) +{ + u16 off; + + off = prof_id * hw->blk[blk].es.fvw; + if (!fv) { + ice_memset(&hw->blk[blk].es.t[off], 0, hw->blk[blk].es.fvw * + sizeof(*fv), ICE_NONDMA_MEM); + hw->blk[blk].es.written[prof_id] = false; + } else { + ice_memcpy(&hw->blk[blk].es.t[off], fv, hw->blk[blk].es.fvw * + sizeof(*fv), ICE_NONDMA_TO_NONDMA); + } +} + /** * ice_prof_dec_ref - decrement reference count for profile * @hw: pointer to the HW struct @@ -2828,31 +2674,15 @@ ice_prof_dec_ref(struct ice_hw *hw, enum ice_block blk, u8 prof_id) return ICE_ERR_PARAM; if (hw->blk[blk].es.ref_count[prof_id] > 0) { - if (!--hw->blk[blk].es.ref_count[prof_id]) + if (!--hw->blk[blk].es.ref_count[prof_id]) { + ice_write_es(hw, blk, prof_id, NULL); return ice_free_prof_id(hw, blk, prof_id); + } } return ICE_SUCCESS; } -/** - * ice_write_es - write an extraction sequence to hardware - * @hw: pointer to the HW struct - * @blk: the block in which to write the extraction sequence - * @prof_id: the profile ID to write - * @fv: pointer to the extraction sequence to write - */ -static void -ice_write_es(struct ice_hw *hw, enum ice_block blk, u8 prof_id, - struct ice_fv_word *fv) -{ - u16 off; - - off = prof_id * hw->blk[blk].es.fvw; - ice_memcpy(&hw->blk[blk].es.t[off], fv, hw->blk[blk].es.fvw * 2, - ICE_NONDMA_TO_NONDMA); -} - /* Block / table section IDs */ static const u32 ice_blk_sids[ICE_BLK_COUNT][ICE_SID_OFF_COUNT] = { /* SWITCH */ @@ -2935,9 +2765,11 @@ static void ice_fill_tbl(struct ice_hw *hw, enum ice_block block_id, u32 sid) while (sect) { switch (sid) { + case ICE_SID_XLT1_SW: case ICE_SID_XLT1_FD: case ICE_SID_XLT1_RSS: case ICE_SID_XLT1_ACL: + case ICE_SID_XLT1_PE: xlt1 = (struct ice_xlt1_section *)sect; src = xlt1->value; sect_len = LE16_TO_CPU(xlt1->count) * @@ -2946,9 +2778,11 @@ static void ice_fill_tbl(struct ice_hw *hw, enum ice_block block_id, u32 sid) dst_len = hw->blk[block_id].xlt1.count * sizeof(*hw->blk[block_id].xlt1.t); break; + case ICE_SID_XLT2_SW: case ICE_SID_XLT2_FD: case ICE_SID_XLT2_RSS: case ICE_SID_XLT2_ACL: + case ICE_SID_XLT2_PE: xlt2 = (struct ice_xlt2_section *)sect; src = (u8 *)xlt2->value; sect_len = LE16_TO_CPU(xlt2->count) * @@ -2957,9 +2791,11 @@ static void ice_fill_tbl(struct ice_hw *hw, enum ice_block block_id, u32 sid) dst_len = hw->blk[block_id].xlt2.count * sizeof(*hw->blk[block_id].xlt2.t); break; + case ICE_SID_PROFID_TCAM_SW: case ICE_SID_PROFID_TCAM_FD: case ICE_SID_PROFID_TCAM_RSS: case ICE_SID_PROFID_TCAM_ACL: + case ICE_SID_PROFID_TCAM_PE: pid = (struct ice_prof_id_section *)sect; src = (u8 *)pid->entry; sect_len = LE16_TO_CPU(pid->count) * @@ -2968,9 +2804,11 @@ static void ice_fill_tbl(struct ice_hw *hw, enum ice_block block_id, u32 sid) dst_len = hw->blk[block_id].prof.count * sizeof(*hw->blk[block_id].prof.t); break; + case ICE_SID_PROFID_REDIR_SW: case ICE_SID_PROFID_REDIR_FD: case ICE_SID_PROFID_REDIR_RSS: case ICE_SID_PROFID_REDIR_ACL: + case ICE_SID_PROFID_REDIR_PE: pr = (struct ice_prof_redir_section *)sect; src = pr->redir_value; sect_len = LE16_TO_CPU(pr->count) * @@ -2979,15 +2817,19 @@ static void ice_fill_tbl(struct ice_hw *hw, enum ice_block block_id, u32 sid) dst_len = hw->blk[block_id].prof_redir.count * sizeof(*hw->blk[block_id].prof_redir.t); break; + case ICE_SID_FLD_VEC_SW: case ICE_SID_FLD_VEC_FD: case ICE_SID_FLD_VEC_RSS: case ICE_SID_FLD_VEC_ACL: + case ICE_SID_FLD_VEC_PE: es = (struct ice_sw_fv_section *)sect; src = (u8 *)es->fv; sect_len = LE16_TO_CPU(es->count) * - sizeof(*hw->blk[block_id].prof_redir.t); + hw->blk[block_id].es.fvw * + sizeof(*hw->blk[block_id].es.t); dst = (u8 *)hw->blk[block_id].es.t; dst_len = hw->blk[block_id].es.count * + hw->blk[block_id].es.fvw * sizeof(*hw->blk[block_id].es.t); break; default: @@ -3082,8 +2924,7 @@ static void ice_free_prof_map(struct ice_hw *hw, enum ice_block blk) LIST_FOR_EACH_ENTRY_SAFE(del, tmp, &hw->blk[blk].es.prof_map, ice_prof_map, list) { - LIST_DEL(&del->list); - ice_free(hw, del); + ice_rem_prof(hw, blk, del->profile_cookie); } } @@ -3125,9 +2966,7 @@ void ice_free_hw_tbls(struct ice_hw *hw) ice_free(hw, hw->blk[i].prof_redir.t); ice_free(hw, hw->blk[i].es.t); ice_free(hw, hw->blk[i].es.ref_count); - - ice_free(hw, hw->blk[i].es.resource_used_hack); - ice_free(hw, hw->blk[i].prof.resource_used_hack); + ice_free(hw, hw->blk[i].es.written); } ice_memset(hw->blk, 0, sizeof(hw->blk), ICE_NONDMA_MEM); @@ -3297,19 +3136,10 @@ enum ice_status ice_init_hw_tbls(struct ice_hw *hw) es->ref_count = (u16 *) ice_calloc(hw, es->count, sizeof(*es->ref_count)); - if (!es->ref_count) - goto err; - - es->resource_used_hack = (u8 *) - ice_calloc(hw, hw->blk[i].es.count, sizeof(u8)); + es->written = (u8 *) + ice_calloc(hw, es->count, sizeof(*es->written)); - if (!es->resource_used_hack) - goto err; - - prof->resource_used_hack = (u8 *)ice_calloc(hw, prof->count, - sizeof(u8)); - - if (!prof->resource_used_hack) + if (!es->ref_count) goto err; INIT_LIST_HEAD(&es->prof_map); @@ -3758,6 +3588,205 @@ error_tmp: return status; } +/** + * ice_update_fd_mask - set Flow Director Field Vector mask for a profile + * @hw: pointer to the HW struct + * @prof_id: profile ID + * @mask_sel: mask select + * + * This function enable any of the masks selected by the mask select parameter + * for the profile specified. + */ +static void ice_update_fd_mask(struct ice_hw *hw, u16 prof_id, u32 mask_sel) +{ + wr32(hw, GLQF_FDMASK_SEL(prof_id), mask_sel); + + ice_debug(hw, ICE_DBG_INIT, "fd mask(%d): %x = %x\n", prof_id, + GLQF_FDMASK_SEL(prof_id), mask_sel); +} + +#define ICE_SRC_DST_MAX_COUNT 8 + +struct ice_fd_src_dst_pair { + u8 prot_id; + u8 count; + u16 off; +}; + +static const struct ice_fd_src_dst_pair ice_fd_pairs[] = { + /* These are defined in pairs */ + { ICE_PROT_IPV4_OF_OR_S, 2, 12 }, + { ICE_PROT_IPV4_OF_OR_S, 2, 16 }, + + { ICE_PROT_IPV4_IL, 2, 12 }, + { ICE_PROT_IPV4_IL, 2, 16 }, + + { ICE_PROT_IPV6_OF_OR_S, 8, 8 }, + { ICE_PROT_IPV6_OF_OR_S, 8, 24 }, + + { ICE_PROT_IPV6_IL, 8, 8 }, + { ICE_PROT_IPV6_IL, 8, 24 }, + + { ICE_PROT_TCP_IL, 1, 0 }, + { ICE_PROT_TCP_IL, 1, 2 }, + + { ICE_PROT_UDP_OF, 1, 0 }, + { ICE_PROT_UDP_OF, 1, 2 }, + + { ICE_PROT_UDP_IL_OR_S, 1, 0 }, + { ICE_PROT_UDP_IL_OR_S, 1, 2 }, + + { ICE_PROT_SCTP_IL, 1, 0 }, + { ICE_PROT_SCTP_IL, 1, 2 } +}; + +#define ICE_FD_SRC_DST_PAIR_COUNT ARRAY_SIZE(ice_fd_pairs) + +/** + * ice_update_fd_swap - set register appropriately for a FD FV extraction + * @hw: pointer to the HW struct + * @prof_id: profile ID + * @es: extraction sequence (length of array is determined by the block) + */ +static enum ice_status +ice_update_fd_swap(struct ice_hw *hw, u16 prof_id, struct ice_fv_word *es) +{ + ice_declare_bitmap(pair_list, ICE_FD_SRC_DST_PAIR_COUNT); + u8 pair_start[ICE_FD_SRC_DST_PAIR_COUNT] = { 0 }; +#define ICE_FD_FV_NOT_FOUND (-2) + s8 first_free = ICE_FD_FV_NOT_FOUND; + u8 used[ICE_MAX_FV_WORDS] = { 0 }; + s8 orig_free, si; + u32 mask_sel = 0; + u8 i, j, k; + + ice_memset(pair_list, 0, sizeof(pair_list), ICE_NONDMA_MEM); + + ice_init_fd_mask_regs(hw); + + /* This code assumes that the Flow Director field vectors are assigned + * from the end of the FV indexes working towards the zero index, that + * only complete fields will be included and will be consecutive, and + * that there are no gaps between valid indexes. + */ + + /* Determine swap fields present */ + for (i = 0; i < hw->blk[ICE_BLK_FD].es.fvw; i++) { + /* Find the first free entry, assuming right to left population. + * This is where we can start adding additional pairs if needed. + */ + if (first_free == ICE_FD_FV_NOT_FOUND && es[i].prot_id != + ICE_PROT_INVALID) + first_free = i - 1; + + for (j = 0; j < ICE_FD_SRC_DST_PAIR_COUNT; j++) { + if (es[i].prot_id == ice_fd_pairs[j].prot_id && + es[i].off == ice_fd_pairs[j].off) { + ice_set_bit(j, pair_list); + pair_start[j] = i; + } + } + } + + orig_free = first_free; + + /* determine missing swap fields that need to be added */ + for (i = 0; i < ICE_FD_SRC_DST_PAIR_COUNT; i += 2) { + u8 bit1 = ice_is_bit_set(pair_list, i + 1); + u8 bit0 = ice_is_bit_set(pair_list, i); + + if (bit0 ^ bit1) { + u8 index; + + /* add the appropriate 'paired' entry */ + if (!bit0) + index = i; + else + index = i + 1; + + /* check for room */ + if (first_free + 1 < ice_fd_pairs[index].count) + return ICE_ERR_MAX_LIMIT; + + /* place in extraction sequence */ + for (k = 0; k < ice_fd_pairs[index].count; k++) { + es[first_free - k].prot_id = + ice_fd_pairs[index].prot_id; + es[first_free - k].off = + ice_fd_pairs[index].off + (k * 2); + + /* keep track of non-relevant fields */ + mask_sel |= 1 << (first_free - k); + } + + pair_start[index] = first_free; + first_free -= ice_fd_pairs[index].count; + } + } + + /* fill in the swap array */ + si = hw->blk[ICE_BLK_FD].es.fvw - 1; + do { + u8 indexes_used = 1; + + /* assume flat at this index */ +#define ICE_SWAP_VALID 0x80 + used[si] = si | ICE_SWAP_VALID; + + if (orig_free == ICE_FD_FV_NOT_FOUND || si <= orig_free) { + si -= indexes_used; + continue; + } + + /* check for a swap location */ + for (j = 0; j < ICE_FD_SRC_DST_PAIR_COUNT; j++) { + if (es[si].prot_id == ice_fd_pairs[j].prot_id && + es[si].off == ice_fd_pairs[j].off) { + u8 idx; + + /* determine the appropriate matching field */ + idx = j + ((j % 2) ? -1 : 1); + + indexes_used = ice_fd_pairs[idx].count; + for (k = 0; k < indexes_used; k++) { + used[si - k] = (pair_start[idx] - k) | + ICE_SWAP_VALID; + } + + break; + } + } + + si -= indexes_used; + } while (si >= 0); + + /* for each set of 4 swap indexes, write the appropriate register */ + for (j = 0; j < hw->blk[ICE_BLK_FD].es.fvw / 4; j++) { + u32 raw_entry = 0; + + for (k = 0; k < 4; k++) { + u8 idx; + + idx = (j * 4) + k; + if (used[idx]) + raw_entry |= used[idx] << (k * 8); + } + + /* write the appropriate register set, based on HW block */ + wr32(hw, GLQF_FDSWAP(prof_id, j), raw_entry); + + ice_debug(hw, ICE_DBG_INIT, "swap wr(%d, %d): %x = %x\n", + prof_id, j, GLQF_FDSWAP(prof_id, j), raw_entry); + } + + /* update the masks for this profile to be sure we ignore fields that + * are not relevant to our match criteria + */ + ice_update_fd_mask(hw, prof_id, mask_sel); + + return ICE_SUCCESS; +} + /** * ice_add_prof - add profile * @hw: pointer to the HW struct @@ -3788,11 +3817,25 @@ ice_add_prof(struct ice_hw *hw, enum ice_block blk, u64 id, u8 ptypes[], status = ice_alloc_prof_id(hw, blk, &prof_id); if (status) goto err_ice_add_prof; + if (blk == ICE_BLK_FD) { + /* For Flow Director block, the extraction sequence may + * need to be altered in the case where there are paired + * fields that have no match. This is necessary because + * for Flow Director, src and dest fields need to paired + * for filter programming and these values are swapped + * during Tx. + */ + status = ice_update_fd_swap(hw, prof_id, es); + if (status) + goto err_ice_add_prof; + } /* and write new es */ ice_write_es(hw, blk, prof_id, es); } + ice_prof_inc_ref(hw, blk, prof_id); + /* add profile info */ prof = (struct ice_prof_map *)ice_malloc(hw, sizeof(*prof)); @@ -3972,10 +4015,6 @@ ice_rem_prof_id(struct ice_hw *hw, enum ice_block blk, for (i = 0; i < prof->tcam_count; i++) { prof->tcam[i].in_use = false; status = ice_rel_tcam_idx(hw, blk, prof->tcam[i].tcam_idx); - if (!status) - status = ice_prof_dec_ref(hw, blk, - prof->tcam[i].prof_id); - if (status) return ICE_ERR_HW_TABLE; } @@ -4013,36 +4052,32 @@ ice_rem_vsig(struct ice_hw *hw, enum ice_block blk, u16 vsig, /* Move all VSIS associated with this VSIG to the default VSIG */ vsi_cur = hw->blk[blk].xlt2.vsig_tbl[idx].first_vsi; - if (!vsi_cur) - return ICE_ERR_CFG; - - do { - struct ice_vsig_vsi *tmp = vsi_cur->next_vsi; - struct ice_chs_chg *p; - - p = (struct ice_chs_chg *)ice_malloc(hw, sizeof(*p)); - if (!p) - goto err_ice_rem_vsig; + /* If the VSIG has at least 1 VSI then iterate through the list + * and remove the VSIs before deleting the group. + */ + if (vsi_cur) { + do { + struct ice_vsig_vsi *tmp = vsi_cur->next_vsi; + struct ice_chs_chg *p; - p->type = ICE_VSIG_REM; - p->orig_vsig = vsig; - p->vsig = ICE_DEFAULT_VSIG; - p->vsi = vsi_cur - hw->blk[blk].xlt2.vsis; + p = (struct ice_chs_chg *)ice_malloc(hw, sizeof(*p)); + if (!p) + return ICE_ERR_NO_MEMORY; - LIST_ADD(&p->list_entry, chg); + p->type = ICE_VSIG_REM; + p->orig_vsig = vsig; + p->vsig = ICE_DEFAULT_VSIG; + p->vsi = vsi_cur - hw->blk[blk].xlt2.vsis; - status = ice_vsig_free(hw, blk, vsig); - if (status) - return status; + LIST_ADD(&p->list_entry, chg); - vsi_cur = tmp; - } while (vsi_cur); + vsi_cur = tmp; + } while (vsi_cur); + } - return ICE_SUCCESS; + status = ice_vsig_free(hw, blk, vsig); -err_ice_rem_vsig: - /* the caller will free up the change list */ - return ICE_ERR_NO_MEMORY; + return status; } /** @@ -4138,15 +4173,18 @@ enum ice_status ice_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 id) if (!pmap) return ICE_ERR_DOES_NOT_EXIST; - status = ice_free_prof_id(hw, blk, pmap->prof_id); - + /* remove all flows with this profile */ + status = ice_rem_flow_all(hw, blk, pmap->profile_cookie); if (status) return status; - /* remove all flows with this profile */ - status = ice_rem_flow_all(hw, blk, pmap->profile_cookie); + /* remove profile */ + status = ice_free_prof_id(hw, blk, pmap->prof_id); if (status) return status; + /* dereference profile, and possibly remove */ + ice_prof_dec_ref(hw, blk, pmap->prof_id); + LIST_DEL(&pmap->list); ice_free(hw, pmap); @@ -4182,7 +4220,7 @@ ice_get_prof_ptgs(struct ice_hw *hw, enum ice_block blk, u64 hdl, if (status) goto err_ice_get_prof_ptgs; - if (add || !hw->blk[blk].es.ref_count[map->prof_id]) { + if (add || !hw->blk[blk].es.written[map->prof_id]) { /* add PTG to change list */ p = (struct ice_chs_chg *)ice_malloc(hw, sizeof(*p)); if (!p) @@ -4193,9 +4231,11 @@ ice_get_prof_ptgs(struct ice_hw *hw, enum ice_block blk, u64 hdl, p->ptg = ptg; p->add_ptg = add; - p->add_prof = !hw->blk[blk].es.ref_count[map->prof_id]; + p->add_prof = !hw->blk[blk].es.written[map->prof_id]; p->prof_id = map->prof_id; + hw->blk[blk].es.written[map->prof_id] = true; + LIST_ADD(&p->list_entry, chg); } } @@ -4234,7 +4274,7 @@ ice_get_profs_vsig(struct ice_hw *hw, enum ice_block blk, u16 vsig, ice_memcpy(p, ent1, sizeof(*p), ICE_NONDMA_TO_NONDMA); - LIST_ADD(&p->list, lst); + LIST_ADD_TAIL(&p->list, lst); } return ICE_SUCCESS; @@ -4276,17 +4316,12 @@ ice_add_prof_to_lst(struct ice_hw *hw, enum ice_block blk, p->tcam_count = map->ptype_count; for (i = 0; i < map->ptype_count; i++) { - enum ice_status status; u8 ptg; p->tcam[i].prof_id = map->prof_id; p->tcam[i].tcam_idx = ICE_INVALID_TCAM; - status = ice_ptg_find_ptype(hw, blk, map->ptype[i], &ptg); - if (status) { - ice_free(hw, p); - return status; - } + ice_ptg_find_ptype(hw, blk, map->ptype[i], &ptg); p->tcam[i].ptg = ptg; } @@ -4523,8 +4558,10 @@ ice_add_prof_id_vsig(struct ice_hw *hw, enum ice_block blk, u16 vsig, u64 hdl, /* allocate the TCAM entry index */ status = ice_alloc_tcam_ent(hw, blk, &tcam_idx); - if (status) + if (status) { + ice_free(hw, p); goto err_ice_add_prof_id_vsig; + } t->tcam[i].ptg = ptg; t->tcam[i].prof_id = map->prof_id; @@ -4546,11 +4583,6 @@ ice_add_prof_id_vsig(struct ice_hw *hw, enum ice_block blk, u16 vsig, u64 hdl, if (status) goto err_ice_add_prof_id_vsig; - /* this increments the reference count of how many TCAM entries - * are using this HW profile ID - */ - status = ice_prof_inc_ref(hw, blk, t->tcam[i].prof_id); - /* log change */ LIST_ADD(&p->list_entry, chg); } @@ -4563,6 +4595,7 @@ ice_add_prof_id_vsig(struct ice_hw *hw, enum ice_block blk, u16 vsig, u64 hdl, err_ice_add_prof_id_vsig: /* let caller clean up the change list */ + ice_free(hw, t); return ICE_ERR_NO_MEMORY; } @@ -4587,16 +4620,18 @@ ice_create_prof_id_vsig(struct ice_hw *hw, enum ice_block blk, u16 vsi, u64 hdl, return ICE_ERR_NO_MEMORY; new_vsig = ice_vsig_alloc(hw, blk); - if (!new_vsig) - return ICE_ERR_HW_TABLE; + if (!new_vsig) { + status = ICE_ERR_HW_TABLE; + goto err_ice_create_prof_id_vsig; + } status = ice_move_vsi(hw, blk, vsi, new_vsig, chg); if (status) - return status; + goto err_ice_create_prof_id_vsig; status = ice_add_prof_id_vsig(hw, blk, new_vsig, hdl, chg); if (status) - return status; + goto err_ice_create_prof_id_vsig; p->type = ICE_VSIG_ADD; p->vsi = vsi; @@ -4606,6 +4641,11 @@ ice_create_prof_id_vsig(struct ice_hw *hw, enum ice_block blk, u16 vsi, u64 hdl, LIST_ADD(&p->list_entry, chg); return ICE_SUCCESS; + +err_ice_create_prof_id_vsig: + /* let caller clean up the change list */ + ice_free(hw, p); + return status; } /** @@ -4741,14 +4781,13 @@ ice_add_prof_id_flow(struct ice_hw *hw, enum ice_block blk, u16 vsi, u64 hdl) /* search for an existing VSIG with an exact charc match */ status = ice_find_dup_props_vsig(hw, blk, &union_lst, &vsig); if (!status) { - /* found an exact match */ - /* move vsi to the VSIG that matches */ + /* move VSI to the VSIG that matches */ status = ice_move_vsi(hw, blk, vsi, vsig, &chg); if (status) goto err_ice_add_prof_id_flow; - /* remove original VSIG if we just moved the only VSI - * from it + /* VSI has been moved out of or_vsig. If the or_vsig had + * only that VSI it is now empty and can be removed. */ if (only_vsi) { status = ice_rem_vsig(hw, blk, or_vsig, &chg); @@ -4954,8 +4993,8 @@ ice_rem_prof_id_flow(struct ice_hw *hw, enum ice_block blk, u16 vsi, u64 hdl) if (status) goto err_ice_rem_prof_id_flow; - } else if (ice_find_dup_props_vsig(hw, blk, ©, - &vsig)) { + } else if (!ice_find_dup_props_vsig(hw, blk, ©, + &vsig)) { /* found an exact match */ /* add or move VSI to the VSIG that matches */ /* Search for a VSIG with a matching profile