ice_txrx.o     \
         ice_ethtool.o
 ice-$(CONFIG_PCI_IOV) += ice_virtchnl_pf.o ice_sriov.o
+ice-$(CONFIG_DCB) += ice_dcb.o ice_dcb_lib.o
 
 #include "ice_devids.h"
 #include "ice_type.h"
 #include "ice_txrx.h"
+#include "ice_dcb.h"
 #include "ice_switch.h"
 #include "ice_common.h"
 #include "ice_sched.h"
        ICE_FLAG_RSS_ENA,
        ICE_FLAG_SRIOV_ENA,
        ICE_FLAG_SRIOV_CAPABLE,
+       ICE_FLAG_DCB_CAPABLE,
+       ICE_FLAG_DCB_ENA,
        ICE_FLAG_LINK_DOWN_ON_CLOSE_ENA,
        ICE_PF_FLAGS_NBITS              /* must be last */
 };
 
        __le32 addr_low;
 };
 
+/* Start LLDP (direct 0x0A06) */
+struct ice_aqc_lldp_start {
+       u8 command;
+#define ICE_AQ_LLDP_AGENT_START                BIT(0)
+#define ICE_AQ_LLDP_AGENT_PERSIST_ENA  BIT(1)
+       u8 reserved[15];
+};
+
+/* Stop/Start LLDP Agent (direct 0x0A09)
+ * Used for stopping/starting specific LLDP agent. e.g. DCBx.
+ * The same structure is used for the response, with the command field
+ * being used as the status field.
+ */
+struct ice_aqc_lldp_stop_start_specific_agent {
+       u8 command;
+#define ICE_AQC_START_STOP_AGENT_M             BIT(0)
+#define ICE_AQC_START_STOP_AGENT_STOP_DCBX     0
+#define ICE_AQC_START_STOP_AGENT_START_DCBX    ICE_AQC_START_STOP_AGENT_M
+       u8 reserved[15];
+};
+
 /* 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_query_txsched_res query_sched_res;
                struct ice_aqc_nvm nvm;
                struct ice_aqc_pf_vf_msg virt;
+               struct ice_aqc_lldp_start lldp_start;
+               struct ice_aqc_lldp_stop_start_specific_agent lldp_agent_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;
        /* PF/VF mailbox commands */
        ice_mbx_opc_send_msg_to_pf                      = 0x0801,
        ice_mbx_opc_send_msg_to_vf                      = 0x0802,
