[PATCH 7/7] wifi: ath12k: introduce mlo_capable flag for device group

Kalle Valo
2024-12-04T16:32:33Z

From: Karthikeyan Periyasamy <quic_periyasa@quicinc.com>

Currently, during mac80211 allocate and register single device is
considered for the registration. But, in future, during multi device
group abstraction is introduced, all the devices has to be combined
together as a single abstraction and then hardware should be allocated.

All the devices in the group should be combined together only if it
supports inter device mlo capability. The decision of whether to combine
the devices or not can be based on the mlo capability flag in
ath12k_hw_group.

By default, mlo_capable flag in the group would be set as false. During
QMI PHY capability exchange, only when we have more than one chip in the
group or if one chip, then that chip supports inter MLO, then mlo_capable
flag in the group will be enabled.

Add changes to introduce mlo_capable flag for device group and refactor
ath12k_mac_hw_allocate() api based on device group (ag) rather than
device (ab).

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: Harshitha Prem <quic_hprem@quicinc.com>
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
---
drivers/net/wireless/ath/ath12k/core.c | 17 +++++++++++++++++
drivers/net/wireless/ath/ath12k/core.h | 3 +++
drivers/net/wireless/ath/ath12k/mac.c | 8 +++++---
drivers/net/wireless/ath/ath12k/qmi.c | 6 ++++--
4 files changed, 29 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c
index 18b29515c6ae..49d1ac15cb7a 100644
--- a/drivers/net/wireless/ath/ath12k/core.c
+++ b/drivers/net/wireless/ath/ath12k/core.c
@@ -1439,6 +1439,7 @@ static struct ath12k_hw_group *ath12k_core_hw_group_assign(struct ath12k_base *a
ab->device_id = ag->num_probed++;
ag->ab[ab->device_id] = ab;
ab->ag = ag;
+ ag->mlo_capable = false;

return ag;
}
@@ -1548,6 +1549,22 @@ static int ath12k_core_hw_group_create(struct ath12k_hw_group *ag)
return 0;
}

+void ath12k_core_hw_group_set_mlo_capable(struct ath12k_hw_group *ag)
+{
+ lockdep_assert_held(&ag->mutex);
+
+ /* If more than one devices are grouped, then inter MLO
+ * functionality can work still independent of whether internally
+ * each device supports single_chip_mlo or not.
+ * Only when there is one device, then it depends whether the
+ * device can support intra chip MLO or not
+ */
+ if (ag->num_devices > 1)
+ ag->mlo_capable = true;
+ else
+ ag->mlo_capable = ag->ab[0]->single_chip_mlo_supp;
+}
+
int ath12k_core_init(struct ath12k_base *ab)
{
struct ath12k_hw_group *ag;
diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h
index 64252d6491cd..458e3d0071a8 100644
--- a/drivers/net/wireless/ath/ath12k/core.h
+++ b/drivers/net/wireless/ath/ath12k/core.h
@@ -844,6 +844,7 @@ struct ath12k_hw_group {
*/
struct ath12k_hw *ah[ATH12K_GROUP_MAX_RADIO];
u8 num_hw;
+ bool mlo_capable;
};

/* Master structure to hold the hw data which may be used in core module */
@@ -1066,6 +1067,8 @@ u32 ath12k_core_get_max_station_per_radio(struct ath12k_base *ab);
u32 ath12k_core_get_max_peers_per_radio(struct ath12k_base *ab);
u32 ath12k_core_get_max_num_tids(struct ath12k_base *ab);

+void ath12k_core_hw_group_set_mlo_capable(struct ath12k_hw_group *ag);
+
static inline const char *ath12k_scan_state_str(enum ath12k_scan_state state)
{
switch (state) {
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index 1cf724a530b5..c4eab4c1c10e 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -10968,10 +10968,12 @@ int ath12k_mac_allocate(struct ath12k_hw_group *ag)
/* All pdev get combined and register as single wiphy based on
* hardware group which participate in multi-link operation else
* each pdev get register separately.
- *
- * Currently, registering as single pdevs.
*/
- radio_per_hw = 1;
+ if (ag->mlo_capable)
+ radio_per_hw = total_radio;
+ else
+ radio_per_hw = 1;
+
num_hw = total_radio / radio_per_hw;

if (WARN_ON(num_hw >= ATH12K_GROUP_MAX_RADIO))
diff --git a/drivers/net/wireless/ath/ath12k/qmi.c b/drivers/net/wireless/ath/ath12k/qmi.c
index 2591d132a3fc..ba3cd2342465 100644
--- a/drivers/net/wireless/ath/ath12k/qmi.c
+++ b/drivers/net/wireless/ath/ath12k/qmi.c
@@ -2023,9 +2023,9 @@ static void ath12k_host_cap_parse_mlo(struct ath12k_base *ab,
u8 hw_link_id = 0;
int i;

- if (!ab->single_chip_mlo_supp) {
+ if (!ab->ag->mlo_capable) {
ath12k_dbg(ab, ATH12K_DBG_QMI,
- "intra device MLO is disabled hence skip QMI MLO cap");
+ "MLO is disabled hence skip QMI MLO cap");
return;
}

@@ -3170,6 +3170,8 @@ int ath12k_qmi_event_server_arrive(struct ath12k_qmi *qmi)
mutex_lock(&ag->mutex);

if (ath12k_qmi_hw_group_host_cap_ready(ag)) {
+ ath12k_core_hw_group_set_mlo_capable(ag);
+
block_ab = ath12k_qmi_hw_group_find_blocked(ag);
if (block_ab)
ath12k_qmi_trigger_host_cap(block_ab);
--
2.39.5