1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2001-2021 Intel Corporation 3 */ 4 5 #include "ice_vlan_mode.h" 6 #include "ice_common.h" 7 8 /** 9 * ice_pkg_supports_dvm - determine if DDP supports Double VLAN mode (DVM) 10 * @hw: pointer to the HW struct 11 * @dvm: output variable to determine if DDP supports DVM(true) or SVM(false) 12 */ 13 static enum ice_status 14 ice_pkg_get_supported_vlan_mode(struct ice_hw *hw, bool *dvm) 15 { 16 u16 meta_init_size = sizeof(struct ice_meta_init_section); 17 struct ice_meta_init_section *sect; 18 struct ice_buf_build *bld; 19 enum ice_status status; 20 21 /* if anything fails, we assume there is no DVM support */ 22 *dvm = false; 23 24 bld = ice_pkg_buf_alloc_single_section(hw, 25 ICE_SID_RXPARSER_METADATA_INIT, 26 meta_init_size, (void **)§); 27 if (!bld) 28 return ICE_ERR_NO_MEMORY; 29 30 /* only need to read a single section */ 31 sect->count = CPU_TO_LE16(1); 32 sect->offset = CPU_TO_LE16(ICE_META_VLAN_MODE_ENTRY); 33 34 status = ice_aq_upload_section(hw, 35 (struct ice_buf_hdr *)ice_pkg_buf(bld), 36 ICE_PKG_BUF_SIZE, NULL); 37 if (!status) { 38 ice_declare_bitmap(entry, ICE_META_INIT_BITS); 39 u32 arr[ICE_META_INIT_DW_CNT]; 40 u16 i; 41 42 /* convert to host bitmap format */ 43 for (i = 0; i < ICE_META_INIT_DW_CNT; i++) 44 arr[i] = LE32_TO_CPU(sect->entry[0].bm[i]); 45 46 ice_bitmap_from_array32(entry, arr, (u16)ICE_META_INIT_BITS); 47 48 /* check if DVM is supported */ 49 *dvm = ice_is_bit_set(entry, ICE_META_VLAN_MODE_BIT); 50 } 51 52 ice_pkg_buf_free(hw, bld); 53 54 return status; 55 } 56 57 /** 58 * ice_aq_get_vlan_mode - get the VLAN mode of the device 59 * @hw: pointer to the HW structure 60 * @get_params: structure FW fills in based on the current VLAN mode config 61 * 62 * Get VLAN Mode Parameters (0x020D) 63 */ 64 static enum ice_status 65 ice_aq_get_vlan_mode(struct ice_hw *hw, 66 struct ice_aqc_get_vlan_mode *get_params) 67 { 68 struct ice_aq_desc desc; 69 70 if (!get_params) 71 return ICE_ERR_PARAM; 72 73 ice_fill_dflt_direct_cmd_desc(&desc, 74 ice_aqc_opc_get_vlan_mode_parameters); 75 76 return ice_aq_send_cmd(hw, &desc, get_params, sizeof(*get_params), 77 NULL); 78 } 79 80 /** 81 * ice_aq_is_dvm_ena - query FW to check if double VLAN mode is enabled 82 * @hw: pointer to the HW structure 83 * 84 * Returns true if the hardware/firmware is configured in double VLAN mode, 85 * else return false signaling that the hardware/firmware is configured in 86 * single VLAN mode. 87 * 88 * Also, return false if this call fails for any reason (i.e. firmware doesn't 89 * support this AQ call). 90 */ 91 static bool ice_aq_is_dvm_ena(struct ice_hw *hw) 92 { 93 struct ice_aqc_get_vlan_mode get_params = { 0 }; 94 enum ice_status status; 95 96 status = ice_aq_get_vlan_mode(hw, &get_params); 97 if (status) { 98 ice_debug(hw, ICE_DBG_AQ, "Failed to get VLAN mode, status %d\n", 99 status); 100 return false; 101 } 102 103 return (get_params.vlan_mode & ICE_AQ_VLAN_MODE_DVM_ENA); 104 } 105 106 /** 107 * ice_is_dvm_ena - check if double VLAN mode is enabled 108 * @hw: pointer to the HW structure 109 * 110 * The device is configured in single or double VLAN mode on initialization and 111 * this cannot be dynamically changed during runtime. Based on this there is no 112 * need to make an AQ call every time the driver needs to know the VLAN mode. 113 * Instead, use the cached VLAN mode. 114 */ 115 bool ice_is_dvm_ena(struct ice_hw *hw) 116 { 117 return hw->dvm_ena; 118 } 119 120 /** 121 * ice_cache_vlan_mode - cache VLAN mode after DDP is downloaded 122 * @hw: pointer to the HW structure 123 * 124 * This is only called after downloading the DDP and after the global 125 * configuration lock has been released because all ports on a device need to 126 * cache the VLAN mode. 127 */ 128 void ice_cache_vlan_mode(struct ice_hw *hw) 129 { 130 hw->dvm_ena = ice_aq_is_dvm_ena(hw) ? true : false; 131 } 132 133 /** 134 * ice_is_dvm_supported - check if Double VLAN Mode is supported 135 * @hw: pointer to the hardware structure 136 * 137 * Returns true if Double VLAN Mode (DVM) is supported and false if only Single 138 * VLAN Mode (SVM) is supported. In order for DVM to be supported the DDP and 139 * firmware must support it, otherwise only SVM is supported. This function 140 * should only be called while the global config lock is held and after the 141 * package has been successfully downloaded. 142 */ 143 static bool ice_is_dvm_supported(struct ice_hw *hw) 144 { 145 struct ice_aqc_get_vlan_mode get_vlan_mode = { 0 }; 146 enum ice_status status; 147 bool pkg_supports_dvm; 148 149 status = ice_pkg_get_supported_vlan_mode(hw, &pkg_supports_dvm); 150 if (status) { 151 ice_debug(hw, ICE_DBG_PKG, "Failed to get supported VLAN mode, status %d\n", 152 status); 153 return false; 154 } 155 156 if (!pkg_supports_dvm) 157 return false; 158 159 /* If firmware returns success, then it supports DVM, else it only 160 * supports SVM 161 */ 162 status = ice_aq_get_vlan_mode(hw, &get_vlan_mode); 163 if (status) { 164 ice_debug(hw, ICE_DBG_NVM, "Failed to get VLAN mode, status %d\n", 165 status); 166 return false; 167 } 168 169 return true; 170 } 171 172 #define ICE_EXTERNAL_VLAN_ID_FV_IDX 11 173 #define ICE_SW_LKUP_VLAN_LOC_LKUP_IDX 1 174 #define ICE_SW_LKUP_VLAN_PKT_FLAGS_LKUP_IDX 2 175 #define ICE_SW_LKUP_PROMISC_VLAN_LOC_LKUP_IDX 2 176 #define ICE_PKT_FLAGS_0_TO_15_FV_IDX 1 177 #define ICE_PKT_FLAGS_0_TO_15_VLAN_FLAGS_MASK 0xD000 178 static struct ice_update_recipe_lkup_idx_params ice_dvm_dflt_recipes[] = { 179 { 180 /* Update recipe ICE_SW_LKUP_VLAN to filter based on the 181 * outer/single VLAN in DVM 182 */ 183 .rid = ICE_SW_LKUP_VLAN, 184 .fv_idx = ICE_EXTERNAL_VLAN_ID_FV_IDX, 185 .ignore_valid = true, 186 .mask = 0, 187 .mask_valid = false, /* use pre-existing mask */ 188 .lkup_idx = ICE_SW_LKUP_VLAN_LOC_LKUP_IDX, 189 }, 190 { 191 /* Update recipe ICE_SW_LKUP_VLAN to filter based on the VLAN 192 * packet flags to support VLAN filtering on multiple VLAN 193 * ethertypes (i.e. 0x8100 and 0x88a8) in DVM 194 */ 195 .rid = ICE_SW_LKUP_VLAN, 196 .fv_idx = ICE_PKT_FLAGS_0_TO_15_FV_IDX, 197 .ignore_valid = false, 198 .mask = ICE_PKT_FLAGS_0_TO_15_VLAN_FLAGS_MASK, 199 .mask_valid = true, 200 .lkup_idx = ICE_SW_LKUP_VLAN_PKT_FLAGS_LKUP_IDX, 201 }, 202 { 203 /* Update recipe ICE_SW_LKUP_PROMISC_VLAN to filter based on the 204 * outer/single VLAN in DVM 205 */ 206 .rid = ICE_SW_LKUP_PROMISC_VLAN, 207 .fv_idx = ICE_EXTERNAL_VLAN_ID_FV_IDX, 208 .ignore_valid = true, 209 .mask = 0, 210 .mask_valid = false, /* use pre-existing mask */ 211 .lkup_idx = ICE_SW_LKUP_PROMISC_VLAN_LOC_LKUP_IDX, 212 }, 213 }; 214 215 /** 216 * ice_dvm_update_dflt_recipes - update default switch recipes in DVM 217 * @hw: hardware structure used to update the recipes 218 */ 219 static enum ice_status ice_dvm_update_dflt_recipes(struct ice_hw *hw) 220 { 221 unsigned long i; 222 223 for (i = 0; i < ARRAY_SIZE(ice_dvm_dflt_recipes); i++) { 224 struct ice_update_recipe_lkup_idx_params *params; 225 enum ice_status status; 226 227 params = &ice_dvm_dflt_recipes[i]; 228 229 status = ice_update_recipe_lkup_idx(hw, params); 230 if (status) { 231 ice_debug(hw, ICE_DBG_INIT, "Failed to update RID %d lkup_idx %d fv_idx %d mask_valid %s mask 0x%04x\n", 232 params->rid, params->lkup_idx, params->fv_idx, 233 params->mask_valid ? "true" : "false", 234 params->mask); 235 return status; 236 } 237 } 238 239 return ICE_SUCCESS; 240 } 241 242 /** 243 * ice_aq_set_vlan_mode - set the VLAN mode of the device 244 * @hw: pointer to the HW structure 245 * @set_params: requested VLAN mode configuration 246 * 247 * Set VLAN Mode Parameters (0x020C) 248 */ 249 static enum ice_status 250 ice_aq_set_vlan_mode(struct ice_hw *hw, 251 struct ice_aqc_set_vlan_mode *set_params) 252 { 253 u8 rdma_packet, mng_vlan_prot_id; 254 struct ice_aq_desc desc; 255 256 if (!set_params) 257 return ICE_ERR_PARAM; 258 259 if (set_params->l2tag_prio_tagging > ICE_AQ_VLAN_PRIO_TAG_MAX) 260 return ICE_ERR_PARAM; 261 262 rdma_packet = set_params->rdma_packet; 263 if (rdma_packet != ICE_AQ_SVM_VLAN_RDMA_PKT_FLAG_SETTING && 264 rdma_packet != ICE_AQ_DVM_VLAN_RDMA_PKT_FLAG_SETTING) 265 return ICE_ERR_PARAM; 266 267 mng_vlan_prot_id = set_params->mng_vlan_prot_id; 268 if (mng_vlan_prot_id != ICE_AQ_VLAN_MNG_PROTOCOL_ID_OUTER && 269 mng_vlan_prot_id != ICE_AQ_VLAN_MNG_PROTOCOL_ID_INNER) 270 return ICE_ERR_PARAM; 271 272 ice_fill_dflt_direct_cmd_desc(&desc, 273 ice_aqc_opc_set_vlan_mode_parameters); 274 desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD); 275 276 return ice_aq_send_cmd(hw, &desc, set_params, sizeof(*set_params), 277 NULL); 278 } 279 280 /** 281 * ice_set_dvm - sets up software and hardware for double VLAN mode 282 * @hw: pointer to the hardware structure 283 */ 284 static enum ice_status ice_set_dvm(struct ice_hw *hw) 285 { 286 struct ice_aqc_set_vlan_mode params = { 0 }; 287 enum ice_status status; 288 289 params.l2tag_prio_tagging = ICE_AQ_VLAN_PRIO_TAG_OUTER_CTAG; 290 params.rdma_packet = ICE_AQ_DVM_VLAN_RDMA_PKT_FLAG_SETTING; 291 params.mng_vlan_prot_id = ICE_AQ_VLAN_MNG_PROTOCOL_ID_OUTER; 292 293 status = ice_aq_set_vlan_mode(hw, ¶ms); 294 if (status) { 295 ice_debug(hw, ICE_DBG_INIT, "Failed to set double VLAN mode parameters, status %d\n", 296 status); 297 return status; 298 } 299 300 status = ice_dvm_update_dflt_recipes(hw); 301 if (status) { 302 ice_debug(hw, ICE_DBG_INIT, "Failed to update default recipes for double VLAN mode, status %d\n", 303 status); 304 return status; 305 } 306 307 status = ice_aq_set_port_params(hw->port_info, 0, false, false, true, 308 NULL); 309 if (status) { 310 ice_debug(hw, ICE_DBG_INIT, "Failed to set port in double VLAN mode, status %d\n", 311 status); 312 return status; 313 } 314 315 status = ice_set_dvm_boost_entries(hw); 316 if (status) { 317 ice_debug(hw, ICE_DBG_INIT, "Failed to set boost TCAM entries for double VLAN mode, status %d\n", 318 status); 319 return status; 320 } 321 322 return ICE_SUCCESS; 323 } 324 325 /** 326 * ice_set_svm - set single VLAN mode 327 * @hw: pointer to the HW structure 328 */ 329 static enum ice_status ice_set_svm(struct ice_hw *hw) 330 { 331 struct ice_aqc_set_vlan_mode *set_params; 332 enum ice_status status; 333 334 status = ice_aq_set_port_params(hw->port_info, 0, false, false, false, NULL); 335 if (status) { 336 ice_debug(hw, ICE_DBG_INIT, "Failed to set port parameters for single VLAN mode\n"); 337 return status; 338 } 339 340 set_params = (struct ice_aqc_set_vlan_mode *) 341 ice_malloc(hw, sizeof(*set_params)); 342 if (!set_params) 343 return ICE_ERR_NO_MEMORY; 344 345 /* default configuration for SVM configurations */ 346 set_params->l2tag_prio_tagging = ICE_AQ_VLAN_PRIO_TAG_INNER_CTAG; 347 set_params->rdma_packet = ICE_AQ_SVM_VLAN_RDMA_PKT_FLAG_SETTING; 348 set_params->mng_vlan_prot_id = ICE_AQ_VLAN_MNG_PROTOCOL_ID_INNER; 349 350 status = ice_aq_set_vlan_mode(hw, set_params); 351 if (status) 352 ice_debug(hw, ICE_DBG_INIT, "Failed to configure port in single VLAN mode\n"); 353 354 ice_free(hw, set_params); 355 return status; 356 } 357 358 /** 359 * ice_set_vlan_mode 360 * @hw: pointer to the HW structure 361 */ 362 enum ice_status ice_set_vlan_mode(struct ice_hw *hw) 363 { 364 /* DCF only has the ability to query the VLAN mode. Setting the VLAN 365 * mode is done by the PF. 366 */ 367 if (hw->dcf_enabled) 368 return ICE_SUCCESS; 369 370 if (!ice_is_dvm_supported(hw)) 371 return ICE_SUCCESS; 372 373 if (!ice_set_dvm(hw)) 374 return ICE_SUCCESS; 375 376 return ice_set_svm(hw); 377 } 378