Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ice: Fix for TCAM entry management

Order intermediate VSIG list correct in order to correctly match existing
VSIG lists.

When overriding pre-existing TCAM entries, properly delete the existing
entry and remove it from the change/update list.

Signed-off-by: Dan Nowlin <dan.nowlin@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>

authored by

Dan Nowlin and committed by
Jeff Kirsher
a6892c96 9d5c5a52

+51 -14
+51 -14
drivers/net/ethernet/intel/ice/ice_flex_pipe.c
··· 3471 3471 } 3472 3472 3473 3473 /** 3474 + * ice_rem_chg_tcam_ent - remove a specific TCAM entry from change list 3475 + * @hw: pointer to the HW struct 3476 + * @idx: the index of the TCAM entry to remove 3477 + * @chg: the list of change structures to search 3478 + */ 3479 + static void 3480 + ice_rem_chg_tcam_ent(struct ice_hw *hw, u16 idx, struct list_head *chg) 3481 + { 3482 + struct ice_chs_chg *pos, *tmp; 3483 + 3484 + list_for_each_entry_safe(tmp, pos, chg, list_entry) 3485 + if (tmp->type == ICE_TCAM_ADD && tmp->tcam_idx == idx) { 3486 + list_del(&tmp->list_entry); 3487 + devm_kfree(ice_hw_to_dev(hw), tmp); 3488 + } 3489 + } 3490 + 3491 + /** 3474 3492 * ice_prof_tcam_ena_dis - add enable or disable TCAM change 3475 3493 * @hw: pointer to the HW struct 3476 3494 * @blk: hardware block ··· 3507 3489 enum ice_status status; 3508 3490 struct ice_chs_chg *p; 3509 3491 3510 - /* Default: enable means change the low flag bit to don't care */ 3511 - u8 dc_msk[ICE_TCAM_KEY_VAL_SZ] = { 0x01, 0x00, 0x00, 0x00, 0x00 }; 3492 + u8 vl_msk[ICE_TCAM_KEY_VAL_SZ] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; 3493 + u8 dc_msk[ICE_TCAM_KEY_VAL_SZ] = { 0xFF, 0xFF, 0x00, 0x00, 0x00 }; 3512 3494 u8 nm_msk[ICE_TCAM_KEY_VAL_SZ] = { 0x00, 0x00, 0x00, 0x00, 0x00 }; 3513 - u8 vl_msk[ICE_TCAM_KEY_VAL_SZ] = { 0x01, 0x00, 0x00, 0x00, 0x00 }; 3514 3495 3515 3496 /* if disabling, free the TCAM */ 3516 3497 if (!enable) { 3517 - status = ice_free_tcam_ent(hw, blk, tcam->tcam_idx); 3498 + status = ice_rel_tcam_idx(hw, blk, tcam->tcam_idx); 3499 + 3500 + /* if we have already created a change for this TCAM entry, then 3501 + * we need to remove that entry, in order to prevent writing to 3502 + * a TCAM entry we no longer will have ownership of. 3503 + */ 3504 + ice_rem_chg_tcam_ent(hw, tcam->tcam_idx, chg); 3518 3505 tcam->tcam_idx = 0; 3519 3506 tcam->in_use = 0; 3520 3507 return status; ··· 3635 3612 * @blk: hardware block 3636 3613 * @vsig: the VSIG to which this profile is to be added 3637 3614 * @hdl: the profile handle indicating the profile to add 3615 + * @rev: true to add entries to the end of the list 3638 3616 * @chg: the change list 3639 3617 */ 3640 3618 static enum ice_status 3641 3619 ice_add_prof_id_vsig(struct ice_hw *hw, enum ice_block blk, u16 vsig, u64 hdl, 3642 - struct list_head *chg) 3620 + bool rev, struct list_head *chg) 3643 3621 { 3644 3622 /* Masks that ignore flags */ 3645 3623 u8 vl_msk[ICE_TCAM_KEY_VAL_SZ] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; ··· 3649 3625 struct ice_prof_map *map; 3650 3626 struct ice_vsig_prof *t; 3651 3627 struct ice_chs_chg *p; 3652 - u16 i; 3628 + u16 vsig_idx, i; 3653 3629 3654 3630 /* Get the details on the profile specified by the handle ID */ 3655 3631 map = ice_search_prof_id(hw, blk, hdl); ··· 3711 3687 } 3712 3688 3713 3689 /* add profile to VSIG */ 3714 - list_add(&t->list, 3715 - &hw->blk[blk].xlt2.vsig_tbl[(vsig & ICE_VSIG_IDX_M)].prop_lst); 3690 + vsig_idx = vsig & ICE_VSIG_IDX_M; 3691 + if (rev) 3692 + list_add_tail(&t->list, 3693 + &hw->blk[blk].xlt2.vsig_tbl[vsig_idx].prop_lst); 3694 + else 3695 + list_add(&t->list, 3696 + &hw->blk[blk].xlt2.vsig_tbl[vsig_idx].prop_lst); 3716 3697 3717 3698 return 0; 3718 3699 ··· 3757 3728 if (status) 3758 3729 goto err_ice_create_prof_id_vsig; 3759 3730 3760 - status = ice_add_prof_id_vsig(hw, blk, new_vsig, hdl, chg); 3731 + status = ice_add_prof_id_vsig(hw, blk, new_vsig, hdl, false, chg); 3761 3732 if (status) 3762 3733 goto err_ice_create_prof_id_vsig; 3763 3734 ··· 3782 3753 * @blk: hardware block 3783 3754 * @vsi: the initial VSI that will be in VSIG 3784 3755 * @lst: the list of profile that will be added to the VSIG 3756 + * @new_vsig: return of new VSIG 3785 3757 * @chg: the change list 3786 3758 */ 3787 3759 static enum ice_status 3788 3760 ice_create_vsig_from_lst(struct ice_hw *hw, enum ice_block blk, u16 vsi, 3789 - struct list_head *lst, struct list_head *chg) 3761 + struct list_head *lst, u16 *new_vsig, 3762 + struct list_head *chg) 3790 3763 { 3791 3764 struct ice_vsig_prof *t; 3792 3765 enum ice_status status; ··· 3803 3772 return status; 3804 3773 3805 3774 list_for_each_entry(t, lst, list) { 3775 + /* Reverse the order here since we are copying the list */ 3806 3776 status = ice_add_prof_id_vsig(hw, blk, vsig, t->profile_cookie, 3807 - chg); 3777 + true, chg); 3808 3778 if (status) 3809 3779 return status; 3810 3780 } 3781 + 3782 + *new_vsig = vsig; 3811 3783 3812 3784 return 0; 3813 3785 } ··· 3933 3899 * not sharing entries and we can simply add the new 3934 3900 * profile to the VSIG. 3935 3901 */ 3936 - status = ice_add_prof_id_vsig(hw, blk, vsig, hdl, &chg); 3902 + status = ice_add_prof_id_vsig(hw, blk, vsig, hdl, false, 3903 + &chg); 3937 3904 if (status) 3938 3905 goto err_ice_add_prof_id_flow; 3939 3906 ··· 3945 3910 } else { 3946 3911 /* No match, so we need a new VSIG */ 3947 3912 status = ice_create_vsig_from_lst(hw, blk, vsi, 3948 - &union_lst, &chg); 3913 + &union_lst, &vsig, 3914 + &chg); 3949 3915 if (status) 3950 3916 goto err_ice_add_prof_id_flow; 3951 3917 ··· 4112 4076 * new VSIG and TCAM entries 4113 4077 */ 4114 4078 status = ice_create_vsig_from_lst(hw, blk, vsi, 4115 - &copy, &chg); 4079 + &copy, &vsig, 4080 + &chg); 4116 4081 if (status) 4117 4082 goto err_ice_rem_prof_id_flow; 4118 4083