Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/ice/ice_flex_pipe.c
Show First 20 Lines • Show All 670 Lines • ▼ Show 20 Lines | |||||
* @dc: array of 8-bit masks that make up the don't care mask | * @dc: array of 8-bit masks that make up the don't care mask | ||||
* @nm: array of 8-bit masks that make up the never match mask | * @nm: array of 8-bit masks that make up the never match mask | ||||
* @off: the offset of the first byte in the key to update | * @off: the offset of the first byte in the key to update | ||||
* @len: the number of bytes in the key update | * @len: the number of bytes in the key update | ||||
* | * | ||||
* This function generates a key from a value, a don't care mask and a never | * This function generates a key from a value, a don't care mask and a never | ||||
* match mask. | * match mask. | ||||
* upd, dc, and nm are optional parameters, and can be NULL: | * upd, dc, and nm are optional parameters, and can be NULL: | ||||
* upd == NULL --> udp mask is all 1's (update all bits) | * upd == NULL --> upd mask is all 1's (update all bits) | ||||
* dc == NULL --> dc mask is all 0's (no don't care bits) | * dc == NULL --> dc mask is all 0's (no don't care bits) | ||||
* nm == NULL --> nm mask is all 0's (no never match bits) | * nm == NULL --> nm mask is all 0's (no never match bits) | ||||
*/ | */ | ||||
enum ice_status | static enum ice_status | ||||
ice_set_key(u8 *key, u16 size, u8 *val, u8 *upd, u8 *dc, u8 *nm, u16 off, | ice_set_key(u8 *key, u16 size, u8 *val, u8 *upd, u8 *dc, u8 *nm, u16 off, | ||||
u16 len) | u16 len) | ||||
{ | { | ||||
u16 half_size; | u16 half_size; | ||||
u16 i; | u16 i; | ||||
/* size must be a multiple of 2 bytes. */ | /* size must be a multiple of 2 bytes. */ | ||||
if (size % 2) | if (size % 2) | ||||
▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | ice_acquire_global_cfg_lock(struct ice_hw *hw, | ||||
enum ice_status status; | enum ice_status status; | ||||
ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); | ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); | ||||
status = ice_acquire_res(hw, ICE_GLOBAL_CFG_LOCK_RES_ID, access, | status = ice_acquire_res(hw, ICE_GLOBAL_CFG_LOCK_RES_ID, access, | ||||
ICE_GLOBAL_CFG_LOCK_TIMEOUT); | ICE_GLOBAL_CFG_LOCK_TIMEOUT); | ||||
if (status == ICE_ERR_AQ_NO_WORK) | if (status == ICE_ERR_AQ_NO_WORK) | ||||
ice_debug(hw, ICE_DBG_PKG, | ice_debug(hw, ICE_DBG_PKG, "Global config lock: No work to do\n"); | ||||
"Global config lock: No work to do\n"); | |||||
return status; | return status; | ||||
} | } | ||||
/** | /** | ||||
* ice_release_global_cfg_lock | * ice_release_global_cfg_lock | ||||
* @hw: pointer to the HW structure | * @hw: pointer to the HW structure | ||||
* | * | ||||
* This function will release the global config lock. | * This function will release the global config lock. | ||||
*/ | */ | ||||
static void ice_release_global_cfg_lock(struct ice_hw *hw) | static void ice_release_global_cfg_lock(struct ice_hw *hw) | ||||
{ | { | ||||
ice_release_res(hw, ICE_GLOBAL_CFG_LOCK_RES_ID); | ice_release_res(hw, ICE_GLOBAL_CFG_LOCK_RES_ID); | ||||
} | } | ||||
/** | /** | ||||
* ice_acquire_change_lock | * ice_acquire_change_lock | ||||
* @hw: pointer to the HW structure | * @hw: pointer to the HW structure | ||||
* @access: access type (read or write) | * @access: access type (read or write) | ||||
* | * | ||||
* This function will request ownership of the change lock. | * This function will request ownership of the change lock. | ||||
*/ | */ | ||||
enum ice_status | static enum ice_status | ||||
ice_acquire_change_lock(struct ice_hw *hw, enum ice_aq_res_access_type access) | ice_acquire_change_lock(struct ice_hw *hw, enum ice_aq_res_access_type access) | ||||
{ | { | ||||
ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); | ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); | ||||
return ice_acquire_res(hw, ICE_CHANGE_LOCK_RES_ID, access, | return ice_acquire_res(hw, ICE_CHANGE_LOCK_RES_ID, access, | ||||
ICE_CHANGE_LOCK_TIMEOUT); | ICE_CHANGE_LOCK_TIMEOUT); | ||||
} | } | ||||
/** | /** | ||||
* ice_release_change_lock | * ice_release_change_lock | ||||
* @hw: pointer to the HW structure | * @hw: pointer to the HW structure | ||||
* | * | ||||
* This function will release the change lock using the proper Admin Command. | * This function will release the change lock using the proper Admin Command. | ||||
*/ | */ | ||||
void ice_release_change_lock(struct ice_hw *hw) | static void ice_release_change_lock(struct ice_hw *hw) | ||||
{ | { | ||||
ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); | ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); | ||||
ice_release_res(hw, ICE_CHANGE_LOCK_RES_ID); | ice_release_res(hw, ICE_CHANGE_LOCK_RES_ID); | ||||
} | } | ||||
/** | /** | ||||
* ice_aq_download_pkg | * ice_aq_download_pkg | ||||
▲ Show 20 Lines • Show All 174 Lines • ▼ Show 20 Lines | ice_update_pkg(struct ice_hw *hw, struct ice_buf *bufs, u32 count) | ||||
for (i = 0; i < count; i++) { | for (i = 0; i < count; i++) { | ||||
struct ice_buf_hdr *bh = (struct ice_buf_hdr *)(bufs + i); | struct ice_buf_hdr *bh = (struct ice_buf_hdr *)(bufs + i); | ||||
bool last = ((i + 1) == count); | bool last = ((i + 1) == count); | ||||
status = ice_aq_update_pkg(hw, bh, LE16_TO_CPU(bh->data_end), | status = ice_aq_update_pkg(hw, bh, LE16_TO_CPU(bh->data_end), | ||||
last, &offset, &info, NULL); | last, &offset, &info, NULL); | ||||
if (status) { | if (status) { | ||||
ice_debug(hw, ICE_DBG_PKG, | ice_debug(hw, ICE_DBG_PKG, "Update pkg failed: err %d off %d inf %d\n", | ||||
"Update pkg failed: err %d off %d inf %d\n", | |||||
status, offset, info); | status, offset, info); | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
ice_release_change_lock(hw); | ice_release_change_lock(hw); | ||||
return status; | return status; | ||||
▲ Show 20 Lines • Show All 61 Lines • ▼ Show 20 Lines | for (i = 0; i < count; i++) { | ||||
bh = (struct ice_buf_hdr *)(bufs + i); | bh = (struct ice_buf_hdr *)(bufs + i); | ||||
status = ice_aq_download_pkg(hw, bh, ICE_PKG_BUF_SIZE, last, | status = ice_aq_download_pkg(hw, bh, ICE_PKG_BUF_SIZE, last, | ||||
&offset, &info, NULL); | &offset, &info, NULL); | ||||
/* Save AQ status from download package */ | /* Save AQ status from download package */ | ||||
hw->pkg_dwnld_status = hw->adminq.sq_last_status; | hw->pkg_dwnld_status = hw->adminq.sq_last_status; | ||||
if (status) { | if (status) { | ||||
ice_debug(hw, ICE_DBG_PKG, | ice_debug(hw, ICE_DBG_PKG, "Pkg download failed: err %d off %d inf %d\n", | ||||
"Pkg download failed: err %d off %d inf %d\n", | |||||
status, offset, info); | status, offset, info); | ||||
break; | break; | ||||
} | } | ||||
if (last) | if (last) | ||||
break; | break; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 81 Lines • ▼ Show 20 Lines | if (meta_seg) { | ||||
ice_memcpy(hw->pkg_name, meta_seg->pkg_name, | ice_memcpy(hw->pkg_name, meta_seg->pkg_name, | ||||
sizeof(hw->pkg_name), ICE_NONDMA_TO_NONDMA); | sizeof(hw->pkg_name), ICE_NONDMA_TO_NONDMA); | ||||
ice_debug(hw, ICE_DBG_PKG, "Pkg: %d.%d.%d.%d, %s\n", | ice_debug(hw, ICE_DBG_PKG, "Pkg: %d.%d.%d.%d, %s\n", | ||||
meta_seg->pkg_ver.major, meta_seg->pkg_ver.minor, | meta_seg->pkg_ver.major, meta_seg->pkg_ver.minor, | ||||
meta_seg->pkg_ver.update, meta_seg->pkg_ver.draft, | meta_seg->pkg_ver.update, meta_seg->pkg_ver.draft, | ||||
meta_seg->pkg_name); | meta_seg->pkg_name); | ||||
} else { | } else { | ||||
ice_debug(hw, ICE_DBG_INIT, | ice_debug(hw, ICE_DBG_INIT, "Did not find metadata segment in driver package\n"); | ||||
"Did not find metadata segment in driver package\n"); | |||||
return ICE_ERR_CFG; | return ICE_ERR_CFG; | ||||
} | } | ||||
seg_hdr = ice_find_seg_in_pkg(hw, SEGMENT_TYPE_ICE, pkg_hdr); | seg_hdr = ice_find_seg_in_pkg(hw, SEGMENT_TYPE_ICE, pkg_hdr); | ||||
if (seg_hdr) { | if (seg_hdr) { | ||||
hw->ice_pkg_ver = seg_hdr->seg_format_ver; | hw->ice_pkg_ver = seg_hdr->seg_format_ver; | ||||
ice_memcpy(hw->ice_pkg_name, seg_hdr->seg_id, | ice_memcpy(hw->ice_pkg_name, seg_hdr->seg_id, | ||||
sizeof(hw->ice_pkg_name), ICE_NONDMA_TO_NONDMA); | sizeof(hw->ice_pkg_name), ICE_NONDMA_TO_NONDMA); | ||||
ice_debug(hw, ICE_DBG_PKG, "Ice Seg: %d.%d.%d.%d, %s\n", | ice_debug(hw, ICE_DBG_PKG, "Ice Seg: %d.%d.%d.%d, %s\n", | ||||
seg_hdr->seg_format_ver.major, | seg_hdr->seg_format_ver.major, | ||||
seg_hdr->seg_format_ver.minor, | seg_hdr->seg_format_ver.minor, | ||||
seg_hdr->seg_format_ver.update, | seg_hdr->seg_format_ver.update, | ||||
seg_hdr->seg_format_ver.draft, | seg_hdr->seg_format_ver.draft, | ||||
seg_hdr->seg_id); | seg_hdr->seg_id); | ||||
} else { | } else { | ||||
ice_debug(hw, ICE_DBG_INIT, | ice_debug(hw, ICE_DBG_INIT, "Did not find ice segment in driver package\n"); | ||||
"Did not find ice segment in driver package\n"); | |||||
return ICE_ERR_CFG; | return ICE_ERR_CFG; | ||||
} | } | ||||
return ICE_SUCCESS; | return ICE_SUCCESS; | ||||
} | } | ||||
/** | /** | ||||
* ice_get_pkg_info | * ice_get_pkg_info | ||||
* @hw: pointer to the hardware structure | * @hw: pointer to the hardware structure | ||||
* | * | ||||
* Store details of the package currently loaded in HW into the HW structure. | * Store details of the package currently loaded in HW into the HW structure. | ||||
*/ | */ | ||||
static enum ice_status ice_get_pkg_info(struct ice_hw *hw) | static enum ice_status ice_get_pkg_info(struct ice_hw *hw) | ||||
{ | { | ||||
struct ice_aqc_get_pkg_info_resp *pkg_info; | struct ice_aqc_get_pkg_info_resp *pkg_info; | ||||
enum ice_status status; | enum ice_status status; | ||||
u16 size; | u16 size; | ||||
u32 i; | u32 i; | ||||
ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); | ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); | ||||
size = ice_struct_size(pkg_info, pkg_info, ICE_PKG_CNT - 1); | size = ice_struct_size(pkg_info, pkg_info, ICE_PKG_CNT); | ||||
pkg_info = (struct ice_aqc_get_pkg_info_resp *)ice_malloc(hw, size); | pkg_info = (struct ice_aqc_get_pkg_info_resp *)ice_malloc(hw, size); | ||||
if (!pkg_info) | if (!pkg_info) | ||||
return ICE_ERR_NO_MEMORY; | return ICE_ERR_NO_MEMORY; | ||||
status = ice_aq_get_pkg_info_list(hw, pkg_info, size, NULL); | status = ice_aq_get_pkg_info_list(hw, pkg_info, size, NULL); | ||||
if (status) | if (status) | ||||
goto init_pkg_free_alloc; | goto init_pkg_free_alloc; | ||||
▲ Show 20 Lines • Show All 79 Lines • ▼ Show 20 Lines | |||||
* Verifies various attributes of the package file, including length, format | * Verifies various attributes of the package file, including length, format | ||||
* version, and the requirement of at least one segment. | * version, and the requirement of at least one segment. | ||||
*/ | */ | ||||
static enum ice_status ice_verify_pkg(struct ice_pkg_hdr *pkg, u32 len) | static enum ice_status ice_verify_pkg(struct ice_pkg_hdr *pkg, u32 len) | ||||
{ | { | ||||
u32 seg_count; | u32 seg_count; | ||||
u32 i; | u32 i; | ||||
if (len < sizeof(*pkg)) | if (len < ice_struct_size(pkg, seg_offset, 1)) | ||||
return ICE_ERR_BUF_TOO_SHORT; | return ICE_ERR_BUF_TOO_SHORT; | ||||
if (pkg->pkg_format_ver.major != ICE_PKG_FMT_VER_MAJ || | if (pkg->pkg_format_ver.major != ICE_PKG_FMT_VER_MAJ || | ||||
pkg->pkg_format_ver.minor != ICE_PKG_FMT_VER_MNR || | pkg->pkg_format_ver.minor != ICE_PKG_FMT_VER_MNR || | ||||
pkg->pkg_format_ver.update != ICE_PKG_FMT_VER_UPD || | pkg->pkg_format_ver.update != ICE_PKG_FMT_VER_UPD || | ||||
pkg->pkg_format_ver.draft != ICE_PKG_FMT_VER_DFT) | pkg->pkg_format_ver.draft != ICE_PKG_FMT_VER_DFT) | ||||
return ICE_ERR_CFG; | return ICE_ERR_CFG; | ||||
/* pkg must have at least one segment */ | /* pkg must have at least one segment */ | ||||
seg_count = LE32_TO_CPU(pkg->seg_count); | seg_count = LE32_TO_CPU(pkg->seg_count); | ||||
if (seg_count < 1) | if (seg_count < 1) | ||||
return ICE_ERR_CFG; | return ICE_ERR_CFG; | ||||
/* make sure segment array fits in package length */ | /* make sure segment array fits in package length */ | ||||
if (len < ice_struct_size(pkg, seg_offset, seg_count - 1)) | if (len < ice_struct_size(pkg, seg_offset, seg_count)) | ||||
return ICE_ERR_BUF_TOO_SHORT; | return ICE_ERR_BUF_TOO_SHORT; | ||||
/* all segments must fit within length */ | /* all segments must fit within length */ | ||||
for (i = 0; i < seg_count; i++) { | for (i = 0; i < seg_count; i++) { | ||||
u32 off = LE32_TO_CPU(pkg->seg_offset[i]); | u32 off = LE32_TO_CPU(pkg->seg_offset[i]); | ||||
struct ice_generic_seg_hdr *seg; | struct ice_generic_seg_hdr *seg; | ||||
/* segment header must fit */ | /* segment header must fit */ | ||||
▲ Show 20 Lines • Show All 90 Lines • ▼ Show 20 Lines | ice_chk_pkg_compat(struct ice_hw *hw, struct ice_pkg_hdr *ospkg, | ||||
*seg = (struct ice_seg *)ice_find_seg_in_pkg(hw, SEGMENT_TYPE_ICE, | *seg = (struct ice_seg *)ice_find_seg_in_pkg(hw, SEGMENT_TYPE_ICE, | ||||
ospkg); | ospkg); | ||||
if (!*seg) { | if (!*seg) { | ||||
ice_debug(hw, ICE_DBG_INIT, "no ice segment in package.\n"); | ice_debug(hw, ICE_DBG_INIT, "no ice segment in package.\n"); | ||||
return ICE_ERR_CFG; | return ICE_ERR_CFG; | ||||
} | } | ||||
/* Check if FW is compatible with the OS package */ | /* Check if FW is compatible with the OS package */ | ||||
size = ice_struct_size(pkg, pkg_info, ICE_PKG_CNT - 1); | size = ice_struct_size(pkg, pkg_info, ICE_PKG_CNT); | ||||
pkg = (struct ice_aqc_get_pkg_info_resp *)ice_malloc(hw, size); | pkg = (struct ice_aqc_get_pkg_info_resp *)ice_malloc(hw, size); | ||||
if (!pkg) | if (!pkg) | ||||
return ICE_ERR_NO_MEMORY; | return ICE_ERR_NO_MEMORY; | ||||
status = ice_aq_get_pkg_info_list(hw, pkg, size, NULL); | status = ice_aq_get_pkg_info_list(hw, pkg, size, NULL); | ||||
if (status) | if (status) | ||||
goto fw_ddp_compat_free_alloc; | goto fw_ddp_compat_free_alloc; | ||||
for (i = 0; i < LE32_TO_CPU(pkg->count); i++) { | for (i = 0; i < LE32_TO_CPU(pkg->count); i++) { | ||||
/* loop till we find the NVM package */ | /* loop till we find the NVM package */ | ||||
if (!pkg->pkg_info[i].is_in_nvm) | if (!pkg->pkg_info[i].is_in_nvm) | ||||
continue; | continue; | ||||
if ((*seg)->hdr.seg_format_ver.major != | if ((*seg)->hdr.seg_format_ver.major != | ||||
pkg->pkg_info[i].ver.major || | pkg->pkg_info[i].ver.major || | ||||
(*seg)->hdr.seg_format_ver.minor > | (*seg)->hdr.seg_format_ver.minor > | ||||
pkg->pkg_info[i].ver.minor) { | pkg->pkg_info[i].ver.minor) { | ||||
status = ICE_ERR_FW_DDP_MISMATCH; | status = ICE_ERR_FW_DDP_MISMATCH; | ||||
ice_debug(hw, ICE_DBG_INIT, | ice_debug(hw, ICE_DBG_INIT, "OS package is not compatible with NVM.\n"); | ||||
"OS package is not compatible with NVM.\n"); | |||||
} | } | ||||
/* done processing NVM package so break */ | /* done processing NVM package so break */ | ||||
break; | break; | ||||
} | } | ||||
fw_ddp_compat_free_alloc: | fw_ddp_compat_free_alloc: | ||||
ice_free(hw, pkg); | ice_free(hw, pkg); | ||||
return status; | return status; | ||||
} | } | ||||
/** | /** | ||||
* ice_sw_fv_handler | |||||
* @sect_type: section type | |||||
* @section: pointer to section | |||||
* @index: index of the field vector entry to be returned | |||||
* @offset: ptr to variable that receives the offset in the field vector table | |||||
* | |||||
* This is a callback function that can be passed to ice_pkg_enum_entry. | |||||
* This function treats the given section as of type ice_sw_fv_section and | |||||
* enumerates offset field. "offset" is an index into the field vector table. | |||||
*/ | |||||
static void * | |||||
ice_sw_fv_handler(u32 sect_type, void *section, u32 index, u32 *offset) | |||||
{ | |||||
struct ice_sw_fv_section *fv_section = | |||||
(struct ice_sw_fv_section *)section; | |||||
if (!section || sect_type != ICE_SID_FLD_VEC_SW) | |||||
return NULL; | |||||
if (index >= LE16_TO_CPU(fv_section->count)) | |||||
return NULL; | |||||
if (offset) | |||||
/* "index" passed in to this function is relative to a given | |||||
* 4k block. To get to the true index into the field vector | |||||
* table need to add the relative index to the base_offset | |||||
* field of this section | |||||
*/ | |||||
*offset = LE16_TO_CPU(fv_section->base_offset) + index; | |||||
return fv_section->fv + index; | |||||
} | |||||
/** | |||||
* ice_get_prof_index_max - get the max profile index for used profile | |||||
* @hw: pointer to the HW struct | |||||
* | |||||
* Calling this function will get the max profile index for used profile | |||||
* and store the index number in struct ice_switch_info *switch_info | |||||
* in hw for following use. | |||||
*/ | |||||
static int ice_get_prof_index_max(struct ice_hw *hw) | |||||
{ | |||||
u16 prof_index = 0, j, max_prof_index = 0; | |||||
struct ice_pkg_enum state; | |||||
struct ice_seg *ice_seg; | |||||
bool flag = false; | |||||
struct ice_fv *fv; | |||||
u32 offset; | |||||
ice_memset(&state, 0, sizeof(state), ICE_NONDMA_MEM); | |||||
if (!hw->seg) | |||||
return ICE_ERR_PARAM; | |||||
ice_seg = hw->seg; | |||||
do { | |||||
fv = (struct ice_fv *) | |||||
ice_pkg_enum_entry(ice_seg, &state, ICE_SID_FLD_VEC_SW, | |||||
&offset, ice_sw_fv_handler); | |||||
if (!fv) | |||||
break; | |||||
ice_seg = NULL; | |||||
/* in the profile that not be used, the prot_id is set to 0xff | |||||
* and the off is set to 0x1ff for all the field vectors. | |||||
*/ | |||||
for (j = 0; j < hw->blk[ICE_BLK_SW].es.fvw; j++) | |||||
if (fv->ew[j].prot_id != ICE_PROT_INVALID || | |||||
fv->ew[j].off != ICE_FV_OFFSET_INVAL) | |||||
flag = true; | |||||
if (flag && prof_index > max_prof_index) | |||||
max_prof_index = prof_index; | |||||
prof_index++; | |||||
flag = false; | |||||
} while (fv); | |||||
hw->switch_info->max_used_prof_index = max_prof_index; | |||||
return ICE_SUCCESS; | |||||
} | |||||
/** | |||||
* ice_init_pkg - initialize/download package | * ice_init_pkg - initialize/download package | ||||
* @hw: pointer to the hardware structure | * @hw: pointer to the hardware structure | ||||
* @buf: pointer to the package buffer | * @buf: pointer to the package buffer | ||||
* @len: size of the package buffer | * @len: size of the package buffer | ||||
* | * | ||||
* This function initializes a package. The package contains HW tables | * This function initializes a package. The package contains HW tables | ||||
* required to do packet processing. First, the function extracts package | * required to do packet processing. First, the function extracts package | ||||
* information such as version. Then it finds the ice configuration segment | * information such as version. Then it finds the ice configuration segment | ||||
▲ Show 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | enum ice_status ice_init_pkg(struct ice_hw *hw, u8 *buf, u32 len) | ||||
status = ice_chk_pkg_compat(hw, pkg, &seg); | status = ice_chk_pkg_compat(hw, pkg, &seg); | ||||
if (status) | if (status) | ||||
return status; | return status; | ||||
/* initialize package hints and then download package */ | /* initialize package hints and then download package */ | ||||
ice_init_pkg_hints(hw, seg); | ice_init_pkg_hints(hw, seg); | ||||
status = ice_download_pkg(hw, seg); | status = ice_download_pkg(hw, seg); | ||||
if (status == ICE_ERR_AQ_NO_WORK) { | if (status == ICE_ERR_AQ_NO_WORK) { | ||||
ice_debug(hw, ICE_DBG_INIT, | ice_debug(hw, ICE_DBG_INIT, "package previously loaded - no work.\n"); | ||||
"package previously loaded - no work.\n"); | |||||
status = ICE_SUCCESS; | status = ICE_SUCCESS; | ||||
} | } | ||||
/* Get information on the package currently loaded in HW, then make sure | /* Get information on the package currently loaded in HW, then make sure | ||||
* the driver is compatible with this version. | * the driver is compatible with this version. | ||||
*/ | */ | ||||
if (!status) { | if (!status) { | ||||
status = ice_get_pkg_info(hw); | status = ice_get_pkg_info(hw); | ||||
if (!status) | if (!status) | ||||
status = ice_chk_pkg_version(&hw->active_pkg_ver); | status = ice_chk_pkg_version(&hw->active_pkg_ver); | ||||
} | } | ||||
if (!status) { | if (!status) { | ||||
hw->seg = seg; | hw->seg = seg; | ||||
/* on successful package download update other required | /* on successful package download update other required | ||||
* registers to support the package and fill HW tables | * registers to support the package and fill HW tables | ||||
* with package content. | * with package content. | ||||
*/ | */ | ||||
ice_init_pkg_regs(hw); | ice_init_pkg_regs(hw); | ||||
ice_fill_blk_tbls(hw); | ice_fill_blk_tbls(hw); | ||||
ice_get_prof_index_max(hw); | |||||
} else { | } else { | ||||
ice_debug(hw, ICE_DBG_INIT, "package load failed, %d\n", | ice_debug(hw, ICE_DBG_INIT, "package load failed, %d\n", | ||||
status); | status); | ||||
} | } | ||||
return status; | return status; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 61 Lines • ▼ Show 20 Lines | static struct ice_buf_build *ice_pkg_buf_alloc(struct ice_hw *hw) | ||||
buf = (struct ice_buf_hdr *)bld; | buf = (struct ice_buf_hdr *)bld; | ||||
buf->data_end = CPU_TO_LE16(offsetof(struct ice_buf_hdr, | buf->data_end = CPU_TO_LE16(offsetof(struct ice_buf_hdr, | ||||
section_entry)); | section_entry)); | ||||
return bld; | return bld; | ||||
} | } | ||||
/** | /** | ||||
* ice_sw_fv_handler | |||||
* @sect_type: section type | |||||
* @section: pointer to section | |||||
* @index: index of the field vector entry to be returned | |||||
* @offset: ptr to variable that receives the offset in the field vector table | |||||
* | |||||
* This is a callback function that can be passed to ice_pkg_enum_entry. | |||||
* This function treats the given section as of type ice_sw_fv_section and | |||||
* enumerates offset field. "offset" is an index into the field vector | |||||
* vector table. | |||||
*/ | |||||
static void * | |||||
ice_sw_fv_handler(u32 sect_type, void *section, u32 index, u32 *offset) | |||||
{ | |||||
struct ice_sw_fv_section *fv_section = | |||||
(struct ice_sw_fv_section *)section; | |||||
if (!section || sect_type != ICE_SID_FLD_VEC_SW) | |||||
return NULL; | |||||
if (index >= LE16_TO_CPU(fv_section->count)) | |||||
return NULL; | |||||
if (offset) | |||||
/* "index" passed in to this function is relative to a given | |||||
* 4k block. To get to the true index into the field vector | |||||
* table need to add the relative index to the base_offset | |||||
* field of this section | |||||
*/ | |||||
*offset = LE16_TO_CPU(fv_section->base_offset) + index; | |||||
return fv_section->fv + index; | |||||
} | |||||
/** | |||||
* ice_get_sw_prof_type - determine switch profile type | * ice_get_sw_prof_type - determine switch profile type | ||||
* @hw: pointer to the HW structure | * @hw: pointer to the HW structure | ||||
* @fv: pointer to the switch field vector | * @fv: pointer to the switch field vector | ||||
*/ | */ | ||||
static enum ice_prof_type | static enum ice_prof_type | ||||
ice_get_sw_prof_type(struct ice_hw *hw, struct ice_fv *fv) | ice_get_sw_prof_type(struct ice_hw *hw, struct ice_fv *fv) | ||||
{ | { | ||||
u16 i; | u16 i; | ||||
Show All 21 Lines | |||||
void | void | ||||
ice_get_sw_fv_bitmap(struct ice_hw *hw, enum ice_prof_type req_profs, | ice_get_sw_fv_bitmap(struct ice_hw *hw, enum ice_prof_type req_profs, | ||||
ice_bitmap_t *bm) | ice_bitmap_t *bm) | ||||
{ | { | ||||
struct ice_pkg_enum state; | struct ice_pkg_enum state; | ||||
struct ice_seg *ice_seg; | struct ice_seg *ice_seg; | ||||
struct ice_fv *fv; | struct ice_fv *fv; | ||||
ice_memset(&state, 0, sizeof(state), ICE_NONDMA_MEM); | |||||
if (req_profs == ICE_PROF_ALL) { | if (req_profs == ICE_PROF_ALL) { | ||||
u16 i; | ice_bitmap_set(bm, 0, ICE_MAX_NUM_PROFILES); | ||||
for (i = 0; i < ICE_MAX_NUM_PROFILES; i++) | |||||
ice_set_bit(i, bm); | |||||
return; | return; | ||||
} | } | ||||
ice_memset(&state, 0, sizeof(state), ICE_NONDMA_MEM); | |||||
ice_zero_bitmap(bm, ICE_MAX_NUM_PROFILES); | ice_zero_bitmap(bm, ICE_MAX_NUM_PROFILES); | ||||
ice_seg = hw->seg; | ice_seg = hw->seg; | ||||
do { | do { | ||||
enum ice_prof_type prof_type; | enum ice_prof_type prof_type; | ||||
u32 offset; | u32 offset; | ||||
fv = (struct ice_fv *) | fv = (struct ice_fv *) | ||||
ice_pkg_enum_entry(ice_seg, &state, ICE_SID_FLD_VEC_SW, | ice_pkg_enum_entry(ice_seg, &state, ICE_SID_FLD_VEC_SW, | ||||
&offset, ice_sw_fv_handler); | &offset, ice_sw_fv_handler); | ||||
▲ Show 20 Lines • Show All 538 Lines • ▼ Show 20 Lines | ice_create_tunnel(struct ice_hw *hw, enum ice_tunnel_type type, u16 port) | ||||
} | } | ||||
/* allocate 2 sections, one for Rx parser, one for Tx parser */ | /* allocate 2 sections, one for Rx parser, one for Tx parser */ | ||||
if (ice_pkg_buf_reserve_section(bld, 2)) | if (ice_pkg_buf_reserve_section(bld, 2)) | ||||
goto ice_create_tunnel_err; | goto ice_create_tunnel_err; | ||||
sect_rx = (struct ice_boost_tcam_section *) | sect_rx = (struct ice_boost_tcam_section *) | ||||
ice_pkg_buf_alloc_section(bld, ICE_SID_RXPARSER_BOOST_TCAM, | ice_pkg_buf_alloc_section(bld, ICE_SID_RXPARSER_BOOST_TCAM, | ||||
sizeof(*sect_rx)); | ice_struct_size(sect_rx, tcam, 1)); | ||||
if (!sect_rx) | if (!sect_rx) | ||||
goto ice_create_tunnel_err; | goto ice_create_tunnel_err; | ||||
sect_rx->count = CPU_TO_LE16(1); | sect_rx->count = CPU_TO_LE16(1); | ||||
sect_tx = (struct ice_boost_tcam_section *) | sect_tx = (struct ice_boost_tcam_section *) | ||||
ice_pkg_buf_alloc_section(bld, ICE_SID_TXPARSER_BOOST_TCAM, | ice_pkg_buf_alloc_section(bld, ICE_SID_TXPARSER_BOOST_TCAM, | ||||
sizeof(*sect_tx)); | ice_struct_size(sect_tx, tcam, 1)); | ||||
if (!sect_tx) | if (!sect_tx) | ||||
goto ice_create_tunnel_err; | goto ice_create_tunnel_err; | ||||
sect_tx->count = CPU_TO_LE16(1); | sect_tx->count = CPU_TO_LE16(1); | ||||
/* copy original boost entry to update package buffer */ | /* copy original boost entry to update package buffer */ | ||||
ice_memcpy(sect_rx->tcam, hw->tnl.tbl[index].boost_entry, | ice_memcpy(sect_rx->tcam, hw->tnl.tbl[index].boost_entry, | ||||
sizeof(*sect_rx->tcam), ICE_NONDMA_TO_NONDMA); | sizeof(*sect_rx->tcam), ICE_NONDMA_TO_NONDMA); | ||||
▲ Show 20 Lines • Show All 61 Lines • ▼ Show 20 Lines | if (hw->tnl.tbl[i].valid && hw->tnl.tbl[i].in_use && | ||||
count++; | count++; | ||||
if (!count) { | if (!count) { | ||||
status = ICE_ERR_PARAM; | status = ICE_ERR_PARAM; | ||||
goto ice_destroy_tunnel_end; | goto ice_destroy_tunnel_end; | ||||
} | } | ||||
/* size of section - there is at least one entry */ | /* size of section - there is at least one entry */ | ||||
size = ice_struct_size(sect_rx, tcam, count - 1); | size = ice_struct_size(sect_rx, tcam, count); | ||||
bld = ice_pkg_buf_alloc(hw); | bld = ice_pkg_buf_alloc(hw); | ||||
if (!bld) { | if (!bld) { | ||||
status = ICE_ERR_NO_MEMORY; | status = ICE_ERR_NO_MEMORY; | ||||
goto ice_destroy_tunnel_end; | goto ice_destroy_tunnel_end; | ||||
} | } | ||||
/* allocate 2 sections, one for Rx parser, one for Tx parser */ | /* allocate 2 sections, one for Rx parser, one for Tx parser */ | ||||
▲ Show 20 Lines • Show All 73 Lines • ▼ Show 20 Lines | if (!hw->tnl.tbl[i].in_use) | ||||
continue; | continue; | ||||
/* Replay tunnels one at a time by destroying them, then | /* Replay tunnels one at a time by destroying them, then | ||||
* recreating them | * recreating them | ||||
*/ | */ | ||||
hw->tnl.tbl[i].ref = 1; /* make sure to destroy in one call */ | hw->tnl.tbl[i].ref = 1; /* make sure to destroy in one call */ | ||||
status = ice_destroy_tunnel(hw, port, false); | status = ice_destroy_tunnel(hw, port, false); | ||||
if (status) { | if (status) { | ||||
ice_debug(hw, ICE_DBG_PKG, | ice_debug(hw, ICE_DBG_PKG, "ERR: 0x%x - destroy tunnel port 0x%x\n", | ||||
"ERR: 0x%x - destroy tunnel port 0x%x\n", | |||||
status, port); | status, port); | ||||
break; | break; | ||||
} | } | ||||
status = ice_create_tunnel(hw, type, port); | status = ice_create_tunnel(hw, type, port); | ||||
if (status) { | if (status) { | ||||
ice_debug(hw, ICE_DBG_PKG, | ice_debug(hw, ICE_DBG_PKG, "ERR: 0x%x - create tunnel port 0x%x\n", | ||||
"ERR: 0x%x - create tunnel port 0x%x\n", | |||||
status, port); | status, port); | ||||
break; | break; | ||||
} | } | ||||
/* reset to original ref count */ | /* reset to original ref count */ | ||||
hw->tnl.tbl[i].ref = refs; | hw->tnl.tbl[i].ref = refs; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | |||||
enum ice_status ice_ptg_update_xlt1(struct ice_hw *hw, enum ice_block blk) | enum ice_status ice_ptg_update_xlt1(struct ice_hw *hw, enum ice_block blk) | ||||
{ | { | ||||
struct ice_xlt1_section *sect; | struct ice_xlt1_section *sect; | ||||
struct ice_buf_build *bld; | struct ice_buf_build *bld; | ||||
enum ice_status status; | enum ice_status status; | ||||
u16 index; | u16 index; | ||||
bld = ice_pkg_buf_alloc_single_section(hw, ice_sect_id(blk, ICE_XLT1), | bld = ice_pkg_buf_alloc_single_section(hw, ice_sect_id(blk, ICE_XLT1), | ||||
ICE_XLT1_SIZE(ICE_XLT1_CNT), | ice_struct_size(sect, value, | ||||
ICE_XLT1_CNT), | |||||
(void **)§); | (void **)§); | ||||
if (!bld) | if (!bld) | ||||
return ICE_ERR_NO_MEMORY; | return ICE_ERR_NO_MEMORY; | ||||
sect->count = CPU_TO_LE16(ICE_XLT1_CNT); | sect->count = CPU_TO_LE16(ICE_XLT1_CNT); | ||||
sect->offset = CPU_TO_LE16(0); | sect->offset = CPU_TO_LE16(0); | ||||
for (index = 0; index < ICE_XLT1_CNT; index++) | for (index = 0; index < ICE_XLT1_CNT; index++) | ||||
sect->value[index] = hw->blk[blk].xlt1.ptypes[index].ptg; | sect->value[index] = hw->blk[blk].xlt1.ptypes[index].ptg; | ||||
▲ Show 20 Lines • Show All 225 Lines • ▼ Show 20 Lines | |||||
ice_match_prop_lst(struct LIST_HEAD_TYPE *list1, struct LIST_HEAD_TYPE *list2) | ice_match_prop_lst(struct LIST_HEAD_TYPE *list1, struct LIST_HEAD_TYPE *list2) | ||||
{ | { | ||||
struct ice_vsig_prof *tmp1; | struct ice_vsig_prof *tmp1; | ||||
struct ice_vsig_prof *tmp2; | struct ice_vsig_prof *tmp2; | ||||
u16 chk_count = 0; | u16 chk_count = 0; | ||||
u16 count = 0; | u16 count = 0; | ||||
/* compare counts */ | /* compare counts */ | ||||
LIST_FOR_EACH_ENTRY(tmp1, list1, ice_vsig_prof, list) { | LIST_FOR_EACH_ENTRY(tmp1, list1, ice_vsig_prof, list) | ||||
count++; | count++; | ||||
} | LIST_FOR_EACH_ENTRY(tmp2, list2, ice_vsig_prof, list) | ||||
LIST_FOR_EACH_ENTRY(tmp2, list2, ice_vsig_prof, list) { | |||||
chk_count++; | chk_count++; | ||||
} | |||||
if (!count || count != chk_count) | if (!count || count != chk_count) | ||||
return false; | return false; | ||||
tmp1 = LIST_FIRST_ENTRY(list1, struct ice_vsig_prof, list); | tmp1 = LIST_FIRST_ENTRY(list1, struct ice_vsig_prof, list); | ||||
tmp2 = LIST_FIRST_ENTRY(list2, struct ice_vsig_prof, list); | tmp2 = LIST_FIRST_ENTRY(list2, struct ice_vsig_prof, list); | ||||
/* profile cookies must compare, and in the exact same order to take | /* profile cookies must compare, and in the exact same order to take | ||||
* into account priority | * into account priority | ||||
Show All 25 Lines | |||||
ice_vsig_update_xlt2_sect(struct ice_hw *hw, enum ice_block blk, u16 vsi, | ice_vsig_update_xlt2_sect(struct ice_hw *hw, enum ice_block blk, u16 vsi, | ||||
u16 vsig) | u16 vsig) | ||||
{ | { | ||||
struct ice_xlt2_section *sect; | struct ice_xlt2_section *sect; | ||||
struct ice_buf_build *bld; | struct ice_buf_build *bld; | ||||
enum ice_status status; | enum ice_status status; | ||||
bld = ice_pkg_buf_alloc_single_section(hw, ice_sect_id(blk, ICE_XLT2), | bld = ice_pkg_buf_alloc_single_section(hw, ice_sect_id(blk, ICE_XLT2), | ||||
sizeof(struct ice_xlt2_section), | ice_struct_size(sect, value, 1), | ||||
(void **)§); | (void **)§); | ||||
if (!bld) | if (!bld) | ||||
return ICE_ERR_NO_MEMORY; | return ICE_ERR_NO_MEMORY; | ||||
sect->count = CPU_TO_LE16(1); | sect->count = CPU_TO_LE16(1); | ||||
sect->offset = CPU_TO_LE16(vsi); | sect->offset = CPU_TO_LE16(vsi); | ||||
sect->value[0] = CPU_TO_LE16(vsig); | sect->value[0] = CPU_TO_LE16(vsig); | ||||
▲ Show 20 Lines • Show All 115 Lines • ▼ Show 20 Lines | |||||
*/ | */ | ||||
static enum ice_status | static enum ice_status | ||||
ice_find_dup_props_vsig(struct ice_hw *hw, enum ice_block blk, | ice_find_dup_props_vsig(struct ice_hw *hw, enum ice_block blk, | ||||
struct LIST_HEAD_TYPE *chs, u16 *vsig) | struct LIST_HEAD_TYPE *chs, u16 *vsig) | ||||
{ | { | ||||
struct ice_xlt2 *xlt2 = &hw->blk[blk].xlt2; | struct ice_xlt2 *xlt2 = &hw->blk[blk].xlt2; | ||||
u16 i; | u16 i; | ||||
for (i = 0; i < xlt2->count; i++) { | for (i = 0; i < xlt2->count; i++) | ||||
if (xlt2->vsig_tbl[i].in_use && | if (xlt2->vsig_tbl[i].in_use && | ||||
ice_match_prop_lst(chs, &xlt2->vsig_tbl[i].prop_lst)) { | ice_match_prop_lst(chs, &xlt2->vsig_tbl[i].prop_lst)) { | ||||
*vsig = ICE_VSIG_VALUE(i, hw->pf_id); | *vsig = ICE_VSIG_VALUE(i, hw->pf_id); | ||||
return ICE_SUCCESS; | return ICE_SUCCESS; | ||||
} | } | ||||
} | |||||
return ICE_ERR_DOES_NOT_EXIST; | return ICE_ERR_DOES_NOT_EXIST; | ||||
} | } | ||||
/** | /** | ||||
* ice_vsig_free - free VSI group | * ice_vsig_free - free VSI group | ||||
* @hw: pointer to the hardware structure | * @hw: pointer to the hardware structure | ||||
* @blk: HW block | * @blk: HW block | ||||
▲ Show 20 Lines • Show All 203 Lines • ▼ Show 20 Lines | |||||
/** | /** | ||||
* ice_prof_id_rsrc_type - get profile ID resource type for a block type | * ice_prof_id_rsrc_type - get profile ID resource type for a block type | ||||
* @blk: the block type | * @blk: the block type | ||||
* @rsrc_type: pointer to variable to receive the resource type | * @rsrc_type: pointer to variable to receive the resource type | ||||
*/ | */ | ||||
static bool ice_prof_id_rsrc_type(enum ice_block blk, u16 *rsrc_type) | static bool ice_prof_id_rsrc_type(enum ice_block blk, u16 *rsrc_type) | ||||
{ | { | ||||
switch (blk) { | switch (blk) { | ||||
case ICE_BLK_SW: | |||||
*rsrc_type = ICE_AQC_RES_TYPE_SWITCH_PROF_BLDR_PROFID; | |||||
break; | |||||
case ICE_BLK_ACL: | |||||
*rsrc_type = ICE_AQC_RES_TYPE_ACL_PROF_BLDR_PROFID; | |||||
break; | |||||
case ICE_BLK_FD: | |||||
*rsrc_type = ICE_AQC_RES_TYPE_FD_PROF_BLDR_PROFID; | |||||
break; | |||||
case ICE_BLK_RSS: | case ICE_BLK_RSS: | ||||
*rsrc_type = ICE_AQC_RES_TYPE_HASH_PROF_BLDR_PROFID; | *rsrc_type = ICE_AQC_RES_TYPE_HASH_PROF_BLDR_PROFID; | ||||
break; | break; | ||||
case ICE_BLK_PE: | case ICE_BLK_PE: | ||||
*rsrc_type = ICE_AQC_RES_TYPE_QHASH_PROF_BLDR_PROFID; | *rsrc_type = ICE_AQC_RES_TYPE_QHASH_PROF_BLDR_PROFID; | ||||
break; | break; | ||||
default: | default: | ||||
return false; | return false; | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
/** | /** | ||||
* ice_tcam_ent_rsrc_type - get TCAM entry resource type for a block type | * ice_tcam_ent_rsrc_type - get TCAM entry resource type for a block type | ||||
* @blk: the block type | * @blk: the block type | ||||
* @rsrc_type: pointer to variable to receive the resource type | * @rsrc_type: pointer to variable to receive the resource type | ||||
*/ | */ | ||||
static bool ice_tcam_ent_rsrc_type(enum ice_block blk, u16 *rsrc_type) | static bool ice_tcam_ent_rsrc_type(enum ice_block blk, u16 *rsrc_type) | ||||
{ | { | ||||
switch (blk) { | switch (blk) { | ||||
case ICE_BLK_SW: | |||||
*rsrc_type = ICE_AQC_RES_TYPE_SWITCH_PROF_BLDR_TCAM; | |||||
break; | |||||
case ICE_BLK_ACL: | |||||
*rsrc_type = ICE_AQC_RES_TYPE_ACL_PROF_BLDR_TCAM; | |||||
break; | |||||
case ICE_BLK_FD: | |||||
*rsrc_type = ICE_AQC_RES_TYPE_FD_PROF_BLDR_TCAM; | |||||
break; | |||||
case ICE_BLK_RSS: | case ICE_BLK_RSS: | ||||
*rsrc_type = ICE_AQC_RES_TYPE_HASH_PROF_BLDR_TCAM; | *rsrc_type = ICE_AQC_RES_TYPE_HASH_PROF_BLDR_TCAM; | ||||
break; | break; | ||||
case ICE_BLK_PE: | case ICE_BLK_PE: | ||||
*rsrc_type = ICE_AQC_RES_TYPE_QHASH_PROF_BLDR_TCAM; | *rsrc_type = ICE_AQC_RES_TYPE_QHASH_PROF_BLDR_TCAM; | ||||
break; | break; | ||||
default: | default: | ||||
return false; | return false; | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
/** | /** | ||||
* ice_alloc_tcam_ent - allocate hardware TCAM entry | * ice_alloc_tcam_ent - allocate hardware TCAM entry | ||||
* @hw: pointer to the HW struct | * @hw: pointer to the HW struct | ||||
* @blk: the block to allocate the TCAM for | * @blk: the block to allocate the TCAM for | ||||
* @btm: true to allocate from bottom of table, false to allocate from top | |||||
* @tcam_idx: pointer to variable to receive the TCAM entry | * @tcam_idx: pointer to variable to receive the TCAM entry | ||||
* | * | ||||
* This function allocates a new entry in a Profile ID TCAM for a specific | * This function allocates a new entry in a Profile ID TCAM for a specific | ||||
* block. | * block. | ||||
*/ | */ | ||||
static enum ice_status | static enum ice_status | ||||
ice_alloc_tcam_ent(struct ice_hw *hw, enum ice_block blk, u16 *tcam_idx) | ice_alloc_tcam_ent(struct ice_hw *hw, enum ice_block blk, bool btm, | ||||
u16 *tcam_idx) | |||||
{ | { | ||||
u16 res_type; | u16 res_type; | ||||
if (!ice_tcam_ent_rsrc_type(blk, &res_type)) | if (!ice_tcam_ent_rsrc_type(blk, &res_type)) | ||||
return ICE_ERR_PARAM; | return ICE_ERR_PARAM; | ||||
return ice_alloc_hw_res(hw, res_type, 1, true, tcam_idx); | return ice_alloc_hw_res(hw, res_type, 1, btm, tcam_idx); | ||||
} | } | ||||
/** | /** | ||||
* ice_free_tcam_ent - free hardware TCAM entry | * ice_free_tcam_ent - free hardware TCAM entry | ||||
* @hw: pointer to the HW struct | * @hw: pointer to the HW struct | ||||
* @blk: the block from which to free the TCAM entry | * @blk: the block from which to free the TCAM entry | ||||
* @tcam_idx: the TCAM entry to free | * @tcam_idx: the TCAM entry to free | ||||
* | * | ||||
▲ Show 20 Lines • Show All 402 Lines • ▼ Show 20 Lines | |||||
*/ | */ | ||||
static void ice_free_flow_profs(struct ice_hw *hw, u8 blk_idx) | static void ice_free_flow_profs(struct ice_hw *hw, u8 blk_idx) | ||||
{ | { | ||||
struct ice_flow_prof *p, *tmp; | struct ice_flow_prof *p, *tmp; | ||||
ice_acquire_lock(&hw->fl_profs_locks[blk_idx]); | ice_acquire_lock(&hw->fl_profs_locks[blk_idx]); | ||||
LIST_FOR_EACH_ENTRY_SAFE(p, tmp, &hw->fl_profs[blk_idx], | LIST_FOR_EACH_ENTRY_SAFE(p, tmp, &hw->fl_profs[blk_idx], | ||||
ice_flow_prof, l_entry) { | ice_flow_prof, l_entry) { | ||||
struct ice_flow_entry *e, *t; | |||||
LIST_FOR_EACH_ENTRY_SAFE(e, t, &p->entries, | |||||
ice_flow_entry, l_entry) | |||||
ice_flow_rem_entry(hw, (enum ice_block)blk_idx, | |||||
ICE_FLOW_ENTRY_HNDL(e)); | |||||
LIST_DEL(&p->l_entry); | LIST_DEL(&p->l_entry); | ||||
if (p->acts) | |||||
ice_free(hw, p->acts); | |||||
ice_free(hw, p); | ice_free(hw, p); | ||||
} | } | ||||
ice_release_lock(&hw->fl_profs_locks[blk_idx]); | ice_release_lock(&hw->fl_profs_locks[blk_idx]); | ||||
/* if driver is in reset and tables are being cleared | /* if driver is in reset and tables are being cleared | ||||
* re-initialize the flow profile list heads | * re-initialize the flow profile list heads | ||||
*/ | */ | ||||
INIT_LIST_HEAD(&hw->fl_profs[blk_idx]); | INIT_LIST_HEAD(&hw->fl_profs[blk_idx]); | ||||
▲ Show 20 Lines • Show All 110 Lines • ▼ Show 20 Lines | ice_memset(xlt2->t, 0, xlt2->count * sizeof(*xlt2->t), | ||||
ICE_NONDMA_MEM); | ICE_NONDMA_MEM); | ||||
ice_memset(prof->t, 0, prof->count * sizeof(*prof->t), | ice_memset(prof->t, 0, prof->count * sizeof(*prof->t), | ||||
ICE_NONDMA_MEM); | ICE_NONDMA_MEM); | ||||
ice_memset(prof_redir->t, 0, | ice_memset(prof_redir->t, 0, | ||||
prof_redir->count * sizeof(*prof_redir->t), | prof_redir->count * sizeof(*prof_redir->t), | ||||
ICE_NONDMA_MEM); | ICE_NONDMA_MEM); | ||||
ice_memset(es->t, 0, es->count * sizeof(*es->t), | ice_memset(es->t, 0, es->count * sizeof(*es->t) * es->fvw, | ||||
ICE_NONDMA_MEM); | ICE_NONDMA_MEM); | ||||
ice_memset(es->ref_count, 0, es->count * sizeof(*es->ref_count), | ice_memset(es->ref_count, 0, es->count * sizeof(*es->ref_count), | ||||
ICE_NONDMA_MEM); | ICE_NONDMA_MEM); | ||||
ice_memset(es->written, 0, es->count * sizeof(*es->written), | ice_memset(es->written, 0, es->count * sizeof(*es->written), | ||||
ICE_NONDMA_MEM); | ICE_NONDMA_MEM); | ||||
} | } | ||||
} | } | ||||
▲ Show 20 Lines • Show All 91 Lines • ▼ Show 20 Lines | es->t = (struct ice_fv_word *) | ||||
ice_calloc(hw, (u32)(es->count * es->fvw), | ice_calloc(hw, (u32)(es->count * es->fvw), | ||||
sizeof(*es->t)); | sizeof(*es->t)); | ||||
if (!es->t) | if (!es->t) | ||||
goto err; | goto err; | ||||
es->ref_count = (u16 *) | es->ref_count = (u16 *) | ||||
ice_calloc(hw, es->count, sizeof(*es->ref_count)); | ice_calloc(hw, es->count, sizeof(*es->ref_count)); | ||||
if (!es->ref_count) | |||||
goto err; | |||||
es->written = (u8 *) | es->written = (u8 *) | ||||
ice_calloc(hw, es->count, sizeof(*es->written)); | ice_calloc(hw, es->count, sizeof(*es->written)); | ||||
if (!es->ref_count) | |||||
if (!es->written) | |||||
goto err; | goto err; | ||||
} | } | ||||
return ICE_SUCCESS; | return ICE_SUCCESS; | ||||
err: | err: | ||||
ice_free_hw_tbls(hw); | ice_free_hw_tbls(hw); | ||||
return ICE_ERR_NO_MEMORY; | return ICE_ERR_NO_MEMORY; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 55 Lines • ▼ Show 20 Lines | |||||
/** | /** | ||||
* ice_tcam_write_entry - write TCAM entry | * ice_tcam_write_entry - write TCAM entry | ||||
* @hw: pointer to the HW struct | * @hw: pointer to the HW struct | ||||
* @blk: the block in which to write profile ID to | * @blk: the block in which to write profile ID to | ||||
* @idx: the entry index to write to | * @idx: the entry index to write to | ||||
* @prof_id: profile ID | * @prof_id: profile ID | ||||
* @ptg: packet type group (PTG) portion of key | * @ptg: packet type group (PTG) portion of key | ||||
* @vsig: VSIG portion of key | * @vsig: VSIG portion of key | ||||
* @cdid: CDID: portion of key | * @cdid: CDID portion of key | ||||
* @flags: flag portion of key | * @flags: flag portion of key | ||||
* @vl_msk: valid mask | * @vl_msk: valid mask | ||||
* @dc_msk: don't care mask | * @dc_msk: don't care mask | ||||
* @nm_msk: never match mask | * @nm_msk: never match mask | ||||
*/ | */ | ||||
static enum ice_status | static enum ice_status | ||||
ice_tcam_write_entry(struct ice_hw *hw, enum ice_block blk, u16 idx, | ice_tcam_write_entry(struct ice_hw *hw, enum ice_block blk, u16 idx, | ||||
u8 prof_id, u8 ptg, u16 vsig, u8 cdid, u16 flags, | u8 prof_id, u8 ptg, u16 vsig, u8 cdid, u16 flags, | ||||
▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | |||||
*/ | */ | ||||
static bool | static bool | ||||
ice_has_prof_vsig(struct ice_hw *hw, enum ice_block blk, u16 vsig, u64 hdl) | ice_has_prof_vsig(struct ice_hw *hw, enum ice_block blk, u16 vsig, u64 hdl) | ||||
{ | { | ||||
u16 idx = vsig & ICE_VSIG_IDX_M; | u16 idx = vsig & ICE_VSIG_IDX_M; | ||||
struct ice_vsig_prof *ent; | struct ice_vsig_prof *ent; | ||||
LIST_FOR_EACH_ENTRY(ent, &hw->blk[blk].xlt2.vsig_tbl[idx].prop_lst, | LIST_FOR_EACH_ENTRY(ent, &hw->blk[blk].xlt2.vsig_tbl[idx].prop_lst, | ||||
ice_vsig_prof, list) { | ice_vsig_prof, list) | ||||
if (ent->profile_cookie == hdl) | if (ent->profile_cookie == hdl) | ||||
return true; | return true; | ||||
} | |||||
ice_debug(hw, ICE_DBG_INIT, | ice_debug(hw, ICE_DBG_INIT, "Characteristic list for VSI group %d not found.\n", | ||||
"Characteristic list for VSI group %d not found.\n", | |||||
vsig); | vsig); | ||||
return false; | return false; | ||||
} | } | ||||
/** | /** | ||||
* ice_prof_bld_es - build profile ID extraction sequence changes | * ice_prof_bld_es - build profile ID extraction sequence changes | ||||
* @hw: pointer to the HW struct | * @hw: pointer to the HW struct | ||||
* @blk: hardware block | * @blk: hardware block | ||||
* @bld: the update package buffer build to add to | * @bld: the update package buffer build to add to | ||||
* @chgs: the list of changes to make in hardware | * @chgs: the list of changes to make in hardware | ||||
*/ | */ | ||||
static enum ice_status | static enum ice_status | ||||
ice_prof_bld_es(struct ice_hw *hw, enum ice_block blk, | ice_prof_bld_es(struct ice_hw *hw, enum ice_block blk, | ||||
struct ice_buf_build *bld, struct LIST_HEAD_TYPE *chgs) | struct ice_buf_build *bld, struct LIST_HEAD_TYPE *chgs) | ||||
{ | { | ||||
u16 vec_size = hw->blk[blk].es.fvw * sizeof(struct ice_fv_word); | u16 vec_size = hw->blk[blk].es.fvw * sizeof(struct ice_fv_word); | ||||
struct ice_chs_chg *tmp; | struct ice_chs_chg *tmp; | ||||
LIST_FOR_EACH_ENTRY(tmp, chgs, ice_chs_chg, list_entry) { | LIST_FOR_EACH_ENTRY(tmp, chgs, ice_chs_chg, list_entry) | ||||
if (tmp->type == ICE_PTG_ES_ADD && tmp->add_prof) { | if (tmp->type == ICE_PTG_ES_ADD && tmp->add_prof) { | ||||
u16 off = tmp->prof_id * hw->blk[blk].es.fvw; | u16 off = tmp->prof_id * hw->blk[blk].es.fvw; | ||||
struct ice_pkg_es *p; | struct ice_pkg_es *p; | ||||
u32 id; | u32 id; | ||||
id = ice_sect_id(blk, ICE_VEC_TBL); | id = ice_sect_id(blk, ICE_VEC_TBL); | ||||
p = (struct ice_pkg_es *) | p = (struct ice_pkg_es *) | ||||
ice_pkg_buf_alloc_section(bld, id, sizeof(*p) + | ice_pkg_buf_alloc_section(bld, id, | ||||
ice_struct_size(p, es, | |||||
1) + | |||||
vec_size - | vec_size - | ||||
sizeof(p->es[0])); | sizeof(p->es[0])); | ||||
if (!p) | if (!p) | ||||
return ICE_ERR_MAX_LIMIT; | return ICE_ERR_MAX_LIMIT; | ||||
p->count = CPU_TO_LE16(1); | p->count = CPU_TO_LE16(1); | ||||
p->offset = CPU_TO_LE16(tmp->prof_id); | p->offset = CPU_TO_LE16(tmp->prof_id); | ||||
ice_memcpy(p->es, &hw->blk[blk].es.t[off], vec_size, | ice_memcpy(p->es, &hw->blk[blk].es.t[off], vec_size, | ||||
ICE_NONDMA_TO_NONDMA); | ICE_NONDMA_TO_NONDMA); | ||||
} | } | ||||
} | |||||
return ICE_SUCCESS; | return ICE_SUCCESS; | ||||
} | } | ||||
/** | /** | ||||
* ice_prof_bld_tcam - build profile ID TCAM changes | * ice_prof_bld_tcam - build profile ID TCAM changes | ||||
* @hw: pointer to the HW struct | * @hw: pointer to the HW struct | ||||
* @blk: hardware block | * @blk: hardware block | ||||
* @bld: the update package buffer build to add to | * @bld: the update package buffer build to add to | ||||
* @chgs: the list of changes to make in hardware | * @chgs: the list of changes to make in hardware | ||||
*/ | */ | ||||
static enum ice_status | static enum ice_status | ||||
ice_prof_bld_tcam(struct ice_hw *hw, enum ice_block blk, | ice_prof_bld_tcam(struct ice_hw *hw, enum ice_block blk, | ||||
struct ice_buf_build *bld, struct LIST_HEAD_TYPE *chgs) | struct ice_buf_build *bld, struct LIST_HEAD_TYPE *chgs) | ||||
{ | { | ||||
struct ice_chs_chg *tmp; | struct ice_chs_chg *tmp; | ||||
LIST_FOR_EACH_ENTRY(tmp, chgs, ice_chs_chg, list_entry) { | LIST_FOR_EACH_ENTRY(tmp, chgs, ice_chs_chg, list_entry) | ||||
if (tmp->type == ICE_TCAM_ADD && tmp->add_tcam_idx) { | if (tmp->type == ICE_TCAM_ADD && tmp->add_tcam_idx) { | ||||
struct ice_prof_id_section *p; | struct ice_prof_id_section *p; | ||||
u32 id; | u32 id; | ||||
id = ice_sect_id(blk, ICE_PROF_TCAM); | id = ice_sect_id(blk, ICE_PROF_TCAM); | ||||
p = (struct ice_prof_id_section *) | p = (struct ice_prof_id_section *) | ||||
ice_pkg_buf_alloc_section(bld, id, sizeof(*p)); | ice_pkg_buf_alloc_section(bld, id, | ||||
ice_struct_size(p, | |||||
entry, | |||||
1)); | |||||
if (!p) | if (!p) | ||||
return ICE_ERR_MAX_LIMIT; | return ICE_ERR_MAX_LIMIT; | ||||
p->count = CPU_TO_LE16(1); | p->count = CPU_TO_LE16(1); | ||||
p->entry[0].addr = CPU_TO_LE16(tmp->tcam_idx); | p->entry[0].addr = CPU_TO_LE16(tmp->tcam_idx); | ||||
p->entry[0].prof_id = tmp->prof_id; | p->entry[0].prof_id = tmp->prof_id; | ||||
ice_memcpy(p->entry[0].key, | ice_memcpy(p->entry[0].key, | ||||
&hw->blk[blk].prof.t[tmp->tcam_idx].key, | &hw->blk[blk].prof.t[tmp->tcam_idx].key, | ||||
sizeof(hw->blk[blk].prof.t->key), | sizeof(hw->blk[blk].prof.t->key), | ||||
ICE_NONDMA_TO_NONDMA); | ICE_NONDMA_TO_NONDMA); | ||||
} | } | ||||
} | |||||
return ICE_SUCCESS; | return ICE_SUCCESS; | ||||
} | } | ||||
/** | /** | ||||
* ice_prof_bld_xlt1 - build XLT1 changes | * ice_prof_bld_xlt1 - build XLT1 changes | ||||
* @blk: hardware block | * @blk: hardware block | ||||
* @bld: the update package buffer build to add to | * @bld: the update package buffer build to add to | ||||
* @chgs: the list of changes to make in hardware | * @chgs: the list of changes to make in hardware | ||||
*/ | */ | ||||
static enum ice_status | static enum ice_status | ||||
ice_prof_bld_xlt1(enum ice_block blk, struct ice_buf_build *bld, | ice_prof_bld_xlt1(enum ice_block blk, struct ice_buf_build *bld, | ||||
struct LIST_HEAD_TYPE *chgs) | struct LIST_HEAD_TYPE *chgs) | ||||
{ | { | ||||
struct ice_chs_chg *tmp; | struct ice_chs_chg *tmp; | ||||
LIST_FOR_EACH_ENTRY(tmp, chgs, ice_chs_chg, list_entry) { | LIST_FOR_EACH_ENTRY(tmp, chgs, ice_chs_chg, list_entry) | ||||
if (tmp->type == ICE_PTG_ES_ADD && tmp->add_ptg) { | if (tmp->type == ICE_PTG_ES_ADD && tmp->add_ptg) { | ||||
struct ice_xlt1_section *p; | struct ice_xlt1_section *p; | ||||
u32 id; | u32 id; | ||||
id = ice_sect_id(blk, ICE_XLT1); | id = ice_sect_id(blk, ICE_XLT1); | ||||
p = (struct ice_xlt1_section *) | p = (struct ice_xlt1_section *) | ||||
ice_pkg_buf_alloc_section(bld, id, sizeof(*p)); | ice_pkg_buf_alloc_section(bld, id, | ||||
ice_struct_size(p, | |||||
value, | |||||
1)); | |||||
if (!p) | if (!p) | ||||
return ICE_ERR_MAX_LIMIT; | return ICE_ERR_MAX_LIMIT; | ||||
p->count = CPU_TO_LE16(1); | p->count = CPU_TO_LE16(1); | ||||
p->offset = CPU_TO_LE16(tmp->ptype); | p->offset = CPU_TO_LE16(tmp->ptype); | ||||
p->value[0] = tmp->ptg; | p->value[0] = tmp->ptg; | ||||
} | } | ||||
} | |||||
return ICE_SUCCESS; | return ICE_SUCCESS; | ||||
} | } | ||||
/** | /** | ||||
* ice_prof_bld_xlt2 - build XLT2 changes | * ice_prof_bld_xlt2 - build XLT2 changes | ||||
* @blk: hardware block | * @blk: hardware block | ||||
* @bld: the update package buffer build to add to | * @bld: the update package buffer build to add to | ||||
Show All 10 Lines | LIST_FOR_EACH_ENTRY(tmp, chgs, ice_chs_chg, list_entry) { | ||||
u32 id; | u32 id; | ||||
switch (tmp->type) { | switch (tmp->type) { | ||||
case ICE_VSIG_ADD: | case ICE_VSIG_ADD: | ||||
case ICE_VSI_MOVE: | case ICE_VSI_MOVE: | ||||
case ICE_VSIG_REM: | case ICE_VSIG_REM: | ||||
id = ice_sect_id(blk, ICE_XLT2); | id = ice_sect_id(blk, ICE_XLT2); | ||||
p = (struct ice_xlt2_section *) | p = (struct ice_xlt2_section *) | ||||
ice_pkg_buf_alloc_section(bld, id, sizeof(*p)); | ice_pkg_buf_alloc_section(bld, id, | ||||
ice_struct_size(p, | |||||
value, | |||||
1)); | |||||
if (!p) | if (!p) | ||||
return ICE_ERR_MAX_LIMIT; | return ICE_ERR_MAX_LIMIT; | ||||
p->count = CPU_TO_LE16(1); | p->count = CPU_TO_LE16(1); | ||||
p->offset = CPU_TO_LE16(tmp->vsi); | p->offset = CPU_TO_LE16(tmp->vsi); | ||||
p->value[0] = CPU_TO_LE16(tmp->vsig); | p->value[0] = CPU_TO_LE16(tmp->vsig); | ||||
break; | break; | ||||
▲ Show 20 Lines • Show All 162 Lines • ▼ Show 20 Lines | ice_add_prof(struct ice_hw *hw, enum ice_block blk, u64 id, u8 ptypes[], | ||||
while (bytes && prof->ptg_cnt < ICE_MAX_PTG_PER_PROFILE) { | while (bytes && prof->ptg_cnt < ICE_MAX_PTG_PER_PROFILE) { | ||||
u8 bit; | u8 bit; | ||||
if (!ptypes[byte]) { | if (!ptypes[byte]) { | ||||
bytes--; | bytes--; | ||||
byte++; | byte++; | ||||
continue; | continue; | ||||
} | } | ||||
/* Examine 8 bits per byte */ | /* Examine 8 bits per byte */ | ||||
for (bit = 0; bit < 8; bit++) { | ice_for_each_set_bit(bit, (ice_bitmap_t *)&ptypes[byte], | ||||
if (ptypes[byte] & BIT(bit)) { | BITS_PER_BYTE) { | ||||
u16 ptype; | u16 ptype; | ||||
u8 ptg; | u8 ptg; | ||||
u8 m; | |||||
ptype = byte * BITS_PER_BYTE + bit; | ptype = byte * BITS_PER_BYTE + bit; | ||||
/* The package should place all ptypes in a | /* The package should place all ptypes in a non-zero | ||||
* non-zero PTG, so the following call should | * PTG, so the following call should never fail. | ||||
* never fail. | |||||
*/ | */ | ||||
if (ice_ptg_find_ptype(hw, blk, ptype, &ptg)) | if (ice_ptg_find_ptype(hw, blk, ptype, &ptg)) | ||||
continue; | continue; | ||||
/* If PTG is already added, skip and continue */ | /* If PTG is already added, skip and continue */ | ||||
if (ice_is_bit_set(ptgs_used, ptg)) | if (ice_is_bit_set(ptgs_used, ptg)) | ||||
continue; | continue; | ||||
ice_set_bit(ptg, ptgs_used); | ice_set_bit(ptg, ptgs_used); | ||||
prof->ptg[prof->ptg_cnt] = ptg; | prof->ptg[prof->ptg_cnt] = ptg; | ||||
if (++prof->ptg_cnt >= ICE_MAX_PTG_PER_PROFILE) | if (++prof->ptg_cnt >= ICE_MAX_PTG_PER_PROFILE) | ||||
break; | break; | ||||
/* nothing left in byte, then exit */ | |||||
m = ~(u8)((1 << (bit + 1)) - 1); | |||||
if (!(ptypes[byte] & m)) | |||||
break; | |||||
} | } | ||||
} | |||||
bytes--; | bytes--; | ||||
byte++; | byte++; | ||||
} | } | ||||
LIST_ADD(&prof->list, &hw->blk[blk].es.prof_map); | LIST_ADD(&prof->list, &hw->blk[blk].es.prof_map); | ||||
status = ICE_SUCCESS; | status = ICE_SUCCESS; | ||||
err_ice_add_prof: | err_ice_add_prof: | ||||
ice_release_lock(&hw->blk[blk].es.prof_map_lock); | ice_release_lock(&hw->blk[blk].es.prof_map_lock); | ||||
return status; | return status; | ||||
} | } | ||||
/** | /** | ||||
* ice_search_prof_id_low - Search for a profile tracking ID low level | * ice_search_prof_id - Search for a profile tracking ID | ||||
* @hw: pointer to the HW struct | * @hw: pointer to the HW struct | ||||
* @blk: hardware block | * @blk: hardware block | ||||
* @id: profile tracking ID | * @id: profile tracking ID | ||||
* | * | ||||
* This will search for a profile tracking ID which was previously added. This | * This will search for a profile tracking ID which was previously added. | ||||
* version assumes that the caller has already acquired the prof map lock. | * The profile map lock should be held before calling this function. | ||||
*/ | */ | ||||
static struct ice_prof_map * | struct ice_prof_map * | ||||
ice_search_prof_id_low(struct ice_hw *hw, enum ice_block blk, u64 id) | ice_search_prof_id(struct ice_hw *hw, enum ice_block blk, u64 id) | ||||
{ | { | ||||
struct ice_prof_map *entry = NULL; | struct ice_prof_map *entry = NULL; | ||||
struct ice_prof_map *map; | struct ice_prof_map *map; | ||||
LIST_FOR_EACH_ENTRY(map, &hw->blk[blk].es.prof_map, ice_prof_map, | LIST_FOR_EACH_ENTRY(map, &hw->blk[blk].es.prof_map, ice_prof_map, list) | ||||
list) { | |||||
if (map->profile_cookie == id) { | if (map->profile_cookie == id) { | ||||
entry = map; | entry = map; | ||||
break; | break; | ||||
} | } | ||||
} | |||||
return entry; | return entry; | ||||
} | } | ||||
/** | /** | ||||
* ice_search_prof_id - Search for a profile tracking ID | |||||
* @hw: pointer to the HW struct | |||||
* @blk: hardware block | |||||
* @id: profile tracking ID | |||||
* | |||||
* This will search for a profile tracking ID which was previously added. | |||||
*/ | |||||
struct ice_prof_map * | |||||
ice_search_prof_id(struct ice_hw *hw, enum ice_block blk, u64 id) | |||||
{ | |||||
struct ice_prof_map *entry; | |||||
ice_acquire_lock(&hw->blk[blk].es.prof_map_lock); | |||||
entry = ice_search_prof_id_low(hw, blk, id); | |||||
ice_release_lock(&hw->blk[blk].es.prof_map_lock); | |||||
return entry; | |||||
} | |||||
/** | |||||
* ice_set_prof_context - Set context for a given profile | * ice_set_prof_context - Set context for a given profile | ||||
* @hw: pointer to the HW struct | * @hw: pointer to the HW struct | ||||
* @blk: hardware block | * @blk: hardware block | ||||
* @id: profile tracking ID | * @id: profile tracking ID | ||||
* @cntxt: context | * @cntxt: context | ||||
*/ | */ | ||||
struct ice_prof_map * | enum ice_status | ||||
ice_set_prof_context(struct ice_hw *hw, enum ice_block blk, u64 id, u64 cntxt) | ice_set_prof_context(struct ice_hw *hw, enum ice_block blk, u64 id, u64 cntxt) | ||||
{ | { | ||||
enum ice_status status = ICE_ERR_DOES_NOT_EXIST; | |||||
struct ice_prof_map *entry; | struct ice_prof_map *entry; | ||||
ice_acquire_lock(&hw->blk[blk].es.prof_map_lock); | |||||
entry = ice_search_prof_id(hw, blk, id); | entry = ice_search_prof_id(hw, blk, id); | ||||
if (entry) | if (entry) { | ||||
entry->context = cntxt; | entry->context = cntxt; | ||||
status = ICE_SUCCESS; | |||||
return entry; | |||||
} | } | ||||
ice_release_lock(&hw->blk[blk].es.prof_map_lock); | |||||
return status; | |||||
} | |||||
/** | /** | ||||
* ice_get_prof_context - Get context for a given profile | * ice_get_prof_context - Get context for a given profile | ||||
* @hw: pointer to the HW struct | * @hw: pointer to the HW struct | ||||
* @blk: hardware block | * @blk: hardware block | ||||
* @id: profile tracking ID | * @id: profile tracking ID | ||||
* @cntxt: pointer to variable to receive the context | * @cntxt: pointer to variable to receive the context | ||||
*/ | */ | ||||
struct ice_prof_map * | enum ice_status | ||||
ice_get_prof_context(struct ice_hw *hw, enum ice_block blk, u64 id, u64 *cntxt) | ice_get_prof_context(struct ice_hw *hw, enum ice_block blk, u64 id, u64 *cntxt) | ||||
{ | { | ||||
enum ice_status status = ICE_ERR_DOES_NOT_EXIST; | |||||
struct ice_prof_map *entry; | struct ice_prof_map *entry; | ||||
ice_acquire_lock(&hw->blk[blk].es.prof_map_lock); | |||||
entry = ice_search_prof_id(hw, blk, id); | entry = ice_search_prof_id(hw, blk, id); | ||||
if (entry) | if (entry) { | ||||
*cntxt = entry->context; | *cntxt = entry->context; | ||||
status = ICE_SUCCESS; | |||||
return entry; | |||||
} | } | ||||
ice_release_lock(&hw->blk[blk].es.prof_map_lock); | |||||
return status; | |||||
} | |||||
/** | /** | ||||
* ice_vsig_prof_id_count - count profiles in a VSIG | * ice_vsig_prof_id_count - count profiles in a VSIG | ||||
* @hw: pointer to the HW struct | * @hw: pointer to the HW struct | ||||
* @blk: hardware block | * @blk: hardware block | ||||
* @vsig: VSIG to remove the profile from | * @vsig: VSIG to remove the profile from | ||||
*/ | */ | ||||
static u16 | static u16 | ||||
ice_vsig_prof_id_count(struct ice_hw *hw, enum ice_block blk, u16 vsig) | ice_vsig_prof_id_count(struct ice_hw *hw, enum ice_block blk, u16 vsig) | ||||
{ | { | ||||
u16 idx = vsig & ICE_VSIG_IDX_M, count = 0; | u16 idx = vsig & ICE_VSIG_IDX_M, count = 0; | ||||
struct ice_vsig_prof *p; | struct ice_vsig_prof *p; | ||||
LIST_FOR_EACH_ENTRY(p, &hw->blk[blk].xlt2.vsig_tbl[idx].prop_lst, | LIST_FOR_EACH_ENTRY(p, &hw->blk[blk].xlt2.vsig_tbl[idx].prop_lst, | ||||
ice_vsig_prof, list) { | ice_vsig_prof, list) | ||||
count++; | count++; | ||||
} | |||||
return count; | return count; | ||||
} | } | ||||
/** | /** | ||||
* ice_rel_tcam_idx - release a TCAM index | * ice_rel_tcam_idx - release a TCAM index | ||||
* @hw: pointer to the HW struct | * @hw: pointer to the HW struct | ||||
* @blk: hardware block | * @blk: hardware block | ||||
Show All 28 Lines | |||||
*/ | */ | ||||
static enum ice_status | static enum ice_status | ||||
ice_rem_prof_id(struct ice_hw *hw, enum ice_block blk, | ice_rem_prof_id(struct ice_hw *hw, enum ice_block blk, | ||||
struct ice_vsig_prof *prof) | struct ice_vsig_prof *prof) | ||||
{ | { | ||||
enum ice_status status; | enum ice_status status; | ||||
u16 i; | u16 i; | ||||
for (i = 0; i < prof->tcam_count; i++) { | for (i = 0; i < prof->tcam_count; i++) | ||||
if (prof->tcam[i].in_use) { | if (prof->tcam[i].in_use) { | ||||
prof->tcam[i].in_use = false; | prof->tcam[i].in_use = false; | ||||
status = ice_rel_tcam_idx(hw, blk, | status = ice_rel_tcam_idx(hw, blk, | ||||
prof->tcam[i].tcam_idx); | prof->tcam[i].tcam_idx); | ||||
if (status) | if (status) | ||||
return ICE_ERR_HW_TABLE; | return ICE_ERR_HW_TABLE; | ||||
} | } | ||||
} | |||||
return ICE_SUCCESS; | return ICE_SUCCESS; | ||||
} | } | ||||
/** | /** | ||||
* ice_rem_vsig - remove VSIG | * ice_rem_vsig - remove VSIG | ||||
* @hw: pointer to the HW struct | * @hw: pointer to the HW struct | ||||
* @blk: hardware block | * @blk: hardware block | ||||
Show All 21 Lines | LIST_FOR_EACH_ENTRY_SAFE(d, t, | ||||
ice_free(hw, d); | ice_free(hw, d); | ||||
} | } | ||||
/* Move all VSIS associated with this VSIG to the default VSIG */ | /* Move all VSIS associated with this VSIG to the default VSIG */ | ||||
vsi_cur = hw->blk[blk].xlt2.vsig_tbl[idx].first_vsi; | vsi_cur = hw->blk[blk].xlt2.vsig_tbl[idx].first_vsi; | ||||
/* If the VSIG has at least 1 VSI then iterate through the list | /* If the VSIG has at least 1 VSI then iterate through the list | ||||
* and remove the VSIs before deleting the group. | * and remove the VSIs before deleting the group. | ||||
*/ | */ | ||||
if (vsi_cur) { | if (vsi_cur) | ||||
do { | do { | ||||
struct ice_vsig_vsi *tmp = vsi_cur->next_vsi; | struct ice_vsig_vsi *tmp = vsi_cur->next_vsi; | ||||
struct ice_chs_chg *p; | struct ice_chs_chg *p; | ||||
p = (struct ice_chs_chg *)ice_malloc(hw, sizeof(*p)); | p = (struct ice_chs_chg *)ice_malloc(hw, sizeof(*p)); | ||||
if (!p) | if (!p) | ||||
return ICE_ERR_NO_MEMORY; | return ICE_ERR_NO_MEMORY; | ||||
p->type = ICE_VSIG_REM; | p->type = ICE_VSIG_REM; | ||||
p->orig_vsig = vsig; | p->orig_vsig = vsig; | ||||
p->vsig = ICE_DEFAULT_VSIG; | p->vsig = ICE_DEFAULT_VSIG; | ||||
p->vsi = vsi_cur - hw->blk[blk].xlt2.vsis; | p->vsi = vsi_cur - hw->blk[blk].xlt2.vsis; | ||||
LIST_ADD(&p->list_entry, chg); | LIST_ADD(&p->list_entry, chg); | ||||
vsi_cur = tmp; | vsi_cur = tmp; | ||||
} while (vsi_cur); | } while (vsi_cur); | ||||
} | |||||
return ice_vsig_free(hw, blk, vsig); | return ice_vsig_free(hw, blk, vsig); | ||||
} | } | ||||
/** | /** | ||||
* ice_rem_prof_id_vsig - remove a specific profile from a VSIG | * ice_rem_prof_id_vsig - remove a specific profile from a VSIG | ||||
* @hw: pointer to the HW struct | * @hw: pointer to the HW struct | ||||
* @blk: hardware block | * @blk: hardware block | ||||
* @vsig: VSIG to remove the profile from | * @vsig: VSIG to remove the profile from | ||||
* @hdl: profile handle indicating which profile to remove | * @hdl: profile handle indicating which profile to remove | ||||
* @chg: list to receive a record of changes | * @chg: list to receive a record of changes | ||||
*/ | */ | ||||
static enum ice_status | static enum ice_status | ||||
ice_rem_prof_id_vsig(struct ice_hw *hw, enum ice_block blk, u16 vsig, u64 hdl, | ice_rem_prof_id_vsig(struct ice_hw *hw, enum ice_block blk, u16 vsig, u64 hdl, | ||||
struct LIST_HEAD_TYPE *chg) | struct LIST_HEAD_TYPE *chg) | ||||
{ | { | ||||
u16 idx = vsig & ICE_VSIG_IDX_M; | u16 idx = vsig & ICE_VSIG_IDX_M; | ||||
struct ice_vsig_prof *p, *t; | struct ice_vsig_prof *p, *t; | ||||
enum ice_status status; | enum ice_status status; | ||||
LIST_FOR_EACH_ENTRY_SAFE(p, t, | LIST_FOR_EACH_ENTRY_SAFE(p, t, | ||||
&hw->blk[blk].xlt2.vsig_tbl[idx].prop_lst, | &hw->blk[blk].xlt2.vsig_tbl[idx].prop_lst, | ||||
ice_vsig_prof, list) { | ice_vsig_prof, list) | ||||
if (p->profile_cookie == hdl) { | if (p->profile_cookie == hdl) { | ||||
if (ice_vsig_prof_id_count(hw, blk, vsig) == 1) | if (ice_vsig_prof_id_count(hw, blk, vsig) == 1) | ||||
/* this is the last profile, remove the VSIG */ | /* this is the last profile, remove the VSIG */ | ||||
return ice_rem_vsig(hw, blk, vsig, chg); | return ice_rem_vsig(hw, blk, vsig, chg); | ||||
status = ice_rem_prof_id(hw, blk, p); | status = ice_rem_prof_id(hw, blk, p); | ||||
if (!status) { | if (!status) { | ||||
LIST_DEL(&p->list); | LIST_DEL(&p->list); | ||||
ice_free(hw, p); | ice_free(hw, p); | ||||
} | } | ||||
return status; | return status; | ||||
} | } | ||||
} | |||||
return ICE_ERR_DOES_NOT_EXIST; | return ICE_ERR_DOES_NOT_EXIST; | ||||
} | } | ||||
/** | /** | ||||
* ice_rem_flow_all - remove all flows with a particular profile | * ice_rem_flow_all - remove all flows with a particular profile | ||||
* @hw: pointer to the HW struct | * @hw: pointer to the HW struct | ||||
* @blk: hardware block | * @blk: hardware block | ||||
* @id: profile tracking ID | * @id: profile tracking ID | ||||
*/ | */ | ||||
static enum ice_status | static enum ice_status | ||||
ice_rem_flow_all(struct ice_hw *hw, enum ice_block blk, u64 id) | ice_rem_flow_all(struct ice_hw *hw, enum ice_block blk, u64 id) | ||||
{ | { | ||||
struct ice_chs_chg *del, *tmp; | struct ice_chs_chg *del, *tmp; | ||||
struct LIST_HEAD_TYPE chg; | |||||
enum ice_status status; | enum ice_status status; | ||||
struct LIST_HEAD_TYPE chg; | |||||
u16 i; | u16 i; | ||||
INIT_LIST_HEAD(&chg); | INIT_LIST_HEAD(&chg); | ||||
for (i = 1; i < ICE_MAX_VSIGS; i++) { | for (i = 1; i < ICE_MAX_VSIGS; i++) | ||||
if (hw->blk[blk].xlt2.vsig_tbl[i].in_use) { | if (hw->blk[blk].xlt2.vsig_tbl[i].in_use) { | ||||
if (ice_has_prof_vsig(hw, blk, i, id)) { | if (ice_has_prof_vsig(hw, blk, i, id)) { | ||||
status = ice_rem_prof_id_vsig(hw, blk, i, id, | status = ice_rem_prof_id_vsig(hw, blk, i, id, | ||||
&chg); | &chg); | ||||
if (status) | if (status) | ||||
goto err_ice_rem_flow_all; | goto err_ice_rem_flow_all; | ||||
} | } | ||||
} | } | ||||
} | |||||
status = ice_upd_prof_hw(hw, blk, &chg); | status = ice_upd_prof_hw(hw, blk, &chg); | ||||
err_ice_rem_flow_all: | err_ice_rem_flow_all: | ||||
LIST_FOR_EACH_ENTRY_SAFE(del, tmp, &chg, ice_chs_chg, list_entry) { | LIST_FOR_EACH_ENTRY_SAFE(del, tmp, &chg, ice_chs_chg, list_entry) { | ||||
LIST_DEL(&del->list_entry); | LIST_DEL(&del->list_entry); | ||||
ice_free(hw, del); | ice_free(hw, del); | ||||
} | } | ||||
Show All 13 Lines | |||||
*/ | */ | ||||
enum ice_status ice_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 id) | enum ice_status ice_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 id) | ||||
{ | { | ||||
struct ice_prof_map *pmap; | struct ice_prof_map *pmap; | ||||
enum ice_status status; | enum ice_status status; | ||||
ice_acquire_lock(&hw->blk[blk].es.prof_map_lock); | ice_acquire_lock(&hw->blk[blk].es.prof_map_lock); | ||||
pmap = ice_search_prof_id_low(hw, blk, id); | pmap = ice_search_prof_id(hw, blk, id); | ||||
if (!pmap) { | if (!pmap) { | ||||
status = ICE_ERR_DOES_NOT_EXIST; | status = ICE_ERR_DOES_NOT_EXIST; | ||||
goto err_ice_rem_prof; | goto err_ice_rem_prof; | ||||
} | } | ||||
/* remove all flows with this profile */ | /* remove all flows with this profile */ | ||||
status = ice_rem_flow_all(hw, blk, pmap->profile_cookie); | status = ice_rem_flow_all(hw, blk, pmap->profile_cookie); | ||||
if (status) | if (status) | ||||
Show All 16 Lines | |||||
* @blk: hardware block | * @blk: hardware block | ||||
* @hdl: profile handle | * @hdl: profile handle | ||||
* @chg: change list | * @chg: change list | ||||
*/ | */ | ||||
static enum ice_status | static enum ice_status | ||||
ice_get_prof(struct ice_hw *hw, enum ice_block blk, u64 hdl, | ice_get_prof(struct ice_hw *hw, enum ice_block blk, u64 hdl, | ||||
struct LIST_HEAD_TYPE *chg) | struct LIST_HEAD_TYPE *chg) | ||||
{ | { | ||||
enum ice_status status = ICE_SUCCESS; | |||||
struct ice_prof_map *map; | struct ice_prof_map *map; | ||||
struct ice_chs_chg *p; | struct ice_chs_chg *p; | ||||
u16 i; | u16 i; | ||||
ice_acquire_lock(&hw->blk[blk].es.prof_map_lock); | |||||
/* Get the details on the profile specified by the handle ID */ | /* Get the details on the profile specified by the handle ID */ | ||||
map = ice_search_prof_id(hw, blk, hdl); | map = ice_search_prof_id(hw, blk, hdl); | ||||
if (!map) | if (!map) { | ||||
return ICE_ERR_DOES_NOT_EXIST; | status = ICE_ERR_DOES_NOT_EXIST; | ||||
goto err_ice_get_prof; | |||||
} | |||||
for (i = 0; i < map->ptg_cnt; i++) { | for (i = 0; i < map->ptg_cnt; i++) | ||||
if (!hw->blk[blk].es.written[map->prof_id]) { | if (!hw->blk[blk].es.written[map->prof_id]) { | ||||
/* add ES to change list */ | /* add ES to change list */ | ||||
p = (struct ice_chs_chg *)ice_malloc(hw, sizeof(*p)); | p = (struct ice_chs_chg *)ice_malloc(hw, sizeof(*p)); | ||||
if (!p) | if (!p) { | ||||
status = ICE_ERR_NO_MEMORY; | |||||
goto err_ice_get_prof; | goto err_ice_get_prof; | ||||
} | |||||
p->type = ICE_PTG_ES_ADD; | p->type = ICE_PTG_ES_ADD; | ||||
p->ptype = 0; | p->ptype = 0; | ||||
p->ptg = map->ptg[i]; | p->ptg = map->ptg[i]; | ||||
p->add_ptg = 0; | p->add_ptg = 0; | ||||
p->add_prof = 1; | p->add_prof = 1; | ||||
p->prof_id = map->prof_id; | p->prof_id = map->prof_id; | ||||
hw->blk[blk].es.written[map->prof_id] = true; | hw->blk[blk].es.written[map->prof_id] = true; | ||||
LIST_ADD(&p->list_entry, chg); | LIST_ADD(&p->list_entry, chg); | ||||
} | } | ||||
} | |||||
return ICE_SUCCESS; | |||||
err_ice_get_prof: | err_ice_get_prof: | ||||
ice_release_lock(&hw->blk[blk].es.prof_map_lock); | |||||
/* let caller clean up the change list */ | /* let caller clean up the change list */ | ||||
return ICE_ERR_NO_MEMORY; | return status; | ||||
} | } | ||||
/** | /** | ||||
* ice_get_profs_vsig - get a copy of the list of profiles from a VSIG | * ice_get_profs_vsig - get a copy of the list of profiles from a VSIG | ||||
* @hw: pointer to the HW struct | * @hw: pointer to the HW struct | ||||
* @blk: hardware block | * @blk: hardware block | ||||
* @vsig: VSIG from which to copy the list | * @vsig: VSIG from which to copy the list | ||||
* @lst: output list | * @lst: output list | ||||
Show All 37 Lines | |||||
* @blk: hardware block | * @blk: hardware block | ||||
* @lst: the list to be added to | * @lst: the list to be added to | ||||
* @hdl: profile handle of entry to add | * @hdl: profile handle of entry to add | ||||
*/ | */ | ||||
static enum ice_status | static enum ice_status | ||||
ice_add_prof_to_lst(struct ice_hw *hw, enum ice_block blk, | ice_add_prof_to_lst(struct ice_hw *hw, enum ice_block blk, | ||||
struct LIST_HEAD_TYPE *lst, u64 hdl) | struct LIST_HEAD_TYPE *lst, u64 hdl) | ||||
{ | { | ||||
enum ice_status status = ICE_SUCCESS; | |||||
struct ice_prof_map *map; | struct ice_prof_map *map; | ||||
struct ice_vsig_prof *p; | struct ice_vsig_prof *p; | ||||
u16 i; | u16 i; | ||||
ice_acquire_lock(&hw->blk[blk].es.prof_map_lock); | |||||
map = ice_search_prof_id(hw, blk, hdl); | map = ice_search_prof_id(hw, blk, hdl); | ||||
if (!map) | if (!map) { | ||||
return ICE_ERR_DOES_NOT_EXIST; | status = ICE_ERR_DOES_NOT_EXIST; | ||||
goto err_ice_add_prof_to_lst; | |||||
} | |||||
p = (struct ice_vsig_prof *)ice_malloc(hw, sizeof(*p)); | p = (struct ice_vsig_prof *)ice_malloc(hw, sizeof(*p)); | ||||
if (!p) | if (!p) { | ||||
return ICE_ERR_NO_MEMORY; | status = ICE_ERR_NO_MEMORY; | ||||
goto err_ice_add_prof_to_lst; | |||||
} | |||||
p->profile_cookie = map->profile_cookie; | p->profile_cookie = map->profile_cookie; | ||||
p->prof_id = map->prof_id; | p->prof_id = map->prof_id; | ||||
p->tcam_count = map->ptg_cnt; | p->tcam_count = map->ptg_cnt; | ||||
for (i = 0; i < map->ptg_cnt; i++) { | for (i = 0; i < map->ptg_cnt; i++) { | ||||
p->tcam[i].prof_id = map->prof_id; | p->tcam[i].prof_id = map->prof_id; | ||||
p->tcam[i].tcam_idx = ICE_INVALID_TCAM; | p->tcam[i].tcam_idx = ICE_INVALID_TCAM; | ||||
p->tcam[i].ptg = map->ptg[i]; | p->tcam[i].ptg = map->ptg[i]; | ||||
} | } | ||||
LIST_ADD(&p->list, lst); | LIST_ADD(&p->list, lst); | ||||
return ICE_SUCCESS; | err_ice_add_prof_to_lst: | ||||
ice_release_lock(&hw->blk[blk].es.prof_map_lock); | |||||
return status; | |||||
} | } | ||||
/** | /** | ||||
* ice_move_vsi - move VSI to another VSIG | * ice_move_vsi - move VSI to another VSIG | ||||
* @hw: pointer to the HW struct | * @hw: pointer to the HW struct | ||||
* @blk: hardware block | * @blk: hardware block | ||||
* @vsi: the VSI to move | * @vsi: the VSI to move | ||||
* @vsig: the VSIG to move the VSI to | * @vsig: the VSIG to move the VSI to | ||||
Show All 36 Lines | |||||
* @idx: the index of the TCAM entry to remove | * @idx: the index of the TCAM entry to remove | ||||
* @chg: the list of change structures to search | * @chg: the list of change structures to search | ||||
*/ | */ | ||||
static void | static void | ||||
ice_rem_chg_tcam_ent(struct ice_hw *hw, u16 idx, struct LIST_HEAD_TYPE *chg) | ice_rem_chg_tcam_ent(struct ice_hw *hw, u16 idx, struct LIST_HEAD_TYPE *chg) | ||||
{ | { | ||||
struct ice_chs_chg *pos, *tmp; | struct ice_chs_chg *pos, *tmp; | ||||
LIST_FOR_EACH_ENTRY_SAFE(tmp, pos, chg, ice_chs_chg, list_entry) { | LIST_FOR_EACH_ENTRY_SAFE(tmp, pos, chg, ice_chs_chg, list_entry) | ||||
if (tmp->type == ICE_TCAM_ADD && tmp->tcam_idx == idx) { | if (tmp->type == ICE_TCAM_ADD && tmp->tcam_idx == idx) { | ||||
LIST_DEL(&tmp->list_entry); | LIST_DEL(&tmp->list_entry); | ||||
ice_free(hw, tmp); | ice_free(hw, tmp); | ||||
} | } | ||||
} | } | ||||
} | |||||
/** | /** | ||||
* ice_prof_tcam_ena_dis - add enable or disable TCAM change | * ice_prof_tcam_ena_dis - add enable or disable TCAM change | ||||
* @hw: pointer to the HW struct | * @hw: pointer to the HW struct | ||||
* @blk: hardware block | * @blk: hardware block | ||||
* @enable: true to enable, false to disable | * @enable: true to enable, false to disable | ||||
* @vsig: the VSIG of the TCAM entry | * @vsig: the VSIG of the TCAM entry | ||||
* @tcam: pointer the TCAM info structure of the TCAM to disable | * @tcam: pointer the TCAM info structure of the TCAM to disable | ||||
Show All 23 Lines | if (!enable) { | ||||
*/ | */ | ||||
ice_rem_chg_tcam_ent(hw, tcam->tcam_idx, chg); | ice_rem_chg_tcam_ent(hw, tcam->tcam_idx, chg); | ||||
tcam->tcam_idx = 0; | tcam->tcam_idx = 0; | ||||
tcam->in_use = 0; | tcam->in_use = 0; | ||||
return status; | return status; | ||||
} | } | ||||
/* for re-enabling, reallocate a TCAM */ | /* for re-enabling, reallocate a TCAM */ | ||||
status = ice_alloc_tcam_ent(hw, blk, &tcam->tcam_idx); | status = ice_alloc_tcam_ent(hw, blk, true, &tcam->tcam_idx); | ||||
if (status) | if (status) | ||||
return status; | return status; | ||||
/* add TCAM to change list */ | /* add TCAM to change list */ | ||||
p = (struct ice_chs_chg *)ice_malloc(hw, sizeof(*p)); | p = (struct ice_chs_chg *)ice_malloc(hw, sizeof(*p)); | ||||
if (!p) | if (!p) | ||||
return ICE_ERR_NO_MEMORY; | return ICE_ERR_NO_MEMORY; | ||||
▲ Show 20 Lines • Show All 105 Lines • ▼ Show 20 Lines | |||||
static enum ice_status | static enum ice_status | ||||
ice_add_prof_id_vsig(struct ice_hw *hw, enum ice_block blk, u16 vsig, u64 hdl, | ice_add_prof_id_vsig(struct ice_hw *hw, enum ice_block blk, u16 vsig, u64 hdl, | ||||
bool rev, struct LIST_HEAD_TYPE *chg) | bool rev, struct LIST_HEAD_TYPE *chg) | ||||
{ | { | ||||
/* Masks that ignore flags */ | /* Masks that ignore flags */ | ||||
u8 vl_msk[ICE_TCAM_KEY_VAL_SZ] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; | u8 vl_msk[ICE_TCAM_KEY_VAL_SZ] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; | ||||
u8 dc_msk[ICE_TCAM_KEY_VAL_SZ] = { 0xFF, 0xFF, 0x00, 0x00, 0x00 }; | u8 dc_msk[ICE_TCAM_KEY_VAL_SZ] = { 0xFF, 0xFF, 0x00, 0x00, 0x00 }; | ||||
u8 nm_msk[ICE_TCAM_KEY_VAL_SZ] = { 0x00, 0x00, 0x00, 0x00, 0x00 }; | u8 nm_msk[ICE_TCAM_KEY_VAL_SZ] = { 0x00, 0x00, 0x00, 0x00, 0x00 }; | ||||
enum ice_status status = ICE_SUCCESS; | |||||
struct ice_prof_map *map; | struct ice_prof_map *map; | ||||
struct ice_vsig_prof *t; | struct ice_vsig_prof *t; | ||||
struct ice_chs_chg *p; | struct ice_chs_chg *p; | ||||
u16 vsig_idx, i; | u16 vsig_idx, i; | ||||
/* Get the details on the profile specified by the handle ID */ | |||||
map = ice_search_prof_id(hw, blk, hdl); | |||||
if (!map) | |||||
return ICE_ERR_DOES_NOT_EXIST; | |||||
/* Error, if this VSIG already has this profile */ | /* Error, if this VSIG already has this profile */ | ||||
if (ice_has_prof_vsig(hw, blk, vsig, hdl)) | if (ice_has_prof_vsig(hw, blk, vsig, hdl)) | ||||
return ICE_ERR_ALREADY_EXISTS; | return ICE_ERR_ALREADY_EXISTS; | ||||
/* new VSIG profile structure */ | /* new VSIG profile structure */ | ||||
t = (struct ice_vsig_prof *)ice_malloc(hw, sizeof(*t)); | t = (struct ice_vsig_prof *)ice_malloc(hw, sizeof(*t)); | ||||
if (!t) | if (!t) | ||||
return ICE_ERR_NO_MEMORY; | return ICE_ERR_NO_MEMORY; | ||||
ice_acquire_lock(&hw->blk[blk].es.prof_map_lock); | |||||
/* Get the details on the profile specified by the handle ID */ | |||||
map = ice_search_prof_id(hw, blk, hdl); | |||||
if (!map) { | |||||
status = ICE_ERR_DOES_NOT_EXIST; | |||||
goto err_ice_add_prof_id_vsig; | |||||
} | |||||
t->profile_cookie = map->profile_cookie; | t->profile_cookie = map->profile_cookie; | ||||
t->prof_id = map->prof_id; | t->prof_id = map->prof_id; | ||||
t->tcam_count = map->ptg_cnt; | t->tcam_count = map->ptg_cnt; | ||||
/* create TCAM entries */ | /* create TCAM entries */ | ||||
for (i = 0; i < map->ptg_cnt; i++) { | for (i = 0; i < map->ptg_cnt; i++) { | ||||
enum ice_status status; | |||||
u16 tcam_idx; | u16 tcam_idx; | ||||
/* add TCAM to change list */ | /* add TCAM to change list */ | ||||
p = (struct ice_chs_chg *)ice_malloc(hw, sizeof(*p)); | p = (struct ice_chs_chg *)ice_malloc(hw, sizeof(*p)); | ||||
if (!p) | if (!p) { | ||||
status = ICE_ERR_NO_MEMORY; | |||||
goto err_ice_add_prof_id_vsig; | goto err_ice_add_prof_id_vsig; | ||||
} | |||||
/* allocate the TCAM entry index */ | /* allocate the TCAM entry index */ | ||||
status = ice_alloc_tcam_ent(hw, blk, &tcam_idx); | status = ice_alloc_tcam_ent(hw, blk, true, &tcam_idx); | ||||
if (status) { | if (status) { | ||||
ice_free(hw, p); | ice_free(hw, p); | ||||
goto err_ice_add_prof_id_vsig; | goto err_ice_add_prof_id_vsig; | ||||
} | } | ||||
t->tcam[i].ptg = map->ptg[i]; | t->tcam[i].ptg = map->ptg[i]; | ||||
t->tcam[i].prof_id = map->prof_id; | t->tcam[i].prof_id = map->prof_id; | ||||
t->tcam[i].tcam_idx = tcam_idx; | t->tcam[i].tcam_idx = tcam_idx; | ||||
Show All 24 Lines | ice_add_prof_id_vsig(struct ice_hw *hw, enum ice_block blk, u16 vsig, u64 hdl, | ||||
vsig_idx = vsig & ICE_VSIG_IDX_M; | vsig_idx = vsig & ICE_VSIG_IDX_M; | ||||
if (rev) | if (rev) | ||||
LIST_ADD_TAIL(&t->list, | LIST_ADD_TAIL(&t->list, | ||||
&hw->blk[blk].xlt2.vsig_tbl[vsig_idx].prop_lst); | &hw->blk[blk].xlt2.vsig_tbl[vsig_idx].prop_lst); | ||||
else | else | ||||
LIST_ADD(&t->list, | LIST_ADD(&t->list, | ||||
&hw->blk[blk].xlt2.vsig_tbl[vsig_idx].prop_lst); | &hw->blk[blk].xlt2.vsig_tbl[vsig_idx].prop_lst); | ||||
return ICE_SUCCESS; | ice_release_lock(&hw->blk[blk].es.prof_map_lock); | ||||
return status; | |||||
err_ice_add_prof_id_vsig: | err_ice_add_prof_id_vsig: | ||||
ice_release_lock(&hw->blk[blk].es.prof_map_lock); | |||||
/* let caller clean up the change list */ | /* let caller clean up the change list */ | ||||
ice_free(hw, t); | ice_free(hw, t); | ||||
return ICE_ERR_NO_MEMORY; | return status; | ||||
} | } | ||||
/** | /** | ||||
* ice_create_prof_id_vsig - add a new VSIG with a single profile | * ice_create_prof_id_vsig - add a new VSIG with a single profile | ||||
* @hw: pointer to the HW struct | * @hw: pointer to the HW struct | ||||
* @blk: hardware block | * @blk: hardware block | ||||
* @vsi: the initial VSI that will be in VSIG | * @vsi: the initial VSI that will be in VSIG | ||||
* @hdl: the profile handle of the profile that will be added to the VSIG | * @hdl: the profile handle of the profile that will be added to the VSIG | ||||
▲ Show 20 Lines • Show All 85 Lines • ▼ Show 20 Lines | |||||
* @blk: hardware block | * @blk: hardware block | ||||
* @hdl: the profile handle of the profile to search for | * @hdl: the profile handle of the profile to search for | ||||
* @vsig: returns the VSIG with the matching profile | * @vsig: returns the VSIG with the matching profile | ||||
*/ | */ | ||||
static bool | static bool | ||||
ice_find_prof_vsig(struct ice_hw *hw, enum ice_block blk, u64 hdl, u16 *vsig) | ice_find_prof_vsig(struct ice_hw *hw, enum ice_block blk, u64 hdl, u16 *vsig) | ||||
{ | { | ||||
struct ice_vsig_prof *t; | struct ice_vsig_prof *t; | ||||
struct LIST_HEAD_TYPE lst; | |||||
enum ice_status status; | enum ice_status status; | ||||
struct LIST_HEAD_TYPE lst; | |||||
INIT_LIST_HEAD(&lst); | INIT_LIST_HEAD(&lst); | ||||
t = (struct ice_vsig_prof *)ice_malloc(hw, sizeof(*t)); | t = (struct ice_vsig_prof *)ice_malloc(hw, sizeof(*t)); | ||||
if (!t) | if (!t) | ||||
return false; | return false; | ||||
t->profile_cookie = hdl; | t->profile_cookie = hdl; | ||||
▲ Show 20 Lines • Show All 58 Lines • ▼ Show 20 Lines | |||||
* Calling this function will update the hardware tables to enable the | * Calling this function will update the hardware tables to enable the | ||||
* profile indicated by the ID parameter for the VSIs specified in the VSI | * profile indicated by the ID parameter for the VSIs specified in the VSI | ||||
* array. Once successfully called, the flow will be enabled. | * array. Once successfully called, the flow will be enabled. | ||||
*/ | */ | ||||
enum ice_status | enum ice_status | ||||
ice_add_prof_id_flow(struct ice_hw *hw, enum ice_block blk, u16 vsi, u64 hdl) | ice_add_prof_id_flow(struct ice_hw *hw, enum ice_block blk, u16 vsi, u64 hdl) | ||||
{ | { | ||||
struct ice_vsig_prof *tmp1, *del1; | struct ice_vsig_prof *tmp1, *del1; | ||||
struct LIST_HEAD_TYPE union_lst; | |||||
struct ice_chs_chg *tmp, *del; | struct ice_chs_chg *tmp, *del; | ||||
struct LIST_HEAD_TYPE chg; | struct LIST_HEAD_TYPE union_lst; | ||||
enum ice_status status; | enum ice_status status; | ||||
struct LIST_HEAD_TYPE chg; | |||||
u16 vsig; | u16 vsig; | ||||
INIT_LIST_HEAD(&union_lst); | INIT_LIST_HEAD(&union_lst); | ||||
INIT_LIST_HEAD(&chg); | INIT_LIST_HEAD(&chg); | ||||
/* Get profile */ | /* Get profile */ | ||||
status = ice_get_prof(hw, blk, hdl, &chg); | status = ice_get_prof(hw, blk, hdl, &chg); | ||||
if (status) | if (status) | ||||
▲ Show 20 Lines • Show All 150 Lines • ▼ Show 20 Lines | |||||
* @lst: list to remove the profile from | * @lst: list to remove the profile from | ||||
* @hdl: the profile handle indicating the profile to remove | * @hdl: the profile handle indicating the profile to remove | ||||
*/ | */ | ||||
static enum ice_status | static enum ice_status | ||||
ice_rem_prof_from_list(struct ice_hw *hw, struct LIST_HEAD_TYPE *lst, u64 hdl) | ice_rem_prof_from_list(struct ice_hw *hw, struct LIST_HEAD_TYPE *lst, u64 hdl) | ||||
{ | { | ||||
struct ice_vsig_prof *ent, *tmp; | struct ice_vsig_prof *ent, *tmp; | ||||
LIST_FOR_EACH_ENTRY_SAFE(ent, tmp, lst, ice_vsig_prof, list) { | LIST_FOR_EACH_ENTRY_SAFE(ent, tmp, lst, ice_vsig_prof, list) | ||||
if (ent->profile_cookie == hdl) { | if (ent->profile_cookie == hdl) { | ||||
LIST_DEL(&ent->list); | LIST_DEL(&ent->list); | ||||
ice_free(hw, ent); | ice_free(hw, ent); | ||||
return ICE_SUCCESS; | return ICE_SUCCESS; | ||||
} | } | ||||
} | |||||
return ICE_ERR_DOES_NOT_EXIST; | return ICE_ERR_DOES_NOT_EXIST; | ||||
} | } | ||||
/** | /** | ||||
* ice_rem_prof_id_flow - remove flow | * ice_rem_prof_id_flow - remove flow | ||||
* @hw: pointer to the HW struct | * @hw: pointer to the HW struct | ||||
* @blk: hardware block | * @blk: hardware block | ||||
* @vsi: the VSI from which to remove the profile specified by ID | * @vsi: the VSI from which to remove the profile specified by ID | ||||
* @hdl: profile tracking handle | * @hdl: profile tracking handle | ||||
* | * | ||||
* Calling this function will update the hardware tables to remove the | * Calling this function will update the hardware tables to remove the | ||||
* profile indicated by the ID parameter for the VSIs specified in the VSI | * profile indicated by the ID parameter for the VSIs specified in the VSI | ||||
* array. Once successfully called, the flow will be disabled. | * array. Once successfully called, the flow will be disabled. | ||||
*/ | */ | ||||
enum ice_status | enum ice_status | ||||
ice_rem_prof_id_flow(struct ice_hw *hw, enum ice_block blk, u16 vsi, u64 hdl) | ice_rem_prof_id_flow(struct ice_hw *hw, enum ice_block blk, u16 vsi, u64 hdl) | ||||
{ | { | ||||
struct ice_vsig_prof *tmp1, *del1; | struct ice_vsig_prof *tmp1, *del1; | ||||
struct LIST_HEAD_TYPE chg, copy; | |||||
struct ice_chs_chg *tmp, *del; | struct ice_chs_chg *tmp, *del; | ||||
struct LIST_HEAD_TYPE chg, copy; | |||||
enum ice_status status; | enum ice_status status; | ||||
u16 vsig; | u16 vsig; | ||||
INIT_LIST_HEAD(©); | INIT_LIST_HEAD(©); | ||||
INIT_LIST_HEAD(&chg); | INIT_LIST_HEAD(&chg); | ||||
/* determine if VSI is already part of a VSIG */ | /* determine if VSI is already part of a VSIG */ | ||||
status = ice_vsig_find_vsi(hw, blk, vsi, &vsig); | status = ice_vsig_find_vsi(hw, blk, vsi, &vsig); | ||||
Show All 13 Lines | if (only_vsi) { | ||||
/* If the original VSIG only contains one reference, | /* If the original VSIG only contains one reference, | ||||
* which will be the requesting VSI, then the VSI is not | * which will be the requesting VSI, then the VSI is not | ||||
* sharing entries and we can simply remove the specific | * sharing entries and we can simply remove the specific | ||||
* characteristics from the VSIG. | * characteristics from the VSIG. | ||||
*/ | */ | ||||
if (last_profile) { | if (last_profile) { | ||||
/* If there are no profiles left for this VSIG, | /* If there are no profiles left for this VSIG, | ||||
* then simply remove the the VSIG. | * then simply remove the VSIG. | ||||
*/ | */ | ||||
status = ice_rem_vsig(hw, blk, vsig, &chg); | status = ice_rem_vsig(hw, blk, vsig, &chg); | ||||
if (status) | if (status) | ||||
goto err_ice_rem_prof_id_flow; | goto err_ice_rem_prof_id_flow; | ||||
} else { | } else { | ||||
status = ice_rem_prof_id_vsig(hw, blk, vsig, | status = ice_rem_prof_id_vsig(hw, blk, vsig, | ||||
hdl, &chg); | hdl, &chg); | ||||
if (status) | if (status) | ||||
▲ Show 20 Lines • Show All 105 Lines • Show Last 20 Lines |