/* check if DVM is supported */
*dvm = test_bit(ICE_META_VLAN_MODE_BIT, entry);
}
ice_pkg_buf_free(hw, bld);
return status;
}
/** * ice_aq_get_vlan_mode - get the VLAN mode of the device * @hw: pointer to the HW structure * @get_params: structure FW fills in based on the current VLAN mode config * * Get VLAN Mode Parameters (0x020D)
*/ staticint
ice_aq_get_vlan_mode(struct ice_hw *hw, struct ice_aqc_get_vlan_mode *get_params)
{ struct libie_aq_desc desc;
/** * ice_aq_is_dvm_ena - query FW to check if double VLAN mode is enabled * @hw: pointer to the HW structure * * Returns true if the hardware/firmware is configured in double VLAN mode, * else return false signaling that the hardware/firmware is configured in * single VLAN mode. * * Also, return false if this call fails for any reason (i.e. firmware doesn't * support this AQ call).
*/ staticbool ice_aq_is_dvm_ena(struct ice_hw *hw)
{ struct ice_aqc_get_vlan_mode get_params = { 0 }; int status;
status = ice_aq_get_vlan_mode(hw, &get_params); if (status) {
ice_debug(hw, ICE_DBG_AQ, "Failed to get VLAN mode, status %d\n",
status); returnfalse;
}
/** * ice_is_dvm_ena - check if double VLAN mode is enabled * @hw: pointer to the HW structure * * The device is configured in single or double VLAN mode on initialization and * this cannot be dynamically changed during runtime. Based on this there is no * need to make an AQ call every time the driver needs to know the VLAN mode. * Instead, use the cached VLAN mode.
*/ bool ice_is_dvm_ena(struct ice_hw *hw)
{ return hw->dvm_ena;
}
/** * ice_cache_vlan_mode - cache VLAN mode after DDP is downloaded * @hw: pointer to the HW structure * * This is only called after downloading the DDP and after the global * configuration lock has been released because all ports on a device need to * cache the VLAN mode.
*/ staticvoid ice_cache_vlan_mode(struct ice_hw *hw)
{
hw->dvm_ena = ice_aq_is_dvm_ena(hw) ? true : false;
}
/** * ice_pkg_supports_dvm - find out if DDP supports DVM * @hw: pointer to the HW structure
*/ staticbool ice_pkg_supports_dvm(struct ice_hw *hw)
{ bool pkg_supports_dvm; int status;
status = ice_pkg_get_supported_vlan_mode(hw, &pkg_supports_dvm); if (status) {
ice_debug(hw, ICE_DBG_PKG, "Failed to get supported VLAN mode, status %d\n",
status); returnfalse;
}
return pkg_supports_dvm;
}
/** * ice_fw_supports_dvm - find out if FW supports DVM * @hw: pointer to the HW structure
*/ staticbool ice_fw_supports_dvm(struct ice_hw *hw)
{ struct ice_aqc_get_vlan_mode get_vlan_mode = { 0 }; int status;
/* If firmware returns success, then it supports DVM, else it only * supports SVM
*/
status = ice_aq_get_vlan_mode(hw, &get_vlan_mode); if (status) {
ice_debug(hw, ICE_DBG_NVM, "Failed to get VLAN mode, status %d\n",
status); returnfalse;
}
returntrue;
}
/** * ice_is_dvm_supported - check if Double VLAN Mode is supported * @hw: pointer to the hardware structure * * Returns true if Double VLAN Mode (DVM) is supported and false if only Single * VLAN Mode (SVM) is supported. In order for DVM to be supported the DDP and * firmware must support it, otherwise only SVM is supported. This function * should only be called while the global config lock is held and after the * package has been successfully downloaded.
*/ staticbool ice_is_dvm_supported(struct ice_hw *hw)
{ if (!ice_pkg_supports_dvm(hw)) {
ice_debug(hw, ICE_DBG_PKG, "DDP doesn't support DVM\n"); returnfalse;
}
if (!ice_fw_supports_dvm(hw)) {
ice_debug(hw, ICE_DBG_PKG, "FW doesn't support DVM\n"); returnfalse;
}
returntrue;
}
#define ICE_EXTERNAL_VLAN_ID_FV_IDX 11 #define ICE_SW_LKUP_VLAN_LOC_LKUP_IDX 1 #define ICE_SW_LKUP_VLAN_PKT_FLAGS_LKUP_IDX 2 #define ICE_SW_LKUP_PROMISC_VLAN_LOC_LKUP_IDX 2 #define ICE_PKT_FLAGS_0_TO_15_FV_IDX 1 staticstruct ice_update_recipe_lkup_idx_params ice_dvm_dflt_recipes[] = {
{ /* Update recipe ICE_SW_LKUP_VLAN to filter based on the * outer/single VLAN in DVM
*/
.rid = ICE_SW_LKUP_VLAN,
.fv_idx = ICE_EXTERNAL_VLAN_ID_FV_IDX,
.ignore_valid = true,
.mask = 0,
.mask_valid = false, /* use pre-existing mask */
.lkup_idx = ICE_SW_LKUP_VLAN_LOC_LKUP_IDX,
},
{ /* Update recipe ICE_SW_LKUP_VLAN to filter based on the VLAN * packet flags to support VLAN filtering on multiple VLAN * ethertypes (i.e. 0x8100 and 0x88a8) in DVM
*/
.rid = ICE_SW_LKUP_VLAN,
.fv_idx = ICE_PKT_FLAGS_0_TO_15_FV_IDX,
.ignore_valid = false,
.mask = ICE_PKT_VLAN_MASK,
.mask_valid = true,
.lkup_idx = ICE_SW_LKUP_VLAN_PKT_FLAGS_LKUP_IDX,
},
{ /* Update recipe ICE_SW_LKUP_PROMISC_VLAN to filter based on the * outer/single VLAN in DVM
*/
.rid = ICE_SW_LKUP_PROMISC_VLAN,
.fv_idx = ICE_EXTERNAL_VLAN_ID_FV_IDX,
.ignore_valid = true,
.mask = 0,
.mask_valid = false, /* use pre-existing mask */
.lkup_idx = ICE_SW_LKUP_PROMISC_VLAN_LOC_LKUP_IDX,
},
};
/** * ice_dvm_update_dflt_recipes - update default switch recipes in DVM * @hw: hardware structure used to update the recipes
*/ staticint ice_dvm_update_dflt_recipes(struct ice_hw *hw)
{ unsignedlong i;
for (i = 0; i < ARRAY_SIZE(ice_dvm_dflt_recipes); i++) { struct ice_update_recipe_lkup_idx_params *params; int status;
status = ice_aq_set_vlan_mode(hw, ¶ms); if (status) {
ice_debug(hw, ICE_DBG_INIT, "Failed to set double VLAN mode parameters, status %d\n",
status); return status;
}
status = ice_dvm_update_dflt_recipes(hw); if (status) {
ice_debug(hw, ICE_DBG_INIT, "Failed to update default recipes for double VLAN mode, status %d\n",
status); return status;
}
status = ice_aq_set_port_params(hw->port_info, true, NULL); if (status) {
ice_debug(hw, ICE_DBG_INIT, "Failed to set port in double VLAN mode, status %d\n",
status); return status;
}
status = ice_set_dvm_boost_entries(hw); if (status) {
ice_debug(hw, ICE_DBG_INIT, "Failed to set boost TCAM entries for double VLAN mode, status %d\n",
status); return status;
}
return 0;
}
/** * ice_set_svm - set single VLAN mode * @hw: pointer to the HW structure
*/ staticint ice_set_svm(struct ice_hw *hw)
{ struct ice_aqc_set_vlan_mode *set_params; int status;
status = ice_aq_set_port_params(hw->port_info, false, NULL); if (status) {
ice_debug(hw, ICE_DBG_INIT, "Failed to set port parameters for single VLAN mode\n"); return status;
}
set_params = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*set_params),
GFP_KERNEL); if (!set_params) return -ENOMEM;
/** * ice_set_vlan_mode * @hw: pointer to the HW structure
*/ int ice_set_vlan_mode(struct ice_hw *hw)
{ if (!ice_is_dvm_supported(hw)) return 0;
if (!ice_set_dvm(hw)) return 0;
return ice_set_svm(hw);
}
/** * ice_print_dvm_not_supported - print if DDP and/or FW doesn't support DVM * @hw: pointer to the HW structure * * The purpose of this function is to print that QinQ is not supported due to * incompatibilty from the DDP and/or FW. This will give a hint to the user to * update one and/or both components if they expect QinQ functionality.
*/ staticvoid ice_print_dvm_not_supported(struct ice_hw *hw)
{ bool pkg_supports_dvm = ice_pkg_supports_dvm(hw); bool fw_supports_dvm = ice_fw_supports_dvm(hw);
if (!fw_supports_dvm && !pkg_supports_dvm)
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"); elseif (!pkg_supports_dvm)
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"); elseif (!fw_supports_dvm)
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");
}
/** * ice_post_pkg_dwnld_vlan_mode_cfg - configure VLAN mode after DDP download * @hw: pointer to the HW structure * * This function is meant to configure any VLAN mode specific functionality * after the global configuration lock has been released and the DDP has been * downloaded. * * Since only one PF downloads the DDP and configures the VLAN mode there needs * to be a way to configure the other PFs after the DDP has been downloaded and * the global configuration lock has been released. All such code should go in * this function.
*/ void ice_post_pkg_dwnld_vlan_mode_cfg(struct ice_hw *hw)
{
ice_cache_vlan_mode(hw);
if (ice_is_dvm_ena(hw))
ice_change_proto_id_to_dvm(); else
ice_print_dvm_not_supported(hw);
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.1 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.