u8 reserved[15];
 };
 
+/* LLDP Filter Control (direct 0x0A0A) */
+struct ice_aqc_lldp_filter_ctrl {
+       u8 cmd_flags;
+#define ICE_AQC_LLDP_FILTER_ACTION_ADD         0x0
+#define ICE_AQC_LLDP_FILTER_ACTION_DELETE      0x1
+       u8 reserved1;
+       __le16 vsi_num;
+       u8 reserved2[12];
+};
+
 /* Get/Set RSS key (indirect 0x0B04/0x0B02) */
 struct ice_aqc_get_set_rss_key {
 #define ICE_AQC_GSET_RSS_KEY_VSI_VALID BIT(15)
                struct ice_aqc_lldp_start lldp_start;
                struct ice_aqc_lldp_set_local_mib lldp_set_mib;
                struct ice_aqc_lldp_stop_start_specific_agent lldp_agent_ctrl;
+               struct ice_aqc_lldp_filter_ctrl lldp_filter_ctrl;
                struct ice_aqc_get_set_rss_lut get_set_rss_lut;
                struct ice_aqc_get_set_rss_key get_set_rss_key;
                struct ice_aqc_add_txqs add_txqs;
        ice_aqc_opc_get_cee_dcb_cfg                     = 0x0A07,
        ice_aqc_opc_lldp_set_local_mib                  = 0x0A08,
        ice_aqc_opc_lldp_stop_start_specific_agent      = 0x0A09,
+       ice_aqc_opc_lldp_filter_ctrl                    = 0x0A0A,
 
        /* RSS commands */
        ice_aqc_opc_set_rss_key                         = 0x0B02,
 
 
        return ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
 }
+
+/**
+ * ice_fw_supports_lldp_fltr - check NVM version supports lldp_fltr_ctrl
+ * @hw: pointer to HW struct
+ */
+bool ice_fw_supports_lldp_fltr_ctrl(struct ice_hw *hw)
+{
+       if (hw->mac_type != ICE_MAC_E810)
+               return false;
+
+       if (hw->api_maj_ver == ICE_FW_API_LLDP_FLTR_MAJ) {
+               if (hw->api_min_ver > ICE_FW_API_LLDP_FLTR_MIN)
+                       return true;
+               if (hw->api_min_ver == ICE_FW_API_LLDP_FLTR_MIN &&
+                   hw->api_patch >= ICE_FW_API_LLDP_FLTR_PATCH)
+                       return true;
+       } else if (hw->api_maj_ver > ICE_FW_API_LLDP_FLTR_MAJ) {
+               return true;
+       }
+       return false;
+}
+
+/**
+ * ice_lldp_fltr_add_remove - add or remove a LLDP Rx switch filter
+ * @hw: pointer to HW struct
+ * @vsi_num: absolute HW index for VSI
+ * @add: boolean for if adding or removing a filter
+ */
+enum ice_status
+ice_lldp_fltr_add_remove(struct ice_hw *hw, u16 vsi_num, bool add)
+{
+       struct ice_aqc_lldp_filter_ctrl *cmd;
+       struct ice_aq_desc desc;
+
+       cmd = &desc.params.lldp_filter_ctrl;
+
+       ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_lldp_filter_ctrl);
+
+       if (add)
+               cmd->cmd_flags = ICE_AQC_LLDP_FILTER_ACTION_ADD;
+       else
+               cmd->cmd_flags = ICE_AQC_LLDP_FILTER_ACTION_DELETE;
+
+       cmd->vsi_num = cpu_to_le16(vsi_num);
+
+       return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
+}
 
 enum ice_status
 ice_aq_set_lldp_mib(struct ice_hw *hw, u8 mib_type, void *buf, u16 buf_size,
                    struct ice_sq_cd *cd);
+bool ice_fw_supports_lldp_fltr_ctrl(struct ice_hw *hw);
+enum ice_status
+ice_lldp_fltr_add_remove(struct ice_hw *hw, u16 vsi_num, bool add);
 #endif /* _ICE_COMMON_H_ */
 
                        enum ice_status status;
                        bool dcbx_agent_status;
 
+                       /* Remove rule to direct LLDP packets to default VSI.
+                        * The FW LLDP engine will now be consuming them.
+                        */
+                       ice_cfg_sw_lldp(vsi, false, false);
+
                        /* AQ command to start FW LLDP agent will return an
                         * error if the agent is already started
                         */
                        if (status)
                                dev_dbg(dev, "Fail to init DCB\n");
 
-                       /* Remove rule to direct LLDP packets to default VSI.
-                        * The FW LLDP engine will now be consuming them.
-                        */
-                       ice_cfg_sw_lldp(vsi, false, false);
-
                        /* Register for MIB change events */
                        status = ice_cfg_lldp_mib_change(&pf->hw, true);
                        if (status)
 
        dev = ice_pf_to_dev(pf);
        eth_fltr = create ? ice_fltr_add_eth : ice_fltr_remove_eth;
 
-       if (tx)
+       if (tx) {
                status = eth_fltr(vsi, ETH_P_LLDP, ICE_FLTR_TX,
                                  ICE_DROP_PACKET);
-       else
-               status = eth_fltr(vsi, ETH_P_LLDP, ICE_FLTR_RX, ICE_FWD_TO_VSI);
+       } else {
+               if (ice_fw_supports_lldp_fltr_ctrl(&pf->hw)) {
+                       status = ice_lldp_fltr_add_remove(&pf->hw, vsi->vsi_num,
+                                                         create);
+               } else {
+                       status = eth_fltr(vsi, ETH_P_LLDP, ICE_FLTR_RX,
+                                         ICE_FWD_TO_VSI);
+               }
+       }
 
        if (status)
                dev_err(dev, "Fail %s %s LLDP rule on VSI %i error: %s\n",
 
 /* Hash redirection LUT for VSI - maximum array size */
 #define ICE_VSIQF_HLUT_ARRAY_SIZE      ((VSIQF_HLUT_MAX_INDEX + 1) * 4)
 
+/* AQ API version for LLDP_FILTER_CONTROL */
+#define ICE_FW_API_LLDP_FLTR_MAJ       1
+#define ICE_FW_API_LLDP_FLTR_MIN       7
+#define ICE_FW_API_LLDP_FLTR_PATCH     1
+
 #endif /* _ICE_TYPE_H_ */