net/ice/base: do not set VLAN mode in DCF mode
[dpdk.git] / drivers / net / ice / base / ice_vlan_mode.c
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 **)&sect);
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, &params);
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         return ICE_SUCCESS;
316 }
317
318 /**
319  * ice_set_svm - set single VLAN mode
320  * @hw: pointer to the HW structure
321  */
322 static enum ice_status ice_set_svm(struct ice_hw *hw)
323 {
324         struct ice_aqc_set_vlan_mode *set_params;
325         enum ice_status status;
326
327         status = ice_aq_set_port_params(hw->port_info, 0, false, false, false, NULL);
328         if (status) {
329                 ice_debug(hw, ICE_DBG_INIT, "Failed to set port parameters for single VLAN mode\n");
330                 return status;
331         }
332
333         set_params = (struct ice_aqc_set_vlan_mode *)
334                 ice_malloc(hw, sizeof(*set_params));
335         if (!set_params)
336                 return ICE_ERR_NO_MEMORY;
337
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;
342
343         status = ice_aq_set_vlan_mode(hw, set_params);
344         if (status)
345                 ice_debug(hw, ICE_DBG_INIT, "Failed to configure port in single VLAN mode\n");
346
347         ice_free(hw, set_params);
348         return status;
349 }
350
351 /**
352  * ice_set_vlan_mode
353  * @hw: pointer to the HW structure
354  */
355 enum ice_status ice_set_vlan_mode(struct ice_hw *hw)
356 {
357         /* DCF only has the ability to query the VLAN mode. Setting the VLAN
358          * mode is done by the PF.
359          */
360         if (hw->dcf_enabled)
361                 return ICE_SUCCESS;
362
363         if (!ice_is_dvm_supported(hw))
364                 return ICE_SUCCESS;
365
366         if (!ice_set_dvm(hw))
367                 return ICE_SUCCESS;
368
369         return ice_set_svm(hw);
370 }