+       /* LLDP commands */
+       ice_aqc_opc_lldp_start                          = 0x0A06,
+       ice_aqc_opc_lldp_stop_start_specific_agent      = 0x0A09,
 
        /* RSS commands */
        ice_aqc_opc_set_rss_key                         = 0x0B02,
 
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2019, Intel Corporation. */
+
+#include "ice_common.h"
+#include "ice_sched.h"
+#include "ice_dcb.h"
+
+/**
+ * ice_aq_start_lldp
+ * @hw: pointer to the HW struct
+ * @cd: pointer to command details structure or NULL
+ *
+ * Start the embedded LLDP Agent on all ports. (0x0A06)
+ */
+enum ice_status ice_aq_start_lldp(struct ice_hw *hw, struct ice_sq_cd *cd)
+{
+       struct ice_aqc_lldp_start *cmd;
+       struct ice_aq_desc desc;
+
+       cmd = &desc.params.lldp_start;
+
+       ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_lldp_start);
+
+       cmd->command = ICE_AQ_LLDP_AGENT_START;
+
+       return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
+}
+
+/**
+ * ice_get_dcbx_status
+ * @hw: pointer to the HW struct
+ *
+ * Get the DCBX status from the Firmware
+ */
+u8 ice_get_dcbx_status(struct ice_hw *hw)
+{
+       u32 reg;
+
+       reg = rd32(hw, PRTDCB_GENS);
+       return (u8)((reg & PRTDCB_GENS_DCBX_STATUS_M) >>
+                   PRTDCB_GENS_DCBX_STATUS_S);
+}
+
+/**
+ * ice_aq_start_stop_dcbx - Start/Stop DCBx service in FW
+ * @hw: pointer to the HW struct
+ * @start_dcbx_agent: True if DCBx Agent needs to be started
+ *                   False if DCBx Agent needs to be stopped
+ * @dcbx_agent_status: FW indicates back the DCBx agent status
+ *                    True if DCBx Agent is active
+ *                    False if DCBx Agent is stopped
+ * @cd: pointer to command details structure or NULL
+ *
+ * Start/Stop the embedded dcbx Agent. In case that this wrapper function
+ * returns ICE_SUCCESS, caller will need to check if FW returns back the same
+ * value as stated in dcbx_agent_status, and react accordingly. (0x0A09)
+ */
+enum ice_status
+ice_aq_start_stop_dcbx(struct ice_hw *hw, bool start_dcbx_agent,
+                      bool *dcbx_agent_status, struct ice_sq_cd *cd)
+{
+       struct ice_aqc_lldp_stop_start_specific_agent *cmd;
+       enum ice_status status;
+       struct ice_aq_desc desc;
+       u16 opcode;
+
+       cmd = &desc.params.lldp_agent_ctrl;
+
+       opcode = ice_aqc_opc_lldp_stop_start_specific_agent;
+
+       ice_fill_dflt_direct_cmd_desc(&desc, opcode);
+
+       if (start_dcbx_agent)
+               cmd->command = ICE_AQC_START_STOP_AGENT_START_DCBX;
+
+       status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
+
+       *dcbx_agent_status = false;
+
+       if (!status &&
+           cmd->command == ICE_AQC_START_STOP_AGENT_START_DCBX)
+               *dcbx_agent_status = true;
+
+       return status;
+}
 
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c) 2019, Intel Corporation. */
+
+#ifndef _ICE_DCB_H_
+#define _ICE_DCB_H_
+
+#include "ice_type.h"
+
+#define ICE_DCBX_STATUS_IN_PROGRESS    1
+#define ICE_DCBX_STATUS_DONE           2
+
+u8 ice_get_dcbx_status(struct ice_hw *hw);
+#ifdef CONFIG_DCB
+enum ice_status ice_aq_start_lldp(struct ice_hw *hw, struct ice_sq_cd *cd);
+enum ice_status
+ice_aq_start_stop_dcbx(struct ice_hw *hw, bool start_dcbx_agent,
+                      bool *dcbx_agent_status, struct ice_sq_cd *cd);
+#else /* CONFIG_DCB */
+static inline enum ice_status
+ice_aq_start_lldp(struct ice_hw __always_unused *hw,
+                 struct ice_sq_cd __always_unused *cd)
+{
+       return 0;
+}
+
+static inline enum ice_status
+ice_aq_start_stop_dcbx(struct ice_hw __always_unused *hw,
+                      bool __always_unused start_dcbx_agent,
+                      bool *dcbx_agent_status,
+                      struct ice_sq_cd __always_unused *cd)
+{
+       *dcbx_agent_status = false;
+
+       return 0;
+}
+#endif /* CONFIG_DCB */
+#endif /* _ICE_DCB_H_ */
 
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2019, Intel Corporation. */
+
+#include "ice_dcb_lib.h"
+
+/**
+ * ice_init_pf_dcb - initialize DCB for a PF
+ * @pf: pf to initiialize DCB for
+ */
+int ice_init_pf_dcb(struct ice_pf *pf)
+{
+       struct device *dev = &pf->pdev->dev;
+       struct ice_port_info *port_info;
+       struct ice_hw *hw = &pf->hw;
+
+       port_info = hw->port_info;
+
+       /* check if device is DCB capable */
+       if (!hw->func_caps.common_cap.dcb) {
+               dev_dbg(dev, "DCB not supported\n");
+               return -EOPNOTSUPP;
+       }
+
+       /* Best effort to put DCBx and LLDP into a good state */
+       port_info->dcbx_status = ice_get_dcbx_status(hw);
+       if (port_info->dcbx_status != ICE_DCBX_STATUS_DONE &&
+           port_info->dcbx_status != ICE_DCBX_STATUS_IN_PROGRESS) {
+               bool dcbx_status;
+
+               /* Attempt to start LLDP engine. Ignore errors
+                * as this will error if it is already started
+                */
+               ice_aq_start_lldp(hw, NULL);
+
+               /* Attempt to start DCBX. Ignore errors as this
+                * will error if it is already started
+                */
+               ice_aq_start_stop_dcbx(hw, true, &dcbx_status, NULL);
+       }
+
+       return 0;
+}
 
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c) 2019, Intel Corporation. */
+
+#ifndef _ICE_DCB_LIB_H_
+#define _ICE_DCB_LIB_H_
+
+#include "ice.h"
+#include "ice_lib.h"
+
+#ifdef CONFIG_DCB
+int ice_init_pf_dcb(struct ice_pf *pf);
+#else
+static inline int ice_init_pf_dcb(struct ice_pf *pf)
+{
+       dev_dbg(&pf->pdev->dev, "DCB not supported\n");
+       return -EOPNOTSUPP;
+}
+#endif /* CONFIG_DCB */
+#endif /* _ICE_DCB_LIB_H_ */
 
 #define PF_MBX_ATQLEN_ATQLEN_M                 ICE_M(0x3FF, 0)
 #define PF_MBX_ATQLEN_ATQENABLE_M              BIT(31)
 #define PF_MBX_ATQT                            0x0022E300
+#define PRTDCB_GENS                            0x00083020
+#define PRTDCB_GENS_DCBX_STATUS_S              0
+#define PRTDCB_GENS_DCBX_STATUS_M              ICE_M(0x7, 0)
 #define GLFLXP_RXDID_FLAGS(_i, _j)             (0x0045D000 + ((_i) * 4 + (_j) * 256))
 #define GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_S      0
 #define GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_M      ICE_M(0x3F, 0)
 
 
 #include "ice.h"
 #include "ice_lib.h"
+#include "ice_dcb_lib.h"
 
 #define DRV_VERSION    "0.7.3-k"
 #define DRV_SUMMARY    "Intel(R) Ethernet Connection E800 Series Linux Driver"
 
        ice_init_pf(pf);
 
+       err = ice_init_pf_dcb(pf);
+       if (err) {
+               clear_bit(ICE_FLAG_DCB_CAPABLE, pf->flags);
+               clear_bit(ICE_FLAG_DCB_ENA, pf->flags);
+
+               /* do not fail overall init if DCB init fails */
+               err = 0;
+       }
+
        ice_determine_q_usage(pf);
 
        pf->num_alloc_vsi = hw->func_caps.guar_num_vsi;
 
        /* RSS related capabilities */
        u16 rss_table_size;             /* 512 for PFs and 64 for VFs */
        u8 rss_table_entry_width;       /* RSS Entry width in bits */
+
+       u8 dcb;
 };
 
 /* Function specific capabilities */
        struct ice_mac_info mac;
        struct ice_phy_info phy;
        struct mutex sched_lock;        /* protect access to TXSched tree */
+       /* LLDP/DCBX Status */
+       u8 dcbx_status;
        u8 lport;
 #define ICE_LPORT_MASK         0xff
        u8 is_vf;