1 /* SPDX-License-Identifier: BSD-3-Clause */ 2 /* Copyright (c) 2023, Intel Corporation 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * 3. Neither the name of the Intel Corporation nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 /*$FreeBSD$*/ 32 33 #include "ice_common.h" 34 35 #include "ice_ddp_common.h" 36 /** 37 * ice_pkg_get_supported_vlan_mode - chk if DDP supports Double VLAN mode (DVM) 38 * @hw: pointer to the HW struct 39 * @dvm: output variable to determine if DDP supports DVM(true) or SVM(false) 40 */ 41 static enum ice_status 42 ice_pkg_get_supported_vlan_mode(struct ice_hw *hw, bool *dvm) 43 { 44 u16 meta_init_size = sizeof(struct ice_meta_init_section); 45 struct ice_meta_init_section *sect; 46 struct ice_buf_build *bld; 47 enum ice_status status; 48 49 /* if anything fails, we assume there is no DVM support */ 50 *dvm = false; 51 52 bld = ice_pkg_buf_alloc_single_section(hw, 53 ICE_SID_RXPARSER_METADATA_INIT, 54 meta_init_size, (void **)§); 55 if (!bld) 56 return ICE_ERR_NO_MEMORY; 57 58 /* only need to read a single section */ 59 sect->count = CPU_TO_LE16(1); 60 sect->offset = CPU_TO_LE16(ICE_META_VLAN_MODE_ENTRY); 61 62 status = ice_aq_upload_section(hw, 63 (struct ice_buf_hdr *)ice_pkg_buf(bld), 64 ICE_PKG_BUF_SIZE, NULL); 65 if (!status) { 66 ice_declare_bitmap(entry, ICE_META_INIT_BITS); 67 u32 arr[ICE_META_INIT_DW_CNT]; 68 u16 i; 69 70 /* convert to host bitmap format */ 71 for (i = 0; i < ICE_META_INIT_DW_CNT; i++) 72 arr[i] = LE32_TO_CPU(sect->entry[0].bm[i]); 73 74 ice_bitmap_from_array32(entry, arr, (u16)ICE_META_INIT_BITS); 75 76 /* check if DVM is supported */ 77 *dvm = ice_is_bit_set(entry, ICE_META_VLAN_MODE_BIT); 78 } 79 80 ice_pkg_buf_free(hw, bld); 81 82 return status; 83 } 84 85 /** 86 * ice_aq_get_vlan_mode - get the VLAN mode of the device 87 * @hw: pointer to the HW structure 88 * @get_params: structure FW fills in based on the current VLAN mode config 89 * 90 * Get VLAN Mode Parameters (0x020D) 91 */ 92 static enum ice_status 93 ice_aq_get_vlan_mode(struct ice_hw *hw, 94 struct ice_aqc_get_vlan_mode *get_params) 95 { 96 struct ice_aq_desc desc; 97 98 if (!get_params) 99 return ICE_ERR_PARAM; 100 101 ice_fill_dflt_direct_cmd_desc(&desc, 102 ice_aqc_opc_get_vlan_mode_parameters); 103 104 return ice_aq_send_cmd(hw, &desc, get_params, sizeof(*get_params), 105 NULL); 106 } 107 108 /** 109 * ice_aq_is_dvm_ena - query FW to check if double VLAN mode is enabled 110 * @hw: pointer to the HW structure 111 * 112 * Returns true if the hardware/firmware is configured in double VLAN mode, 113 * else return false signaling that the hardware/firmware is configured in 114 * single VLAN mode. 115 * 116 * Also, return false if this call fails for any reason (i.e. firmware doesn't 117 * support this AQ call). 118 */ 119 static bool ice_aq_is_dvm_ena(struct ice_hw *hw) 120 { 121 struct ice_aqc_get_vlan_mode get_params = { 0 }; 122 enum ice_status status; 123 124 status = ice_aq_get_vlan_mode(hw, &get_params); 125 if (status) { 126 ice_debug(hw, ICE_DBG_AQ, "Failed to get VLAN mode, status %d\n", 127 status); 128 return false; 129 } 130 131 return (get_params.vlan_mode & ICE_AQ_VLAN_MODE_DVM_ENA); 132 } 133 134 /** 135 * ice_is_dvm_ena - check if double VLAN mode is enabled 136 * @hw: pointer to the HW structure 137 * 138 * The device is configured in single or double VLAN mode on initialization and 139 * this cannot be dynamically changed during runtime. Based on this there is no 140 * need to make an AQ call every time the driver needs to know the VLAN mode. 141 * Instead, use the cached VLAN mode. 142 */ 143 bool ice_is_dvm_ena(struct ice_hw *hw) 144 { 145 return hw->dvm_ena; 146 } 147 148 /** 149 * ice_cache_vlan_mode - cache VLAN mode after DDP is downloaded 150 * @hw: pointer to the HW structure 151 * 152 * This is only called after downloading the DDP and after the global 153 * configuration lock has been released because all ports on a device need to 154 * cache the VLAN mode. 155 */ 156 static void ice_cache_vlan_mode(struct ice_hw *hw) 157 { 158 hw->dvm_ena = ice_aq_is_dvm_ena(hw) ? true : false; 159 } 160 161 /** 162 * ice_pkg_supports_dvm - find out if DDP supports DVM 163 * @hw: pointer to the HW structure 164 */ 165 static bool ice_pkg_supports_dvm(struct ice_hw *hw) 166 { 167 enum ice_status status; 168 bool pkg_supports_dvm; 169 170 status = ice_pkg_get_supported_vlan_mode(hw, &pkg_supports_dvm); 171 if (status) { 172 ice_debug(hw, ICE_DBG_PKG, "Failed to get supported VLAN mode, status %d\n", 173 status); 174 return false; 175 } 176 177 return pkg_supports_dvm; 178 } 179 180 /** 181 * ice_fw_supports_dvm - find out if FW supports DVM 182 * @hw: pointer to the HW structure 183 */ 184 static bool ice_fw_supports_dvm(struct ice_hw *hw) 185 { 186 struct ice_aqc_get_vlan_mode get_vlan_mode = { 0 }; 187 enum ice_status status; 188 189 /* If firmware returns success, then it supports DVM, else it only 190 * supports SVM 191 */ 192 status = ice_aq_get_vlan_mode(hw, &get_vlan_mode); 193 if (status) { 194 ice_debug(hw, ICE_DBG_NVM, "Failed to get VLAN mode, status %d\n", 195 status); 196 return false; 197 } 198 199 return true; 200 } 201 202 /** 203 * ice_is_dvm_supported - check if Double VLAN Mode is supported 204 * @hw: pointer to the hardware structure 205 * 206 * Returns true if Double VLAN Mode (DVM) is supported and false if only Single 207 * VLAN Mode (SVM) is supported. In order for DVM to be supported the DDP and 208 * firmware must support it, otherwise only SVM is supported. This function 209 * should only be called while the global config lock is held and after the 210 * package has been successfully downloaded. 211 */ 212 static bool ice_is_dvm_supported(struct ice_hw *hw) 213 { 214 if (!ice_pkg_supports_dvm(hw)) { 215 ice_debug(hw, ICE_DBG_PKG, "DDP doesn't support DVM\n"); 216 return false; 217 } 218 219 if (!ice_fw_supports_dvm(hw)) { 220 ice_debug(hw, ICE_DBG_PKG, "FW doesn't support DVM\n"); 221 return false; 222 } 223 224 return true; 225 } 226 227 /** 228 * ice_aq_set_vlan_mode - set the VLAN mode of the device 229 * @hw: pointer to the HW structure 230 * @set_params: requested VLAN mode configuration 231 * 232 * Set VLAN Mode Parameters (0x020C) 233 */ 234 static enum ice_status 235 ice_aq_set_vlan_mode(struct ice_hw *hw, 236 struct ice_aqc_set_vlan_mode *set_params) 237 { 238 u8 rdma_packet, mng_vlan_prot_id; 239 struct ice_aq_desc desc; 240 241 if (!set_params) 242 return ICE_ERR_PARAM; 243 244 if (set_params->l2tag_prio_tagging > ICE_AQ_VLAN_PRIO_TAG_MAX) 245 return ICE_ERR_PARAM; 246 247 rdma_packet = set_params->rdma_packet; 248 if (rdma_packet != ICE_AQ_SVM_VLAN_RDMA_PKT_FLAG_SETTING && 249 rdma_packet != ICE_AQ_DVM_VLAN_RDMA_PKT_FLAG_SETTING) 250 return ICE_ERR_PARAM; 251 252 mng_vlan_prot_id = set_params->mng_vlan_prot_id; 253 if (mng_vlan_prot_id != ICE_AQ_VLAN_MNG_PROTOCOL_ID_OUTER && 254 mng_vlan_prot_id != ICE_AQ_VLAN_MNG_PROTOCOL_ID_INNER) 255 return ICE_ERR_PARAM; 256 257 ice_fill_dflt_direct_cmd_desc(&desc, 258 ice_aqc_opc_set_vlan_mode_parameters); 259 desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD); 260 261 return ice_aq_send_cmd(hw, &desc, set_params, sizeof(*set_params), 262 NULL); 263 } 264 265 /** 266 * ice_set_svm - set single VLAN mode 267 * @hw: pointer to the HW structure 268 */ 269 static enum ice_status ice_set_svm(struct ice_hw *hw) 270 { 271 struct ice_aqc_set_vlan_mode *set_params; 272 enum ice_status status; 273 274 status = ice_aq_set_port_params(hw->port_info, 0, false, false, false, NULL); 275 if (status) { 276 ice_debug(hw, ICE_DBG_INIT, "Failed to set port parameters for single VLAN mode\n"); 277 return status; 278 } 279 280 set_params = (struct ice_aqc_set_vlan_mode *) 281 ice_malloc(hw, sizeof(*set_params)); 282 if (!set_params) 283 return ICE_ERR_NO_MEMORY; 284 285 /* default configuration for SVM configurations */ 286 set_params->l2tag_prio_tagging = ICE_AQ_VLAN_PRIO_TAG_INNER_CTAG; 287 set_params->rdma_packet = ICE_AQ_SVM_VLAN_RDMA_PKT_FLAG_SETTING; 288 set_params->mng_vlan_prot_id = ICE_AQ_VLAN_MNG_PROTOCOL_ID_INNER; 289 290 status = ice_aq_set_vlan_mode(hw, set_params); 291 if (status) 292 ice_debug(hw, ICE_DBG_INIT, "Failed to configure port in single VLAN mode\n"); 293 294 ice_free(hw, set_params); 295 return status; 296 } 297 298 /** 299 * ice_set_vlan_mode 300 * @hw: pointer to the HW structure 301 */ 302 enum ice_status ice_set_vlan_mode(struct ice_hw *hw) 303 { 304 if (!ice_is_dvm_supported(hw)) 305 return ICE_SUCCESS; 306 307 return ice_set_svm(hw); 308 } 309 310 /** 311 * ice_post_pkg_dwnld_vlan_mode_cfg - configure VLAN mode after DDP download 312 * @hw: pointer to the HW structure 313 * 314 * This function is meant to configure any VLAN mode specific functionality 315 * after the global configuration lock has been released and the DDP has been 316 * downloaded. 317 * 318 * Since only one PF downloads the DDP and configures the VLAN mode there needs 319 * to be a way to configure the other PFs after the DDP has been downloaded and 320 * the global configuration lock has been released. All such code should go in 321 * this function. 322 */ 323 void ice_post_pkg_dwnld_vlan_mode_cfg(struct ice_hw *hw) 324 { 325 ice_cache_vlan_mode(hw); 326 } 327