1d08b8680SEric Joyner /* SPDX-License-Identifier: BSD-3-Clause */ 2015f8cc5SEric Joyner /* Copyright (c) 2024, Intel Corporation 3d08b8680SEric Joyner * All rights reserved. 4d08b8680SEric Joyner * 5d08b8680SEric Joyner * Redistribution and use in source and binary forms, with or without 6d08b8680SEric Joyner * modification, are permitted provided that the following conditions are met: 7d08b8680SEric Joyner * 8d08b8680SEric Joyner * 1. Redistributions of source code must retain the above copyright notice, 9d08b8680SEric Joyner * this list of conditions and the following disclaimer. 10d08b8680SEric Joyner * 11d08b8680SEric Joyner * 2. Redistributions in binary form must reproduce the above copyright 12d08b8680SEric Joyner * notice, this list of conditions and the following disclaimer in the 13d08b8680SEric Joyner * documentation and/or other materials provided with the distribution. 14d08b8680SEric Joyner * 15d08b8680SEric Joyner * 3. Neither the name of the Intel Corporation nor the names of its 16d08b8680SEric Joyner * contributors may be used to endorse or promote products derived from 17d08b8680SEric Joyner * this software without specific prior written permission. 18d08b8680SEric Joyner * 19d08b8680SEric Joyner * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20d08b8680SEric Joyner * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21d08b8680SEric Joyner * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22d08b8680SEric Joyner * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23d08b8680SEric Joyner * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24d08b8680SEric Joyner * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25d08b8680SEric Joyner * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26d08b8680SEric Joyner * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27d08b8680SEric Joyner * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28d08b8680SEric Joyner * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29d08b8680SEric Joyner * POSSIBILITY OF SUCH DAMAGE. 30d08b8680SEric Joyner */ 31d08b8680SEric Joyner 32d08b8680SEric Joyner #include "ice_common.h" 33d08b8680SEric Joyner 348923de59SPiotr Kubaj #include "ice_ddp_common.h" 35d08b8680SEric Joyner /** 3656429daeSEric Joyner * ice_pkg_get_supported_vlan_mode - chk if DDP supports Double VLAN mode (DVM) 379cf1841cSEric Joyner * @hw: pointer to the HW struct 389cf1841cSEric Joyner * @dvm: output variable to determine if DDP supports DVM(true) or SVM(false) 399cf1841cSEric Joyner */ 40*f2635e84SEric Joyner static int 419cf1841cSEric Joyner ice_pkg_get_supported_vlan_mode(struct ice_hw *hw, bool *dvm) 429cf1841cSEric Joyner { 439cf1841cSEric Joyner u16 meta_init_size = sizeof(struct ice_meta_init_section); 449cf1841cSEric Joyner struct ice_meta_init_section *sect; 459cf1841cSEric Joyner struct ice_buf_build *bld; 46*f2635e84SEric Joyner int status; 479cf1841cSEric Joyner 489cf1841cSEric Joyner /* if anything fails, we assume there is no DVM support */ 499cf1841cSEric Joyner *dvm = false; 509cf1841cSEric Joyner 519cf1841cSEric Joyner bld = ice_pkg_buf_alloc_single_section(hw, 529cf1841cSEric Joyner ICE_SID_RXPARSER_METADATA_INIT, 539cf1841cSEric Joyner meta_init_size, (void **)§); 549cf1841cSEric Joyner if (!bld) 559cf1841cSEric Joyner return ICE_ERR_NO_MEMORY; 569cf1841cSEric Joyner 579cf1841cSEric Joyner /* only need to read a single section */ 589cf1841cSEric Joyner sect->count = CPU_TO_LE16(1); 599cf1841cSEric Joyner sect->offset = CPU_TO_LE16(ICE_META_VLAN_MODE_ENTRY); 609cf1841cSEric Joyner 619cf1841cSEric Joyner status = ice_aq_upload_section(hw, 629cf1841cSEric Joyner (struct ice_buf_hdr *)ice_pkg_buf(bld), 639cf1841cSEric Joyner ICE_PKG_BUF_SIZE, NULL); 649cf1841cSEric Joyner if (!status) { 659cf1841cSEric Joyner ice_declare_bitmap(entry, ICE_META_INIT_BITS); 669cf1841cSEric Joyner u32 arr[ICE_META_INIT_DW_CNT]; 679cf1841cSEric Joyner u16 i; 689cf1841cSEric Joyner 699cf1841cSEric Joyner /* convert to host bitmap format */ 709cf1841cSEric Joyner for (i = 0; i < ICE_META_INIT_DW_CNT; i++) 719cf1841cSEric Joyner arr[i] = LE32_TO_CPU(sect->entry[0].bm[i]); 729cf1841cSEric Joyner 739cf1841cSEric Joyner ice_bitmap_from_array32(entry, arr, (u16)ICE_META_INIT_BITS); 749cf1841cSEric Joyner 759cf1841cSEric Joyner /* check if DVM is supported */ 769cf1841cSEric Joyner *dvm = ice_is_bit_set(entry, ICE_META_VLAN_MODE_BIT); 779cf1841cSEric Joyner } 789cf1841cSEric Joyner 799cf1841cSEric Joyner ice_pkg_buf_free(hw, bld); 809cf1841cSEric Joyner 819cf1841cSEric Joyner return status; 829cf1841cSEric Joyner } 839cf1841cSEric Joyner 849cf1841cSEric Joyner /** 859cf1841cSEric Joyner * ice_aq_get_vlan_mode - get the VLAN mode of the device 869cf1841cSEric Joyner * @hw: pointer to the HW structure 879cf1841cSEric Joyner * @get_params: structure FW fills in based on the current VLAN mode config 889cf1841cSEric Joyner * 899cf1841cSEric Joyner * Get VLAN Mode Parameters (0x020D) 909cf1841cSEric Joyner */ 91*f2635e84SEric Joyner static int 929cf1841cSEric Joyner ice_aq_get_vlan_mode(struct ice_hw *hw, 939cf1841cSEric Joyner struct ice_aqc_get_vlan_mode *get_params) 949cf1841cSEric Joyner { 959cf1841cSEric Joyner struct ice_aq_desc desc; 969cf1841cSEric Joyner 979cf1841cSEric Joyner if (!get_params) 989cf1841cSEric Joyner return ICE_ERR_PARAM; 999cf1841cSEric Joyner 1009cf1841cSEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, 1019cf1841cSEric Joyner ice_aqc_opc_get_vlan_mode_parameters); 1029cf1841cSEric Joyner 1039cf1841cSEric Joyner return ice_aq_send_cmd(hw, &desc, get_params, sizeof(*get_params), 1049cf1841cSEric Joyner NULL); 1059cf1841cSEric Joyner } 1069cf1841cSEric Joyner 1079cf1841cSEric Joyner /** 1089cf1841cSEric Joyner * ice_aq_is_dvm_ena - query FW to check if double VLAN mode is enabled 1099cf1841cSEric Joyner * @hw: pointer to the HW structure 1109cf1841cSEric Joyner * 1119cf1841cSEric Joyner * Returns true if the hardware/firmware is configured in double VLAN mode, 1129cf1841cSEric Joyner * else return false signaling that the hardware/firmware is configured in 1139cf1841cSEric Joyner * single VLAN mode. 1149cf1841cSEric Joyner * 1159cf1841cSEric Joyner * Also, return false if this call fails for any reason (i.e. firmware doesn't 1169cf1841cSEric Joyner * support this AQ call). 1179cf1841cSEric Joyner */ 1189cf1841cSEric Joyner static bool ice_aq_is_dvm_ena(struct ice_hw *hw) 1199cf1841cSEric Joyner { 1209cf1841cSEric Joyner struct ice_aqc_get_vlan_mode get_params = { 0 }; 121*f2635e84SEric Joyner int status; 1229cf1841cSEric Joyner 1239cf1841cSEric Joyner status = ice_aq_get_vlan_mode(hw, &get_params); 1249cf1841cSEric Joyner if (status) { 1259cf1841cSEric Joyner ice_debug(hw, ICE_DBG_AQ, "Failed to get VLAN mode, status %d\n", 1269cf1841cSEric Joyner status); 1279cf1841cSEric Joyner return false; 1289cf1841cSEric Joyner } 1299cf1841cSEric Joyner 1309cf1841cSEric Joyner return (get_params.vlan_mode & ICE_AQ_VLAN_MODE_DVM_ENA); 1319cf1841cSEric Joyner } 1329cf1841cSEric Joyner 1339cf1841cSEric Joyner /** 1349cf1841cSEric Joyner * ice_is_dvm_ena - check if double VLAN mode is enabled 1359cf1841cSEric Joyner * @hw: pointer to the HW structure 1369cf1841cSEric Joyner * 1379cf1841cSEric Joyner * The device is configured in single or double VLAN mode on initialization and 1389cf1841cSEric Joyner * this cannot be dynamically changed during runtime. Based on this there is no 1399cf1841cSEric Joyner * need to make an AQ call every time the driver needs to know the VLAN mode. 1409cf1841cSEric Joyner * Instead, use the cached VLAN mode. 1419cf1841cSEric Joyner */ 1429cf1841cSEric Joyner bool ice_is_dvm_ena(struct ice_hw *hw) 1439cf1841cSEric Joyner { 1449cf1841cSEric Joyner return hw->dvm_ena; 1459cf1841cSEric Joyner } 1469cf1841cSEric Joyner 1479cf1841cSEric Joyner /** 1489cf1841cSEric Joyner * ice_cache_vlan_mode - cache VLAN mode after DDP is downloaded 1499cf1841cSEric Joyner * @hw: pointer to the HW structure 1509cf1841cSEric Joyner * 1519cf1841cSEric Joyner * This is only called after downloading the DDP and after the global 1529cf1841cSEric Joyner * configuration lock has been released because all ports on a device need to 1539cf1841cSEric Joyner * cache the VLAN mode. 1549cf1841cSEric Joyner */ 15556429daeSEric Joyner static void ice_cache_vlan_mode(struct ice_hw *hw) 1569cf1841cSEric Joyner { 1579cf1841cSEric Joyner hw->dvm_ena = ice_aq_is_dvm_ena(hw) ? true : false; 1589cf1841cSEric Joyner } 1599cf1841cSEric Joyner 1609cf1841cSEric Joyner /** 16156429daeSEric Joyner * ice_pkg_supports_dvm - find out if DDP supports DVM 16256429daeSEric Joyner * @hw: pointer to the HW structure 16356429daeSEric Joyner */ 16456429daeSEric Joyner static bool ice_pkg_supports_dvm(struct ice_hw *hw) 16556429daeSEric Joyner { 166*f2635e84SEric Joyner int status; 16756429daeSEric Joyner bool pkg_supports_dvm; 16856429daeSEric Joyner 16956429daeSEric Joyner status = ice_pkg_get_supported_vlan_mode(hw, &pkg_supports_dvm); 17056429daeSEric Joyner if (status) { 17156429daeSEric Joyner ice_debug(hw, ICE_DBG_PKG, "Failed to get supported VLAN mode, status %d\n", 17256429daeSEric Joyner status); 17356429daeSEric Joyner return false; 17456429daeSEric Joyner } 17556429daeSEric Joyner 17656429daeSEric Joyner return pkg_supports_dvm; 17756429daeSEric Joyner } 17856429daeSEric Joyner 17956429daeSEric Joyner /** 18056429daeSEric Joyner * ice_fw_supports_dvm - find out if FW supports DVM 18156429daeSEric Joyner * @hw: pointer to the HW structure 18256429daeSEric Joyner */ 18356429daeSEric Joyner static bool ice_fw_supports_dvm(struct ice_hw *hw) 18456429daeSEric Joyner { 18556429daeSEric Joyner struct ice_aqc_get_vlan_mode get_vlan_mode = { 0 }; 186*f2635e84SEric Joyner int status; 18756429daeSEric Joyner 18856429daeSEric Joyner /* If firmware returns success, then it supports DVM, else it only 18956429daeSEric Joyner * supports SVM 19056429daeSEric Joyner */ 19156429daeSEric Joyner status = ice_aq_get_vlan_mode(hw, &get_vlan_mode); 19256429daeSEric Joyner if (status) { 19356429daeSEric Joyner ice_debug(hw, ICE_DBG_NVM, "Failed to get VLAN mode, status %d\n", 19456429daeSEric Joyner status); 19556429daeSEric Joyner return false; 19656429daeSEric Joyner } 19756429daeSEric Joyner 19856429daeSEric Joyner return true; 19956429daeSEric Joyner } 20056429daeSEric Joyner 20156429daeSEric Joyner /** 2029cf1841cSEric Joyner * ice_is_dvm_supported - check if Double VLAN Mode is supported 2039cf1841cSEric Joyner * @hw: pointer to the hardware structure 2049cf1841cSEric Joyner * 2059cf1841cSEric Joyner * Returns true if Double VLAN Mode (DVM) is supported and false if only Single 2069cf1841cSEric Joyner * VLAN Mode (SVM) is supported. In order for DVM to be supported the DDP and 2079cf1841cSEric Joyner * firmware must support it, otherwise only SVM is supported. This function 2089cf1841cSEric Joyner * should only be called while the global config lock is held and after the 2099cf1841cSEric Joyner * package has been successfully downloaded. 2109cf1841cSEric Joyner */ 2119cf1841cSEric Joyner static bool ice_is_dvm_supported(struct ice_hw *hw) 2129cf1841cSEric Joyner { 21356429daeSEric Joyner if (!ice_pkg_supports_dvm(hw)) { 21456429daeSEric Joyner ice_debug(hw, ICE_DBG_PKG, "DDP doesn't support DVM\n"); 2159cf1841cSEric Joyner return false; 2169cf1841cSEric Joyner } 2179cf1841cSEric Joyner 21856429daeSEric Joyner if (!ice_fw_supports_dvm(hw)) { 21956429daeSEric Joyner ice_debug(hw, ICE_DBG_PKG, "FW doesn't support DVM\n"); 2209cf1841cSEric Joyner return false; 2219cf1841cSEric Joyner } 2229cf1841cSEric Joyner 2239cf1841cSEric Joyner return true; 2249cf1841cSEric Joyner } 2259cf1841cSEric Joyner 2269cf1841cSEric Joyner /** 2279cf1841cSEric Joyner * ice_aq_set_vlan_mode - set the VLAN mode of the device 2289cf1841cSEric Joyner * @hw: pointer to the HW structure 2299cf1841cSEric Joyner * @set_params: requested VLAN mode configuration 2309cf1841cSEric Joyner * 2319cf1841cSEric Joyner * Set VLAN Mode Parameters (0x020C) 2329cf1841cSEric Joyner */ 233*f2635e84SEric Joyner static int 2349cf1841cSEric Joyner ice_aq_set_vlan_mode(struct ice_hw *hw, 2359cf1841cSEric Joyner struct ice_aqc_set_vlan_mode *set_params) 2369cf1841cSEric Joyner { 2379cf1841cSEric Joyner u8 rdma_packet, mng_vlan_prot_id; 2389cf1841cSEric Joyner struct ice_aq_desc desc; 2399cf1841cSEric Joyner 2409cf1841cSEric Joyner if (!set_params) 2419cf1841cSEric Joyner return ICE_ERR_PARAM; 2429cf1841cSEric Joyner 2439cf1841cSEric Joyner if (set_params->l2tag_prio_tagging > ICE_AQ_VLAN_PRIO_TAG_MAX) 2449cf1841cSEric Joyner return ICE_ERR_PARAM; 2459cf1841cSEric Joyner 2469cf1841cSEric Joyner rdma_packet = set_params->rdma_packet; 2479cf1841cSEric Joyner if (rdma_packet != ICE_AQ_SVM_VLAN_RDMA_PKT_FLAG_SETTING && 2489cf1841cSEric Joyner rdma_packet != ICE_AQ_DVM_VLAN_RDMA_PKT_FLAG_SETTING) 2499cf1841cSEric Joyner return ICE_ERR_PARAM; 2509cf1841cSEric Joyner 2519cf1841cSEric Joyner mng_vlan_prot_id = set_params->mng_vlan_prot_id; 2529cf1841cSEric Joyner if (mng_vlan_prot_id != ICE_AQ_VLAN_MNG_PROTOCOL_ID_OUTER && 2539cf1841cSEric Joyner mng_vlan_prot_id != ICE_AQ_VLAN_MNG_PROTOCOL_ID_INNER) 2549cf1841cSEric Joyner return ICE_ERR_PARAM; 2559cf1841cSEric Joyner 2569cf1841cSEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, 2579cf1841cSEric Joyner ice_aqc_opc_set_vlan_mode_parameters); 2589cf1841cSEric Joyner desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD); 2599cf1841cSEric Joyner 2609cf1841cSEric Joyner return ice_aq_send_cmd(hw, &desc, set_params, sizeof(*set_params), 2619cf1841cSEric Joyner NULL); 2629cf1841cSEric Joyner } 2639cf1841cSEric Joyner 2649cf1841cSEric Joyner /** 265d08b8680SEric Joyner * ice_set_svm - set single VLAN mode 266d08b8680SEric Joyner * @hw: pointer to the HW structure 267d08b8680SEric Joyner */ 268*f2635e84SEric Joyner static int ice_set_svm(struct ice_hw *hw) 269d08b8680SEric Joyner { 2709cf1841cSEric Joyner struct ice_aqc_set_vlan_mode *set_params; 271*f2635e84SEric Joyner int status; 272d08b8680SEric Joyner 2739cf1841cSEric Joyner status = ice_aq_set_port_params(hw->port_info, 0, false, false, false, NULL); 2749cf1841cSEric Joyner if (status) { 2759cf1841cSEric Joyner ice_debug(hw, ICE_DBG_INIT, "Failed to set port parameters for single VLAN mode\n"); 2769cf1841cSEric Joyner return status; 277d08b8680SEric Joyner } 278d08b8680SEric Joyner 2799cf1841cSEric Joyner set_params = (struct ice_aqc_set_vlan_mode *) 2809cf1841cSEric Joyner ice_malloc(hw, sizeof(*set_params)); 2819cf1841cSEric Joyner if (!set_params) 2829cf1841cSEric Joyner return ICE_ERR_NO_MEMORY; 2839cf1841cSEric Joyner 2849cf1841cSEric Joyner /* default configuration for SVM configurations */ 2859cf1841cSEric Joyner set_params->l2tag_prio_tagging = ICE_AQ_VLAN_PRIO_TAG_INNER_CTAG; 2869cf1841cSEric Joyner set_params->rdma_packet = ICE_AQ_SVM_VLAN_RDMA_PKT_FLAG_SETTING; 2879cf1841cSEric Joyner set_params->mng_vlan_prot_id = ICE_AQ_VLAN_MNG_PROTOCOL_ID_INNER; 2889cf1841cSEric Joyner 2899cf1841cSEric Joyner status = ice_aq_set_vlan_mode(hw, set_params); 2909cf1841cSEric Joyner if (status) 2919cf1841cSEric Joyner ice_debug(hw, ICE_DBG_INIT, "Failed to configure port in single VLAN mode\n"); 2929cf1841cSEric Joyner 2939cf1841cSEric Joyner ice_free(hw, set_params); 2949cf1841cSEric Joyner return status; 295d08b8680SEric Joyner } 296d08b8680SEric Joyner 297d08b8680SEric Joyner /** 298d08b8680SEric Joyner * ice_set_vlan_mode 299d08b8680SEric Joyner * @hw: pointer to the HW structure 300d08b8680SEric Joyner */ 301*f2635e84SEric Joyner int ice_set_vlan_mode(struct ice_hw *hw) 302d08b8680SEric Joyner { 3039cf1841cSEric Joyner if (!ice_is_dvm_supported(hw)) 304*f2635e84SEric Joyner return 0; 305d08b8680SEric Joyner 3069cf1841cSEric Joyner return ice_set_svm(hw); 307d08b8680SEric Joyner } 30856429daeSEric Joyner 30956429daeSEric Joyner /** 31056429daeSEric Joyner * ice_post_pkg_dwnld_vlan_mode_cfg - configure VLAN mode after DDP download 31156429daeSEric Joyner * @hw: pointer to the HW structure 31256429daeSEric Joyner * 31356429daeSEric Joyner * This function is meant to configure any VLAN mode specific functionality 31456429daeSEric Joyner * after the global configuration lock has been released and the DDP has been 31556429daeSEric Joyner * downloaded. 31656429daeSEric Joyner * 31756429daeSEric Joyner * Since only one PF downloads the DDP and configures the VLAN mode there needs 31856429daeSEric Joyner * to be a way to configure the other PFs after the DDP has been downloaded and 31956429daeSEric Joyner * the global configuration lock has been released. All such code should go in 32056429daeSEric Joyner * this function. 32156429daeSEric Joyner */ 32256429daeSEric Joyner void ice_post_pkg_dwnld_vlan_mode_cfg(struct ice_hw *hw) 32356429daeSEric Joyner { 32456429daeSEric Joyner ice_cache_vlan_mode(hw); 32556429daeSEric Joyner } 326