diff --git a/dp/inc/cdp_txrx_ops.h b/dp/inc/cdp_txrx_ops.h index 82871aca06..204f423cb8 100644 --- a/dp/inc/cdp_txrx_ops.h +++ b/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, diff --git a/dp/inc/cdp_txrx_stats_struct.h b/dp/inc/cdp_txrx_stats_struct.h index 8ee6cfab66..26467a08b9 100644 --- a/dp/inc/cdp_txrx_stats_struct.h +++ b/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, }; diff --git a/dp/wifi3.0/be/dp_be_rx.c b/dp/wifi3.0/be/dp_be_rx.c index 9e3deec1b8..4053d6b68a 100644 --- a/dp/wifi3.0/be/dp_be_rx.c +++ b/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); diff --git a/dp/wifi3.0/be/dp_be_rx.h b/dp/wifi3.0/be/dp_be_rx.h index bbdd5b94b3..3f0e0fb93c 100644 --- a/dp/wifi3.0/be/dp_be_rx.h +++ b/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; + int tid; + QDF_STATUS status; - 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 { + 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 */ diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 25d2a3d2bf..fd5e417927 100644 --- a/dp/wifi3.0/dp_main.c +++ b/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; diff --git a/dp/wifi3.0/dp_rx.h b/dp/wifi3.0/dp_rx.h index 7e9a548902..2bbd8691a8 100644 --- a/dp/wifi3.0/dp_rx.h +++ b/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); } diff --git a/dp/wifi3.0/dp_rx_tid.c b/dp/wifi3.0/dp_rx_tid.c index 08786ba704..1d40a6380c 100644 --- a/dp/wifi3.0/dp_rx_tid.c +++ b/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); diff --git a/dp/wifi3.0/dp_rx_tid.h b/dp/wifi3.0/dp_rx_tid.h index bcbf45eaab..d9db5c961b 100644 --- a/dp/wifi3.0/dp_rx_tid.h +++ b/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); /** diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index e85eda1ebe..d11a514ce9 100644 --- a/dp/wifi3.0/dp_types.h +++ b/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 { diff --git a/dp/wifi3.0/li/dp_li_rx.c b/dp/wifi3.0/li/dp_li_rx.c index 54e6e9485d..0b194b94ab 100644 --- a/dp/wifi3.0/li/dp_li_rx.c +++ b/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); diff --git a/dp/wifi3.0/li/dp_li_rx.h b/dp/wifi3.0/li/dp_li_rx.h index b7d1f0f3b0..e9218d3c42 100644 --- a/dp/wifi3.0/li/dp_li_rx.h +++ b/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; diff --git a/dp/wifi3.0/rh/dp_rh_rx.h b/dp/wifi3.0/rh/dp_rh_rx.h index 02325637cf..2effc4986e 100644 --- a/dp/wifi3.0/rh/dp_rh_rx.h +++ b/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; diff --git a/target_if/dp/inc/target_if_dp.h b/target_if/dp/inc/target_if_dp.h index 3497f5c983..7320e8f9e3 100644 --- a/target_if/dp/inc/target_if_dp.h +++ b/target_if/dp/inc/target_if_dp.h @@ -31,9 +31,11 @@ #include #include #include +#include #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 diff --git a/target_if/dp/src/target_if_dp.c b/target_if/dp/src/target_if_dp.c index 58aeb9571e..eed84237de 100644 --- a/target_if/dp/src/target_if_dp.c +++ b/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, ¶m); +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 diff --git a/target_if/init_deinit/src/init_event_handler.c b/target_if/init_deinit/src/init_event_handler.c index 2f3bef08a7..639355ace4 100644 --- a/target_if/init_deinit/src/init_event_handler.c +++ b/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; }