net/ice/base: add interface to support configuring VLAN mode
authorQi Zhang <qi.z.zhang@intel.com>
Tue, 15 Dec 2020 04:00:55 +0000 (12:00 +0800)
committerFerruh Yigit <ferruh.yigit@intel.com>
Fri, 8 Jan 2021 15:03:06 +0000 (16:03 +0100)
The VLAN mode of the device has to be configured while the global
configuration lock is held while downloading the DDP, specifically after
the DDP has been downloaded. In order to support this a VLAN mode
interface was added. By default the device will stay in single VLAN
mode (SVM), which is the current implementation. However, this can be
changed by implementing the .set_dvm op.

Signed-off-by: Brett Creeley <brett.creeley@intel.com>
Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>
Acked-by: Qiming Yang <qiming.yang@intel.com>
drivers/net/ice/base/ice_adminq_cmd.h
drivers/net/ice/base/ice_common.c
drivers/net/ice/base/ice_common.h
drivers/net/ice/base/ice_flex_pipe.c
drivers/net/ice/base/ice_type.h
drivers/net/ice/base/ice_vlan_mode.c [new file with mode: 0644]
drivers/net/ice/base/ice_vlan_mode.h [new file with mode: 0644]
drivers/net/ice/base/meson.build

index e696914..ff0e712 100644 (file)
@@ -227,6 +227,27 @@ struct ice_aqc_get_sw_cfg_resp_elem {
 #define ICE_AQC_GET_SW_CONF_RESP_IS_VF         BIT(15)
 };
 
+/* Set Port parameters, (direct, 0x0203) */
+struct ice_aqc_set_port_params {
+       __le16 cmd_flags;
+#define ICE_AQC_SET_P_PARAMS_SAVE_BAD_PACKETS  BIT(0)
+#define ICE_AQC_SET_P_PARAMS_PAD_SHORT_PACKETS BIT(1)
+#define ICE_AQC_SET_P_PARAMS_DOUBLE_VLAN_ENA   BIT(2)
+       __le16 bad_frame_vsi;
+#define ICE_AQC_SET_P_PARAMS_VSI_S     0
+#define ICE_AQC_SET_P_PARAMS_VSI_M     (0x3FF << ICE_AQC_SET_P_PARAMS_VSI_S)
+#define ICE_AQC_SET_P_PARAMS_VSI_VALID BIT(15)
+       __le16 swid;
+#define ICE_AQC_SET_P_PARAMS_SWID_S    0
+#define ICE_AQC_SET_P_PARAMS_SWID_M    (0xFF << ICE_AQC_SET_P_PARAMS_SWID_S)
+#define ICE_AQC_SET_P_PARAMS_LOGI_PORT_ID_S    8
+#define ICE_AQC_SET_P_PARAMS_LOGI_PORT_ID_M    \
+                               (0x3F << ICE_AQC_SET_P_PARAMS_LOGI_PORT_ID_S)
+#define ICE_AQC_SET_P_PARAMS_IS_LOGI_PORT      BIT(14)
+#define ICE_AQC_SET_P_PARAMS_SWID_VALID                BIT(15)
+       u8 reserved[10];
+};
+
 /* These resource type defines are used for all switch resource
  * commands where a resource type is required, such as:
  * Get Resource Allocation command (indirect 0x0204)
@@ -2709,6 +2730,7 @@ struct ice_aq_desc {
                struct ice_aqc_sff_eeprom read_write_sff_param;
                struct ice_aqc_set_port_id_led set_port_id_led;
                struct ice_aqc_get_sw_cfg get_sw_conf;
+               struct ice_aqc_set_port_params set_port_params;
                struct ice_aqc_sw_rules sw_rules;
                struct ice_aqc_storm_cfg storm_conf;
                struct ice_aqc_add_get_recipe add_get_recipe;
@@ -2872,6 +2894,7 @@ enum ice_adminq_opc {
 
        /* internal switch commands */
        ice_aqc_opc_get_sw_cfg                          = 0x0200,
