]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: ath12k: add reo queue lookup table for ML peers
authorRameshkumar Sundaram <quic_ramess@quicinc.com>
Thu, 21 Nov 2024 15:58:03 +0000 (17:58 +0200)
committerKalle Valo <quic_kvalo@quicinc.com>
Mon, 25 Nov 2024 17:02:55 +0000 (19:02 +0200)
Currently reoqueue tid setup uses lookup table (LUT) during peer association,
but for ML peer there will be multiple link peers (belonging to different
underlying firmware) affiliated to each other. Hence the reo queue should be
setup only on one of the links which is the primary link.

Add changes to create separate ML reo queue lookup table for ML peers and use
the same while setting up rx tid for ML peer's primary link. For ML peers use
ml_peer_id instead of peer_id to setup/lookup the reo queue entry in the LUT.

Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00173-QCAHKSWPL_SILICONZ-1
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3

Signed-off-by: Rameshkumar Sundaram <quic_ramess@quicinc.com>
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
Link: https://patch.msgid.link/20241121155806.1862733-6-kvalo@kernel.org
drivers/net/wireless/ath/ath12k/dp.c
drivers/net/wireless/ath/ath12k/dp.h
drivers/net/wireless/ath/ath12k/dp_rx.c
drivers/net/wireless/ath/ath12k/peer.c
drivers/net/wireless/ath/ath12k/peer.h

index 23326e2dfe8d232eddd4de5a7642a53a12465bbb..328be2c635d679e3c55f0711ab4b0999d66216b3 100644 (file)
@@ -1265,15 +1265,23 @@ static void ath12k_dp_reoq_lut_cleanup(struct ath12k_base *ab)
        if (!ab->hw_params->reoq_lut_support)
                return;
 
-       if (!dp->reoq_lut.vaddr)
-               return;
-
-       dma_free_coherent(ab->dev, DP_REOQ_LUT_SIZE,
-                         dp->reoq_lut.vaddr, dp->reoq_lut.paddr);
-       dp->reoq_lut.vaddr = NULL;
-
-       ath12k_hif_write32(ab,
-                          HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO1_QDESC_LUT_BASE0(ab), 0);
+       if (dp->reoq_lut.vaddr) {
+               ath12k_hif_write32(ab,
+                                  HAL_SEQ_WCSS_UMAC_REO_REG +
+                                  HAL_REO1_QDESC_LUT_BASE0(ab), 0);
+               dma_free_coherent(ab->dev, DP_REOQ_LUT_SIZE,
+                                 dp->reoq_lut.vaddr, dp->reoq_lut.paddr);
+               dp->reoq_lut.vaddr = NULL;
+       }
+
+       if (dp->ml_reoq_lut.vaddr) {
+               ath12k_hif_write32(ab,
+                                  HAL_SEQ_WCSS_UMAC_REO_REG +
+                                  HAL_REO1_QDESC_LUT_BASE1(ab), 0);
+               dma_free_coherent(ab->dev, DP_REOQ_LUT_SIZE,
+                                 dp->ml_reoq_lut.vaddr, dp->ml_reoq_lut.paddr);
+               dp->ml_reoq_lut.vaddr = NULL;
+       }
 }
 
 void ath12k_dp_free(struct ath12k_base *ab)
@@ -1599,8 +1607,23 @@ static int ath12k_dp_reoq_lut_setup(struct ath12k_base *ab)
                return -ENOMEM;
        }
 
+       dp->ml_reoq_lut.vaddr = dma_alloc_coherent(ab->dev,
+                                                  DP_REOQ_LUT_SIZE,
+                                                  &dp->ml_reoq_lut.paddr,
+                                                  GFP_KERNEL | __GFP_ZERO);
+       if (!dp->ml_reoq_lut.vaddr) {
+               ath12k_warn(ab, "failed to allocate memory for ML reoq table");
+               dma_free_coherent(ab->dev, DP_REOQ_LUT_SIZE,
+                                 dp->reoq_lut.vaddr, dp->reoq_lut.paddr);
+               dp->reoq_lut.vaddr = NULL;
+               return -ENOMEM;
+       }
+
        ath12k_hif_write32(ab, HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO1_QDESC_LUT_BASE0(ab),
                           dp->reoq_lut.paddr);
+       ath12k_hif_write32(ab, HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO1_QDESC_LUT_BASE1(ab),
+                          dp->ml_reoq_lut.paddr >> 8);
+
        return 0;
 }
 
index 2e05fc19410e89e84cf73f0985f465986599f2e4..a120b7a8477d88a4fb152d5ed9cfbd0d63d24848 100644 (file)
@@ -368,6 +368,7 @@ struct ath12k_dp {
        struct dp_rxdma_mon_ring rxdma_mon_buf_ring;
        struct dp_rxdma_mon_ring tx_mon_buf_ring;
        struct ath12k_reo_q_addr_lut reoq_lut;
+       struct ath12k_reo_q_addr_lut ml_reoq_lut;
 };
 
 /* HTT definitions */
