net/ice/base: support DCB
[dpdk.git] / drivers / net / ice / base / ice_flex_pipe.c
index 66c47ab..99108d8 100644 (file)
@@ -1314,7 +1314,7 @@ static void ice_init_pkg_regs(struct ice_hw *hw)
  * ice_copy_and_init_pkg() instead of directly calling ice_init_pkg() in this
  * case.
  */
-static enum ice_status ice_init_pkg(struct ice_hw *hw, u8 *buf, u32 len)
+enum ice_status ice_init_pkg(struct ice_hw *hw, u8 *buf, u32 len)
 {
        struct ice_pkg_hdr *pkg;
        enum ice_status status;
@@ -2247,8 +2247,6 @@ ice_find_dup_props_vsig(struct ice_hw *hw, enum ice_block blk,
        for (i = 0; i < xlt2->count; i++) {
                if (xlt2->vsig_tbl[i].in_use &&
                    ice_match_prop_lst(chs, &xlt2->vsig_tbl[i].prop_lst)) {
-                       *vsig = (i | ((hw->pf_id << ICE_PF_NUM_S) &
-                                     ICE_PF_NUM_M));
                        *vsig = ICE_VSIG_VALUE(i, hw->pf_id);
                        return ICE_SUCCESS;
                }
@@ -2817,6 +2815,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
@@ -2830,31 +2852,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 */
@@ -2937,9 +2943,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) *
@@ -2948,9 +2956,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) *
@@ -2959,9 +2969,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) *
@@ -2970,9 +2982,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) *
@@ -2981,15 +2995,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:
@@ -3130,6 +3148,7 @@ void ice_free_hw_tbls(struct ice_hw *hw)
 
                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);
@@ -3299,6 +3318,9 @@ enum ice_status ice_init_hw_tbls(struct ice_hw *hw)
                es->ref_count = (u16 *)
                        ice_calloc(hw, es->count, sizeof(*es->ref_count));
 
+               es->written = (u8 *)
+                       ice_calloc(hw, es->count, sizeof(*es->written));
+
                if (!es->ref_count)
                        goto err;
 
@@ -3560,8 +3582,7 @@ ice_prof_bld_tcam(struct ice_hw *hw, enum ice_block blk,
        struct ice_chs_chg *tmp;
 
        LIST_FOR_EACH_ENTRY(tmp, chgs, ice_chs_chg, list_entry) {
-               if ((tmp->type == ICE_TCAM_ADD && tmp->add_tcam_idx) ||
-                   tmp->type == ICE_TCAM_REM) {
+               if (tmp->type == ICE_TCAM_ADD && tmp->add_tcam_idx) {
                        struct ice_prof_id_section *p;
                        u32 id;
 
@@ -3691,7 +3712,6 @@ ice_upd_prof_hw(struct ice_hw *hw, enum ice_block blk,
                                es++;
                        break;
                case ICE_TCAM_ADD:
-               case ICE_TCAM_REM:
                        tcam++;
                        break;
                case ICE_VSIG_ADD:
@@ -3797,6 +3817,8 @@ ice_add_prof(struct ice_hw *hw, enum ice_block blk, u64 id, u8 ptypes[],
                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));
@@ -3964,46 +3986,23 @@ ice_rel_tcam_idx(struct ice_hw *hw, enum ice_block blk, u16 idx)
  * ice_rem_prof_id - remove one profile from a VSIG
  * @hw: pointer to the HW struct
  * @blk: hardware block
- * @vsig: VSIG to remove the profile from
  * @prof: pointer to profile structure to remove
- * @chg: pointer to list to record changes
  */
 static enum ice_status
-ice_rem_prof_id(struct ice_hw *hw, enum ice_block blk, u16 vsig,
-               struct ice_vsig_prof *prof, struct LIST_HEAD_TYPE *chg)
+ice_rem_prof_id(struct ice_hw *hw, enum ice_block blk,
+               struct ice_vsig_prof *prof)
 {
        enum ice_status status;
-       struct ice_chs_chg *p;
        u16 i;
 
        for (i = 0; i < prof->tcam_count; i++) {
-               p = (struct ice_chs_chg *)ice_malloc(hw, sizeof(*p));
-               if (!p)
-                       goto err_ice_rem_prof_id;
-
-               p->type = ICE_TCAM_REM;
-               p->vsig = vsig;
-               p->prof_id = prof->tcam[i].prof_id;
-               p->tcam_idx = prof->tcam[i].tcam_idx;
-
-               p->ptg = prof->tcam[i].ptg;
                prof->tcam[i].in_use = false;
-               p->orig_ent = hw->blk[blk].prof.t[p->tcam_idx];
-               status = ice_rel_tcam_idx(hw, blk, p->tcam_idx);
-               if (!status)
-                       status = ice_prof_dec_ref(hw, blk, p->prof_id);
-
-               LIST_ADD(&p->list_entry, chg);
-
+               status = ice_rel_tcam_idx(hw, blk, prof->tcam[i].tcam_idx);
                if (status)
-                       goto err_ice_rem_prof_id;
+                       return ICE_ERR_HW_TABLE;
        }
 
        return ICE_SUCCESS;
-
-err_ice_rem_prof_id:
-       /* caller will clean up the change list */
-       return ICE_ERR_NO_MEMORY;
 }
 
 /**
@@ -4026,9 +4025,9 @@ ice_rem_vsig(struct ice_hw *hw, enum ice_block blk, u16 vsig,
        LIST_FOR_EACH_ENTRY_SAFE(d, t,
                                 &hw->blk[blk].xlt2.vsig_tbl[idx].prop_lst,
                                 ice_vsig_prof, list) {
-               status = ice_rem_prof_id(hw, blk, vsig, d, chg);
+               status = ice_rem_prof_id(hw, blk, d);
                if (status)
-                       goto err_ice_rem_vsig;
+                       return status;
 
                LIST_DEL(&d->list);
                ice_free(hw, d);
@@ -4092,7 +4091,7 @@ ice_rem_prof_id_vsig(struct ice_hw *hw, enum ice_block blk, u16 vsig, u64 hdl,
                                /* this is the last profile, remove the VSIG */
                                return ice_rem_vsig(hw, blk, vsig, chg);
 
-                       status = ice_rem_prof_id(hw, blk, vsig, p, chg);
+                       status = ice_rem_prof_id(hw, blk, p);
                        if (!status) {
                                LIST_DEL(&p->list);
                                ice_free(hw, p);
@@ -4170,6 +4169,9 @@ enum ice_status ice_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 id)
        status = ice_rem_flow_all(hw, blk, pmap->profile_cookie);
        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);
 
@@ -4205,7 +4207,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)
@@ -4216,9 +4218,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);
                }
        }
@@ -4299,17 +4303,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;
        }
@@ -4546,8 +4545,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;
@@ -4569,11 +4570,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);
        }
@@ -4586,6 +4582,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;
 }
 
@@ -4610,16 +4607,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;
@@ -4629,6 +4628,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;
 }
 
 /**
@@ -4977,8 +4981,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, &copy,
-                                                          &vsig)) {
+                       } else if (!ice_find_dup_props_vsig(hw, blk, &copy,
+                                                           &vsig)) {
                                /* found an exact match */
                                /* add or move VSI to the VSIG that matches */
                                /* Search for a VSIG with a matching profile