diff --git a/drivers/net/bnxt/bnxt.h b/drivers/net/bnxt/bnxt.h
index 773227048..7e71607ab 100644
--- a/drivers/net/bnxt/bnxt.h
+++ b/drivers/net/bnxt/bnxt.h
@@ -461,8 +461,10 @@ struct bnxt {
 
 	uint32_t		flow_flags;
 #define BNXT_FLOW_FLAG_L2_HDR_SRC_FILTER_EN	BIT(0)
-
 	pthread_mutex_t         flow_lock;
+
+	uint32_t		vnic_cap_flags;
+#define BNXT_VNIC_CAP_COS_CLASSIFY	BIT(0)
 	unsigned int		rx_nr_rings;
 	unsigned int		rx_cp_nr_rings;
 	unsigned int		rx_num_qs_per_vnic;
@@ -515,8 +517,10 @@ struct bnxt {
 	uint16_t                        hwrm_max_ext_req_len;
 
 	struct bnxt_link_info	link_info;
-	struct bnxt_cos_queue_info	cos_queue[BNXT_COS_QUEUE_COUNT];
+	struct bnxt_cos_queue_info	rx_cos_queue[BNXT_COS_QUEUE_COUNT];
+	struct bnxt_cos_queue_info	tx_cos_queue[BNXT_COS_QUEUE_COUNT];
 	uint8_t			tx_cosq_id;
+	uint8_t			rx_cosq_cnt;
 	uint8_t                 max_tc;
 	uint8_t                 max_lltc;
 	uint8_t                 max_q;
diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c
index f5cbc0038..720a36d7b 100644
--- a/drivers/net/bnxt/bnxt_ethdev.c
+++ b/drivers/net/bnxt/bnxt_ethdev.c
@@ -311,6 +311,25 @@ static int bnxt_init_chip(struct bnxt *bp)
 		goto err_out;
 	}
 
+	if (!(bp->vnic_cap_flags & BNXT_VNIC_CAP_COS_CLASSIFY))
+		goto skip_cosq_cfg;
+
+	for (j = 0, i = 0; i < BNXT_COS_QUEUE_COUNT; i++) {
+		if (bp->rx_cos_queue[i].id != 0xff) {
+			struct bnxt_vnic_info *vnic = &bp->vnic_info[j++];
+
+			if (!vnic) {
+				PMD_DRV_LOG(ERR,
+					    "Num pools more than FW profile\n");
+				rc = -EINVAL;
+				goto err_out;
+			}
+			vnic->cos_queue_id = bp->rx_cos_queue[i].id;
+			bp->rx_cosq_cnt++;
+		}
+	}
+
+skip_cosq_cfg:
 	rc = bnxt_mq_rx_configure(bp);
 	if (rc) {
 		PMD_DRV_LOG(ERR, "MQ mode configure failure rc: %x\n", rc);
diff --git a/drivers/net/bnxt/bnxt_hwrm.c b/drivers/net/bnxt/bnxt_hwrm.c
index 227d893da..f919f8599 100644
--- a/drivers/net/bnxt/bnxt_hwrm.c
+++ b/drivers/net/bnxt/bnxt_hwrm.c
@@ -677,6 +677,7 @@ int bnxt_hwrm_func_qcaps(struct bnxt *bp)
 	return rc;
 }
 
+/* VNIC cap covers capability of all VNICs. So no need to pass vnic_id */
 int bnxt_hwrm_vnic_qcaps(struct bnxt *bp)
 {
 	int rc = 0;
@@ -691,6 +692,12 @@ int bnxt_hwrm_vnic_qcaps(struct bnxt *bp)
 
 	HWRM_CHECK_RESULT();
 
+	if (rte_le_to_cpu_32(resp->flags) &
+	    HWRM_VNIC_QCAPS_OUTPUT_FLAGS_COS_ASSIGNMENT_CAP) {
+		bp->vnic_cap_flags |= BNXT_VNIC_CAP_COS_CLASSIFY;
+		PMD_DRV_LOG(INFO, "CoS assignment capability enabled\n");
+	}
+
 	bp->max_tpa_v2 = rte_le_to_cpu_16(resp->max_aggs_supported);
 
 	HWRM_UNLOCK();
@@ -1170,11 +1177,13 @@ int bnxt_hwrm_queue_qportcfg(struct bnxt *bp)
 	int rc = 0;
 	struct hwrm_queue_qportcfg_input req = {.req_type = 0 };
 	struct hwrm_queue_qportcfg_output *resp = bp->hwrm_cmd_resp_addr;
+	uint32_t dir = HWRM_QUEUE_QPORTCFG_INPUT_FLAGS_PATH_TX;
 	int i;
 
+get_rx_info:
 	HWRM_PREP(req, QUEUE_QPORTCFG, BNXT_USE_CHIMP_MB);
 
-	req.flags = HWRM_QUEUE_QPORTCFG_INPUT_FLAGS_PATH_TX;
+	req.flags = rte_cpu_to_le_32(dir);
 	/* HWRM Version >= 1.9.1 */
 	if (bp->hwrm_spec_code >= HWRM_VERSION_1_9_1)
 		req.drv_qmap_cap =
@@ -1183,29 +1192,39 @@ int bnxt_hwrm_queue_qportcfg(struct bnxt *bp)
 
 	HWRM_CHECK_RESULT();
 
-#define GET_QUEUE_INFO(x) \
-	bp->cos_queue[x].id = resp->queue_id##x; \
-	bp->cos_queue[x].profile = resp->queue_id##x##_service_profile
-
-	GET_QUEUE_INFO(0);
-	GET_QUEUE_INFO(1);
-	GET_QUEUE_INFO(2);
-	GET_QUEUE_INFO(3);
-	GET_QUEUE_INFO(4);
-	GET_QUEUE_INFO(5);
-	GET_QUEUE_INFO(6);
-	GET_QUEUE_INFO(7);
+	if (dir == HWRM_QUEUE_QPORTCFG_INPUT_FLAGS_PATH_TX) {
+		GET_TX_QUEUE_INFO(0);
+		GET_TX_QUEUE_INFO(1);
+		GET_TX_QUEUE_INFO(2);
+		GET_TX_QUEUE_INFO(3);
+		GET_TX_QUEUE_INFO(4);
+		GET_TX_QUEUE_INFO(5);
+		GET_TX_QUEUE_INFO(6);
+		GET_TX_QUEUE_INFO(7);
+	} else  {
+		GET_RX_QUEUE_INFO(0);
+		GET_RX_QUEUE_INFO(1);
+		GET_RX_QUEUE_INFO(2);
+		GET_RX_QUEUE_INFO(3);
+		GET_RX_QUEUE_INFO(4);
+		GET_RX_QUEUE_INFO(5);
+		GET_RX_QUEUE_INFO(6);
+		GET_RX_QUEUE_INFO(7);
+	}
 
 	HWRM_UNLOCK();
 
+	if (dir == HWRM_QUEUE_QPORTCFG_INPUT_FLAGS_PATH_RX)
+		goto done;
+
 	if (bp->hwrm_spec_code < HWRM_VERSION_1_9_1) {
-		bp->tx_cosq_id = bp->cos_queue[0].id;
+		bp->tx_cosq_id = bp->tx_cos_queue[0].id;
 	} else {
 		/* iterate and find the COSq profile to use for Tx */
-		for (i = 0; i < BNXT_COS_QUEUE_COUNT; i++) {
-			if (bp->cos_queue[i].profile ==
+		for (i = BNXT_COS_QUEUE_COUNT - 1; i >= 0; i--) {
+			if (bp->tx_cos_queue[i].profile ==
 				HWRM_QUEUE_SERVICE_PROFILE_LOSSY) {
-				bp->tx_cosq_id = bp->cos_queue[i].id;
+				bp->tx_cosq_id = bp->tx_cos_queue[i].id;
 				break;
 			}
 		}
@@ -1217,8 +1236,12 @@ int bnxt_hwrm_queue_qportcfg(struct bnxt *bp)
 		bp->max_tc = BNXT_MAX_QUEUE;
 	bp->max_q = bp->max_tc;
 
-	PMD_DRV_LOG(DEBUG, "Tx Cos Queue to use: %d\n", bp->tx_cosq_id);
+	if (dir == HWRM_QUEUE_QPORTCFG_INPUT_FLAGS_PATH_TX) {
+		dir = HWRM_QUEUE_QPORTCFG_INPUT_FLAGS_PATH_RX;
+		goto get_rx_info;
+	}
 
+done:
 	return rc;
 }
 
@@ -1654,6 +1677,11 @@ int bnxt_hwrm_vnic_cfg(struct bnxt *bp, struct bnxt_vnic_info *vnic)
 		ctx_enable_flag |= HWRM_VNIC_CFG_INPUT_ENABLES_MRU;
 		ctx_enable_flag |= HWRM_VNIC_CFG_INPUT_ENABLES_RSS_RULE;
 	}
+	if (bp->vnic_cap_flags & BNXT_VNIC_CAP_COS_CLASSIFY) {
+		ctx_enable_flag |= HWRM_VNIC_CFG_INPUT_ENABLES_QUEUE_ID;
+		req.queue_id = rte_cpu_to_le_16(vnic->cos_queue_id);
+	}
+
 	enables |= ctx_enable_flag;
 	req.dflt_ring_grp = rte_cpu_to_le_16(vnic->dflt_ring_grp);
 	req.rss_rule = rte_cpu_to_le_16(vnic->rss_rule);
diff --git a/drivers/net/bnxt/bnxt_hwrm.h b/drivers/net/bnxt/bnxt_hwrm.h
index 9fa52be72..c78e54adf 100644
--- a/drivers/net/bnxt/bnxt_hwrm.h
+++ b/drivers/net/bnxt/bnxt_hwrm.h
@@ -52,6 +52,16 @@ HWRM_CFA_ADV_FLOW_MGNT_QCAPS_OUTPUT_FLAGS_L2_HEADER_SOURCE_FIELDS_SUPPORTED
 	HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_VNIC |       \
 	HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_STAT)
 
+#define GET_TX_QUEUE_INFO(x) \
+	bp->tx_cos_queue[x].id = resp->queue_id##x; \
+	bp->tx_cos_queue[x].profile =	\
+		resp->queue_id##x##_service_profile
+
+#define GET_RX_QUEUE_INFO(x) \
+	bp->rx_cos_queue[x].id = resp->queue_id##x; \
+	bp->rx_cos_queue[x].profile =	\
+		resp->queue_id##x##_service_profile
+
 int bnxt_hwrm_cfa_l2_clear_rx_mask(struct bnxt *bp,
 				   struct bnxt_vnic_info *vnic);
 int bnxt_hwrm_cfa_l2_set_rx_mask(struct bnxt *bp, struct bnxt_vnic_info *vnic,
diff --git a/drivers/net/bnxt/bnxt_rxq.c b/drivers/net/bnxt/bnxt_rxq.c
index 2e5f2cf29..4df839fa2 100644
--- a/drivers/net/bnxt/bnxt_rxq.c
+++ b/drivers/net/bnxt/bnxt_rxq.c
@@ -75,6 +75,7 @@ int bnxt_mq_rx_configure(struct bnxt *bp)
 		switch (dev_conf->rxmode.mq_mode) {
 		case ETH_MQ_RX_VMDQ_RSS:
 		case ETH_MQ_RX_VMDQ_ONLY:
+		case ETH_MQ_RX_VMDQ_DCB_RSS:
 			/* FALLTHROUGH */
 			/* ETH_8/64_POOLs */
 			pools = conf->nb_queue_pools;
@@ -90,7 +91,7 @@ int bnxt_mq_rx_configure(struct bnxt *bp)
 				pools = max_pools;
 			break;
 		case ETH_MQ_RX_RSS:
-			pools = 1;
+			pools = bp->rx_cosq_cnt ? bp->rx_cosq_cnt : 1;
 			break;
 		default:
 			PMD_DRV_LOG(ERR, "Unsupported mq_mod %d\n",
diff --git a/drivers/net/bnxt/bnxt_vnic.h b/drivers/net/bnxt/bnxt_vnic.h
index de34b21eb..4f760e0b0 100644
--- a/drivers/net/bnxt/bnxt_vnic.h
+++ b/drivers/net/bnxt/bnxt_vnic.h
@@ -45,6 +45,7 @@ struct bnxt_vnic_info {
 	uint16_t	cos_rule;
 	uint16_t	lb_rule;
 	uint16_t	rx_queue_cnt;
+	uint16_t	cos_queue_id;
 	bool		vlan_strip;
 	bool		func_default;
 	bool		bd_stall;
diff --git a/drivers/net/bnxt/hsi_struct_def_dpdk.h b/drivers/net/bnxt/hsi_struct_def_dpdk.h
index 54f0c04c0..a2097126e 100644
--- a/drivers/net/bnxt/hsi_struct_def_dpdk.h
+++ b/drivers/net/bnxt/hsi_struct_def_dpdk.h
@@ -21146,7 +21146,7 @@ struct hwrm_vnic_free_output {
  *****************/
 
 
-/* hwrm_vnic_cfg_input (size:320b/40B) */
+/* hwrm_vnic_cfg_input (size:384b/48B) */
 struct hwrm_vnic_cfg_input {
 	/* The HWRM command request type. */
 	uint16_t	req_type;
@@ -21289,6 +21289,9 @@ struct hwrm_vnic_cfg_input {
 	 */
 	#define HWRM_VNIC_CFG_INPUT_ENABLES_DEFAULT_CMPL_RING_ID \
 		UINT32_C(0x40)
+	/* This bit must be '1' for the queue_id field to be configured. */
+	#define HWRM_VNIC_CFG_INPUT_ENABLES_QUEUE_ID \
+		UINT32_C(0x80)
 	/* Logical vnic ID */
 	uint16_t	vnic_id;
 	/*
@@ -21334,6 +21337,19 @@ struct hwrm_vnic_cfg_input {
 	 * be chosen if packet does not match any RSS rules.
 	 */
 	uint16_t	default_cmpl_ring_id;
+	/*
+	 * When specified, only incoming packets classified to the specified CoS
+	 * queue ID will be arriving on this VNIC.  Packet priority to CoS mapping
+	 * rules can be specified using HWRM_QUEUE_PRI2COS_CFG.  In this mode,
+	 * ntuple filters with VNIC destination specified are invalid since they
+	 * conflict with the the CoS to VNIC steering rules in this mode.
+	 *
+	 * If this field is not specified, packet to VNIC steering will be
+	 * subject to the standard L2 filter rules and any additional ntuple
+	 * filter rules with destination VNIC specified.
+	 */
+	uint16_t	queue_id;
+	uint8_t	unused0[6];
 } __attribute__((packed));
 
 /* hwrm_vnic_cfg_output (size:128b/16B) */
@@ -21629,6 +21645,16 @@ struct hwrm_vnic_qcaps_output {
 	 */
 	#define HWRM_VNIC_QCAPS_OUTPUT_FLAGS_OUTERMOST_RSS_CAP \
 		UINT32_C(0x80)
+	/*
+	 * When this bit is '1', it indicates that firmware supports the
+	 * ability to steer incoming packets from one CoS queue to one
+	 * VNIC.  This optional feature can then be enabled
+	 * using HWRM_VNIC_CFG on any VNIC.  This feature is only
+	 * available when NVM option “enable_cos_classfication” is set
+	 * to 1.  If set to '0', firmware does not support this feature.
+	 */
+	#define HWRM_VNIC_QCAPS_OUTPUT_FLAGS_COS_ASSIGNMENT_CAP \
+		UINT32_C(0x100)
 	/*
 	 * This field advertises the maximum concurrent TPA aggregations
 	 * supported by the VNIC on new devices that support TPA v2.
