bp->hwrm_cmd_resp_dma_addr);
                bp->hwrm_cmd_resp_addr = NULL;
        }
+
+       if (bp->hwrm_cmd_kong_resp_addr) {
+               dma_free_coherent(&pdev->dev, PAGE_SIZE,
+                                 bp->hwrm_cmd_kong_resp_addr,
+                                 bp->hwrm_cmd_kong_resp_dma_addr);
+               bp->hwrm_cmd_kong_resp_addr = NULL;
+       }
+}
+
+static int bnxt_alloc_kong_hwrm_resources(struct bnxt *bp)
+{
+       struct pci_dev *pdev = bp->pdev;
+
+       bp->hwrm_cmd_kong_resp_addr =
+               dma_alloc_coherent(&pdev->dev, PAGE_SIZE,
+                                  &bp->hwrm_cmd_kong_resp_dma_addr,
+                                  GFP_KERNEL);
+       if (!bp->hwrm_cmd_kong_resp_addr)
+               return -ENOMEM;
+
+       return 0;
 }
 
 static int bnxt_alloc_hwrm_resources(struct bnxt *bp)
        req->req_type = cpu_to_le16(req_type);
        req->cmpl_ring = cpu_to_le16(cmpl_ring);
        req->target_id = cpu_to_le16(target_id);
