linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/9] wifi: ath12k: MLO support part 8
@ 2024-12-09 18:54 Kalle Valo
  2024-12-09 18:54 ` [PATCH 1/9] wifi: ath12k: move to HW link id based reveive handling Kalle Valo
                   ` (10 more replies)
  0 siblings, 11 replies; 14+ messages in thread
From: Kalle Valo @ 2024-12-09 18:54 UTC (permalink / raw)
  To: ath12k; +Cc: linux-wireless

From: Kalle Valo <quic_kvalo@quicinc.com>

Getting MLO to work with QCN9274 is getting close, this should be the second to
last patchset. Small patches this time. Minor changes to data path to support
MLO, some interface combination rework and few fixes.

Please review.

Aditya Kumar Singh (3):
  wifi: ath12k: fix ath12k_qmi_alloc_chunk() to handle too large
    allocations
  wifi: ath12k: fix ar->supports_6ghz usage during hw register
  wifi: ath12k: pass link ID during MLO while delivering skb

Karthikeyan Periyasamy (6):
  wifi: ath12k: move to HW link id based reveive handling
  wifi: ath12k: add partner device buffer support in receive data path
  wifi: ath12k: add helper function to init partner cmem configuration
  wifi: ath12k: introduce interface combination cleanup helper
  wifi: ath12k: Refactor radio frequency information
  wifi: ath12k: advertise multi device interface combination

 drivers/net/wireless/ath/ath12k/core.c   |   5 +-
 drivers/net/wireless/ath/ath12k/core.h   |  17 +-
 drivers/net/wireless/ath/ath12k/dp.c     |  14 ++
 drivers/net/wireless/ath/ath12k/dp.h     |   4 +-
 drivers/net/wireless/ath/ath12k/dp_mon.c |   8 +-
 drivers/net/wireless/ath/ath12k/dp_rx.c  | 213 +++++++++++++------
 drivers/net/wireless/ath/ath12k/mac.c    | 247 +++++++++++++++++++----
 drivers/net/wireless/ath/ath12k/peer.c   |   2 +
 drivers/net/wireless/ath/ath12k/peer.h   |   3 +
 drivers/net/wireless/ath/ath12k/qmi.c    |  10 +-
 10 files changed, 414 insertions(+), 109 deletions(-)


base-commit: 400568fb3b022247c1603fdbdd6444b3ef14ffce
prerequisite-patch-id: 721655de1e9eb1b723c3340c80f52be7ab6e73a7
prerequisite-patch-id: 99576487c570edbaf46b35e8ba6b9e20ad9bf85c
prerequisite-patch-id: f0a242859176e986640595256e7f488561683309
prerequisite-patch-id: 532325a3a8da40d6b43ef643f38dca5389750820
prerequisite-patch-id: 1a0adfd0f7ad52c7d0ddd6466659e7a8a229013b
prerequisite-patch-id: e1a1418434e24374ef1ad04a49249436de602dd8
prerequisite-patch-id: 8847add439503b799079f8cfa043b15b57691d7f
prerequisite-patch-id: 017994ce11ee18d218464d1bb5ffb50ac8d941a5
-- 
2.39.5


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 1/9] wifi: ath12k: move to HW link id based reveive handling
  2024-12-09 18:54 [PATCH 0/9] wifi: ath12k: MLO support part 8 Kalle Valo
@ 2024-12-09 18:54 ` Kalle Valo
  2024-12-09 19:44   ` Jeff Johnson
  2024-12-09 18:54 ` [PATCH 2/9] wifi: ath12k: add partner device buffer support in receive data path Kalle Valo
                   ` (9 subsequent siblings)
  10 siblings, 1 reply; 14+ messages in thread
From: Kalle Valo @ 2024-12-09 18:54 UTC (permalink / raw)
  To: ath12k; +Cc: linux-wireless

From: Karthikeyan Periyasamy <quic_periyasa@quicinc.com>

Currently, all the rx processing treats the hardware link id as the MAC id.
The HW link id is a unique identifier for all hardware links participating in
the multi link group. Therefore, the current MAC id derivation is insufficient
to process the partner rx buffer in the Multi-Link Operation. So derive the
MAC id from the HW link id and implementing this change in rx processing will
enable the scaling of partner buffer processing in Multi-Link Operation.

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: Karthikeyan Periyasamy <quic_periyasa@quicinc.com>
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
---
 drivers/net/wireless/ath/ath12k/core.h  |  8 +++-
 drivers/net/wireless/ath/ath12k/dp_rx.c | 49 +++++++++++++++----------
 drivers/net/wireless/ath/ath12k/mac.c   |  3 ++
 3 files changed, 39 insertions(+), 21 deletions(-)

diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h
index dc01f7b3fd73..9386e9592dff 100644
--- a/drivers/net/wireless/ath/ath12k/core.h
+++ b/drivers/net/wireless/ath/ath12k/core.h
@@ -136,7 +136,7 @@ struct ath12k_skb_rxcb {
 	struct hal_rx_desc *rx_desc;
 	u8 err_rel_src;
 	u8 err_code;
-	u8 mac_id;
+	u8 hw_link_id;
 	u8 unmapped;
 	u8 is_frag;
 	u8 tid;
@@ -831,6 +831,11 @@ struct ath12k_mlo_memory {
 	bool init_done;
 };
 
+struct ath12k_hw_link {
+	u8 device_id;
+	u8 pdev_idx;
+};
+
 /* Holds info on the group of devices that are registered as a single
  * wiphy, protected with struct ath12k_hw_group::mutex.
  */
@@ -857,6 +862,7 @@ struct ath12k_hw_group {
 	bool mlo_capable;
 	struct device_node *wsi_node[ATH12K_MAX_SOCS];
 	struct ath12k_mlo_memory mlo_mem;
+	struct ath12k_hw_link hw_links[ATH12K_GROUP_MAX_RADIO];
 };
 
 /* Holds WSI info specific to each device, excluding WSI group info */
diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c
index 2c919503ddef..d658d4eb1fd7 100644
--- a/drivers/net/wireless/ath/ath12k/dp_rx.c
+++ b/drivers/net/wireless/ath/ath12k/dp_rx.c
@@ -2595,11 +2595,13 @@ static void ath12k_dp_rx_process_received_packets(struct ath12k_base *ab,
 						  struct sk_buff_head *msdu_list,
 						  int ring_id)
 {
+	struct ath12k_hw_group *ag = ab->ag;
 	struct ieee80211_rx_status rx_status = {0};
 	struct ath12k_skb_rxcb *rxcb;
 	struct sk_buff *msdu;
 	struct ath12k *ar;
-	u8 mac_id, pdev_id;
+	struct ath12k_hw_link *hw_links = ag->hw_links;
+	u8 hw_link_id, pdev_id;
 	int ret;
 
 	if (skb_queue_empty(msdu_list))
@@ -2609,8 +2611,10 @@ static void ath12k_dp_rx_process_received_packets(struct ath12k_base *ab,
 
 	while ((msdu = __skb_dequeue(msdu_list))) {
 		rxcb = ATH12K_SKB_RXCB(msdu);
-		mac_id = rxcb->mac_id;
-		pdev_id = ath12k_hw_mac_id_to_pdev_id(ab->hw_params, mac_id);
+		hw_link_id = rxcb->hw_link_id;
+
+		pdev_id = ath12k_hw_mac_id_to_pdev_id(ab->hw_params,
+						      hw_links[hw_link_id].pdev_idx);
 		ar = ab->pdevs[pdev_id].ar;
 		if (!rcu_dereference(ab->pdevs_active[pdev_id])) {
 			dev_kfree_skb_any(msdu);
@@ -2674,7 +2678,7 @@ int ath12k_dp_rx_process(struct ath12k_base *ab, int ring_id,
 	struct hal_srng *srng;
 	struct sk_buff *msdu;
 	bool done = false;
-	int mac_id;
+	u8 hw_link_id;
 	u64 desc_va;
 
 	__skb_queue_head_init(&msdu_list);
@@ -2695,8 +2699,8 @@ int ath12k_dp_rx_process(struct ath12k_base *ab, int ring_id,
 		cookie = le32_get_bits(desc->buf_addr_info.info1,
 				       BUFFER_ADDR_INFO1_SW_COOKIE);
 
-		mac_id = le32_get_bits(desc->info0,
-				       HAL_REO_DEST_RING_INFO0_SRC_LINK_ID);
+		hw_link_id = le32_get_bits(desc->info0,
+					   HAL_REO_DEST_RING_INFO0_SRC_LINK_ID);
 
 		desc_va = ((u64)le32_to_cpu(desc->buf_va_hi) << 32 |
 			   le32_to_cpu(desc->buf_va_lo));
@@ -2745,7 +2749,7 @@ int ath12k_dp_rx_process(struct ath12k_base *ab, int ring_id,
 					RX_MSDU_DESC_INFO0_LAST_MSDU_IN_MPDU);
 		rxcb->is_continuation = !!(le32_to_cpu(msdu_info->info0) &
 					   RX_MSDU_DESC_INFO0_MSDU_CONTINUATION);
-		rxcb->mac_id = mac_id;
+		rxcb->hw_link_id = hw_link_id;
 		rxcb->peer_id = ath12k_dp_rx_get_peer_id(ab, dp->peer_metadata_ver,
 							 mpdu_info->peer_meta_data);
 		rxcb->tid = le32_get_bits(mpdu_info->info0,
@@ -3472,6 +3476,7 @@ ath12k_dp_process_rx_err_buf(struct ath12k *ar, struct hal_reo_dest_ring *desc,
 int ath12k_dp_rx_process_err(struct ath12k_base *ab, struct napi_struct *napi,
 			     int budget)
 {
+	struct ath12k_hw_group *ag = ab->ag;
 	u32 msdu_cookies[HAL_NUM_RX_MSDUS_PER_LINK_DESC];
 	struct dp_link_desc_bank *link_desc_banks;
 	enum hal_rx_buf_return_buf_manager rbm;
@@ -3480,11 +3485,12 @@ int ath12k_dp_rx_process_err(struct ath12k_base *ab, struct napi_struct *napi,
 	struct hal_reo_dest_ring *reo_desc;
 	struct dp_rxdma_ring *rx_ring;
 	struct dp_srng *reo_except;
+	struct ath12k_hw_link *hw_links = ag->hw_links;
 	LIST_HEAD(rx_desc_used_list);
 	u32 desc_bank, num_msdus;
 	struct hal_srng *srng;
 	struct ath12k_dp *dp;
-	int mac_id;
+	u8 hw_link_id;
 	struct ath12k *ar;
 	dma_addr_t paddr;
 	bool is_frag;
@@ -3517,10 +3523,11 @@ int ath12k_dp_rx_process_err(struct ath12k_base *ab, struct napi_struct *napi,
 			continue;
 		}
 
-		mac_id = le32_get_bits(reo_desc->info0,
-				       HAL_REO_DEST_RING_INFO0_SRC_LINK_ID);
+		hw_link_id = le32_get_bits(reo_desc->info0,
+					   HAL_REO_DEST_RING_INFO0_SRC_LINK_ID);
 
-		pdev_id = ath12k_hw_mac_id_to_pdev_id(ab->hw_params, mac_id);
+		pdev_id = ath12k_hw_mac_id_to_pdev_id(ab->hw_params,
+						      hw_links[hw_link_id].pdev_idx);
 		ar = ab->pdevs[pdev_id].ar;
 
 		link_desc_va = link_desc_banks[desc_bank].vaddr +
@@ -3801,9 +3808,10 @@ int ath12k_dp_rx_process_wbm_err(struct ath12k_base *ab,
 	struct sk_buff_head msdu_list, scatter_msdu_list;
 	struct ath12k_skb_rxcb *rxcb;
 	void *rx_desc;
-	u8 mac_id;
+	u8 hw_link_id;
 	int num_buffs_reaped = 0;
 	struct ath12k_rx_desc_info *desc_info;
+	struct ath12k_hw_link *hw_links = ab->ag->hw_links;
 	int ret, pdev_id;
 	struct hal_rx_desc *msdu_data;
 
@@ -3878,9 +3886,9 @@ int ath12k_dp_rx_process_wbm_err(struct ath12k_base *ab,
 			continue;
 		}
 
-		mac_id = ath12k_dp_rx_get_msdu_src_link(ab,
-							msdu_data);
-		if (mac_id >= MAX_RADIOS) {
+		hw_link_id = ath12k_dp_rx_get_msdu_src_link(ab,
+							    msdu_data);
+		if (hw_link_id >= MAX_RADIOS) {
 			dev_kfree_skb_any(msdu);
 
 			/* In any case continuation bit is set
@@ -3895,7 +3903,7 @@ int ath12k_dp_rx_process_wbm_err(struct ath12k_base *ab,
 
 			skb_queue_walk(&scatter_msdu_list, msdu) {
 				rxcb = ATH12K_SKB_RXCB(msdu);
-				rxcb->mac_id = mac_id;
+				rxcb->hw_link_id = hw_link_id;
 			}
 
 			skb_queue_splice_tail_init(&scatter_msdu_list,
@@ -3903,7 +3911,7 @@ int ath12k_dp_rx_process_wbm_err(struct ath12k_base *ab,
 		}
 
 		rxcb = ATH12K_SKB_RXCB(msdu);
-		rxcb->mac_id = mac_id;
+		rxcb->hw_link_id = hw_link_id;
 		__skb_queue_tail(&msdu_list, msdu);
 	}
 
@@ -3925,12 +3933,13 @@ int ath12k_dp_rx_process_wbm_err(struct ath12k_base *ab,
 	rcu_read_lock();
 	while ((msdu = __skb_dequeue(&msdu_list))) {
 		rxcb = ATH12K_SKB_RXCB(msdu);
-		mac_id = rxcb->mac_id;
+		hw_link_id = rxcb->hw_link_id;
 
-		pdev_id = ath12k_hw_mac_id_to_pdev_id(ab->hw_params, mac_id);
+		pdev_id = ath12k_hw_mac_id_to_pdev_id(ab->hw_params,
+						      hw_links[hw_link_id].pdev_idx);
 		ar = ab->pdevs[pdev_id].ar;
 
-		if (!ar || !rcu_dereference(ar->ab->pdevs_active[mac_id])) {
+		if (!ar || !rcu_dereference(ar->ab->pdevs_active[hw_link_id])) {
 			dev_kfree_skb_any(msdu);
 			continue;
 		}
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index 23c5c8fd952d..7e8eb0feb871 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -11050,6 +11050,9 @@ static struct ath12k_hw *ath12k_mac_hw_allocate(struct ath12k_hw_group *ag,
 		ar->pdev_idx = pdev_idx;
 		pdev->ar = ar;
 
+		ag->hw_links[ar->hw_link_id].device_id = ab->device_id;
+		ag->hw_links[ar->hw_link_id].pdev_idx = pdev_idx;
+
 		ath12k_mac_setup(ar);
 		ath12k_dp_pdev_pre_alloc(ar);
 	}
-- 
2.39.5


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 2/9] wifi: ath12k: add partner device buffer support in receive data path
  2024-12-09 18:54 [PATCH 0/9] wifi: ath12k: MLO support part 8 Kalle Valo
  2024-12-09 18:54 ` [PATCH 1/9] wifi: ath12k: move to HW link id based reveive handling Kalle Valo
@ 2024-12-09 18:54 ` Kalle Valo
  2024-12-09 18:54 ` [PATCH 3/9] wifi: ath12k: add helper function to init partner cmem configuration Kalle Valo
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Kalle Valo @ 2024-12-09 18:54 UTC (permalink / raw)
  To: ath12k; +Cc: linux-wireless

From: Karthikeyan Periyasamy <quic_periyasa@quicinc.com>

Currently, partner device buffer is not handled in the receive data path. In
Multi-Link Operation, the partner device buffer is reported to the primary
upper MAC rings. Therefore, add partner device buffer processing in the REO and
Exception ring handler.

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: Karthikeyan Periyasamy <quic_periyasa@quicinc.com>
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
---
 drivers/net/wireless/ath/ath12k/core.h  |   6 +
 drivers/net/wireless/ath/ath12k/dp.c    |   1 +
 drivers/net/wireless/ath/ath12k/dp.h    |   3 +-
 drivers/net/wireless/ath/ath12k/dp_rx.c | 179 +++++++++++++++++-------
 4 files changed, 140 insertions(+), 49 deletions(-)

diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h
index 9386e9592dff..d7caa58bb262 100644
--- a/drivers/net/wireless/ath/ath12k/core.h
+++ b/drivers/net/wireless/ath/ath12k/core.h
@@ -1229,4 +1229,10 @@ static inline void ath12k_core_stopped(struct ath12k_base *ab)
 	ab->ag->num_started--;
 }
 
+static inline struct ath12k_base *ath12k_ag_to_ab(struct ath12k_hw_group *ag,
+						  u8 device_id)
+{
+	return ag->ab[device_id];
+}
+
 #endif /* _CORE_H_ */
diff --git a/drivers/net/wireless/ath/ath12k/dp.c b/drivers/net/wireless/ath/ath12k/dp.c
index 68abe9d4ab45..9a7df54bf570 100644
--- a/drivers/net/wireless/ath/ath12k/dp.c
+++ b/drivers/net/wireless/ath/ath12k/dp.c
@@ -1445,6 +1445,7 @@ static int ath12k_dp_cc_desc_init(struct ath12k_base *ab)
 		for (j = 0; j < ATH12K_MAX_SPT_ENTRIES; j++) {
 			rx_descs[j].cookie = ath12k_dp_cc_cookie_gen(cookie_ppt_idx, j);
 			rx_descs[j].magic = ATH12K_DP_RX_DESC_MAGIC;
+			rx_descs[j].device_id = ab->device_id;
 			list_add_tail(&rx_descs[j].list, &dp->rx_desc_free_list);
 
 			/* Update descriptor VA in SPT */
diff --git a/drivers/net/wireless/ath/ath12k/dp.h b/drivers/net/wireless/ath/ath12k/dp.h
index 021cd9e8ee1d..d3f3d39a1cd0 100644
--- a/drivers/net/wireless/ath/ath12k/dp.h
+++ b/drivers/net/wireless/ath/ath12k/dp.h
@@ -287,7 +287,8 @@ struct ath12k_rx_desc_info {
 	u32 cookie;
 	u32 magic;
 	u8 in_use	: 1,
-	   reserved	: 7;
+	   device_id	: 3,
+	   reserved	: 4;
 };
 
 struct ath12k_tx_desc_info {
diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c
index d658d4eb1fd7..adbd7bbcef6f 100644
--- a/drivers/net/wireless/ath/ath12k/dp_rx.c
+++ b/drivers/net/wireless/ath/ath12k/dp_rx.c
@@ -2601,6 +2601,7 @@ static void ath12k_dp_rx_process_received_packets(struct ath12k_base *ab,
 	struct sk_buff *msdu;
 	struct ath12k *ar;
 	struct ath12k_hw_link *hw_links = ag->hw_links;
+	struct ath12k_base *partner_ab;
 	u8 hw_link_id, pdev_id;
 	int ret;
 
@@ -2612,11 +2613,12 @@ static void ath12k_dp_rx_process_received_packets(struct ath12k_base *ab,
 	while ((msdu = __skb_dequeue(msdu_list))) {
 		rxcb = ATH12K_SKB_RXCB(msdu);
 		hw_link_id = rxcb->hw_link_id;
-
-		pdev_id = ath12k_hw_mac_id_to_pdev_id(ab->hw_params,
+		partner_ab = ath12k_ag_to_ab(ag,
+					     hw_links[hw_link_id].device_id);
+		pdev_id = ath12k_hw_mac_id_to_pdev_id(partner_ab->hw_params,
 						      hw_links[hw_link_id].pdev_idx);
-		ar = ab->pdevs[pdev_id].ar;
-		if (!rcu_dereference(ab->pdevs_active[pdev_id])) {
+		ar = partner_ab->pdevs[pdev_id].ar;
+		if (!rcu_dereference(partner_ab->pdevs_active[pdev_id])) {
 			dev_kfree_skb_any(msdu);
 			continue;
 		}
@@ -2666,23 +2668,29 @@ static u16 ath12k_dp_rx_get_peer_id(struct ath12k_base *ab,
 int ath12k_dp_rx_process(struct ath12k_base *ab, int ring_id,
 			 struct napi_struct *napi, int budget)
 {
-	LIST_HEAD(rx_desc_used_list);
+	struct ath12k_hw_group *ag = ab->ag;
+	struct list_head rx_desc_used_list[ATH12K_MAX_SOCS];
+	struct ath12k_hw_link *hw_links = ag->hw_links;
+	int num_buffs_reaped[ATH12K_MAX_SOCS] = {};
 	struct ath12k_rx_desc_info *desc_info;
 	struct ath12k_dp *dp = &ab->dp;
 	struct dp_rxdma_ring *rx_ring = &dp->rx_refill_buf_ring;
 	struct hal_reo_dest_ring *desc;
-	int num_buffs_reaped = 0;
+	struct ath12k_base *partner_ab;
 	struct sk_buff_head msdu_list;
 	struct ath12k_skb_rxcb *rxcb;
 	int total_msdu_reaped = 0;
+	u8 hw_link_id, device_id;
 	struct hal_srng *srng;
 	struct sk_buff *msdu;
 	bool done = false;
-	u8 hw_link_id;
 	u64 desc_va;
 
 	__skb_queue_head_init(&msdu_list);
 
+	for (device_id = 0; device_id < ATH12K_MAX_SOCS; device_id++)
+		INIT_LIST_HEAD(&rx_desc_used_list[device_id]);
+
 	srng = &ab->hal.srng_list[dp->reo_dst_ring[ring_id].ring_id];
 
 	spin_lock_bh(&srng->lock);
@@ -2706,11 +2714,22 @@ int ath12k_dp_rx_process(struct ath12k_base *ab, int ring_id,
 			   le32_to_cpu(desc->buf_va_lo));
 		desc_info = (struct ath12k_rx_desc_info *)((unsigned long)desc_va);
 
+		device_id = hw_links[hw_link_id].device_id;
+		partner_ab = ath12k_ag_to_ab(ag, device_id);
+		if (unlikely(!partner_ab)) {
+			if (desc_info->skb) {
+				dev_kfree_skb_any(desc_info->skb);
+				desc_info->skb = NULL;
+			}
+
+			continue;
+		}
+
 		/* retry manual desc retrieval */
 		if (!desc_info) {
-			desc_info = ath12k_dp_get_rx_desc(ab, cookie);
+			desc_info = ath12k_dp_get_rx_desc(partner_ab, cookie);
 			if (!desc_info) {
-				ath12k_warn(ab, "Invalid cookie in manual descriptor retrieval: 0x%x\n",
+				ath12k_warn(partner_ab, "Invalid cookie in manual descriptor retrieval: 0x%x\n",
 					    cookie);
 				continue;
 			}
@@ -2722,14 +2741,14 @@ int ath12k_dp_rx_process(struct ath12k_base *ab, int ring_id,
 		msdu = desc_info->skb;
 		desc_info->skb = NULL;
 
-		list_add_tail(&desc_info->list, &rx_desc_used_list);
+		list_add_tail(&desc_info->list, &rx_desc_used_list[device_id]);
 
 		rxcb = ATH12K_SKB_RXCB(msdu);
-		dma_unmap_single(ab->dev, rxcb->paddr,
+		dma_unmap_single(partner_ab->dev, rxcb->paddr,
 				 msdu->len + skb_tailroom(msdu),
 				 DMA_FROM_DEVICE);
 
-		num_buffs_reaped++;
+		num_buffs_reaped[device_id]++;
 
 		push_reason = le32_get_bits(desc->info0,
 					    HAL_REO_DEST_RING_INFO0_PUSH_REASON);
@@ -2786,8 +2805,17 @@ int ath12k_dp_rx_process(struct ath12k_base *ab, int ring_id,
 	if (!total_msdu_reaped)
 		goto exit;
 
-	ath12k_dp_rx_bufs_replenish(ab, rx_ring, &rx_desc_used_list,
-				    num_buffs_reaped);
+	for (device_id = 0; device_id < ATH12K_MAX_SOCS; device_id++) {
+		if (!num_buffs_reaped[device_id])
+			continue;
+
+		partner_ab = ath12k_ag_to_ab(ag, device_id);
+		rx_ring = &partner_ab->dp.rx_refill_buf_ring;
+
+		ath12k_dp_rx_bufs_replenish(partner_ab, rx_ring,
+					    &rx_desc_used_list[device_id],
+					    num_buffs_reaped[device_id]);
+	}
 
 	ath12k_dp_rx_process_received_packets(ab, napi, &msdu_list,
 					      ring_id);
@@ -3477,7 +3505,9 @@ int ath12k_dp_rx_process_err(struct ath12k_base *ab, struct napi_struct *napi,
 			     int budget)
 {
 	struct ath12k_hw_group *ag = ab->ag;
+	struct list_head rx_desc_used_list[ATH12K_MAX_SOCS];
 	u32 msdu_cookies[HAL_NUM_RX_MSDUS_PER_LINK_DESC];
+	int num_buffs_reaped[ATH12K_MAX_SOCS] = {};
 	struct dp_link_desc_bank *link_desc_banks;
 	enum hal_rx_buf_return_buf_manager rbm;
 	struct hal_rx_msdu_link *link_desc_va;
@@ -3486,11 +3516,10 @@ int ath12k_dp_rx_process_err(struct ath12k_base *ab, struct napi_struct *napi,
 	struct dp_rxdma_ring *rx_ring;
 	struct dp_srng *reo_except;
 	struct ath12k_hw_link *hw_links = ag->hw_links;
-	LIST_HEAD(rx_desc_used_list);
+	struct ath12k_base *partner_ab;
+	u8 hw_link_id, device_id;
 	u32 desc_bank, num_msdus;
 	struct hal_srng *srng;
-	struct ath12k_dp *dp;
-	u8 hw_link_id;
 	struct ath12k *ar;
 	dma_addr_t paddr;
 	bool is_frag;
@@ -3500,9 +3529,10 @@ int ath12k_dp_rx_process_err(struct ath12k_base *ab, struct napi_struct *napi,
 	tot_n_bufs_reaped = 0;
 	quota = budget;
 
-	dp = &ab->dp;
-	reo_except = &dp->reo_except_ring;
-	link_desc_banks = dp->link_desc_banks;
+	for (device_id = 0; device_id < ATH12K_MAX_SOCS; device_id++)
+		INIT_LIST_HEAD(&rx_desc_used_list[device_id]);
+
+	reo_except = &ab->dp.reo_except_ring;
 
 	srng = &ab->hal.srng_list[reo_except->ring_id];
 
@@ -3525,21 +3555,24 @@ int ath12k_dp_rx_process_err(struct ath12k_base *ab, struct napi_struct *napi,
 
 		hw_link_id = le32_get_bits(reo_desc->info0,
 					   HAL_REO_DEST_RING_INFO0_SRC_LINK_ID);
+		device_id = hw_links[hw_link_id].device_id;
+		partner_ab = ath12k_ag_to_ab(ag, device_id);
 
-		pdev_id = ath12k_hw_mac_id_to_pdev_id(ab->hw_params,
+		pdev_id = ath12k_hw_mac_id_to_pdev_id(partner_ab->hw_params,
 						      hw_links[hw_link_id].pdev_idx);
-		ar = ab->pdevs[pdev_id].ar;
+		ar = partner_ab->pdevs[pdev_id].ar;
 
+		link_desc_banks = partner_ab->dp.link_desc_banks;
 		link_desc_va = link_desc_banks[desc_bank].vaddr +
 			       (paddr - link_desc_banks[desc_bank].paddr);
 		ath12k_hal_rx_msdu_link_info_get(link_desc_va, &num_msdus, msdu_cookies,
 						 &rbm);
-		if (rbm != dp->idle_link_rbm &&
+		if (rbm != partner_ab->dp.idle_link_rbm &&
 		    rbm != HAL_RX_BUF_RBM_SW3_BM &&
-		    rbm != ab->hw_params->hal_params->rx_buf_rbm) {
+		    rbm != partner_ab->hw_params->hal_params->rx_buf_rbm) {
 			ab->soc_stats.invalid_rbm++;
 			ath12k_warn(ab, "invalid return buffer manager %d\n", rbm);
-			ath12k_dp_rx_link_desc_return(ab, reo_desc,
+			ath12k_dp_rx_link_desc_return(partner_ab, reo_desc,
 						      HAL_WBM_REL_BM_ACT_REL_MSDU);
 			continue;
 		}
@@ -3549,20 +3582,26 @@ int ath12k_dp_rx_process_err(struct ath12k_base *ab, struct napi_struct *napi,
 
 		/* Process only rx fragments with one msdu per link desc below, and drop
 		 * msdu's indicated due to error reasons.
+		 * Dynamic fragmentation not supported in Multi-link client, so drop the
+		 * partner device buffers.
 		 */
-		if (!is_frag || num_msdus > 1) {
+		if (!is_frag || num_msdus > 1 ||
+		    partner_ab->device_id != ab->device_id) {
 			drop = true;
+
 			/* Return the link desc back to wbm idle list */
-			ath12k_dp_rx_link_desc_return(ab, reo_desc,
+			ath12k_dp_rx_link_desc_return(partner_ab, reo_desc,
 						      HAL_WBM_REL_BM_ACT_PUT_IN_IDLE);
 		}
 
 		for (i = 0; i < num_msdus; i++) {
 			if (!ath12k_dp_process_rx_err_buf(ar, reo_desc,
-							  &rx_desc_used_list,
+							  &rx_desc_used_list[device_id],
 							  drop,
-							  msdu_cookies[i]))
+							  msdu_cookies[i])) {
+				num_buffs_reaped[device_id]++;
 				tot_n_bufs_reaped++;
+			}
 		}
 
 		if (tot_n_bufs_reaped >= quota) {
@@ -3578,10 +3617,17 @@ int ath12k_dp_rx_process_err(struct ath12k_base *ab, struct napi_struct *napi,
 
 	spin_unlock_bh(&srng->lock);
 
-	rx_ring = &dp->rx_refill_buf_ring;
+	for (device_id = 0; device_id < ATH12K_MAX_SOCS; device_id++) {
+		if (!num_buffs_reaped[device_id])
+			continue;
 
-	ath12k_dp_rx_bufs_replenish(ab, rx_ring, &rx_desc_used_list,
-				    tot_n_bufs_reaped);
+		partner_ab = ath12k_ag_to_ab(ag, device_id);
+		rx_ring = &partner_ab->dp.rx_refill_buf_ring;
+
+		ath12k_dp_rx_bufs_replenish(partner_ab, rx_ring,
+					    &rx_desc_used_list[device_id],
+					    num_buffs_reaped[device_id]);
+	}
 
 	return tot_n_bufs_reaped;
 }
@@ -3798,7 +3844,8 @@ static void ath12k_dp_rx_wbm_err(struct ath12k *ar,
 int ath12k_dp_rx_process_wbm_err(struct ath12k_base *ab,
 				 struct napi_struct *napi, int budget)
 {
-	LIST_HEAD(rx_desc_used_list);
+	struct list_head rx_desc_used_list[ATH12K_MAX_SOCS];
+	struct ath12k_hw_group *ag = ab->ag;
 	struct ath12k *ar;
 	struct ath12k_dp *dp = &ab->dp;
 	struct dp_rxdma_ring *rx_ring;
@@ -3808,18 +3855,22 @@ int ath12k_dp_rx_process_wbm_err(struct ath12k_base *ab,
 	struct sk_buff_head msdu_list, scatter_msdu_list;
 	struct ath12k_skb_rxcb *rxcb;
 	void *rx_desc;
-	u8 hw_link_id;
-	int num_buffs_reaped = 0;
+	int num_buffs_reaped[ATH12K_MAX_SOCS] = {};
+	int total_num_buffs_reaped = 0;
 	struct ath12k_rx_desc_info *desc_info;
-	struct ath12k_hw_link *hw_links = ab->ag->hw_links;
+	struct ath12k_hw_link *hw_links = ag->hw_links;
+	struct ath12k_base *partner_ab;
+	u8 hw_link_id, device_id;
 	int ret, pdev_id;
 	struct hal_rx_desc *msdu_data;
 
 	__skb_queue_head_init(&msdu_list);
 	__skb_queue_head_init(&scatter_msdu_list);
 
+	for (device_id = 0; device_id < ATH12K_MAX_SOCS; device_id++)
+		INIT_LIST_HEAD(&rx_desc_used_list[device_id]);
+
 	srng = &ab->hal.srng_list[dp->rx_rel_ring.ring_id];
-	rx_ring = &dp->rx_refill_buf_ring;
 	spin_lock_bh(&srng->lock);
 
 	ath12k_hal_srng_access_begin(ab, srng);
@@ -3855,14 +3906,27 @@ int ath12k_dp_rx_process_wbm_err(struct ath12k_base *ab,
 		msdu = desc_info->skb;
 		desc_info->skb = NULL;
 
-		list_add_tail(&desc_info->list, &rx_desc_used_list);
+		device_id = desc_info->device_id;
+		partner_ab = ath12k_ag_to_ab(ag, device_id);
+		if (unlikely(!partner_ab)) {
+			dev_kfree_skb_any(msdu);
+
+			/* In any case continuation bit is set
+			 * in the previous record, cleanup scatter_msdu_list
+			 */
+			ath12k_dp_clean_up_skb_list(&scatter_msdu_list);
+			continue;
+		}
+
+		list_add_tail(&desc_info->list, &rx_desc_used_list[device_id]);
 
 		rxcb = ATH12K_SKB_RXCB(msdu);
-		dma_unmap_single(ab->dev, rxcb->paddr,
+		dma_unmap_single(partner_ab->dev, rxcb->paddr,
 				 msdu->len + skb_tailroom(msdu),
 				 DMA_FROM_DEVICE);
 
-		num_buffs_reaped++;
+		num_buffs_reaped[device_id]++;
+		total_num_buffs_reaped++;
 
 		if (!err_info.continuation)
 			budget--;
@@ -3886,9 +3950,9 @@ int ath12k_dp_rx_process_wbm_err(struct ath12k_base *ab,
 			continue;
 		}
 
-		hw_link_id = ath12k_dp_rx_get_msdu_src_link(ab,
+		hw_link_id = ath12k_dp_rx_get_msdu_src_link(partner_ab,
 							    msdu_data);
-		if (hw_link_id >= MAX_RADIOS) {
+		if (hw_link_id >= ATH12K_GROUP_MAX_RADIO) {
 			dev_kfree_skb_any(msdu);
 
 			/* In any case continuation bit is set
@@ -3924,20 +3988,39 @@ int ath12k_dp_rx_process_wbm_err(struct ath12k_base *ab,
 
 	spin_unlock_bh(&srng->lock);
 
-	if (!num_buffs_reaped)
+	if (!total_num_buffs_reaped)
 		goto done;
 
-	ath12k_dp_rx_bufs_replenish(ab, rx_ring, &rx_desc_used_list,
-				    num_buffs_reaped);
+	for (device_id = 0; device_id < ATH12K_MAX_SOCS; device_id++) {
+		if (!num_buffs_reaped[device_id])
+			continue;
+
+		partner_ab = ath12k_ag_to_ab(ag, device_id);
+		rx_ring = &partner_ab->dp.rx_refill_buf_ring;
+
+		ath12k_dp_rx_bufs_replenish(ab, rx_ring,
+					    &rx_desc_used_list[device_id],
+					    num_buffs_reaped[device_id]);
+	}
 
 	rcu_read_lock();
 	while ((msdu = __skb_dequeue(&msdu_list))) {
 		rxcb = ATH12K_SKB_RXCB(msdu);
 		hw_link_id = rxcb->hw_link_id;
 
-		pdev_id = ath12k_hw_mac_id_to_pdev_id(ab->hw_params,
+		device_id = hw_links[hw_link_id].device_id;
+		partner_ab = ath12k_ag_to_ab(ag, device_id);
+		if (unlikely(!partner_ab)) {
+			ath12k_dbg(ab, ATH12K_DBG_DATA,
+				   "Unable to process WBM error msdu due to invalid hw link id %d device id %d\n",
+				   hw_link_id, device_id);
+			dev_kfree_skb_any(msdu);
+			continue;
+		}
+
+		pdev_id = ath12k_hw_mac_id_to_pdev_id(partner_ab->hw_params,
 						      hw_links[hw_link_id].pdev_idx);
-		ar = ab->pdevs[pdev_id].ar;
+		ar = partner_ab->pdevs[pdev_id].ar;
 
 		if (!ar || !rcu_dereference(ar->ab->pdevs_active[hw_link_id])) {
 			dev_kfree_skb_any(msdu);
@@ -3952,7 +4035,7 @@ int ath12k_dp_rx_process_wbm_err(struct ath12k_base *ab,
 	}
 	rcu_read_unlock();
 done:
-	return num_buffs_reaped;
+	return total_num_buffs_reaped;
 }
 
 void ath12k_dp_rx_process_reo_status(struct ath12k_base *ab)
-- 
2.39.5


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 3/9] wifi: ath12k: add helper function to init partner cmem configuration
  2024-12-09 18:54 [PATCH 0/9] wifi: ath12k: MLO support part 8 Kalle Valo
  2024-12-09 18:54 ` [PATCH 1/9] wifi: ath12k: move to HW link id based reveive handling Kalle Valo
  2024-12-09 18:54 ` [PATCH 2/9] wifi: ath12k: add partner device buffer support in receive data path Kalle Valo
@ 2024-12-09 18:54 ` Kalle Valo
  2024-12-09 18:54 ` [PATCH 4/9] wifi: ath12k: introduce interface combination cleanup helper Kalle Valo
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Kalle Valo @ 2024-12-09 18:54 UTC (permalink / raw)
  To: ath12k; +Cc: linux-wireless

From: Karthikeyan Periyasamy <quic_periyasa@quicinc.com>

In the Inter Multi-Link Operation, the primary device is expected to receive
the partner device buffer. Therefore, each device initializes the partner
device buffer in their cmem configuration. So add a helper function to
initialize the partner device buffer in their cmem configuration.

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: Karthikeyan Periyasamy <quic_periyasa@quicinc.com>
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
---
 drivers/net/wireless/ath/ath12k/core.c |  5 ++++-
 drivers/net/wireless/ath/ath12k/dp.c   | 13 +++++++++++++
 drivers/net/wireless/ath/ath12k/dp.h   |  1 +
 3 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c
index af642b466ea0..ff79cb910523 100644
--- a/drivers/net/wireless/ath/ath12k/core.c
+++ b/drivers/net/wireless/ath/ath12k/core.c
@@ -930,7 +930,7 @@ int ath12k_mac_mlo_ready(struct ath12k_hw_group *ag)
 
 static int ath12k_core_mlo_setup(struct ath12k_hw_group *ag)
 {
-	int ret;
+	int ret, i;
 
 	if (!ag->mlo_capable || ag->num_devices == 1)
 		return 0;
@@ -939,6 +939,9 @@ static int ath12k_core_mlo_setup(struct ath12k_hw_group *ag)
 	if (ret)
 		return ret;
 
+	for (i = 0; i < ag->num_devices; i++)
+		ath12k_dp_partner_cc_init(ag->ab[i]);
+
 	ret = ath12k_mac_mlo_ready(ag);
 	if (ret)
 		goto err_mlo_teardown;
diff --git a/drivers/net/wireless/ath/ath12k/dp.c b/drivers/net/wireless/ath/ath12k/dp.c
index 9a7df54bf570..9e5a4e75f2f6 100644
--- a/drivers/net/wireless/ath/ath12k/dp.c
+++ b/drivers/net/wireless/ath/ath12k/dp.c
@@ -1522,6 +1522,19 @@ static int ath12k_dp_cmem_init(struct ath12k_base *ab,
 	return 0;
 }
 
+void ath12k_dp_partner_cc_init(struct ath12k_base *ab)
+{
+	struct ath12k_hw_group *ag = ab->ag;
+	int i;
+
+	for (i = 0; i < ag->num_devices; i++) {
+		if (ag->ab[i] == ab)
+			continue;
+
+		ath12k_dp_cmem_init(ab, &ag->ab[i]->dp, ATH12K_DP_RX_DESC);
+	}
+}
+
 static int ath12k_dp_cc_init(struct ath12k_base *ab)
 {
 	struct ath12k_dp *dp = &ab->dp;
diff --git a/drivers/net/wireless/ath/ath12k/dp.h b/drivers/net/wireless/ath/ath12k/dp.h
index d3f3d39a1cd0..7700828375e3 100644
--- a/drivers/net/wireless/ath/ath12k/dp.h
+++ b/drivers/net/wireless/ath/ath12k/dp.h
@@ -1806,6 +1806,7 @@ void ath12k_dp_vdev_tx_attach(struct ath12k *ar, struct ath12k_link_vif *arvif);
 void ath12k_dp_free(struct ath12k_base *ab);
 int ath12k_dp_alloc(struct ath12k_base *ab);
 void ath12k_dp_cc_config(struct ath12k_base *ab);
+void ath12k_dp_partner_cc_init(struct ath12k_base *ab);
 int ath12k_dp_pdev_alloc(struct ath12k_base *ab);
 void ath12k_dp_pdev_pre_alloc(struct ath12k *ar);
 void ath12k_dp_pdev_free(struct ath12k_base *ab);
-- 
2.39.5


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 4/9] wifi: ath12k: introduce interface combination cleanup helper
  2024-12-09 18:54 [PATCH 0/9] wifi: ath12k: MLO support part 8 Kalle Valo
                   ` (2 preceding siblings ...)
  2024-12-09 18:54 ` [PATCH 3/9] wifi: ath12k: add helper function to init partner cmem configuration Kalle Valo
@ 2024-12-09 18:54 ` Kalle Valo
  2024-12-09 18:54 ` [PATCH 5/9] wifi: ath12k: Refactor radio frequency information Kalle Valo
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Kalle Valo @ 2024-12-09 18:54 UTC (permalink / raw)
  To: ath12k; +Cc: linux-wireless

From: Karthikeyan Periyasamy <quic_periyasa@quicinc.com>

Introduce a cleanup helper function to avoid redundant code for interface
combination cleanup. Remove the cleanup code from ath12k_mac_hw_unregister()
and ath12k_mac_hw_register() and replace it with a new cleanup helper function.

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: Karthikeyan Periyasamy <quic_periyasa@quicinc.com>
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
---
 drivers/net/wireless/ath/ath12k/mac.c | 21 +++++++++++++--------
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index 7e8eb0feb871..dc61fe761090 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -10351,6 +10351,14 @@ static bool ath12k_mac_is_iface_mode_enable(struct ath12k_hw *ah,
 	return is_enable;
 }
 
+static void ath12k_mac_cleanup_iface_combinations(struct ath12k_hw *ah)
+{
+	struct wiphy *wiphy = ah->hw->wiphy;
+
+	kfree(wiphy->iface_combinations[0].limits);
+	kfree(wiphy->iface_combinations);
+}
+
 static int ath12k_mac_setup_iface_combinations(struct ath12k_hw *ah)
 {
 	struct wiphy *wiphy = ah->hw->wiphy;
@@ -10479,7 +10487,6 @@ static void ath12k_mac_cleanup_unregister(struct ath12k *ar)
 static void ath12k_mac_hw_unregister(struct ath12k_hw *ah)
 {
 	struct ieee80211_hw *hw = ah->hw;
-	struct wiphy *wiphy = hw->wiphy;
 	struct ath12k *ar;
 	int i;
 
@@ -10493,8 +10500,7 @@ static void ath12k_mac_hw_unregister(struct ath12k_hw *ah)
 	for_each_ar(ah, ar, i)
 		ath12k_mac_cleanup_unregister(ar);
 
-	kfree(wiphy->iface_combinations[0].limits);
-	kfree(wiphy->iface_combinations);
+	ath12k_mac_cleanup_iface_combinations(ah);
 
 	SET_IEEE80211_DEV(hw, NULL);
 }
@@ -10724,13 +10730,13 @@ static int ath12k_mac_hw_register(struct ath12k_hw *ah)
 	ret = ath12k_wow_init(ar);
 	if (ret) {
 		ath12k_warn(ar->ab, "failed to init wow: %d\n", ret);
-		goto err_free_if_combs;
+		goto err_cleanup_if_combs;
 	}
 
 	ret = ieee80211_register_hw(hw);
 	if (ret) {
 		ath12k_err(ab, "ieee80211 registration failed: %d\n", ret);
-		goto err_free_if_combs;
+		goto err_cleanup_if_combs;
 	}
 
 	if (is_monitor_disable)
@@ -10760,9 +10766,8 @@ static int ath12k_mac_hw_register(struct ath12k_hw *ah)
 
 	ieee80211_unregister_hw(hw);
 
-err_free_if_combs:
-	kfree(wiphy->iface_combinations[0].limits);
-	kfree(wiphy->iface_combinations);
+err_cleanup_if_combs:
+	ath12k_mac_cleanup_iface_combinations(ah);
 
 err_complete_cleanup_unregister:
 	i = ah->num_radio;
-- 
2.39.5


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 5/9] wifi: ath12k: Refactor radio frequency information
  2024-12-09 18:54 [PATCH 0/9] wifi: ath12k: MLO support part 8 Kalle Valo
                   ` (3 preceding siblings ...)
  2024-12-09 18:54 ` [PATCH 4/9] wifi: ath12k: introduce interface combination cleanup helper Kalle Valo
@ 2024-12-09 18:54 ` Kalle Valo
  2024-12-09 18:54 ` [PATCH 6/9] wifi: ath12k: advertise multi device interface combination Kalle Valo
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Kalle Valo @ 2024-12-09 18:54 UTC (permalink / raw)
  To: ath12k; +Cc: linux-wireless

From: Karthikeyan Periyasamy <quic_periyasa@quicinc.com>

Currently, radio stores the low frequency and high frequency information as
separate variables. However, cfg80211 already provides a suitable data
structure struct wiphy_radio_freq_range to store this information efficiently.
Additionally, for multi radio per wiphy infrastructure, this frequency range
information is essential. In future patches using struct wiphy_radio_freq_range
makes the code simpler.

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: Karthikeyan Periyasamy <quic_periyasa@quicinc.com>
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
---
 drivers/net/wireless/ath/ath12k/core.h | 3 +--
 drivers/net/wireless/ath/ath12k/mac.c  | 8 ++++----
 2 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h
index d7caa58bb262..d09ebcdde94f 100644
--- a/drivers/net/wireless/ath/ath12k/core.h
+++ b/drivers/net/wireless/ath/ath12k/core.h
@@ -711,8 +711,7 @@ struct ath12k {
 	bool monitor_started;
 	int monitor_vdev_id;
 
-	u32 freq_low;
-	u32 freq_high;
+	struct wiphy_radio_freq_range freq_range;
 
 	bool nlo_enabled;
 
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index dc61fe761090..1bf89be1cccc 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -708,8 +708,8 @@ static struct ath12k *ath12k_mac_get_ar_by_chan(struct ieee80211_hw *hw,
 		return ar;
 
 	for_each_ar(ah, ar, i) {
-		if (channel->center_freq >= ar->freq_low &&
-		    channel->center_freq <= ar->freq_high)
+		if (channel->center_freq >= KHZ_TO_MHZ(ar->freq_range.start_freq) &&
+		    channel->center_freq <= KHZ_TO_MHZ(ar->freq_range.end_freq))
 			return ar;
 	}
 	return NULL;
@@ -10203,8 +10203,8 @@ static void ath12k_mac_update_ch_list(struct ath12k *ar,
 			band->channels[i].flags |= IEEE80211_CHAN_DISABLED;
 	}
 
-	ar->freq_low = freq_low;
-	ar->freq_high = freq_high;
+	ar->freq_range.start_freq = MHZ_TO_KHZ(freq_low);
+	ar->freq_range.end_freq = MHZ_TO_KHZ(freq_high);
 }
 
 static u32 ath12k_get_phy_id(struct ath12k *ar, u32 band)
-- 
2.39.5


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 6/9] wifi: ath12k: advertise multi device interface combination
  2024-12-09 18:54 [PATCH 0/9] wifi: ath12k: MLO support part 8 Kalle Valo
                   ` (4 preceding siblings ...)
  2024-12-09 18:54 ` [PATCH 5/9] wifi: ath12k: Refactor radio frequency information Kalle Valo
@ 2024-12-09 18:54 ` Kalle Valo
  2024-12-09 18:54 ` [PATCH 7/9] wifi: ath12k: fix ath12k_qmi_alloc_chunk() to handle too large allocations Kalle Valo
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Kalle Valo @ 2024-12-09 18:54 UTC (permalink / raw)
  To: ath12k; +Cc: linux-wireless

From: Karthikeyan Periyasamy <quic_periyasa@quicinc.com>

The prerequisite for MLO support in cfg80211/mac80211 requires that all the
links participating in MLO belong to the same wiphy/struct ieee80211_hw. The
driver needs to group multiple discrete hardware components, each acting as a
link in MLO, under one wiphy. Consequently, the driver advertises
multi-hardware device interface combination capabilities specific to the radio,
including supported frequencies. The global interface combination represent the
combined interface capabilities.

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: Karthikeyan Periyasamy <quic_periyasa@quicinc.com>
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
---
 drivers/net/wireless/ath/ath12k/mac.c | 222 +++++++++++++++++++++-----
 1 file changed, 185 insertions(+), 37 deletions(-)

diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index 1bf89be1cccc..de2f55f4ea03 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -10336,14 +10336,20 @@ static bool ath12k_mac_is_iface_mode_enable(struct ath12k_hw *ah,
 {
 	struct ath12k *ar;
 	int i;
-	u16 interface_modes, mode;
-	bool is_enable = true;
+	u16 interface_modes, mode = 0;
+	bool is_enable = false;
+
+	if (type == NL80211_IFTYPE_MESH_POINT) {
+		if (IS_ENABLED(CONFIG_MAC80211_MESH))
+			mode = BIT(type);
+	} else {
+		mode = BIT(type);
+	}
 
-	mode = BIT(type);
 	for_each_ar(ah, ar, i) {
 		interface_modes = ar->ab->hw_params->interface_modes;
-		if (!(interface_modes & mode)) {
-			is_enable = false;
+		if (interface_modes & mode) {
+			is_enable = true;
 			break;
 		}
 	}
@@ -10351,31 +10357,20 @@ static bool ath12k_mac_is_iface_mode_enable(struct ath12k_hw *ah,
 	return is_enable;
 }
 
-static void ath12k_mac_cleanup_iface_combinations(struct ath12k_hw *ah)
+static int
+ath12k_mac_setup_radio_iface_comb(struct ath12k *ar,
+				  struct ieee80211_iface_combination *comb)
 {
-	struct wiphy *wiphy = ah->hw->wiphy;
-
-	kfree(wiphy->iface_combinations[0].limits);
-	kfree(wiphy->iface_combinations);
-}
-
-static int ath12k_mac_setup_iface_combinations(struct ath12k_hw *ah)
-{
-	struct wiphy *wiphy = ah->hw->wiphy;
-	struct ieee80211_iface_combination *combinations;
+	u16 interface_modes = ar->ab->hw_params->interface_modes;
 	struct ieee80211_iface_limit *limits;
 	int n_limits, max_interfaces;
 	bool ap, mesh, p2p;
 
-	ap = ath12k_mac_is_iface_mode_enable(ah, NL80211_IFTYPE_AP);
-	p2p = ath12k_mac_is_iface_mode_enable(ah, NL80211_IFTYPE_P2P_DEVICE);
+	ap = interface_modes & BIT(NL80211_IFTYPE_AP);
+	p2p = interface_modes & BIT(NL80211_IFTYPE_P2P_DEVICE);
 
 	mesh = IS_ENABLED(CONFIG_MAC80211_MESH) &&
-		ath12k_mac_is_iface_mode_enable(ah, NL80211_IFTYPE_MESH_POINT);
-
-	combinations = kzalloc(sizeof(*combinations), GFP_KERNEL);
-	if (!combinations)
-		return -ENOMEM;
+	       (interface_modes & BIT(NL80211_IFTYPE_MESH_POINT));
 
 	if ((ap || mesh) && !p2p) {
 		n_limits = 2;
@@ -10392,10 +10387,8 @@ static int ath12k_mac_setup_iface_combinations(struct ath12k_hw *ah)
 	}
 
 	limits = kcalloc(n_limits, sizeof(*limits), GFP_KERNEL);
-	if (!limits) {
-		kfree(combinations);
+	if (!limits)
 		return -ENOMEM;
-	}
 
 	limits[0].max = 1;
 	limits[0].types |= BIT(NL80211_IFTYPE_STATION);
@@ -10411,26 +10404,181 @@ static int ath12k_mac_setup_iface_combinations(struct ath12k_hw *ah)
 
 	if (p2p) {
 		limits[1].types |= BIT(NL80211_IFTYPE_P2P_CLIENT) |
-				   BIT(NL80211_IFTYPE_P2P_GO);
+					BIT(NL80211_IFTYPE_P2P_GO);
 		limits[2].max = 1;
 		limits[2].types |= BIT(NL80211_IFTYPE_P2P_DEVICE);
 	}
 
-	combinations[0].limits = limits;
-	combinations[0].n_limits = n_limits;
-	combinations[0].max_interfaces = max_interfaces;
-	combinations[0].num_different_channels = 1;
-	combinations[0].beacon_int_infra_match = true;
-	combinations[0].beacon_int_min_gcd = 100;
-	combinations[0].radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) |
-						BIT(NL80211_CHAN_WIDTH_20) |
-						BIT(NL80211_CHAN_WIDTH_40) |
-						BIT(NL80211_CHAN_WIDTH_80);
+	comb[0].limits = limits;
+	comb[0].n_limits = n_limits;
+	comb[0].max_interfaces = max_interfaces;
+	comb[0].num_different_channels = 1;
+	comb[0].beacon_int_infra_match = true;
+	comb[0].beacon_int_min_gcd = 100;
+	comb[0].radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) |
+					BIT(NL80211_CHAN_WIDTH_20) |
+					BIT(NL80211_CHAN_WIDTH_40) |
+					BIT(NL80211_CHAN_WIDTH_80);
 
+	return 0;
+}
+
+static int
+ath12k_mac_setup_global_iface_comb(struct ath12k_hw *ah,
+				   struct wiphy_radio *radio,
+				   u8 n_radio,
+				   struct ieee80211_iface_combination *comb)
+{
+	const struct ieee80211_iface_combination *iter_comb;
+	struct ieee80211_iface_limit *limits;
+	int i, j, n_limits;
+	bool ap, mesh, p2p;
+
+	if (!n_radio)
+		return 0;
+
+	ap = ath12k_mac_is_iface_mode_enable(ah, NL80211_IFTYPE_AP);
+	p2p = ath12k_mac_is_iface_mode_enable(ah, NL80211_IFTYPE_P2P_DEVICE);
+	mesh = ath12k_mac_is_iface_mode_enable(ah, NL80211_IFTYPE_MESH_POINT);
+
+	if ((ap || mesh) && !p2p)
+		n_limits = 2;
+	else if (p2p)
+		n_limits = 3;
+	else
+		n_limits = 1;
+
+	limits = kcalloc(n_limits, sizeof(*limits), GFP_KERNEL);
+	if (!limits)
+		return -ENOMEM;
+
+	for (i = 0; i < n_radio; i++) {
+		iter_comb = radio[i].iface_combinations;
+		for (j = 0; j < iter_comb->n_limits && j < n_limits; j++) {
+			limits[j].types |= iter_comb->limits[j].types;
+			limits[j].max += iter_comb->limits[j].max;
+		}
+
+		comb->max_interfaces += iter_comb->max_interfaces;
+		comb->num_different_channels += iter_comb->num_different_channels;
+		comb->radar_detect_widths |= iter_comb->radar_detect_widths;
+	}
+
+	comb->limits = limits;
+	comb->n_limits = n_limits;
+	comb->beacon_int_infra_match = true;
+	comb->beacon_int_min_gcd = 100;
+
+	return 0;
+}
+
+static
+void ath12k_mac_cleanup_iface_comb(const struct ieee80211_iface_combination *iface_comb)
+{
+	kfree(iface_comb[0].limits);
+	kfree(iface_comb);
+}
+
+static void ath12k_mac_cleanup_iface_combinations(struct ath12k_hw *ah)
+{
+	struct wiphy *wiphy = ah->hw->wiphy;
+	const struct wiphy_radio *radio;
+	int i;
+
+	if (wiphy->n_radio > 0) {
+		radio = wiphy->radio;
+		for (i = 0; i < wiphy->n_radio; i++)
+			ath12k_mac_cleanup_iface_comb(radio[i].iface_combinations);
+
+		kfree(wiphy->radio);
+	}
+
+	ath12k_mac_cleanup_iface_comb(wiphy->iface_combinations);
+}
+
+static int ath12k_mac_setup_iface_combinations(struct ath12k_hw *ah)
+{
+	struct ieee80211_iface_combination *combinations, *comb;
+	struct wiphy *wiphy = ah->hw->wiphy;
+	struct wiphy_radio *radio;
+	struct ath12k *ar;
+	int i, ret;
+
+	combinations = kzalloc(sizeof(*combinations), GFP_KERNEL);
+	if (!combinations)
+		return -ENOMEM;
+
+	if (ah->num_radio == 1) {
+		ret = ath12k_mac_setup_radio_iface_comb(&ah->radio[0],
+							combinations);
+		if (ret) {
+			ath12k_hw_warn(ah, "failed to setup radio interface combinations for one radio: %d",
+				       ret);
+			goto err_free_combinations;
+		}
+
+		goto out;
+	}
+
+	/* there are multiple radios */
+
+	radio = kcalloc(ah->num_radio, sizeof(*radio), GFP_KERNEL);
+	if (!radio) {
+		ret = -ENOMEM;
+		goto err_free_combinations;
+	}
+
+	for_each_ar(ah, ar, i) {
+		comb = kzalloc(sizeof(*comb), GFP_KERNEL);
+		if (!comb) {
+			ret = -ENOMEM;
+			goto err_free_radios;
+		}
+
+		ret = ath12k_mac_setup_radio_iface_comb(ar, comb);
+		if (ret) {
+			ath12k_hw_warn(ah, "failed to setup radio interface combinations for radio %d: %d",
+				       i, ret);
+			kfree(comb);
+			goto err_free_radios;
+		}
+
+		radio[i].freq_range = &ar->freq_range;
+		radio[i].n_freq_range = 1;
+
+		radio[i].iface_combinations = comb;
+		radio[i].n_iface_combinations = 1;
+	}
+
+	ret = ath12k_mac_setup_global_iface_comb(ah, radio, ah->num_radio, combinations);
+	if (ret) {
+		ath12k_hw_warn(ah, "failed to setup global interface combinations: %d",
+			       ret);
+		goto err_free_all_radios;
+	}
+
+	wiphy->radio = radio;
+	wiphy->n_radio = ah->num_radio;
+
+out:
 	wiphy->iface_combinations = combinations;
 	wiphy->n_iface_combinations = 1;
 
 	return 0;
+
+err_free_all_radios:
+	i = ah->num_radio;
+
+err_free_radios:
+	while (i--)
+		ath12k_mac_cleanup_iface_comb(radio[i].iface_combinations);
+
+	kfree(radio);
+
+err_free_combinations:
+	kfree(combinations);
+
+	return ret;
 }
 
 static const u8 ath12k_if_types_ext_capa[] = {
-- 
2.39.5


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 7/9] wifi: ath12k: fix ath12k_qmi_alloc_chunk() to handle too large allocations
  2024-12-09 18:54 [PATCH 0/9] wifi: ath12k: MLO support part 8 Kalle Valo
                   ` (5 preceding siblings ...)
  2024-12-09 18:54 ` [PATCH 6/9] wifi: ath12k: advertise multi device interface combination Kalle Valo
@ 2024-12-09 18:54 ` Kalle Valo
  2024-12-09 18:54 ` [PATCH 8/9] wifi: ath12k: fix ar->supports_6ghz usage during hw register Kalle Valo
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Kalle Valo @ 2024-12-09 18:54 UTC (permalink / raw)
  To: ath12k; +Cc: linux-wireless

From: Aditya Kumar Singh <quic_adisi@quicinc.com>

If the requested memory chunk is too large, an error message is logged, but the
request continues to be processed. However, no actual memory is allocated to
the firmware from this request. Instead, the firmware sends another request
with smaller chunks, where memory will be allocated accordingly. Therefore, it
is pointless to proceed with parsing the request if at least one of the
requests cannot be fulfilled.

Hence, return -EAGAIN immediately and proceed to process the new request.

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: Aditya Kumar Singh <quic_adisi@quicinc.com>
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
---
 drivers/net/wireless/ath/ath12k/qmi.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath12k/qmi.c b/drivers/net/wireless/ath/ath12k/qmi.c
index e7846aaca10a..964d350be748 100644
--- a/drivers/net/wireless/ath/ath12k/qmi.c
+++ b/drivers/net/wireless/ath/ath12k/qmi.c
@@ -2497,7 +2497,7 @@ static int ath12k_qmi_alloc_chunk(struct ath12k_base *ab,
 				    chunk->size,
 				    chunk->type);
 			ath12k_qmi_free_target_mem_chunk(ab);
-			return 0;
+			return -EAGAIN;
 		}
 		ath12k_warn(ab, "memory allocation failure for %u size: %d\n",
 			    chunk->type, chunk->size);
@@ -2600,6 +2600,14 @@ static int ath12k_qmi_alloc_target_mem_chunk(struct ath12k_base *ab)
 
 	mutex_unlock(&ag->mutex);
 
+	/* The firmware will attempt to request memory in smaller chunks
+	 * on the next try. However, the current caller should be notified
+	 * that this instance of request parsing was successful.
+	 * Therefore, return 0 only.
+	 */
+	if (ret == -EAGAIN)
+		ret = 0;
+
 	return ret;
 }
 
-- 
2.39.5


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 8/9] wifi: ath12k: fix ar->supports_6ghz usage during hw register
  2024-12-09 18:54 [PATCH 0/9] wifi: ath12k: MLO support part 8 Kalle Valo
                   ` (6 preceding siblings ...)
  2024-12-09 18:54 ` [PATCH 7/9] wifi: ath12k: fix ath12k_qmi_alloc_chunk() to handle too large allocations Kalle Valo
@ 2024-12-09 18:54 ` Kalle Valo
  2024-12-09 18:54 ` [PATCH 9/9] wifi: ath12k: pass link ID during MLO while delivering skb Kalle Valo
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Kalle Valo @ 2024-12-09 18:54 UTC (permalink / raw)
  To: ath12k; +Cc: linux-wireless

From: Aditya Kumar Singh <quic_adisi@quicinc.com>

In the ath12k_mac_hw_register() function's context, ar is an iterator
variable, and there is no assurance that the last ar will be the one with
6 GHz enabled. Therefore, checking directly ar->supports_6ghz outside the
loop is not appropriate.

Additionally, 6 GHz lacks HT capabilities. To obtain the super set of
HT capabilities across all grouped radios, 6 GHz should be excluded.

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: Aditya Kumar Singh <quic_adisi@quicinc.com>
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
---
 drivers/net/wireless/ath/ath12k/mac.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index de2f55f4ea03..6f4a34c91038 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -10723,7 +10723,10 @@ static int ath12k_mac_hw_register(struct ath12k_hw *ah)
 		if (ret)
 			goto err_cleanup_unregister;
 
-		ht_cap &= ht_cap_info;
+		/* 6 GHz does not support HT Cap, hence do not consider it */
+		if (!ar->supports_6ghz)
+			ht_cap &= ht_cap_info;
+
 		wiphy->max_ap_assoc_sta += ar->max_num_stations;
 
 		/* Advertise the max antenna support of all radios, driver can handle
@@ -10787,7 +10790,7 @@ static int ath12k_mac_hw_register(struct ath12k_hw *ah)
 	ieee80211_hw_set(hw, SUPPORTS_TX_FRAG);
 	ieee80211_hw_set(hw, REPORTS_LOW_ACK);
 
-	if ((ht_cap & WMI_HT_CAP_ENABLED) || ar->supports_6ghz) {
+	if ((ht_cap & WMI_HT_CAP_ENABLED) || is_6ghz) {
 		ieee80211_hw_set(hw, AMPDU_AGGREGATION);
 		ieee80211_hw_set(hw, TX_AMPDU_SETUP_IN_HW);
 		ieee80211_hw_set(hw, SUPPORTS_REORDERING_BUFFER);
@@ -10803,7 +10806,7 @@ static int ath12k_mac_hw_register(struct ath12k_hw *ah)
 	 * handle it when the ht capability different for each band.
 	 */
 	if (ht_cap & WMI_HT_CAP_DYNAMIC_SMPS ||
-	    (ar->supports_6ghz && ab->hw_params->supports_dynamic_smps_6ghz))
+	    (is_6ghz && ab->hw_params->supports_dynamic_smps_6ghz))
 		wiphy->features |= NL80211_FEATURE_DYNAMIC_SMPS;
 
 	wiphy->max_scan_ssids = WLAN_SCAN_PARAMS_MAX_SSID;
-- 
2.39.5


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 9/9] wifi: ath12k: pass link ID during MLO while delivering skb
  2024-12-09 18:54 [PATCH 0/9] wifi: ath12k: MLO support part 8 Kalle Valo
                   ` (7 preceding siblings ...)
  2024-12-09 18:54 ` [PATCH 8/9] wifi: ath12k: fix ar->supports_6ghz usage during hw register Kalle Valo
@ 2024-12-09 18:54 ` Kalle Valo
  2024-12-10  8:25 ` [PATCH 0/9] wifi: ath12k: MLO support part 8 Kalle Valo
  2024-12-16 16:50 ` Jeff Johnson
  10 siblings, 0 replies; 14+ messages in thread
From: Kalle Valo @ 2024-12-09 18:54 UTC (permalink / raw)
  To: ath12k; +Cc: linux-wireless

From: Aditya Kumar Singh <quic_adisi@quicinc.com>

mac80211 expects link_id in some scenarios or else the packet might
get dropped. Hence, add link_id information before delivering the skb.

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: Aditya Kumar Singh <quic_adisi@quicinc.com>
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
---
 drivers/net/wireless/ath/ath12k/dp_mon.c | 8 +++++++-
 drivers/net/wireless/ath/ath12k/dp_rx.c  | 5 +++++
 drivers/net/wireless/ath/ath12k/peer.c   | 2 ++
 drivers/net/wireless/ath/ath12k/peer.h   | 3 +++
 4 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath12k/dp_mon.c b/drivers/net/wireless/ath/ath12k/dp_mon.c
index 494984133a91..2d53404095d6 100644
--- a/drivers/net/wireless/ath/ath12k/dp_mon.c
+++ b/drivers/net/wireless/ath/ath12k/dp_mon.c
@@ -1093,8 +1093,14 @@ static void ath12k_dp_mon_rx_deliver_msdu(struct ath12k *ar, struct napi_struct
 		decap = ath12k_dp_rx_h_decap_type(ar->ab, rxcb->rx_desc);
 	spin_lock_bh(&ar->ab->base_lock);
 	peer = ath12k_dp_rx_h_find_peer(ar->ab, msdu);
-	if (peer && peer->sta)
+	if (peer && peer->sta) {
 		pubsta = peer->sta;
+		if (pubsta->valid_links) {
+			status->link_valid = 1;
+			status->link_id = peer->link_id;
+		}
+	}
+
 	spin_unlock_bh(&ar->ab->base_lock);
 
 	ath12k_dbg(ar->ab, ATH12K_DBG_DATA,
diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c
index adbd7bbcef6f..1cc7f6ce55b9 100644
--- a/drivers/net/wireless/ath/ath12k/dp_rx.c
+++ b/drivers/net/wireless/ath/ath12k/dp_rx.c
@@ -2474,6 +2474,11 @@ static void ath12k_dp_rx_deliver_msdu(struct ath12k *ar, struct napi_struct *nap
 
 	pubsta = peer ? peer->sta : NULL;
 
+	if (pubsta && pubsta->valid_links) {
+		status->link_valid = 1;
+		status->link_id = peer->link_id;
+	}
+
 	spin_unlock_bh(&ab->base_lock);
 
 	ath12k_dbg(ab, ATH12K_DBG_DATA,
diff --git a/drivers/net/wireless/ath/ath12k/peer.c b/drivers/net/wireless/ath/ath12k/peer.c
index 5763c5a40cfc..792cca8a3fb1 100644
--- a/drivers/net/wireless/ath/ath12k/peer.c
+++ b/drivers/net/wireless/ath/ath12k/peer.c
@@ -388,6 +388,8 @@ int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif,
 		arsta = wiphy_dereference(ath12k_ar_to_hw(ar)->wiphy,
 					  ahsta->link[link_id]);
 
+		peer->link_id = arsta->link_id;
+
 		/* Fill ML info into created peer */
 		if (sta->mlo) {
 			ml_peer_id = ahsta->ml_peer_id;
diff --git a/drivers/net/wireless/ath/ath12k/peer.h b/drivers/net/wireless/ath/ath12k/peer.h
index 7e6231cb2b52..5870ee11a8c7 100644
--- a/drivers/net/wireless/ath/ath12k/peer.h
+++ b/drivers/net/wireless/ath/ath12k/peer.h
@@ -59,6 +59,9 @@ struct ath12k_peer {
 
 	/* To ensure only certain work related to dp is done once */
 	bool primary_link;
+
+	/* for reference to ath12k_link_sta */
+	u8 link_id;
 };
 
 struct ath12k_ml_peer {
-- 
2.39.5


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/9] wifi: ath12k: move to HW link id based reveive handling
  2024-12-09 18:54 ` [PATCH 1/9] wifi: ath12k: move to HW link id based reveive handling Kalle Valo
@ 2024-12-09 19:44   ` Jeff Johnson
  2024-12-09 20:01     ` Kalle Valo
  0 siblings, 1 reply; 14+ messages in thread
From: Jeff Johnson @ 2024-12-09 19:44 UTC (permalink / raw)
  To: Kalle Valo, ath12k; +Cc: linux-wireless

Subject nit: s/reveive/receive/

I'll fixup in 'pending' if there are no additional comments on this series

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/9] wifi: ath12k: move to HW link id based reveive handling
  2024-12-09 19:44   ` Jeff Johnson
@ 2024-12-09 20:01     ` Kalle Valo
  0 siblings, 0 replies; 14+ messages in thread
From: Kalle Valo @ 2024-12-09 20:01 UTC (permalink / raw)
  To: Jeff Johnson; +Cc: ath12k, linux-wireless

Jeff Johnson <jeff.johnson@oss.qualcomm.com> writes:

> Subject nit: s/reveive/receive/
>
> I'll fixup in 'pending' if there are no additional comments on this series

Great, thanks.

-- 
https://patchwork.kernel.org/project/linux-wireless/list/

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 0/9] wifi: ath12k: MLO support part 8
  2024-12-09 18:54 [PATCH 0/9] wifi: ath12k: MLO support part 8 Kalle Valo
                   ` (8 preceding siblings ...)
  2024-12-09 18:54 ` [PATCH 9/9] wifi: ath12k: pass link ID during MLO while delivering skb Kalle Valo
@ 2024-12-10  8:25 ` Kalle Valo
  2024-12-16 16:50 ` Jeff Johnson
  10 siblings, 0 replies; 14+ messages in thread
From: Kalle Valo @ 2024-12-10  8:25 UTC (permalink / raw)
  To: ath12k; +Cc: linux-wireless

Kalle Valo <kvalo@kernel.org> writes:

> From: Kalle Valo <quic_kvalo@quicinc.com>
>
> Getting MLO to work with QCN9274 is getting close, this should be the second to
> last patchset. Small patches this time. Minor changes to data path to support
> MLO, some interface combination rework and few fixes.
>
> Please review.

I forgot to mention that this (naturally) depends on part 7:

https://patchwork.kernel.org/project/linux-wireless/cover/20241209153034.50558-1-kvalo@kernel.org/

-- 
https://patchwork.kernel.org/project/linux-wireless/list/

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 0/9] wifi: ath12k: MLO support part 8
  2024-12-09 18:54 [PATCH 0/9] wifi: ath12k: MLO support part 8 Kalle Valo
                   ` (9 preceding siblings ...)
  2024-12-10  8:25 ` [PATCH 0/9] wifi: ath12k: MLO support part 8 Kalle Valo
@ 2024-12-16 16:50 ` Jeff Johnson
  10 siblings, 0 replies; 14+ messages in thread
From: Jeff Johnson @ 2024-12-16 16:50 UTC (permalink / raw)
  To: ath12k, Kalle Valo; +Cc: linux-wireless


On Mon, 09 Dec 2024 20:54:12 +0200, Kalle Valo wrote:
> Getting MLO to work with QCN9274 is getting close, this should be the second to
> last patchset. Small patches this time. Minor changes to data path to support
> MLO, some interface combination rework and few fixes.
> 
> Please review.
> 
> Aditya Kumar Singh (3):
>   wifi: ath12k: fix ath12k_qmi_alloc_chunk() to handle too large
>     allocations
>   wifi: ath12k: fix ar->supports_6ghz usage during hw register
>   wifi: ath12k: pass link ID during MLO while delivering skb
> 
> [...]

Applied, thanks!

[1/9] wifi: ath12k: move to HW link id based reveive handling
      commit: e536c8690cf423f47e5e2f491134d3511edbbaf2
[2/9] wifi: ath12k: add partner device buffer support in receive data path
      commit: fc1e7e004b1808da38c862d57fccfad631a1445a
[3/9] wifi: ath12k: add helper function to init partner cmem configuration
      commit: 5a8abdf88deac066c4c4a224e45b80088ea94ff0
[4/9] wifi: ath12k: introduce interface combination cleanup helper
      commit: 2e4b8a49191ea9df8430cb6e8af7429eadd54709
[5/9] wifi: ath12k: Refactor radio frequency information
      commit: 4b861d256235c0c94d1a09e4dd888accc0eec5e9
[6/9] wifi: ath12k: advertise multi device interface combination
      commit: 03156d08d9ae768bffc0eba5eeeede868f52331f
[7/9] wifi: ath12k: fix ath12k_qmi_alloc_chunk() to handle too large allocations
      commit: c14725f359ef982923f3bc7e222c7687ffe4e496
[8/9] wifi: ath12k: fix ar->supports_6ghz usage during hw register
      commit: 95740fb0d3dbe276bf414c44cea0c35948407800
[9/9] wifi: ath12k: pass link ID during MLO while delivering skb
      commit: 1d015d783da57b002fda75b29aa3b886724c0129

Best regards,
-- 
Jeff Johnson <jeff.johnson@oss.qualcomm.com>


^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2024-12-16 16:51 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-12-09 18:54 [PATCH 0/9] wifi: ath12k: MLO support part 8 Kalle Valo
2024-12-09 18:54 ` [PATCH 1/9] wifi: ath12k: move to HW link id based reveive handling Kalle Valo
2024-12-09 19:44   ` Jeff Johnson
2024-12-09 20:01     ` Kalle Valo
2024-12-09 18:54 ` [PATCH 2/9] wifi: ath12k: add partner device buffer support in receive data path Kalle Valo
2024-12-09 18:54 ` [PATCH 3/9] wifi: ath12k: add helper function to init partner cmem configuration Kalle Valo
2024-12-09 18:54 ` [PATCH 4/9] wifi: ath12k: introduce interface combination cleanup helper Kalle Valo
2024-12-09 18:54 ` [PATCH 5/9] wifi: ath12k: Refactor radio frequency information Kalle Valo
2024-12-09 18:54 ` [PATCH 6/9] wifi: ath12k: advertise multi device interface combination Kalle Valo
2024-12-09 18:54 ` [PATCH 7/9] wifi: ath12k: fix ath12k_qmi_alloc_chunk() to handle too large allocations Kalle Valo
2024-12-09 18:54 ` [PATCH 8/9] wifi: ath12k: fix ar->supports_6ghz usage during hw register Kalle Valo
2024-12-09 18:54 ` [PATCH 9/9] wifi: ath12k: pass link ID during MLO while delivering skb Kalle Valo
2024-12-10  8:25 ` [PATCH 0/9] wifi: ath12k: MLO support part 8 Kalle Valo
2024-12-16 16:50 ` Jeff Johnson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).