1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2001-2021 Intel Corporation
5 #include "ice_common.h"
8 * ice_pkg_get_supported_vlan_mode - chk if DDP supports Double VLAN mode (DVM)
9 * @hw: pointer to the HW struct
10 * @dvm: output variable to determine if DDP supports DVM(true) or SVM(false)
12 static enum ice_status
13 ice_pkg_get_supported_vlan_mode(struct ice_hw *hw, bool *dvm)
15 u16 meta_init_size = sizeof(struct ice_meta_init_section);
16 struct ice_meta_init_section *sect;
17 struct ice_buf_build *bld;
18 enum ice_status status;
20 /* if anything fails, we assume there is no DVM support */
23 bld = ice_pkg_buf_alloc_single_section(hw,
24 ICE_SID_RXPARSER_METADATA_INIT,
25 meta_init_size, (void **)§);
27 return ICE_ERR_NO_MEMORY;
29 /* only need to read a single section */
30 sect->count = CPU_TO_LE16(1);
31 sect->offset = CPU_TO_LE16(ICE_META_VLAN_MODE_ENTRY);
33 status = ice_aq_upload_section(hw,
34 (struct ice_buf_hdr *)ice_pkg_buf(bld),
35 ICE_PKG_BUF_SIZE, NULL);
37 ice_declare_bitmap(entry, ICE_META_INIT_BITS);
38 u32 arr[ICE_META_INIT_DW_CNT];
41 /* convert to host bitmap format */
42 for (i = 0; i < ICE_META_INIT_DW_CNT; i++)
43 arr[i] = LE32_TO_CPU(sect->entry[0].bm[i]);
45 ice_bitmap_from_array32(entry, arr, (u16)ICE_META_INIT_BITS);
47 /* check if DVM is supported */
48 *dvm = ice_is_bit_set(entry, ICE_META_VLAN_MODE_BIT);
51 ice_pkg_buf_free(hw, bld);
57 * ice_aq_get_vlan_mode - get the VLAN mode of the device
58 * @hw: pointer to the HW structure
59 * @get_params: structure FW fills in based on the current VLAN mode config
61 * Get VLAN Mode Parameters (0x020D)
63 static enum ice_status
64 ice_aq_get_vlan_mode(struct ice_hw *hw,
65 struct ice_aqc_get_vlan_mode *get_params)
67 struct ice_aq_desc desc;
72 ice_fill_dflt_direct_cmd_desc(&desc,
73 ice_aqc_opc_get_vlan_mode_parameters);
75 return ice_aq_send_cmd(hw, &desc, get_params, sizeof(*get_params),
80 * ice_aq_is_dvm_ena - query FW to check if double VLAN mode is enabled
81 * @hw: pointer to the HW structure
83 * Returns true if the hardware/firmware is configured in double VLAN mode,
84 * else return false signaling that the hardware/firmware is configured in
87 * Also, return false if this call fails for any reason (i.e. firmware doesn't
88 * support this AQ call).
90 static bool ice_aq_is_dvm_ena(struct ice_hw *hw)
92 struct ice_aqc_get_vlan_mode get_params = { 0 };
93 enum ice_status status;
95 status = ice_aq_get_vlan_mode(hw, &get_params);
97 ice_debug(hw, ICE_DBG_AQ, "Failed to get VLAN mode, status %d\n",
102 return (get_params.vlan_mode & ICE_AQ_VLAN_MODE_DVM_ENA);
106 * ice_is_dvm_ena - check if double VLAN mode is enabled
107 * @hw: pointer to the HW structure
109 * The device is configured in single or double VLAN mode on initialization and
110 * this cannot be dynamically changed during runtime. Based on this there is no
111 * need to make an AQ call every time the driver needs to know the VLAN mode.
112 * Instead, use the cached VLAN mode.
114 bool ice_is_dvm_ena(struct ice_hw *hw)
120 * ice_cache_vlan_mode - cache VLAN mode after DDP is downloaded
121 * @hw: pointer to the HW structure
123 * This is only called after downloading the DDP and after the global
124 * configuration lock has been released because all ports on a device need to
125 * cache the VLAN mode.
127 static void ice_cache_vlan_mode(struct ice_hw *hw)
129 hw->dvm_ena = ice_aq_is_dvm_ena(hw) ? true : false;
133 * ice_pkg_supports_dvm - find out if DDP supports DVM
134 * @hw: pointer to the HW structure
136 static bool ice_pkg_supports_dvm(struct ice_hw *hw)
138 enum ice_status status;
139 bool pkg_supports_dvm;
141 status = ice_pkg_get_supported_vlan_mode(hw, &pkg_supports_dvm);
143 ice_debug(hw, ICE_DBG_PKG, "Failed to get supported VLAN mode, status %d\n",
148 return pkg_supports_dvm;
152 * ice_fw_supports_dvm - find out if FW supports DVM
153 * @hw: pointer to the HW structure
155 static bool ice_fw_supports_dvm(struct ice_hw *hw)
157 struct ice_aqc_get_vlan_mode get_vlan_mode = { 0 };
158 enum ice_status status;
160 /* If firmware returns success, then it supports DVM, else it only
163 status = ice_aq_get_vlan_mode(hw, &get_vlan_mode);
165 ice_debug(hw, ICE_DBG_NVM, "Failed to get VLAN mode, status %d\n",
174 * ice_is_dvm_supported - check if Double VLAN Mode is supported
175 * @hw: pointer to the hardware structure
177 * Returns true if Double VLAN Mode (DVM) is supported and false if only Single
178 * VLAN Mode (SVM) is supported. In order for DVM to be supported the DDP and
179 * firmware must support it, otherwise only SVM is supported. This function
180 * should only be called while the global config lock is held and after the
181 * package has been successfully downloaded.
183 static bool ice_is_dvm_supported(struct ice_hw *hw)
185 if (!ice_pkg_supports_dvm(hw)) {
186 ice_debug(hw, ICE_DBG_PKG, "DDP doesn't support DVM\n");
190 if (!ice_fw_supports_dvm(hw)) {
191 ice_debug(hw, ICE_DBG_PKG, "FW doesn't support DVM\n");
198 #define ICE_EXTERNAL_VLAN_ID_FV_IDX 11
199 #define ICE_SW_LKUP_VLAN_LOC_LKUP_IDX 1
200 #define ICE_SW_LKUP_VLAN_PKT_FLAGS_LKUP_IDX 2
201 #define ICE_SW_LKUP_PROMISC_VLAN_LOC_LKUP_IDX 2
202 #define ICE_PKT_FLAGS_0_TO_15_FV_IDX 1
203 #define ICE_PKT_FLAGS_0_TO_15_VLAN_FLAGS_MASK 0xD000
204 static struct ice_update_recipe_lkup_idx_params ice_dvm_dflt_recipes[] = {
206 /* Update recipe ICE_SW_LKUP_VLAN to filter based on the
207 * outer/single VLAN in DVM
209 .rid = ICE_SW_LKUP_VLAN,
210 .fv_idx = ICE_EXTERNAL_VLAN_ID_FV_IDX,
211 .ignore_valid = true,
213 .mask_valid = false, /* use pre-existing mask */
214 .lkup_idx = ICE_SW_LKUP_VLAN_LOC_LKUP_IDX,
217 /* Update recipe ICE_SW_LKUP_VLAN to filter based on the VLAN
218 * packet flags to support VLAN filtering on multiple VLAN
219 * ethertypes (i.e. 0x8100 and 0x88a8) in DVM
221 .rid = ICE_SW_LKUP_VLAN,
222 .fv_idx = ICE_PKT_FLAGS_0_TO_15_FV_IDX,
223 .ignore_valid = false,
224 .mask = ICE_PKT_FLAGS_0_TO_15_VLAN_FLAGS_MASK,
226 .lkup_idx = ICE_SW_LKUP_VLAN_PKT_FLAGS_LKUP_IDX,
229 /* Update recipe ICE_SW_LKUP_PROMISC_VLAN to filter based on the
230 * outer/single VLAN in DVM
232 .rid = ICE_SW_LKUP_PROMISC_VLAN,
233 .fv_idx = ICE_EXTERNAL_VLAN_ID_FV_IDX,
234 .ignore_valid = true,
236 .mask_valid = false, /* use pre-existing mask */
237 .lkup_idx = ICE_SW_LKUP_PROMISC_VLAN_LOC_LKUP_IDX,
242 * ice_dvm_update_dflt_recipes - update default switch recipes in DVM
243 * @hw: hardware structure used to update the recipes
245 static enum ice_status ice_dvm_update_dflt_recipes(struct ice_hw *hw)
249 for (i = 0; i < ARRAY_SIZE(ice_dvm_dflt_recipes); i++) {
250 struct ice_update_recipe_lkup_idx_params *params;
251 enum ice_status status;
253 params = &ice_dvm_dflt_recipes[i];
255 status = ice_update_recipe_lkup_idx(hw, params);
257 ice_debug(hw, ICE_DBG_INIT, "Failed to update RID %d lkup_idx %d fv_idx %d mask_valid %s mask 0x%04x\n",
258 params->rid, params->lkup_idx, params->fv_idx,
259 params->mask_valid ? "true" : "false",
269 * ice_aq_set_vlan_mode - set the VLAN mode of the device
270 * @hw: pointer to the HW structure
271 * @set_params: requested VLAN mode configuration
273 * Set VLAN Mode Parameters (0x020C)
275 static enum ice_status
276 ice_aq_set_vlan_mode(struct ice_hw *hw,
277 struct ice_aqc_set_vlan_mode *set_params)
279 u8 rdma_packet, mng_vlan_prot_id;
280 struct ice_aq_desc desc;
283 return ICE_ERR_PARAM;
285 if (set_params->l2tag_prio_tagging > ICE_AQ_VLAN_PRIO_TAG_MAX)
286 return ICE_ERR_PARAM;
288 rdma_packet = set_params->rdma_packet;
289 if (rdma_packet != ICE_AQ_SVM_VLAN_RDMA_PKT_FLAG_SETTING &&
290 rdma_packet != ICE_AQ_DVM_VLAN_RDMA_PKT_FLAG_SETTING)
291 return ICE_ERR_PARAM;
293 mng_vlan_prot_id = set_params->mng_vlan_prot_id;
294 if (mng_vlan_prot_id != ICE_AQ_VLAN_MNG_PROTOCOL_ID_OUTER &&
295 mng_vlan_prot_id != ICE_AQ_VLAN_MNG_PROTOCOL_ID_INNER)
296 return ICE_ERR_PARAM;
298 ice_fill_dflt_direct_cmd_desc(&desc,
299 ice_aqc_opc_set_vlan_mode_parameters);
300 desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
302 return ice_aq_send_cmd(hw, &desc, set_params, sizeof(*set_params),
307 * ice_set_dvm - sets up software and hardware for double VLAN mode
308 * @hw: pointer to the hardware structure
310 static enum ice_status ice_set_dvm(struct ice_hw *hw)
312 struct ice_aqc_set_vlan_mode params = { 0 };
313 enum ice_status status;
315 params.l2tag_prio_tagging = ICE_AQ_VLAN_PRIO_TAG_OUTER_CTAG;
316 params.rdma_packet = ICE_AQ_DVM_VLAN_RDMA_PKT_FLAG_SETTING;
317 params.mng_vlan_prot_id = ICE_AQ_VLAN_MNG_PROTOCOL_ID_OUTER;
319 status = ice_aq_set_vlan_mode(hw, ¶ms);
321 ice_debug(hw, ICE_DBG_INIT, "Failed to set double VLAN mode parameters, status %d\n",
326 status = ice_dvm_update_dflt_recipes(hw);
328 ice_debug(hw, ICE_DBG_INIT, "Failed to update default recipes for double VLAN mode, status %d\n",
333 status = ice_aq_set_port_params(hw->port_info, 0, false, false, true,
336 ice_debug(hw, ICE_DBG_INIT, "Failed to set port in double VLAN mode, status %d\n",
341 status = ice_set_dvm_boost_entries(hw);
343 ice_debug(hw, ICE_DBG_INIT, "Failed to set boost TCAM entries for double VLAN mode, status %d\n",
352 * ice_set_svm - set single VLAN mode
353 * @hw: pointer to the HW structure
355 static enum ice_status ice_set_svm(struct ice_hw *hw)
357 struct ice_aqc_set_vlan_mode *set_params;
358 enum ice_status status;
360 status = ice_aq_set_port_params(hw->port_info, 0, false, false, false, NULL);
362 ice_debug(hw, ICE_DBG_INIT, "Failed to set port parameters for single VLAN mode\n");
366 set_params = (struct ice_aqc_set_vlan_mode *)
367 ice_malloc(hw, sizeof(*set_params));
369 return ICE_ERR_NO_MEMORY;
371 /* default configuration for SVM configurations */
372 set_params->l2tag_prio_tagging = ICE_AQ_VLAN_PRIO_TAG_INNER_CTAG;
373 set_params->rdma_packet = ICE_AQ_SVM_VLAN_RDMA_PKT_FLAG_SETTING;
374 set_params->mng_vlan_prot_id = ICE_AQ_VLAN_MNG_PROTOCOL_ID_INNER;
376 status = ice_aq_set_vlan_mode(hw, set_params);
378 ice_debug(hw, ICE_DBG_INIT, "Failed to configure port in single VLAN mode\n");
380 ice_free(hw, set_params);
386 * @hw: pointer to the HW structure
388 enum ice_status ice_set_vlan_mode(struct ice_hw *hw)
390 /* DCF only has the ability to query the VLAN mode. Setting the VLAN
391 * mode is done by the PF.
396 if (!ice_is_dvm_supported(hw))
399 if (!ice_set_dvm(hw))
402 return ice_set_svm(hw);
406 * ice_print_dvm_not_supported - print if DDP and/or FW doesn't support DVM
407 * @hw: pointer to the HW structure
409 * The purpose of this function is to print that QinQ is not supported due to
410 * incompatibilty from the DDP and/or FW. This will give a hint to the user to
411 * update one and/or both components if they expect QinQ functionality.
413 static void ice_print_dvm_not_supported(struct ice_hw *hw)
415 bool pkg_supports_dvm = ice_pkg_supports_dvm(hw);
416 bool fw_supports_dvm = ice_fw_supports_dvm(hw);
418 if (!fw_supports_dvm && !pkg_supports_dvm)
419 ice_info(hw, "QinQ functionality cannot be enabled on this device. "
420 "Update your DDP package and NVM to versions that support QinQ.\n");
421 else if (!pkg_supports_dvm)
422 ice_info(hw, "QinQ functionality cannot be enabled on this device. "
423 "Update your DDP package to a version that supports QinQ.\n");
424 else if (!fw_supports_dvm)
425 ice_info(hw, "QinQ functionality cannot be enabled on this device. "
426 "Update your NVM to a version that supports QinQ.\n");
430 * ice_post_pkg_dwnld_vlan_mode_cfg - configure VLAN mode after DDP download
431 * @hw: pointer to the HW structure
433 * This function is meant to configure any VLAN mode specific functionality
434 * after the global configuration lock has been released and the DDP has been
437 * Since only one PF downloads the DDP and configures the VLAN mode there needs
438 * to be a way to configure the other PFs after the DDP has been downloaded and
439 * the global configuration lock has been released. All such code should go in
442 void ice_post_pkg_dwnld_vlan_mode_cfg(struct ice_hw *hw)
444 ice_cache_vlan_mode(hw);
446 if (ice_is_dvm_ena(hw))
447 ice_change_proto_id_to_dvm();
449 ice_print_dvm_not_supported(hw);