Parcourir la source

qcacmn: Optimize rx reorder queue setup

This change optimizes rx reorder queue setup by using
tid_bitmap, which contains a group of tids, to set up
multi tids at a time instead of one tid after another.

Change-Id: I161b0c812c436ef79d2d1db693b8d0ac41505878
CRs-Fixed: 3661593
jinbao liu il y a 1 an
Parent
commit
b4f2073ac3

+ 4 - 0
dp/inc/cdp_txrx_ops.h

@@ -1525,6 +1525,10 @@ struct ol_if_ops {
 				       uint8_t ba_window_size_valid,
 				       uint16_t ba_window_size);
 	QDF_STATUS
+	(*peer_multi_rx_reorder_queue_setup)(struct cdp_ctrl_objmgr_psoc *ctrl_psoc,
+					     uint8_t pdev_id,
+					     struct multi_rx_reorder_queue_setup_params *tid_params);
+	QDF_STATUS
 	(*peer_rx_reorder_queue_remove)(struct cdp_ctrl_objmgr_psoc *ctrl_psoc,
 					uint8_t pdev_id,
 					uint8_t vdev_id, uint8_t *peer_macaddr,

+ 3 - 0
dp/inc/cdp_txrx_stats_struct.h

@@ -3329,6 +3329,8 @@ struct cdp_peer_hmwds_ast_add_status {
  * @DP_SOC_PARAM_MULTI_PEER_GRP_CMD_SUPPORT: For sending bulk AST delete
  * @DP_SOC_PARAM_RSSI_DBM_CONV_SUPPORT: To set the rssi dbm support bit
  * @DP_SOC_PARAM_UMAC_HW_RESET_SUPPORT: Whether target supports UMAC HW reset
+ * @DP_SOC_PARAM_MULTI_RX_REORDER_SETUP_SUPPORT: Whether setting up a group of
+ *						 TIDs at a time is supported
  * @DP_SOC_PARAM_MAX:
  */
 enum cdp_soc_param_t {
@@ -3339,6 +3341,7 @@ enum cdp_soc_param_t {
 	DP_SOC_PARAM_MULTI_PEER_GRP_CMD_SUPPORT,
 	DP_SOC_PARAM_RSSI_DBM_CONV_SUPPORT,
 	DP_SOC_PARAM_UMAC_HW_RESET_SUPPORT,
+	DP_SOC_PARAM_MULTI_RX_REORDER_SETUP_SUPPORT,
 	DP_SOC_PARAM_MAX,
 };
 

+ 2 - 2
dp/wifi3.0/be/dp_be_rx.c

@@ -2427,11 +2427,11 @@ dp_rx_null_q_desc_handle_be(struct dp_soc *soc, qdf_nbuf_t nbuf,
 				if (qdf_unlikely(vdev->mesh_vdev) ||
 				    qdf_unlikely(txrx_peer->nawds_enabled))
 					dp_rx_tid_setup_wifi3(
-						peer, tid,
+						peer, BIT(tid),
 						hal_get_rx_max_ba_window(soc->hal_soc,tid),
 						IEEE80211_SEQ_MAX);
 				else
-					dp_rx_tid_setup_wifi3(peer, tid, 1,
+					dp_rx_tid_setup_wifi3(peer, BIT(tid), 1,
 							      IEEE80211_SEQ_MAX);
 			}
 			qdf_spin_unlock_bh(&rx_tid->tid_lock);

+ 197 - 84
dp/wifi3.0/be/dp_be_rx.h

@@ -275,6 +275,124 @@ dp_soc_get_num_soc_be(struct dp_soc *soc)
 }
 #endif
 
+static inline QDF_STATUS
+dp_peer_rx_reorder_q_setup_per_tid(struct dp_peer *peer,
+				   uint32_t tid_bitmap,
+				   uint32_t ba_window_size)
+{
+	int tid;
+	struct dp_rx_tid *rx_tid;
+	struct dp_soc *soc = peer->vdev->pdev->soc;
+
+	if (!soc->cdp_soc.ol_ops->peer_rx_reorder_queue_setup) {
+		dp_peer_debug("%pK: rx_reorder_queue_setup NULL bitmap 0x%x",
+			      soc, tid_bitmap);
+		return QDF_STATUS_SUCCESS;
+	}
+
+	for (tid = 0; tid < DP_MAX_TIDS; tid++) {
+		if (!(BIT(tid) & tid_bitmap))
+			continue;
+
+		rx_tid = &peer->rx_tid[tid];
+		if (!rx_tid->hw_qdesc_paddr) {
+			tid_bitmap &= ~BIT(tid);
+			continue;
+		}
+
+		if (soc->cdp_soc.ol_ops->peer_rx_reorder_queue_setup(
+		    soc->ctrl_psoc,
+		    peer->vdev->pdev->pdev_id,
+		    peer->vdev->vdev_id,
+		    peer->mac_addr.raw,
+		    rx_tid->hw_qdesc_paddr,
+		    tid, tid,
+		    1, ba_window_size)) {
+			dp_peer_err("%pK: Fail to send reo q to FW. tid %d",
+				    soc, tid);
+			return QDF_STATUS_E_FAILURE;
+		}
+	}
+
+	if (!tid_bitmap) {
+		dp_peer_err("tid_bitmap=0. All tids setup fail");
+		return QDF_STATUS_E_FAILURE;
+	}
+	return QDF_STATUS_SUCCESS;
+}
+
+static inline QDF_STATUS
+dp_peer_multi_tid_params_setup(struct dp_peer *peer,
+		uint32_t tid_bitmap,
+		uint32_t ba_window_size,
+		struct multi_rx_reorder_queue_setup_params *tid_params)
+{
+	struct dp_rx_tid *rx_tid;
+	int tid;
+
+	tid_params->peer_macaddr = peer->mac_addr.raw;
+	tid_params->tid_bitmap = tid_bitmap;
+	tid_params->vdev_id = peer->vdev->vdev_id;
+
+	for (tid = 0; tid < DP_MAX_TIDS; tid++) {
+		if (!(BIT(tid) & tid_bitmap))
+			continue;
+
+		rx_tid = &peer->rx_tid[tid];
+		if (!rx_tid->hw_qdesc_paddr) {
+			tid_params->tid_bitmap &= ~BIT(tid);
+			continue;
+		}
+
+		tid_params->tid_num++;
+		tid_params->queue_params_list[tid].hw_qdesc_paddr =
+			rx_tid->hw_qdesc_paddr;
+		tid_params->queue_params_list[tid].queue_no = tid;
+		tid_params->queue_params_list[tid].ba_window_size_valid = 1;
+		tid_params->queue_params_list[tid].ba_window_size =
+			ba_window_size;
+	}
+
+	if (!tid_params->tid_bitmap) {
+		dp_peer_err("tid_bitmap=0. All tids setup fail");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+
+static inline QDF_STATUS
+dp_peer_rx_reorder_multi_q_setup(struct dp_peer *peer,
+				 uint32_t tid_bitmap,
+				 uint32_t ba_window_size)
+{
+	QDF_STATUS status;
+	struct dp_soc *soc = peer->vdev->pdev->soc;
+	struct multi_rx_reorder_queue_setup_params tid_params = {0};
+
+	if (!soc->cdp_soc.ol_ops->peer_multi_rx_reorder_queue_setup) {
+		dp_peer_debug("%pK: callback NULL", soc);
+		return QDF_STATUS_SUCCESS;
+	}
+
+	status = dp_peer_multi_tid_params_setup(peer, tid_bitmap,
+						ba_window_size,
+						&tid_params);
+	if (qdf_unlikely(QDF_IS_STATUS_ERROR(status)))
+		return status;
+
+	if (soc->cdp_soc.ol_ops->peer_multi_rx_reorder_queue_setup(
+	    soc->ctrl_psoc,
+	    peer->vdev->pdev->pdev_id,
+	    &tid_params)) {
+		dp_peer_err("%pK: multi_reorder_q_setup fail. tid_bitmap 0x%x",
+			    soc, tid_bitmap);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+
 #ifdef WLAN_FEATURE_11BE_MLO
 /**
  * dp_rx_mlo_igmp_handler() - Rx handler for Mcast packets
@@ -293,11 +411,11 @@ bool dp_rx_mlo_igmp_handler(struct dp_soc *soc,
 			    uint8_t link_id);
 
 /**
- * dp_peer_rx_reorder_queue_setup_be() - Send reo queue setup wmi cmd to FW
- *					 per peer type
+ * dp_peer_rx_reorder_queue_setup_be() - Send reo queue
+ *        setup wmi cmd to FW per peer type
  * @soc: DP Soc handle
  * @peer: dp peer to operate on
- * @tid: TID
+ * @tid_bitmap: TIDs to be set up
  * @ba_window_size: BlockAck window size
  *
  * Return: 0 - success, others - failure
@@ -305,70 +423,17 @@ bool dp_rx_mlo_igmp_handler(struct dp_soc *soc,
 static inline
 QDF_STATUS dp_peer_rx_reorder_queue_setup_be(struct dp_soc *soc,
 					     struct dp_peer *peer,
-					     int tid,
+					     uint32_t tid_bitmap,
 					     uint32_t ba_window_size)
 {
 	uint8_t i;
 	struct dp_mld_link_peers link_peers_info;
 	struct dp_peer *link_peer;
 	struct dp_rx_tid *rx_tid;
-	struct dp_soc *link_peer_soc;
-
-	rx_tid = &peer->rx_tid[tid];
-	if (!rx_tid->hw_qdesc_paddr)
-		return QDF_STATUS_E_INVAL;
-
-	if (!hal_reo_shared_qaddr_is_enable(soc->hal_soc)) {
-		if (IS_MLO_DP_MLD_PEER(peer)) {
-			/* get link peers with reference */
-			dp_get_link_peers_ref_from_mld_peer(soc, peer,
-							    &link_peers_info,
-							    DP_MOD_ID_CDP);
-			/* send WMI cmd to each link peers */
-			for (i = 0; i < link_peers_info.num_links; i++) {
-				link_peer = link_peers_info.link_peers[i];
-				link_peer_soc = link_peer->vdev->pdev->soc;
-				if (link_peer_soc->cdp_soc.ol_ops->
-						peer_rx_reorder_queue_setup) {
-					if (link_peer_soc->cdp_soc.ol_ops->
-						peer_rx_reorder_queue_setup(
-					    link_peer_soc->ctrl_psoc,
-					    link_peer->vdev->pdev->pdev_id,
-					    link_peer->vdev->vdev_id,
-					    link_peer->mac_addr.raw,
-					    rx_tid->hw_qdesc_paddr,
-					    tid, tid,
-					    1, ba_window_size)) {
-						dp_peer_err("%pK: Failed to send reo queue setup to FW - tid %d\n",
-							    link_peer_soc, tid);
-						return QDF_STATUS_E_FAILURE;
-					}
-				}
-			}
-			/* release link peers reference */
-			dp_release_link_peers_ref(&link_peers_info,
-						  DP_MOD_ID_CDP);
-		} else if (peer->peer_type == CDP_LINK_PEER_TYPE) {
-			if (soc->cdp_soc.ol_ops->peer_rx_reorder_queue_setup) {
-				if (soc->cdp_soc.ol_ops->
-					peer_rx_reorder_queue_setup(
-				    soc->ctrl_psoc,
-				    peer->vdev->pdev->pdev_id,
-				    peer->vdev->vdev_id,
-				    peer->mac_addr.raw,
-				    rx_tid->hw_qdesc_paddr,
-				    tid, tid,
-				    1, ba_window_size)) {
-					dp_peer_err("%pK: Failed to send reo queue setup to FW - tid %d\n",
-						    soc, tid);
-					return QDF_STATUS_E_FAILURE;
-				}
-			}
-		} else {
-			dp_peer_err("invalid peer type %d", peer->peer_type);
-			return QDF_STATUS_E_FAILURE;
-		}
-	} else {
+	int tid;
+	QDF_STATUS status;
+
+	if (hal_reo_shared_qaddr_is_enable(soc->hal_soc)) {
 		/* Some BE targets dont require WMI and use shared
 		 * table managed by host for storing Reo queue ref structs
 		 */
@@ -388,38 +453,86 @@ QDF_STATUS dp_peer_rx_reorder_queue_setup_be(struct dp_soc *soc,
 			return QDF_STATUS_SUCCESS;
 		}
 
-		hal_reo_shared_qaddr_write(soc->hal_soc,
-					   peer->peer_id,
-					   tid, peer->rx_tid[tid].hw_qdesc_paddr);
+		for (tid = 0; tid < DP_MAX_TIDS; tid++) {
+			if (!((1 << tid) & tid_bitmap))
+				continue;
+
+			rx_tid = &peer->rx_tid[tid];
+			if (!rx_tid->hw_qdesc_paddr) {
+				tid_bitmap &= ~BIT(tid);
+				continue;
+			}
+
+			hal_reo_shared_qaddr_write(soc->hal_soc,
+						   peer->peer_id,
+						   tid, peer->rx_tid[tid].
+							hw_qdesc_paddr);
+
+			if (!tid_bitmap) {
+				dp_peer_err("tid_bitmap=0. All tids setup fail");
+				return QDF_STATUS_E_FAILURE;
+			}
+		}
+
+		return QDF_STATUS_SUCCESS;
 	}
+
+	/* when (!hal_reo_shared_qaddr_is_enable(soc->hal_soc)) is true: */
+	if (IS_MLO_DP_MLD_PEER(peer)) {
+		/* get link peers with reference */
+		dp_get_link_peers_ref_from_mld_peer(soc, peer,
+						    &link_peers_info,
+						    DP_MOD_ID_CDP);
+		/* send WMI cmd to each link peers */
+		for (i = 0; i < link_peers_info.num_links; i++) {
+			link_peer = link_peers_info.link_peers[i];
+			if (soc->features.multi_rx_reorder_q_setup_support)
+				status = dp_peer_rx_reorder_multi_q_setup(
+					link_peer, tid_bitmap, ba_window_size);
+			else
+				status = dp_peer_rx_reorder_q_setup_per_tid(
+							link_peer,
+							tid_bitmap,
+							ba_window_size);
+			if (QDF_IS_STATUS_ERROR(status)) {
+				dp_release_link_peers_ref(&link_peers_info, DP_MOD_ID_CDP);
+				return status;
+			}
+		}
+		/* release link peers reference */
+		dp_release_link_peers_ref(&link_peers_info, DP_MOD_ID_CDP);
+	} else if (peer->peer_type == CDP_LINK_PEER_TYPE) {
+		if (soc->features.multi_rx_reorder_q_setup_support)
+			return dp_peer_rx_reorder_multi_q_setup(peer,
+								tid_bitmap,
+								ba_window_size);
+		else
+			return dp_peer_rx_reorder_q_setup_per_tid(peer,
+							tid_bitmap,
+							ba_window_size);
+	} else {
+		dp_peer_err("invalid peer type %d", peer->peer_type);
+
+		return QDF_STATUS_E_FAILURE;
+	}
+
 	return QDF_STATUS_SUCCESS;
 }
 #else
 static inline
 QDF_STATUS dp_peer_rx_reorder_queue_setup_be(struct dp_soc *soc,
 					     struct dp_peer *peer,
-					     int tid,
+					     uint32_t tid_bitmap,
 					     uint32_t ba_window_size)
 {
-	struct dp_rx_tid *rx_tid = &peer->rx_tid[tid];
-
-	if (!rx_tid->hw_qdesc_paddr)
-		return QDF_STATUS_E_INVAL;
-
-	if (soc->cdp_soc.ol_ops->peer_rx_reorder_queue_setup) {
-		if (soc->cdp_soc.ol_ops->peer_rx_reorder_queue_setup(
-		    soc->ctrl_psoc,
-		    peer->vdev->pdev->pdev_id,
-		    peer->vdev->vdev_id,
-		    peer->mac_addr.raw, rx_tid->hw_qdesc_paddr, tid, tid,
-		    1, ba_window_size)) {
-			dp_peer_err("%pK: Failed to send reo queue setup to FW - tid %d\n",
-				    soc, tid);
-			return QDF_STATUS_E_FAILURE;
-		}
-	}
-
-	return QDF_STATUS_SUCCESS;
+	if (soc->features.multi_rx_reorder_q_setup_support)
+		return dp_peer_rx_reorder_multi_q_setup(peer,
+							tid_bitmap,
+							ba_window_size);
+	else
+		return dp_peer_rx_reorder_q_setup_per_tid(peer,
+							  tid_bitmap,
+							  ba_window_size);
 }
 #endif /* WLAN_FEATURE_11BE_MLO */
 

+ 5 - 0
dp/wifi3.0/dp_main.c

@@ -11222,6 +11222,11 @@ static QDF_STATUS dp_soc_set_param(struct cdp_soc_t  *soc_hdl,
 		dp_info("UMAC HW reset support :%u",
 			soc->features.umac_hw_reset_support);
 		break;
+	case DP_SOC_PARAM_MULTI_RX_REORDER_SETUP_SUPPORT:
+		soc->features.multi_rx_reorder_q_setup_support = value;
+		dp_info("Multi rx reorder queue setup support: %u",
+			soc->features.multi_rx_reorder_q_setup_support);
+		break;
 	default:
 		dp_info("not handled param %d ", param);
 		break;

+ 2 - 2
dp/wifi3.0/dp_rx.h

@@ -2905,10 +2905,10 @@ end:
 
 static inline QDF_STATUS
 dp_peer_rx_reorder_queue_setup(struct dp_soc *soc, struct dp_peer *peer,
-			       int tid, uint32_t ba_window_size)
+			       uint32_t tid_bitmap, uint32_t ba_window_size)
 {
 	return soc->arch_ops.dp_peer_rx_reorder_queue_setup(soc,
-							    peer, tid,
+							    peer, tid_bitmap,
 							    ba_window_size);
 }
 

+ 133 - 39
dp/wifi3.0/dp_rx_tid.c

@@ -391,7 +391,7 @@ dp_rx_tid_update_wifi3(struct dp_peer *peer, int tid, uint32_t ba_window_size,
 
 	if (!bar_update)
 		dp_peer_rx_reorder_queue_setup(soc, peer,
-					       tid, ba_window_size);
+					       BIT(tid), ba_window_size);
 
 	return QDF_STATUS_SUCCESS;
 }
@@ -577,8 +577,37 @@ static inline int dp_reo_desc_addr_chk(qdf_dma_addr_t dma_addr)
 }
 #endif
 
-QDF_STATUS dp_rx_tid_setup_wifi3(struct dp_peer *peer, int tid,
-				 uint32_t ba_window_size, uint32_t start_seq)
+static inline void
+dp_rx_tid_setup_error_process(uint32_t tid_bitmap, struct dp_peer *peer)
+{
+	struct dp_rx_tid *rx_tid;
+	int tid;
+	struct dp_soc *soc = peer->vdev->pdev->soc;
+
+	for (tid = 0; tid < DP_MAX_TIDS; tid++) {
+		if (!(BIT(tid) & tid_bitmap))
+			continue;
+
+		rx_tid = &peer->rx_tid[tid];
+		if (!rx_tid->hw_qdesc_vaddr_unaligned)
+			continue;
+
+		if (dp_reo_desc_addr_chk(rx_tid->hw_qdesc_paddr) ==
+		    QDF_STATUS_SUCCESS)
+			qdf_mem_unmap_nbytes_single(
+				soc->osdev,
+				rx_tid->hw_qdesc_paddr,
+				QDF_DMA_BIDIRECTIONAL,
+				rx_tid->hw_qdesc_alloc_size);
+		qdf_mem_free(rx_tid->hw_qdesc_vaddr_unaligned);
+		rx_tid->hw_qdesc_vaddr_unaligned = NULL;
+		rx_tid->hw_qdesc_paddr = 0;
+	}
+}
+
+static QDF_STATUS
+dp_single_rx_tid_setup(struct dp_peer *peer, int tid,
+		       uint32_t ba_window_size, uint32_t start_seq)
 {
 	struct dp_rx_tid *rx_tid = &peer->rx_tid[tid];
 	struct dp_vdev *vdev = peer->vdev;
@@ -591,19 +620,6 @@ QDF_STATUS dp_rx_tid_setup_wifi3(struct dp_peer *peer, int tid,
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
 	struct dp_txrx_peer *txrx_peer;
 
-	if (!qdf_atomic_read(&peer->is_default_route_set))
-		return QDF_STATUS_E_FAILURE;
-
-	if (!dp_rx_tid_setup_allow(peer)) {
-		dp_peer_info("skip rx tid setup for peer" QDF_MAC_ADDR_FMT,
-			     QDF_MAC_ADDR_REF(peer->mac_addr.raw));
-		goto send_wmi_reo_cmd;
-	}
-
-	rx_tid->ba_win_size = ba_window_size;
-	if (rx_tid->hw_qdesc_vaddr_unaligned)
-		return dp_rx_tid_update_wifi3(peer, tid, ba_window_size,
-			start_seq, false);
 	rx_tid->delba_tx_status = 0;
 	rx_tid->ppdu_id_2k = 0;
 	rx_tid->num_of_addba_req = 0;
@@ -713,37 +729,112 @@ try_desc_alloc:
 			rx_tid->hw_qdesc_vaddr_unaligned = NULL;
 			goto try_desc_alloc;
 		} else {
-			dp_peer_err("%pK: Rx tid HW desc alloc failed (lowmem): tid %d",
+			dp_peer_err("%pK: Rx tid %d desc alloc fail (lowmem)",
 				    soc, tid);
 			status = QDF_STATUS_E_NOMEM;
 			goto error;
 		}
 	}
 
+	return QDF_STATUS_SUCCESS;
+
+error:
+	dp_rx_tid_setup_error_process(1 << tid, peer);
+
+	return status;
+}
+
+QDF_STATUS dp_rx_tid_setup_wifi3(struct dp_peer *peer,
+				 uint32_t tid_bitmap,
+				 uint32_t ba_window_size,
+				 uint32_t start_seq)
+{
+	QDF_STATUS status;
+	int tid;
+	struct dp_rx_tid *rx_tid;
+	struct dp_vdev *vdev = peer->vdev;
+	struct dp_soc *soc = vdev->pdev->soc;
+	uint8_t setup_fail_cnt = 0;
+
+	if (!qdf_atomic_read(&peer->is_default_route_set))
+		return QDF_STATUS_E_FAILURE;
+
+	if (!dp_rx_tid_setup_allow(peer)) {
+		dp_peer_info("skip rx tid setup for peer" QDF_MAC_ADDR_FMT,
+			     QDF_MAC_ADDR_REF(peer->mac_addr.raw));
+		goto send_wmi_reo_cmd;
+	}
+
+	dp_peer_info("tid_bitmap 0x%x, ba_window_size %d, start_seq %d",
+		     tid_bitmap, ba_window_size, start_seq);
+
+	for (tid = 0; tid < DP_MAX_TIDS; tid++) {
+		if (!(BIT(tid) & tid_bitmap))
+			continue;
+
+		rx_tid = &peer->rx_tid[tid];
+		rx_tid->ba_win_size = ba_window_size;
+		if (rx_tid->hw_qdesc_vaddr_unaligned) {
+			status = dp_rx_tid_update_wifi3(peer, tid,
+					ba_window_size, start_seq, false);
+			if (QDF_IS_STATUS_ERROR(status)) {
+				/* Not continue to update other tid(s) and
+				 * return even if they have not been set up.
+				 */
+				dp_peer_err("Update tid %d fail", tid);
+				return status;
+			}
+
+			dp_peer_info("Update tid %d", tid);
+			tid_bitmap &= ~BIT(tid);
+			continue;
+		}
+
+		status = dp_single_rx_tid_setup(peer, tid,
+						ba_window_size, start_seq);
+		if (QDF_IS_STATUS_ERROR(status)) {
+			dp_peer_err("Set up tid %d fail, status=%d",
+				    tid, status);
+			tid_bitmap &= ~BIT(tid);
+			setup_fail_cnt++;
+			continue;
+		}
+	}
+
+	/* tid_bitmap == 0 means there is no tid(s) for further setup */
+	if (!tid_bitmap) {
+		dp_peer_info("tid_bitmap=0, no tid setup, setup_fail_cnt %d",
+			     setup_fail_cnt);
+
+		/*  If setup_fail_cnt==0, all tid(s) has been
+		 * successfully updated, so we return success.
+		 */
+		if (!setup_fail_cnt)
+			return QDF_STATUS_SUCCESS;
+		else
+			return QDF_STATUS_E_FAILURE;
+	}
+
 send_wmi_reo_cmd:
 	if (dp_get_peer_vdev_roaming_in_progress(peer)) {
 		status = QDF_STATUS_E_PERM;
 		goto error;
 	}
 
+	dp_peer_info("peer %pK, tids 0x%x, multi_reo %d, s_seq %d, w_size %d",
+		      peer, tid_bitmap,
+		      soc->features.multi_rx_reorder_q_setup_support,
+		      start_seq, ba_window_size);
+
 	status = dp_peer_rx_reorder_queue_setup(soc, peer,
-						tid, ba_window_size);
+						tid_bitmap,
+						ba_window_size);
 	if (QDF_IS_STATUS_SUCCESS(status))
 		return status;
 
 error:
-	if (rx_tid->hw_qdesc_vaddr_unaligned) {
-		if (dp_reo_desc_addr_chk(rx_tid->hw_qdesc_paddr) ==
-		    QDF_STATUS_SUCCESS)
-			qdf_mem_unmap_nbytes_single(
-				soc->osdev,
-				rx_tid->hw_qdesc_paddr,
-				QDF_DMA_BIDIRECTIONAL,
-				rx_tid->hw_qdesc_alloc_size);
-		qdf_mem_free(rx_tid->hw_qdesc_vaddr_unaligned);
-		rx_tid->hw_qdesc_vaddr_unaligned = NULL;
-		rx_tid->hw_qdesc_paddr = 0;
-	}
+	dp_rx_tid_setup_error_process(tid_bitmap, peer);
+
 	return status;
 }
 
@@ -1071,13 +1162,16 @@ static int dp_rx_tid_delete_wifi3(struct dp_peer *peer, int tid)
 static void dp_peer_setup_remaining_tids(struct dp_peer *peer)
 {
 	int tid;
+	uint32_t tid_bitmap = 0;
 
-	for (tid = 1; tid < DP_MAX_TIDS-1; tid++) {
-		dp_rx_tid_setup_wifi3(peer, tid, 1, 0);
-		dp_peer_debug("Setting up TID %d for peer %pK peer->local_id %d",
-			      tid, peer, peer->local_id);
-	}
+	for (tid = 1; tid < DP_MAX_TIDS-1; tid++)
+		tid_bitmap |= BIT(tid);
+
+	dp_peer_info("Sett up tid_bitmap 0x%x for peer %pK peer->local_id %d",
+		     tid_bitmap, peer, peer->local_id);
+	dp_rx_tid_setup_wifi3(peer, tid_bitmap, 1, 0);
 }
+
 #else
 static void dp_peer_setup_remaining_tids(struct dp_peer *peer) {};
 #endif
@@ -1159,7 +1253,7 @@ void dp_peer_rx_tid_setup(struct dp_peer *peer)
 	dp_peer_rx_tids_init(peer);
 
 	/* Setup default (non-qos) rx tid queue */
-	dp_rx_tid_setup_wifi3(peer, DP_NON_QOS_TID, 1, 0);
+	dp_rx_tid_setup_wifi3(peer, BIT(DP_NON_QOS_TID), 1, 0);
 
 	/* Setup rx tid queue for TID 0.
 	 * Other queues will be setup on receiving first packet, which will cause
@@ -1171,11 +1265,11 @@ void dp_peer_rx_tid_setup(struct dp_peer *peer)
 	if (qdf_unlikely(vdev->mesh_vdev) ||
 	    qdf_unlikely(txrx_peer->nawds_enabled))
 		dp_rx_tid_setup_wifi3(
-				peer, 0,
+				peer, BIT(0),
 				hal_get_rx_max_ba_window(soc->hal_soc, 0),
 				0);
 	else
-		dp_rx_tid_setup_wifi3(peer, 0, 1, 0);
+		dp_rx_tid_setup_wifi3(peer, BIT(0), 1, 0);
 
 	/*
 	 * Setup the rest of TID's to handle LFR
@@ -1562,7 +1656,7 @@ int dp_addba_requestprocess_wifi3(struct cdp_soc_t *cdp_soc,
 
 	dp_check_ba_buffersize(peer, tid, buffersize);
 
-	if (dp_rx_tid_setup_wifi3(peer, tid,
+	if (dp_rx_tid_setup_wifi3(peer, BIT(tid),
 	    rx_tid->ba_win_size, startseqnum)) {
 		rx_tid->ba_status = DP_RX_BA_INACTIVE;
 		qdf_spin_unlock_bh(&rx_tid->tid_lock);

+ 3 - 3
dp/wifi3.0/dp_rx_tid.h

@@ -45,15 +45,15 @@ void dp_rx_tid_stats_cb(struct dp_soc *soc, void *cb_ctxt,
 void dp_peer_rx_cleanup(struct dp_vdev *vdev, struct dp_peer *peer);
 
 /**
- * dp_rx_tid_setup_wifi3() - Setup receive TID state
+ * dp_rx_tid_setup_wifi3() - Set up receive TID state
  * @peer: Datapath peer handle
- * @tid: TID
+ * @tid_bitmap: TIDs to be set up
  * @ba_window_size: BlockAck window size
  * @start_seq: Starting sequence number
  *
  * Return: QDF_STATUS code
  */
-QDF_STATUS dp_rx_tid_setup_wifi3(struct dp_peer *peer, int tid,
+QDF_STATUS dp_rx_tid_setup_wifi3(struct dp_peer *peer, uint32_t tid_bitmap,
 				 uint32_t ba_window_size, uint32_t start_seq);
 
 /**

+ 3 - 1
dp/wifi3.0/dp_types.h

@@ -2469,7 +2469,7 @@ struct dp_arch_ops {
 				      enum peer_stats_type stats_type);
 	QDF_STATUS (*dp_peer_rx_reorder_queue_setup)(struct dp_soc *soc,
 						     struct dp_peer *peer,
-						     int tid,
+						     uint32_t tid_bitmap,
 						     uint32_t ba_window_size);
 	void (*dp_bank_reconfig)(struct dp_soc *soc, struct dp_vdev *vdev);
 
@@ -2572,6 +2572,7 @@ struct dp_arch_ops {
  * @rssi_dbm_conv_support: Rssi dbm conversion support param.
  * @umac_hw_reset_support: UMAC HW reset support
  * @wds_ext_ast_override_enable:
+ * @multi_rx_reorder_q_setup_support: multi rx reorder q setup at a time support
  */
 struct dp_soc_features {
 	uint8_t pn_in_reo_dest:1,
@@ -2579,6 +2580,7 @@ struct dp_soc_features {
 	bool rssi_dbm_conv_support;
 	bool umac_hw_reset_support;
 	bool wds_ext_ast_override_enable;
+	bool multi_rx_reorder_q_setup_support;
 };
 
 enum sysfs_printing_mode {

+ 2 - 2
dp/wifi3.0/li/dp_li_rx.c

@@ -1528,11 +1528,11 @@ dp_rx_null_q_desc_handle_li(struct dp_soc *soc, qdf_nbuf_t nbuf,
 				if (qdf_unlikely(vdev->mesh_vdev) ||
 				    qdf_unlikely(txrx_peer->nawds_enabled))
 					dp_rx_tid_setup_wifi3(
-						peer, tid,
+						peer, BIT(tid),
 						hal_get_rx_max_ba_window(soc->hal_soc,tid),
 						IEEE80211_SEQ_MAX);
 				else
-					dp_rx_tid_setup_wifi3(peer, tid, 1,
+					dp_rx_tid_setup_wifi3(peer, BIT(tid), 1,
 							      IEEE80211_SEQ_MAX);
 			}
 			qdf_spin_unlock_bh(&rx_tid->tid_lock);

+ 23 - 6
dp/wifi3.0/li/dp_li_rx.h

@@ -261,25 +261,42 @@ void dp_rx_prefetch_hw_sw_nbuf_desc(struct dp_soc *soc,
 static inline
 QDF_STATUS dp_peer_rx_reorder_queue_setup_li(struct dp_soc *soc,
 					     struct dp_peer *peer,
-					     int tid,
+					     uint32_t tid_bitmap,
 					     uint32_t ba_window_size)
 {
-	struct dp_rx_tid *rx_tid = &peer->rx_tid[tid];
+	int tid;
+	struct dp_rx_tid *rx_tid;
 
-	if (!rx_tid->hw_qdesc_paddr)
-		return QDF_STATUS_E_INVAL;
+	if (!soc->cdp_soc.ol_ops->peer_rx_reorder_queue_setup) {
+		dp_peer_debug("peer_rx_reorder_queue_setup NULL");
+		return QDF_STATUS_SUCCESS;
+	}
+
+	for (tid = 0; tid < DP_MAX_TIDS; tid++) {
+		if (!(BIT(tid) & tid_bitmap))
+			continue;
+
+		rx_tid = &peer->rx_tid[tid];
+		if (!rx_tid->hw_qdesc_paddr) {
+			tid_bitmap &= ~BIT(tid);
+			continue;
+		}
 
-	if (soc->cdp_soc.ol_ops->peer_rx_reorder_queue_setup) {
 		if (soc->cdp_soc.ol_ops->peer_rx_reorder_queue_setup(
 		    soc->ctrl_psoc,
 		    peer->vdev->pdev->pdev_id,
 		    peer->vdev->vdev_id,
 		    peer->mac_addr.raw, rx_tid->hw_qdesc_paddr, tid, tid,
 		    1, ba_window_size)) {
-			dp_peer_err("%pK: Failed to send reo queue setup to FW - tid %d\n",
+			dp_peer_err("%pK: Fail to send reo q setup. tid %d",
 				    soc, tid);
 			return QDF_STATUS_E_FAILURE;
 		}
+
+		if (!tid_bitmap) {
+			dp_peer_err("tid_bitmap=0. All tids setup fail");
+			return QDF_STATUS_E_FAILURE;
+		}
 	}
 
 	return QDF_STATUS_SUCCESS;

+ 2 - 2
dp/wifi3.0/rh/dp_rh_rx.h

@@ -200,7 +200,7 @@ void dp_rx_prefetch_hw_sw_nbuf_desc(struct dp_soc *soc,
  * dp_peer_rx_reorder_queue_setup_rh() - NOP for RH arch implementation
  * @soc: Handle to HAL Soc structure
  * @peer: DP peer structure
- * @tid: tid id
+ * @tid_bitmap: tids to be set up
  * @ba_window_size: BA window size
  *
  * Return: None
@@ -208,7 +208,7 @@ void dp_rx_prefetch_hw_sw_nbuf_desc(struct dp_soc *soc,
 static inline
 QDF_STATUS dp_peer_rx_reorder_queue_setup_rh(struct dp_soc *soc,
 					     struct dp_peer *peer,
-					     int tid,
+					     uint32_t tid_bitmap,
 					     uint32_t ba_window_size)
 {
 	return QDF_STATUS_SUCCESS;

+ 52 - 1
target_if/dp/inc/target_if_dp.h

@@ -31,9 +31,11 @@
 #include <wlan_objmgr_psoc_obj.h>
 #include <target_if.h>
 #include <cdp_txrx_ops.h>
+#include <wlan_cfg.h>
 
 #define PEER_ROUTING_LMAC_ID_INDEX	6
 #define PEER_ROUTING_LMAC_ID_BITS	2
+
 /**
  * struct reorder_q_setup - reorder queue setup params
  * @psoc: psoc
@@ -58,6 +60,41 @@ struct reorder_q_setup {
 	uint16_t ba_window_size;
 };
 
+/**
+ * struct reorder_q_setup_list - Specific tid params for each tid
+ * @hw_qdesc_paddr: hw queue descriptor
+ * @queue_no: queue number
+ * @ba_window_size: BA window size
+ * @ba_window_size_valid: BA window size validity flag
+ */
+struct reorder_q_setup_list {
+	qdf_dma_addr_t hw_qdesc_paddr;
+	uint16_t queue_no;
+	uint16_t ba_window_size;
+	uint8_t ba_window_size_valid;
+};
+
+/**
+ * struct multi_reorder_q_setup - multi reorder queue setup
+ *	params for setting up TIDs at a time
+ * @q_setup_list:  An array for recording the specific params for each tid
+ * @peer_mac: peer mac address
+ * @psoc: psoc
+ * @vdev_id: vdev id
+ * @pdev_id: pdev id
+ * @tid_num: Total number of TIDs to be set up
+ * @tid_bitmap: TIDs to be set up
+ */
+struct multi_reorder_q_setup {
+	struct reorder_q_setup_list q_setup_list[DP_MAX_TIDS];
+	uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
+	struct cdp_ctrl_objmgr_psoc *psoc;
+	uint8_t vdev_id;
+	uint8_t pdev_id;
+	uint8_t tid_num;
+	uint32_t tid_bitmap;
+};
+
 /**
  * target_if_get_active_mac_phy_number() - Get max MAC-PHY number enabled by
  * target
@@ -88,7 +125,7 @@ target_if_peer_set_default_routing(struct cdp_ctrl_objmgr_psoc *psoc,
 				   bool hash_based, uint8_t ring_num,
 				   uint8_t lmac_peer_id_msb);
 /**
- * target_if_peer_rx_reorder_queue_setup() - setup rx reorder queue
+ * target_if_peer_rx_reorder_queue_setup() - set up rx reorder queue
  * @psoc: psoc pointer
  * @pdev_id: pdev id
  * @vdev_id: vdev id
@@ -110,6 +147,20 @@ target_if_peer_rx_reorder_queue_setup(struct cdp_ctrl_objmgr_psoc *psoc,
 				      uint8_t ba_window_size_valid,
 				      uint16_t ba_window_size);
 
+/**
+ * target_if_peer_multi_rx_reorder_queue_setup() - set up multi rx reorder queue
+ * @psoc: psoc pointer
+ * @pdev_id: pdev id
+ * @tid_params: TIDs with their parameters to be set
+ *
+ * return: QDF_STATUS_SUCCESS for success or error code
+ */
+QDF_STATUS
+target_if_peer_multi_rx_reorder_queue_setup(
+	struct cdp_ctrl_objmgr_psoc *psoc,
+	uint8_t pdev_id,
+	struct multi_rx_reorder_queue_setup_params *tid_params);
+
 /**
  * target_if_peer_rx_reorder_queue_remove() - remove rx reorder queue
  * @psoc: psoc pointer

+ 136 - 2
target_if/dp/src/target_if_dp.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2019-2020 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -155,6 +155,66 @@ out:
 	return status;
 }
 
+static QDF_STATUS
+target_if_multi_rx_reorder_queue_setup(struct scheduler_msg *msg)
+{
+	struct multi_rx_reorder_queue_setup_params param = {0};
+	struct wmi_unified *pdev_wmi_handle;
+	struct multi_reorder_q_setup *q_params;
+	QDF_STATUS status;
+	struct wlan_objmgr_pdev *pdev;
+	struct wlan_objmgr_psoc *psoc;
+	int tid;
+
+	if (!(msg->bodyptr)) {
+		target_if_err("rx_reorder: Invalid message body");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	q_params = msg->bodyptr;
+	psoc = (struct wlan_objmgr_psoc *)q_params->psoc;
+
+	pdev = wlan_objmgr_get_pdev_by_id(psoc, q_params->pdev_id,
+					  WLAN_PDEV_TARGET_IF_ID);
+	if (!pdev) {
+		target_if_err("pdev with id %d is NULL", q_params->pdev_id);
+		return QDF_STATUS_E_INVAL;
+	}
+
+	pdev_wmi_handle = lmac_get_pdev_wmi_handle(pdev);
+	if (!pdev_wmi_handle) {
+		target_if_err("pdev wmi handle NULL");
+		status = QDF_STATUS_E_FAILURE;
+		goto out;
+	}
+
+	param.tid_bitmap = q_params->tid_bitmap;
+	param.vdev_id = q_params->vdev_id;
+	param.peer_macaddr = q_params->peer_mac;
+	param.tid_num = q_params->tid_num;
+
+	for (tid = 0; tid < DP_MAX_TIDS; tid++) {
+		if (!(BIT(tid) & q_params->tid_bitmap))
+			continue;
+		param.queue_params_list[tid].hw_qdesc_paddr =
+			q_params->q_setup_list[tid].hw_qdesc_paddr;
+		param.queue_params_list[tid].queue_no =
+			q_params->q_setup_list[tid].queue_no;
+		param.queue_params_list[tid].ba_window_size_valid =
+			q_params->q_setup_list[tid].ba_window_size_valid;
+		param.queue_params_list[tid].ba_window_size =
+			q_params->q_setup_list[tid].ba_window_size;
+	}
+
+	status = wmi_unified_peer_multi_rx_reorder_queue_setup_send(
+		pdev_wmi_handle, &param);
+out:
+	wlan_objmgr_pdev_release_ref(pdev, WLAN_PDEV_TARGET_IF_ID);
+	qdf_mem_free(q_params);
+
+	return status;
+}
+
 QDF_STATUS
 target_if_peer_rx_reorder_queue_setup(struct cdp_ctrl_objmgr_psoc *psoc,
 				      uint8_t pdev_id,
@@ -194,8 +254,53 @@ target_if_peer_rx_reorder_queue_setup(struct cdp_ctrl_objmgr_psoc *psoc,
 	return status;
 }
 
-#else
+QDF_STATUS
+target_if_peer_multi_rx_reorder_queue_setup(struct cdp_ctrl_objmgr_psoc *psoc,
+		uint8_t pdev_id,
+		struct multi_rx_reorder_queue_setup_params *tid_params)
+{
+	struct scheduler_msg msg = {0};
+	struct multi_reorder_q_setup *q_params;
+	QDF_STATUS status;
+	int tid;
 
+	q_params = qdf_mem_malloc(sizeof(*q_params));
+	if (!q_params)
+		return QDF_STATUS_E_NOMEM;
+
+	q_params->psoc = psoc;
+	q_params->vdev_id = tid_params->vdev_id;
+	q_params->pdev_id = pdev_id;
+	q_params->tid_bitmap = tid_params->tid_bitmap;
+	q_params->tid_num = tid_params->tid_num;
+	qdf_mem_copy(q_params->peer_mac, tid_params->peer_macaddr,
+		     QDF_MAC_ADDR_SIZE);
+
+	for (tid = 0; tid < DP_MAX_TIDS; tid++) {
+		if (!(BIT(tid) & tid_params->tid_bitmap))
+			continue;
+		q_params->q_setup_list[tid].hw_qdesc_paddr =
+			tid_params->queue_params_list[tid].hw_qdesc_paddr;
+		q_params->q_setup_list[tid].queue_no =
+			tid_params->queue_params_list[tid].queue_no;
+		q_params->q_setup_list[tid].ba_window_size_valid =
+			tid_params->queue_params_list[tid].ba_window_size_valid;
+		q_params->q_setup_list[tid].ba_window_size =
+			tid_params->queue_params_list[tid].ba_window_size;
+	}
+
+	msg.bodyptr = q_params;
+	msg.callback = target_if_multi_rx_reorder_queue_setup;
+	status = scheduler_post_message(QDF_MODULE_ID_TARGET_IF,
+					QDF_MODULE_ID_TARGET_IF,
+					QDF_MODULE_ID_TARGET_IF, &msg);
+
+	if (status != QDF_STATUS_SUCCESS)
+		qdf_mem_free(q_params);
+
+	return status;
+}
+#else
 QDF_STATUS
 target_if_peer_rx_reorder_queue_setup(struct cdp_ctrl_objmgr_psoc *psoc,
 				      uint8_t pdev_id,
@@ -238,6 +343,35 @@ target_if_peer_rx_reorder_queue_setup(struct cdp_ctrl_objmgr_psoc *psoc,
 
 	return status;
 }
+
+QDF_STATUS
+target_if_peer_multi_rx_reorder_queue_setup(struct cdp_ctrl_objmgr_psoc *psoc,
+		uint8_t pdev_id,
+		struct multi_rx_reorder_queue_setup_params *tid_params)
+{
+	struct wmi_unified *pdev_wmi_handle;
+	QDF_STATUS status;
+	struct wlan_objmgr_pdev *pdev =
+		wlan_objmgr_get_pdev_by_id((struct wlan_objmgr_psoc *)psoc,
+					   pdev_id, WLAN_PDEV_TARGET_IF_ID);
+	if (!pdev) {
+		target_if_err("pdev with id %d is NULL", pdev_id);
+		return QDF_STATUS_E_INVAL;
+	}
+
+	pdev_wmi_handle = lmac_get_pdev_wmi_handle(pdev);
+	if (!pdev_wmi_handle) {
+		wlan_objmgr_pdev_release_ref(pdev, WLAN_PDEV_TARGET_IF_ID);
+		target_if_err("pdev wmi handle NULL");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	status = wmi_unified_peer_multi_rx_reorder_queue_setup_send(
+						pdev_wmi_handle, tid_params);
+	wlan_objmgr_pdev_release_ref(pdev, WLAN_PDEV_TARGET_IF_ID);
+
+	return status;
+}
 #endif
 
 QDF_STATUS

+ 5 - 0
target_if/init_deinit/src/init_event_handler.c

@@ -476,6 +476,11 @@ static int init_deinit_service_ready_event_handler(ol_scn_t scn_handle,
 		init_deinit_set_send_init_cmd(psoc, tgt_hdl);
 	}
 
+	if (wmi_service_enabled(wmi_handle,
+			wmi_service_multiple_reorder_queue_setup_support))
+		cdp_soc_set_param(wlan_psoc_get_dp_handle(psoc),
+			DP_SOC_PARAM_MULTI_RX_REORDER_SETUP_SUPPORT, 1);
+
 exit:
 	return err_code;
 }