+       ice_aqc_opc_set_port_params                     = 0x0203,
 
        /* Alloc/Free/Get Resources */
        ice_aqc_opc_get_res_alloc                       = 0x0204,
index ca764b2..16dc474 100644 (file)
@@ -830,6 +830,9 @@ enum ice_status ice_init_hw(struct ice_hw *hw)
        if (status)
                goto err_unroll_fltr_mgmt_struct;
        ice_init_lock(&hw->tnl_lock);
+
+       ice_init_vlan_mode_ops(hw);
+
        return ICE_SUCCESS;
 
 err_unroll_fltr_mgmt_struct:
@@ -2387,6 +2390,43 @@ void ice_clear_pxe_mode(struct ice_hw *hw)
                ice_aq_clear_pxe_mode(hw);
 }
 
+/**
+ * ice_aq_set_port_params - set physical port parameters.
+ * @pi: pointer to the port info struct
+ * @bad_frame_vsi: defines the VSI to which bad frames are forwarded
+ * @save_bad_pac: if set packets with errors are forwarded to the bad frames VSI
+ * @pad_short_pac: if set transmit packets smaller than 60 bytes are padded
+ * @double_vlan: if set double VLAN is enabled
+ * @cd: pointer to command details structure or NULL
+ *
+ * Set Physical port parameters (0x0203)
+ */
+enum ice_status
+ice_aq_set_port_params(struct ice_port_info *pi, u16 bad_frame_vsi,
+                      bool save_bad_pac, bool pad_short_pac, bool double_vlan,
+                      struct ice_sq_cd *cd)
+
+{
+       struct ice_aqc_set_port_params *cmd;
+       struct ice_hw *hw = pi->hw;
+       struct ice_aq_desc desc;
+       u16 cmd_flags = 0;
+
+       cmd = &desc.params.set_port_params;
+
+       ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_port_params);
+       cmd->bad_frame_vsi = CPU_TO_LE16(bad_frame_vsi);
+       if (save_bad_pac)
+               cmd_flags |= ICE_AQC_SET_P_PARAMS_SAVE_BAD_PACKETS;
+       if (pad_short_pac)
+               cmd_flags |= ICE_AQC_SET_P_PARAMS_PAD_SHORT_PACKETS;
+       if (double_vlan)
+               cmd_flags |= ICE_AQC_SET_P_PARAMS_DOUBLE_VLAN_ENA;
+       cmd->cmd_flags = CPU_TO_LE16(cmd_flags);
+
+       return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
+}
+
 /**
  * ice_get_link_speed_based_on_phy_type - returns link speed
  * @phy_type_low: lower part of phy_type
index 8c16c7a..765dc30 100644 (file)
@@ -123,6 +123,10 @@ enum ice_status
 ice_aq_send_driver_ver(struct ice_hw *hw, struct ice_driver_ver *dv,
                       struct ice_sq_cd *cd);
 enum ice_status
+ice_aq_set_port_params(struct ice_port_info *pi, u16 bad_frame_vsi,
+                      bool save_bad_pac, bool pad_short_pac, bool double_vlan,
+                      struct ice_sq_cd *cd);
+enum ice_status
 ice_aq_get_phy_caps(struct ice_port_info *pi, bool qual_mods, u8 report_mode,
                    struct ice_aqc_get_phy_caps_data *caps,
                    struct ice_sq_cd *cd);
index 7594df1..0812135 100644 (file)
@@ -1006,6 +1006,13 @@ ice_dwnld_cfg_bufs(struct ice_hw *hw, struct ice_buf *bufs, u32 count)
                        break;
        }
 
+       if (!status) {
+               status = ice_set_vlan_mode(hw);
+               if (status)
+                       ice_debug(hw, ICE_DBG_PKG, "Failed to set VLAN mode: err %d\n",
+                                 status);
+       }
+
        ice_release_global_cfg_lock(hw);
 
        return status;
index 984dca6..7790ee2 100644 (file)
@@ -57,6 +57,7 @@
 #include "ice_lan_tx_rx.h"
 #include "ice_flex_type.h"
 #include "ice_protocol_type.h"
+#include "ice_vlan_mode.h"
 
 /**
  * ice_is_pow2 - check if integer value is a power of 2
@@ -990,6 +991,7 @@ struct ice_hw {
        ice_declare_bitmap(fdir_perfect_fltr, ICE_FLTR_PTYPE_MAX);
        struct ice_lock rss_locks;      /* protect RSS configuration */
        struct LIST_HEAD_TYPE rss_list_head;