-       req->resp_addr = cpu_to_le64(bp->hwrm_cmd_resp_dma_addr);
+       if (bnxt_kong_hwrm_message(bp, req))
+               req->resp_addr = cpu_to_le64(bp->hwrm_cmd_kong_resp_dma_addr);
+       else
+               req->resp_addr = cpu_to_le64(bp->hwrm_cmd_resp_dma_addr);
 }
 
 static int bnxt_hwrm_do_send_msg(struct bnxt *bp, void *msg, u32 msg_len,
        u32 doorbell_offset = BNXT_GRCPF_REG_CHIMP_COMM_TRIGGER;
        u8 *resp_addr = (u8 *)bp->hwrm_cmd_resp_addr;
        u32 bar_offset = BNXT_GRCPF_REG_CHIMP_COMM;
-
-       req->seq_id = cpu_to_le16(bnxt_get_hwrm_seq_id(bp));
-       memset(resp, 0, PAGE_SIZE);
-       cp_ring_id = le16_to_cpu(req->cmpl_ring);
-       intr_process = (cp_ring_id == INVALID_HW_RING_ID) ? 0 : 1;
+       u16 dst = BNXT_HWRM_CHNL_CHIMP;
 
        if (msg_len > BNXT_HWRM_MAX_REQ_LEN) {
                if (msg_len > bp->hwrm_max_ext_req_len ||
                        return -EINVAL;
        }
 
+       if (bnxt_hwrm_kong_chnl(bp, req)) {
+               dst = BNXT_HWRM_CHNL_KONG;
+               bar_offset = BNXT_GRCPF_REG_KONG_COMM;
+               doorbell_offset = BNXT_GRCPF_REG_KONG_COMM_TRIGGER;
+               resp = bp->hwrm_cmd_kong_resp_addr;
+               resp_addr = (u8 *)bp->hwrm_cmd_kong_resp_addr;
+       }
+
+       memset(resp, 0, PAGE_SIZE);
+       cp_ring_id = le16_to_cpu(req->cmpl_ring);
+       intr_process = (cp_ring_id == INVALID_HW_RING_ID) ? 0 : 1;
+
+       req->seq_id = cpu_to_le16(bnxt_get_hwrm_seq_id(bp, dst));
+       /* currently supports only one outstanding message */
+       if (intr_process)
+               bp->hwrm_intr_seq_id = le16_to_cpu(req->seq_id);
+
        if ((bp->fw_cap & BNXT_FW_CAP_SHORT_CMD) ||
            msg_len > BNXT_HWRM_MAX_REQ_LEN) {
                void *short_cmd_req = bp->hwrm_short_cmd_req_addr;
        for (i = msg_len; i < max_req_len; i += 4)
                writel(0, bp->bar0 + bar_offset + i);
 
-       /* currently supports only one outstanding message */
-       if (intr_process)
-               bp->hwrm_intr_seq_id = le16_to_cpu(req->seq_id);
-
        /* Ring channel doorbell */
        writel(1, bp->bar0 + doorbell_offset);
 
            (dev_caps_cfg & VER_GET_RESP_DEV_CAPS_CFG_SHORT_CMD_REQUIRED))
                bp->fw_cap |= BNXT_FW_CAP_SHORT_CMD;
 
+       if (dev_caps_cfg & VER_GET_RESP_DEV_CAPS_CFG_KONG_MB_CHNL_SUPPORTED)
+               bp->fw_cap |= BNXT_FW_CAP_KONG_MB_CHNL;
+
 hwrm_ver_get_exit:
        mutex_unlock(&bp->hwrm_cmd_lock);
        return rc;
        if (rc)
                goto init_err_pci_clean;
 
+       if (bp->fw_cap & BNXT_FW_CAP_KONG_MB_CHNL) {
+               rc = bnxt_alloc_kong_hwrm_resources(bp);
+               if (rc)
+                       bp->fw_cap &= ~BNXT_FW_CAP_KONG_MB_CHNL;
+       }
+
        if ((bp->fw_cap & BNXT_FW_CAP_SHORT_CMD) ||
            bp->hwrm_max_ext_req_len > BNXT_HWRM_MAX_REQ_LEN) {
                rc = bnxt_alloc_hwrm_short_cmd_req(bp);
 
 
 #define HWRM_VALID_BIT_DELAY_USEC      20
 
+#define BNXT_HWRM_CHNL_CHIMP   0
+#define BNXT_HWRM_CHNL_KONG    1
+
 #define BNXT_RX_EVENT  1
 #define BNXT_AGG_EVENT 2
 #define BNXT_TX_EVENT  4
 #define BNXT_CAG_REG_LEGACY_INT_STATUS         0x4014
 #define BNXT_CAG_REG_BASE                      0x300000
 
+#define BNXT_GRCPF_REG_KONG_COMM               0xA00
+#define BNXT_GRCPF_REG_KONG_COMM_TRIGGER       0xB00
+
 struct bnxt_tc_flow_stats {
        u64             packets;
        u64             bytes;
        u32                     msg_enable;
 
        u32                     fw_cap;
-       #define BNXT_FW_CAP_SHORT_CMD   0x00000001
-       #define BNXT_FW_CAP_LLDP_AGENT  0x00000002
-       #define BNXT_FW_CAP_DCBX_AGENT  0x00000004
-       #define BNXT_FW_CAP_NEW_RM      0x00000008
-       #define BNXT_FW_CAP_IF_CHANGE   0x00000010
+       #define BNXT_FW_CAP_SHORT_CMD                   0x00000001
+       #define BNXT_FW_CAP_LLDP_AGENT                  0x00000002
+       #define BNXT_FW_CAP_DCBX_AGENT                  0x00000004
+       #define BNXT_FW_CAP_NEW_RM                      0x00000008
+       #define BNXT_FW_CAP_IF_CHANGE                   0x00000010
+       #define BNXT_FW_CAP_KONG_MB_CHNL                0x00000080
 
 #define BNXT_NEW_RM(bp)                ((bp)->fw_cap & BNXT_FW_CAP_NEW_RM)
        u32                     hwrm_spec_code;
        u16                     hwrm_cmd_seq;
+       u16                     hwrm_cmd_kong_seq;
        u16                     hwrm_intr_seq_id;
        void                    *hwrm_short_cmd_req_addr;
        dma_addr_t              hwrm_short_cmd_req_dma_addr;
        void                    *hwrm_cmd_resp_addr;
        dma_addr_t              hwrm_cmd_resp_dma_addr;
+       void                    *hwrm_cmd_kong_resp_addr;
+       dma_addr_t              hwrm_cmd_kong_resp_dma_addr;
 
        struct rtnl_link_stats64        net_stats_prev;
        struct rx_port_stats    *hw_rx_port_stats;
        }
 }
 
+static inline bool bnxt_cfa_hwrm_message(u16 req_type)
+{
+       switch (req_type) {
+       case HWRM_CFA_ENCAP_RECORD_ALLOC:
+       case HWRM_CFA_ENCAP_RECORD_FREE:
+       case HWRM_CFA_DECAP_FILTER_ALLOC:
+       case HWRM_CFA_DECAP_FILTER_FREE:
+       case HWRM_CFA_NTUPLE_FILTER_ALLOC:
+       case HWRM_CFA_NTUPLE_FILTER_FREE:
+       case HWRM_CFA_NTUPLE_FILTER_CFG:
+       case HWRM_CFA_EM_FLOW_ALLOC:
+       case HWRM_CFA_EM_FLOW_FREE:
+       case HWRM_CFA_EM_FLOW_CFG:
+       case HWRM_CFA_FLOW_ALLOC:
+       case HWRM_CFA_FLOW_FREE:
+       case HWRM_CFA_FLOW_INFO:
+       case HWRM_CFA_FLOW_FLUSH:
+       case HWRM_CFA_FLOW_STATS:
+       case HWRM_CFA_METER_PROFILE_ALLOC:
+       case HWRM_CFA_METER_PROFILE_FREE:
+       case HWRM_CFA_METER_PROFILE_CFG:
+       case HWRM_CFA_METER_INSTANCE_ALLOC:
+       case HWRM_CFA_METER_INSTANCE_FREE:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static inline bool bnxt_kong_hwrm_message(struct bnxt *bp, struct input *req)
+{
+       return (bp->fw_cap & BNXT_FW_CAP_KONG_MB_CHNL &&
+               bnxt_cfa_hwrm_message(le16_to_cpu(req->req_type)));
+}
+
+static inline bool bnxt_hwrm_kong_chnl(struct bnxt *bp, struct input *req)
+{
+       return (bp->fw_cap & BNXT_FW_CAP_KONG_MB_CHNL &&
+               req->resp_addr == cpu_to_le64(bp->hwrm_cmd_kong_resp_dma_addr));
+}
+
 static inline void *bnxt_get_hwrm_resp_addr(struct bnxt *bp, void *req)
 {
-       return bp->hwrm_cmd_resp_addr;
+       if (bnxt_hwrm_kong_chnl(bp, (struct input *)req))
+               return bp->hwrm_cmd_kong_resp_addr;
+       else
+               return bp->hwrm_cmd_resp_addr;
 }
 
-static inline u16 bnxt_get_hwrm_seq_id(struct bnxt *bp)
+static inline u16 bnxt_get_hwrm_seq_id(struct bnxt *bp, u16 dst)
 {
        u16 seq_id;
 
-       seq_id = bp->hwrm_cmd_seq++;
+       if (dst == BNXT_HWRM_CHNL_CHIMP)
+               seq_id = bp->hwrm_cmd_seq++;
+       else
+               seq_id = bp->hwrm_cmd_kong_seq++;
        return seq_id;
 }