index da3ebdf094c3c05511521622eb8ef5ab73973850..70680f2124e5201eef9c97d486ebcedf894f7c12 100644 (file)
@@ -740,15 +740,22 @@ static void ath12k_peer_rx_tid_qref_setup(struct ath12k_base *ab, u16 peer_id, u
 {
        struct ath12k_reo_queue_ref *qref;
        struct ath12k_dp *dp = &ab->dp;
+       bool ml_peer = false;
 
        if (!ab->hw_params->reoq_lut_support)
                return;
 
-       /* TODO: based on ML peer or not, select the LUT. below assumes non
-        * ML peer
-        */
-       qref = (struct ath12k_reo_queue_ref *)dp->reoq_lut.vaddr +
-                       (peer_id * (IEEE80211_NUM_TIDS + 1) + tid);
+       if (peer_id & ATH12K_PEER_ML_ID_VALID) {
+               peer_id &= ~ATH12K_PEER_ML_ID_VALID;
+               ml_peer = true;
+       }
+
+       if (ml_peer)
+               qref = (struct ath12k_reo_queue_ref *)dp->ml_reoq_lut.vaddr +
+                               (peer_id * (IEEE80211_NUM_TIDS + 1) + tid);
+       else
+               qref = (struct ath12k_reo_queue_ref *)dp->reoq_lut.vaddr +
+                               (peer_id * (IEEE80211_NUM_TIDS + 1) + tid);
 
        qref->info0 = u32_encode_bits(lower_32_bits(paddr),
                                      BUFFER_ADDR_INFO0_ADDR);
@@ -761,15 +768,22 @@ static void ath12k_peer_rx_tid_qref_reset(struct ath12k_base *ab, u16 peer_id, u
 {
        struct ath12k_reo_queue_ref *qref;
        struct ath12k_dp *dp = &ab->dp;
+       bool ml_peer = false;
 
        if (!ab->hw_params->reoq_lut_support)
                return;
 
-       /* TODO: based on ML peer or not, select the LUT. below assumes non
-        * ML peer
-        */
-       qref = (struct ath12k_reo_queue_ref *)dp->reoq_lut.vaddr +
-                       (peer_id * (IEEE80211_NUM_TIDS + 1) + tid);
+       if (peer_id & ATH12K_PEER_ML_ID_VALID) {
+               peer_id &= ~ATH12K_PEER_ML_ID_VALID;
+               ml_peer = true;
+       }
+
+       if (ml_peer)
+               qref = (struct ath12k_reo_queue_ref *)dp->ml_reoq_lut.vaddr +
+                               (peer_id * (IEEE80211_NUM_TIDS + 1) + tid);
+       else
+               qref = (struct ath12k_reo_queue_ref *)dp->reoq_lut.vaddr +
+                               (peer_id * (IEEE80211_NUM_TIDS + 1) + tid);
 
        qref->info0 = u32_encode_bits(0, BUFFER_ADDR_INFO0_ADDR);
        qref->info1 = u32_encode_bits(0, BUFFER_ADDR_INFO1_ADDR) |
@@ -802,7 +816,10 @@ void ath12k_dp_rx_peer_tid_delete(struct ath12k *ar,
                rx_tid->vaddr = NULL;
        }
 
-       ath12k_peer_rx_tid_qref_reset(ar->ab, peer->peer_id, tid);
+       if (peer->mlo)
+               ath12k_peer_rx_tid_qref_reset(ar->ab, peer->ml_id, tid);
+       else
+               ath12k_peer_rx_tid_qref_reset(ar->ab, peer->peer_id, tid);
 
        rx_tid->active = false;
 }
@@ -945,7 +962,8 @@ int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_
                return 0;
        }
 
-       if (ab->hw_params->reoq_lut_support && !dp->reoq_lut.vaddr) {
+       if (ab->hw_params->reoq_lut_support &&
+           (!dp->reoq_lut.vaddr || !dp->ml_reoq_lut.vaddr)) {
                spin_unlock_bh(&ab->base_lock);
                ath12k_warn(ab, "reo qref table is not setup\n");
                return -EINVAL;
@@ -1026,7 +1044,11 @@ int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_
                /* Update the REO queue LUT at the corresponding peer id
                 * and tid with qaddr.
                 */
-               ath12k_peer_rx_tid_qref_setup(ab, peer->peer_id, tid, paddr);
+               if (peer->mlo)
+                       ath12k_peer_rx_tid_qref_setup(ab, peer->ml_id, tid, paddr);
+               else
+                       ath12k_peer_rx_tid_qref_setup(ab, peer->peer_id, tid, paddr);
+
                spin_unlock_bh(&ab->base_lock);
        } else {
                spin_unlock_bh(&ab->base_lock);
index 25905498e8fb3596f57a6d3a2b644f5667f0ed41..5763c5a40cfc3ed5c663a2d09df07f464148232e 100644 (file)
@@ -396,9 +396,11 @@ int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif,
 
                        /* the assoc link is considered primary for now */
                        peer->primary_link = arsta->is_assoc_link;
+                       peer->mlo = true;
                } else {
                        peer->ml_id = ATH12K_MLO_PEER_ID_INVALID;
                        peer->primary_link = true;
+                       peer->mlo = false;
                }
        }
 
index a39e943bd66b13fef92ffb7d72f5d34b05430995..7e6231cb2b529c863e0ced9a7a4318d8d4141b9c 100644 (file)
@@ -46,7 +46,7 @@ struct ath12k_peer {
        struct ppdu_user_delayba ppdu_stats_delayba;
        bool delayba_flag;
        bool is_authorized;
-
+       bool mlo;
        /* protected by ab->data_lock */
        bool dp_setup_done;