M(READY,               0x001, ready, msg_req, ready_msg_rsp)           \
 M(ATTACH_RESOURCES,    0x002, attach_resources, rsrc_attach, msg_rsp)  \
 M(DETACH_RESOURCES,    0x003, detach_resources, rsrc_detach, msg_rsp)  \
+M(FREE_RSRC_CNT,       0x004, free_rsrc_cnt, msg_req, free_rsrcs_rsp)  \
 M(MSIX_OFFSET,         0x005, msix_offset, msg_req, msix_offset_rsp)   \
 M(VF_FLR,              0x006, vf_flr, msg_req, msg_rsp)                \
 M(PTP_OP,              0x007, ptp_op, ptp_req, ptp_rsp)                \
        u8 cptlfs:1;
 };
 
+/* Number of resources available to the caller.
+ * In reply to MBOX_MSG_FREE_RSRC_CNT.
+ */
+struct free_rsrcs_rsp {
+       struct mbox_msghdr hdr;
+       u16 schq[NIX_TXSCH_LVL_CNT];
+       u16  sso;
+       u16  tim;
+       u16  ssow;
+       u16  cpt;
+       u8   npa;
+       u8   nix;
+       u16  schq_nix1[NIX_TXSCH_LVL_CNT];
+       u8   nix1;
+       u8   cpt1;
+       u8   ree0;
+       u8   ree1;
+};
+
 #define MSIX_VECTOR_INVALID    0xFFFF
 #define MAX_RVU_BLKLF_CNT      256
 
 
        return 0;
 }
 
+int rvu_mbox_handler_free_rsrc_cnt(struct rvu *rvu, struct msg_req *req,
+                                  struct free_rsrcs_rsp *rsp)
+{
+       struct rvu_hwinfo *hw = rvu->hw;
+       struct rvu_block *block;
+       struct nix_txsch *txsch;
+       struct nix_hw *nix_hw;
+
+       mutex_lock(&rvu->rsrc_lock);
+
+       block = &hw->block[BLKADDR_NPA];
+       rsp->npa = rvu_rsrc_free_count(&block->lf);
+
+       block = &hw->block[BLKADDR_NIX0];
+       rsp->nix = rvu_rsrc_free_count(&block->lf);
+
+       block = &hw->block[BLKADDR_NIX1];
+       rsp->nix1 = rvu_rsrc_free_count(&block->lf);
+
+       block = &hw->block[BLKADDR_SSO];
+       rsp->sso = rvu_rsrc_free_count(&block->lf);
+
+       block = &hw->block[BLKADDR_SSOW];
+       rsp->ssow = rvu_rsrc_free_count(&block->lf);
+
+       block = &hw->block[BLKADDR_TIM];
+       rsp->tim = rvu_rsrc_free_count(&block->lf);
+
+       block = &hw->block[BLKADDR_CPT0];
+       rsp->cpt = rvu_rsrc_free_count(&block->lf);
+
+       block = &hw->block[BLKADDR_CPT1];
+       rsp->cpt1 = rvu_rsrc_free_count(&block->lf);
+
+       if (rvu->hw->cap.nix_fixed_txschq_mapping) {
+               rsp->schq[NIX_TXSCH_LVL_SMQ] = 1;
+               rsp->schq[NIX_TXSCH_LVL_TL4] = 1;
+               rsp->schq[NIX_TXSCH_LVL_TL3] = 1;
+               rsp->schq[NIX_TXSCH_LVL_TL2] = 1;
+               /* NIX1 */
+               if (!is_block_implemented(rvu->hw, BLKADDR_NIX1))
+                       goto out;
+               rsp->schq_nix1[NIX_TXSCH_LVL_SMQ] = 1;
+               rsp->schq_nix1[NIX_TXSCH_LVL_TL4] = 1;
+               rsp->schq_nix1[NIX_TXSCH_LVL_TL3] = 1;
+               rsp->schq_nix1[NIX_TXSCH_LVL_TL2] = 1;
+       } else {
+               nix_hw = get_nix_hw(hw, BLKADDR_NIX0);
+               txsch = &nix_hw->txsch[NIX_TXSCH_LVL_SMQ];
+               rsp->schq[NIX_TXSCH_LVL_SMQ] =
+                               rvu_rsrc_free_count(&txsch->schq);
+
+               txsch = &nix_hw->txsch[NIX_TXSCH_LVL_TL4];
+               rsp->schq[NIX_TXSCH_LVL_TL4] =
+                               rvu_rsrc_free_count(&txsch->schq);
+
+               txsch = &nix_hw->txsch[NIX_TXSCH_LVL_TL3];
+               rsp->schq[NIX_TXSCH_LVL_TL3] =
+                               rvu_rsrc_free_count(&txsch->schq);
+
+               txsch = &nix_hw->txsch[NIX_TXSCH_LVL_TL2];
+               rsp->schq[NIX_TXSCH_LVL_TL2] =
+                               rvu_rsrc_free_count(&txsch->schq);
+
+               if (!is_block_implemented(rvu->hw, BLKADDR_NIX1))
+                       goto out;
+
+               nix_hw = get_nix_hw(hw, BLKADDR_NIX1);
+               txsch = &nix_hw->txsch[NIX_TXSCH_LVL_SMQ];
+               rsp->schq_nix1[NIX_TXSCH_LVL_SMQ] =
+                               rvu_rsrc_free_count(&txsch->schq);
+
+               txsch = &nix_hw->txsch[NIX_TXSCH_LVL_TL4];
+               rsp->schq_nix1[NIX_TXSCH_LVL_TL4] =
+                               rvu_rsrc_free_count(&txsch->schq);
+
+               txsch = &nix_hw->txsch[NIX_TXSCH_LVL_TL3];
+               rsp->schq_nix1[NIX_TXSCH_LVL_TL3] =
+                               rvu_rsrc_free_count(&txsch->schq);
+
+               txsch = &nix_hw->txsch[NIX_TXSCH_LVL_TL2];
+               rsp->schq_nix1[NIX_TXSCH_LVL_TL2] =
+                               rvu_rsrc_free_count(&txsch->schq);
+       }
+
+       rsp->schq_nix1[NIX_TXSCH_LVL_TL1] = 1;
+out:
+       rsp->schq[NIX_TXSCH_LVL_TL1] = 1;
+       mutex_unlock(&rvu->rsrc_lock);
+
+       return 0;
+}
+
 int rvu_mbox_handler_vf_flr(struct rvu *rvu, struct msg_req *req,
                            struct msg_rsp *rsp)
 {