1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (C) 2019-2021, Intel Corporation. */ 3 4 #include "ice_common.h" 5 6 /** 7 * ice_pkg_get_supported_vlan_mode - determine if DDP supports Double VLAN mode 8 * @hw: pointer to the HW struct 9 * @dvm: output variable to determine if DDP supports DVM(true) or SVM(false) 10 */ 11 static int 12 ice_pkg_get_supported_vlan_mode(struct ice_hw *hw, bool *dvm) 13 { 14 u16 meta_init_size = sizeof(struct ice_meta_init_section); 15 struct ice_meta_init_section *sect; 16 struct ice_buf_build *bld; 17 int status; 18 19 /* if anything fails, we assume there is no DVM support */ 20 *dvm = false; 21 22 bld = ice_pkg_buf_alloc_single_section(hw, 23 ICE_SID_RXPARSER_METADATA_INIT, 24 meta_init_size, (void **)§); 25 if (!bld) 26 return -ENOMEM; 27 28 /* only need to read a single section */ 29 sect->count = cpu_to_le16(1); 30 sect->offset = cpu_to_le16(ICE_META_VLAN_MODE_ENTRY); 31 32 status = ice_aq_upload_section(hw, 33 (struct ice_buf_hdr *)ice_pkg_buf(bld), 34 ICE_PKG_BUF_SIZE, NULL); 35 if (!status) { 36 DECLARE_BITMAP(entry, ICE_META_INIT_BITS); 37 u32 arr[ICE_META_INIT_DW_CNT]; 38 u16 i; 39 40 /* convert to host bitmap format */ 41 for (i = 0; i < ICE_META_INIT_DW_CNT; i++) 42 arr[i] = le32_to_cpu(sect->entry.bm[i]); 43 44 bitmap_from_arr32(entry, arr, (u16)ICE_META_INIT_BITS); 45 46 /* check if DVM is supported */ 47 *dvm = test_bit(ICE_META_VLAN_MODE_BIT, entry); 48 } 49 50 ice_pkg_buf_free(hw, bld); 51 52 return status; 53 } 54 55 /** 56 * ice_aq_get_vlan_mode - get the VLAN mode of the device 57 * @hw: pointer to the HW structure 58 * @get_params: structure FW fills in based on the current VLAN mode config 59 * 60 * Get VLAN Mode Parameters (0x020D) 61 */ 62 static int 63 ice_aq_get_vlan_mode(struct ice_hw *hw, 64 struct ice_aqc_get_vlan_mode *get_params) 65 { 66 struct ice_aq_desc desc; 67 68 if (!get_params) 69 return -EINVAL; 70 71 ice_fill_dflt_direct_cmd_desc(&desc, 72 ice_aqc_opc_get_vlan_mode_parameters); 73 74 return ice_aq_send_cmd(hw, &desc, get_params, sizeof(*get_params), 75 NULL); 76 } 77 78 /** 79 * ice_aq_is_dvm_ena - query FW to check if double VLAN mode is enabled 80 * @hw: pointer to the HW structure 81 * 82 * Returns true if the hardware/firmware is configured in double VLAN mode, 83 * else return false signaling that the hardware/firmware is configured in 84 * single VLAN mode. 85 * 86 * Also, return false if this call fails for any reason (i.e. firmware doesn't 87 * support this AQ call). 88 */ 89 static bool ice_aq_is_dvm_ena(struct ice_hw *hw) 90 { 91 struct ice_aqc_get_vlan_mode get_params = { 0 }; 92 int status; 93 94 status = ice_aq_get_vlan_mode(hw, &get_params); 95 if (status) { 96 ice_debug(hw, ICE_DBG_AQ, "Failed to get VLAN mode, status %d\n", 97 status); 98 return false; 99 } 100 101 return (get_params.vlan_mode & ICE_AQ_VLAN_MODE_DVM_ENA); 102 } 103 104 /** 105 * ice_is_dvm_ena - check if double VLAN mode is enabled 106 * @hw: pointer to the HW structure 107 * 108 * The device is configured in single or double VLAN mode on initialization and 109 * this cannot be dynamically changed during runtime. Based on this there is no 110 * need to make an AQ call every time the driver needs to know the VLAN mode. 111 * Instead, use the cached VLAN mode. 112 */ 113 bool ice_is_dvm_ena(struct ice_hw *hw) 114 { 115 return hw->dvm_ena; 116 } 117 118 /** 119 * ice_cache_vlan_mode - cache VLAN mode after DDP is downloaded 120 * @hw: pointer to the HW structure 121 * 122 * This is only called after downloading the DDP and after the global 123 * configuration lock has been released because all ports on a device need to 124 * cache the VLAN mode. 125 */ 126 static void ice_cache_vlan_mode(struct ice_hw *hw) 127 { 128 hw->dvm_ena = ice_aq_is_dvm_ena(hw) ? true : false; 129 } 130 131 /** 132 * ice_pkg_supports_dvm - find out if DDP supports DVM 133 * @hw: pointer to the HW structure 134 */ 135 static bool ice_pkg_supports_dvm(struct ice_hw *hw) 136 { 137 bool pkg_supports_dvm; 138 int status; 139 140 status = ice_pkg_get_supported_vlan_mode(hw, &pkg_supports_dvm); 141 if (status) { 142 ice_debug(hw, ICE_DBG_PKG, "Failed to get supported VLAN mode, status %d\n", 143 status); 144 return false; 145 } 146 147 return pkg_supports_dvm; 148 } 149 150 /** 151 * ice_fw_supports_dvm - find out if FW supports DVM 152 * @hw: pointer to the HW structure 153 */ 154 static bool ice_fw_supports_dvm(struct ice_hw *hw) 155 { 156 struct ice_aqc_get_vlan_mode get_vlan_mode = { 0 }; 157 int status; 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 /** 173 * ice_is_dvm_supported - check if Double VLAN Mode is supported 174 * @hw: pointer to the hardware structure 175 * 176 * Returns true if Double VLAN Mode (DVM) is supported and false if only Single 177 * VLAN Mode (SVM) is supported. In order for DVM to be supported the DDP and 178 * firmware must support it, otherwise only SVM is supported. This function 179 * should only be called while the global config lock is held and after the 180 * package has been successfully downloaded. 181 */ 182 static bool ice_is_dvm_supported(struct ice_hw *hw) 183 { 184 if (!ice_pkg_supports_dvm(hw)) { 185 ice_debug(hw, ICE_DBG_PKG, "DDP doesn't support DVM\n"); 186 return false; 187 } 188 189 if (!ice_fw_supports_dvm(hw)) { 190 ice_debug(hw, ICE_DBG_PKG, "FW doesn't support DVM\n"); 191 return false; 192 } 193 194 return true; 195 } 196 197 #define ICE_EXTERNAL_VLAN_ID_FV_IDX 11 198 #define ICE_SW_LKUP_VLAN_LOC_LKUP_IDX 1 199 #define ICE_SW_LKUP_VLAN_PKT_FLAGS_LKUP_IDX 2 200 #define ICE_SW_LKUP_PROMISC_VLAN_LOC_LKUP_IDX 2 201 #define ICE_PKT_FLAGS_0_TO_15_FV_IDX 1 202 static struct ice_update_recipe_lkup_idx_params ice_dvm_dflt_recipes[] = { 203 { 204 /* Update recipe ICE_SW_LKUP_VLAN to filter based on the 205 * outer/single VLAN in DVM 206 */ 207 .rid = ICE_SW_LKUP_VLAN, 208 .fv_idx = ICE_EXTERNAL_VLAN_ID_FV_IDX, 209 .ignore_valid = true, 210 .mask = 0, 211 .mask_valid = false, /* use pre-existing mask */ 212 .lkup_idx = ICE_SW_LKUP_VLAN_LOC_LKUP_IDX, 213 }, 214 { 215 /* Update recipe ICE_SW_LKUP_VLAN to filter based on the VLAN 216 * packet flags to support VLAN filtering on multiple VLAN 217 * ethertypes (i.e. 0x8100 and 0x88a8) in DVM 218 */ 219 .rid = ICE_SW_LKUP_VLAN, 220 .fv_idx = ICE_PKT_FLAGS_0_TO_15_FV_IDX, 221 .ignore_valid = false, 222 .mask = ICE_PKT_VLAN_MASK, 223 .mask_valid = true, 224 .lkup_idx = ICE_SW_LKUP_VLAN_PKT_FLAGS_LKUP_IDX, 225 }, 226 { 227 /* Update recipe ICE_SW_LKUP_PROMISC_VLAN to filter based on the 228 * outer/single VLAN in DVM 229 */ 230 .rid = ICE_SW_LKUP_PROMISC_VLAN, 231 .fv_idx = ICE_EXTERNAL_VLAN_ID_FV_IDX, 232 .ignore_valid = true, 233 .mask = 0, 234 .mask_valid = false, /* use pre-existing mask */ 235 .lkup_idx = ICE_SW_LKUP_PROMISC_VLAN_LOC_LKUP_IDX, 236 }, 237 }; 238 239 /** 240 * ice_dvm_update_dflt_recipes - update default switch recipes in DVM 241 * @hw: hardware structure used to update the recipes 242 */ 243 static int ice_dvm_update_dflt_recipes(struct ice_hw *hw) 244 { 245 unsigned long i; 246 247 for (i = 0; i < ARRAY_SIZE(ice_dvm_dflt_recipes); i++) { 248 struct ice_update_recipe_lkup_idx_params *params; 249 int status; 250 251 params = &ice_dvm_dflt_recipes[i]; 252 253 status = ice_update_recipe_lkup_idx(hw, params); 254 if (status) { 255 ice_debug(hw, ICE_DBG_INIT, "Failed to update RID %d lkup_idx %d fv_idx %d mask_valid %s mask 0x%04x\n", 256 params->rid, params->lkup_idx, params->fv_idx, 257 params->mask_valid ? "true" : "false", 258 params->mask); 259 return status; 260 } 261 } 262 263 return 0; 264 } 265 266 /** 267 * ice_aq_set_vlan_mode - set the VLAN mode of the device 268 * @hw: pointer to the HW structure 269 * @set_params: requested VLAN mode configuration 270 * 271 * Set VLAN Mode Parameters (0x020C) 272 */ 273 static int 274 ice_aq_set_vlan_mode(struct ice_hw *hw, 275 struct ice_aqc_set_vlan_mode *set_params) 276 { 277 u8 rdma_packet, mng_vlan_prot_id; 278 struct ice_aq_desc desc; 279 280 if (!set_params) 281 return -EINVAL; 282 283 if (set_params->l2tag_prio_tagging > ICE_AQ_VLAN_PRIO_TAG_MAX) 284 return -EINVAL; 285 286 rdma_packet = set_params->rdma_packet; 287 if (rdma_packet != ICE_AQ_SVM_VLAN_RDMA_PKT_FLAG_SETTING && 288 rdma_packet != ICE_AQ_DVM_VLAN_RDMA_PKT_FLAG_SETTING) 289 return -EINVAL; 290 291 mng_vlan_prot_id = set_params->mng_vlan_prot_id; 292 if (mng_vlan_prot_id != ICE_AQ_VLAN_MNG_PROTOCOL_ID_OUTER && 293 mng_vlan_prot_id != ICE_AQ_VLAN_MNG_PROTOCOL_ID_INNER) 294 return -EINVAL; 295 296 ice_fill_dflt_direct_cmd_desc(&desc, 297 ice_aqc_opc_set_vlan_mode_parameters); 298 desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD); 299 300 return ice_aq_send_cmd(hw, &desc, set_params, sizeof(*set_params), 301 NULL); 302 } 303 304 /** 305 * ice_set_dvm - sets up software and hardware for double VLAN mode 306 * @hw: pointer to the hardware structure 307 */ 308 static int ice_set_dvm(struct ice_hw *hw) 309 { 310 struct ice_aqc_set_vlan_mode params = { 0 }; 311 int status; 312 313 params.l2tag_prio_tagging = ICE_AQ_VLAN_PRIO_TAG_OUTER_CTAG; 314 params.rdma_packet = ICE_AQ_DVM_VLAN_RDMA_PKT_FLAG_SETTING; 315 params.mng_vlan_prot_id = ICE_AQ_VLAN_MNG_PROTOCOL_ID_OUTER; 316 317 status = ice_aq_set_vlan_mode(hw, ¶ms); 318 if (status) { 319 ice_debug(hw, ICE_DBG_INIT, "Failed to set double VLAN mode parameters, status %d\n", 320 status); 321 return status; 322 } 323 324 status = ice_dvm_update_dflt_recipes(hw); 325 if (status) { 326 ice_debug(hw, ICE_DBG_INIT, "Failed to update default recipes for double VLAN mode, status %d\n", 327 status); 328 return status; 329 } 330 331 status = ice_aq_set_port_params(hw->port_info, true, NULL); 332 if (status) { 333 ice_debug(hw, ICE_DBG_INIT, "Failed to set port in double VLAN mode, status %d\n", 334 status); 335 return status; 336 } 337 338 status = ice_set_dvm_boost_entries(hw); 339 if (status) { 340 ice_debug(hw, ICE_DBG_INIT, "Failed to set boost TCAM entries for double VLAN mode, status %d\n", 341 status); 342 return status; 343 } 344 345 return 0; 346 } 347 348 /** 349 * ice_set_svm - set single VLAN mode 350 * @hw: pointer to the HW structure 351 */ 352 static int ice_set_svm(struct ice_hw *hw) 353 { 354 struct ice_aqc_set_vlan_mode *set_params; 355 int status; 356 357 status = ice_aq_set_port_params(hw->port_info, false, NULL); 358 if (status) { 359 ice_debug(hw, ICE_DBG_INIT, "Failed to set port parameters for single VLAN mode\n"); 360 return status; 361 } 362 363 set_params = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*set_params), 364 GFP_KERNEL); 365 if (!set_params) 366 return -ENOMEM; 367 368 /* default configuration for SVM configurations */ 369 set_params->l2tag_prio_tagging = ICE_AQ_VLAN_PRIO_TAG_INNER_CTAG; 370 set_params->rdma_packet = ICE_AQ_SVM_VLAN_RDMA_PKT_FLAG_SETTING; 371 set_params->mng_vlan_prot_id = ICE_AQ_VLAN_MNG_PROTOCOL_ID_INNER; 372 373 status = ice_aq_set_vlan_mode(hw, set_params); 374 if (status) 375 ice_debug(hw, ICE_DBG_INIT, "Failed to configure port in single VLAN mode\n"); 376 377 devm_kfree(ice_hw_to_dev(hw), set_params); 378 return status; 379 } 380 381 /** 382 * ice_set_vlan_mode 383 * @hw: pointer to the HW structure 384 */ 385 int ice_set_vlan_mode(struct ice_hw *hw) 386 { 387 if (!ice_is_dvm_supported(hw)) 388 return 0; 389 390 if (!ice_set_dvm(hw)) 391 return 0; 392 393 return ice_set_svm(hw); 394 } 395 396 /** 397 * ice_print_dvm_not_supported - print if DDP and/or FW doesn't support DVM 398 * @hw: pointer to the HW structure 399 * 400 * The purpose of this function is to print that QinQ is not supported due to 401 * incompatibilty from the DDP and/or FW. This will give a hint to the user to 402 * update one and/or both components if they expect QinQ functionality. 403 */ 404 static void ice_print_dvm_not_supported(struct ice_hw *hw) 405 { 406 bool pkg_supports_dvm = ice_pkg_supports_dvm(hw); 407 bool fw_supports_dvm = ice_fw_supports_dvm(hw); 408 409 if (!fw_supports_dvm && !pkg_supports_dvm) 410 dev_info(ice_hw_to_dev(hw), "QinQ functionality cannot be enabled on this device. Update your DDP package and NVM to versions that support QinQ.\n"); 411 else if (!pkg_supports_dvm) 412 dev_info(ice_hw_to_dev(hw), "QinQ functionality cannot be enabled on this device. Update your DDP package to a version that supports QinQ.\n"); 413 else if (!fw_supports_dvm) 414 dev_info(ice_hw_to_dev(hw), "QinQ functionality cannot be enabled on this device. Update your NVM to a version that supports QinQ.\n"); 415 } 416 417 /** 418 * ice_post_pkg_dwnld_vlan_mode_cfg - configure VLAN mode after DDP download 419 * @hw: pointer to the HW structure 420 * 421 * This function is meant to configure any VLAN mode specific functionality 422 * after the global configuration lock has been released and the DDP has been 423 * downloaded. 424 * 425 * Since only one PF downloads the DDP and configures the VLAN mode there needs 426 * to be a way to configure the other PFs after the DDP has been downloaded and 427 * the global configuration lock has been released. All such code should go in 428 * this function. 429 */ 430 void ice_post_pkg_dwnld_vlan_mode_cfg(struct ice_hw *hw) 431 { 432 ice_cache_vlan_mode(hw); 433 434 if (ice_is_dvm_ena(hw)) 435 ice_change_proto_id_to_dvm(); 436 else 437 ice_print_dvm_not_supported(hw); 438 } 439