if (hw->pkg_copy) {
ice_free(hw, hw->pkg_copy);
hw->pkg_copy = NULL;
+ hw->pkg_size = 0;
}
hw->seg = NULL;
}
* 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;
status = ICE_SUCCESS;
}
- /* Free a previous segment, if necessary */
- ice_free_seg(hw);
if (!status) {
hw->seg = seg;
/* on successful package download, update other required
buf_copy = (u8 *)ice_memdup(hw, buf, len, ICE_NONDMA_TO_NONDMA);
status = ice_init_pkg(hw, buf_copy, len);
- if (status)
+ if (status) {
/* Free the copy, since we failed to initialize the package */
ice_free(hw, buf_copy);
- else
+ } else {
/* Track the copied pkg so we can free it later */
hw->pkg_copy = buf_copy;
+ hw->pkg_size = len;
+ }
return status;
}
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;
}
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
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 */
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) *
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) *
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) *
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) *
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:
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);
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;
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;
es++;
break;
case ICE_TCAM_ADD:
- case ICE_TCAM_REM:
tcam++;
break;
case ICE_VSIG_ADD:
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));
* 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;
}
/**
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);
/* 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);
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);
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)
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);
}
}
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;
}
/* 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;
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);
}
err_ice_add_prof_id_vsig:
/* let caller clean up the change list */
+ ice_free(hw, t);
return ICE_ERR_NO_MEMORY;
}
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;
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;
}
/**
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