Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Copyright (C) 2019-2021, Intel Corporation. */
0003 
0004 #include "ice_common.h"
0005 
0006 /**
0007  * ice_pkg_get_supported_vlan_mode - determine if DDP supports Double VLAN mode
0008  * @hw: pointer to the HW struct
0009  * @dvm: output variable to determine if DDP supports DVM(true) or SVM(false)
0010  */
0011 static int
0012 ice_pkg_get_supported_vlan_mode(struct ice_hw *hw, bool *dvm)
0013 {
0014     u16 meta_init_size = sizeof(struct ice_meta_init_section);
0015     struct ice_meta_init_section *sect;
0016     struct ice_buf_build *bld;
0017     int status;
0018 
0019     /* if anything fails, we assume there is no DVM support */
0020     *dvm = false;
0021 
0022     bld = ice_pkg_buf_alloc_single_section(hw,
0023                            ICE_SID_RXPARSER_METADATA_INIT,
0024                            meta_init_size, (void **)&sect);
0025     if (!bld)
0026         return -ENOMEM;
0027 
0028     /* only need to read a single section */
0029     sect->count = cpu_to_le16(1);
0030     sect->offset = cpu_to_le16(ICE_META_VLAN_MODE_ENTRY);
0031 
0032     status = ice_aq_upload_section(hw,
0033                        (struct ice_buf_hdr *)ice_pkg_buf(bld),
0034                        ICE_PKG_BUF_SIZE, NULL);
0035     if (!status) {
0036         DECLARE_BITMAP(entry, ICE_META_INIT_BITS);
0037         u32 arr[ICE_META_INIT_DW_CNT];
0038         u16 i;
0039 
0040         /* convert to host bitmap format */
0041         for (i = 0; i < ICE_META_INIT_DW_CNT; i++)
0042             arr[i] = le32_to_cpu(sect->entry.bm[i]);
0043 
0044         bitmap_from_arr32(entry, arr, (u16)ICE_META_INIT_BITS);
0045 
0046         /* check if DVM is supported */
0047         *dvm = test_bit(ICE_META_VLAN_MODE_BIT, entry);
0048     }
0049 
0050     ice_pkg_buf_free(hw, bld);
0051 
0052     return status;
0053 }
0054 
0055 /**
0056  * ice_aq_get_vlan_mode - get the VLAN mode of the device
0057  * @hw: pointer to the HW structure
0058  * @get_params: structure FW fills in based on the current VLAN mode config
0059  *
0060  * Get VLAN Mode Parameters (0x020D)
0061  */
0062 static int
0063 ice_aq_get_vlan_mode(struct ice_hw *hw,
0064              struct ice_aqc_get_vlan_mode *get_params)
0065 {
0066     struct ice_aq_desc desc;
0067 
0068     if (!get_params)
0069         return -EINVAL;
0070 
0071     ice_fill_dflt_direct_cmd_desc(&desc,
0072                       ice_aqc_opc_get_vlan_mode_parameters);
0073 
0074     return ice_aq_send_cmd(hw, &desc, get_params, sizeof(*get_params),
0075                    NULL);
0076 }
0077 
0078 /**
0079  * ice_aq_is_dvm_ena - query FW to check if double VLAN mode is enabled
0080  * @hw: pointer to the HW structure
0081  *
0082  * Returns true if the hardware/firmware is configured in double VLAN mode,
0083  * else return false signaling that the hardware/firmware is configured in
0084  * single VLAN mode.
0085  *
0086  * Also, return false if this call fails for any reason (i.e. firmware doesn't
0087  * support this AQ call).
0088  */
0089 static bool ice_aq_is_dvm_ena(struct ice_hw *hw)
0090 {
0091     struct ice_aqc_get_vlan_mode get_params = { 0 };
0092     int status;
0093 
0094     status = ice_aq_get_vlan_mode(hw, &get_params);
0095     if (status) {
0096         ice_debug(hw, ICE_DBG_AQ, "Failed to get VLAN mode, status %d\n",
0097               status);
0098         return false;
0099     }
0100 
0101     return (get_params.vlan_mode & ICE_AQ_VLAN_MODE_DVM_ENA);
0102 }
0103 
0104 /**
0105  * ice_is_dvm_ena - check if double VLAN mode is enabled
0106  * @hw: pointer to the HW structure
0107  *
0108  * The device is configured in single or double VLAN mode on initialization and
0109  * this cannot be dynamically changed during runtime. Based on this there is no
0110  * need to make an AQ call every time the driver needs to know the VLAN mode.
0111  * Instead, use the cached VLAN mode.
0112  */
0113 bool ice_is_dvm_ena(struct ice_hw *hw)
0114 {
0115     return hw->dvm_ena;
0116 }
0117 
0118 /**
0119  * ice_cache_vlan_mode - cache VLAN mode after DDP is downloaded
0120  * @hw: pointer to the HW structure
0121  *
0122  * This is only called after downloading the DDP and after the global
0123  * configuration lock has been released because all ports on a device need to
0124  * cache the VLAN mode.
0125  */
0126 static void ice_cache_vlan_mode(struct ice_hw *hw)
0127 {
0128     hw->dvm_ena = ice_aq_is_dvm_ena(hw) ? true : false;
0129 }
0130 
0131 /**
0132  * ice_pkg_supports_dvm - find out if DDP supports DVM
0133  * @hw: pointer to the HW structure
0134  */
0135 static bool ice_pkg_supports_dvm(struct ice_hw *hw)
0136 {
0137     bool pkg_supports_dvm;
0138     int status;
0139 
0140     status = ice_pkg_get_supported_vlan_mode(hw, &pkg_supports_dvm);
0141     if (status) {
0142         ice_debug(hw, ICE_DBG_PKG, "Failed to get supported VLAN mode, status %d\n",
0143               status);
0144         return false;
0145     }
0146 
0147     return pkg_supports_dvm;
0148 }
0149 
0150 /**
0151  * ice_fw_supports_dvm - find out if FW supports DVM
0152  * @hw: pointer to the HW structure
0153  */
0154 static bool ice_fw_supports_dvm(struct ice_hw *hw)
0155 {
0156     struct ice_aqc_get_vlan_mode get_vlan_mode = { 0 };
0157     int status;
0158 
0159     /* If firmware returns success, then it supports DVM, else it only
0160      * supports SVM
0161      */
0162     status = ice_aq_get_vlan_mode(hw, &get_vlan_mode);
0163     if (status) {
0164         ice_debug(hw, ICE_DBG_NVM, "Failed to get VLAN mode, status %d\n",
0165               status);
0166         return false;
0167     }
0168 
0169     return true;
0170 }
0171 
0172 /**
0173  * ice_is_dvm_supported - check if Double VLAN Mode is supported
0174  * @hw: pointer to the hardware structure
0175  *
0176  * Returns true if Double VLAN Mode (DVM) is supported and false if only Single
0177  * VLAN Mode (SVM) is supported. In order for DVM to be supported the DDP and
0178  * firmware must support it, otherwise only SVM is supported. This function
0179  * should only be called while the global config lock is held and after the
0180  * package has been successfully downloaded.
0181  */
0182 static bool ice_is_dvm_supported(struct ice_hw *hw)
0183 {
0184     if (!ice_pkg_supports_dvm(hw)) {
0185         ice_debug(hw, ICE_DBG_PKG, "DDP doesn't support DVM\n");
0186         return false;
0187     }
0188 
0189     if (!ice_fw_supports_dvm(hw)) {
0190         ice_debug(hw, ICE_DBG_PKG, "FW doesn't support DVM\n");
0191         return false;
0192     }
0193 
0194     return true;
0195 }
0196 
0197 #define ICE_EXTERNAL_VLAN_ID_FV_IDX         11
0198 #define ICE_SW_LKUP_VLAN_LOC_LKUP_IDX           1
0199 #define ICE_SW_LKUP_VLAN_PKT_FLAGS_LKUP_IDX     2
0200 #define ICE_SW_LKUP_PROMISC_VLAN_LOC_LKUP_IDX       2
0201 #define ICE_PKT_FLAGS_0_TO_15_FV_IDX            1
0202 static struct ice_update_recipe_lkup_idx_params ice_dvm_dflt_recipes[] = {
0203     {
0204         /* Update recipe ICE_SW_LKUP_VLAN to filter based on the
0205          * outer/single VLAN in DVM
0206          */
0207         .rid = ICE_SW_LKUP_VLAN,
0208         .fv_idx = ICE_EXTERNAL_VLAN_ID_FV_IDX,
0209         .ignore_valid = true,
0210         .mask = 0,
0211         .mask_valid = false, /* use pre-existing mask */
0212         .lkup_idx = ICE_SW_LKUP_VLAN_LOC_LKUP_IDX,
0213     },
0214     {
0215         /* Update recipe ICE_SW_LKUP_VLAN to filter based on the VLAN
0216          * packet flags to support VLAN filtering on multiple VLAN
0217          * ethertypes (i.e. 0x8100 and 0x88a8) in DVM
0218          */
0219         .rid = ICE_SW_LKUP_VLAN,
0220         .fv_idx = ICE_PKT_FLAGS_0_TO_15_FV_IDX,
0221         .ignore_valid = false,
0222         .mask = ICE_PKT_FLAGS_0_TO_15_VLAN_FLAGS_MASK,
0223         .mask_valid = true,
0224         .lkup_idx = ICE_SW_LKUP_VLAN_PKT_FLAGS_LKUP_IDX,
0225     },
0226     {
0227         /* Update recipe ICE_SW_LKUP_PROMISC_VLAN to filter based on the
0228          * outer/single VLAN in DVM
0229          */
0230         .rid = ICE_SW_LKUP_PROMISC_VLAN,
0231         .fv_idx = ICE_EXTERNAL_VLAN_ID_FV_IDX,
0232         .ignore_valid = true,
0233         .mask = 0,
0234         .mask_valid = false,  /* use pre-existing mask */
0235         .lkup_idx = ICE_SW_LKUP_PROMISC_VLAN_LOC_LKUP_IDX,
0236     },
0237 };
0238 
0239 /**
0240  * ice_dvm_update_dflt_recipes - update default switch recipes in DVM
0241  * @hw: hardware structure used to update the recipes
0242  */
0243 static int ice_dvm_update_dflt_recipes(struct ice_hw *hw)
0244 {
0245     unsigned long i;
0246 
0247     for (i = 0; i < ARRAY_SIZE(ice_dvm_dflt_recipes); i++) {
0248         struct ice_update_recipe_lkup_idx_params *params;
0249         int status;
0250 
0251         params = &ice_dvm_dflt_recipes[i];
0252 
0253         status = ice_update_recipe_lkup_idx(hw, params);
0254         if (status) {
0255             ice_debug(hw, ICE_DBG_INIT, "Failed to update RID %d lkup_idx %d fv_idx %d mask_valid %s mask 0x%04x\n",
0256                   params->rid, params->lkup_idx, params->fv_idx,
0257                   params->mask_valid ? "true" : "false",
0258                   params->mask);
0259             return status;
0260         }
0261     }
0262 
0263     return 0;
0264 }
0265 
0266 /**
0267  * ice_aq_set_vlan_mode - set the VLAN mode of the device
0268  * @hw: pointer to the HW structure
0269  * @set_params: requested VLAN mode configuration
0270  *
0271  * Set VLAN Mode Parameters (0x020C)
0272  */
0273 static int
0274 ice_aq_set_vlan_mode(struct ice_hw *hw,
0275              struct ice_aqc_set_vlan_mode *set_params)
0276 {
0277     u8 rdma_packet, mng_vlan_prot_id;
0278     struct ice_aq_desc desc;
0279 
0280     if (!set_params)
0281         return -EINVAL;
0282 
0283     if (set_params->l2tag_prio_tagging > ICE_AQ_VLAN_PRIO_TAG_MAX)
0284         return -EINVAL;
0285 
0286     rdma_packet = set_params->rdma_packet;
0287     if (rdma_packet != ICE_AQ_SVM_VLAN_RDMA_PKT_FLAG_SETTING &&
0288         rdma_packet != ICE_AQ_DVM_VLAN_RDMA_PKT_FLAG_SETTING)
0289         return -EINVAL;
0290 
0291     mng_vlan_prot_id = set_params->mng_vlan_prot_id;
0292     if (mng_vlan_prot_id != ICE_AQ_VLAN_MNG_PROTOCOL_ID_OUTER &&
0293         mng_vlan_prot_id != ICE_AQ_VLAN_MNG_PROTOCOL_ID_INNER)
0294         return -EINVAL;
0295 
0296     ice_fill_dflt_direct_cmd_desc(&desc,
0297                       ice_aqc_opc_set_vlan_mode_parameters);
0298     desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
0299 
0300     return ice_aq_send_cmd(hw, &desc, set_params, sizeof(*set_params),
0301                    NULL);
0302 }
0303 
0304 /**
0305  * ice_set_dvm - sets up software and hardware for double VLAN mode
0306  * @hw: pointer to the hardware structure
0307  */
0308 static int ice_set_dvm(struct ice_hw *hw)
0309 {
0310     struct ice_aqc_set_vlan_mode params = { 0 };
0311     int status;
0312 
0313     params.l2tag_prio_tagging = ICE_AQ_VLAN_PRIO_TAG_OUTER_CTAG;
0314     params.rdma_packet = ICE_AQ_DVM_VLAN_RDMA_PKT_FLAG_SETTING;
0315     params.mng_vlan_prot_id = ICE_AQ_VLAN_MNG_PROTOCOL_ID_OUTER;
0316 
0317     status = ice_aq_set_vlan_mode(hw, &params);
0318     if (status) {
0319         ice_debug(hw, ICE_DBG_INIT, "Failed to set double VLAN mode parameters, status %d\n",
0320               status);
0321         return status;
0322     }
0323 
0324     status = ice_dvm_update_dflt_recipes(hw);
0325     if (status) {
0326         ice_debug(hw, ICE_DBG_INIT, "Failed to update default recipes for double VLAN mode, status %d\n",
0327               status);
0328         return status;
0329     }
0330 
0331     status = ice_aq_set_port_params(hw->port_info, true, NULL);
0332     if (status) {
0333         ice_debug(hw, ICE_DBG_INIT, "Failed to set port in double VLAN mode, status %d\n",
0334               status);
0335         return status;
0336     }
0337 
0338     status = ice_set_dvm_boost_entries(hw);
0339     if (status) {
0340         ice_debug(hw, ICE_DBG_INIT, "Failed to set boost TCAM entries for double VLAN mode, status %d\n",
0341               status);
0342         return status;
0343     }
0344 
0345     return 0;
0346 }
0347 
0348 /**
0349  * ice_set_svm - set single VLAN mode
0350  * @hw: pointer to the HW structure
0351  */
0352 static int ice_set_svm(struct ice_hw *hw)
0353 {
0354     struct ice_aqc_set_vlan_mode *set_params;
0355     int status;
0356 
0357     status = ice_aq_set_port_params(hw->port_info, false, NULL);
0358     if (status) {
0359         ice_debug(hw, ICE_DBG_INIT, "Failed to set port parameters for single VLAN mode\n");
0360         return status;
0361     }
0362 
0363     set_params = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*set_params),
0364                   GFP_KERNEL);
0365     if (!set_params)
0366         return -ENOMEM;
0367 
0368     /* default configuration for SVM configurations */
0369     set_params->l2tag_prio_tagging = ICE_AQ_VLAN_PRIO_TAG_INNER_CTAG;
0370     set_params->rdma_packet = ICE_AQ_SVM_VLAN_RDMA_PKT_FLAG_SETTING;
0371     set_params->mng_vlan_prot_id = ICE_AQ_VLAN_MNG_PROTOCOL_ID_INNER;
0372 
0373     status = ice_aq_set_vlan_mode(hw, set_params);
0374     if (status)
0375         ice_debug(hw, ICE_DBG_INIT, "Failed to configure port in single VLAN mode\n");
0376 
0377     devm_kfree(ice_hw_to_dev(hw), set_params);
0378     return status;
0379 }
0380 
0381 /**
0382  * ice_set_vlan_mode
0383  * @hw: pointer to the HW structure
0384  */
0385 int ice_set_vlan_mode(struct ice_hw *hw)
0386 {
0387     if (!ice_is_dvm_supported(hw))
0388         return 0;
0389 
0390     if (!ice_set_dvm(hw))
0391         return 0;
0392 
0393     return ice_set_svm(hw);
0394 }
0395 
0396 /**
0397  * ice_print_dvm_not_supported - print if DDP and/or FW doesn't support DVM
0398  * @hw: pointer to the HW structure
0399  *
0400  * The purpose of this function is to print that  QinQ is not supported due to
0401  * incompatibilty from the DDP and/or FW. This will give a hint to the user to
0402  * update one and/or both components if they expect QinQ functionality.
0403  */
0404 static void ice_print_dvm_not_supported(struct ice_hw *hw)
0405 {
0406     bool pkg_supports_dvm = ice_pkg_supports_dvm(hw);
0407     bool fw_supports_dvm = ice_fw_supports_dvm(hw);
0408 
0409     if (!fw_supports_dvm && !pkg_supports_dvm)
0410         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");
0411     else if (!pkg_supports_dvm)
0412         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");
0413     else if (!fw_supports_dvm)
0414         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");
0415 }
0416 
0417 /**
0418  * ice_post_pkg_dwnld_vlan_mode_cfg - configure VLAN mode after DDP download
0419  * @hw: pointer to the HW structure
0420  *
0421  * This function is meant to configure any VLAN mode specific functionality
0422  * after the global configuration lock has been released and the DDP has been
0423  * downloaded.
0424  *
0425  * Since only one PF downloads the DDP and configures the VLAN mode there needs
0426  * to be a way to configure the other PFs after the DDP has been downloaded and
0427  * the global configuration lock has been released. All such code should go in
0428  * this function.
0429  */
0430 void ice_post_pkg_dwnld_vlan_mode_cfg(struct ice_hw *hw)
0431 {
0432     ice_cache_vlan_mode(hw);
0433 
0434     if (ice_is_dvm_ena(hw))
0435         ice_change_proto_id_to_dvm();
0436     else
0437         ice_print_dvm_not_supported(hw);
0438 }