X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fice%2Fbase%2Fice_flex_pipe.c;h=e511b50a007f40c4d1c26fc247640c7a5d20731b;hb=cb71192486c34eada5b65c6c46d32afd05cc091b;hp=077325ad59730cd569c9d9707643fd2346c01aff;hpb=f3202a097f12d008a257ab516db12fa5341d9e50;p=dpdk.git diff --git a/drivers/net/ice/base/ice_flex_pipe.c b/drivers/net/ice/base/ice_flex_pipe.c index 077325ad59..e511b50a00 100644 --- a/drivers/net/ice/base/ice_flex_pipe.c +++ b/drivers/net/ice/base/ice_flex_pipe.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2001-2019 + * Copyright(c) 2001-2020 Intel Corporation */ #include "ice_common.h" @@ -648,7 +648,7 @@ static bool ice_bits_max_set(const u8 *mask, u16 size, u16 max) * This function generates a key from a value, a don't care mask and a never * match mask. * 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) * nm == NULL --> nm mask is all 0's (no never match bits) */ @@ -712,8 +712,7 @@ ice_acquire_global_cfg_lock(struct ice_hw *hw, ICE_GLOBAL_CFG_LOCK_TIMEOUT); if (status == ICE_ERR_AQ_NO_WORK) - ice_debug(hw, ICE_DBG_PKG, - "Global config lock: No work to do\n"); + ice_debug(hw, ICE_DBG_PKG, "Global config lock: No work to do\n"); return status; } @@ -808,6 +807,28 @@ ice_aq_download_pkg(struct ice_hw *hw, struct ice_buf_hdr *pkg_buf, return status; } +/** + * ice_aq_upload_section + * @hw: pointer to the hardware structure + * @pkg_buf: the package buffer which will receive the section + * @buf_size: the size of the package buffer + * @cd: pointer to command details structure or NULL + * + * Upload Section (0x0C41) + */ +enum ice_status +ice_aq_upload_section(struct ice_hw *hw, struct ice_buf_hdr *pkg_buf, + u16 buf_size, struct ice_sq_cd *cd) +{ + struct ice_aq_desc desc; + + ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); + ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_upload_section); + desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD); + + return ice_aq_send_cmd(hw, &desc, pkg_buf, buf_size, cd); +} + /** * ice_aq_update_pkg * @hw: pointer to the hardware structure @@ -876,8 +897,9 @@ ice_find_seg_in_pkg(struct ice_hw *hw, u32 seg_type, ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); ice_debug(hw, ICE_DBG_PKG, "Package format version: %d.%d.%d.%d\n", - pkg_hdr->format_ver.major, pkg_hdr->format_ver.minor, - pkg_hdr->format_ver.update, pkg_hdr->format_ver.draft); + pkg_hdr->pkg_format_ver.major, pkg_hdr->pkg_format_ver.minor, + pkg_hdr->pkg_format_ver.update, + pkg_hdr->pkg_format_ver.draft); /* Search all package segments for the requested segment type */ for (i = 0; i < LE32_TO_CPU(pkg_hdr->seg_count); i++) { @@ -919,8 +941,7 @@ ice_update_pkg(struct ice_hw *hw, struct ice_buf *bufs, u32 count) last, &offset, &info, NULL); if (status) { - ice_debug(hw, ICE_DBG_PKG, - "Update pkg failed: err %d off %d inf %d\n", + ice_debug(hw, ICE_DBG_PKG, "Update pkg failed: err %d off %d inf %d\n", status, offset, info); break; } @@ -998,8 +1019,7 @@ ice_dwnld_cfg_bufs(struct ice_hw *hw, struct ice_buf *bufs, u32 count) /* Save AQ status from download package */ hw->pkg_dwnld_status = hw->adminq.sq_last_status; if (status) { - ice_debug(hw, ICE_DBG_PKG, - "Pkg download failed: err %d off %d inf %d\n", + ice_debug(hw, ICE_DBG_PKG, "Pkg download failed: err %d off %d inf %d\n", status, offset, info); break; } @@ -1008,6 +1028,13 @@ ice_dwnld_cfg_bufs(struct ice_hw *hw, struct ice_buf *bufs, u32 count) break; } + if (!status) { + status = ice_set_vlan_mode(hw); + if (status) + ice_debug(hw, ICE_DBG_PKG, "Failed to set VLAN mode: err %d\n", + status); + } + ice_release_global_cfg_lock(hw); return status; @@ -1048,13 +1075,15 @@ ice_download_pkg(struct ice_hw *hw, struct ice_seg *ice_seg) struct ice_buf_table *ice_buf_tbl; ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); - ice_debug(hw, ICE_DBG_PKG, "Segment version: %d.%d.%d.%d\n", - ice_seg->hdr.seg_ver.major, ice_seg->hdr.seg_ver.minor, - ice_seg->hdr.seg_ver.update, ice_seg->hdr.seg_ver.draft); + ice_debug(hw, ICE_DBG_PKG, "Segment format version: %d.%d.%d.%d\n", + ice_seg->hdr.seg_format_ver.major, + ice_seg->hdr.seg_format_ver.minor, + ice_seg->hdr.seg_format_ver.update, + ice_seg->hdr.seg_format_ver.draft); ice_debug(hw, ICE_DBG_PKG, "Seg: type 0x%X, size %d, name %s\n", LE32_TO_CPU(ice_seg->hdr.seg_type), - LE32_TO_CPU(ice_seg->hdr.seg_size), ice_seg->hdr.seg_name); + LE32_TO_CPU(ice_seg->hdr.seg_size), ice_seg->hdr.seg_id); ice_buf_tbl = ice_find_buf_table(ice_seg); @@ -1075,43 +1104,49 @@ ice_download_pkg(struct ice_hw *hw, struct ice_seg *ice_seg) static enum ice_status ice_init_pkg_info(struct ice_hw *hw, struct ice_pkg_hdr *pkg_hdr) { - struct ice_global_metadata_seg *meta_seg; struct ice_generic_seg_hdr *seg_hdr; ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); if (!pkg_hdr) return ICE_ERR_PARAM; - meta_seg = (struct ice_global_metadata_seg *) - ice_find_seg_in_pkg(hw, SEGMENT_TYPE_METADATA, pkg_hdr); - if (meta_seg) { - hw->pkg_ver = meta_seg->pkg_ver; - ice_memcpy(hw->pkg_name, meta_seg->pkg_name, - sizeof(hw->pkg_name), ICE_NONDMA_TO_NONDMA); + seg_hdr = (struct ice_generic_seg_hdr *) + ice_find_seg_in_pkg(hw, SEGMENT_TYPE_ICE, pkg_hdr); + if (seg_hdr) { + struct ice_meta_sect *meta; + struct ice_pkg_enum state; - 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.update, meta_seg->pkg_ver.draft, - meta_seg->pkg_name); - } else { - ice_debug(hw, ICE_DBG_INIT, - "Did not find metadata segment in driver package\n"); - return ICE_ERR_CFG; - } + ice_memset(&state, 0, sizeof(state), ICE_NONDMA_MEM); - seg_hdr = ice_find_seg_in_pkg(hw, SEGMENT_TYPE_ICE, pkg_hdr); - if (seg_hdr) { - hw->ice_pkg_ver = seg_hdr->seg_ver; - ice_memcpy(hw->ice_pkg_name, seg_hdr->seg_name, - sizeof(hw->ice_pkg_name), ICE_NONDMA_TO_NONDMA); - - ice_debug(hw, ICE_DBG_PKG, "Ice Pkg: %d.%d.%d.%d, %s\n", - seg_hdr->seg_ver.major, seg_hdr->seg_ver.minor, - seg_hdr->seg_ver.update, seg_hdr->seg_ver.draft, - seg_hdr->seg_name); + /* Get package information from the Metadata Section */ + meta = (struct ice_meta_sect *) + ice_pkg_enum_section((struct ice_seg *)seg_hdr, &state, + ICE_SID_METADATA); + if (!meta) { + ice_debug(hw, ICE_DBG_INIT, "Did not find ice metadata section in package\n"); + return ICE_ERR_CFG; + } + + hw->pkg_ver = meta->ver; + ice_memcpy(hw->pkg_name, meta->name, sizeof(meta->name), + ICE_NONDMA_TO_NONDMA); + + ice_debug(hw, ICE_DBG_PKG, "Pkg: %d.%d.%d.%d, %s\n", + meta->ver.major, meta->ver.minor, meta->ver.update, + meta->ver.draft, meta->name); + + hw->ice_seg_fmt_ver = seg_hdr->seg_format_ver; + ice_memcpy(hw->ice_seg_id, seg_hdr->seg_id, + sizeof(hw->ice_seg_id), ICE_NONDMA_TO_NONDMA); + + 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.minor, + seg_hdr->seg_format_ver.update, + seg_hdr->seg_format_ver.draft, + seg_hdr->seg_id); } else { - ice_debug(hw, ICE_DBG_INIT, - "Did not find ice segment in driver package\n"); + ice_debug(hw, ICE_DBG_INIT, "Did not find ice segment in driver package\n"); return ICE_ERR_CFG; } @@ -1133,7 +1168,7 @@ static enum ice_status ice_get_pkg_info(struct ice_hw *hw) 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); if (!pkg_info) return ICE_ERR_NO_MEMORY; @@ -1150,9 +1185,11 @@ static enum ice_status ice_get_pkg_info(struct ice_hw *hw) if (pkg_info->pkg_info[i].is_active) { flags[place++] = 'A'; hw->active_pkg_ver = pkg_info->pkg_info[i].ver; + hw->active_track_id = + LE32_TO_CPU(pkg_info->pkg_info[i].track_id); ice_memcpy(hw->active_pkg_name, pkg_info->pkg_info[i].name, - sizeof(hw->active_pkg_name), + sizeof(pkg_info->pkg_info[i].name), ICE_NONDMA_TO_NONDMA); hw->active_pkg_in_nvm = pkg_info->pkg_info[i].is_in_nvm; } @@ -1190,13 +1227,13 @@ static enum ice_status ice_verify_pkg(struct ice_pkg_hdr *pkg, u32 len) u32 seg_count; u32 i; - if (len < sizeof(*pkg)) + if (len < ice_struct_size(pkg, seg_offset, 1)) return ICE_ERR_BUF_TOO_SHORT; - if (pkg->format_ver.major != ICE_PKG_FMT_VER_MAJ || - pkg->format_ver.minor != ICE_PKG_FMT_VER_MNR || - pkg->format_ver.update != ICE_PKG_FMT_VER_UPD || - pkg->format_ver.draft != ICE_PKG_FMT_VER_DFT) + 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.update != ICE_PKG_FMT_VER_UPD || + pkg->pkg_format_ver.draft != ICE_PKG_FMT_VER_DFT) return ICE_ERR_CFG; /* pkg must have at least one segment */ @@ -1205,7 +1242,7 @@ static enum ice_status ice_verify_pkg(struct ice_pkg_hdr *pkg, u32 len) return ICE_ERR_CFG; /* 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; /* all segments must fit within length */ @@ -1253,6 +1290,8 @@ static void ice_init_pkg_regs(struct ice_hw *hw) #define ICE_SW_BLK_INP_MASK_L 0xFFFFFFFF #define ICE_SW_BLK_INP_MASK_H 0x0000FFFF #define ICE_SW_BLK_IDX 0 + if (hw->dcf_enabled) + return; /* setup Switch block input mask, which is 48-bits in two parts */ wr32(hw, GL_PREEXT_L2_PMASK0(ICE_SW_BLK_IDX), ICE_SW_BLK_INP_MASK_L); @@ -1277,6 +1316,151 @@ static enum ice_status ice_chk_pkg_version(struct ice_pkg_ver *pkg_ver) return ICE_SUCCESS; } +/** + * ice_chk_pkg_compat + * @hw: pointer to the hardware structure + * @ospkg: pointer to the package hdr + * @seg: pointer to the package segment hdr + * + * This function checks the package version compatibility with driver and NVM + */ +static enum ice_status +ice_chk_pkg_compat(struct ice_hw *hw, struct ice_pkg_hdr *ospkg, + struct ice_seg **seg) +{ + struct ice_aqc_get_pkg_info_resp *pkg; + enum ice_status status; + u16 size; + u32 i; + + ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); + + /* Check package version compatibility */ + status = ice_chk_pkg_version(&hw->pkg_ver); + if (status) { + ice_debug(hw, ICE_DBG_INIT, "Package version check failed.\n"); + return status; + } + + /* find ICE segment in given package */ + *seg = (struct ice_seg *)ice_find_seg_in_pkg(hw, SEGMENT_TYPE_ICE, + ospkg); + if (!*seg) { + ice_debug(hw, ICE_DBG_INIT, "no ice segment in package.\n"); + return ICE_ERR_CFG; + } + + /* Check if FW is compatible with the OS package */ + size = ice_struct_size(pkg, pkg_info, ICE_PKG_CNT); + pkg = (struct ice_aqc_get_pkg_info_resp *)ice_malloc(hw, size); + if (!pkg) + return ICE_ERR_NO_MEMORY; + + status = ice_aq_get_pkg_info_list(hw, pkg, size, NULL); + if (status) + goto fw_ddp_compat_free_alloc; + + for (i = 0; i < LE32_TO_CPU(pkg->count); i++) { + /* loop till we find the NVM package */ + if (!pkg->pkg_info[i].is_in_nvm) + continue; + if ((*seg)->hdr.seg_format_ver.major != + pkg->pkg_info[i].ver.major || + (*seg)->hdr.seg_format_ver.minor > + pkg->pkg_info[i].ver.minor) { + status = ICE_ERR_FW_DDP_MISMATCH; + ice_debug(hw, ICE_DBG_INIT, "OS package is not compatible with NVM.\n"); + } + /* done processing NVM package so break */ + break; + } +fw_ddp_compat_free_alloc: + ice_free(hw, pkg); + 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 * @hw: pointer to the hardware structure @@ -1327,23 +1511,15 @@ enum ice_status ice_init_pkg(struct ice_hw *hw, u8 *buf, u32 len) /* before downloading the package, check package version for * compatibility with driver */ - status = ice_chk_pkg_version(&hw->pkg_ver); + status = ice_chk_pkg_compat(hw, pkg, &seg); if (status) return status; - /* find segment in given package */ - seg = (struct ice_seg *)ice_find_seg_in_pkg(hw, SEGMENT_TYPE_ICE, pkg); - if (!seg) { - ice_debug(hw, ICE_DBG_INIT, "no ice segment in package.\n"); - return ICE_ERR_CFG; - } - /* initialize package hints and then download package */ ice_init_pkg_hints(hw, seg); status = ice_download_pkg(hw, seg); if (status == ICE_ERR_AQ_NO_WORK) { - ice_debug(hw, ICE_DBG_INIT, - "package previously loaded - no work.\n"); + ice_debug(hw, ICE_DBG_INIT, "package previously loaded - no work.\n"); status = ICE_SUCCESS; } @@ -1364,6 +1540,7 @@ enum ice_status ice_init_pkg(struct ice_hw *hw, u8 *buf, u32 len) */ ice_init_pkg_regs(hw); ice_fill_blk_tbls(hw); + ice_get_prof_index_max(hw); } else { ice_debug(hw, ICE_DBG_INIT, "package load failed, %d\n", status); @@ -1440,38 +1617,6 @@ static struct ice_buf_build *ice_pkg_buf_alloc(struct ice_hw *hw) 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 * @hw: pointer to the HW structure @@ -1514,18 +1659,13 @@ ice_get_sw_fv_bitmap(struct ice_hw *hw, enum ice_prof_type req_profs, struct ice_seg *ice_seg; struct ice_fv *fv; - ice_memset(&state, 0, sizeof(state), ICE_NONDMA_MEM); - if (req_profs == ICE_PROF_ALL) { - u16 i; - - for (i = 0; i < ICE_MAX_NUM_PROFILES; i++) - ice_set_bit(i, bm); + ice_bitmap_set(bm, 0, ICE_MAX_NUM_PROFILES); return; } + ice_memset(&state, 0, sizeof(state), ICE_NONDMA_MEM); ice_zero_bitmap(bm, ICE_MAX_NUM_PROFILES); - ice_seg = hw->seg; do { enum ice_prof_type prof_type; @@ -1682,7 +1822,7 @@ void ice_init_prof_result_bm(struct ice_hw *hw) * * Frees a package buffer */ -static void ice_pkg_buf_free(struct ice_hw *hw, struct ice_buf_build *bld) +void ice_pkg_buf_free(struct ice_hw *hw, struct ice_buf_build *bld) { ice_free(hw, bld); } @@ -1722,7 +1862,7 @@ ice_pkg_buf_reserve_section(struct ice_buf_build *bld, u16 count) bld->reserved_section_table_entries += count; data_end = LE16_TO_CPU(buf->data_end) + - (count * sizeof(buf->section_entry[0])); + FLEX_ARRAY_SIZE(buf, section_entry, count); buf->data_end = CPU_TO_LE16(data_end); return ICE_SUCCESS; @@ -1781,6 +1921,43 @@ ice_pkg_buf_alloc_section(struct ice_buf_build *bld, u32 type, u16 size) return NULL; } +/** + * ice_pkg_buf_alloc_single_section + * @hw: pointer to the HW structure + * @type: the section type value + * @size: the size of the section to reserve (in bytes) + * @section: returns pointer to the section + * + * Allocates a package buffer with a single section. + * Note: all package contents must be in Little Endian form. + */ +struct ice_buf_build * +ice_pkg_buf_alloc_single_section(struct ice_hw *hw, u32 type, u16 size, + void **section) +{ + struct ice_buf_build *buf; + + if (!section) + return NULL; + + buf = ice_pkg_buf_alloc(hw); + if (!buf) + return NULL; + + if (ice_pkg_buf_reserve_section(buf, 1)) + goto ice_pkg_buf_alloc_single_section_err; + + *section = ice_pkg_buf_alloc_section(buf, type, size); + if (!*section) + goto ice_pkg_buf_alloc_single_section_err; + + return buf; + +ice_pkg_buf_alloc_single_section_err: + ice_pkg_buf_free(hw, buf); + return NULL; +} + /** * ice_pkg_buf_get_active_sections * @bld: pointer to pkg build (allocated by ice_pkg_buf_alloc()) @@ -1808,7 +1985,7 @@ static u16 ice_pkg_buf_get_active_sections(struct ice_buf_build *bld) * * Return a pointer to the buffer's header */ -static struct ice_buf *ice_pkg_buf(struct ice_buf_build *bld) +struct ice_buf *ice_pkg_buf(struct ice_buf_build *bld) { if (!bld) return NULL; @@ -1817,7 +1994,7 @@ static struct ice_buf *ice_pkg_buf(struct ice_buf_build *bld) } /** - * ice_tunnel_port_in_use + * ice_tunnel_port_in_use_hlpr - helper function to determine tunnel usage * @hw: pointer to the HW structure * @port: port to search for * @index: optionally returns index @@ -1825,7 +2002,7 @@ static struct ice_buf *ice_pkg_buf(struct ice_buf_build *bld) * Returns whether a port is already in use as a tunnel, and optionally its * index */ -bool ice_tunnel_port_in_use(struct ice_hw *hw, u16 port, u16 *index) +static bool ice_tunnel_port_in_use_hlpr(struct ice_hw *hw, u16 port, u16 *index) { u16 i; @@ -1839,6 +2016,26 @@ bool ice_tunnel_port_in_use(struct ice_hw *hw, u16 port, u16 *index) return false; } +/** + * ice_tunnel_port_in_use + * @hw: pointer to the HW structure + * @port: port to search for + * @index: optionally returns index + * + * Returns whether a port is already in use as a tunnel, and optionally its + * index + */ +bool ice_tunnel_port_in_use(struct ice_hw *hw, u16 port, u16 *index) +{ + bool res; + + ice_acquire_lock(&hw->tnl_lock); + res = ice_tunnel_port_in_use_hlpr(hw, port, index); + ice_release_lock(&hw->tnl_lock); + + return res; +} + /** * ice_tunnel_get_type * @hw: pointer to the HW structure @@ -1850,15 +2047,21 @@ bool ice_tunnel_port_in_use(struct ice_hw *hw, u16 port, u16 *index) bool ice_tunnel_get_type(struct ice_hw *hw, u16 port, enum ice_tunnel_type *type) { + bool res = false; u16 i; + ice_acquire_lock(&hw->tnl_lock); + for (i = 0; i < hw->tnl.count && i < ICE_TUNNEL_MAX_ENTRIES; i++) if (hw->tnl.tbl[i].in_use && hw->tnl.tbl[i].port == port) { *type = hw->tnl.tbl[i].type; - return true; + res = true; + break; } - return false; + ice_release_lock(&hw->tnl_lock); + + return res; } /** @@ -1887,7 +2090,7 @@ ice_find_free_tunnel_entry(struct ice_hw *hw, enum ice_tunnel_type type, } /** - * ice_get_tunnel_port - retrieve an open tunnel port + * ice_get_open_tunnel_port - retrieve an open tunnel port * @hw: pointer to the HW structure * @type: tunnel type (TNL_ALL will return any open port) * @port: returns open port @@ -1896,16 +2099,22 @@ bool ice_get_open_tunnel_port(struct ice_hw *hw, enum ice_tunnel_type type, u16 *port) { + bool res = false; u16 i; + ice_acquire_lock(&hw->tnl_lock); + for (i = 0; i < hw->tnl.count && i < ICE_TUNNEL_MAX_ENTRIES; i++) if (hw->tnl.tbl[i].valid && hw->tnl.tbl[i].in_use && (type == TNL_ALL || hw->tnl.tbl[i].type == type)) { *port = hw->tnl.tbl[i].port; - return true; + res = true; + break; } - return false; + ice_release_lock(&hw->tnl_lock); + + return res; } /** @@ -1926,15 +2135,24 @@ ice_create_tunnel(struct ice_hw *hw, enum ice_tunnel_type type, u16 port) struct ice_buf_build *bld; u16 index; - if (ice_tunnel_port_in_use(hw, port, NULL)) - return ICE_ERR_ALREADY_EXISTS; + ice_acquire_lock(&hw->tnl_lock); - if (!ice_find_free_tunnel_entry(hw, type, &index)) - return ICE_ERR_OUT_OF_RANGE; + if (ice_tunnel_port_in_use_hlpr(hw, port, &index)) { + hw->tnl.tbl[index].ref++; + status = ICE_SUCCESS; + goto ice_create_tunnel_end; + } + + if (!ice_find_free_tunnel_entry(hw, type, &index)) { + status = ICE_ERR_OUT_OF_RANGE; + goto ice_create_tunnel_end; + } bld = ice_pkg_buf_alloc(hw); - if (!bld) - return ICE_ERR_NO_MEMORY; + if (!bld) { + status = ICE_ERR_NO_MEMORY; + goto ice_create_tunnel_end; + } /* allocate 2 sections, one for Rx parser, one for Tx parser */ if (ice_pkg_buf_reserve_section(bld, 2)) @@ -1942,14 +2160,14 @@ ice_create_tunnel(struct ice_hw *hw, enum ice_tunnel_type type, u16 port) sect_rx = (struct ice_boost_tcam_section *) ice_pkg_buf_alloc_section(bld, ICE_SID_RXPARSER_BOOST_TCAM, - sizeof(*sect_rx)); + ice_struct_size(sect_rx, tcam, 1)); if (!sect_rx) goto ice_create_tunnel_err; sect_rx->count = CPU_TO_LE16(1); sect_tx = (struct ice_boost_tcam_section *) ice_pkg_buf_alloc_section(bld, ICE_SID_TXPARSER_BOOST_TCAM, - sizeof(*sect_tx)); + ice_struct_size(sect_tx, tcam, 1)); if (!sect_tx) goto ice_create_tunnel_err; sect_tx->count = CPU_TO_LE16(1); @@ -1974,11 +2192,15 @@ ice_create_tunnel(struct ice_hw *hw, enum ice_tunnel_type type, u16 port) if (!status) { hw->tnl.tbl[index].port = port; hw->tnl.tbl[index].in_use = true; + hw->tnl.tbl[index].ref = 1; } ice_create_tunnel_err: ice_pkg_buf_free(hw, bld); +ice_create_tunnel_end: + ice_release_lock(&hw->tnl_lock); + return status; } @@ -1998,8 +2220,18 @@ enum ice_status ice_destroy_tunnel(struct ice_hw *hw, u16 port, bool all) enum ice_status status = ICE_ERR_MAX_LIMIT; struct ice_buf_build *bld; u16 count = 0; + u16 index; u16 size; - u16 i; + u16 i, j; + + ice_acquire_lock(&hw->tnl_lock); + + if (!all && ice_tunnel_port_in_use_hlpr(hw, port, &index)) + if (hw->tnl.tbl[index].ref > 1) { + hw->tnl.tbl[index].ref--; + status = ICE_SUCCESS; + goto ice_destroy_tunnel_end; + } /* determine count */ for (i = 0; i < hw->tnl.count && i < ICE_TUNNEL_MAX_ENTRIES; i++) @@ -2007,15 +2239,19 @@ enum ice_status ice_destroy_tunnel(struct ice_hw *hw, u16 port, bool all) (all || hw->tnl.tbl[i].port == port)) count++; - if (!count) - return ICE_ERR_PARAM; + if (!count) { + status = ICE_ERR_PARAM; + goto ice_destroy_tunnel_end; + } /* 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); - if (!bld) - return ICE_ERR_NO_MEMORY; + if (!bld) { + status = ICE_ERR_NO_MEMORY; + goto ice_destroy_tunnel_end; + } /* allocate 2 sections, one for Rx parser, one for Tx parser */ if (ice_pkg_buf_reserve_section(bld, 2)) @@ -2026,30 +2262,31 @@ enum ice_status ice_destroy_tunnel(struct ice_hw *hw, u16 port, bool all) size); if (!sect_rx) goto ice_destroy_tunnel_err; - sect_rx->count = CPU_TO_LE16(1); + sect_rx->count = CPU_TO_LE16(count); sect_tx = (struct ice_boost_tcam_section *) ice_pkg_buf_alloc_section(bld, ICE_SID_TXPARSER_BOOST_TCAM, size); if (!sect_tx) goto ice_destroy_tunnel_err; - sect_tx->count = CPU_TO_LE16(1); + sect_tx->count = CPU_TO_LE16(count); /* copy original boost entry to update package buffer, one copy to Rx * section, another copy to the Tx section */ - for (i = 0; i < hw->tnl.count && i < ICE_TUNNEL_MAX_ENTRIES; i++) + for (i = 0, j = 0; i < hw->tnl.count && i < ICE_TUNNEL_MAX_ENTRIES; i++) if (hw->tnl.tbl[i].valid && hw->tnl.tbl[i].in_use && (all || hw->tnl.tbl[i].port == port)) { - ice_memcpy(sect_rx->tcam + i, + ice_memcpy(sect_rx->tcam + j, hw->tnl.tbl[i].boost_entry, sizeof(*sect_rx->tcam), ICE_NONDMA_TO_NONDMA); - ice_memcpy(sect_tx->tcam + i, + ice_memcpy(sect_tx->tcam + j, hw->tnl.tbl[i].boost_entry, sizeof(*sect_tx->tcam), ICE_NONDMA_TO_NONDMA); hw->tnl.tbl[i].marked = true; + j++; } status = ice_update_pkg(hw, ice_pkg_buf(bld), 1); @@ -2057,6 +2294,7 @@ enum ice_status ice_destroy_tunnel(struct ice_hw *hw, u16 port, bool all) for (i = 0; i < hw->tnl.count && i < ICE_TUNNEL_MAX_ENTRIES; i++) if (hw->tnl.tbl[i].marked) { + hw->tnl.tbl[i].ref = 0; hw->tnl.tbl[i].port = 0; hw->tnl.tbl[i].in_use = false; hw->tnl.tbl[i].marked = false; @@ -2065,6 +2303,9 @@ enum ice_status ice_destroy_tunnel(struct ice_hw *hw, u16 port, bool all) ice_destroy_tunnel_err: ice_pkg_buf_free(hw, bld); +ice_destroy_tunnel_end: + ice_release_lock(&hw->tnl_lock); + return status; } @@ -2299,12 +2540,10 @@ ice_match_prop_lst(struct LIST_HEAD_TYPE *list1, struct LIST_HEAD_TYPE *list2) u16 count = 0; /* compare counts */ - LIST_FOR_EACH_ENTRY(tmp1, list1, ice_vsig_prof, list) { + LIST_FOR_EACH_ENTRY(tmp1, list1, ice_vsig_prof, list) count++; - } - LIST_FOR_EACH_ENTRY(tmp2, list2, ice_vsig_prof, list) { + LIST_FOR_EACH_ENTRY(tmp2, list2, ice_vsig_prof, list) chk_count++; - } if (!count || count != chk_count) return false; @@ -2413,13 +2652,12 @@ ice_find_dup_props_vsig(struct ice_hw *hw, enum ice_block blk, struct ice_xlt2 *xlt2 = &hw->blk[blk].xlt2; u16 i; - for (i = 0; i < xlt2->count; i++) { + 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 = ICE_VSIG_VALUE(i, hw->pf_id); return ICE_SUCCESS; } - } return ICE_ERR_DOES_NOT_EXIST; } @@ -2609,7 +2847,7 @@ ice_vsig_add_mv_vsi(struct ice_hw *hw, enum ice_block blk, u16 vsi, u16 vsig) * @blk: HW block * @prof: profile to check * @idx: profile index to check - * @masks: masks to match + * @mask: mask to match */ static bool ice_prof_has_mask_idx(struct ice_hw *hw, enum ice_block blk, u8 prof, u16 idx, @@ -2682,6 +2920,12 @@ ice_find_prof_id_with_mask(struct ice_hw *hw, enum ice_block blk, struct ice_es *es = &hw->blk[blk].es; u8 i; + /* For FD and RSS, we don't want to re-use an existed profile with the + * same field vector and mask. This will cause rule interference. + */ + if (blk == ICE_BLK_FD || blk == ICE_BLK_RSS) + return ICE_ERR_DOES_NOT_EXIST; + for (i = 0; i < (u8)es->count; i++) { u16 off = i * es->fvw; @@ -2761,20 +3005,22 @@ static bool ice_tcam_ent_rsrc_type(enum ice_block blk, u16 *rsrc_type) * ice_alloc_tcam_ent - allocate hardware TCAM entry * @hw: pointer to the HW struct * @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 * * This function allocates a new entry in a Profile ID TCAM for a specific * block. */ 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; if (!ice_tcam_ent_rsrc_type(blk, &res_type)) 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); } /** @@ -3129,7 +3375,6 @@ static void ice_shutdown_prof_masks(struct ice_hw *hw, enum ice_block blk) /** * ice_shutdown_all_prof_masks - releases all locks for masking * @hw: pointer to the HW struct - * @blk: hardware block * * This should be called before unloading the driver */ @@ -3144,12 +3389,11 @@ void ice_shutdown_all_prof_masks(struct ice_hw *hw) * @hw: pointer to the HW struct * @blk: hardware block * @prof_id: profile ID - * @es: field vector * @masks: masks */ static enum ice_status ice_update_prof_masking(struct ice_hw *hw, enum ice_block blk, u16 prof_id, - struct ice_fv_word *es, u16 *masks) + u16 *masks) { bool err = false; u32 ena_mask = 0; @@ -3534,6 +3778,8 @@ static void ice_free_flow_profs(struct ice_hw *hw, u8 blk_idx) LIST_DEL(&p->l_entry); if (p->acts) ice_free(hw, p->acts); + + ice_destroy_lock(&p->entries_lock); ice_free(hw, p); } ice_release_lock(&hw->fl_profs_locks[blk_idx]); @@ -3602,7 +3848,8 @@ void ice_free_hw_tbls(struct ice_hw *hw) ice_free(hw, r); } ice_destroy_lock(&hw->rss_locks); - ice_shutdown_all_prof_masks(hw); + if (!hw->dcf_enabled) + ice_shutdown_all_prof_masks(hw); ice_memset(hw->blk, 0, sizeof(hw->blk), ICE_NONDMA_MEM); } @@ -3661,7 +3908,7 @@ void ice_clear_hw_tbls(struct ice_hw *hw) prof_redir->count * sizeof(*prof_redir->t), 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_memset(es->ref_count, 0, es->count * sizeof(*es->ref_count), ICE_NONDMA_MEM); @@ -3682,7 +3929,8 @@ enum ice_status ice_init_hw_tbls(struct ice_hw *hw) ice_init_lock(&hw->rss_locks); INIT_LIST_HEAD(&hw->rss_list_head); - ice_init_all_prof_masks(hw); + if (!hw->dcf_enabled) + ice_init_all_prof_masks(hw); for (i = 0; i < ICE_BLK_COUNT; i++) { struct ice_prof_redir *prof_redir = &hw->blk[i].prof_redir; struct ice_prof_tcam *prof = &hw->blk[i].prof; @@ -3772,11 +4020,19 @@ enum ice_status ice_init_hw_tbls(struct ice_hw *hw) es->ref_count = (u16 *) ice_calloc(hw, es->count, sizeof(*es->ref_count)); + if (!es->ref_count) + goto err; + es->written = (u8 *) ice_calloc(hw, es->count, sizeof(*es->written)); + + if (!es->written) + goto err; + es->mask_ena = (u32 *) ice_calloc(hw, es->count, sizeof(*es->mask_ena)); - if (!es->ref_count) + + if (!es->mask_ena) goto err; } return ICE_SUCCESS; @@ -3849,7 +4105,7 @@ ice_prof_gen_key(struct ice_hw *hw, enum ice_block blk, u8 ptg, u16 vsig, * @prof_id: profile ID * @ptg: packet type group (PTG) portion of key * @vsig: VSIG portion of key - * @cdid: CDID: portion of key + * @cdid: CDID portion of key * @flags: flag portion of key * @vl_msk: valid mask * @dc_msk: don't care mask @@ -3916,13 +4172,11 @@ ice_has_prof_vsig(struct ice_hw *hw, enum ice_block blk, u16 vsig, u64 hdl) struct ice_vsig_prof *ent; 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) return true; - } - ice_debug(hw, ICE_DBG_INIT, - "Characteristic list for VSI group %d not found.\n", + ice_debug(hw, ICE_DBG_INIT, "Characteristic list for VSI group %d not found.\n", vsig); return false; } @@ -3941,7 +4195,7 @@ ice_prof_bld_es(struct ice_hw *hw, enum ice_block blk, u16 vec_size = hw->blk[blk].es.fvw * sizeof(struct ice_fv_word); 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) { u16 off = tmp->prof_id * hw->blk[blk].es.fvw; struct ice_pkg_es *p; @@ -3949,7 +4203,9 @@ ice_prof_bld_es(struct ice_hw *hw, enum ice_block blk, id = ice_sect_id(blk, ICE_VEC_TBL); 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 - sizeof(p->es[0])); @@ -3962,7 +4218,6 @@ ice_prof_bld_es(struct ice_hw *hw, enum ice_block blk, ice_memcpy(p->es, &hw->blk[blk].es.t[off], vec_size, ICE_NONDMA_TO_NONDMA); } - } return ICE_SUCCESS; } @@ -3980,14 +4235,17 @@ ice_prof_bld_tcam(struct ice_hw *hw, enum ice_block blk, { struct ice_chs_chg *tmp; - LIST_FOR_EACH_ENTRY(tmp, chgs, ice_chs_chg, list_entry) { + LIST_FOR_EACH_ENTRY(tmp, chgs, ice_chs_chg, list_entry) if (tmp->type == ICE_TCAM_ADD && tmp->add_tcam_idx) { struct ice_prof_id_section *p; u32 id; id = ice_sect_id(blk, ICE_PROF_TCAM); 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) return ICE_ERR_MAX_LIMIT; @@ -4001,7 +4259,6 @@ ice_prof_bld_tcam(struct ice_hw *hw, enum ice_block blk, sizeof(hw->blk[blk].prof.t->key), ICE_NONDMA_TO_NONDMA); } - } return ICE_SUCCESS; } @@ -4018,14 +4275,17 @@ ice_prof_bld_xlt1(enum ice_block blk, struct ice_buf_build *bld, { 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) { struct ice_xlt1_section *p; u32 id; id = ice_sect_id(blk, ICE_XLT1); 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) return ICE_ERR_MAX_LIMIT; @@ -4034,7 +4294,6 @@ ice_prof_bld_xlt1(enum ice_block blk, struct ice_buf_build *bld, p->offset = CPU_TO_LE16(tmp->ptype); p->value[0] = tmp->ptg; } - } return ICE_SUCCESS; } @@ -4061,7 +4320,10 @@ ice_prof_bld_xlt2(enum ice_block blk, struct ice_buf_build *bld, case ICE_VSIG_REM: id = ice_sect_id(blk, ICE_XLT2); 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) return ICE_ERR_MAX_LIMIT; @@ -4265,13 +4527,12 @@ ice_update_fd_swap(struct ice_hw *hw, u16 prof_id, struct ice_fv_word *es) ICE_PROT_INVALID) first_free = i - 1; - for (j = 0; j < ICE_FD_SRC_DST_PAIR_COUNT; j++) { + for (j = 0; j < ICE_FD_SRC_DST_PAIR_COUNT; j++) if (es[i].prot_id == ice_fd_pairs[j].prot_id && es[i].off == ice_fd_pairs[j].off) { ice_set_bit(j, pair_list); pair_start[j] = i; } - } } orig_free = first_free; @@ -4328,7 +4589,7 @@ ice_update_fd_swap(struct ice_hw *hw, u16 prof_id, struct ice_fv_word *es) } /* check for a swap location */ - for (j = 0; j < ICE_FD_SRC_DST_PAIR_COUNT; j++) { + for (j = 0; j < ICE_FD_SRC_DST_PAIR_COUNT; j++) if (es[si].prot_id == ice_fd_pairs[j].prot_id && es[si].off == ice_fd_pairs[j].off) { u8 idx; @@ -4344,7 +4605,6 @@ ice_update_fd_swap(struct ice_hw *hw, u16 prof_id, struct ice_fv_word *es) break; } - } si -= indexes_used; } @@ -4491,7 +4751,7 @@ ice_add_prof(struct ice_hw *hw, enum ice_block blk, u64 id, u8 ptypes[], if (status) goto err_ice_add_prof; } - status = ice_update_prof_masking(hw, blk, prof_id, es, masks); + status = ice_update_prof_masking(hw, blk, prof_id, masks); if (status) goto err_ice_add_prof; @@ -4521,50 +4781,42 @@ ice_add_prof(struct ice_hw *hw, enum ice_block blk, u64 id, u8 ptypes[], byte++; continue; } + /* Examine 8 bits per byte */ - for (bit = 0; bit < 8; bit++) { - if (ptypes[byte] & BIT(bit)) { - u16 ptype; - u8 ptg; - u8 m; + ice_for_each_set_bit(bit, (ice_bitmap_t *)&ptypes[byte], + BITS_PER_BYTE) { + u16 ptype; + u8 ptg; - ptype = byte * BITS_PER_BYTE + bit; + ptype = byte * BITS_PER_BYTE + bit; - /* The package should place all ptypes in a - * non-zero PTG, so the following call should - * never fail. - */ - if (ice_ptg_find_ptype(hw, blk, ptype, &ptg)) - continue; + /* The package should place all ptypes in a non-zero + * PTG, so the following call should never fail. + */ + if (ice_ptg_find_ptype(hw, blk, ptype, &ptg)) + continue; - /* If PTG is already added, skip and continue */ - if (ice_is_bit_set(ptgs_used, ptg)) - continue; + /* If PTG is already added, skip and continue */ + if (ice_is_bit_set(ptgs_used, ptg)) + continue; - ice_set_bit(ptg, ptgs_used); - /* Check to see there are any attributes for - * this ptype, and add them if found. + ice_set_bit(ptg, ptgs_used); + /* Check to see there are any attributes for this + * ptype, and add them if found. + */ + status = ice_add_prof_attrib(prof, ptg, ptype, attr, + attr_cnt); + if (status == ICE_ERR_MAX_LIMIT) + break; + if (status) { + /* This is simple a ptype/PTG with no + * attribute */ - status = ice_add_prof_attrib(prof, ptg, ptype, - attr, attr_cnt); - if (status == ICE_ERR_MAX_LIMIT) - break; - if (status) { - /* This is simple a ptype/PTG with no - * attribute - */ - prof->ptg[prof->ptg_cnt] = ptg; - prof->attr[prof->ptg_cnt].flags = 0; - prof->attr[prof->ptg_cnt].mask = 0; - - if (++prof->ptg_cnt >= - ICE_MAX_PTG_PER_PROFILE) - break; - } + prof->ptg[prof->ptg_cnt] = ptg; + prof->attr[prof->ptg_cnt].flags = 0; + prof->attr[prof->ptg_cnt].mask = 0; - /* nothing left in byte, then exit */ - m = ~(u8)((1 << (bit + 1)) - 1); - if (!(ptypes[byte] & m)) + if (++prof->ptg_cnt >= ICE_MAX_PTG_PER_PROFILE) break; } } @@ -4582,47 +4834,25 @@ err_ice_add_prof: } /** - * 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 * @blk: hardware block * @id: profile tracking ID * - * This will search for a profile tracking ID which was previously added. This - * version assumes that the caller has already acquired the prof map lock. + * This will search for a profile tracking ID which was previously added. + * The profile map lock should be held before calling this function. */ -static struct ice_prof_map * -ice_search_prof_id_low(struct ice_hw *hw, enum ice_block blk, u64 id) +struct ice_prof_map * +ice_search_prof_id(struct ice_hw *hw, enum ice_block blk, u64 id) { struct ice_prof_map *entry = NULL; struct ice_prof_map *map; - LIST_FOR_EACH_ENTRY(map, &hw->blk[blk].es.prof_map, ice_prof_map, - list) { + LIST_FOR_EACH_ENTRY(map, &hw->blk[blk].es.prof_map, ice_prof_map, list) if (map->profile_cookie == id) { entry = map; break; } - } - - 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; } @@ -4640,9 +4870,8 @@ ice_vsig_prof_id_count(struct ice_hw *hw, enum ice_block blk, u16 vsig) struct ice_vsig_prof *p; LIST_FOR_EACH_ENTRY(p, &hw->blk[blk].xlt2.vsig_tbl[idx].prop_lst, - ice_vsig_prof, list) { + ice_vsig_prof, list) count++; - } return count; } @@ -4687,7 +4916,7 @@ ice_rem_prof_id(struct ice_hw *hw, enum ice_block blk, enum ice_status status; u16 i; - for (i = 0; i < prof->tcam_count; i++) { + for (i = 0; i < prof->tcam_count; i++) if (prof->tcam[i].in_use) { prof->tcam[i].in_use = false; status = ice_rel_tcam_idx(hw, blk, @@ -4695,7 +4924,6 @@ ice_rem_prof_id(struct ice_hw *hw, enum ice_block blk, if (status) return ICE_ERR_HW_TABLE; } - } return ICE_SUCCESS; } @@ -4733,7 +4961,7 @@ ice_rem_vsig(struct ice_hw *hw, enum ice_block blk, u16 vsig, /* If the VSIG has at least 1 VSI then iterate through the list * and remove the VSIs before deleting the group. */ - if (vsi_cur) { + if (vsi_cur) do { struct ice_vsig_vsi *tmp = vsi_cur->next_vsi; struct ice_chs_chg *p; @@ -4751,7 +4979,6 @@ ice_rem_vsig(struct ice_hw *hw, enum ice_block blk, u16 vsig, vsi_cur = tmp; } while (vsi_cur); - } return ice_vsig_free(hw, blk, vsig); } @@ -4774,7 +5001,7 @@ ice_rem_prof_id_vsig(struct ice_hw *hw, enum ice_block blk, u16 vsig, u64 hdl, LIST_FOR_EACH_ENTRY_SAFE(p, t, &hw->blk[blk].xlt2.vsig_tbl[idx].prop_lst, - ice_vsig_prof, list) { + ice_vsig_prof, list) if (p->profile_cookie == hdl) { if (ice_vsig_prof_id_count(hw, blk, vsig) == 1) /* this is the last profile, remove the VSIG */ @@ -4787,7 +5014,6 @@ ice_rem_prof_id_vsig(struct ice_hw *hw, enum ice_block blk, u16 vsig, u64 hdl, } return status; } - } return ICE_ERR_DOES_NOT_EXIST; } @@ -4808,7 +5034,7 @@ ice_rem_flow_all(struct ice_hw *hw, enum ice_block blk, u64 id) 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 (ice_has_prof_vsig(hw, blk, i, id)) { status = ice_rem_prof_id_vsig(hw, blk, i, id, @@ -4817,7 +5043,6 @@ ice_rem_flow_all(struct ice_hw *hw, enum ice_block blk, u64 id) goto err_ice_rem_flow_all; } } - } status = ice_upd_prof_hw(hw, blk, &chg); @@ -4847,7 +5072,7 @@ enum ice_status ice_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 id) 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) { status = ICE_ERR_DOES_NOT_EXIST; goto err_ice_rem_prof; @@ -4880,21 +5105,27 @@ static enum ice_status ice_get_prof(struct ice_hw *hw, enum ice_block blk, u64 hdl, struct LIST_HEAD_TYPE *chg) { + enum ice_status status = ICE_SUCCESS; struct ice_prof_map *map; struct ice_chs_chg *p; u16 i; + 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) - return ICE_ERR_DOES_NOT_EXIST; + if (!map) { + 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]) { /* add ES to change list */ p = (struct ice_chs_chg *)ice_malloc(hw, sizeof(*p)); - if (!p) + if (!p) { + status = ICE_ERR_NO_MEMORY; goto err_ice_get_prof; + } p->type = ICE_PTG_ES_ADD; p->ptype = 0; @@ -4909,13 +5140,11 @@ ice_get_prof(struct ice_hw *hw, enum ice_block blk, u64 hdl, LIST_ADD(&p->list_entry, chg); } - } - - return ICE_SUCCESS; err_ice_get_prof: + ice_release_lock(&hw->blk[blk].es.prof_map_lock); /* let caller clean up the change list */ - return ICE_ERR_NO_MEMORY; + return status; } /** @@ -4969,17 +5198,23 @@ static enum ice_status ice_add_prof_to_lst(struct ice_hw *hw, enum ice_block blk, struct LIST_HEAD_TYPE *lst, u64 hdl) { + enum ice_status status = ICE_SUCCESS; struct ice_prof_map *map; struct ice_vsig_prof *p; u16 i; + ice_acquire_lock(&hw->blk[blk].es.prof_map_lock); map = ice_search_prof_id(hw, blk, hdl); - if (!map) - return ICE_ERR_DOES_NOT_EXIST; + if (!map) { + status = ICE_ERR_DOES_NOT_EXIST; + goto err_ice_add_prof_to_lst; + } p = (struct ice_vsig_prof *)ice_malloc(hw, sizeof(*p)); - if (!p) - return ICE_ERR_NO_MEMORY; + if (!p) { + status = ICE_ERR_NO_MEMORY; + goto err_ice_add_prof_to_lst; + } p->profile_cookie = map->profile_cookie; p->prof_id = map->prof_id; @@ -4994,7 +5229,9 @@ ice_add_prof_to_lst(struct ice_hw *hw, enum ice_block blk, 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; } /** @@ -5061,12 +5298,11 @@ ice_rem_chg_tcam_ent(struct ice_hw *hw, u16 idx, struct LIST_HEAD_TYPE *chg) { 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) { LIST_DEL(&tmp->list_entry); ice_free(hw, tmp); } - } } /** @@ -5107,7 +5343,12 @@ ice_prof_tcam_ena_dis(struct ice_hw *hw, enum ice_block blk, bool enable, } /* for re-enabling, reallocate a TCAM */ - status = ice_alloc_tcam_ent(hw, blk, &tcam->tcam_idx); + /* for entries with empty attribute masks, allocate entry from + * the bottom of the TCAM table; otherwise, allocate from the + * top of the table in order to give it higher priority + */ + status = ice_alloc_tcam_ent(hw, blk, tcam->attr.mask == 0, + &tcam->tcam_idx); if (status) return status; @@ -5247,8 +5488,7 @@ ice_adj_prof_priorities(struct ice_hw *hw, enum ice_block blk, u16 vsig, if (attr_used_cnt < ICE_MAX_PTG_ATTRS) attr_used[attr_used_cnt++] = &t->tcam[i]; else - ice_debug(hw, ICE_DBG_INIT, - "Warn: ICE_MAX_PTG_ATTRS exceeded\n"); + ice_debug(hw, ICE_DBG_INIT, "Warn: ICE_MAX_PTG_ATTRS exceeded\n"); } } @@ -5274,16 +5514,12 @@ ice_add_prof_id_vsig(struct ice_hw *hw, enum ice_block blk, u16 vsig, u64 hdl, 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 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_vsig_prof *t; struct ice_chs_chg *p; 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 */ if (ice_has_prof_vsig(hw, blk, vsig, hdl)) return ICE_ERR_ALREADY_EXISTS; @@ -5293,22 +5529,36 @@ ice_add_prof_id_vsig(struct ice_hw *hw, enum ice_block blk, u16 vsig, u64 hdl, if (!t) 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->prof_id = map->prof_id; t->tcam_count = map->ptg_cnt; /* create TCAM entries */ for (i = 0; i < map->ptg_cnt; i++) { - enum ice_status status; u16 tcam_idx; /* add TCAM to change list */ 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; + } /* allocate the TCAM entry index */ - status = ice_alloc_tcam_ent(hw, blk, &tcam_idx); + /* for entries with empty attribute masks, allocate entry from + * the bottom of the TCAM table; otherwise, allocate from the + * top of the table in order to give it higher priority + */ + status = ice_alloc_tcam_ent(hw, blk, map->attr[i].mask == 0, + &tcam_idx); if (status) { ice_free(hw, p); goto err_ice_add_prof_id_vsig; @@ -5354,12 +5604,14 @@ ice_add_prof_id_vsig(struct ice_hw *hw, enum ice_block blk, u16 vsig, u64 hdl, LIST_ADD(&t->list, &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: + ice_release_lock(&hw->blk[blk].es.prof_map_lock); /* let caller clean up the change list */ ice_free(hw, t); - return ICE_ERR_NO_MEMORY; + return status; } /** @@ -5679,13 +5931,12 @@ ice_rem_prof_from_list(struct ice_hw *hw, struct LIST_HEAD_TYPE *lst, u64 hdl) { 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) { LIST_DEL(&ent->list); ice_free(hw, ent); return ICE_SUCCESS; } - } return ICE_ERR_DOES_NOT_EXIST; } @@ -5736,7 +5987,7 @@ ice_rem_prof_id_flow(struct ice_hw *hw, enum ice_block blk, u16 vsi, u64 hdl) if (last_profile) { /* 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); if (status)