@@ -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;
@@ -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) {
@@ -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))
@@ -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);