+       struct ice_vlan_mode_ops vlan_mode_ops;
 };
 
 /* Statistics collected by each port, VSI, VEB, and S-channel */
diff --git a/drivers/net/ice/base/ice_vlan_mode.c b/drivers/net/ice/base/ice_vlan_mode.c
new file mode 100644 (file)
index 0000000..603de74
--- /dev/null
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2001-2020 Intel Corporation
+ */
+
+#include "ice_vlan_mode.h"
+#include "ice_common.h"
+
+/**
+ * ice_set_svm - set single VLAN mode
+ * @hw: pointer to the HW structure
+ */
+static enum ice_status ice_set_svm_dflt(struct ice_hw *hw)
+{
+       ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
+
+       return ice_aq_set_port_params(hw->port_info, 0, false, false, false, NULL);
+}
+
+/**
+ * ice_init_vlan_mode_ops - initialize VLAN mode configuration ops
+ * @hw: pointer to the HW structure
+ */
+void ice_init_vlan_mode_ops(struct ice_hw *hw)
+{
+       hw->vlan_mode_ops.set_dvm = NULL;
+       hw->vlan_mode_ops.set_svm = ice_set_svm_dflt;
+}
+
+/**
+ * ice_set_vlan_mode
+ * @hw: pointer to the HW structure
+ */
+enum ice_status ice_set_vlan_mode(struct ice_hw *hw)
+{
+       enum ice_status status = ICE_ERR_NOT_IMPL;
+
+       if (hw->vlan_mode_ops.set_dvm)
+               status = hw->vlan_mode_ops.set_dvm(hw);
+
+       if (status)
+               return hw->vlan_mode_ops.set_svm(hw);
+
+       return ICE_SUCCESS;
+}
diff --git a/drivers/net/ice/base/ice_vlan_mode.h b/drivers/net/ice/base/ice_vlan_mode.h
new file mode 100644 (file)
index 0000000..1b9db4d
--- /dev/null
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2001-2020 Intel Corporation
+ */
+
+#ifndef _ICE_VLAN_MODE_H_
+#define _ICE_VLAN_MODE_H_
+
+struct ice_hw;
+
+enum ice_status ice_set_vlan_mode(struct ice_hw *hw);
+void ice_init_vlan_mode_ops(struct ice_hw *hw);
+
+/* This structure defines the VLAN mode configuration interface. It is used to set the VLAN mode.
+ *
+ * Note: These operations will be called while the global configuration lock is held.
+ *
+ * enum ice_status (*set_svm)(struct ice_hw *hw);
+ *     This function is called when the DDP and/or Firmware don't support double VLAN mode (DVM) or
+ *     if the set_dvm op is not implemented and/or returns failure. It will set the device in
+ *     single VLAN mode (SVM).
+ *
+ * enum ice_status (*set_dvm)(struct ice_hw *hw);
+ *     This function is called when the DDP and Firmware support double VLAN mode (DVM). It should
+ *     be implemented to set double VLAN mode. If it fails or remains unimplemented, set_svm will
+ *     be called as a fallback plan.
+ */
+struct ice_vlan_mode_ops {
+       enum ice_status (*set_svm)(struct ice_hw *hw);
+       enum ice_status (*set_dvm)(struct ice_hw *hw);
+};
+
+#endif /* _ICE_VLAN_MODE_H */
index 22963ce..ad5e5da 100644 (file)
@@ -13,6 +13,7 @@ sources = [
        'ice_fdir.c',
        'ice_acl.c',
        'ice_acl_ctrl.c',
+       'ice_vlan_mode.c',
 ]
 
 error_cflags = ['-Wno-unused-value',