171d10453SEric Joyner /* SPDX-License-Identifier: BSD-3-Clause */ 2015f8cc5SEric Joyner /* Copyright (c) 2024, Intel Corporation 371d10453SEric Joyner * All rights reserved. 471d10453SEric Joyner * 571d10453SEric Joyner * Redistribution and use in source and binary forms, with or without 671d10453SEric Joyner * modification, are permitted provided that the following conditions are met: 771d10453SEric Joyner * 871d10453SEric Joyner * 1. Redistributions of source code must retain the above copyright notice, 971d10453SEric Joyner * this list of conditions and the following disclaimer. 1071d10453SEric Joyner * 1171d10453SEric Joyner * 2. Redistributions in binary form must reproduce the above copyright 1271d10453SEric Joyner * notice, this list of conditions and the following disclaimer in the 1371d10453SEric Joyner * documentation and/or other materials provided with the distribution. 1471d10453SEric Joyner * 1571d10453SEric Joyner * 3. Neither the name of the Intel Corporation nor the names of its 1671d10453SEric Joyner * contributors may be used to endorse or promote products derived from 1771d10453SEric Joyner * this software without specific prior written permission. 1871d10453SEric Joyner * 1971d10453SEric Joyner * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2071d10453SEric Joyner * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2171d10453SEric Joyner * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2271d10453SEric Joyner * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 2371d10453SEric Joyner * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2471d10453SEric Joyner * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2571d10453SEric Joyner * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2671d10453SEric Joyner * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2771d10453SEric Joyner * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2871d10453SEric Joyner * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 2971d10453SEric Joyner * POSSIBILITY OF SUCH DAMAGE. 3071d10453SEric Joyner */ 3171d10453SEric Joyner 3271d10453SEric Joyner #include "ice_common.h" 338923de59SPiotr Kubaj #include "ice_ddp_common.h" 3471d10453SEric Joyner #include "ice_flex_pipe.h" 3571d10453SEric Joyner #include "ice_protocol_type.h" 3671d10453SEric Joyner #include "ice_flow.h" 3771d10453SEric Joyner 3871d10453SEric Joyner static const struct ice_tunnel_type_scan tnls[] = { 3971d10453SEric Joyner { TNL_VXLAN, "TNL_VXLAN_PF" }, 4071d10453SEric Joyner { TNL_GENEVE, "TNL_GENEVE_PF" }, 4171d10453SEric Joyner { TNL_LAST, "" } 4271d10453SEric Joyner }; 4371d10453SEric Joyner 4471d10453SEric Joyner static const u32 ice_sect_lkup[ICE_BLK_COUNT][ICE_SECT_COUNT] = { 4571d10453SEric Joyner /* SWITCH */ 4671d10453SEric Joyner { 4771d10453SEric Joyner ICE_SID_XLT0_SW, 4871d10453SEric Joyner ICE_SID_XLT_KEY_BUILDER_SW, 4971d10453SEric Joyner ICE_SID_XLT1_SW, 5071d10453SEric Joyner ICE_SID_XLT2_SW, 5171d10453SEric Joyner ICE_SID_PROFID_TCAM_SW, 5271d10453SEric Joyner ICE_SID_PROFID_REDIR_SW, 5371d10453SEric Joyner ICE_SID_FLD_VEC_SW, 5471d10453SEric Joyner ICE_SID_CDID_KEY_BUILDER_SW, 5571d10453SEric Joyner ICE_SID_CDID_REDIR_SW 5671d10453SEric Joyner }, 5771d10453SEric Joyner 5871d10453SEric Joyner /* ACL */ 5971d10453SEric Joyner { 6071d10453SEric Joyner ICE_SID_XLT0_ACL, 6171d10453SEric Joyner ICE_SID_XLT_KEY_BUILDER_ACL, 6271d10453SEric Joyner ICE_SID_XLT1_ACL, 6371d10453SEric Joyner ICE_SID_XLT2_ACL, 6471d10453SEric Joyner ICE_SID_PROFID_TCAM_ACL, 6571d10453SEric Joyner ICE_SID_PROFID_REDIR_ACL, 6671d10453SEric Joyner ICE_SID_FLD_VEC_ACL, 6771d10453SEric Joyner ICE_SID_CDID_KEY_BUILDER_ACL, 6871d10453SEric Joyner ICE_SID_CDID_REDIR_ACL 6971d10453SEric Joyner }, 7071d10453SEric Joyner 7171d10453SEric Joyner /* FD */ 7271d10453SEric Joyner { 7371d10453SEric Joyner ICE_SID_XLT0_FD, 7471d10453SEric Joyner ICE_SID_XLT_KEY_BUILDER_FD, 7571d10453SEric Joyner ICE_SID_XLT1_FD, 7671d10453SEric Joyner ICE_SID_XLT2_FD, 7771d10453SEric Joyner ICE_SID_PROFID_TCAM_FD, 7871d10453SEric Joyner ICE_SID_PROFID_REDIR_FD, 7971d10453SEric Joyner ICE_SID_FLD_VEC_FD, 8071d10453SEric Joyner ICE_SID_CDID_KEY_BUILDER_FD, 8171d10453SEric Joyner ICE_SID_CDID_REDIR_FD 8271d10453SEric Joyner }, 8371d10453SEric Joyner 8471d10453SEric Joyner /* RSS */ 8571d10453SEric Joyner { 8671d10453SEric Joyner ICE_SID_XLT0_RSS, 8771d10453SEric Joyner ICE_SID_XLT_KEY_BUILDER_RSS, 8871d10453SEric Joyner ICE_SID_XLT1_RSS, 8971d10453SEric Joyner ICE_SID_XLT2_RSS, 9071d10453SEric Joyner ICE_SID_PROFID_TCAM_RSS, 9171d10453SEric Joyner ICE_SID_PROFID_REDIR_RSS, 9271d10453SEric Joyner ICE_SID_FLD_VEC_RSS, 9371d10453SEric Joyner ICE_SID_CDID_KEY_BUILDER_RSS, 9471d10453SEric Joyner ICE_SID_CDID_REDIR_RSS 9571d10453SEric Joyner }, 9671d10453SEric Joyner 9771d10453SEric Joyner /* PE */ 9871d10453SEric Joyner { 9971d10453SEric Joyner ICE_SID_XLT0_PE, 10071d10453SEric Joyner ICE_SID_XLT_KEY_BUILDER_PE, 10171d10453SEric Joyner ICE_SID_XLT1_PE, 10271d10453SEric Joyner ICE_SID_XLT2_PE, 10371d10453SEric Joyner ICE_SID_PROFID_TCAM_PE, 10471d10453SEric Joyner ICE_SID_PROFID_REDIR_PE, 10571d10453SEric Joyner ICE_SID_FLD_VEC_PE, 10671d10453SEric Joyner ICE_SID_CDID_KEY_BUILDER_PE, 10771d10453SEric Joyner ICE_SID_CDID_REDIR_PE 10871d10453SEric Joyner } 10971d10453SEric Joyner }; 11071d10453SEric Joyner 11171d10453SEric Joyner /** 11271d10453SEric Joyner * ice_sect_id - returns section ID 11371d10453SEric Joyner * @blk: block type 11471d10453SEric Joyner * @sect: section type 11571d10453SEric Joyner * 11671d10453SEric Joyner * This helper function returns the proper section ID given a block type and a 11771d10453SEric Joyner * section type. 11871d10453SEric Joyner */ 11971d10453SEric Joyner static u32 ice_sect_id(enum ice_block blk, enum ice_sect sect) 12071d10453SEric Joyner { 12171d10453SEric Joyner return ice_sect_lkup[blk][sect]; 12271d10453SEric Joyner } 12371d10453SEric Joyner 12471d10453SEric Joyner /** 1259cf1841cSEric Joyner * ice_add_tunnel_hint 1269cf1841cSEric Joyner * @hw: pointer to the HW structure 1279cf1841cSEric Joyner * @label_name: label text 1289cf1841cSEric Joyner * @val: value of the tunnel port boost entry 1299cf1841cSEric Joyner */ 1308923de59SPiotr Kubaj void ice_add_tunnel_hint(struct ice_hw *hw, char *label_name, u16 val) 1319cf1841cSEric Joyner { 1329cf1841cSEric Joyner if (hw->tnl.count < ICE_TUNNEL_MAX_ENTRIES) { 1339cf1841cSEric Joyner u16 i; 1349cf1841cSEric Joyner 1359cf1841cSEric Joyner for (i = 0; tnls[i].type != TNL_LAST; i++) { 1369cf1841cSEric Joyner size_t len = strlen(tnls[i].label_prefix); 1379cf1841cSEric Joyner 1389cf1841cSEric Joyner /* Look for matching label start, before continuing */ 1399cf1841cSEric Joyner if (strncmp(label_name, tnls[i].label_prefix, len)) 1409cf1841cSEric Joyner continue; 1419cf1841cSEric Joyner 1429cf1841cSEric Joyner /* Make sure this label matches our PF. Note that the PF 1439cf1841cSEric Joyner * character ('0' - '7') will be located where our 1449cf1841cSEric Joyner * prefix string's null terminator is located. 1459cf1841cSEric Joyner */ 1469cf1841cSEric Joyner if ((label_name[len] - '0') == hw->pf_id) { 1479cf1841cSEric Joyner hw->tnl.tbl[hw->tnl.count].type = tnls[i].type; 1489cf1841cSEric Joyner hw->tnl.tbl[hw->tnl.count].valid = false; 1499cf1841cSEric Joyner hw->tnl.tbl[hw->tnl.count].in_use = false; 1509cf1841cSEric Joyner hw->tnl.tbl[hw->tnl.count].marked = false; 1519cf1841cSEric Joyner hw->tnl.tbl[hw->tnl.count].boost_addr = val; 1529cf1841cSEric Joyner hw->tnl.tbl[hw->tnl.count].port = 0; 1539cf1841cSEric Joyner hw->tnl.count++; 1549cf1841cSEric Joyner break; 1559cf1841cSEric Joyner } 1569cf1841cSEric Joyner } 1579cf1841cSEric Joyner } 1589cf1841cSEric Joyner } 1599cf1841cSEric Joyner 16071d10453SEric Joyner /* Key creation */ 16171d10453SEric Joyner 16271d10453SEric Joyner #define ICE_DC_KEY 0x1 /* don't care */ 16371d10453SEric Joyner #define ICE_DC_KEYINV 0x1 16471d10453SEric Joyner #define ICE_NM_KEY 0x0 /* never match */ 16571d10453SEric Joyner #define ICE_NM_KEYINV 0x0 16671d10453SEric Joyner #define ICE_0_KEY 0x1 /* match 0 */ 16771d10453SEric Joyner #define ICE_0_KEYINV 0x0 16871d10453SEric Joyner #define ICE_1_KEY 0x0 /* match 1 */ 16971d10453SEric Joyner #define ICE_1_KEYINV 0x1 17071d10453SEric Joyner 17171d10453SEric Joyner /** 17271d10453SEric Joyner * ice_gen_key_word - generate 16-bits of a key/mask word 17371d10453SEric Joyner * @val: the value 17471d10453SEric Joyner * @valid: valid bits mask (change only the valid bits) 17571d10453SEric Joyner * @dont_care: don't care mask 17671d10453SEric Joyner * @nvr_mtch: never match mask 17771d10453SEric Joyner * @key: pointer to an array of where the resulting key portion 17871d10453SEric Joyner * @key_inv: pointer to an array of where the resulting key invert portion 17971d10453SEric Joyner * 18071d10453SEric Joyner * This function generates 16-bits from a 8-bit value, an 8-bit don't care mask 18171d10453SEric Joyner * and an 8-bit never match mask. The 16-bits of output are divided into 8 bits 18271d10453SEric Joyner * of key and 8 bits of key invert. 18371d10453SEric Joyner * 18471d10453SEric Joyner * '0' = b01, always match a 0 bit 18571d10453SEric Joyner * '1' = b10, always match a 1 bit 18671d10453SEric Joyner * '?' = b11, don't care bit (always matches) 18771d10453SEric Joyner * '~' = b00, never match bit 18871d10453SEric Joyner * 18971d10453SEric Joyner * Input: 19071d10453SEric Joyner * val: b0 1 0 1 0 1 19171d10453SEric Joyner * dont_care: b0 0 1 1 0 0 19271d10453SEric Joyner * never_mtch: b0 0 0 0 1 1 19371d10453SEric Joyner * ------------------------------ 19471d10453SEric Joyner * Result: key: b01 10 11 11 00 00 19571d10453SEric Joyner */ 196*f2635e84SEric Joyner static int 19771d10453SEric Joyner ice_gen_key_word(u8 val, u8 valid, u8 dont_care, u8 nvr_mtch, u8 *key, 19871d10453SEric Joyner u8 *key_inv) 19971d10453SEric Joyner { 20071d10453SEric Joyner u8 in_key = *key, in_key_inv = *key_inv; 20171d10453SEric Joyner u8 i; 20271d10453SEric Joyner 20371d10453SEric Joyner /* 'dont_care' and 'nvr_mtch' masks cannot overlap */ 20471d10453SEric Joyner if ((dont_care ^ nvr_mtch) != (dont_care | nvr_mtch)) 20571d10453SEric Joyner return ICE_ERR_CFG; 20671d10453SEric Joyner 20771d10453SEric Joyner *key = 0; 20871d10453SEric Joyner *key_inv = 0; 20971d10453SEric Joyner 21071d10453SEric Joyner /* encode the 8 bits into 8-bit key and 8-bit key invert */ 21171d10453SEric Joyner for (i = 0; i < 8; i++) { 21271d10453SEric Joyner *key >>= 1; 21371d10453SEric Joyner *key_inv >>= 1; 21471d10453SEric Joyner 21571d10453SEric Joyner if (!(valid & 0x1)) { /* change only valid bits */ 21671d10453SEric Joyner *key |= (in_key & 0x1) << 7; 21771d10453SEric Joyner *key_inv |= (in_key_inv & 0x1) << 7; 21871d10453SEric Joyner } else if (dont_care & 0x1) { /* don't care bit */ 21971d10453SEric Joyner *key |= ICE_DC_KEY << 7; 22071d10453SEric Joyner *key_inv |= ICE_DC_KEYINV << 7; 22171d10453SEric Joyner } else if (nvr_mtch & 0x1) { /* never match bit */ 22271d10453SEric Joyner *key |= ICE_NM_KEY << 7; 22371d10453SEric Joyner *key_inv |= ICE_NM_KEYINV << 7; 22471d10453SEric Joyner } else if (val & 0x01) { /* exact 1 match */ 22571d10453SEric Joyner *key |= ICE_1_KEY << 7; 22671d10453SEric Joyner *key_inv |= ICE_1_KEYINV << 7; 22771d10453SEric Joyner } else { /* exact 0 match */ 22871d10453SEric Joyner *key |= ICE_0_KEY << 7; 22971d10453SEric Joyner *key_inv |= ICE_0_KEYINV << 7; 23071d10453SEric Joyner } 23171d10453SEric Joyner 23271d10453SEric Joyner dont_care >>= 1; 23371d10453SEric Joyner nvr_mtch >>= 1; 23471d10453SEric Joyner valid >>= 1; 23571d10453SEric Joyner val >>= 1; 23671d10453SEric Joyner in_key >>= 1; 23771d10453SEric Joyner in_key_inv >>= 1; 23871d10453SEric Joyner } 23971d10453SEric Joyner 240*f2635e84SEric Joyner return 0; 24171d10453SEric Joyner } 24271d10453SEric Joyner 24371d10453SEric Joyner /** 24471d10453SEric Joyner * ice_bits_max_set - determine if the number of bits set is within a maximum 24571d10453SEric Joyner * @mask: pointer to the byte array which is the mask 24671d10453SEric Joyner * @size: the number of bytes in the mask 24771d10453SEric Joyner * @max: the max number of set bits 24871d10453SEric Joyner * 24971d10453SEric Joyner * This function determines if there are at most 'max' number of bits set in an 25071d10453SEric Joyner * array. Returns true if the number for bits set is <= max or will return false 25171d10453SEric Joyner * otherwise. 25271d10453SEric Joyner */ 25371d10453SEric Joyner static bool ice_bits_max_set(const u8 *mask, u16 size, u16 max) 25471d10453SEric Joyner { 25571d10453SEric Joyner u16 count = 0; 25671d10453SEric Joyner u16 i; 25771d10453SEric Joyner 25871d10453SEric Joyner /* check each byte */ 25971d10453SEric Joyner for (i = 0; i < size; i++) { 26071d10453SEric Joyner /* if 0, go to next byte */ 26171d10453SEric Joyner if (!mask[i]) 26271d10453SEric Joyner continue; 26371d10453SEric Joyner 26471d10453SEric Joyner /* We know there is at least one set bit in this byte because of 26571d10453SEric Joyner * the above check; if we already have found 'max' number of 26671d10453SEric Joyner * bits set, then we can return failure now. 26771d10453SEric Joyner */ 26871d10453SEric Joyner if (count == max) 26971d10453SEric Joyner return false; 27071d10453SEric Joyner 27171d10453SEric Joyner /* count the bits in this byte, checking threshold */ 27271d10453SEric Joyner count += ice_hweight8(mask[i]); 27371d10453SEric Joyner if (count > max) 27471d10453SEric Joyner return false; 27571d10453SEric Joyner } 27671d10453SEric Joyner 27771d10453SEric Joyner return true; 27871d10453SEric Joyner } 27971d10453SEric Joyner 28071d10453SEric Joyner /** 28171d10453SEric Joyner * ice_set_key - generate a variable sized key with multiples of 16-bits 28271d10453SEric Joyner * @key: pointer to where the key will be stored 28371d10453SEric Joyner * @size: the size of the complete key in bytes (must be even) 28471d10453SEric Joyner * @val: array of 8-bit values that makes up the value portion of the key 28571d10453SEric Joyner * @upd: array of 8-bit masks that determine what key portion to update 28671d10453SEric Joyner * @dc: array of 8-bit masks that make up the don't care mask 28771d10453SEric Joyner * @nm: array of 8-bit masks that make up the never match mask 28871d10453SEric Joyner * @off: the offset of the first byte in the key to update 28971d10453SEric Joyner * @len: the number of bytes in the key update 29071d10453SEric Joyner * 29171d10453SEric Joyner * This function generates a key from a value, a don't care mask and a never 29271d10453SEric Joyner * match mask. 29371d10453SEric Joyner * upd, dc, and nm are optional parameters, and can be NULL: 2947d7af7f8SEric Joyner * upd == NULL --> upd mask is all 1's (update all bits) 29571d10453SEric Joyner * dc == NULL --> dc mask is all 0's (no don't care bits) 29671d10453SEric Joyner * nm == NULL --> nm mask is all 0's (no never match bits) 29771d10453SEric Joyner */ 298*f2635e84SEric Joyner static int 29971d10453SEric Joyner ice_set_key(u8 *key, u16 size, u8 *val, u8 *upd, u8 *dc, u8 *nm, u16 off, 30071d10453SEric Joyner u16 len) 30171d10453SEric Joyner { 30271d10453SEric Joyner u16 half_size; 30371d10453SEric Joyner u16 i; 30471d10453SEric Joyner 30571d10453SEric Joyner /* size must be a multiple of 2 bytes. */ 30671d10453SEric Joyner if (size % 2) 30771d10453SEric Joyner return ICE_ERR_CFG; 30871d10453SEric Joyner half_size = size / 2; 30971d10453SEric Joyner 31071d10453SEric Joyner if (off + len > half_size) 31171d10453SEric Joyner return ICE_ERR_CFG; 31271d10453SEric Joyner 31371d10453SEric Joyner /* Make sure at most one bit is set in the never match mask. Having more 31471d10453SEric Joyner * than one never match mask bit set will cause HW to consume excessive 31571d10453SEric Joyner * power otherwise; this is a power management efficiency check. 31671d10453SEric Joyner */ 31771d10453SEric Joyner #define ICE_NVR_MTCH_BITS_MAX 1 31871d10453SEric Joyner if (nm && !ice_bits_max_set(nm, len, ICE_NVR_MTCH_BITS_MAX)) 31971d10453SEric Joyner return ICE_ERR_CFG; 32071d10453SEric Joyner 32171d10453SEric Joyner for (i = 0; i < len; i++) 32271d10453SEric Joyner if (ice_gen_key_word(val[i], upd ? upd[i] : 0xff, 32371d10453SEric Joyner dc ? dc[i] : 0, nm ? nm[i] : 0, 32471d10453SEric Joyner key + off + i, key + half_size + off + i)) 32571d10453SEric Joyner return ICE_ERR_CFG; 32671d10453SEric Joyner 327*f2635e84SEric Joyner return 0; 32871d10453SEric Joyner } 32971d10453SEric Joyner 33071d10453SEric Joyner /** 33171d10453SEric Joyner * ice_tunnel_port_in_use_hlpr - helper function to determine tunnel usage 33271d10453SEric Joyner * @hw: pointer to the HW structure 33371d10453SEric Joyner * @port: port to search for 33471d10453SEric Joyner * @index: optionally returns index 33571d10453SEric Joyner * 33671d10453SEric Joyner * Returns whether a port is already in use as a tunnel, and optionally its 33771d10453SEric Joyner * index 33871d10453SEric Joyner */ 33971d10453SEric Joyner static bool ice_tunnel_port_in_use_hlpr(struct ice_hw *hw, u16 port, u16 *index) 34071d10453SEric Joyner { 34171d10453SEric Joyner u16 i; 34271d10453SEric Joyner 34371d10453SEric Joyner for (i = 0; i < hw->tnl.count && i < ICE_TUNNEL_MAX_ENTRIES; i++) 34471d10453SEric Joyner if (hw->tnl.tbl[i].in_use && hw->tnl.tbl[i].port == port) { 34571d10453SEric Joyner if (index) 34671d10453SEric Joyner *index = i; 34771d10453SEric Joyner return true; 34871d10453SEric Joyner } 34971d10453SEric Joyner 35071d10453SEric Joyner return false; 35171d10453SEric Joyner } 35271d10453SEric Joyner 35371d10453SEric Joyner /** 35471d10453SEric Joyner * ice_tunnel_port_in_use 35571d10453SEric Joyner * @hw: pointer to the HW structure 35671d10453SEric Joyner * @port: port to search for 35771d10453SEric Joyner * @index: optionally returns index 35871d10453SEric Joyner * 35971d10453SEric Joyner * Returns whether a port is already in use as a tunnel, and optionally its 36071d10453SEric Joyner * index 36171d10453SEric Joyner */ 36271d10453SEric Joyner bool ice_tunnel_port_in_use(struct ice_hw *hw, u16 port, u16 *index) 36371d10453SEric Joyner { 36471d10453SEric Joyner bool res; 36571d10453SEric Joyner 36671d10453SEric Joyner ice_acquire_lock(&hw->tnl_lock); 36771d10453SEric Joyner res = ice_tunnel_port_in_use_hlpr(hw, port, index); 36871d10453SEric Joyner ice_release_lock(&hw->tnl_lock); 36971d10453SEric Joyner 37071d10453SEric Joyner return res; 37171d10453SEric Joyner } 37271d10453SEric Joyner 37371d10453SEric Joyner /** 37471d10453SEric Joyner * ice_tunnel_get_type 37571d10453SEric Joyner * @hw: pointer to the HW structure 37671d10453SEric Joyner * @port: port to search for 37771d10453SEric Joyner * @type: returns tunnel index 37871d10453SEric Joyner * 37971d10453SEric Joyner * For a given port number, will return the type of tunnel. 38071d10453SEric Joyner */ 38171d10453SEric Joyner bool 38271d10453SEric Joyner ice_tunnel_get_type(struct ice_hw *hw, u16 port, enum ice_tunnel_type *type) 38371d10453SEric Joyner { 38471d10453SEric Joyner bool res = false; 38571d10453SEric Joyner u16 i; 38671d10453SEric Joyner 38771d10453SEric Joyner ice_acquire_lock(&hw->tnl_lock); 38871d10453SEric Joyner 38971d10453SEric Joyner for (i = 0; i < hw->tnl.count && i < ICE_TUNNEL_MAX_ENTRIES; i++) 39071d10453SEric Joyner if (hw->tnl.tbl[i].in_use && hw->tnl.tbl[i].port == port) { 39171d10453SEric Joyner *type = hw->tnl.tbl[i].type; 39271d10453SEric Joyner res = true; 39371d10453SEric Joyner break; 39471d10453SEric Joyner } 39571d10453SEric Joyner 39671d10453SEric Joyner ice_release_lock(&hw->tnl_lock); 39771d10453SEric Joyner 39871d10453SEric Joyner return res; 39971d10453SEric Joyner } 40071d10453SEric Joyner 40171d10453SEric Joyner /** 40271d10453SEric Joyner * ice_find_free_tunnel_entry 40371d10453SEric Joyner * @hw: pointer to the HW structure 40471d10453SEric Joyner * @type: tunnel type 40571d10453SEric Joyner * @index: optionally returns index 40671d10453SEric Joyner * 40771d10453SEric Joyner * Returns whether there is a free tunnel entry, and optionally its index 40871d10453SEric Joyner */ 40971d10453SEric Joyner static bool 41071d10453SEric Joyner ice_find_free_tunnel_entry(struct ice_hw *hw, enum ice_tunnel_type type, 41171d10453SEric Joyner u16 *index) 41271d10453SEric Joyner { 41371d10453SEric Joyner u16 i; 41471d10453SEric Joyner 41571d10453SEric Joyner for (i = 0; i < hw->tnl.count && i < ICE_TUNNEL_MAX_ENTRIES; i++) 41671d10453SEric Joyner if (hw->tnl.tbl[i].valid && !hw->tnl.tbl[i].in_use && 41771d10453SEric Joyner hw->tnl.tbl[i].type == type) { 41871d10453SEric Joyner if (index) 41971d10453SEric Joyner *index = i; 42071d10453SEric Joyner return true; 42171d10453SEric Joyner } 42271d10453SEric Joyner 42371d10453SEric Joyner return false; 42471d10453SEric Joyner } 42571d10453SEric Joyner 42671d10453SEric Joyner /** 42771d10453SEric Joyner * ice_get_open_tunnel_port - retrieve an open tunnel port 42871d10453SEric Joyner * @hw: pointer to the HW structure 42971d10453SEric Joyner * @type: tunnel type (TNL_ALL will return any open port) 43071d10453SEric Joyner * @port: returns open port 43171d10453SEric Joyner */ 43271d10453SEric Joyner bool 43371d10453SEric Joyner ice_get_open_tunnel_port(struct ice_hw *hw, enum ice_tunnel_type type, 43471d10453SEric Joyner u16 *port) 43571d10453SEric Joyner { 43671d10453SEric Joyner bool res = false; 43771d10453SEric Joyner u16 i; 43871d10453SEric Joyner 43971d10453SEric Joyner ice_acquire_lock(&hw->tnl_lock); 44071d10453SEric Joyner 44171d10453SEric Joyner for (i = 0; i < hw->tnl.count && i < ICE_TUNNEL_MAX_ENTRIES; i++) 44271d10453SEric Joyner if (hw->tnl.tbl[i].valid && hw->tnl.tbl[i].in_use && 44371d10453SEric Joyner (type == TNL_ALL || hw->tnl.tbl[i].type == type)) { 44471d10453SEric Joyner *port = hw->tnl.tbl[i].port; 44571d10453SEric Joyner res = true; 44671d10453SEric Joyner break; 44771d10453SEric Joyner } 44871d10453SEric Joyner 44971d10453SEric Joyner ice_release_lock(&hw->tnl_lock); 45071d10453SEric Joyner 45171d10453SEric Joyner return res; 45271d10453SEric Joyner } 45371d10453SEric Joyner 45471d10453SEric Joyner /** 45571d10453SEric Joyner * ice_create_tunnel 45671d10453SEric Joyner * @hw: pointer to the HW structure 45771d10453SEric Joyner * @type: type of tunnel 45871d10453SEric Joyner * @port: port of tunnel to create 45971d10453SEric Joyner * 46071d10453SEric Joyner * Create a tunnel by updating the parse graph in the parser. We do that by 46171d10453SEric Joyner * creating a package buffer with the tunnel info and issuing an update package 46271d10453SEric Joyner * command. 46371d10453SEric Joyner */ 464*f2635e84SEric Joyner int 46571d10453SEric Joyner ice_create_tunnel(struct ice_hw *hw, enum ice_tunnel_type type, u16 port) 46671d10453SEric Joyner { 46771d10453SEric Joyner struct ice_boost_tcam_section *sect_rx, *sect_tx; 46871d10453SEric Joyner struct ice_buf_build *bld; 469*f2635e84SEric Joyner int status = ICE_ERR_MAX_LIMIT; 47071d10453SEric Joyner u16 index; 47171d10453SEric Joyner 47271d10453SEric Joyner ice_acquire_lock(&hw->tnl_lock); 47371d10453SEric Joyner 47471d10453SEric Joyner if (ice_tunnel_port_in_use_hlpr(hw, port, &index)) { 47571d10453SEric Joyner hw->tnl.tbl[index].ref++; 476*f2635e84SEric Joyner status = 0; 47771d10453SEric Joyner goto ice_create_tunnel_end; 47871d10453SEric Joyner } 47971d10453SEric Joyner 48071d10453SEric Joyner if (!ice_find_free_tunnel_entry(hw, type, &index)) { 48171d10453SEric Joyner status = ICE_ERR_OUT_OF_RANGE; 48271d10453SEric Joyner goto ice_create_tunnel_end; 48371d10453SEric Joyner } 48471d10453SEric Joyner 48571d10453SEric Joyner bld = ice_pkg_buf_alloc(hw); 48671d10453SEric Joyner if (!bld) { 48771d10453SEric Joyner status = ICE_ERR_NO_MEMORY; 48871d10453SEric Joyner goto ice_create_tunnel_end; 48971d10453SEric Joyner } 49071d10453SEric Joyner 49171d10453SEric Joyner /* allocate 2 sections, one for Rx parser, one for Tx parser */ 49271d10453SEric Joyner if (ice_pkg_buf_reserve_section(bld, 2)) 49371d10453SEric Joyner goto ice_create_tunnel_err; 49471d10453SEric Joyner 49571d10453SEric Joyner sect_rx = (struct ice_boost_tcam_section *) 49671d10453SEric Joyner ice_pkg_buf_alloc_section(bld, ICE_SID_RXPARSER_BOOST_TCAM, 4977d7af7f8SEric Joyner ice_struct_size(sect_rx, tcam, 1)); 49871d10453SEric Joyner if (!sect_rx) 49971d10453SEric Joyner goto ice_create_tunnel_err; 50071d10453SEric Joyner sect_rx->count = CPU_TO_LE16(1); 50171d10453SEric Joyner 50271d10453SEric Joyner sect_tx = (struct ice_boost_tcam_section *) 50371d10453SEric Joyner ice_pkg_buf_alloc_section(bld, ICE_SID_TXPARSER_BOOST_TCAM, 5047d7af7f8SEric Joyner ice_struct_size(sect_tx, tcam, 1)); 50571d10453SEric Joyner if (!sect_tx) 50671d10453SEric Joyner goto ice_create_tunnel_err; 50771d10453SEric Joyner sect_tx->count = CPU_TO_LE16(1); 50871d10453SEric Joyner 50971d10453SEric Joyner /* copy original boost entry to update package buffer */ 51071d10453SEric Joyner ice_memcpy(sect_rx->tcam, hw->tnl.tbl[index].boost_entry, 51171d10453SEric Joyner sizeof(*sect_rx->tcam), ICE_NONDMA_TO_NONDMA); 51271d10453SEric Joyner 51371d10453SEric Joyner /* over-write the never-match dest port key bits with the encoded port 51471d10453SEric Joyner * bits 51571d10453SEric Joyner */ 51671d10453SEric Joyner ice_set_key((u8 *)§_rx->tcam[0].key, sizeof(sect_rx->tcam[0].key), 51771d10453SEric Joyner (u8 *)&port, NULL, NULL, NULL, 51871d10453SEric Joyner (u16)offsetof(struct ice_boost_key_value, hv_dst_port_key), 51971d10453SEric Joyner sizeof(sect_rx->tcam[0].key.key.hv_dst_port_key)); 52071d10453SEric Joyner 52171d10453SEric Joyner /* exact copy of entry to Tx section entry */ 52271d10453SEric Joyner ice_memcpy(sect_tx->tcam, sect_rx->tcam, sizeof(*sect_tx->tcam), 52371d10453SEric Joyner ICE_NONDMA_TO_NONDMA); 52471d10453SEric Joyner 52571d10453SEric Joyner status = ice_update_pkg(hw, ice_pkg_buf(bld), 1); 52671d10453SEric Joyner if (!status) { 52771d10453SEric Joyner hw->tnl.tbl[index].port = port; 52871d10453SEric Joyner hw->tnl.tbl[index].in_use = true; 52971d10453SEric Joyner hw->tnl.tbl[index].ref = 1; 53071d10453SEric Joyner } 53171d10453SEric Joyner 53271d10453SEric Joyner ice_create_tunnel_err: 53371d10453SEric Joyner ice_pkg_buf_free(hw, bld); 53471d10453SEric Joyner 53571d10453SEric Joyner ice_create_tunnel_end: 53671d10453SEric Joyner ice_release_lock(&hw->tnl_lock); 53771d10453SEric Joyner 53871d10453SEric Joyner return status; 53971d10453SEric Joyner } 54071d10453SEric Joyner 54171d10453SEric Joyner /** 54271d10453SEric Joyner * ice_destroy_tunnel 54371d10453SEric Joyner * @hw: pointer to the HW structure 54471d10453SEric Joyner * @port: port of tunnel to destroy (ignored if the all parameter is true) 54571d10453SEric Joyner * @all: flag that states to destroy all tunnels 54671d10453SEric Joyner * 54771d10453SEric Joyner * Destroys a tunnel or all tunnels by creating an update package buffer 54871d10453SEric Joyner * targeting the specific updates requested and then performing an update 54971d10453SEric Joyner * package. 55071d10453SEric Joyner */ 551*f2635e84SEric Joyner int ice_destroy_tunnel(struct ice_hw *hw, u16 port, bool all) 55271d10453SEric Joyner { 55371d10453SEric Joyner struct ice_boost_tcam_section *sect_rx, *sect_tx; 55471d10453SEric Joyner struct ice_buf_build *bld; 555*f2635e84SEric Joyner int status = ICE_ERR_MAX_LIMIT; 55671d10453SEric Joyner u16 count = 0; 55771d10453SEric Joyner u16 index; 55871d10453SEric Joyner u16 size; 5599cf1841cSEric Joyner u16 i, j; 56071d10453SEric Joyner 56171d10453SEric Joyner ice_acquire_lock(&hw->tnl_lock); 56271d10453SEric Joyner 56371d10453SEric Joyner if (!all && ice_tunnel_port_in_use_hlpr(hw, port, &index)) 56471d10453SEric Joyner if (hw->tnl.tbl[index].ref > 1) { 56571d10453SEric Joyner hw->tnl.tbl[index].ref--; 566*f2635e84SEric Joyner status = 0; 56771d10453SEric Joyner goto ice_destroy_tunnel_end; 56871d10453SEric Joyner } 56971d10453SEric Joyner 57071d10453SEric Joyner /* determine count */ 57171d10453SEric Joyner for (i = 0; i < hw->tnl.count && i < ICE_TUNNEL_MAX_ENTRIES; i++) 57271d10453SEric Joyner if (hw->tnl.tbl[i].valid && hw->tnl.tbl[i].in_use && 57371d10453SEric Joyner (all || hw->tnl.tbl[i].port == port)) 57471d10453SEric Joyner count++; 57571d10453SEric Joyner 57671d10453SEric Joyner if (!count) { 57771d10453SEric Joyner status = ICE_ERR_PARAM; 57871d10453SEric Joyner goto ice_destroy_tunnel_end; 57971d10453SEric Joyner } 58071d10453SEric Joyner 58171d10453SEric Joyner /* size of section - there is at least one entry */ 5827d7af7f8SEric Joyner size = ice_struct_size(sect_rx, tcam, count); 58371d10453SEric Joyner 58471d10453SEric Joyner bld = ice_pkg_buf_alloc(hw); 58571d10453SEric Joyner if (!bld) { 58671d10453SEric Joyner status = ICE_ERR_NO_MEMORY; 58771d10453SEric Joyner goto ice_destroy_tunnel_end; 58871d10453SEric Joyner } 58971d10453SEric Joyner 59071d10453SEric Joyner /* allocate 2 sections, one for Rx parser, one for Tx parser */ 59171d10453SEric Joyner if (ice_pkg_buf_reserve_section(bld, 2)) 59271d10453SEric Joyner goto ice_destroy_tunnel_err; 59371d10453SEric Joyner 59471d10453SEric Joyner sect_rx = (struct ice_boost_tcam_section *) 59571d10453SEric Joyner ice_pkg_buf_alloc_section(bld, ICE_SID_RXPARSER_BOOST_TCAM, 59671d10453SEric Joyner size); 59771d10453SEric Joyner if (!sect_rx) 59871d10453SEric Joyner goto ice_destroy_tunnel_err; 5999cf1841cSEric Joyner sect_rx->count = CPU_TO_LE16(count); 60071d10453SEric Joyner 60171d10453SEric Joyner sect_tx = (struct ice_boost_tcam_section *) 60271d10453SEric Joyner ice_pkg_buf_alloc_section(bld, ICE_SID_TXPARSER_BOOST_TCAM, 60371d10453SEric Joyner size); 60471d10453SEric Joyner if (!sect_tx) 60571d10453SEric Joyner goto ice_destroy_tunnel_err; 6069cf1841cSEric Joyner sect_tx->count = CPU_TO_LE16(count); 60771d10453SEric Joyner 60871d10453SEric Joyner /* copy original boost entry to update package buffer, one copy to Rx 60971d10453SEric Joyner * section, another copy to the Tx section 61071d10453SEric Joyner */ 6119cf1841cSEric Joyner for (i = 0, j = 0; i < hw->tnl.count && i < ICE_TUNNEL_MAX_ENTRIES; i++) 61271d10453SEric Joyner if (hw->tnl.tbl[i].valid && hw->tnl.tbl[i].in_use && 61371d10453SEric Joyner (all || hw->tnl.tbl[i].port == port)) { 6149cf1841cSEric Joyner ice_memcpy(sect_rx->tcam + j, 61571d10453SEric Joyner hw->tnl.tbl[i].boost_entry, 61671d10453SEric Joyner sizeof(*sect_rx->tcam), 61771d10453SEric Joyner ICE_NONDMA_TO_NONDMA); 6189cf1841cSEric Joyner ice_memcpy(sect_tx->tcam + j, 61971d10453SEric Joyner hw->tnl.tbl[i].boost_entry, 62071d10453SEric Joyner sizeof(*sect_tx->tcam), 62171d10453SEric Joyner ICE_NONDMA_TO_NONDMA); 62271d10453SEric Joyner hw->tnl.tbl[i].marked = true; 6239cf1841cSEric Joyner j++; 62471d10453SEric Joyner } 62571d10453SEric Joyner 62671d10453SEric Joyner status = ice_update_pkg(hw, ice_pkg_buf(bld), 1); 62771d10453SEric Joyner if (!status) 62871d10453SEric Joyner for (i = 0; i < hw->tnl.count && 62971d10453SEric Joyner i < ICE_TUNNEL_MAX_ENTRIES; i++) 63071d10453SEric Joyner if (hw->tnl.tbl[i].marked) { 63171d10453SEric Joyner hw->tnl.tbl[i].ref = 0; 63271d10453SEric Joyner hw->tnl.tbl[i].port = 0; 63371d10453SEric Joyner hw->tnl.tbl[i].in_use = false; 63471d10453SEric Joyner hw->tnl.tbl[i].marked = false; 63571d10453SEric Joyner } 63671d10453SEric Joyner 63771d10453SEric Joyner ice_destroy_tunnel_err: 63871d10453SEric Joyner ice_pkg_buf_free(hw, bld); 63971d10453SEric Joyner 64071d10453SEric Joyner ice_destroy_tunnel_end: 64171d10453SEric Joyner ice_release_lock(&hw->tnl_lock); 64271d10453SEric Joyner 64371d10453SEric Joyner return status; 64471d10453SEric Joyner } 64571d10453SEric Joyner 64671d10453SEric Joyner /** 64771d10453SEric Joyner * ice_replay_tunnels 64871d10453SEric Joyner * @hw: pointer to the HW structure 64971d10453SEric Joyner * 65071d10453SEric Joyner * Replays all tunnels 65171d10453SEric Joyner */ 652*f2635e84SEric Joyner int ice_replay_tunnels(struct ice_hw *hw) 65371d10453SEric Joyner { 654*f2635e84SEric Joyner int status = 0; 65571d10453SEric Joyner u16 i; 65671d10453SEric Joyner 65771d10453SEric Joyner ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); 65871d10453SEric Joyner 65971d10453SEric Joyner for (i = 0; i < hw->tnl.count && i < ICE_TUNNEL_MAX_ENTRIES; i++) { 66071d10453SEric Joyner enum ice_tunnel_type type = hw->tnl.tbl[i].type; 66171d10453SEric Joyner u16 refs = hw->tnl.tbl[i].ref; 66271d10453SEric Joyner u16 port = hw->tnl.tbl[i].port; 66371d10453SEric Joyner 66471d10453SEric Joyner if (!hw->tnl.tbl[i].in_use) 66571d10453SEric Joyner continue; 66671d10453SEric Joyner 66771d10453SEric Joyner /* Replay tunnels one at a time by destroying them, then 66871d10453SEric Joyner * recreating them 66971d10453SEric Joyner */ 67071d10453SEric Joyner hw->tnl.tbl[i].ref = 1; /* make sure to destroy in one call */ 67171d10453SEric Joyner status = ice_destroy_tunnel(hw, port, false); 67271d10453SEric Joyner if (status) { 6737d7af7f8SEric Joyner ice_debug(hw, ICE_DBG_PKG, "ERR: 0x%x - destroy tunnel port 0x%x\n", 67471d10453SEric Joyner status, port); 6759e54973fSEric Joyner hw->tnl.tbl[i].ref = refs; 67671d10453SEric Joyner break; 67771d10453SEric Joyner } 67871d10453SEric Joyner 67971d10453SEric Joyner status = ice_create_tunnel(hw, type, port); 68071d10453SEric Joyner if (status) { 6817d7af7f8SEric Joyner ice_debug(hw, ICE_DBG_PKG, "ERR: 0x%x - create tunnel port 0x%x\n", 68271d10453SEric Joyner status, port); 68371d10453SEric Joyner break; 68471d10453SEric Joyner } 68571d10453SEric Joyner 68671d10453SEric Joyner /* reset to original ref count */ 68771d10453SEric Joyner hw->tnl.tbl[i].ref = refs; 68871d10453SEric Joyner } 68971d10453SEric Joyner 69071d10453SEric Joyner return status; 69171d10453SEric Joyner } 69271d10453SEric Joyner 69371d10453SEric Joyner /** 69471d10453SEric Joyner * ice_find_prot_off - find prot ID and offset pair, based on prof and FV index 69571d10453SEric Joyner * @hw: pointer to the hardware structure 69671d10453SEric Joyner * @blk: hardware block 69771d10453SEric Joyner * @prof: profile ID 69871d10453SEric Joyner * @fv_idx: field vector word index 69971d10453SEric Joyner * @prot: variable to receive the protocol ID 70071d10453SEric Joyner * @off: variable to receive the protocol offset 70171d10453SEric Joyner */ 702*f2635e84SEric Joyner int 70371d10453SEric Joyner ice_find_prot_off(struct ice_hw *hw, enum ice_block blk, u8 prof, u16 fv_idx, 70471d10453SEric Joyner u8 *prot, u16 *off) 70571d10453SEric Joyner { 70671d10453SEric Joyner struct ice_fv_word *fv_ext; 70771d10453SEric Joyner 70871d10453SEric Joyner if (prof >= hw->blk[blk].es.count) 70971d10453SEric Joyner return ICE_ERR_PARAM; 71071d10453SEric Joyner 71171d10453SEric Joyner if (fv_idx >= hw->blk[blk].es.fvw) 71271d10453SEric Joyner return ICE_ERR_PARAM; 71371d10453SEric Joyner 71471d10453SEric Joyner fv_ext = hw->blk[blk].es.t + (prof * hw->blk[blk].es.fvw); 71571d10453SEric Joyner 71671d10453SEric Joyner *prot = fv_ext[fv_idx].prot_id; 71771d10453SEric Joyner *off = fv_ext[fv_idx].off; 71871d10453SEric Joyner 719*f2635e84SEric Joyner return 0; 72071d10453SEric Joyner } 72171d10453SEric Joyner 72271d10453SEric Joyner /* PTG Management */ 72371d10453SEric Joyner 72471d10453SEric Joyner /** 72571d10453SEric Joyner * ice_ptg_update_xlt1 - Updates packet type groups in HW via XLT1 table 72671d10453SEric Joyner * @hw: pointer to the hardware structure 72771d10453SEric Joyner * @blk: HW block 72871d10453SEric Joyner * 72971d10453SEric Joyner * This function will update the XLT1 hardware table to reflect the new 73071d10453SEric Joyner * packet type group configuration. 73171d10453SEric Joyner */ 732*f2635e84SEric Joyner int ice_ptg_update_xlt1(struct ice_hw *hw, enum ice_block blk) 73371d10453SEric Joyner { 73471d10453SEric Joyner struct ice_xlt1_section *sect; 73571d10453SEric Joyner struct ice_buf_build *bld; 736*f2635e84SEric Joyner int status; 73771d10453SEric Joyner u16 index; 73871d10453SEric Joyner 73971d10453SEric Joyner bld = ice_pkg_buf_alloc_single_section(hw, ice_sect_id(blk, ICE_XLT1), 7407d7af7f8SEric Joyner ice_struct_size(sect, value, 7417d7af7f8SEric Joyner ICE_XLT1_CNT), 74271d10453SEric Joyner (void **)§); 74371d10453SEric Joyner if (!bld) 74471d10453SEric Joyner return ICE_ERR_NO_MEMORY; 74571d10453SEric Joyner 74671d10453SEric Joyner sect->count = CPU_TO_LE16(ICE_XLT1_CNT); 74771d10453SEric Joyner sect->offset = CPU_TO_LE16(0); 74871d10453SEric Joyner for (index = 0; index < ICE_XLT1_CNT; index++) 74971d10453SEric Joyner sect->value[index] = hw->blk[blk].xlt1.ptypes[index].ptg; 75071d10453SEric Joyner 75171d10453SEric Joyner status = ice_update_pkg(hw, ice_pkg_buf(bld), 1); 75271d10453SEric Joyner 75371d10453SEric Joyner ice_pkg_buf_free(hw, bld); 75471d10453SEric Joyner 75571d10453SEric Joyner return status; 75671d10453SEric Joyner } 75771d10453SEric Joyner 75871d10453SEric Joyner /** 75971d10453SEric Joyner * ice_ptg_find_ptype - Search for packet type group using packet type (ptype) 76071d10453SEric Joyner * @hw: pointer to the hardware structure 76171d10453SEric Joyner * @blk: HW block 76271d10453SEric Joyner * @ptype: the ptype to search for 76371d10453SEric Joyner * @ptg: pointer to variable that receives the PTG 76471d10453SEric Joyner * 76571d10453SEric Joyner * This function will search the PTGs for a particular ptype, returning the 76671d10453SEric Joyner * PTG ID that contains it through the PTG parameter, with the value of 76771d10453SEric Joyner * ICE_DEFAULT_PTG (0) meaning it is part the default PTG. 76871d10453SEric Joyner */ 769*f2635e84SEric Joyner static int 77071d10453SEric Joyner ice_ptg_find_ptype(struct ice_hw *hw, enum ice_block blk, u16 ptype, u8 *ptg) 77171d10453SEric Joyner { 77271d10453SEric Joyner if (ptype >= ICE_XLT1_CNT || !ptg) 77371d10453SEric Joyner return ICE_ERR_PARAM; 77471d10453SEric Joyner 77571d10453SEric Joyner *ptg = hw->blk[blk].xlt1.ptypes[ptype].ptg; 776*f2635e84SEric Joyner return 0; 77771d10453SEric Joyner } 77871d10453SEric Joyner 77971d10453SEric Joyner /** 78071d10453SEric Joyner * ice_ptg_alloc_val - Allocates a new packet type group ID by value 78171d10453SEric Joyner * @hw: pointer to the hardware structure 78271d10453SEric Joyner * @blk: HW block 78371d10453SEric Joyner * @ptg: the PTG to allocate 78471d10453SEric Joyner * 78571d10453SEric Joyner * This function allocates a given packet type group ID specified by the PTG 78671d10453SEric Joyner * parameter. 78771d10453SEric Joyner */ 78871d10453SEric Joyner static void ice_ptg_alloc_val(struct ice_hw *hw, enum ice_block blk, u8 ptg) 78971d10453SEric Joyner { 79071d10453SEric Joyner hw->blk[blk].xlt1.ptg_tbl[ptg].in_use = true; 79171d10453SEric Joyner } 79271d10453SEric Joyner 79371d10453SEric Joyner /** 79471d10453SEric Joyner * ice_ptg_free - Frees a packet type group 79571d10453SEric Joyner * @hw: pointer to the hardware structure 79671d10453SEric Joyner * @blk: HW block 79771d10453SEric Joyner * @ptg: the PTG ID to free 79871d10453SEric Joyner * 79971d10453SEric Joyner * This function frees a packet type group, and returns all the current ptypes 80071d10453SEric Joyner * within it to the default PTG. 80171d10453SEric Joyner */ 80271d10453SEric Joyner void ice_ptg_free(struct ice_hw *hw, enum ice_block blk, u8 ptg) 80371d10453SEric Joyner { 80471d10453SEric Joyner struct ice_ptg_ptype *p, *temp; 80571d10453SEric Joyner 80671d10453SEric Joyner hw->blk[blk].xlt1.ptg_tbl[ptg].in_use = false; 80771d10453SEric Joyner p = hw->blk[blk].xlt1.ptg_tbl[ptg].first_ptype; 80871d10453SEric Joyner while (p) { 80971d10453SEric Joyner p->ptg = ICE_DEFAULT_PTG; 81071d10453SEric Joyner temp = p->next_ptype; 81171d10453SEric Joyner p->next_ptype = NULL; 81271d10453SEric Joyner p = temp; 81371d10453SEric Joyner } 81471d10453SEric Joyner 81571d10453SEric Joyner hw->blk[blk].xlt1.ptg_tbl[ptg].first_ptype = NULL; 81671d10453SEric Joyner } 81771d10453SEric Joyner 81871d10453SEric Joyner /** 81971d10453SEric Joyner * ice_ptg_remove_ptype - Removes ptype from a particular packet type group 82071d10453SEric Joyner * @hw: pointer to the hardware structure 82171d10453SEric Joyner * @blk: HW block 82271d10453SEric Joyner * @ptype: the ptype to remove 82371d10453SEric Joyner * @ptg: the PTG to remove the ptype from 82471d10453SEric Joyner * 82571d10453SEric Joyner * This function will remove the ptype from the specific PTG, and move it to 82671d10453SEric Joyner * the default PTG (ICE_DEFAULT_PTG). 82771d10453SEric Joyner */ 828*f2635e84SEric Joyner static int 82971d10453SEric Joyner ice_ptg_remove_ptype(struct ice_hw *hw, enum ice_block blk, u16 ptype, u8 ptg) 83071d10453SEric Joyner { 83171d10453SEric Joyner struct ice_ptg_ptype **ch; 83271d10453SEric Joyner struct ice_ptg_ptype *p; 83371d10453SEric Joyner 83471d10453SEric Joyner if (ptype > ICE_XLT1_CNT - 1) 83571d10453SEric Joyner return ICE_ERR_PARAM; 83671d10453SEric Joyner 83771d10453SEric Joyner if (!hw->blk[blk].xlt1.ptg_tbl[ptg].in_use) 83871d10453SEric Joyner return ICE_ERR_DOES_NOT_EXIST; 83971d10453SEric Joyner 84071d10453SEric Joyner /* Should not happen if .in_use is set, bad config */ 84171d10453SEric Joyner if (!hw->blk[blk].xlt1.ptg_tbl[ptg].first_ptype) 84271d10453SEric Joyner return ICE_ERR_CFG; 84371d10453SEric Joyner 84471d10453SEric Joyner /* find the ptype within this PTG, and bypass the link over it */ 84571d10453SEric Joyner p = hw->blk[blk].xlt1.ptg_tbl[ptg].first_ptype; 84671d10453SEric Joyner ch = &hw->blk[blk].xlt1.ptg_tbl[ptg].first_ptype; 84771d10453SEric Joyner while (p) { 84871d10453SEric Joyner if (ptype == (p - hw->blk[blk].xlt1.ptypes)) { 84971d10453SEric Joyner *ch = p->next_ptype; 85071d10453SEric Joyner break; 85171d10453SEric Joyner } 85271d10453SEric Joyner 85371d10453SEric Joyner ch = &p->next_ptype; 85471d10453SEric Joyner p = p->next_ptype; 85571d10453SEric Joyner } 85671d10453SEric Joyner 85771d10453SEric Joyner hw->blk[blk].xlt1.ptypes[ptype].ptg = ICE_DEFAULT_PTG; 85871d10453SEric Joyner hw->blk[blk].xlt1.ptypes[ptype].next_ptype = NULL; 85971d10453SEric Joyner 860*f2635e84SEric Joyner return 0; 86171d10453SEric Joyner } 86271d10453SEric Joyner 86371d10453SEric Joyner /** 86471d10453SEric Joyner * ice_ptg_add_mv_ptype - Adds/moves ptype to a particular packet type group 86571d10453SEric Joyner * @hw: pointer to the hardware structure 86671d10453SEric Joyner * @blk: HW block 86771d10453SEric Joyner * @ptype: the ptype to add or move 86871d10453SEric Joyner * @ptg: the PTG to add or move the ptype to 86971d10453SEric Joyner * 87071d10453SEric Joyner * This function will either add or move a ptype to a particular PTG depending 87171d10453SEric Joyner * on if the ptype is already part of another group. Note that using a 87271d10453SEric Joyner * a destination PTG ID of ICE_DEFAULT_PTG (0) will move the ptype to the 87371d10453SEric Joyner * default PTG. 87471d10453SEric Joyner */ 875*f2635e84SEric Joyner static int 87671d10453SEric Joyner ice_ptg_add_mv_ptype(struct ice_hw *hw, enum ice_block blk, u16 ptype, u8 ptg) 87771d10453SEric Joyner { 87871d10453SEric Joyner u8 original_ptg; 879*f2635e84SEric Joyner int status; 88071d10453SEric Joyner 88171d10453SEric Joyner if (ptype > ICE_XLT1_CNT - 1) 88271d10453SEric Joyner return ICE_ERR_PARAM; 88371d10453SEric Joyner 88471d10453SEric Joyner if (!hw->blk[blk].xlt1.ptg_tbl[ptg].in_use && ptg != ICE_DEFAULT_PTG) 88571d10453SEric Joyner return ICE_ERR_DOES_NOT_EXIST; 88671d10453SEric Joyner 88771d10453SEric Joyner status = ice_ptg_find_ptype(hw, blk, ptype, &original_ptg); 88871d10453SEric Joyner if (status) 88971d10453SEric Joyner return status; 89071d10453SEric Joyner 89171d10453SEric Joyner /* Is ptype already in the correct PTG? */ 89271d10453SEric Joyner if (original_ptg == ptg) 893*f2635e84SEric Joyner return 0; 89471d10453SEric Joyner 89571d10453SEric Joyner /* Remove from original PTG and move back to the default PTG */ 89671d10453SEric Joyner if (original_ptg != ICE_DEFAULT_PTG) 89771d10453SEric Joyner ice_ptg_remove_ptype(hw, blk, ptype, original_ptg); 89871d10453SEric Joyner 89971d10453SEric Joyner /* Moving to default PTG? Then we're done with this request */ 90071d10453SEric Joyner if (ptg == ICE_DEFAULT_PTG) 901*f2635e84SEric Joyner return 0; 90271d10453SEric Joyner 90371d10453SEric Joyner /* Add ptype to PTG at beginning of list */ 90471d10453SEric Joyner hw->blk[blk].xlt1.ptypes[ptype].next_ptype = 90571d10453SEric Joyner hw->blk[blk].xlt1.ptg_tbl[ptg].first_ptype; 90671d10453SEric Joyner hw->blk[blk].xlt1.ptg_tbl[ptg].first_ptype = 90771d10453SEric Joyner &hw->blk[blk].xlt1.ptypes[ptype]; 90871d10453SEric Joyner 90971d10453SEric Joyner hw->blk[blk].xlt1.ptypes[ptype].ptg = ptg; 91071d10453SEric Joyner hw->blk[blk].xlt1.t[ptype] = ptg; 91171d10453SEric Joyner 912*f2635e84SEric Joyner return 0; 91371d10453SEric Joyner } 91471d10453SEric Joyner 91571d10453SEric Joyner /* Block / table size info */ 91671d10453SEric Joyner struct ice_blk_size_details { 91771d10453SEric Joyner u16 xlt1; /* # XLT1 entries */ 91871d10453SEric Joyner u16 xlt2; /* # XLT2 entries */ 91971d10453SEric Joyner u16 prof_tcam; /* # profile ID TCAM entries */ 92071d10453SEric Joyner u16 prof_id; /* # profile IDs */ 92171d10453SEric Joyner u8 prof_cdid_bits; /* # CDID one-hot bits used in key */ 92271d10453SEric Joyner u16 prof_redir; /* # profile redirection entries */ 92371d10453SEric Joyner u16 es; /* # extraction sequence entries */ 92471d10453SEric Joyner u16 fvw; /* # field vector words */ 92571d10453SEric Joyner u8 overwrite; /* overwrite existing entries allowed */ 92671d10453SEric Joyner u8 reverse; /* reverse FV order */ 92771d10453SEric Joyner }; 92871d10453SEric Joyner 92971d10453SEric Joyner static const struct ice_blk_size_details blk_sizes[ICE_BLK_COUNT] = { 93071d10453SEric Joyner /** 93171d10453SEric Joyner * Table Definitions 93271d10453SEric Joyner * XLT1 - Number of entries in XLT1 table 93371d10453SEric Joyner * XLT2 - Number of entries in XLT2 table 93471d10453SEric Joyner * TCAM - Number of entries Profile ID TCAM table 93571d10453SEric Joyner * CDID - Control Domain ID of the hardware block 93671d10453SEric Joyner * PRED - Number of entries in the Profile Redirection Table 93771d10453SEric Joyner * FV - Number of entries in the Field Vector 93871d10453SEric Joyner * FVW - Width (in WORDs) of the Field Vector 93971d10453SEric Joyner * OVR - Overwrite existing table entries 94071d10453SEric Joyner * REV - Reverse FV 94171d10453SEric Joyner */ 94271d10453SEric Joyner /* XLT1 , XLT2 ,TCAM, PID,CDID,PRED, FV, FVW */ 94371d10453SEric Joyner /* Overwrite , Reverse FV */ 94471d10453SEric Joyner /* SW */ { ICE_XLT1_CNT, ICE_XLT2_CNT, 512, 256, 0, 256, 256, 48, 94571d10453SEric Joyner false, false }, 94671d10453SEric Joyner /* ACL */ { ICE_XLT1_CNT, ICE_XLT2_CNT, 512, 128, 0, 128, 128, 32, 94771d10453SEric Joyner false, false }, 94871d10453SEric Joyner /* FD */ { ICE_XLT1_CNT, ICE_XLT2_CNT, 512, 128, 0, 128, 128, 24, 94971d10453SEric Joyner false, true }, 95071d10453SEric Joyner /* RSS */ { ICE_XLT1_CNT, ICE_XLT2_CNT, 512, 128, 0, 128, 128, 24, 95171d10453SEric Joyner true, true }, 95271d10453SEric Joyner /* PE */ { ICE_XLT1_CNT, ICE_XLT2_CNT, 64, 32, 0, 32, 32, 24, 95371d10453SEric Joyner false, false }, 95471d10453SEric Joyner }; 95571d10453SEric Joyner 95671d10453SEric Joyner enum ice_sid_all { 95771d10453SEric Joyner ICE_SID_XLT1_OFF = 0, 95871d10453SEric Joyner ICE_SID_XLT2_OFF, 95971d10453SEric Joyner ICE_SID_PR_OFF, 96071d10453SEric Joyner ICE_SID_PR_REDIR_OFF, 96171d10453SEric Joyner ICE_SID_ES_OFF, 96271d10453SEric Joyner ICE_SID_OFF_COUNT, 96371d10453SEric Joyner }; 96471d10453SEric Joyner 96571d10453SEric Joyner /* Characteristic handling */ 96671d10453SEric Joyner 96771d10453SEric Joyner /** 96871d10453SEric Joyner * ice_match_prop_lst - determine if properties of two lists match 96971d10453SEric Joyner * @list1: first properties list 97071d10453SEric Joyner * @list2: second properties list 97171d10453SEric Joyner * 97271d10453SEric Joyner * Count, cookies and the order must match in order to be considered equivalent. 97371d10453SEric Joyner */ 97471d10453SEric Joyner static bool 97571d10453SEric Joyner ice_match_prop_lst(struct LIST_HEAD_TYPE *list1, struct LIST_HEAD_TYPE *list2) 97671d10453SEric Joyner { 97771d10453SEric Joyner struct ice_vsig_prof *tmp1; 97871d10453SEric Joyner struct ice_vsig_prof *tmp2; 97971d10453SEric Joyner u16 chk_count = 0; 98071d10453SEric Joyner u16 count = 0; 98171d10453SEric Joyner 98271d10453SEric Joyner /* compare counts */ 9837d7af7f8SEric Joyner LIST_FOR_EACH_ENTRY(tmp1, list1, ice_vsig_prof, list) 98471d10453SEric Joyner count++; 9857d7af7f8SEric Joyner LIST_FOR_EACH_ENTRY(tmp2, list2, ice_vsig_prof, list) 98671d10453SEric Joyner chk_count++; 98771d10453SEric Joyner if (!count || count != chk_count) 98871d10453SEric Joyner return false; 98971d10453SEric Joyner 99071d10453SEric Joyner tmp1 = LIST_FIRST_ENTRY(list1, struct ice_vsig_prof, list); 99171d10453SEric Joyner tmp2 = LIST_FIRST_ENTRY(list2, struct ice_vsig_prof, list); 99271d10453SEric Joyner 99371d10453SEric Joyner /* profile cookies must compare, and in the exact same order to take 99471d10453SEric Joyner * into account priority 99571d10453SEric Joyner */ 99671d10453SEric Joyner while (count--) { 99771d10453SEric Joyner if (tmp2->profile_cookie != tmp1->profile_cookie) 99871d10453SEric Joyner return false; 99971d10453SEric Joyner 100071d10453SEric Joyner tmp1 = LIST_NEXT_ENTRY(tmp1, struct ice_vsig_prof, list); 100171d10453SEric Joyner tmp2 = LIST_NEXT_ENTRY(tmp2, struct ice_vsig_prof, list); 100271d10453SEric Joyner } 100371d10453SEric Joyner 100471d10453SEric Joyner return true; 100571d10453SEric Joyner } 100671d10453SEric Joyner 100771d10453SEric Joyner /* VSIG Management */ 100871d10453SEric Joyner 100971d10453SEric Joyner /** 101071d10453SEric Joyner * ice_vsig_update_xlt2_sect - update one section of XLT2 table 101171d10453SEric Joyner * @hw: pointer to the hardware structure 101271d10453SEric Joyner * @blk: HW block 101371d10453SEric Joyner * @vsi: HW VSI number to program 101471d10453SEric Joyner * @vsig: VSIG for the VSI 101571d10453SEric Joyner * 101671d10453SEric Joyner * This function will update the XLT2 hardware table with the input VSI 101771d10453SEric Joyner * group configuration. 101871d10453SEric Joyner */ 1019*f2635e84SEric Joyner static int 102071d10453SEric Joyner ice_vsig_update_xlt2_sect(struct ice_hw *hw, enum ice_block blk, u16 vsi, 102171d10453SEric Joyner u16 vsig) 102271d10453SEric Joyner { 102371d10453SEric Joyner struct ice_xlt2_section *sect; 102471d10453SEric Joyner struct ice_buf_build *bld; 1025*f2635e84SEric Joyner int status; 102671d10453SEric Joyner 102771d10453SEric Joyner bld = ice_pkg_buf_alloc_single_section(hw, ice_sect_id(blk, ICE_XLT2), 10287d7af7f8SEric Joyner ice_struct_size(sect, value, 1), 102971d10453SEric Joyner (void **)§); 103071d10453SEric Joyner if (!bld) 103171d10453SEric Joyner return ICE_ERR_NO_MEMORY; 103271d10453SEric Joyner 103371d10453SEric Joyner sect->count = CPU_TO_LE16(1); 103471d10453SEric Joyner sect->offset = CPU_TO_LE16(vsi); 103571d10453SEric Joyner sect->value[0] = CPU_TO_LE16(vsig); 103671d10453SEric Joyner 103771d10453SEric Joyner status = ice_update_pkg(hw, ice_pkg_buf(bld), 1); 103871d10453SEric Joyner 103971d10453SEric Joyner ice_pkg_buf_free(hw, bld); 104071d10453SEric Joyner 104171d10453SEric Joyner return status; 104271d10453SEric Joyner } 104371d10453SEric Joyner 104471d10453SEric Joyner /** 104571d10453SEric Joyner * ice_vsig_update_xlt2 - update XLT2 table with VSIG configuration 104671d10453SEric Joyner * @hw: pointer to the hardware structure 104771d10453SEric Joyner * @blk: HW block 104871d10453SEric Joyner * 104971d10453SEric Joyner * This function will update the XLT2 hardware table with the input VSI 105071d10453SEric Joyner * group configuration of used vsis. 105171d10453SEric Joyner */ 1052*f2635e84SEric Joyner int ice_vsig_update_xlt2(struct ice_hw *hw, enum ice_block blk) 105371d10453SEric Joyner { 105471d10453SEric Joyner u16 vsi; 105571d10453SEric Joyner 105671d10453SEric Joyner for (vsi = 0; vsi < ICE_MAX_VSI; vsi++) { 105771d10453SEric Joyner /* update only vsis that have been changed */ 105871d10453SEric Joyner if (hw->blk[blk].xlt2.vsis[vsi].changed) { 1059*f2635e84SEric Joyner int status; 106071d10453SEric Joyner u16 vsig; 106171d10453SEric Joyner 106271d10453SEric Joyner vsig = hw->blk[blk].xlt2.vsis[vsi].vsig; 106371d10453SEric Joyner status = ice_vsig_update_xlt2_sect(hw, blk, vsi, vsig); 106471d10453SEric Joyner if (status) 106571d10453SEric Joyner return status; 106671d10453SEric Joyner 106771d10453SEric Joyner hw->blk[blk].xlt2.vsis[vsi].changed = 0; 106871d10453SEric Joyner } 106971d10453SEric Joyner } 107071d10453SEric Joyner 1071*f2635e84SEric Joyner return 0; 107271d10453SEric Joyner } 107371d10453SEric Joyner 107471d10453SEric Joyner /** 107571d10453SEric Joyner * ice_vsig_find_vsi - find a VSIG that contains a specified VSI 107671d10453SEric Joyner * @hw: pointer to the hardware structure 107771d10453SEric Joyner * @blk: HW block 107871d10453SEric Joyner * @vsi: VSI of interest 107971d10453SEric Joyner * @vsig: pointer to receive the VSI group 108071d10453SEric Joyner * 108171d10453SEric Joyner * This function will lookup the VSI entry in the XLT2 list and return 108271d10453SEric Joyner * the VSI group its associated with. 108371d10453SEric Joyner */ 1084*f2635e84SEric Joyner int 108571d10453SEric Joyner ice_vsig_find_vsi(struct ice_hw *hw, enum ice_block blk, u16 vsi, u16 *vsig) 108671d10453SEric Joyner { 108771d10453SEric Joyner if (!vsig || vsi >= ICE_MAX_VSI) 108871d10453SEric Joyner return ICE_ERR_PARAM; 108971d10453SEric Joyner 109071d10453SEric Joyner /* As long as there's a default or valid VSIG associated with the input 109171d10453SEric Joyner * VSI, the functions returns a success. Any handling of VSIG will be 109271d10453SEric Joyner * done by the following add, update or remove functions. 109371d10453SEric Joyner */ 109471d10453SEric Joyner *vsig = hw->blk[blk].xlt2.vsis[vsi].vsig; 109571d10453SEric Joyner 1096*f2635e84SEric Joyner return 0; 109771d10453SEric Joyner } 109871d10453SEric Joyner 109971d10453SEric Joyner /** 110071d10453SEric Joyner * ice_vsig_alloc_val - allocate a new VSIG by value 110171d10453SEric Joyner * @hw: pointer to the hardware structure 110271d10453SEric Joyner * @blk: HW block 110371d10453SEric Joyner * @vsig: the VSIG to allocate 110471d10453SEric Joyner * 110571d10453SEric Joyner * This function will allocate a given VSIG specified by the VSIG parameter. 110671d10453SEric Joyner */ 110771d10453SEric Joyner static u16 ice_vsig_alloc_val(struct ice_hw *hw, enum ice_block blk, u16 vsig) 110871d10453SEric Joyner { 110971d10453SEric Joyner u16 idx = vsig & ICE_VSIG_IDX_M; 111071d10453SEric Joyner 111171d10453SEric Joyner if (!hw->blk[blk].xlt2.vsig_tbl[idx].in_use) { 111271d10453SEric Joyner INIT_LIST_HEAD(&hw->blk[blk].xlt2.vsig_tbl[idx].prop_lst); 111371d10453SEric Joyner hw->blk[blk].xlt2.vsig_tbl[idx].in_use = true; 111471d10453SEric Joyner } 111571d10453SEric Joyner 111671d10453SEric Joyner return ICE_VSIG_VALUE(idx, hw->pf_id); 111771d10453SEric Joyner } 111871d10453SEric Joyner 111971d10453SEric Joyner /** 112071d10453SEric Joyner * ice_vsig_alloc - Finds a free entry and allocates a new VSIG 112171d10453SEric Joyner * @hw: pointer to the hardware structure 112271d10453SEric Joyner * @blk: HW block 112371d10453SEric Joyner * 112471d10453SEric Joyner * This function will iterate through the VSIG list and mark the first 112571d10453SEric Joyner * unused entry for the new VSIG entry as used and return that value. 112671d10453SEric Joyner */ 112771d10453SEric Joyner static u16 ice_vsig_alloc(struct ice_hw *hw, enum ice_block blk) 112871d10453SEric Joyner { 112971d10453SEric Joyner u16 i; 113071d10453SEric Joyner 113171d10453SEric Joyner for (i = 1; i < ICE_MAX_VSIGS; i++) 113271d10453SEric Joyner if (!hw->blk[blk].xlt2.vsig_tbl[i].in_use) 113371d10453SEric Joyner return ice_vsig_alloc_val(hw, blk, i); 113471d10453SEric Joyner 113571d10453SEric Joyner return ICE_DEFAULT_VSIG; 113671d10453SEric Joyner } 113771d10453SEric Joyner 113871d10453SEric Joyner /** 113971d10453SEric Joyner * ice_find_dup_props_vsig - find VSI group with a specified set of properties 114071d10453SEric Joyner * @hw: pointer to the hardware structure 114171d10453SEric Joyner * @blk: HW block 114271d10453SEric Joyner * @chs: characteristic list 114371d10453SEric Joyner * @vsig: returns the VSIG with the matching profiles, if found 114471d10453SEric Joyner * 114571d10453SEric Joyner * Each VSIG is associated with a characteristic set; i.e. all VSIs under 114671d10453SEric Joyner * a group have the same characteristic set. To check if there exists a VSIG 114771d10453SEric Joyner * which has the same characteristics as the input characteristics; this 114871d10453SEric Joyner * function will iterate through the XLT2 list and return the VSIG that has a 114971d10453SEric Joyner * matching configuration. In order to make sure that priorities are accounted 115071d10453SEric Joyner * for, the list must match exactly, including the order in which the 115171d10453SEric Joyner * characteristics are listed. 115271d10453SEric Joyner */ 1153*f2635e84SEric Joyner static int 115471d10453SEric Joyner ice_find_dup_props_vsig(struct ice_hw *hw, enum ice_block blk, 115571d10453SEric Joyner struct LIST_HEAD_TYPE *chs, u16 *vsig) 115671d10453SEric Joyner { 115771d10453SEric Joyner struct ice_xlt2 *xlt2 = &hw->blk[blk].xlt2; 115871d10453SEric Joyner u16 i; 115971d10453SEric Joyner 11607d7af7f8SEric Joyner for (i = 0; i < xlt2->count; i++) 116171d10453SEric Joyner if (xlt2->vsig_tbl[i].in_use && 116271d10453SEric Joyner ice_match_prop_lst(chs, &xlt2->vsig_tbl[i].prop_lst)) { 116371d10453SEric Joyner *vsig = ICE_VSIG_VALUE(i, hw->pf_id); 1164*f2635e84SEric Joyner return 0; 116571d10453SEric Joyner } 116671d10453SEric Joyner 116771d10453SEric Joyner return ICE_ERR_DOES_NOT_EXIST; 116871d10453SEric Joyner } 116971d10453SEric Joyner 117071d10453SEric Joyner /** 117171d10453SEric Joyner * ice_vsig_free - free VSI group 117271d10453SEric Joyner * @hw: pointer to the hardware structure 117371d10453SEric Joyner * @blk: HW block 117471d10453SEric Joyner * @vsig: VSIG to remove 117571d10453SEric Joyner * 117671d10453SEric Joyner * The function will remove all VSIs associated with the input VSIG and move 117771d10453SEric Joyner * them to the DEFAULT_VSIG and mark the VSIG available. 117871d10453SEric Joyner */ 1179*f2635e84SEric Joyner static int 118071d10453SEric Joyner ice_vsig_free(struct ice_hw *hw, enum ice_block blk, u16 vsig) 118171d10453SEric Joyner { 118271d10453SEric Joyner struct ice_vsig_prof *dtmp, *del; 118371d10453SEric Joyner struct ice_vsig_vsi *vsi_cur; 118471d10453SEric Joyner u16 idx; 118571d10453SEric Joyner 118671d10453SEric Joyner idx = vsig & ICE_VSIG_IDX_M; 118771d10453SEric Joyner if (idx >= ICE_MAX_VSIGS) 118871d10453SEric Joyner return ICE_ERR_PARAM; 118971d10453SEric Joyner 119071d10453SEric Joyner if (!hw->blk[blk].xlt2.vsig_tbl[idx].in_use) 119171d10453SEric Joyner return ICE_ERR_DOES_NOT_EXIST; 119271d10453SEric Joyner 119371d10453SEric Joyner hw->blk[blk].xlt2.vsig_tbl[idx].in_use = false; 119471d10453SEric Joyner 119571d10453SEric Joyner vsi_cur = hw->blk[blk].xlt2.vsig_tbl[idx].first_vsi; 119671d10453SEric Joyner /* If the VSIG has at least 1 VSI then iterate through the 119771d10453SEric Joyner * list and remove the VSIs before deleting the group. 119871d10453SEric Joyner */ 119971d10453SEric Joyner if (vsi_cur) { 120071d10453SEric Joyner /* remove all vsis associated with this VSIG XLT2 entry */ 120171d10453SEric Joyner do { 120271d10453SEric Joyner struct ice_vsig_vsi *tmp = vsi_cur->next_vsi; 120371d10453SEric Joyner 120471d10453SEric Joyner vsi_cur->vsig = ICE_DEFAULT_VSIG; 120571d10453SEric Joyner vsi_cur->changed = 1; 120671d10453SEric Joyner vsi_cur->next_vsi = NULL; 120771d10453SEric Joyner vsi_cur = tmp; 120871d10453SEric Joyner } while (vsi_cur); 120971d10453SEric Joyner 121071d10453SEric Joyner /* NULL terminate head of VSI list */ 121171d10453SEric Joyner hw->blk[blk].xlt2.vsig_tbl[idx].first_vsi = NULL; 121271d10453SEric Joyner } 121371d10453SEric Joyner 121471d10453SEric Joyner /* free characteristic list */ 121571d10453SEric Joyner LIST_FOR_EACH_ENTRY_SAFE(del, dtmp, 121671d10453SEric Joyner &hw->blk[blk].xlt2.vsig_tbl[idx].prop_lst, 121771d10453SEric Joyner ice_vsig_prof, list) { 121871d10453SEric Joyner LIST_DEL(&del->list); 121971d10453SEric Joyner ice_free(hw, del); 122071d10453SEric Joyner } 122171d10453SEric Joyner 122271d10453SEric Joyner /* if VSIG characteristic list was cleared for reset 122371d10453SEric Joyner * re-initialize the list head 122471d10453SEric Joyner */ 122571d10453SEric Joyner INIT_LIST_HEAD(&hw->blk[blk].xlt2.vsig_tbl[idx].prop_lst); 122671d10453SEric Joyner 1227*f2635e84SEric Joyner return 0; 122871d10453SEric Joyner } 122971d10453SEric Joyner 123071d10453SEric Joyner /** 123171d10453SEric Joyner * ice_vsig_remove_vsi - remove VSI from VSIG 123271d10453SEric Joyner * @hw: pointer to the hardware structure 123371d10453SEric Joyner * @blk: HW block 123471d10453SEric Joyner * @vsi: VSI to remove 123571d10453SEric Joyner * @vsig: VSI group to remove from 123671d10453SEric Joyner * 123771d10453SEric Joyner * The function will remove the input VSI from its VSI group and move it 123871d10453SEric Joyner * to the DEFAULT_VSIG. 123971d10453SEric Joyner */ 1240*f2635e84SEric Joyner static int 124171d10453SEric Joyner ice_vsig_remove_vsi(struct ice_hw *hw, enum ice_block blk, u16 vsi, u16 vsig) 124271d10453SEric Joyner { 124371d10453SEric Joyner struct ice_vsig_vsi **vsi_head, *vsi_cur, *vsi_tgt; 124471d10453SEric Joyner u16 idx; 124571d10453SEric Joyner 124671d10453SEric Joyner idx = vsig & ICE_VSIG_IDX_M; 124771d10453SEric Joyner 124871d10453SEric Joyner if (vsi >= ICE_MAX_VSI || idx >= ICE_MAX_VSIGS) 124971d10453SEric Joyner return ICE_ERR_PARAM; 125071d10453SEric Joyner 125171d10453SEric Joyner if (!hw->blk[blk].xlt2.vsig_tbl[idx].in_use) 125271d10453SEric Joyner return ICE_ERR_DOES_NOT_EXIST; 125371d10453SEric Joyner 125471d10453SEric Joyner /* entry already in default VSIG, don't have to remove */ 125571d10453SEric Joyner if (idx == ICE_DEFAULT_VSIG) 1256*f2635e84SEric Joyner return 0; 125771d10453SEric Joyner 125871d10453SEric Joyner vsi_head = &hw->blk[blk].xlt2.vsig_tbl[idx].first_vsi; 125971d10453SEric Joyner if (!(*vsi_head)) 126071d10453SEric Joyner return ICE_ERR_CFG; 126171d10453SEric Joyner 126271d10453SEric Joyner vsi_tgt = &hw->blk[blk].xlt2.vsis[vsi]; 126371d10453SEric Joyner vsi_cur = (*vsi_head); 126471d10453SEric Joyner 126571d10453SEric Joyner /* iterate the VSI list, skip over the entry to be removed */ 126671d10453SEric Joyner while (vsi_cur) { 126771d10453SEric Joyner if (vsi_tgt == vsi_cur) { 126871d10453SEric Joyner (*vsi_head) = vsi_cur->next_vsi; 126971d10453SEric Joyner break; 127071d10453SEric Joyner } 127171d10453SEric Joyner vsi_head = &vsi_cur->next_vsi; 127271d10453SEric Joyner vsi_cur = vsi_cur->next_vsi; 127371d10453SEric Joyner } 127471d10453SEric Joyner 127571d10453SEric Joyner /* verify if VSI was removed from group list */ 127671d10453SEric Joyner if (!vsi_cur) 127771d10453SEric Joyner return ICE_ERR_DOES_NOT_EXIST; 127871d10453SEric Joyner 127971d10453SEric Joyner vsi_cur->vsig = ICE_DEFAULT_VSIG; 128071d10453SEric Joyner vsi_cur->changed = 1; 128171d10453SEric Joyner vsi_cur->next_vsi = NULL; 128271d10453SEric Joyner 1283*f2635e84SEric Joyner return 0; 128471d10453SEric Joyner } 128571d10453SEric Joyner 128671d10453SEric Joyner /** 128771d10453SEric Joyner * ice_vsig_add_mv_vsi - add or move a VSI to a VSI group 128871d10453SEric Joyner * @hw: pointer to the hardware structure 128971d10453SEric Joyner * @blk: HW block 129071d10453SEric Joyner * @vsi: VSI to move 129171d10453SEric Joyner * @vsig: destination VSI group 129271d10453SEric Joyner * 129371d10453SEric Joyner * This function will move or add the input VSI to the target VSIG. 129471d10453SEric Joyner * The function will find the original VSIG the VSI belongs to and 129571d10453SEric Joyner * move the entry to the DEFAULT_VSIG, update the original VSIG and 129671d10453SEric Joyner * then move entry to the new VSIG. 129771d10453SEric Joyner */ 1298*f2635e84SEric Joyner static int 129971d10453SEric Joyner ice_vsig_add_mv_vsi(struct ice_hw *hw, enum ice_block blk, u16 vsi, u16 vsig) 130071d10453SEric Joyner { 130171d10453SEric Joyner struct ice_vsig_vsi *tmp; 130271d10453SEric Joyner u16 orig_vsig, idx; 1303*f2635e84SEric Joyner int status; 130471d10453SEric Joyner 130571d10453SEric Joyner idx = vsig & ICE_VSIG_IDX_M; 130671d10453SEric Joyner 130771d10453SEric Joyner if (vsi >= ICE_MAX_VSI || idx >= ICE_MAX_VSIGS) 130871d10453SEric Joyner return ICE_ERR_PARAM; 130971d10453SEric Joyner 131071d10453SEric Joyner /* if VSIG not in use and VSIG is not default type this VSIG 131171d10453SEric Joyner * doesn't exist. 131271d10453SEric Joyner */ 131371d10453SEric Joyner if (!hw->blk[blk].xlt2.vsig_tbl[idx].in_use && 131471d10453SEric Joyner vsig != ICE_DEFAULT_VSIG) 131571d10453SEric Joyner return ICE_ERR_DOES_NOT_EXIST; 131671d10453SEric Joyner 131771d10453SEric Joyner status = ice_vsig_find_vsi(hw, blk, vsi, &orig_vsig); 131871d10453SEric Joyner if (status) 131971d10453SEric Joyner return status; 132071d10453SEric Joyner 132171d10453SEric Joyner /* no update required if vsigs match */ 132271d10453SEric Joyner if (orig_vsig == vsig) 1323*f2635e84SEric Joyner return 0; 132471d10453SEric Joyner 132571d10453SEric Joyner if (orig_vsig != ICE_DEFAULT_VSIG) { 132671d10453SEric Joyner /* remove entry from orig_vsig and add to default VSIG */ 132771d10453SEric Joyner status = ice_vsig_remove_vsi(hw, blk, vsi, orig_vsig); 132871d10453SEric Joyner if (status) 132971d10453SEric Joyner return status; 133071d10453SEric Joyner } 133171d10453SEric Joyner 133271d10453SEric Joyner if (idx == ICE_DEFAULT_VSIG) 1333*f2635e84SEric Joyner return 0; 133471d10453SEric Joyner 133571d10453SEric Joyner /* Create VSI entry and add VSIG and prop_mask values */ 133671d10453SEric Joyner hw->blk[blk].xlt2.vsis[vsi].vsig = vsig; 133771d10453SEric Joyner hw->blk[blk].xlt2.vsis[vsi].changed = 1; 133871d10453SEric Joyner 133971d10453SEric Joyner /* Add new entry to the head of the VSIG list */ 134071d10453SEric Joyner tmp = hw->blk[blk].xlt2.vsig_tbl[idx].first_vsi; 134171d10453SEric Joyner hw->blk[blk].xlt2.vsig_tbl[idx].first_vsi = 134271d10453SEric Joyner &hw->blk[blk].xlt2.vsis[vsi]; 134371d10453SEric Joyner hw->blk[blk].xlt2.vsis[vsi].next_vsi = tmp; 134471d10453SEric Joyner hw->blk[blk].xlt2.t[vsi] = vsig; 134571d10453SEric Joyner 1346*f2635e84SEric Joyner return 0; 134771d10453SEric Joyner } 134871d10453SEric Joyner 134971d10453SEric Joyner /** 135071d10453SEric Joyner * ice_find_prof_id - find profile ID for a given field vector 135171d10453SEric Joyner * @hw: pointer to the hardware structure 135271d10453SEric Joyner * @blk: HW block 135371d10453SEric Joyner * @fv: field vector to search for 135471d10453SEric Joyner * @prof_id: receives the profile ID 135571d10453SEric Joyner */ 1356*f2635e84SEric Joyner static int 135771d10453SEric Joyner ice_find_prof_id(struct ice_hw *hw, enum ice_block blk, 135871d10453SEric Joyner struct ice_fv_word *fv, u8 *prof_id) 135971d10453SEric Joyner { 136071d10453SEric Joyner struct ice_es *es = &hw->blk[blk].es; 136171d10453SEric Joyner u16 off; 136271d10453SEric Joyner u8 i; 136371d10453SEric Joyner 136471d10453SEric Joyner for (i = 0; i < (u8)es->count; i++) { 136571d10453SEric Joyner off = i * es->fvw; 136671d10453SEric Joyner 136771d10453SEric Joyner if (memcmp(&es->t[off], fv, es->fvw * sizeof(*fv))) 136871d10453SEric Joyner continue; 136971d10453SEric Joyner 137071d10453SEric Joyner *prof_id = i; 1371*f2635e84SEric Joyner return 0; 137271d10453SEric Joyner } 137371d10453SEric Joyner 137471d10453SEric Joyner return ICE_ERR_DOES_NOT_EXIST; 137571d10453SEric Joyner } 137671d10453SEric Joyner 137771d10453SEric Joyner /** 137871d10453SEric Joyner * ice_prof_id_rsrc_type - get profile ID resource type for a block type 137971d10453SEric Joyner * @blk: the block type 138071d10453SEric Joyner * @rsrc_type: pointer to variable to receive the resource type 138171d10453SEric Joyner */ 138271d10453SEric Joyner static bool ice_prof_id_rsrc_type(enum ice_block blk, u16 *rsrc_type) 138371d10453SEric Joyner { 138471d10453SEric Joyner switch (blk) { 138571d10453SEric Joyner case ICE_BLK_RSS: 138671d10453SEric Joyner *rsrc_type = ICE_AQC_RES_TYPE_HASH_PROF_BLDR_PROFID; 138771d10453SEric Joyner break; 138871d10453SEric Joyner case ICE_BLK_PE: 138971d10453SEric Joyner *rsrc_type = ICE_AQC_RES_TYPE_QHASH_PROF_BLDR_PROFID; 139071d10453SEric Joyner break; 139171d10453SEric Joyner default: 139271d10453SEric Joyner return false; 139371d10453SEric Joyner } 139471d10453SEric Joyner return true; 139571d10453SEric Joyner } 139671d10453SEric Joyner 139771d10453SEric Joyner /** 139871d10453SEric Joyner * ice_tcam_ent_rsrc_type - get TCAM entry resource type for a block type 139971d10453SEric Joyner * @blk: the block type 140071d10453SEric Joyner * @rsrc_type: pointer to variable to receive the resource type 140171d10453SEric Joyner */ 140271d10453SEric Joyner static bool ice_tcam_ent_rsrc_type(enum ice_block blk, u16 *rsrc_type) 140371d10453SEric Joyner { 140471d10453SEric Joyner switch (blk) { 140571d10453SEric Joyner case ICE_BLK_RSS: 140671d10453SEric Joyner *rsrc_type = ICE_AQC_RES_TYPE_HASH_PROF_BLDR_TCAM; 140771d10453SEric Joyner break; 140871d10453SEric Joyner case ICE_BLK_PE: 140971d10453SEric Joyner *rsrc_type = ICE_AQC_RES_TYPE_QHASH_PROF_BLDR_TCAM; 141071d10453SEric Joyner break; 141171d10453SEric Joyner default: 141271d10453SEric Joyner return false; 141371d10453SEric Joyner } 141471d10453SEric Joyner return true; 141571d10453SEric Joyner } 141671d10453SEric Joyner 141771d10453SEric Joyner /** 141871d10453SEric Joyner * ice_alloc_tcam_ent - allocate hardware TCAM entry 141971d10453SEric Joyner * @hw: pointer to the HW struct 142071d10453SEric Joyner * @blk: the block to allocate the TCAM for 14217d7af7f8SEric Joyner * @btm: true to allocate from bottom of table, false to allocate from top 142271d10453SEric Joyner * @tcam_idx: pointer to variable to receive the TCAM entry 142371d10453SEric Joyner * 142471d10453SEric Joyner * This function allocates a new entry in a Profile ID TCAM for a specific 142571d10453SEric Joyner * block. 142671d10453SEric Joyner */ 1427*f2635e84SEric Joyner static int 14287d7af7f8SEric Joyner ice_alloc_tcam_ent(struct ice_hw *hw, enum ice_block blk, bool btm, 14297d7af7f8SEric Joyner u16 *tcam_idx) 143071d10453SEric Joyner { 143171d10453SEric Joyner u16 res_type; 143271d10453SEric Joyner 143371d10453SEric Joyner if (!ice_tcam_ent_rsrc_type(blk, &res_type)) 143471d10453SEric Joyner return ICE_ERR_PARAM; 143571d10453SEric Joyner 14367d7af7f8SEric Joyner return ice_alloc_hw_res(hw, res_type, 1, btm, tcam_idx); 143771d10453SEric Joyner } 143871d10453SEric Joyner 143971d10453SEric Joyner /** 144071d10453SEric Joyner * ice_free_tcam_ent - free hardware TCAM entry 144171d10453SEric Joyner * @hw: pointer to the HW struct 144271d10453SEric Joyner * @blk: the block from which to free the TCAM entry 144371d10453SEric Joyner * @tcam_idx: the TCAM entry to free 144471d10453SEric Joyner * 144571d10453SEric Joyner * This function frees an entry in a Profile ID TCAM for a specific block. 144671d10453SEric Joyner */ 1447*f2635e84SEric Joyner static int 144871d10453SEric Joyner ice_free_tcam_ent(struct ice_hw *hw, enum ice_block blk, u16 tcam_idx) 144971d10453SEric Joyner { 145071d10453SEric Joyner u16 res_type; 145171d10453SEric Joyner 145271d10453SEric Joyner if (!ice_tcam_ent_rsrc_type(blk, &res_type)) 145371d10453SEric Joyner return ICE_ERR_PARAM; 145471d10453SEric Joyner 145571d10453SEric Joyner return ice_free_hw_res(hw, res_type, 1, &tcam_idx); 145671d10453SEric Joyner } 145771d10453SEric Joyner 145871d10453SEric Joyner /** 145971d10453SEric Joyner * ice_alloc_prof_id - allocate profile ID 146071d10453SEric Joyner * @hw: pointer to the HW struct 146171d10453SEric Joyner * @blk: the block to allocate the profile ID for 146271d10453SEric Joyner * @prof_id: pointer to variable to receive the profile ID 146371d10453SEric Joyner * 146471d10453SEric Joyner * This function allocates a new profile ID, which also corresponds to a Field 146571d10453SEric Joyner * Vector (Extraction Sequence) entry. 146671d10453SEric Joyner */ 1467*f2635e84SEric Joyner static int 146871d10453SEric Joyner ice_alloc_prof_id(struct ice_hw *hw, enum ice_block blk, u8 *prof_id) 146971d10453SEric Joyner { 147071d10453SEric Joyner u16 res_type; 147171d10453SEric Joyner u16 get_prof; 1472*f2635e84SEric Joyner int status; 147371d10453SEric Joyner 147471d10453SEric Joyner if (!ice_prof_id_rsrc_type(blk, &res_type)) 147571d10453SEric Joyner return ICE_ERR_PARAM; 147671d10453SEric Joyner 147771d10453SEric Joyner status = ice_alloc_hw_res(hw, res_type, 1, false, &get_prof); 147871d10453SEric Joyner if (!status) 147971d10453SEric Joyner *prof_id = (u8)get_prof; 148071d10453SEric Joyner 148171d10453SEric Joyner return status; 148271d10453SEric Joyner } 148371d10453SEric Joyner 148471d10453SEric Joyner /** 148571d10453SEric Joyner * ice_free_prof_id - free profile ID 148671d10453SEric Joyner * @hw: pointer to the HW struct 148771d10453SEric Joyner * @blk: the block from which to free the profile ID 148871d10453SEric Joyner * @prof_id: the profile ID to free 148971d10453SEric Joyner * 149071d10453SEric Joyner * This function frees a profile ID, which also corresponds to a Field Vector. 149171d10453SEric Joyner */ 1492*f2635e84SEric Joyner static int 149371d10453SEric Joyner ice_free_prof_id(struct ice_hw *hw, enum ice_block blk, u8 prof_id) 149471d10453SEric Joyner { 149571d10453SEric Joyner u16 tmp_prof_id = (u16)prof_id; 149671d10453SEric Joyner u16 res_type; 149771d10453SEric Joyner 149871d10453SEric Joyner if (!ice_prof_id_rsrc_type(blk, &res_type)) 149971d10453SEric Joyner return ICE_ERR_PARAM; 150071d10453SEric Joyner 150171d10453SEric Joyner return ice_free_hw_res(hw, res_type, 1, &tmp_prof_id); 150271d10453SEric Joyner } 150371d10453SEric Joyner 150471d10453SEric Joyner /** 150571d10453SEric Joyner * ice_prof_inc_ref - increment reference count for profile 150671d10453SEric Joyner * @hw: pointer to the HW struct 150771d10453SEric Joyner * @blk: the block from which to free the profile ID 150871d10453SEric Joyner * @prof_id: the profile ID for which to increment the reference count 150971d10453SEric Joyner */ 1510*f2635e84SEric Joyner static int 151171d10453SEric Joyner ice_prof_inc_ref(struct ice_hw *hw, enum ice_block blk, u8 prof_id) 151271d10453SEric Joyner { 151371d10453SEric Joyner if (prof_id > hw->blk[blk].es.count) 151471d10453SEric Joyner return ICE_ERR_PARAM; 151571d10453SEric Joyner 151671d10453SEric Joyner hw->blk[blk].es.ref_count[prof_id]++; 151771d10453SEric Joyner 1518*f2635e84SEric Joyner return 0; 151971d10453SEric Joyner } 152071d10453SEric Joyner 152171d10453SEric Joyner /** 152271d10453SEric Joyner * ice_write_es - write an extraction sequence to hardware 152371d10453SEric Joyner * @hw: pointer to the HW struct 152471d10453SEric Joyner * @blk: the block in which to write the extraction sequence 152571d10453SEric Joyner * @prof_id: the profile ID to write 152671d10453SEric Joyner * @fv: pointer to the extraction sequence to write - NULL to clear extraction 152771d10453SEric Joyner */ 152871d10453SEric Joyner static void 152971d10453SEric Joyner ice_write_es(struct ice_hw *hw, enum ice_block blk, u8 prof_id, 153071d10453SEric Joyner struct ice_fv_word *fv) 153171d10453SEric Joyner { 153271d10453SEric Joyner u16 off; 153371d10453SEric Joyner 153471d10453SEric Joyner off = prof_id * hw->blk[blk].es.fvw; 153571d10453SEric Joyner if (!fv) { 153671d10453SEric Joyner ice_memset(&hw->blk[blk].es.t[off], 0, hw->blk[blk].es.fvw * 153771d10453SEric Joyner sizeof(*fv), ICE_NONDMA_MEM); 153871d10453SEric Joyner hw->blk[blk].es.written[prof_id] = false; 153971d10453SEric Joyner } else { 154071d10453SEric Joyner ice_memcpy(&hw->blk[blk].es.t[off], fv, hw->blk[blk].es.fvw * 154171d10453SEric Joyner sizeof(*fv), ICE_NONDMA_TO_NONDMA); 154271d10453SEric Joyner } 154371d10453SEric Joyner } 154471d10453SEric Joyner 154571d10453SEric Joyner /** 154671d10453SEric Joyner * ice_prof_dec_ref - decrement reference count for profile 154771d10453SEric Joyner * @hw: pointer to the HW struct 154871d10453SEric Joyner * @blk: the block from which to free the profile ID 154971d10453SEric Joyner * @prof_id: the profile ID for which to decrement the reference count 155071d10453SEric Joyner */ 1551*f2635e84SEric Joyner static int 155271d10453SEric Joyner ice_prof_dec_ref(struct ice_hw *hw, enum ice_block blk, u8 prof_id) 155371d10453SEric Joyner { 155471d10453SEric Joyner if (prof_id > hw->blk[blk].es.count) 155571d10453SEric Joyner return ICE_ERR_PARAM; 155671d10453SEric Joyner 155771d10453SEric Joyner if (hw->blk[blk].es.ref_count[prof_id] > 0) { 155871d10453SEric Joyner if (!--hw->blk[blk].es.ref_count[prof_id]) { 155971d10453SEric Joyner ice_write_es(hw, blk, prof_id, NULL); 156071d10453SEric Joyner return ice_free_prof_id(hw, blk, prof_id); 156171d10453SEric Joyner } 156271d10453SEric Joyner } 156371d10453SEric Joyner 1564*f2635e84SEric Joyner return 0; 156571d10453SEric Joyner } 156671d10453SEric Joyner 156771d10453SEric Joyner /* Block / table section IDs */ 156871d10453SEric Joyner static const u32 ice_blk_sids[ICE_BLK_COUNT][ICE_SID_OFF_COUNT] = { 156971d10453SEric Joyner /* SWITCH */ 157071d10453SEric Joyner { ICE_SID_XLT1_SW, 157171d10453SEric Joyner ICE_SID_XLT2_SW, 157271d10453SEric Joyner ICE_SID_PROFID_TCAM_SW, 157371d10453SEric Joyner ICE_SID_PROFID_REDIR_SW, 157471d10453SEric Joyner ICE_SID_FLD_VEC_SW 157571d10453SEric Joyner }, 157671d10453SEric Joyner 157771d10453SEric Joyner /* ACL */ 157871d10453SEric Joyner { ICE_SID_XLT1_ACL, 157971d10453SEric Joyner ICE_SID_XLT2_ACL, 158071d10453SEric Joyner ICE_SID_PROFID_TCAM_ACL, 158171d10453SEric Joyner ICE_SID_PROFID_REDIR_ACL, 158271d10453SEric Joyner ICE_SID_FLD_VEC_ACL 158371d10453SEric Joyner }, 158471d10453SEric Joyner 158571d10453SEric Joyner /* FD */ 158671d10453SEric Joyner { ICE_SID_XLT1_FD, 158771d10453SEric Joyner ICE_SID_XLT2_FD, 158871d10453SEric Joyner ICE_SID_PROFID_TCAM_FD, 158971d10453SEric Joyner ICE_SID_PROFID_REDIR_FD, 159071d10453SEric Joyner ICE_SID_FLD_VEC_FD 159171d10453SEric Joyner }, 159271d10453SEric Joyner 159371d10453SEric Joyner /* RSS */ 159471d10453SEric Joyner { ICE_SID_XLT1_RSS, 159571d10453SEric Joyner ICE_SID_XLT2_RSS, 159671d10453SEric Joyner ICE_SID_PROFID_TCAM_RSS, 159771d10453SEric Joyner ICE_SID_PROFID_REDIR_RSS, 159871d10453SEric Joyner ICE_SID_FLD_VEC_RSS 159971d10453SEric Joyner }, 160071d10453SEric Joyner 160171d10453SEric Joyner /* PE */ 160271d10453SEric Joyner { ICE_SID_XLT1_PE, 160371d10453SEric Joyner ICE_SID_XLT2_PE, 160471d10453SEric Joyner ICE_SID_PROFID_TCAM_PE, 160571d10453SEric Joyner ICE_SID_PROFID_REDIR_PE, 160671d10453SEric Joyner ICE_SID_FLD_VEC_PE 160771d10453SEric Joyner } 160871d10453SEric Joyner }; 160971d10453SEric Joyner 161071d10453SEric Joyner /** 161171d10453SEric Joyner * ice_init_sw_xlt1_db - init software XLT1 database from HW tables 161271d10453SEric Joyner * @hw: pointer to the hardware structure 161371d10453SEric Joyner * @blk: the HW block to initialize 161471d10453SEric Joyner */ 161571d10453SEric Joyner static void ice_init_sw_xlt1_db(struct ice_hw *hw, enum ice_block blk) 161671d10453SEric Joyner { 161771d10453SEric Joyner u16 pt; 161871d10453SEric Joyner 161971d10453SEric Joyner for (pt = 0; pt < hw->blk[blk].xlt1.count; pt++) { 162071d10453SEric Joyner u8 ptg; 162171d10453SEric Joyner 162271d10453SEric Joyner ptg = hw->blk[blk].xlt1.t[pt]; 162371d10453SEric Joyner if (ptg != ICE_DEFAULT_PTG) { 162471d10453SEric Joyner ice_ptg_alloc_val(hw, blk, ptg); 162571d10453SEric Joyner ice_ptg_add_mv_ptype(hw, blk, pt, ptg); 162671d10453SEric Joyner } 162771d10453SEric Joyner } 162871d10453SEric Joyner } 162971d10453SEric Joyner 163071d10453SEric Joyner /** 163171d10453SEric Joyner * ice_init_sw_xlt2_db - init software XLT2 database from HW tables 163271d10453SEric Joyner * @hw: pointer to the hardware structure 163371d10453SEric Joyner * @blk: the HW block to initialize 163471d10453SEric Joyner */ 163571d10453SEric Joyner static void ice_init_sw_xlt2_db(struct ice_hw *hw, enum ice_block blk) 163671d10453SEric Joyner { 163771d10453SEric Joyner u16 vsi; 163871d10453SEric Joyner 163971d10453SEric Joyner for (vsi = 0; vsi < hw->blk[blk].xlt2.count; vsi++) { 164071d10453SEric Joyner u16 vsig; 164171d10453SEric Joyner 164271d10453SEric Joyner vsig = hw->blk[blk].xlt2.t[vsi]; 164371d10453SEric Joyner if (vsig) { 164471d10453SEric Joyner ice_vsig_alloc_val(hw, blk, vsig); 164571d10453SEric Joyner ice_vsig_add_mv_vsi(hw, blk, vsi, vsig); 164671d10453SEric Joyner /* no changes at this time, since this has been 164771d10453SEric Joyner * initialized from the original package 164871d10453SEric Joyner */ 164971d10453SEric Joyner hw->blk[blk].xlt2.vsis[vsi].changed = 0; 165071d10453SEric Joyner } 165171d10453SEric Joyner } 165271d10453SEric Joyner } 165371d10453SEric Joyner 165471d10453SEric Joyner /** 165571d10453SEric Joyner * ice_init_sw_db - init software database from HW tables 165671d10453SEric Joyner * @hw: pointer to the hardware structure 165771d10453SEric Joyner */ 165871d10453SEric Joyner static void ice_init_sw_db(struct ice_hw *hw) 165971d10453SEric Joyner { 166071d10453SEric Joyner u16 i; 166171d10453SEric Joyner 166271d10453SEric Joyner for (i = 0; i < ICE_BLK_COUNT; i++) { 166371d10453SEric Joyner ice_init_sw_xlt1_db(hw, (enum ice_block)i); 166471d10453SEric Joyner ice_init_sw_xlt2_db(hw, (enum ice_block)i); 166571d10453SEric Joyner } 166671d10453SEric Joyner } 166771d10453SEric Joyner 166871d10453SEric Joyner /** 166971d10453SEric Joyner * ice_fill_tbl - Reads content of a single table type into database 167071d10453SEric Joyner * @hw: pointer to the hardware structure 167171d10453SEric Joyner * @block_id: Block ID of the table to copy 167271d10453SEric Joyner * @sid: Section ID of the table to copy 167371d10453SEric Joyner * 167471d10453SEric Joyner * Will attempt to read the entire content of a given table of a single block 167571d10453SEric Joyner * into the driver database. We assume that the buffer will always 167671d10453SEric Joyner * be as large or larger than the data contained in the package. If 167771d10453SEric Joyner * this condition is not met, there is most likely an error in the package 167871d10453SEric Joyner * contents. 167971d10453SEric Joyner */ 168071d10453SEric Joyner static void ice_fill_tbl(struct ice_hw *hw, enum ice_block block_id, u32 sid) 168171d10453SEric Joyner { 168271d10453SEric Joyner u32 dst_len, sect_len, offset = 0; 168371d10453SEric Joyner struct ice_prof_redir_section *pr; 168471d10453SEric Joyner struct ice_prof_id_section *pid; 168571d10453SEric Joyner struct ice_xlt1_section *xlt1; 168671d10453SEric Joyner struct ice_xlt2_section *xlt2; 168771d10453SEric Joyner struct ice_sw_fv_section *es; 168871d10453SEric Joyner struct ice_pkg_enum state; 168971d10453SEric Joyner u8 *src, *dst; 169071d10453SEric Joyner void *sect; 169171d10453SEric Joyner 169271d10453SEric Joyner /* if the HW segment pointer is null then the first iteration of 169371d10453SEric Joyner * ice_pkg_enum_section() will fail. In this case the HW tables will 169471d10453SEric Joyner * not be filled and return success. 169571d10453SEric Joyner */ 169671d10453SEric Joyner if (!hw->seg) { 169771d10453SEric Joyner ice_debug(hw, ICE_DBG_PKG, "hw->seg is NULL, tables are not filled\n"); 169871d10453SEric Joyner return; 169971d10453SEric Joyner } 170071d10453SEric Joyner 170171d10453SEric Joyner ice_memset(&state, 0, sizeof(state), ICE_NONDMA_MEM); 170271d10453SEric Joyner 170371d10453SEric Joyner sect = ice_pkg_enum_section(hw->seg, &state, sid); 170471d10453SEric Joyner 170571d10453SEric Joyner while (sect) { 170671d10453SEric Joyner switch (sid) { 170771d10453SEric Joyner case ICE_SID_XLT1_SW: 170871d10453SEric Joyner case ICE_SID_XLT1_FD: 170971d10453SEric Joyner case ICE_SID_XLT1_RSS: 171071d10453SEric Joyner case ICE_SID_XLT1_ACL: 171171d10453SEric Joyner case ICE_SID_XLT1_PE: 171271d10453SEric Joyner xlt1 = (struct ice_xlt1_section *)sect; 171371d10453SEric Joyner src = xlt1->value; 171471d10453SEric Joyner sect_len = LE16_TO_CPU(xlt1->count) * 171571d10453SEric Joyner sizeof(*hw->blk[block_id].xlt1.t); 171671d10453SEric Joyner dst = hw->blk[block_id].xlt1.t; 171771d10453SEric Joyner dst_len = hw->blk[block_id].xlt1.count * 171871d10453SEric Joyner sizeof(*hw->blk[block_id].xlt1.t); 171971d10453SEric Joyner break; 172071d10453SEric Joyner case ICE_SID_XLT2_SW: 172171d10453SEric Joyner case ICE_SID_XLT2_FD: 172271d10453SEric Joyner case ICE_SID_XLT2_RSS: 172371d10453SEric Joyner case ICE_SID_XLT2_ACL: 172471d10453SEric Joyner case ICE_SID_XLT2_PE: 172571d10453SEric Joyner xlt2 = (struct ice_xlt2_section *)sect; 172671d10453SEric Joyner src = (_FORCE_ u8 *)xlt2->value; 172771d10453SEric Joyner sect_len = LE16_TO_CPU(xlt2->count) * 172871d10453SEric Joyner sizeof(*hw->blk[block_id].xlt2.t); 172971d10453SEric Joyner dst = (u8 *)hw->blk[block_id].xlt2.t; 173071d10453SEric Joyner dst_len = hw->blk[block_id].xlt2.count * 173171d10453SEric Joyner sizeof(*hw->blk[block_id].xlt2.t); 173271d10453SEric Joyner break; 173371d10453SEric Joyner case ICE_SID_PROFID_TCAM_SW: 173471d10453SEric Joyner case ICE_SID_PROFID_TCAM_FD: 173571d10453SEric Joyner case ICE_SID_PROFID_TCAM_RSS: 173671d10453SEric Joyner case ICE_SID_PROFID_TCAM_ACL: 173771d10453SEric Joyner case ICE_SID_PROFID_TCAM_PE: 173871d10453SEric Joyner pid = (struct ice_prof_id_section *)sect; 173971d10453SEric Joyner src = (u8 *)pid->entry; 174071d10453SEric Joyner sect_len = LE16_TO_CPU(pid->count) * 174171d10453SEric Joyner sizeof(*hw->blk[block_id].prof.t); 174271d10453SEric Joyner dst = (u8 *)hw->blk[block_id].prof.t; 174371d10453SEric Joyner dst_len = hw->blk[block_id].prof.count * 174471d10453SEric Joyner sizeof(*hw->blk[block_id].prof.t); 174571d10453SEric Joyner break; 174671d10453SEric Joyner case ICE_SID_PROFID_REDIR_SW: 174771d10453SEric Joyner case ICE_SID_PROFID_REDIR_FD: 174871d10453SEric Joyner case ICE_SID_PROFID_REDIR_RSS: 174971d10453SEric Joyner case ICE_SID_PROFID_REDIR_ACL: 175071d10453SEric Joyner case ICE_SID_PROFID_REDIR_PE: 175171d10453SEric Joyner pr = (struct ice_prof_redir_section *)sect; 175271d10453SEric Joyner src = pr->redir_value; 175371d10453SEric Joyner sect_len = LE16_TO_CPU(pr->count) * 175471d10453SEric Joyner sizeof(*hw->blk[block_id].prof_redir.t); 175571d10453SEric Joyner dst = hw->blk[block_id].prof_redir.t; 175671d10453SEric Joyner dst_len = hw->blk[block_id].prof_redir.count * 175771d10453SEric Joyner sizeof(*hw->blk[block_id].prof_redir.t); 175871d10453SEric Joyner break; 175971d10453SEric Joyner case ICE_SID_FLD_VEC_SW: 176071d10453SEric Joyner case ICE_SID_FLD_VEC_FD: 176171d10453SEric Joyner case ICE_SID_FLD_VEC_RSS: 176271d10453SEric Joyner case ICE_SID_FLD_VEC_ACL: 176371d10453SEric Joyner case ICE_SID_FLD_VEC_PE: 176471d10453SEric Joyner es = (struct ice_sw_fv_section *)sect; 176571d10453SEric Joyner src = (u8 *)es->fv; 176671d10453SEric Joyner sect_len = (u32)(LE16_TO_CPU(es->count) * 176771d10453SEric Joyner hw->blk[block_id].es.fvw) * 176871d10453SEric Joyner sizeof(*hw->blk[block_id].es.t); 176971d10453SEric Joyner dst = (u8 *)hw->blk[block_id].es.t; 177071d10453SEric Joyner dst_len = (u32)(hw->blk[block_id].es.count * 177171d10453SEric Joyner hw->blk[block_id].es.fvw) * 177271d10453SEric Joyner sizeof(*hw->blk[block_id].es.t); 177371d10453SEric Joyner break; 177471d10453SEric Joyner default: 177571d10453SEric Joyner return; 177671d10453SEric Joyner } 177771d10453SEric Joyner 177871d10453SEric Joyner /* if the section offset exceeds destination length, terminate 177971d10453SEric Joyner * table fill. 178071d10453SEric Joyner */ 178171d10453SEric Joyner if (offset > dst_len) 178271d10453SEric Joyner return; 178371d10453SEric Joyner 178471d10453SEric Joyner /* if the sum of section size and offset exceed destination size 178571d10453SEric Joyner * then we are out of bounds of the HW table size for that PF. 178671d10453SEric Joyner * Changing section length to fill the remaining table space 178771d10453SEric Joyner * of that PF. 178871d10453SEric Joyner */ 178971d10453SEric Joyner if ((offset + sect_len) > dst_len) 179071d10453SEric Joyner sect_len = dst_len - offset; 179171d10453SEric Joyner 179271d10453SEric Joyner ice_memcpy(dst + offset, src, sect_len, ICE_NONDMA_TO_NONDMA); 179371d10453SEric Joyner offset += sect_len; 179471d10453SEric Joyner sect = ice_pkg_enum_section(NULL, &state, sid); 179571d10453SEric Joyner } 179671d10453SEric Joyner } 179771d10453SEric Joyner 179871d10453SEric Joyner /** 17998923de59SPiotr Kubaj * ice_init_flow_profs - init flow profile locks and list heads 18008923de59SPiotr Kubaj * @hw: pointer to the hardware structure 18018923de59SPiotr Kubaj * @blk_idx: HW block index 18028923de59SPiotr Kubaj */ 18038923de59SPiotr Kubaj static 18048923de59SPiotr Kubaj void ice_init_flow_profs(struct ice_hw *hw, u8 blk_idx) 18058923de59SPiotr Kubaj { 18068923de59SPiotr Kubaj ice_init_lock(&hw->fl_profs_locks[blk_idx]); 18078923de59SPiotr Kubaj INIT_LIST_HEAD(&hw->fl_profs[blk_idx]); 18088923de59SPiotr Kubaj } 18098923de59SPiotr Kubaj 18108923de59SPiotr Kubaj /** 18118923de59SPiotr Kubaj * ice_init_hw_tbls - init hardware table memory 18128923de59SPiotr Kubaj * @hw: pointer to the hardware structure 18138923de59SPiotr Kubaj */ 1814*f2635e84SEric Joyner int ice_init_hw_tbls(struct ice_hw *hw) 18158923de59SPiotr Kubaj { 18168923de59SPiotr Kubaj u8 i; 18178923de59SPiotr Kubaj 18188923de59SPiotr Kubaj ice_init_lock(&hw->rss_locks); 18198923de59SPiotr Kubaj INIT_LIST_HEAD(&hw->rss_list_head); 18208923de59SPiotr Kubaj for (i = 0; i < ICE_BLK_COUNT; i++) { 18218923de59SPiotr Kubaj struct ice_prof_redir *prof_redir = &hw->blk[i].prof_redir; 18228923de59SPiotr Kubaj struct ice_prof_tcam *prof = &hw->blk[i].prof; 18238923de59SPiotr Kubaj struct ice_xlt1 *xlt1 = &hw->blk[i].xlt1; 18248923de59SPiotr Kubaj struct ice_xlt2 *xlt2 = &hw->blk[i].xlt2; 18258923de59SPiotr Kubaj struct ice_es *es = &hw->blk[i].es; 18268923de59SPiotr Kubaj u16 j; 18278923de59SPiotr Kubaj 18288923de59SPiotr Kubaj if (hw->blk[i].is_list_init) 18298923de59SPiotr Kubaj continue; 18308923de59SPiotr Kubaj 18318923de59SPiotr Kubaj ice_init_flow_profs(hw, i); 18328923de59SPiotr Kubaj ice_init_lock(&es->prof_map_lock); 18338923de59SPiotr Kubaj INIT_LIST_HEAD(&es->prof_map); 18348923de59SPiotr Kubaj hw->blk[i].is_list_init = true; 18358923de59SPiotr Kubaj 18368923de59SPiotr Kubaj hw->blk[i].overwrite = blk_sizes[i].overwrite; 18378923de59SPiotr Kubaj es->reverse = blk_sizes[i].reverse; 18388923de59SPiotr Kubaj 18398923de59SPiotr Kubaj xlt1->sid = ice_blk_sids[i][ICE_SID_XLT1_OFF]; 18408923de59SPiotr Kubaj xlt1->count = blk_sizes[i].xlt1; 18418923de59SPiotr Kubaj 18428923de59SPiotr Kubaj xlt1->ptypes = (struct ice_ptg_ptype *) 18438923de59SPiotr Kubaj ice_calloc(hw, xlt1->count, sizeof(*xlt1->ptypes)); 18448923de59SPiotr Kubaj 18458923de59SPiotr Kubaj if (!xlt1->ptypes) 18468923de59SPiotr Kubaj goto err; 18478923de59SPiotr Kubaj 18488923de59SPiotr Kubaj xlt1->ptg_tbl = (struct ice_ptg_entry *) 18498923de59SPiotr Kubaj ice_calloc(hw, ICE_MAX_PTGS, sizeof(*xlt1->ptg_tbl)); 18508923de59SPiotr Kubaj 18518923de59SPiotr Kubaj if (!xlt1->ptg_tbl) 18528923de59SPiotr Kubaj goto err; 18538923de59SPiotr Kubaj 18548923de59SPiotr Kubaj xlt1->t = (u8 *)ice_calloc(hw, xlt1->count, sizeof(*xlt1->t)); 18558923de59SPiotr Kubaj if (!xlt1->t) 18568923de59SPiotr Kubaj goto err; 18578923de59SPiotr Kubaj 18588923de59SPiotr Kubaj xlt2->sid = ice_blk_sids[i][ICE_SID_XLT2_OFF]; 18598923de59SPiotr Kubaj xlt2->count = blk_sizes[i].xlt2; 18608923de59SPiotr Kubaj 18618923de59SPiotr Kubaj xlt2->vsis = (struct ice_vsig_vsi *) 18628923de59SPiotr Kubaj ice_calloc(hw, xlt2->count, sizeof(*xlt2->vsis)); 18638923de59SPiotr Kubaj 18648923de59SPiotr Kubaj if (!xlt2->vsis) 18658923de59SPiotr Kubaj goto err; 18668923de59SPiotr Kubaj 18678923de59SPiotr Kubaj xlt2->vsig_tbl = (struct ice_vsig_entry *) 18688923de59SPiotr Kubaj ice_calloc(hw, xlt2->count, sizeof(*xlt2->vsig_tbl)); 18698923de59SPiotr Kubaj if (!xlt2->vsig_tbl) 18708923de59SPiotr Kubaj goto err; 18718923de59SPiotr Kubaj 18728923de59SPiotr Kubaj for (j = 0; j < xlt2->count; j++) 18738923de59SPiotr Kubaj INIT_LIST_HEAD(&xlt2->vsig_tbl[j].prop_lst); 18748923de59SPiotr Kubaj 18758923de59SPiotr Kubaj xlt2->t = (u16 *)ice_calloc(hw, xlt2->count, sizeof(*xlt2->t)); 18768923de59SPiotr Kubaj if (!xlt2->t) 18778923de59SPiotr Kubaj goto err; 18788923de59SPiotr Kubaj 18798923de59SPiotr Kubaj prof->sid = ice_blk_sids[i][ICE_SID_PR_OFF]; 18808923de59SPiotr Kubaj prof->count = blk_sizes[i].prof_tcam; 18818923de59SPiotr Kubaj prof->max_prof_id = blk_sizes[i].prof_id; 18828923de59SPiotr Kubaj prof->cdid_bits = blk_sizes[i].prof_cdid_bits; 18838923de59SPiotr Kubaj prof->t = (struct ice_prof_tcam_entry *) 18848923de59SPiotr Kubaj ice_calloc(hw, prof->count, sizeof(*prof->t)); 18858923de59SPiotr Kubaj 18868923de59SPiotr Kubaj if (!prof->t) 18878923de59SPiotr Kubaj goto err; 18888923de59SPiotr Kubaj 18898923de59SPiotr Kubaj prof_redir->sid = ice_blk_sids[i][ICE_SID_PR_REDIR_OFF]; 18908923de59SPiotr Kubaj prof_redir->count = blk_sizes[i].prof_redir; 18918923de59SPiotr Kubaj prof_redir->t = (u8 *)ice_calloc(hw, prof_redir->count, 18928923de59SPiotr Kubaj sizeof(*prof_redir->t)); 18938923de59SPiotr Kubaj 18948923de59SPiotr Kubaj if (!prof_redir->t) 18958923de59SPiotr Kubaj goto err; 18968923de59SPiotr Kubaj 18978923de59SPiotr Kubaj es->sid = ice_blk_sids[i][ICE_SID_ES_OFF]; 18988923de59SPiotr Kubaj es->count = blk_sizes[i].es; 18998923de59SPiotr Kubaj es->fvw = blk_sizes[i].fvw; 19008923de59SPiotr Kubaj es->t = (struct ice_fv_word *) 19018923de59SPiotr Kubaj ice_calloc(hw, (u32)(es->count * es->fvw), 19028923de59SPiotr Kubaj sizeof(*es->t)); 19038923de59SPiotr Kubaj if (!es->t) 19048923de59SPiotr Kubaj goto err; 19058923de59SPiotr Kubaj 19068923de59SPiotr Kubaj es->ref_count = (u16 *) 19078923de59SPiotr Kubaj ice_calloc(hw, es->count, sizeof(*es->ref_count)); 19088923de59SPiotr Kubaj 19098923de59SPiotr Kubaj if (!es->ref_count) 19108923de59SPiotr Kubaj goto err; 19118923de59SPiotr Kubaj 19128923de59SPiotr Kubaj es->written = (u8 *) 19138923de59SPiotr Kubaj ice_calloc(hw, es->count, sizeof(*es->written)); 19148923de59SPiotr Kubaj 19158923de59SPiotr Kubaj if (!es->written) 19168923de59SPiotr Kubaj goto err; 19178923de59SPiotr Kubaj 19188923de59SPiotr Kubaj } 1919*f2635e84SEric Joyner return 0; 19208923de59SPiotr Kubaj 19218923de59SPiotr Kubaj err: 19228923de59SPiotr Kubaj ice_free_hw_tbls(hw); 19238923de59SPiotr Kubaj return ICE_ERR_NO_MEMORY; 19248923de59SPiotr Kubaj } 19258923de59SPiotr Kubaj 19268923de59SPiotr Kubaj /** 192771d10453SEric Joyner * ice_fill_blk_tbls - Read package context for tables 192871d10453SEric Joyner * @hw: pointer to the hardware structure 192971d10453SEric Joyner * 193071d10453SEric Joyner * Reads the current package contents and populates the driver 193171d10453SEric Joyner * database with the data iteratively for all advanced feature 193271d10453SEric Joyner * blocks. Assume that the HW tables have been allocated. 193371d10453SEric Joyner */ 193471d10453SEric Joyner void ice_fill_blk_tbls(struct ice_hw *hw) 193571d10453SEric Joyner { 193671d10453SEric Joyner u8 i; 193771d10453SEric Joyner 193871d10453SEric Joyner for (i = 0; i < ICE_BLK_COUNT; i++) { 193971d10453SEric Joyner enum ice_block blk_id = (enum ice_block)i; 194071d10453SEric Joyner 194171d10453SEric Joyner ice_fill_tbl(hw, blk_id, hw->blk[blk_id].xlt1.sid); 194271d10453SEric Joyner ice_fill_tbl(hw, blk_id, hw->blk[blk_id].xlt2.sid); 194371d10453SEric Joyner ice_fill_tbl(hw, blk_id, hw->blk[blk_id].prof.sid); 194471d10453SEric Joyner ice_fill_tbl(hw, blk_id, hw->blk[blk_id].prof_redir.sid); 194571d10453SEric Joyner ice_fill_tbl(hw, blk_id, hw->blk[blk_id].es.sid); 194671d10453SEric Joyner } 194771d10453SEric Joyner 194871d10453SEric Joyner ice_init_sw_db(hw); 194971d10453SEric Joyner } 195071d10453SEric Joyner 195171d10453SEric Joyner /** 195271d10453SEric Joyner * ice_free_prof_map - free profile map 195371d10453SEric Joyner * @hw: pointer to the hardware structure 195471d10453SEric Joyner * @blk_idx: HW block index 195571d10453SEric Joyner */ 195671d10453SEric Joyner static void ice_free_prof_map(struct ice_hw *hw, u8 blk_idx) 195771d10453SEric Joyner { 195871d10453SEric Joyner struct ice_es *es = &hw->blk[blk_idx].es; 195971d10453SEric Joyner struct ice_prof_map *del, *tmp; 196071d10453SEric Joyner 196171d10453SEric Joyner ice_acquire_lock(&es->prof_map_lock); 196271d10453SEric Joyner LIST_FOR_EACH_ENTRY_SAFE(del, tmp, &es->prof_map, 196371d10453SEric Joyner ice_prof_map, list) { 196471d10453SEric Joyner LIST_DEL(&del->list); 196571d10453SEric Joyner ice_free(hw, del); 196671d10453SEric Joyner } 196771d10453SEric Joyner INIT_LIST_HEAD(&es->prof_map); 196871d10453SEric Joyner ice_release_lock(&es->prof_map_lock); 196971d10453SEric Joyner } 197071d10453SEric Joyner 197171d10453SEric Joyner /** 197271d10453SEric Joyner * ice_free_flow_profs - free flow profile entries 197371d10453SEric Joyner * @hw: pointer to the hardware structure 197471d10453SEric Joyner * @blk_idx: HW block index 197571d10453SEric Joyner */ 197671d10453SEric Joyner static void ice_free_flow_profs(struct ice_hw *hw, u8 blk_idx) 197771d10453SEric Joyner { 197871d10453SEric Joyner struct ice_flow_prof *p, *tmp; 197971d10453SEric Joyner 198071d10453SEric Joyner ice_acquire_lock(&hw->fl_profs_locks[blk_idx]); 198171d10453SEric Joyner LIST_FOR_EACH_ENTRY_SAFE(p, tmp, &hw->fl_profs[blk_idx], 198271d10453SEric Joyner ice_flow_prof, l_entry) { 198371d10453SEric Joyner LIST_DEL(&p->l_entry); 19847d7af7f8SEric Joyner 198571d10453SEric Joyner ice_free(hw, p); 198671d10453SEric Joyner } 198771d10453SEric Joyner ice_release_lock(&hw->fl_profs_locks[blk_idx]); 198871d10453SEric Joyner 198971d10453SEric Joyner /* if driver is in reset and tables are being cleared 199071d10453SEric Joyner * re-initialize the flow profile list heads 199171d10453SEric Joyner */ 199271d10453SEric Joyner INIT_LIST_HEAD(&hw->fl_profs[blk_idx]); 199371d10453SEric Joyner } 199471d10453SEric Joyner 199571d10453SEric Joyner /** 199671d10453SEric Joyner * ice_free_vsig_tbl - free complete VSIG table entries 199771d10453SEric Joyner * @hw: pointer to the hardware structure 199871d10453SEric Joyner * @blk: the HW block on which to free the VSIG table entries 199971d10453SEric Joyner */ 200071d10453SEric Joyner static void ice_free_vsig_tbl(struct ice_hw *hw, enum ice_block blk) 200171d10453SEric Joyner { 200271d10453SEric Joyner u16 i; 200371d10453SEric Joyner 200471d10453SEric Joyner if (!hw->blk[blk].xlt2.vsig_tbl) 200571d10453SEric Joyner return; 200671d10453SEric Joyner 200771d10453SEric Joyner for (i = 1; i < ICE_MAX_VSIGS; i++) 200871d10453SEric Joyner if (hw->blk[blk].xlt2.vsig_tbl[i].in_use) 200971d10453SEric Joyner ice_vsig_free(hw, blk, i); 201071d10453SEric Joyner } 201171d10453SEric Joyner 201271d10453SEric Joyner /** 201371d10453SEric Joyner * ice_free_hw_tbls - free hardware table memory 201471d10453SEric Joyner * @hw: pointer to the hardware structure 201571d10453SEric Joyner */ 201671d10453SEric Joyner void ice_free_hw_tbls(struct ice_hw *hw) 201771d10453SEric Joyner { 201871d10453SEric Joyner struct ice_rss_cfg *r, *rt; 201971d10453SEric Joyner u8 i; 202071d10453SEric Joyner 202171d10453SEric Joyner for (i = 0; i < ICE_BLK_COUNT; i++) { 202271d10453SEric Joyner if (hw->blk[i].is_list_init) { 202371d10453SEric Joyner struct ice_es *es = &hw->blk[i].es; 202471d10453SEric Joyner 202571d10453SEric Joyner ice_free_prof_map(hw, i); 202671d10453SEric Joyner ice_destroy_lock(&es->prof_map_lock); 202771d10453SEric Joyner 202871d10453SEric Joyner ice_free_flow_profs(hw, i); 202971d10453SEric Joyner ice_destroy_lock(&hw->fl_profs_locks[i]); 203071d10453SEric Joyner 203171d10453SEric Joyner hw->blk[i].is_list_init = false; 203271d10453SEric Joyner } 203371d10453SEric Joyner ice_free_vsig_tbl(hw, (enum ice_block)i); 203471d10453SEric Joyner ice_free(hw, hw->blk[i].xlt1.ptypes); 203571d10453SEric Joyner ice_free(hw, hw->blk[i].xlt1.ptg_tbl); 203671d10453SEric Joyner ice_free(hw, hw->blk[i].xlt1.t); 203771d10453SEric Joyner ice_free(hw, hw->blk[i].xlt2.t); 203871d10453SEric Joyner ice_free(hw, hw->blk[i].xlt2.vsig_tbl); 203971d10453SEric Joyner ice_free(hw, hw->blk[i].xlt2.vsis); 204071d10453SEric Joyner ice_free(hw, hw->blk[i].prof.t); 204171d10453SEric Joyner ice_free(hw, hw->blk[i].prof_redir.t); 204271d10453SEric Joyner ice_free(hw, hw->blk[i].es.t); 204371d10453SEric Joyner ice_free(hw, hw->blk[i].es.ref_count); 204471d10453SEric Joyner ice_free(hw, hw->blk[i].es.written); 204571d10453SEric Joyner } 204671d10453SEric Joyner 204771d10453SEric Joyner LIST_FOR_EACH_ENTRY_SAFE(r, rt, &hw->rss_list_head, 204871d10453SEric Joyner ice_rss_cfg, l_entry) { 204971d10453SEric Joyner LIST_DEL(&r->l_entry); 205071d10453SEric Joyner ice_free(hw, r); 205171d10453SEric Joyner } 205271d10453SEric Joyner ice_destroy_lock(&hw->rss_locks); 205371d10453SEric Joyner ice_memset(hw->blk, 0, sizeof(hw->blk), ICE_NONDMA_MEM); 205471d10453SEric Joyner } 205571d10453SEric Joyner 205671d10453SEric Joyner /** 205771d10453SEric Joyner * ice_clear_hw_tbls - clear HW tables and flow profiles 205871d10453SEric Joyner * @hw: pointer to the hardware structure 205971d10453SEric Joyner */ 206071d10453SEric Joyner void ice_clear_hw_tbls(struct ice_hw *hw) 206171d10453SEric Joyner { 206271d10453SEric Joyner u8 i; 206371d10453SEric Joyner 206471d10453SEric Joyner for (i = 0; i < ICE_BLK_COUNT; i++) { 206571d10453SEric Joyner struct ice_prof_redir *prof_redir = &hw->blk[i].prof_redir; 206671d10453SEric Joyner struct ice_prof_tcam *prof = &hw->blk[i].prof; 206771d10453SEric Joyner struct ice_xlt1 *xlt1 = &hw->blk[i].xlt1; 206871d10453SEric Joyner struct ice_xlt2 *xlt2 = &hw->blk[i].xlt2; 206971d10453SEric Joyner struct ice_es *es = &hw->blk[i].es; 207071d10453SEric Joyner 207171d10453SEric Joyner if (hw->blk[i].is_list_init) { 207271d10453SEric Joyner ice_free_prof_map(hw, i); 207371d10453SEric Joyner ice_free_flow_profs(hw, i); 207471d10453SEric Joyner } 207571d10453SEric Joyner 207671d10453SEric Joyner ice_free_vsig_tbl(hw, (enum ice_block)i); 207771d10453SEric Joyner 20788923de59SPiotr Kubaj if (xlt1->ptypes) 20798923de59SPiotr Kubaj ice_memset(xlt1->ptypes, 0, 20808923de59SPiotr Kubaj xlt1->count * sizeof(*xlt1->ptypes), 208171d10453SEric Joyner ICE_NONDMA_MEM); 20828923de59SPiotr Kubaj 20838923de59SPiotr Kubaj if (xlt1->ptg_tbl) 208471d10453SEric Joyner ice_memset(xlt1->ptg_tbl, 0, 208571d10453SEric Joyner ICE_MAX_PTGS * sizeof(*xlt1->ptg_tbl), 208671d10453SEric Joyner ICE_NONDMA_MEM); 20878923de59SPiotr Kubaj 20888923de59SPiotr Kubaj if (xlt1->t) 208971d10453SEric Joyner ice_memset(xlt1->t, 0, xlt1->count * sizeof(*xlt1->t), 209071d10453SEric Joyner ICE_NONDMA_MEM); 209171d10453SEric Joyner 20928923de59SPiotr Kubaj if (xlt2->vsis) 20938923de59SPiotr Kubaj ice_memset(xlt2->vsis, 0, 20948923de59SPiotr Kubaj xlt2->count * sizeof(*xlt2->vsis), 209571d10453SEric Joyner ICE_NONDMA_MEM); 20968923de59SPiotr Kubaj 20978923de59SPiotr Kubaj if (xlt2->vsig_tbl) 209871d10453SEric Joyner ice_memset(xlt2->vsig_tbl, 0, 209971d10453SEric Joyner xlt2->count * sizeof(*xlt2->vsig_tbl), 210071d10453SEric Joyner ICE_NONDMA_MEM); 21018923de59SPiotr Kubaj 21028923de59SPiotr Kubaj if (xlt2->t) 210371d10453SEric Joyner ice_memset(xlt2->t, 0, xlt2->count * sizeof(*xlt2->t), 210471d10453SEric Joyner ICE_NONDMA_MEM); 210571d10453SEric Joyner 21068923de59SPiotr Kubaj if (prof->t) 210771d10453SEric Joyner ice_memset(prof->t, 0, prof->count * sizeof(*prof->t), 210871d10453SEric Joyner ICE_NONDMA_MEM); 21098923de59SPiotr Kubaj 21108923de59SPiotr Kubaj if (prof_redir->t) 211171d10453SEric Joyner ice_memset(prof_redir->t, 0, 211271d10453SEric Joyner prof_redir->count * sizeof(*prof_redir->t), 211371d10453SEric Joyner ICE_NONDMA_MEM); 211471d10453SEric Joyner 21158923de59SPiotr Kubaj if (es->t) 21168923de59SPiotr Kubaj ice_memset(es->t, 0, 21178923de59SPiotr Kubaj es->count * sizeof(*es->t) * es->fvw, 211871d10453SEric Joyner ICE_NONDMA_MEM); 21198923de59SPiotr Kubaj 21208923de59SPiotr Kubaj if (es->ref_count) 21218923de59SPiotr Kubaj ice_memset(es->ref_count, 0, 21228923de59SPiotr Kubaj es->count * sizeof(*es->ref_count), 212371d10453SEric Joyner ICE_NONDMA_MEM); 21248923de59SPiotr Kubaj 21258923de59SPiotr Kubaj if (es->written) 21268923de59SPiotr Kubaj ice_memset(es->written, 0, 21278923de59SPiotr Kubaj es->count * sizeof(*es->written), 212871d10453SEric Joyner ICE_NONDMA_MEM); 21297d7af7f8SEric Joyner 213071d10453SEric Joyner } 213171d10453SEric Joyner } 213271d10453SEric Joyner 213371d10453SEric Joyner /** 213471d10453SEric Joyner * ice_prof_gen_key - generate profile ID key 213571d10453SEric Joyner * @hw: pointer to the HW struct 213671d10453SEric Joyner * @blk: the block in which to write profile ID to 213771d10453SEric Joyner * @ptg: packet type group (PTG) portion of key 213871d10453SEric Joyner * @vsig: VSIG portion of key 213971d10453SEric Joyner * @cdid: CDID portion of key 214071d10453SEric Joyner * @flags: flag portion of key 214171d10453SEric Joyner * @vl_msk: valid mask 214271d10453SEric Joyner * @dc_msk: don't care mask 214371d10453SEric Joyner * @nm_msk: never match mask 214471d10453SEric Joyner * @key: output of profile ID key 214571d10453SEric Joyner */ 2146*f2635e84SEric Joyner static int 214771d10453SEric Joyner ice_prof_gen_key(struct ice_hw *hw, enum ice_block blk, u8 ptg, u16 vsig, 214871d10453SEric Joyner u8 cdid, u16 flags, u8 vl_msk[ICE_TCAM_KEY_VAL_SZ], 214971d10453SEric Joyner u8 dc_msk[ICE_TCAM_KEY_VAL_SZ], u8 nm_msk[ICE_TCAM_KEY_VAL_SZ], 215071d10453SEric Joyner u8 key[ICE_TCAM_KEY_SZ]) 215171d10453SEric Joyner { 215271d10453SEric Joyner struct ice_prof_id_key inkey; 215371d10453SEric Joyner 215471d10453SEric Joyner inkey.xlt1 = ptg; 215571d10453SEric Joyner inkey.xlt2_cdid = CPU_TO_LE16(vsig); 215671d10453SEric Joyner inkey.flags = CPU_TO_LE16(flags); 215771d10453SEric Joyner 215871d10453SEric Joyner switch (hw->blk[blk].prof.cdid_bits) { 215971d10453SEric Joyner case 0: 216071d10453SEric Joyner break; 216171d10453SEric Joyner case 2: 216271d10453SEric Joyner #define ICE_CD_2_M 0xC000U 216371d10453SEric Joyner #define ICE_CD_2_S 14 216471d10453SEric Joyner inkey.xlt2_cdid &= ~CPU_TO_LE16(ICE_CD_2_M); 216571d10453SEric Joyner inkey.xlt2_cdid |= CPU_TO_LE16(BIT(cdid) << ICE_CD_2_S); 216671d10453SEric Joyner break; 216771d10453SEric Joyner case 4: 216871d10453SEric Joyner #define ICE_CD_4_M 0xF000U 216971d10453SEric Joyner #define ICE_CD_4_S 12 217071d10453SEric Joyner inkey.xlt2_cdid &= ~CPU_TO_LE16(ICE_CD_4_M); 217171d10453SEric Joyner inkey.xlt2_cdid |= CPU_TO_LE16(BIT(cdid) << ICE_CD_4_S); 217271d10453SEric Joyner break; 217371d10453SEric Joyner case 8: 217471d10453SEric Joyner #define ICE_CD_8_M 0xFF00U 217571d10453SEric Joyner #define ICE_CD_8_S 16 217671d10453SEric Joyner inkey.xlt2_cdid &= ~CPU_TO_LE16(ICE_CD_8_M); 217771d10453SEric Joyner inkey.xlt2_cdid |= CPU_TO_LE16(BIT(cdid) << ICE_CD_8_S); 217871d10453SEric Joyner break; 217971d10453SEric Joyner default: 218071d10453SEric Joyner ice_debug(hw, ICE_DBG_PKG, "Error in profile config\n"); 218171d10453SEric Joyner break; 218271d10453SEric Joyner } 218371d10453SEric Joyner 218471d10453SEric Joyner return ice_set_key(key, ICE_TCAM_KEY_SZ, (u8 *)&inkey, vl_msk, dc_msk, 218571d10453SEric Joyner nm_msk, 0, ICE_TCAM_KEY_SZ / 2); 218671d10453SEric Joyner } 218771d10453SEric Joyner 218871d10453SEric Joyner /** 218971d10453SEric Joyner * ice_tcam_write_entry - write TCAM entry 219071d10453SEric Joyner * @hw: pointer to the HW struct 219171d10453SEric Joyner * @blk: the block in which to write profile ID to 219271d10453SEric Joyner * @idx: the entry index to write to 219371d10453SEric Joyner * @prof_id: profile ID 219471d10453SEric Joyner * @ptg: packet type group (PTG) portion of key 219571d10453SEric Joyner * @vsig: VSIG portion of key 21967d7af7f8SEric Joyner * @cdid: CDID portion of key 219771d10453SEric Joyner * @flags: flag portion of key 219871d10453SEric Joyner * @vl_msk: valid mask 219971d10453SEric Joyner * @dc_msk: don't care mask 220071d10453SEric Joyner * @nm_msk: never match mask 220171d10453SEric Joyner */ 2202*f2635e84SEric Joyner static int 220371d10453SEric Joyner ice_tcam_write_entry(struct ice_hw *hw, enum ice_block blk, u16 idx, 220471d10453SEric Joyner u8 prof_id, u8 ptg, u16 vsig, u8 cdid, u16 flags, 220571d10453SEric Joyner u8 vl_msk[ICE_TCAM_KEY_VAL_SZ], 220671d10453SEric Joyner u8 dc_msk[ICE_TCAM_KEY_VAL_SZ], 220771d10453SEric Joyner u8 nm_msk[ICE_TCAM_KEY_VAL_SZ]) 220871d10453SEric Joyner { 220971d10453SEric Joyner struct ice_prof_tcam_entry; 2210*f2635e84SEric Joyner int status; 221171d10453SEric Joyner 221271d10453SEric Joyner status = ice_prof_gen_key(hw, blk, ptg, vsig, cdid, flags, vl_msk, 221371d10453SEric Joyner dc_msk, nm_msk, hw->blk[blk].prof.t[idx].key); 221471d10453SEric Joyner if (!status) { 221571d10453SEric Joyner hw->blk[blk].prof.t[idx].addr = CPU_TO_LE16(idx); 221671d10453SEric Joyner hw->blk[blk].prof.t[idx].prof_id = prof_id; 221771d10453SEric Joyner } 221871d10453SEric Joyner 221971d10453SEric Joyner return status; 222071d10453SEric Joyner } 222171d10453SEric Joyner 222271d10453SEric Joyner /** 222371d10453SEric Joyner * ice_vsig_get_ref - returns number of VSIs belong to a VSIG 222471d10453SEric Joyner * @hw: pointer to the hardware structure 222571d10453SEric Joyner * @blk: HW block 222671d10453SEric Joyner * @vsig: VSIG to query 222771d10453SEric Joyner * @refs: pointer to variable to receive the reference count 222871d10453SEric Joyner */ 2229*f2635e84SEric Joyner static int 223071d10453SEric Joyner ice_vsig_get_ref(struct ice_hw *hw, enum ice_block blk, u16 vsig, u16 *refs) 223171d10453SEric Joyner { 223271d10453SEric Joyner u16 idx = vsig & ICE_VSIG_IDX_M; 223371d10453SEric Joyner struct ice_vsig_vsi *ptr; 223471d10453SEric Joyner 223571d10453SEric Joyner *refs = 0; 223671d10453SEric Joyner 223771d10453SEric Joyner if (!hw->blk[blk].xlt2.vsig_tbl[idx].in_use) 223871d10453SEric Joyner return ICE_ERR_DOES_NOT_EXIST; 223971d10453SEric Joyner 224071d10453SEric Joyner ptr = hw->blk[blk].xlt2.vsig_tbl[idx].first_vsi; 224171d10453SEric Joyner while (ptr) { 224271d10453SEric Joyner (*refs)++; 224371d10453SEric Joyner ptr = ptr->next_vsi; 224471d10453SEric Joyner } 224571d10453SEric Joyner 2246*f2635e84SEric Joyner return 0; 224771d10453SEric Joyner } 224871d10453SEric Joyner 224971d10453SEric Joyner /** 225071d10453SEric Joyner * ice_has_prof_vsig - check to see if VSIG has a specific profile 225171d10453SEric Joyner * @hw: pointer to the hardware structure 225271d10453SEric Joyner * @blk: HW block 225371d10453SEric Joyner * @vsig: VSIG to check against 225471d10453SEric Joyner * @hdl: profile handle 225571d10453SEric Joyner */ 225671d10453SEric Joyner static bool 225771d10453SEric Joyner ice_has_prof_vsig(struct ice_hw *hw, enum ice_block blk, u16 vsig, u64 hdl) 225871d10453SEric Joyner { 225971d10453SEric Joyner u16 idx = vsig & ICE_VSIG_IDX_M; 226071d10453SEric Joyner struct ice_vsig_prof *ent; 226171d10453SEric Joyner 226271d10453SEric Joyner LIST_FOR_EACH_ENTRY(ent, &hw->blk[blk].xlt2.vsig_tbl[idx].prop_lst, 22637d7af7f8SEric Joyner ice_vsig_prof, list) 226471d10453SEric Joyner if (ent->profile_cookie == hdl) 226571d10453SEric Joyner return true; 226671d10453SEric Joyner 22677d7af7f8SEric Joyner ice_debug(hw, ICE_DBG_INIT, "Characteristic list for VSI group %d not found.\n", 226871d10453SEric Joyner vsig); 226971d10453SEric Joyner return false; 227071d10453SEric Joyner } 227171d10453SEric Joyner 227271d10453SEric Joyner /** 227371d10453SEric Joyner * ice_prof_bld_es - build profile ID extraction sequence changes 227471d10453SEric Joyner * @hw: pointer to the HW struct 227571d10453SEric Joyner * @blk: hardware block 227671d10453SEric Joyner * @bld: the update package buffer build to add to 227771d10453SEric Joyner * @chgs: the list of changes to make in hardware 227871d10453SEric Joyner */ 2279*f2635e84SEric Joyner static int 228071d10453SEric Joyner ice_prof_bld_es(struct ice_hw *hw, enum ice_block blk, 228171d10453SEric Joyner struct ice_buf_build *bld, struct LIST_HEAD_TYPE *chgs) 228271d10453SEric Joyner { 228371d10453SEric Joyner u16 vec_size = hw->blk[blk].es.fvw * sizeof(struct ice_fv_word); 228471d10453SEric Joyner struct ice_chs_chg *tmp; 228571d10453SEric Joyner 22867d7af7f8SEric Joyner LIST_FOR_EACH_ENTRY(tmp, chgs, ice_chs_chg, list_entry) 228771d10453SEric Joyner if (tmp->type == ICE_PTG_ES_ADD && tmp->add_prof) { 228871d10453SEric Joyner u16 off = tmp->prof_id * hw->blk[blk].es.fvw; 228971d10453SEric Joyner struct ice_pkg_es *p; 229071d10453SEric Joyner u32 id; 229171d10453SEric Joyner 229271d10453SEric Joyner id = ice_sect_id(blk, ICE_VEC_TBL); 229371d10453SEric Joyner p = (struct ice_pkg_es *) 22947d7af7f8SEric Joyner ice_pkg_buf_alloc_section(bld, id, 22957d7af7f8SEric Joyner ice_struct_size(p, es, 22967d7af7f8SEric Joyner 1) + 229771d10453SEric Joyner vec_size - 229871d10453SEric Joyner sizeof(p->es[0])); 229971d10453SEric Joyner 230071d10453SEric Joyner if (!p) 230171d10453SEric Joyner return ICE_ERR_MAX_LIMIT; 230271d10453SEric Joyner 230371d10453SEric Joyner p->count = CPU_TO_LE16(1); 230471d10453SEric Joyner p->offset = CPU_TO_LE16(tmp->prof_id); 230571d10453SEric Joyner 230671d10453SEric Joyner ice_memcpy(p->es, &hw->blk[blk].es.t[off], vec_size, 230771d10453SEric Joyner ICE_NONDMA_TO_NONDMA); 230871d10453SEric Joyner } 230971d10453SEric Joyner 2310*f2635e84SEric Joyner return 0; 231171d10453SEric Joyner } 231271d10453SEric Joyner 231371d10453SEric Joyner /** 231471d10453SEric Joyner * ice_prof_bld_tcam - build profile ID TCAM changes 231571d10453SEric Joyner * @hw: pointer to the HW struct 231671d10453SEric Joyner * @blk: hardware block 231771d10453SEric Joyner * @bld: the update package buffer build to add to 231871d10453SEric Joyner * @chgs: the list of changes to make in hardware 231971d10453SEric Joyner */ 2320*f2635e84SEric Joyner static int 232171d10453SEric Joyner ice_prof_bld_tcam(struct ice_hw *hw, enum ice_block blk, 232271d10453SEric Joyner struct ice_buf_build *bld, struct LIST_HEAD_TYPE *chgs) 232371d10453SEric Joyner { 232471d10453SEric Joyner struct ice_chs_chg *tmp; 232571d10453SEric Joyner 23267d7af7f8SEric Joyner LIST_FOR_EACH_ENTRY(tmp, chgs, ice_chs_chg, list_entry) 232771d10453SEric Joyner if (tmp->type == ICE_TCAM_ADD && tmp->add_tcam_idx) { 232871d10453SEric Joyner struct ice_prof_id_section *p; 232971d10453SEric Joyner u32 id; 233071d10453SEric Joyner 233171d10453SEric Joyner id = ice_sect_id(blk, ICE_PROF_TCAM); 233271d10453SEric Joyner p = (struct ice_prof_id_section *) 23337d7af7f8SEric Joyner ice_pkg_buf_alloc_section(bld, id, 23347d7af7f8SEric Joyner ice_struct_size(p, 23357d7af7f8SEric Joyner entry, 23367d7af7f8SEric Joyner 1)); 233771d10453SEric Joyner 233871d10453SEric Joyner if (!p) 233971d10453SEric Joyner return ICE_ERR_MAX_LIMIT; 234071d10453SEric Joyner 234171d10453SEric Joyner p->count = CPU_TO_LE16(1); 234271d10453SEric Joyner p->entry[0].addr = CPU_TO_LE16(tmp->tcam_idx); 234371d10453SEric Joyner p->entry[0].prof_id = tmp->prof_id; 234471d10453SEric Joyner 234571d10453SEric Joyner ice_memcpy(p->entry[0].key, 234671d10453SEric Joyner &hw->blk[blk].prof.t[tmp->tcam_idx].key, 234771d10453SEric Joyner sizeof(hw->blk[blk].prof.t->key), 234871d10453SEric Joyner ICE_NONDMA_TO_NONDMA); 234971d10453SEric Joyner } 235071d10453SEric Joyner 2351*f2635e84SEric Joyner return 0; 235271d10453SEric Joyner } 235371d10453SEric Joyner 235471d10453SEric Joyner /** 235571d10453SEric Joyner * ice_prof_bld_xlt1 - build XLT1 changes 235671d10453SEric Joyner * @blk: hardware block 235771d10453SEric Joyner * @bld: the update package buffer build to add to 235871d10453SEric Joyner * @chgs: the list of changes to make in hardware 235971d10453SEric Joyner */ 2360*f2635e84SEric Joyner static int 236171d10453SEric Joyner ice_prof_bld_xlt1(enum ice_block blk, struct ice_buf_build *bld, 236271d10453SEric Joyner struct LIST_HEAD_TYPE *chgs) 236371d10453SEric Joyner { 236471d10453SEric Joyner struct ice_chs_chg *tmp; 236571d10453SEric Joyner 23667d7af7f8SEric Joyner LIST_FOR_EACH_ENTRY(tmp, chgs, ice_chs_chg, list_entry) 236771d10453SEric Joyner if (tmp->type == ICE_PTG_ES_ADD && tmp->add_ptg) { 236871d10453SEric Joyner struct ice_xlt1_section *p; 236971d10453SEric Joyner u32 id; 237071d10453SEric Joyner 237171d10453SEric Joyner id = ice_sect_id(blk, ICE_XLT1); 237271d10453SEric Joyner p = (struct ice_xlt1_section *) 23737d7af7f8SEric Joyner ice_pkg_buf_alloc_section(bld, id, 23747d7af7f8SEric Joyner ice_struct_size(p, 23757d7af7f8SEric Joyner value, 23767d7af7f8SEric Joyner 1)); 237771d10453SEric Joyner 237871d10453SEric Joyner if (!p) 237971d10453SEric Joyner return ICE_ERR_MAX_LIMIT; 238071d10453SEric Joyner 238171d10453SEric Joyner p->count = CPU_TO_LE16(1); 238271d10453SEric Joyner p->offset = CPU_TO_LE16(tmp->ptype); 238371d10453SEric Joyner p->value[0] = tmp->ptg; 238471d10453SEric Joyner } 238571d10453SEric Joyner 2386*f2635e84SEric Joyner return 0; 238771d10453SEric Joyner } 238871d10453SEric Joyner 238971d10453SEric Joyner /** 239071d10453SEric Joyner * ice_prof_bld_xlt2 - build XLT2 changes 239171d10453SEric Joyner * @blk: hardware block 239271d10453SEric Joyner * @bld: the update package buffer build to add to 239371d10453SEric Joyner * @chgs: the list of changes to make in hardware 239471d10453SEric Joyner */ 2395*f2635e84SEric Joyner static int 239671d10453SEric Joyner ice_prof_bld_xlt2(enum ice_block blk, struct ice_buf_build *bld, 239771d10453SEric Joyner struct LIST_HEAD_TYPE *chgs) 239871d10453SEric Joyner { 239971d10453SEric Joyner struct ice_chs_chg *tmp; 240071d10453SEric Joyner 240171d10453SEric Joyner LIST_FOR_EACH_ENTRY(tmp, chgs, ice_chs_chg, list_entry) { 240271d10453SEric Joyner struct ice_xlt2_section *p; 240371d10453SEric Joyner u32 id; 240471d10453SEric Joyner 240571d10453SEric Joyner switch (tmp->type) { 240671d10453SEric Joyner case ICE_VSIG_ADD: 240771d10453SEric Joyner case ICE_VSI_MOVE: 240871d10453SEric Joyner case ICE_VSIG_REM: 240971d10453SEric Joyner id = ice_sect_id(blk, ICE_XLT2); 241071d10453SEric Joyner p = (struct ice_xlt2_section *) 24117d7af7f8SEric Joyner ice_pkg_buf_alloc_section(bld, id, 24127d7af7f8SEric Joyner ice_struct_size(p, 24137d7af7f8SEric Joyner value, 24147d7af7f8SEric Joyner 1)); 241571d10453SEric Joyner 241671d10453SEric Joyner if (!p) 241771d10453SEric Joyner return ICE_ERR_MAX_LIMIT; 241871d10453SEric Joyner 241971d10453SEric Joyner p->count = CPU_TO_LE16(1); 242071d10453SEric Joyner p->offset = CPU_TO_LE16(tmp->vsi); 242171d10453SEric Joyner p->value[0] = CPU_TO_LE16(tmp->vsig); 242271d10453SEric Joyner break; 242371d10453SEric Joyner default: 242471d10453SEric Joyner break; 242571d10453SEric Joyner } 242671d10453SEric Joyner } 242771d10453SEric Joyner 2428*f2635e84SEric Joyner return 0; 242971d10453SEric Joyner } 243071d10453SEric Joyner 243171d10453SEric Joyner /** 243271d10453SEric Joyner * ice_upd_prof_hw - update hardware using the change list 243371d10453SEric Joyner * @hw: pointer to the HW struct 243471d10453SEric Joyner * @blk: hardware block 243571d10453SEric Joyner * @chgs: the list of changes to make in hardware 243671d10453SEric Joyner */ 2437*f2635e84SEric Joyner static int 243871d10453SEric Joyner ice_upd_prof_hw(struct ice_hw *hw, enum ice_block blk, 243971d10453SEric Joyner struct LIST_HEAD_TYPE *chgs) 244071d10453SEric Joyner { 244171d10453SEric Joyner struct ice_buf_build *b; 244271d10453SEric Joyner struct ice_chs_chg *tmp; 244371d10453SEric Joyner u16 pkg_sects; 244471d10453SEric Joyner u16 xlt1 = 0; 244571d10453SEric Joyner u16 xlt2 = 0; 244671d10453SEric Joyner u16 tcam = 0; 244771d10453SEric Joyner u16 es = 0; 2448*f2635e84SEric Joyner int status; 244971d10453SEric Joyner u16 sects; 245071d10453SEric Joyner 245171d10453SEric Joyner /* count number of sections we need */ 245271d10453SEric Joyner LIST_FOR_EACH_ENTRY(tmp, chgs, ice_chs_chg, list_entry) { 245371d10453SEric Joyner switch (tmp->type) { 245471d10453SEric Joyner case ICE_PTG_ES_ADD: 245571d10453SEric Joyner if (tmp->add_ptg) 245671d10453SEric Joyner xlt1++; 245771d10453SEric Joyner if (tmp->add_prof) 245871d10453SEric Joyner es++; 245971d10453SEric Joyner break; 246071d10453SEric Joyner case ICE_TCAM_ADD: 246171d10453SEric Joyner tcam++; 246271d10453SEric Joyner break; 246371d10453SEric Joyner case ICE_VSIG_ADD: 246471d10453SEric Joyner case ICE_VSI_MOVE: 246571d10453SEric Joyner case ICE_VSIG_REM: 246671d10453SEric Joyner xlt2++; 246771d10453SEric Joyner break; 246871d10453SEric Joyner default: 246971d10453SEric Joyner break; 247071d10453SEric Joyner } 247171d10453SEric Joyner } 247271d10453SEric Joyner sects = xlt1 + xlt2 + tcam + es; 247371d10453SEric Joyner 247471d10453SEric Joyner if (!sects) 2475*f2635e84SEric Joyner return 0; 247671d10453SEric Joyner 247771d10453SEric Joyner /* Build update package buffer */ 247871d10453SEric Joyner b = ice_pkg_buf_alloc(hw); 247971d10453SEric Joyner if (!b) 248071d10453SEric Joyner return ICE_ERR_NO_MEMORY; 248171d10453SEric Joyner 248271d10453SEric Joyner status = ice_pkg_buf_reserve_section(b, sects); 248371d10453SEric Joyner if (status) 248471d10453SEric Joyner goto error_tmp; 248571d10453SEric Joyner 248671d10453SEric Joyner /* Preserve order of table update: ES, TCAM, PTG, VSIG */ 248771d10453SEric Joyner if (es) { 248871d10453SEric Joyner status = ice_prof_bld_es(hw, blk, b, chgs); 248971d10453SEric Joyner if (status) 249071d10453SEric Joyner goto error_tmp; 249171d10453SEric Joyner } 249271d10453SEric Joyner 249371d10453SEric Joyner if (tcam) { 249471d10453SEric Joyner status = ice_prof_bld_tcam(hw, blk, b, chgs); 249571d10453SEric Joyner if (status) 249671d10453SEric Joyner goto error_tmp; 249771d10453SEric Joyner } 249871d10453SEric Joyner 249971d10453SEric Joyner if (xlt1) { 250071d10453SEric Joyner status = ice_prof_bld_xlt1(blk, b, chgs); 250171d10453SEric Joyner if (status) 250271d10453SEric Joyner goto error_tmp; 250371d10453SEric Joyner } 250471d10453SEric Joyner 250571d10453SEric Joyner if (xlt2) { 250671d10453SEric Joyner status = ice_prof_bld_xlt2(blk, b, chgs); 250771d10453SEric Joyner if (status) 250871d10453SEric Joyner goto error_tmp; 250971d10453SEric Joyner } 251071d10453SEric Joyner 251171d10453SEric Joyner /* After package buffer build check if the section count in buffer is 251271d10453SEric Joyner * non-zero and matches the number of sections detected for package 251371d10453SEric Joyner * update. 251471d10453SEric Joyner */ 251571d10453SEric Joyner pkg_sects = ice_pkg_buf_get_active_sections(b); 251671d10453SEric Joyner if (!pkg_sects || pkg_sects != sects) { 251771d10453SEric Joyner status = ICE_ERR_INVAL_SIZE; 251871d10453SEric Joyner goto error_tmp; 251971d10453SEric Joyner } 252071d10453SEric Joyner 252171d10453SEric Joyner /* update package */ 252271d10453SEric Joyner status = ice_update_pkg(hw, ice_pkg_buf(b), 1); 252371d10453SEric Joyner if (status == ICE_ERR_AQ_ERROR) 252471d10453SEric Joyner ice_debug(hw, ICE_DBG_INIT, "Unable to update HW profile\n"); 252571d10453SEric Joyner 252671d10453SEric Joyner error_tmp: 252771d10453SEric Joyner ice_pkg_buf_free(hw, b); 252871d10453SEric Joyner return status; 252971d10453SEric Joyner } 253071d10453SEric Joyner 253171d10453SEric Joyner /** 253271d10453SEric Joyner * ice_add_prof - add profile 253371d10453SEric Joyner * @hw: pointer to the HW struct 253471d10453SEric Joyner * @blk: hardware block 253571d10453SEric Joyner * @id: profile tracking ID 25368923de59SPiotr Kubaj * @ptypes: bitmap indicating ptypes (ICE_FLOW_PTYPE_MAX bits) 253771d10453SEric Joyner * @es: extraction sequence (length of array is determined by the block) 253871d10453SEric Joyner * 253971d10453SEric Joyner * This function registers a profile, which matches a set of PTGs with a 254071d10453SEric Joyner * particular extraction sequence. While the hardware profile is allocated 254171d10453SEric Joyner * it will not be written until the first call to ice_add_flow that specifies 254271d10453SEric Joyner * the ID value used here. 254371d10453SEric Joyner */ 2544*f2635e84SEric Joyner int 25458923de59SPiotr Kubaj ice_add_prof(struct ice_hw *hw, enum ice_block blk, u64 id, 25468923de59SPiotr Kubaj ice_bitmap_t *ptypes, struct ice_fv_word *es) 254771d10453SEric Joyner { 254871d10453SEric Joyner ice_declare_bitmap(ptgs_used, ICE_XLT1_CNT); 254971d10453SEric Joyner struct ice_prof_map *prof; 2550*f2635e84SEric Joyner int status; 255171d10453SEric Joyner u8 prof_id; 25528923de59SPiotr Kubaj u16 ptype; 255371d10453SEric Joyner 255471d10453SEric Joyner ice_zero_bitmap(ptgs_used, ICE_XLT1_CNT); 255571d10453SEric Joyner 255671d10453SEric Joyner ice_acquire_lock(&hw->blk[blk].es.prof_map_lock); 255771d10453SEric Joyner 255871d10453SEric Joyner /* search for existing profile */ 255971d10453SEric Joyner status = ice_find_prof_id(hw, blk, es, &prof_id); 256071d10453SEric Joyner if (status) { 256171d10453SEric Joyner /* allocate profile ID */ 256271d10453SEric Joyner status = ice_alloc_prof_id(hw, blk, &prof_id); 256371d10453SEric Joyner if (status) 256471d10453SEric Joyner goto err_ice_add_prof; 256571d10453SEric Joyner 256671d10453SEric Joyner /* and write new es */ 256771d10453SEric Joyner ice_write_es(hw, blk, prof_id, es); 256871d10453SEric Joyner } 256971d10453SEric Joyner 257071d10453SEric Joyner ice_prof_inc_ref(hw, blk, prof_id); 257171d10453SEric Joyner 257271d10453SEric Joyner /* add profile info */ 257371d10453SEric Joyner 257471d10453SEric Joyner prof = (struct ice_prof_map *)ice_malloc(hw, sizeof(*prof)); 257571d10453SEric Joyner if (!prof) 257671d10453SEric Joyner goto err_ice_add_prof; 257771d10453SEric Joyner 257871d10453SEric Joyner prof->profile_cookie = id; 257971d10453SEric Joyner prof->prof_id = prof_id; 258071d10453SEric Joyner prof->ptg_cnt = 0; 258171d10453SEric Joyner prof->context = 0; 258271d10453SEric Joyner 258371d10453SEric Joyner /* build list of ptgs */ 25848923de59SPiotr Kubaj ice_for_each_set_bit(ptype, ptypes, ICE_FLOW_PTYPE_MAX) { 258571d10453SEric Joyner u8 ptg; 258671d10453SEric Joyner 25877d7af7f8SEric Joyner /* The package should place all ptypes in a non-zero 25887d7af7f8SEric Joyner * PTG, so the following call should never fail. 258971d10453SEric Joyner */ 259071d10453SEric Joyner if (ice_ptg_find_ptype(hw, blk, ptype, &ptg)) 259171d10453SEric Joyner continue; 259271d10453SEric Joyner 259371d10453SEric Joyner /* If PTG is already added, skip and continue */ 259471d10453SEric Joyner if (ice_is_bit_set(ptgs_used, ptg)) 259571d10453SEric Joyner continue; 259671d10453SEric Joyner 259771d10453SEric Joyner ice_set_bit(ptg, ptgs_used); 259871d10453SEric Joyner prof->ptg[prof->ptg_cnt] = ptg; 259971d10453SEric Joyner 260071d10453SEric Joyner if (++prof->ptg_cnt >= ICE_MAX_PTG_PER_PROFILE) 260171d10453SEric Joyner break; 260271d10453SEric Joyner } 260371d10453SEric Joyner 260471d10453SEric Joyner LIST_ADD(&prof->list, &hw->blk[blk].es.prof_map); 2605*f2635e84SEric Joyner status = 0; 260671d10453SEric Joyner 260771d10453SEric Joyner err_ice_add_prof: 260871d10453SEric Joyner ice_release_lock(&hw->blk[blk].es.prof_map_lock); 260971d10453SEric Joyner return status; 261071d10453SEric Joyner } 261171d10453SEric Joyner 261271d10453SEric Joyner /** 261371d10453SEric Joyner * ice_search_prof_id - Search for a profile tracking ID 261471d10453SEric Joyner * @hw: pointer to the HW struct 261571d10453SEric Joyner * @blk: hardware block 261671d10453SEric Joyner * @id: profile tracking ID 261771d10453SEric Joyner * 261871d10453SEric Joyner * This will search for a profile tracking ID which was previously added. 26197d7af7f8SEric Joyner * The profile map lock should be held before calling this function. 262071d10453SEric Joyner */ 262171d10453SEric Joyner struct ice_prof_map * 262271d10453SEric Joyner ice_search_prof_id(struct ice_hw *hw, enum ice_block blk, u64 id) 262371d10453SEric Joyner { 26247d7af7f8SEric Joyner struct ice_prof_map *entry = NULL; 26257d7af7f8SEric Joyner struct ice_prof_map *map; 262671d10453SEric Joyner 26277d7af7f8SEric Joyner LIST_FOR_EACH_ENTRY(map, &hw->blk[blk].es.prof_map, ice_prof_map, list) 26287d7af7f8SEric Joyner if (map->profile_cookie == id) { 26297d7af7f8SEric Joyner entry = map; 26307d7af7f8SEric Joyner break; 26317d7af7f8SEric Joyner } 263271d10453SEric Joyner 263371d10453SEric Joyner return entry; 263471d10453SEric Joyner } 263571d10453SEric Joyner 263671d10453SEric Joyner /** 263771d10453SEric Joyner * ice_set_prof_context - Set context for a given profile 263871d10453SEric Joyner * @hw: pointer to the HW struct 263971d10453SEric Joyner * @blk: hardware block 264071d10453SEric Joyner * @id: profile tracking ID 264171d10453SEric Joyner * @cntxt: context 264271d10453SEric Joyner */ 2643*f2635e84SEric Joyner int 264471d10453SEric Joyner ice_set_prof_context(struct ice_hw *hw, enum ice_block blk, u64 id, u64 cntxt) 264571d10453SEric Joyner { 264671d10453SEric Joyner struct ice_prof_map *entry; 2647*f2635e84SEric Joyner int status = ICE_ERR_DOES_NOT_EXIST; 264871d10453SEric Joyner 26497d7af7f8SEric Joyner ice_acquire_lock(&hw->blk[blk].es.prof_map_lock); 265071d10453SEric Joyner entry = ice_search_prof_id(hw, blk, id); 26517d7af7f8SEric Joyner if (entry) { 265271d10453SEric Joyner entry->context = cntxt; 2653*f2635e84SEric Joyner status = 0; 26547d7af7f8SEric Joyner } 26557d7af7f8SEric Joyner ice_release_lock(&hw->blk[blk].es.prof_map_lock); 26567d7af7f8SEric Joyner return status; 265771d10453SEric Joyner } 265871d10453SEric Joyner 265971d10453SEric Joyner /** 266071d10453SEric Joyner * ice_get_prof_context - Get context for a given profile 266171d10453SEric Joyner * @hw: pointer to the HW struct 266271d10453SEric Joyner * @blk: hardware block 266371d10453SEric Joyner * @id: profile tracking ID 266471d10453SEric Joyner * @cntxt: pointer to variable to receive the context 266571d10453SEric Joyner */ 2666*f2635e84SEric Joyner int 266771d10453SEric Joyner ice_get_prof_context(struct ice_hw *hw, enum ice_block blk, u64 id, u64 *cntxt) 266871d10453SEric Joyner { 266971d10453SEric Joyner struct ice_prof_map *entry; 2670*f2635e84SEric Joyner int status = ICE_ERR_DOES_NOT_EXIST; 267171d10453SEric Joyner 26727d7af7f8SEric Joyner ice_acquire_lock(&hw->blk[blk].es.prof_map_lock); 267371d10453SEric Joyner entry = ice_search_prof_id(hw, blk, id); 26747d7af7f8SEric Joyner if (entry) { 267571d10453SEric Joyner *cntxt = entry->context; 2676*f2635e84SEric Joyner status = 0; 26777d7af7f8SEric Joyner } 26787d7af7f8SEric Joyner ice_release_lock(&hw->blk[blk].es.prof_map_lock); 26797d7af7f8SEric Joyner return status; 268071d10453SEric Joyner } 268171d10453SEric Joyner 268271d10453SEric Joyner /** 268371d10453SEric Joyner * ice_vsig_prof_id_count - count profiles in a VSIG 268471d10453SEric Joyner * @hw: pointer to the HW struct 268571d10453SEric Joyner * @blk: hardware block 268671d10453SEric Joyner * @vsig: VSIG to remove the profile from 268771d10453SEric Joyner */ 268871d10453SEric Joyner static u16 268971d10453SEric Joyner ice_vsig_prof_id_count(struct ice_hw *hw, enum ice_block blk, u16 vsig) 269071d10453SEric Joyner { 269171d10453SEric Joyner u16 idx = vsig & ICE_VSIG_IDX_M, count = 0; 269271d10453SEric Joyner struct ice_vsig_prof *p; 269371d10453SEric Joyner 269471d10453SEric Joyner LIST_FOR_EACH_ENTRY(p, &hw->blk[blk].xlt2.vsig_tbl[idx].prop_lst, 26957d7af7f8SEric Joyner ice_vsig_prof, list) 269671d10453SEric Joyner count++; 269771d10453SEric Joyner 269871d10453SEric Joyner return count; 269971d10453SEric Joyner } 270071d10453SEric Joyner 270171d10453SEric Joyner /** 270271d10453SEric Joyner * ice_rel_tcam_idx - release a TCAM index 270371d10453SEric Joyner * @hw: pointer to the HW struct 270471d10453SEric Joyner * @blk: hardware block 270571d10453SEric Joyner * @idx: the index to release 270671d10453SEric Joyner */ 2707*f2635e84SEric Joyner static int 270871d10453SEric Joyner ice_rel_tcam_idx(struct ice_hw *hw, enum ice_block blk, u16 idx) 270971d10453SEric Joyner { 271071d10453SEric Joyner /* Masks to invoke a never match entry */ 271171d10453SEric Joyner u8 vl_msk[ICE_TCAM_KEY_VAL_SZ] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; 271271d10453SEric Joyner u8 dc_msk[ICE_TCAM_KEY_VAL_SZ] = { 0xFE, 0xFF, 0xFF, 0xFF, 0xFF }; 271371d10453SEric Joyner u8 nm_msk[ICE_TCAM_KEY_VAL_SZ] = { 0x01, 0x00, 0x00, 0x00, 0x00 }; 2714*f2635e84SEric Joyner int status; 271571d10453SEric Joyner 271671d10453SEric Joyner /* write the TCAM entry */ 271771d10453SEric Joyner status = ice_tcam_write_entry(hw, blk, idx, 0, 0, 0, 0, 0, vl_msk, 271871d10453SEric Joyner dc_msk, nm_msk); 271971d10453SEric Joyner if (status) 272071d10453SEric Joyner return status; 272171d10453SEric Joyner 272271d10453SEric Joyner /* release the TCAM entry */ 272371d10453SEric Joyner status = ice_free_tcam_ent(hw, blk, idx); 272471d10453SEric Joyner 272571d10453SEric Joyner return status; 272671d10453SEric Joyner } 272771d10453SEric Joyner 272871d10453SEric Joyner /** 272971d10453SEric Joyner * ice_rem_prof_id - remove one profile from a VSIG 273071d10453SEric Joyner * @hw: pointer to the HW struct 273171d10453SEric Joyner * @blk: hardware block 273271d10453SEric Joyner * @prof: pointer to profile structure to remove 273371d10453SEric Joyner */ 2734*f2635e84SEric Joyner static int 273571d10453SEric Joyner ice_rem_prof_id(struct ice_hw *hw, enum ice_block blk, 273671d10453SEric Joyner struct ice_vsig_prof *prof) 273771d10453SEric Joyner { 2738*f2635e84SEric Joyner int status; 273971d10453SEric Joyner u16 i; 274071d10453SEric Joyner 27417d7af7f8SEric Joyner for (i = 0; i < prof->tcam_count; i++) 274271d10453SEric Joyner if (prof->tcam[i].in_use) { 274371d10453SEric Joyner prof->tcam[i].in_use = false; 274471d10453SEric Joyner status = ice_rel_tcam_idx(hw, blk, 274571d10453SEric Joyner prof->tcam[i].tcam_idx); 274671d10453SEric Joyner if (status) 274771d10453SEric Joyner return ICE_ERR_HW_TABLE; 274871d10453SEric Joyner } 274971d10453SEric Joyner 2750*f2635e84SEric Joyner return 0; 275171d10453SEric Joyner } 275271d10453SEric Joyner 275371d10453SEric Joyner /** 275471d10453SEric Joyner * ice_rem_vsig - remove VSIG 275571d10453SEric Joyner * @hw: pointer to the HW struct 275671d10453SEric Joyner * @blk: hardware block 275771d10453SEric Joyner * @vsig: the VSIG to remove 275871d10453SEric Joyner * @chg: the change list 275971d10453SEric Joyner */ 2760*f2635e84SEric Joyner static int 276171d10453SEric Joyner ice_rem_vsig(struct ice_hw *hw, enum ice_block blk, u16 vsig, 276271d10453SEric Joyner struct LIST_HEAD_TYPE *chg) 276371d10453SEric Joyner { 276471d10453SEric Joyner u16 idx = vsig & ICE_VSIG_IDX_M; 276571d10453SEric Joyner struct ice_vsig_vsi *vsi_cur; 276671d10453SEric Joyner struct ice_vsig_prof *d, *t; 276771d10453SEric Joyner 276871d10453SEric Joyner /* remove TCAM entries */ 276971d10453SEric Joyner LIST_FOR_EACH_ENTRY_SAFE(d, t, 277071d10453SEric Joyner &hw->blk[blk].xlt2.vsig_tbl[idx].prop_lst, 277171d10453SEric Joyner ice_vsig_prof, list) { 2772*f2635e84SEric Joyner int status; 27738923de59SPiotr Kubaj 277471d10453SEric Joyner status = ice_rem_prof_id(hw, blk, d); 277571d10453SEric Joyner if (status) 277671d10453SEric Joyner return status; 277771d10453SEric Joyner 277871d10453SEric Joyner LIST_DEL(&d->list); 277971d10453SEric Joyner ice_free(hw, d); 278071d10453SEric Joyner } 278171d10453SEric Joyner 278271d10453SEric Joyner /* Move all VSIS associated with this VSIG to the default VSIG */ 278371d10453SEric Joyner vsi_cur = hw->blk[blk].xlt2.vsig_tbl[idx].first_vsi; 278471d10453SEric Joyner /* If the VSIG has at least 1 VSI then iterate through the list 278571d10453SEric Joyner * and remove the VSIs before deleting the group. 278671d10453SEric Joyner */ 27877d7af7f8SEric Joyner if (vsi_cur) 278871d10453SEric Joyner do { 278971d10453SEric Joyner struct ice_vsig_vsi *tmp = vsi_cur->next_vsi; 279071d10453SEric Joyner struct ice_chs_chg *p; 279171d10453SEric Joyner 279271d10453SEric Joyner p = (struct ice_chs_chg *)ice_malloc(hw, sizeof(*p)); 279371d10453SEric Joyner if (!p) 279471d10453SEric Joyner return ICE_ERR_NO_MEMORY; 279571d10453SEric Joyner 279671d10453SEric Joyner p->type = ICE_VSIG_REM; 279771d10453SEric Joyner p->orig_vsig = vsig; 279871d10453SEric Joyner p->vsig = ICE_DEFAULT_VSIG; 27998923de59SPiotr Kubaj p->vsi = (u16)(vsi_cur - hw->blk[blk].xlt2.vsis); 280071d10453SEric Joyner 280171d10453SEric Joyner LIST_ADD(&p->list_entry, chg); 280271d10453SEric Joyner 280371d10453SEric Joyner vsi_cur = tmp; 280471d10453SEric Joyner } while (vsi_cur); 280571d10453SEric Joyner 280671d10453SEric Joyner return ice_vsig_free(hw, blk, vsig); 280771d10453SEric Joyner } 280871d10453SEric Joyner 280971d10453SEric Joyner /** 281071d10453SEric Joyner * ice_rem_prof_id_vsig - remove a specific profile from a VSIG 281171d10453SEric Joyner * @hw: pointer to the HW struct 281271d10453SEric Joyner * @blk: hardware block 281371d10453SEric Joyner * @vsig: VSIG to remove the profile from 281471d10453SEric Joyner * @hdl: profile handle indicating which profile to remove 281571d10453SEric Joyner * @chg: list to receive a record of changes 281671d10453SEric Joyner */ 2817*f2635e84SEric Joyner static int 281871d10453SEric Joyner ice_rem_prof_id_vsig(struct ice_hw *hw, enum ice_block blk, u16 vsig, u64 hdl, 281971d10453SEric Joyner struct LIST_HEAD_TYPE *chg) 282071d10453SEric Joyner { 282171d10453SEric Joyner u16 idx = vsig & ICE_VSIG_IDX_M; 282271d10453SEric Joyner struct ice_vsig_prof *p, *t; 282371d10453SEric Joyner 282471d10453SEric Joyner LIST_FOR_EACH_ENTRY_SAFE(p, t, 282571d10453SEric Joyner &hw->blk[blk].xlt2.vsig_tbl[idx].prop_lst, 28267d7af7f8SEric Joyner ice_vsig_prof, list) 282771d10453SEric Joyner if (p->profile_cookie == hdl) { 2828*f2635e84SEric Joyner int status; 28298923de59SPiotr Kubaj 283071d10453SEric Joyner if (ice_vsig_prof_id_count(hw, blk, vsig) == 1) 283171d10453SEric Joyner /* this is the last profile, remove the VSIG */ 283271d10453SEric Joyner return ice_rem_vsig(hw, blk, vsig, chg); 283371d10453SEric Joyner 283471d10453SEric Joyner status = ice_rem_prof_id(hw, blk, p); 283571d10453SEric Joyner if (!status) { 283671d10453SEric Joyner LIST_DEL(&p->list); 283771d10453SEric Joyner ice_free(hw, p); 283871d10453SEric Joyner } 283971d10453SEric Joyner return status; 284071d10453SEric Joyner } 284171d10453SEric Joyner 284271d10453SEric Joyner return ICE_ERR_DOES_NOT_EXIST; 284371d10453SEric Joyner } 284471d10453SEric Joyner 284571d10453SEric Joyner /** 284671d10453SEric Joyner * ice_rem_flow_all - remove all flows with a particular profile 284771d10453SEric Joyner * @hw: pointer to the HW struct 284871d10453SEric Joyner * @blk: hardware block 284971d10453SEric Joyner * @id: profile tracking ID 285071d10453SEric Joyner */ 2851*f2635e84SEric Joyner static int 285271d10453SEric Joyner ice_rem_flow_all(struct ice_hw *hw, enum ice_block blk, u64 id) 285371d10453SEric Joyner { 285471d10453SEric Joyner struct ice_chs_chg *del, *tmp; 28557d7af7f8SEric Joyner struct LIST_HEAD_TYPE chg; 2856*f2635e84SEric Joyner int status; 285771d10453SEric Joyner u16 i; 285871d10453SEric Joyner 285971d10453SEric Joyner INIT_LIST_HEAD(&chg); 286071d10453SEric Joyner 28617d7af7f8SEric Joyner for (i = 1; i < ICE_MAX_VSIGS; i++) 286271d10453SEric Joyner if (hw->blk[blk].xlt2.vsig_tbl[i].in_use) { 286371d10453SEric Joyner if (ice_has_prof_vsig(hw, blk, i, id)) { 286471d10453SEric Joyner status = ice_rem_prof_id_vsig(hw, blk, i, id, 286571d10453SEric Joyner &chg); 286671d10453SEric Joyner if (status) 286771d10453SEric Joyner goto err_ice_rem_flow_all; 286871d10453SEric Joyner } 286971d10453SEric Joyner } 287071d10453SEric Joyner 287171d10453SEric Joyner status = ice_upd_prof_hw(hw, blk, &chg); 287271d10453SEric Joyner 287371d10453SEric Joyner err_ice_rem_flow_all: 287471d10453SEric Joyner LIST_FOR_EACH_ENTRY_SAFE(del, tmp, &chg, ice_chs_chg, list_entry) { 287571d10453SEric Joyner LIST_DEL(&del->list_entry); 287671d10453SEric Joyner ice_free(hw, del); 287771d10453SEric Joyner } 287871d10453SEric Joyner 287971d10453SEric Joyner return status; 288071d10453SEric Joyner } 288171d10453SEric Joyner 288271d10453SEric Joyner /** 288371d10453SEric Joyner * ice_rem_prof - remove profile 288471d10453SEric Joyner * @hw: pointer to the HW struct 288571d10453SEric Joyner * @blk: hardware block 288671d10453SEric Joyner * @id: profile tracking ID 288771d10453SEric Joyner * 288871d10453SEric Joyner * This will remove the profile specified by the ID parameter, which was 288971d10453SEric Joyner * previously created through ice_add_prof. If any existing entries 289071d10453SEric Joyner * are associated with this profile, they will be removed as well. 289171d10453SEric Joyner */ 2892*f2635e84SEric Joyner int ice_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 id) 289371d10453SEric Joyner { 289471d10453SEric Joyner struct ice_prof_map *pmap; 2895*f2635e84SEric Joyner int status; 289671d10453SEric Joyner 289771d10453SEric Joyner ice_acquire_lock(&hw->blk[blk].es.prof_map_lock); 289871d10453SEric Joyner 28997d7af7f8SEric Joyner pmap = ice_search_prof_id(hw, blk, id); 290071d10453SEric Joyner if (!pmap) { 290171d10453SEric Joyner status = ICE_ERR_DOES_NOT_EXIST; 290271d10453SEric Joyner goto err_ice_rem_prof; 290371d10453SEric Joyner } 290471d10453SEric Joyner 290571d10453SEric Joyner /* remove all flows with this profile */ 290671d10453SEric Joyner status = ice_rem_flow_all(hw, blk, pmap->profile_cookie); 290771d10453SEric Joyner if (status) 290871d10453SEric Joyner goto err_ice_rem_prof; 290971d10453SEric Joyner 291071d10453SEric Joyner /* dereference profile, and possibly remove */ 291171d10453SEric Joyner ice_prof_dec_ref(hw, blk, pmap->prof_id); 291271d10453SEric Joyner 291371d10453SEric Joyner LIST_DEL(&pmap->list); 291471d10453SEric Joyner ice_free(hw, pmap); 291571d10453SEric Joyner 291671d10453SEric Joyner err_ice_rem_prof: 291771d10453SEric Joyner ice_release_lock(&hw->blk[blk].es.prof_map_lock); 291871d10453SEric Joyner return status; 291971d10453SEric Joyner } 292071d10453SEric Joyner 292171d10453SEric Joyner /** 292271d10453SEric Joyner * ice_get_prof - get profile 292371d10453SEric Joyner * @hw: pointer to the HW struct 292471d10453SEric Joyner * @blk: hardware block 292571d10453SEric Joyner * @hdl: profile handle 292671d10453SEric Joyner * @chg: change list 292771d10453SEric Joyner */ 2928*f2635e84SEric Joyner static int 292971d10453SEric Joyner ice_get_prof(struct ice_hw *hw, enum ice_block blk, u64 hdl, 293071d10453SEric Joyner struct LIST_HEAD_TYPE *chg) 293171d10453SEric Joyner { 293271d10453SEric Joyner struct ice_prof_map *map; 293371d10453SEric Joyner struct ice_chs_chg *p; 2934*f2635e84SEric Joyner int status = 0; 293571d10453SEric Joyner u16 i; 293671d10453SEric Joyner 29377d7af7f8SEric Joyner ice_acquire_lock(&hw->blk[blk].es.prof_map_lock); 293871d10453SEric Joyner /* Get the details on the profile specified by the handle ID */ 293971d10453SEric Joyner map = ice_search_prof_id(hw, blk, hdl); 29407d7af7f8SEric Joyner if (!map) { 29417d7af7f8SEric Joyner status = ICE_ERR_DOES_NOT_EXIST; 29427d7af7f8SEric Joyner goto err_ice_get_prof; 29437d7af7f8SEric Joyner } 294471d10453SEric Joyner 29457d7af7f8SEric Joyner for (i = 0; i < map->ptg_cnt; i++) 294671d10453SEric Joyner if (!hw->blk[blk].es.written[map->prof_id]) { 294771d10453SEric Joyner /* add ES to change list */ 294871d10453SEric Joyner p = (struct ice_chs_chg *)ice_malloc(hw, sizeof(*p)); 29497d7af7f8SEric Joyner if (!p) { 29507d7af7f8SEric Joyner status = ICE_ERR_NO_MEMORY; 295171d10453SEric Joyner goto err_ice_get_prof; 29527d7af7f8SEric Joyner } 295371d10453SEric Joyner 295471d10453SEric Joyner p->type = ICE_PTG_ES_ADD; 295571d10453SEric Joyner p->ptype = 0; 295671d10453SEric Joyner p->ptg = map->ptg[i]; 295771d10453SEric Joyner p->add_ptg = 0; 295871d10453SEric Joyner 295971d10453SEric Joyner p->add_prof = 1; 296071d10453SEric Joyner p->prof_id = map->prof_id; 296171d10453SEric Joyner 296271d10453SEric Joyner hw->blk[blk].es.written[map->prof_id] = true; 296371d10453SEric Joyner 296471d10453SEric Joyner LIST_ADD(&p->list_entry, chg); 296571d10453SEric Joyner } 296671d10453SEric Joyner 296771d10453SEric Joyner err_ice_get_prof: 29687d7af7f8SEric Joyner ice_release_lock(&hw->blk[blk].es.prof_map_lock); 296971d10453SEric Joyner /* let caller clean up the change list */ 29707d7af7f8SEric Joyner return status; 297171d10453SEric Joyner } 297271d10453SEric Joyner 297371d10453SEric Joyner /** 297471d10453SEric Joyner * ice_get_profs_vsig - get a copy of the list of profiles from a VSIG 297571d10453SEric Joyner * @hw: pointer to the HW struct 297671d10453SEric Joyner * @blk: hardware block 297771d10453SEric Joyner * @vsig: VSIG from which to copy the list 297871d10453SEric Joyner * @lst: output list 297971d10453SEric Joyner * 298071d10453SEric Joyner * This routine makes a copy of the list of profiles in the specified VSIG. 298171d10453SEric Joyner */ 2982*f2635e84SEric Joyner static int 298371d10453SEric Joyner ice_get_profs_vsig(struct ice_hw *hw, enum ice_block blk, u16 vsig, 298471d10453SEric Joyner struct LIST_HEAD_TYPE *lst) 298571d10453SEric Joyner { 298671d10453SEric Joyner struct ice_vsig_prof *ent1, *ent2; 298771d10453SEric Joyner u16 idx = vsig & ICE_VSIG_IDX_M; 298871d10453SEric Joyner 298971d10453SEric Joyner LIST_FOR_EACH_ENTRY(ent1, &hw->blk[blk].xlt2.vsig_tbl[idx].prop_lst, 299071d10453SEric Joyner ice_vsig_prof, list) { 299171d10453SEric Joyner struct ice_vsig_prof *p; 299271d10453SEric Joyner 299371d10453SEric Joyner /* copy to the input list */ 299471d10453SEric Joyner p = (struct ice_vsig_prof *)ice_memdup(hw, ent1, sizeof(*p), 299571d10453SEric Joyner ICE_NONDMA_TO_NONDMA); 299671d10453SEric Joyner if (!p) 299771d10453SEric Joyner goto err_ice_get_profs_vsig; 299871d10453SEric Joyner 299971d10453SEric Joyner LIST_ADD_TAIL(&p->list, lst); 300071d10453SEric Joyner } 300171d10453SEric Joyner 3002*f2635e84SEric Joyner return 0; 300371d10453SEric Joyner 300471d10453SEric Joyner err_ice_get_profs_vsig: 300571d10453SEric Joyner LIST_FOR_EACH_ENTRY_SAFE(ent1, ent2, lst, ice_vsig_prof, list) { 300671d10453SEric Joyner LIST_DEL(&ent1->list); 300771d10453SEric Joyner ice_free(hw, ent1); 300871d10453SEric Joyner } 300971d10453SEric Joyner 301071d10453SEric Joyner return ICE_ERR_NO_MEMORY; 301171d10453SEric Joyner } 301271d10453SEric Joyner 301371d10453SEric Joyner /** 301471d10453SEric Joyner * ice_add_prof_to_lst - add profile entry to a list 301571d10453SEric Joyner * @hw: pointer to the HW struct 301671d10453SEric Joyner * @blk: hardware block 301771d10453SEric Joyner * @lst: the list to be added to 301871d10453SEric Joyner * @hdl: profile handle of entry to add 301971d10453SEric Joyner */ 3020*f2635e84SEric Joyner static int 302171d10453SEric Joyner ice_add_prof_to_lst(struct ice_hw *hw, enum ice_block blk, 302271d10453SEric Joyner struct LIST_HEAD_TYPE *lst, u64 hdl) 302371d10453SEric Joyner { 302471d10453SEric Joyner struct ice_prof_map *map; 302571d10453SEric Joyner struct ice_vsig_prof *p; 3026*f2635e84SEric Joyner int status = 0; 302771d10453SEric Joyner u16 i; 302871d10453SEric Joyner 30297d7af7f8SEric Joyner ice_acquire_lock(&hw->blk[blk].es.prof_map_lock); 303071d10453SEric Joyner map = ice_search_prof_id(hw, blk, hdl); 30317d7af7f8SEric Joyner if (!map) { 30327d7af7f8SEric Joyner status = ICE_ERR_DOES_NOT_EXIST; 30337d7af7f8SEric Joyner goto err_ice_add_prof_to_lst; 30347d7af7f8SEric Joyner } 303571d10453SEric Joyner 303671d10453SEric Joyner p = (struct ice_vsig_prof *)ice_malloc(hw, sizeof(*p)); 30377d7af7f8SEric Joyner if (!p) { 30387d7af7f8SEric Joyner status = ICE_ERR_NO_MEMORY; 30397d7af7f8SEric Joyner goto err_ice_add_prof_to_lst; 30407d7af7f8SEric Joyner } 304171d10453SEric Joyner 304271d10453SEric Joyner p->profile_cookie = map->profile_cookie; 304371d10453SEric Joyner p->prof_id = map->prof_id; 304471d10453SEric Joyner p->tcam_count = map->ptg_cnt; 304571d10453SEric Joyner 304671d10453SEric Joyner for (i = 0; i < map->ptg_cnt; i++) { 304771d10453SEric Joyner p->tcam[i].prof_id = map->prof_id; 304871d10453SEric Joyner p->tcam[i].tcam_idx = ICE_INVALID_TCAM; 304971d10453SEric Joyner p->tcam[i].ptg = map->ptg[i]; 305071d10453SEric Joyner } 305171d10453SEric Joyner 305271d10453SEric Joyner LIST_ADD(&p->list, lst); 305371d10453SEric Joyner 30547d7af7f8SEric Joyner err_ice_add_prof_to_lst: 30557d7af7f8SEric Joyner ice_release_lock(&hw->blk[blk].es.prof_map_lock); 30567d7af7f8SEric Joyner return status; 305771d10453SEric Joyner } 305871d10453SEric Joyner 305971d10453SEric Joyner /** 306071d10453SEric Joyner * ice_move_vsi - move VSI to another VSIG 306171d10453SEric Joyner * @hw: pointer to the HW struct 306271d10453SEric Joyner * @blk: hardware block 306371d10453SEric Joyner * @vsi: the VSI to move 306471d10453SEric Joyner * @vsig: the VSIG to move the VSI to 306571d10453SEric Joyner * @chg: the change list 306671d10453SEric Joyner */ 3067*f2635e84SEric Joyner static int 306871d10453SEric Joyner ice_move_vsi(struct ice_hw *hw, enum ice_block blk, u16 vsi, u16 vsig, 306971d10453SEric Joyner struct LIST_HEAD_TYPE *chg) 307071d10453SEric Joyner { 307171d10453SEric Joyner struct ice_chs_chg *p; 307271d10453SEric Joyner u16 orig_vsig; 3073*f2635e84SEric Joyner int status; 307471d10453SEric Joyner 307571d10453SEric Joyner p = (struct ice_chs_chg *)ice_malloc(hw, sizeof(*p)); 307671d10453SEric Joyner if (!p) 307771d10453SEric Joyner return ICE_ERR_NO_MEMORY; 307871d10453SEric Joyner 307971d10453SEric Joyner status = ice_vsig_find_vsi(hw, blk, vsi, &orig_vsig); 308071d10453SEric Joyner if (!status) 308171d10453SEric Joyner status = ice_vsig_add_mv_vsi(hw, blk, vsi, vsig); 308271d10453SEric Joyner 308371d10453SEric Joyner if (status) { 308471d10453SEric Joyner ice_free(hw, p); 308571d10453SEric Joyner return status; 308671d10453SEric Joyner } 308771d10453SEric Joyner 308871d10453SEric Joyner p->type = ICE_VSI_MOVE; 308971d10453SEric Joyner p->vsi = vsi; 309071d10453SEric Joyner p->orig_vsig = orig_vsig; 309171d10453SEric Joyner p->vsig = vsig; 309271d10453SEric Joyner 309371d10453SEric Joyner LIST_ADD(&p->list_entry, chg); 309471d10453SEric Joyner 3095*f2635e84SEric Joyner return 0; 309671d10453SEric Joyner } 309771d10453SEric Joyner 309871d10453SEric Joyner /** 309971d10453SEric Joyner * ice_rem_chg_tcam_ent - remove a specific TCAM entry from change list 310071d10453SEric Joyner * @hw: pointer to the HW struct 310171d10453SEric Joyner * @idx: the index of the TCAM entry to remove 310271d10453SEric Joyner * @chg: the list of change structures to search 310371d10453SEric Joyner */ 310471d10453SEric Joyner static void 310571d10453SEric Joyner ice_rem_chg_tcam_ent(struct ice_hw *hw, u16 idx, struct LIST_HEAD_TYPE *chg) 310671d10453SEric Joyner { 310771d10453SEric Joyner struct ice_chs_chg *pos, *tmp; 310871d10453SEric Joyner 31097d7af7f8SEric Joyner LIST_FOR_EACH_ENTRY_SAFE(tmp, pos, chg, ice_chs_chg, list_entry) 311071d10453SEric Joyner if (tmp->type == ICE_TCAM_ADD && tmp->tcam_idx == idx) { 311171d10453SEric Joyner LIST_DEL(&tmp->list_entry); 311271d10453SEric Joyner ice_free(hw, tmp); 311371d10453SEric Joyner } 311471d10453SEric Joyner } 311571d10453SEric Joyner 311671d10453SEric Joyner /** 311771d10453SEric Joyner * ice_prof_tcam_ena_dis - add enable or disable TCAM change 311871d10453SEric Joyner * @hw: pointer to the HW struct 311971d10453SEric Joyner * @blk: hardware block 312071d10453SEric Joyner * @enable: true to enable, false to disable 312171d10453SEric Joyner * @vsig: the VSIG of the TCAM entry 312271d10453SEric Joyner * @tcam: pointer the TCAM info structure of the TCAM to disable 312371d10453SEric Joyner * @chg: the change list 312471d10453SEric Joyner * 312571d10453SEric Joyner * This function appends an enable or disable TCAM entry in the change log 312671d10453SEric Joyner */ 3127*f2635e84SEric Joyner static int 312871d10453SEric Joyner ice_prof_tcam_ena_dis(struct ice_hw *hw, enum ice_block blk, bool enable, 312971d10453SEric Joyner u16 vsig, struct ice_tcam_inf *tcam, 313071d10453SEric Joyner struct LIST_HEAD_TYPE *chg) 313171d10453SEric Joyner { 313271d10453SEric Joyner struct ice_chs_chg *p; 3133*f2635e84SEric Joyner int status; 313471d10453SEric Joyner 313571d10453SEric Joyner u8 vl_msk[ICE_TCAM_KEY_VAL_SZ] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; 313671d10453SEric Joyner u8 dc_msk[ICE_TCAM_KEY_VAL_SZ] = { 0xFF, 0xFF, 0x00, 0x00, 0x00 }; 313771d10453SEric Joyner u8 nm_msk[ICE_TCAM_KEY_VAL_SZ] = { 0x00, 0x00, 0x00, 0x00, 0x00 }; 313871d10453SEric Joyner 313971d10453SEric Joyner /* if disabling, free the TCAM */ 314071d10453SEric Joyner if (!enable) { 314171d10453SEric Joyner status = ice_rel_tcam_idx(hw, blk, tcam->tcam_idx); 314271d10453SEric Joyner 314371d10453SEric Joyner /* if we have already created a change for this TCAM entry, then 314471d10453SEric Joyner * we need to remove that entry, in order to prevent writing to 314571d10453SEric Joyner * a TCAM entry we no longer will have ownership of. 314671d10453SEric Joyner */ 314771d10453SEric Joyner ice_rem_chg_tcam_ent(hw, tcam->tcam_idx, chg); 314871d10453SEric Joyner tcam->tcam_idx = 0; 314971d10453SEric Joyner tcam->in_use = 0; 315071d10453SEric Joyner return status; 315171d10453SEric Joyner } 315271d10453SEric Joyner 315371d10453SEric Joyner /* for re-enabling, reallocate a TCAM */ 31547d7af7f8SEric Joyner status = ice_alloc_tcam_ent(hw, blk, true, &tcam->tcam_idx); 315571d10453SEric Joyner if (status) 315671d10453SEric Joyner return status; 315771d10453SEric Joyner 315871d10453SEric Joyner /* add TCAM to change list */ 315971d10453SEric Joyner p = (struct ice_chs_chg *)ice_malloc(hw, sizeof(*p)); 316071d10453SEric Joyner if (!p) 316171d10453SEric Joyner return ICE_ERR_NO_MEMORY; 316271d10453SEric Joyner 316371d10453SEric Joyner status = ice_tcam_write_entry(hw, blk, tcam->tcam_idx, tcam->prof_id, 316471d10453SEric Joyner tcam->ptg, vsig, 0, 0, vl_msk, dc_msk, 316571d10453SEric Joyner nm_msk); 316671d10453SEric Joyner if (status) 316771d10453SEric Joyner goto err_ice_prof_tcam_ena_dis; 316871d10453SEric Joyner 316971d10453SEric Joyner tcam->in_use = 1; 317071d10453SEric Joyner 317171d10453SEric Joyner p->type = ICE_TCAM_ADD; 317271d10453SEric Joyner p->add_tcam_idx = true; 317371d10453SEric Joyner p->prof_id = tcam->prof_id; 317471d10453SEric Joyner p->ptg = tcam->ptg; 317571d10453SEric Joyner p->vsig = 0; 317671d10453SEric Joyner p->tcam_idx = tcam->tcam_idx; 317771d10453SEric Joyner 317871d10453SEric Joyner /* log change */ 317971d10453SEric Joyner LIST_ADD(&p->list_entry, chg); 318071d10453SEric Joyner 3181*f2635e84SEric Joyner return 0; 318271d10453SEric Joyner 318371d10453SEric Joyner err_ice_prof_tcam_ena_dis: 318471d10453SEric Joyner ice_free(hw, p); 318571d10453SEric Joyner return status; 318671d10453SEric Joyner } 318771d10453SEric Joyner 318871d10453SEric Joyner /** 318971d10453SEric Joyner * ice_adj_prof_priorities - adjust profile based on priorities 319071d10453SEric Joyner * @hw: pointer to the HW struct 319171d10453SEric Joyner * @blk: hardware block 319271d10453SEric Joyner * @vsig: the VSIG for which to adjust profile priorities 319371d10453SEric Joyner * @chg: the change list 319471d10453SEric Joyner */ 3195*f2635e84SEric Joyner static int 319671d10453SEric Joyner ice_adj_prof_priorities(struct ice_hw *hw, enum ice_block blk, u16 vsig, 319771d10453SEric Joyner struct LIST_HEAD_TYPE *chg) 319871d10453SEric Joyner { 319971d10453SEric Joyner ice_declare_bitmap(ptgs_used, ICE_XLT1_CNT); 320071d10453SEric Joyner struct ice_vsig_prof *t; 3201*f2635e84SEric Joyner int status = 0; 320271d10453SEric Joyner u16 idx; 320371d10453SEric Joyner 320471d10453SEric Joyner ice_zero_bitmap(ptgs_used, ICE_XLT1_CNT); 320571d10453SEric Joyner idx = vsig & ICE_VSIG_IDX_M; 320671d10453SEric Joyner 320771d10453SEric Joyner /* Priority is based on the order in which the profiles are added. The 320871d10453SEric Joyner * newest added profile has highest priority and the oldest added 320971d10453SEric Joyner * profile has the lowest priority. Since the profile property list for 321071d10453SEric Joyner * a VSIG is sorted from newest to oldest, this code traverses the list 321171d10453SEric Joyner * in order and enables the first of each PTG that it finds (that is not 321271d10453SEric Joyner * already enabled); it also disables any duplicate PTGs that it finds 321371d10453SEric Joyner * in the older profiles (that are currently enabled). 321471d10453SEric Joyner */ 321571d10453SEric Joyner 321671d10453SEric Joyner LIST_FOR_EACH_ENTRY(t, &hw->blk[blk].xlt2.vsig_tbl[idx].prop_lst, 321771d10453SEric Joyner ice_vsig_prof, list) { 321871d10453SEric Joyner u16 i; 321971d10453SEric Joyner 322071d10453SEric Joyner for (i = 0; i < t->tcam_count; i++) { 322171d10453SEric Joyner bool used; 322271d10453SEric Joyner 322371d10453SEric Joyner /* Scan the priorities from newest to oldest. 322471d10453SEric Joyner * Make sure that the newest profiles take priority. 322571d10453SEric Joyner */ 322671d10453SEric Joyner used = ice_is_bit_set(ptgs_used, t->tcam[i].ptg); 322771d10453SEric Joyner 322871d10453SEric Joyner if (used && t->tcam[i].in_use) { 322971d10453SEric Joyner /* need to mark this PTG as never match, as it 323071d10453SEric Joyner * was already in use and therefore duplicate 323171d10453SEric Joyner * (and lower priority) 323271d10453SEric Joyner */ 323371d10453SEric Joyner status = ice_prof_tcam_ena_dis(hw, blk, false, 323471d10453SEric Joyner vsig, 323571d10453SEric Joyner &t->tcam[i], 323671d10453SEric Joyner chg); 323771d10453SEric Joyner if (status) 323871d10453SEric Joyner return status; 323971d10453SEric Joyner } else if (!used && !t->tcam[i].in_use) { 324071d10453SEric Joyner /* need to enable this PTG, as it in not in use 324171d10453SEric Joyner * and not enabled (highest priority) 324271d10453SEric Joyner */ 324371d10453SEric Joyner status = ice_prof_tcam_ena_dis(hw, blk, true, 324471d10453SEric Joyner vsig, 324571d10453SEric Joyner &t->tcam[i], 324671d10453SEric Joyner chg); 324771d10453SEric Joyner if (status) 324871d10453SEric Joyner return status; 324971d10453SEric Joyner } 325071d10453SEric Joyner 325171d10453SEric Joyner /* keep track of used ptgs */ 325271d10453SEric Joyner ice_set_bit(t->tcam[i].ptg, ptgs_used); 325371d10453SEric Joyner } 325471d10453SEric Joyner } 325571d10453SEric Joyner 325671d10453SEric Joyner return status; 325771d10453SEric Joyner } 325871d10453SEric Joyner 325971d10453SEric Joyner /** 326071d10453SEric Joyner * ice_add_prof_id_vsig - add profile to VSIG 326171d10453SEric Joyner * @hw: pointer to the HW struct 326271d10453SEric Joyner * @blk: hardware block 326371d10453SEric Joyner * @vsig: the VSIG to which this profile is to be added 326471d10453SEric Joyner * @hdl: the profile handle indicating the profile to add 326571d10453SEric Joyner * @rev: true to add entries to the end of the list 326671d10453SEric Joyner * @chg: the change list 326771d10453SEric Joyner */ 3268*f2635e84SEric Joyner static int 326971d10453SEric Joyner ice_add_prof_id_vsig(struct ice_hw *hw, enum ice_block blk, u16 vsig, u64 hdl, 327071d10453SEric Joyner bool rev, struct LIST_HEAD_TYPE *chg) 327171d10453SEric Joyner { 327271d10453SEric Joyner /* Masks that ignore flags */ 327371d10453SEric Joyner u8 vl_msk[ICE_TCAM_KEY_VAL_SZ] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; 327471d10453SEric Joyner u8 dc_msk[ICE_TCAM_KEY_VAL_SZ] = { 0xFF, 0xFF, 0x00, 0x00, 0x00 }; 327571d10453SEric Joyner u8 nm_msk[ICE_TCAM_KEY_VAL_SZ] = { 0x00, 0x00, 0x00, 0x00, 0x00 }; 327671d10453SEric Joyner struct ice_prof_map *map; 327771d10453SEric Joyner struct ice_vsig_prof *t; 327871d10453SEric Joyner struct ice_chs_chg *p; 327971d10453SEric Joyner u16 vsig_idx, i; 3280*f2635e84SEric Joyner int status = 0; 328171d10453SEric Joyner 328271d10453SEric Joyner /* Error, if this VSIG already has this profile */ 328371d10453SEric Joyner if (ice_has_prof_vsig(hw, blk, vsig, hdl)) 328471d10453SEric Joyner return ICE_ERR_ALREADY_EXISTS; 328571d10453SEric Joyner 328671d10453SEric Joyner /* new VSIG profile structure */ 328771d10453SEric Joyner t = (struct ice_vsig_prof *)ice_malloc(hw, sizeof(*t)); 328871d10453SEric Joyner if (!t) 328971d10453SEric Joyner return ICE_ERR_NO_MEMORY; 329071d10453SEric Joyner 32917d7af7f8SEric Joyner ice_acquire_lock(&hw->blk[blk].es.prof_map_lock); 32927d7af7f8SEric Joyner /* Get the details on the profile specified by the handle ID */ 32937d7af7f8SEric Joyner map = ice_search_prof_id(hw, blk, hdl); 32947d7af7f8SEric Joyner if (!map) { 32957d7af7f8SEric Joyner status = ICE_ERR_DOES_NOT_EXIST; 32967d7af7f8SEric Joyner goto err_ice_add_prof_id_vsig; 32977d7af7f8SEric Joyner } 32987d7af7f8SEric Joyner 329971d10453SEric Joyner t->profile_cookie = map->profile_cookie; 330071d10453SEric Joyner t->prof_id = map->prof_id; 330171d10453SEric Joyner t->tcam_count = map->ptg_cnt; 330271d10453SEric Joyner 330371d10453SEric Joyner /* create TCAM entries */ 330471d10453SEric Joyner for (i = 0; i < map->ptg_cnt; i++) { 330571d10453SEric Joyner u16 tcam_idx; 330671d10453SEric Joyner 330771d10453SEric Joyner /* add TCAM to change list */ 330871d10453SEric Joyner p = (struct ice_chs_chg *)ice_malloc(hw, sizeof(*p)); 33097d7af7f8SEric Joyner if (!p) { 33107d7af7f8SEric Joyner status = ICE_ERR_NO_MEMORY; 331171d10453SEric Joyner goto err_ice_add_prof_id_vsig; 33127d7af7f8SEric Joyner } 331371d10453SEric Joyner 331471d10453SEric Joyner /* allocate the TCAM entry index */ 33157d7af7f8SEric Joyner status = ice_alloc_tcam_ent(hw, blk, true, &tcam_idx); 331671d10453SEric Joyner if (status) { 331771d10453SEric Joyner ice_free(hw, p); 331871d10453SEric Joyner goto err_ice_add_prof_id_vsig; 331971d10453SEric Joyner } 332071d10453SEric Joyner 332171d10453SEric Joyner t->tcam[i].ptg = map->ptg[i]; 332271d10453SEric Joyner t->tcam[i].prof_id = map->prof_id; 332371d10453SEric Joyner t->tcam[i].tcam_idx = tcam_idx; 332471d10453SEric Joyner t->tcam[i].in_use = true; 332571d10453SEric Joyner 332671d10453SEric Joyner p->type = ICE_TCAM_ADD; 332771d10453SEric Joyner p->add_tcam_idx = true; 332871d10453SEric Joyner p->prof_id = t->tcam[i].prof_id; 332971d10453SEric Joyner p->ptg = t->tcam[i].ptg; 333071d10453SEric Joyner p->vsig = vsig; 333171d10453SEric Joyner p->tcam_idx = t->tcam[i].tcam_idx; 333271d10453SEric Joyner 333371d10453SEric Joyner /* write the TCAM entry */ 333471d10453SEric Joyner status = ice_tcam_write_entry(hw, blk, t->tcam[i].tcam_idx, 333571d10453SEric Joyner t->tcam[i].prof_id, 333671d10453SEric Joyner t->tcam[i].ptg, vsig, 0, 0, 333771d10453SEric Joyner vl_msk, dc_msk, nm_msk); 333871d10453SEric Joyner if (status) { 333971d10453SEric Joyner ice_free(hw, p); 334071d10453SEric Joyner goto err_ice_add_prof_id_vsig; 334171d10453SEric Joyner } 334271d10453SEric Joyner 334371d10453SEric Joyner /* log change */ 334471d10453SEric Joyner LIST_ADD(&p->list_entry, chg); 334571d10453SEric Joyner } 334671d10453SEric Joyner 334771d10453SEric Joyner /* add profile to VSIG */ 334871d10453SEric Joyner vsig_idx = vsig & ICE_VSIG_IDX_M; 334971d10453SEric Joyner if (rev) 335071d10453SEric Joyner LIST_ADD_TAIL(&t->list, 335171d10453SEric Joyner &hw->blk[blk].xlt2.vsig_tbl[vsig_idx].prop_lst); 335271d10453SEric Joyner else 335371d10453SEric Joyner LIST_ADD(&t->list, 335471d10453SEric Joyner &hw->blk[blk].xlt2.vsig_tbl[vsig_idx].prop_lst); 335571d10453SEric Joyner 33567d7af7f8SEric Joyner ice_release_lock(&hw->blk[blk].es.prof_map_lock); 33577d7af7f8SEric Joyner return status; 335871d10453SEric Joyner 335971d10453SEric Joyner err_ice_add_prof_id_vsig: 33607d7af7f8SEric Joyner ice_release_lock(&hw->blk[blk].es.prof_map_lock); 336171d10453SEric Joyner /* let caller clean up the change list */ 336271d10453SEric Joyner ice_free(hw, t); 33637d7af7f8SEric Joyner return status; 336471d10453SEric Joyner } 336571d10453SEric Joyner 336671d10453SEric Joyner /** 336771d10453SEric Joyner * ice_create_prof_id_vsig - add a new VSIG with a single profile 336871d10453SEric Joyner * @hw: pointer to the HW struct 336971d10453SEric Joyner * @blk: hardware block 337071d10453SEric Joyner * @vsi: the initial VSI that will be in VSIG 337171d10453SEric Joyner * @hdl: the profile handle of the profile that will be added to the VSIG 337271d10453SEric Joyner * @chg: the change list 337371d10453SEric Joyner */ 3374*f2635e84SEric Joyner static int 337571d10453SEric Joyner ice_create_prof_id_vsig(struct ice_hw *hw, enum ice_block blk, u16 vsi, u64 hdl, 337671d10453SEric Joyner struct LIST_HEAD_TYPE *chg) 337771d10453SEric Joyner { 337871d10453SEric Joyner struct ice_chs_chg *p; 337971d10453SEric Joyner u16 new_vsig; 3380*f2635e84SEric Joyner int status; 338171d10453SEric Joyner 338271d10453SEric Joyner p = (struct ice_chs_chg *)ice_malloc(hw, sizeof(*p)); 338371d10453SEric Joyner if (!p) 338471d10453SEric Joyner return ICE_ERR_NO_MEMORY; 338571d10453SEric Joyner 338671d10453SEric Joyner new_vsig = ice_vsig_alloc(hw, blk); 338771d10453SEric Joyner if (!new_vsig) { 338871d10453SEric Joyner status = ICE_ERR_HW_TABLE; 338971d10453SEric Joyner goto err_ice_create_prof_id_vsig; 339071d10453SEric Joyner } 339171d10453SEric Joyner 339271d10453SEric Joyner status = ice_move_vsi(hw, blk, vsi, new_vsig, chg); 339371d10453SEric Joyner if (status) 339471d10453SEric Joyner goto err_ice_create_prof_id_vsig; 339571d10453SEric Joyner 339671d10453SEric Joyner status = ice_add_prof_id_vsig(hw, blk, new_vsig, hdl, false, chg); 339771d10453SEric Joyner if (status) 339871d10453SEric Joyner goto err_ice_create_prof_id_vsig; 339971d10453SEric Joyner 340071d10453SEric Joyner p->type = ICE_VSIG_ADD; 340171d10453SEric Joyner p->vsi = vsi; 340271d10453SEric Joyner p->orig_vsig = ICE_DEFAULT_VSIG; 340371d10453SEric Joyner p->vsig = new_vsig; 340471d10453SEric Joyner 340571d10453SEric Joyner LIST_ADD(&p->list_entry, chg); 340671d10453SEric Joyner 3407*f2635e84SEric Joyner return 0; 340871d10453SEric Joyner 340971d10453SEric Joyner err_ice_create_prof_id_vsig: 341071d10453SEric Joyner /* let caller clean up the change list */ 341171d10453SEric Joyner ice_free(hw, p); 341271d10453SEric Joyner return status; 341371d10453SEric Joyner } 341471d10453SEric Joyner 341571d10453SEric Joyner /** 341671d10453SEric Joyner * ice_create_vsig_from_lst - create a new VSIG with a list of profiles 341771d10453SEric Joyner * @hw: pointer to the HW struct 341871d10453SEric Joyner * @blk: hardware block 341971d10453SEric Joyner * @vsi: the initial VSI that will be in VSIG 342071d10453SEric Joyner * @lst: the list of profile that will be added to the VSIG 342171d10453SEric Joyner * @new_vsig: return of new VSIG 342271d10453SEric Joyner * @chg: the change list 342371d10453SEric Joyner */ 3424*f2635e84SEric Joyner static int 342571d10453SEric Joyner ice_create_vsig_from_lst(struct ice_hw *hw, enum ice_block blk, u16 vsi, 342671d10453SEric Joyner struct LIST_HEAD_TYPE *lst, u16 *new_vsig, 342771d10453SEric Joyner struct LIST_HEAD_TYPE *chg) 342871d10453SEric Joyner { 342971d10453SEric Joyner struct ice_vsig_prof *t; 3430*f2635e84SEric Joyner int status; 343171d10453SEric Joyner u16 vsig; 343271d10453SEric Joyner 343371d10453SEric Joyner vsig = ice_vsig_alloc(hw, blk); 343471d10453SEric Joyner if (!vsig) 343571d10453SEric Joyner return ICE_ERR_HW_TABLE; 343671d10453SEric Joyner 343771d10453SEric Joyner status = ice_move_vsi(hw, blk, vsi, vsig, chg); 343871d10453SEric Joyner if (status) 343971d10453SEric Joyner return status; 344071d10453SEric Joyner 344171d10453SEric Joyner LIST_FOR_EACH_ENTRY(t, lst, ice_vsig_prof, list) { 344271d10453SEric Joyner /* Reverse the order here since we are copying the list */ 344371d10453SEric Joyner status = ice_add_prof_id_vsig(hw, blk, vsig, t->profile_cookie, 344471d10453SEric Joyner true, chg); 344571d10453SEric Joyner if (status) 344671d10453SEric Joyner return status; 344771d10453SEric Joyner } 344871d10453SEric Joyner 344971d10453SEric Joyner *new_vsig = vsig; 345071d10453SEric Joyner 3451*f2635e84SEric Joyner return 0; 345271d10453SEric Joyner } 345371d10453SEric Joyner 345471d10453SEric Joyner /** 345571d10453SEric Joyner * ice_find_prof_vsig - find a VSIG with a specific profile handle 345671d10453SEric Joyner * @hw: pointer to the HW struct 345771d10453SEric Joyner * @blk: hardware block 345871d10453SEric Joyner * @hdl: the profile handle of the profile to search for 345971d10453SEric Joyner * @vsig: returns the VSIG with the matching profile 346071d10453SEric Joyner */ 346171d10453SEric Joyner static bool 346271d10453SEric Joyner ice_find_prof_vsig(struct ice_hw *hw, enum ice_block blk, u64 hdl, u16 *vsig) 346371d10453SEric Joyner { 346471d10453SEric Joyner struct ice_vsig_prof *t; 34657d7af7f8SEric Joyner struct LIST_HEAD_TYPE lst; 3466*f2635e84SEric Joyner int status; 346771d10453SEric Joyner 346871d10453SEric Joyner INIT_LIST_HEAD(&lst); 346971d10453SEric Joyner 347071d10453SEric Joyner t = (struct ice_vsig_prof *)ice_malloc(hw, sizeof(*t)); 347171d10453SEric Joyner if (!t) 347271d10453SEric Joyner return false; 347371d10453SEric Joyner 347471d10453SEric Joyner t->profile_cookie = hdl; 347571d10453SEric Joyner LIST_ADD(&t->list, &lst); 347671d10453SEric Joyner 347771d10453SEric Joyner status = ice_find_dup_props_vsig(hw, blk, &lst, vsig); 347871d10453SEric Joyner 347971d10453SEric Joyner LIST_DEL(&t->list); 348071d10453SEric Joyner ice_free(hw, t); 348171d10453SEric Joyner 3482*f2635e84SEric Joyner return !status; 348371d10453SEric Joyner } 348471d10453SEric Joyner 348571d10453SEric Joyner /** 348671d10453SEric Joyner * ice_add_vsi_flow - add VSI flow 348771d10453SEric Joyner * @hw: pointer to the HW struct 348871d10453SEric Joyner * @blk: hardware block 348971d10453SEric Joyner * @vsi: input VSI 349071d10453SEric Joyner * @vsig: target VSIG to include the input VSI 349171d10453SEric Joyner * 349271d10453SEric Joyner * Calling this function will add the VSI to a given VSIG and 349371d10453SEric Joyner * update the HW tables accordingly. This call can be used to 349471d10453SEric Joyner * add multiple VSIs to a VSIG if we know beforehand that those 349571d10453SEric Joyner * VSIs have the same characteristics of the VSIG. This will 349671d10453SEric Joyner * save time in generating a new VSIG and TCAMs till a match is 349771d10453SEric Joyner * found and subsequent rollback when a matching VSIG is found. 349871d10453SEric Joyner */ 3499*f2635e84SEric Joyner int 350071d10453SEric Joyner ice_add_vsi_flow(struct ice_hw *hw, enum ice_block blk, u16 vsi, u16 vsig) 350171d10453SEric Joyner { 350271d10453SEric Joyner struct ice_chs_chg *tmp, *del; 350371d10453SEric Joyner struct LIST_HEAD_TYPE chg; 3504*f2635e84SEric Joyner int status; 350571d10453SEric Joyner 350671d10453SEric Joyner /* if target VSIG is default the move is invalid */ 350771d10453SEric Joyner if ((vsig & ICE_VSIG_IDX_M) == ICE_DEFAULT_VSIG) 350871d10453SEric Joyner return ICE_ERR_PARAM; 350971d10453SEric Joyner 351071d10453SEric Joyner INIT_LIST_HEAD(&chg); 351171d10453SEric Joyner 351271d10453SEric Joyner /* move VSI to the VSIG that matches */ 351371d10453SEric Joyner status = ice_move_vsi(hw, blk, vsi, vsig, &chg); 351471d10453SEric Joyner /* update hardware if success */ 351571d10453SEric Joyner if (!status) 351671d10453SEric Joyner status = ice_upd_prof_hw(hw, blk, &chg); 351771d10453SEric Joyner 351871d10453SEric Joyner LIST_FOR_EACH_ENTRY_SAFE(del, tmp, &chg, ice_chs_chg, list_entry) { 351971d10453SEric Joyner LIST_DEL(&del->list_entry); 352071d10453SEric Joyner ice_free(hw, del); 352171d10453SEric Joyner } 352271d10453SEric Joyner 352371d10453SEric Joyner return status; 352471d10453SEric Joyner } 352571d10453SEric Joyner 352671d10453SEric Joyner /** 352771d10453SEric Joyner * ice_add_prof_id_flow - add profile flow 352871d10453SEric Joyner * @hw: pointer to the HW struct 352971d10453SEric Joyner * @blk: hardware block 353071d10453SEric Joyner * @vsi: the VSI to enable with the profile specified by ID 353171d10453SEric Joyner * @hdl: profile handle 353271d10453SEric Joyner * 353371d10453SEric Joyner * Calling this function will update the hardware tables to enable the 353471d10453SEric Joyner * profile indicated by the ID parameter for the VSIs specified in the VSI 353571d10453SEric Joyner * array. Once successfully called, the flow will be enabled. 353671d10453SEric Joyner */ 3537*f2635e84SEric Joyner int 353871d10453SEric Joyner ice_add_prof_id_flow(struct ice_hw *hw, enum ice_block blk, u16 vsi, u64 hdl) 353971d10453SEric Joyner { 354071d10453SEric Joyner struct ice_vsig_prof *tmp1, *del1; 354171d10453SEric Joyner struct ice_chs_chg *tmp, *del; 35427d7af7f8SEric Joyner struct LIST_HEAD_TYPE union_lst; 35437d7af7f8SEric Joyner struct LIST_HEAD_TYPE chg; 3544*f2635e84SEric Joyner int status; 354571d10453SEric Joyner u16 vsig; 354671d10453SEric Joyner 354771d10453SEric Joyner INIT_LIST_HEAD(&union_lst); 354871d10453SEric Joyner INIT_LIST_HEAD(&chg); 354971d10453SEric Joyner 355071d10453SEric Joyner /* Get profile */ 355171d10453SEric Joyner status = ice_get_prof(hw, blk, hdl, &chg); 355271d10453SEric Joyner if (status) 355371d10453SEric Joyner return status; 355471d10453SEric Joyner 355571d10453SEric Joyner /* determine if VSI is already part of a VSIG */ 355671d10453SEric Joyner status = ice_vsig_find_vsi(hw, blk, vsi, &vsig); 355771d10453SEric Joyner if (!status && vsig) { 355871d10453SEric Joyner bool only_vsi; 355971d10453SEric Joyner u16 or_vsig; 356071d10453SEric Joyner u16 ref; 356171d10453SEric Joyner 356271d10453SEric Joyner /* found in VSIG */ 356371d10453SEric Joyner or_vsig = vsig; 356471d10453SEric Joyner 356571d10453SEric Joyner /* make sure that there is no overlap/conflict between the new 356671d10453SEric Joyner * characteristics and the existing ones; we don't support that 356771d10453SEric Joyner * scenario 356871d10453SEric Joyner */ 356971d10453SEric Joyner if (ice_has_prof_vsig(hw, blk, vsig, hdl)) { 357071d10453SEric Joyner status = ICE_ERR_ALREADY_EXISTS; 357171d10453SEric Joyner goto err_ice_add_prof_id_flow; 357271d10453SEric Joyner } 357371d10453SEric Joyner 357471d10453SEric Joyner /* last VSI in the VSIG? */ 357571d10453SEric Joyner status = ice_vsig_get_ref(hw, blk, vsig, &ref); 357671d10453SEric Joyner if (status) 357771d10453SEric Joyner goto err_ice_add_prof_id_flow; 357871d10453SEric Joyner only_vsi = (ref == 1); 357971d10453SEric Joyner 358071d10453SEric Joyner /* create a union of the current profiles and the one being 358171d10453SEric Joyner * added 358271d10453SEric Joyner */ 358371d10453SEric Joyner status = ice_get_profs_vsig(hw, blk, vsig, &union_lst); 358471d10453SEric Joyner if (status) 358571d10453SEric Joyner goto err_ice_add_prof_id_flow; 358671d10453SEric Joyner 358771d10453SEric Joyner status = ice_add_prof_to_lst(hw, blk, &union_lst, hdl); 358871d10453SEric Joyner if (status) 358971d10453SEric Joyner goto err_ice_add_prof_id_flow; 359071d10453SEric Joyner 359171d10453SEric Joyner /* search for an existing VSIG with an exact charc match */ 359271d10453SEric Joyner status = ice_find_dup_props_vsig(hw, blk, &union_lst, &vsig); 359371d10453SEric Joyner if (!status) { 359471d10453SEric Joyner /* move VSI to the VSIG that matches */ 359571d10453SEric Joyner status = ice_move_vsi(hw, blk, vsi, vsig, &chg); 359671d10453SEric Joyner if (status) 359771d10453SEric Joyner goto err_ice_add_prof_id_flow; 359871d10453SEric Joyner 359971d10453SEric Joyner /* VSI has been moved out of or_vsig. If the or_vsig had 360071d10453SEric Joyner * only that VSI it is now empty and can be removed. 360171d10453SEric Joyner */ 360271d10453SEric Joyner if (only_vsi) { 360371d10453SEric Joyner status = ice_rem_vsig(hw, blk, or_vsig, &chg); 360471d10453SEric Joyner if (status) 360571d10453SEric Joyner goto err_ice_add_prof_id_flow; 360671d10453SEric Joyner } 360771d10453SEric Joyner } else if (only_vsi) { 360871d10453SEric Joyner /* If the original VSIG only contains one VSI, then it 360971d10453SEric Joyner * will be the requesting VSI. In this case the VSI is 361071d10453SEric Joyner * not sharing entries and we can simply add the new 361171d10453SEric Joyner * profile to the VSIG. 361271d10453SEric Joyner */ 361371d10453SEric Joyner status = ice_add_prof_id_vsig(hw, blk, vsig, hdl, false, 361471d10453SEric Joyner &chg); 361571d10453SEric Joyner if (status) 361671d10453SEric Joyner goto err_ice_add_prof_id_flow; 361771d10453SEric Joyner 361871d10453SEric Joyner /* Adjust priorities */ 361971d10453SEric Joyner status = ice_adj_prof_priorities(hw, blk, vsig, &chg); 362071d10453SEric Joyner if (status) 362171d10453SEric Joyner goto err_ice_add_prof_id_flow; 362271d10453SEric Joyner } else { 362371d10453SEric Joyner /* No match, so we need a new VSIG */ 362471d10453SEric Joyner status = ice_create_vsig_from_lst(hw, blk, vsi, 362571d10453SEric Joyner &union_lst, &vsig, 362671d10453SEric Joyner &chg); 362771d10453SEric Joyner if (status) 362871d10453SEric Joyner goto err_ice_add_prof_id_flow; 362971d10453SEric Joyner 363071d10453SEric Joyner /* Adjust priorities */ 363171d10453SEric Joyner status = ice_adj_prof_priorities(hw, blk, vsig, &chg); 363271d10453SEric Joyner if (status) 363371d10453SEric Joyner goto err_ice_add_prof_id_flow; 363471d10453SEric Joyner } 363571d10453SEric Joyner } else { 363671d10453SEric Joyner /* need to find or add a VSIG */ 363771d10453SEric Joyner /* search for an existing VSIG with an exact charc match */ 363871d10453SEric Joyner if (ice_find_prof_vsig(hw, blk, hdl, &vsig)) { 363971d10453SEric Joyner /* found an exact match */ 364071d10453SEric Joyner /* add or move VSI to the VSIG that matches */ 364171d10453SEric Joyner status = ice_move_vsi(hw, blk, vsi, vsig, &chg); 364271d10453SEric Joyner if (status) 364371d10453SEric Joyner goto err_ice_add_prof_id_flow; 364471d10453SEric Joyner } else { 364571d10453SEric Joyner /* we did not find an exact match */ 364671d10453SEric Joyner /* we need to add a VSIG */ 364771d10453SEric Joyner status = ice_create_prof_id_vsig(hw, blk, vsi, hdl, 364871d10453SEric Joyner &chg); 364971d10453SEric Joyner if (status) 365071d10453SEric Joyner goto err_ice_add_prof_id_flow; 365171d10453SEric Joyner } 365271d10453SEric Joyner } 365371d10453SEric Joyner 365471d10453SEric Joyner /* update hardware */ 365571d10453SEric Joyner if (!status) 365671d10453SEric Joyner status = ice_upd_prof_hw(hw, blk, &chg); 365771d10453SEric Joyner 365871d10453SEric Joyner err_ice_add_prof_id_flow: 365971d10453SEric Joyner LIST_FOR_EACH_ENTRY_SAFE(del, tmp, &chg, ice_chs_chg, list_entry) { 366071d10453SEric Joyner LIST_DEL(&del->list_entry); 366171d10453SEric Joyner ice_free(hw, del); 366271d10453SEric Joyner } 366371d10453SEric Joyner 366471d10453SEric Joyner LIST_FOR_EACH_ENTRY_SAFE(del1, tmp1, &union_lst, ice_vsig_prof, list) { 366571d10453SEric Joyner LIST_DEL(&del1->list); 366671d10453SEric Joyner ice_free(hw, del1); 366771d10453SEric Joyner } 366871d10453SEric Joyner 366971d10453SEric Joyner return status; 367071d10453SEric Joyner } 367171d10453SEric Joyner 367271d10453SEric Joyner /** 367371d10453SEric Joyner * ice_add_flow - add flow 367471d10453SEric Joyner * @hw: pointer to the HW struct 367571d10453SEric Joyner * @blk: hardware block 367671d10453SEric Joyner * @vsi: array of VSIs to enable with the profile specified by ID 367771d10453SEric Joyner * @count: number of elements in the VSI array 367871d10453SEric Joyner * @id: profile tracking ID 367971d10453SEric Joyner * 368071d10453SEric Joyner * Calling this function will update the hardware tables to enable the 368171d10453SEric Joyner * profile indicated by the ID parameter for the VSIs specified in the VSI 368271d10453SEric Joyner * array. Once successfully called, the flow will be enabled. 368371d10453SEric Joyner */ 3684*f2635e84SEric Joyner int 368571d10453SEric Joyner ice_add_flow(struct ice_hw *hw, enum ice_block blk, u16 vsi[], u8 count, 368671d10453SEric Joyner u64 id) 368771d10453SEric Joyner { 368871d10453SEric Joyner u16 i; 368971d10453SEric Joyner 369071d10453SEric Joyner for (i = 0; i < count; i++) { 3691*f2635e84SEric Joyner int status; 36928923de59SPiotr Kubaj 369371d10453SEric Joyner status = ice_add_prof_id_flow(hw, blk, vsi[i], id); 369471d10453SEric Joyner if (status) 369571d10453SEric Joyner return status; 369671d10453SEric Joyner } 369771d10453SEric Joyner 3698*f2635e84SEric Joyner return 0; 369971d10453SEric Joyner } 370071d10453SEric Joyner 370171d10453SEric Joyner /** 370271d10453SEric Joyner * ice_rem_prof_from_list - remove a profile from list 370371d10453SEric Joyner * @hw: pointer to the HW struct 370471d10453SEric Joyner * @lst: list to remove the profile from 370571d10453SEric Joyner * @hdl: the profile handle indicating the profile to remove 370671d10453SEric Joyner */ 3707*f2635e84SEric Joyner static int 370871d10453SEric Joyner ice_rem_prof_from_list(struct ice_hw *hw, struct LIST_HEAD_TYPE *lst, u64 hdl) 370971d10453SEric Joyner { 371071d10453SEric Joyner struct ice_vsig_prof *ent, *tmp; 371171d10453SEric Joyner 37127d7af7f8SEric Joyner LIST_FOR_EACH_ENTRY_SAFE(ent, tmp, lst, ice_vsig_prof, list) 371371d10453SEric Joyner if (ent->profile_cookie == hdl) { 371471d10453SEric Joyner LIST_DEL(&ent->list); 371571d10453SEric Joyner ice_free(hw, ent); 3716*f2635e84SEric Joyner return 0; 371771d10453SEric Joyner } 371871d10453SEric Joyner 371971d10453SEric Joyner return ICE_ERR_DOES_NOT_EXIST; 372071d10453SEric Joyner } 372171d10453SEric Joyner 372271d10453SEric Joyner /** 372371d10453SEric Joyner * ice_rem_prof_id_flow - remove flow 372471d10453SEric Joyner * @hw: pointer to the HW struct 372571d10453SEric Joyner * @blk: hardware block 372671d10453SEric Joyner * @vsi: the VSI from which to remove the profile specified by ID 372771d10453SEric Joyner * @hdl: profile tracking handle 372871d10453SEric Joyner * 372971d10453SEric Joyner * Calling this function will update the hardware tables to remove the 373071d10453SEric Joyner * profile indicated by the ID parameter for the VSIs specified in the VSI 373171d10453SEric Joyner * array. Once successfully called, the flow will be disabled. 373271d10453SEric Joyner */ 3733*f2635e84SEric Joyner int 373471d10453SEric Joyner ice_rem_prof_id_flow(struct ice_hw *hw, enum ice_block blk, u16 vsi, u64 hdl) 373571d10453SEric Joyner { 373671d10453SEric Joyner struct ice_vsig_prof *tmp1, *del1; 373771d10453SEric Joyner struct ice_chs_chg *tmp, *del; 37387d7af7f8SEric Joyner struct LIST_HEAD_TYPE chg, copy; 3739*f2635e84SEric Joyner int status; 374071d10453SEric Joyner u16 vsig; 374171d10453SEric Joyner 374271d10453SEric Joyner INIT_LIST_HEAD(©); 374371d10453SEric Joyner INIT_LIST_HEAD(&chg); 374471d10453SEric Joyner 374571d10453SEric Joyner /* determine if VSI is already part of a VSIG */ 374671d10453SEric Joyner status = ice_vsig_find_vsi(hw, blk, vsi, &vsig); 374771d10453SEric Joyner if (!status && vsig) { 374871d10453SEric Joyner bool last_profile; 374971d10453SEric Joyner bool only_vsi; 375071d10453SEric Joyner u16 ref; 375171d10453SEric Joyner 375271d10453SEric Joyner /* found in VSIG */ 375371d10453SEric Joyner last_profile = ice_vsig_prof_id_count(hw, blk, vsig) == 1; 375471d10453SEric Joyner status = ice_vsig_get_ref(hw, blk, vsig, &ref); 375571d10453SEric Joyner if (status) 375671d10453SEric Joyner goto err_ice_rem_prof_id_flow; 375771d10453SEric Joyner only_vsi = (ref == 1); 375871d10453SEric Joyner 375971d10453SEric Joyner if (only_vsi) { 376071d10453SEric Joyner /* If the original VSIG only contains one reference, 376171d10453SEric Joyner * which will be the requesting VSI, then the VSI is not 376271d10453SEric Joyner * sharing entries and we can simply remove the specific 376371d10453SEric Joyner * characteristics from the VSIG. 376471d10453SEric Joyner */ 376571d10453SEric Joyner 376671d10453SEric Joyner if (last_profile) { 376771d10453SEric Joyner /* If there are no profiles left for this VSIG, 37687d7af7f8SEric Joyner * then simply remove the VSIG. 376971d10453SEric Joyner */ 377071d10453SEric Joyner status = ice_rem_vsig(hw, blk, vsig, &chg); 377171d10453SEric Joyner if (status) 377271d10453SEric Joyner goto err_ice_rem_prof_id_flow; 377371d10453SEric Joyner } else { 377471d10453SEric Joyner status = ice_rem_prof_id_vsig(hw, blk, vsig, 377571d10453SEric Joyner hdl, &chg); 377671d10453SEric Joyner if (status) 377771d10453SEric Joyner goto err_ice_rem_prof_id_flow; 377871d10453SEric Joyner 377971d10453SEric Joyner /* Adjust priorities */ 378071d10453SEric Joyner status = ice_adj_prof_priorities(hw, blk, vsig, 378171d10453SEric Joyner &chg); 378271d10453SEric Joyner if (status) 378371d10453SEric Joyner goto err_ice_rem_prof_id_flow; 378471d10453SEric Joyner } 378571d10453SEric Joyner 378671d10453SEric Joyner } else { 378771d10453SEric Joyner /* Make a copy of the VSIG's list of Profiles */ 378871d10453SEric Joyner status = ice_get_profs_vsig(hw, blk, vsig, ©); 378971d10453SEric Joyner if (status) 379071d10453SEric Joyner goto err_ice_rem_prof_id_flow; 379171d10453SEric Joyner 379271d10453SEric Joyner /* Remove specified profile entry from the list */ 379371d10453SEric Joyner status = ice_rem_prof_from_list(hw, ©, hdl); 379471d10453SEric Joyner if (status) 379571d10453SEric Joyner goto err_ice_rem_prof_id_flow; 379671d10453SEric Joyner 379771d10453SEric Joyner if (LIST_EMPTY(©)) { 379871d10453SEric Joyner status = ice_move_vsi(hw, blk, vsi, 379971d10453SEric Joyner ICE_DEFAULT_VSIG, &chg); 380071d10453SEric Joyner if (status) 380171d10453SEric Joyner goto err_ice_rem_prof_id_flow; 380271d10453SEric Joyner 380371d10453SEric Joyner } else if (!ice_find_dup_props_vsig(hw, blk, ©, 380471d10453SEric Joyner &vsig)) { 380571d10453SEric Joyner /* found an exact match */ 380671d10453SEric Joyner /* add or move VSI to the VSIG that matches */ 380771d10453SEric Joyner /* Search for a VSIG with a matching profile 380871d10453SEric Joyner * list 380971d10453SEric Joyner */ 381071d10453SEric Joyner 381171d10453SEric Joyner /* Found match, move VSI to the matching VSIG */ 381271d10453SEric Joyner status = ice_move_vsi(hw, blk, vsi, vsig, &chg); 381371d10453SEric Joyner if (status) 381471d10453SEric Joyner goto err_ice_rem_prof_id_flow; 381571d10453SEric Joyner } else { 381671d10453SEric Joyner /* since no existing VSIG supports this 381771d10453SEric Joyner * characteristic pattern, we need to create a 381871d10453SEric Joyner * new VSIG and TCAM entries 381971d10453SEric Joyner */ 382071d10453SEric Joyner status = ice_create_vsig_from_lst(hw, blk, vsi, 382171d10453SEric Joyner ©, &vsig, 382271d10453SEric Joyner &chg); 382371d10453SEric Joyner if (status) 382471d10453SEric Joyner goto err_ice_rem_prof_id_flow; 382571d10453SEric Joyner 382671d10453SEric Joyner /* Adjust priorities */ 382771d10453SEric Joyner status = ice_adj_prof_priorities(hw, blk, vsig, 382871d10453SEric Joyner &chg); 382971d10453SEric Joyner if (status) 383071d10453SEric Joyner goto err_ice_rem_prof_id_flow; 383171d10453SEric Joyner } 383271d10453SEric Joyner } 383371d10453SEric Joyner } else { 383471d10453SEric Joyner status = ICE_ERR_DOES_NOT_EXIST; 383571d10453SEric Joyner } 383671d10453SEric Joyner 383771d10453SEric Joyner /* update hardware tables */ 383871d10453SEric Joyner if (!status) 383971d10453SEric Joyner status = ice_upd_prof_hw(hw, blk, &chg); 384071d10453SEric Joyner 384171d10453SEric Joyner err_ice_rem_prof_id_flow: 384271d10453SEric Joyner LIST_FOR_EACH_ENTRY_SAFE(del, tmp, &chg, ice_chs_chg, list_entry) { 384371d10453SEric Joyner LIST_DEL(&del->list_entry); 384471d10453SEric Joyner ice_free(hw, del); 384571d10453SEric Joyner } 384671d10453SEric Joyner 384771d10453SEric Joyner LIST_FOR_EACH_ENTRY_SAFE(del1, tmp1, ©, ice_vsig_prof, list) { 384871d10453SEric Joyner LIST_DEL(&del1->list); 384971d10453SEric Joyner ice_free(hw, del1); 385071d10453SEric Joyner } 385171d10453SEric Joyner 385271d10453SEric Joyner return status; 385371d10453SEric Joyner } 385471d10453SEric Joyner 385571d10453SEric Joyner /** 385671d10453SEric Joyner * ice_rem_flow - remove flow 385771d10453SEric Joyner * @hw: pointer to the HW struct 385871d10453SEric Joyner * @blk: hardware block 385971d10453SEric Joyner * @vsi: array of VSIs from which to remove the profile specified by ID 386071d10453SEric Joyner * @count: number of elements in the VSI array 386171d10453SEric Joyner * @id: profile tracking ID 386271d10453SEric Joyner * 386371d10453SEric Joyner * The function will remove flows from the specified VSIs that were enabled 386471d10453SEric Joyner * using ice_add_flow. The ID value will indicated which profile will be 386571d10453SEric Joyner * removed. Once successfully called, the flow will be disabled. 386671d10453SEric Joyner */ 3867*f2635e84SEric Joyner int 386871d10453SEric Joyner ice_rem_flow(struct ice_hw *hw, enum ice_block blk, u16 vsi[], u8 count, 386971d10453SEric Joyner u64 id) 387071d10453SEric Joyner { 387171d10453SEric Joyner u16 i; 387271d10453SEric Joyner 387371d10453SEric Joyner for (i = 0; i < count; i++) { 3874*f2635e84SEric Joyner int status; 38758923de59SPiotr Kubaj 387671d10453SEric Joyner status = ice_rem_prof_id_flow(hw, blk, vsi[i], id); 387771d10453SEric Joyner if (status) 387871d10453SEric Joyner return status; 387971d10453SEric Joyner } 388071d10453SEric Joyner 3881*f2635e84SEric Joyner return 0; 388271d10453SEric Joyner } 3883