1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2001-2021 Intel Corporation
5 #include "ice_vlan_mode.h"
6 #include "ice_common.h"
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)
13 static enum ice_status
14 ice_pkg_get_supported_vlan_mode(struct ice_hw *hw, bool *dvm)
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;
21 /* if anything fails, we assume there is no DVM support */
24 bld = ice_pkg_buf_alloc_single_section(hw,
25 ICE_SID_RXPARSER_METADATA_INIT,
26 meta_init_size, (void **)§);
28 return ICE_ERR_NO_MEMORY;
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);
34 status = ice_aq_upload_section(hw,
35 (struct ice_buf_hdr *)ice_pkg_buf(bld),
36 ICE_PKG_BUF_SIZE, NULL);
38 ice_declare_bitmap(entry, ICE_META_INIT_BITS);
39 u32 arr[ICE_META_INIT_DW_CNT];
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]);
46 ice_bitmap_from_array32(entry, arr, (u16)ICE_META_INIT_BITS);
48 /* check if DVM is supported */
49 *dvm = ice_is_bit_set(entry, ICE_META_VLAN_MODE_BIT);
52 ice_pkg_buf_free(hw, bld);
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
62 * Get VLAN Mode Parameters (0x020D)
64 static enum ice_status
65 ice_aq_get_vlan_mode(struct ice_hw *hw,
66 struct ice_aqc_get_vlan_mode *get_params)
68 struct ice_aq_desc desc;
73 ice_fill_dflt_direct_cmd_desc(&desc,
74 ice_aqc_opc_get_vlan_mode_parameters);
76 return ice_aq_send_cmd(hw, &desc, get_params, sizeof(*get_params),
81 * ice_aq_is_dvm_ena - query FW to check if double VLAN mode is enabled
82 * @hw: pointer to the HW structure
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
88 * Also, return false if this call fails for any reason (i.e. firmware doesn't
89 * support this AQ call).
91 static bool ice_aq_is_dvm_ena(struct ice_hw *hw)
93 struct ice_aqc_get_vlan_mode get_params = { 0 };
94 enum ice_status status;
96 status = ice_aq_get_vlan_mode(hw, &get_params);
98 ice_debug(hw, ICE_DBG_AQ, "Failed to get VLAN mode, status %d\n",
103 return (get_params.vlan_mode & ICE_AQ_VLAN_MODE_DVM_ENA);
107 * ice_is_dvm_ena - check if double VLAN mode is enabled
108 * @hw: pointer to the HW structure
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.
115 bool ice_is_dvm_ena(struct ice_hw *hw)
121 * ice_cache_vlan_mode - cache VLAN mode after DDP is downloaded
122 * @hw: pointer to the HW structure
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.
128 void ice_cache_vlan_mode(struct ice_hw *hw)
130 hw->dvm_ena = ice_aq_is_dvm_ena(hw) ? true : false;
134 * ice_is_dvm_supported - check if Double VLAN Mode is supported
135 * @hw: pointer to the hardware structure
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.
143 static bool ice_is_dvm_supported(struct ice_hw *hw)
145 struct ice_aqc_get_vlan_mode get_vlan_mode = { 0 };
146 enum ice_status status;
147 bool pkg_supports_dvm;
149 status = ice_pkg_get_supported_vlan_mode(hw, &pkg_supports_dvm);
151 ice_debug(hw, ICE_DBG_PKG, "Failed to get supported VLAN mode, status %d\n",
156 if (!pkg_supports_dvm)
159 /* If firmware returns success, then it supports DVM, else it only
162 status = ice_aq_get_vlan_mode(hw, &get_vlan_mode);
164 ice_debug(hw, ICE_DBG_NVM, "Failed to get VLAN mode, status %d\n",
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[] = {
180 /* Update recipe ICE_SW_LKUP_VLAN to filter based on the
181 * outer/single VLAN in DVM
183 .rid = ICE_SW_LKUP_VLAN,
184 .fv_idx = ICE_EXTERNAL_VLAN_ID_FV_IDX,
185 .ignore_valid = true,
187 .mask_valid = false, /* use pre-existing mask */
188 .lkup_idx = ICE_SW_LKUP_VLAN_LOC_LKUP_IDX,
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
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,
200 .lkup_idx = ICE_SW_LKUP_VLAN_PKT_FLAGS_LKUP_IDX,
203 /* Update recipe ICE_SW_LKUP_PROMISC_VLAN to filter based on the
204 * outer/single VLAN in DVM
206 .rid = ICE_SW_LKUP_PROMISC_VLAN,
207 .fv_idx = ICE_EXTERNAL_VLAN_ID_FV_IDX,
208 .ignore_valid = true,
210 .mask_valid = false, /* use pre-existing mask */
211 .lkup_idx = ICE_SW_LKUP_PROMISC_VLAN_LOC_LKUP_IDX,
216 * ice_dvm_update_dflt_recipes - update default switch recipes in DVM
217 * @hw: hardware structure used to update the recipes
219 static enum ice_status ice_dvm_update_dflt_recipes(struct ice_hw *hw)
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;
227 params = &ice_dvm_dflt_recipes[i];
229 status = ice_update_recipe_lkup_idx(hw, params);
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",
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
247 * Set VLAN Mode Parameters (0x020C)
249 static enum ice_status
250 ice_aq_set_vlan_mode(struct ice_hw *hw,
251 struct ice_aqc_set_vlan_mode *set_params)
253 u8 rdma_packet, mng_vlan_prot_id;
254 struct ice_aq_desc desc;
257 return ICE_ERR_PARAM;
259 if (set_params->l2tag_prio_tagging > ICE_AQ_VLAN_PRIO_TAG_MAX)
260 return ICE_ERR_PARAM;
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;
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;
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);
276 return ice_aq_send_cmd(hw, &desc, set_params, sizeof(*set_params),
281 * ice_set_dvm - sets up software and hardware for double VLAN mode
282 * @hw: pointer to the hardware structure
284 static enum ice_status ice_set_dvm(struct ice_hw *hw)
286 struct ice_aqc_set_vlan_mode params = { 0 };
287 enum ice_status status;
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;
293 status = ice_aq_set_vlan_mode(hw, ¶ms);
295 ice_debug(hw, ICE_DBG_INIT, "Failed to set double VLAN mode parameters, status %d\n",
300 status = ice_dvm_update_dflt_recipes(hw);
302 ice_debug(hw, ICE_DBG_INIT, "Failed to update default recipes for double VLAN mode, status %d\n",
307 status = ice_aq_set_port_params(hw->port_info, 0, false, false, true,
310 ice_debug(hw, ICE_DBG_INIT, "Failed to set port in double VLAN mode, status %d\n",
319 * ice_set_svm - set single VLAN mode
320 * @hw: pointer to the HW structure
322 static enum ice_status ice_set_svm(struct ice_hw *hw)
324 struct ice_aqc_set_vlan_mode *set_params;
325 enum ice_status status;
327 status = ice_aq_set_port_params(hw->port_info, 0, false, false, false, NULL);
329 ice_debug(hw, ICE_DBG_INIT, "Failed to set port parameters for single VLAN mode\n");
333 set_params = (struct ice_aqc_set_vlan_mode *)
334 ice_malloc(hw, sizeof(*set_params));
336 return ICE_ERR_NO_MEMORY;
338 /* default configuration for SVM configurations */
339 set_params->l2tag_prio_tagging = ICE_AQ_VLAN_PRIO_TAG_INNER_CTAG;
340 set_params->rdma_packet = ICE_AQ_SVM_VLAN_RDMA_PKT_FLAG_SETTING;
341 set_params->mng_vlan_prot_id = ICE_AQ_VLAN_MNG_PROTOCOL_ID_INNER;
343 status = ice_aq_set_vlan_mode(hw, set_params);
345 ice_debug(hw, ICE_DBG_INIT, "Failed to configure port in single VLAN mode\n");
347 ice_free(hw, set_params);
353 * @hw: pointer to the HW structure
355 enum ice_status ice_set_vlan_mode(struct ice_hw *hw)
357 /* DCF only has the ability to query the VLAN mode. Setting the VLAN
358 * mode is done by the PF.
363 if (!ice_is_dvm_supported(hw))
366 if (!ice_set_dvm(hw))
369 return ice_set_svm(hw);