[RFC PATCH v3 4/5] wifi: ath12k: Assign unique hardware link IDs during QMI host capability

Raj Kumar Bhagat
2024-11-05T18:05:54Z

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

Currently, in the QMI host capability, the device index, the number of
local links, and the corresponding hardware link IDs are sent. The
hardware link ID assignment is based on the local variable `hw_link_id`,
which starts from 0 and ranges up to `num_local_links` in the device.
Starting from 0 is not ideal because it can result in the same link ID
being assigned to different devices in certain scenarios (e.g., split MAC).
Additionally, for multi link operations the firmware expects the hardware
link IDs in the same order as the Wireless Serial Interface (WSI)
connection.

Hence, for MLO to function seamlessly, the hardware link IDs across
devices need to be unique and should follow the order of the WSI
connection.

To address this, a previous change read the WSI index from the Device Tree
(DT) and stored it. Use this WSI index to determine the starting hardware
link IDs for each device, ensuring uniqueness and correct order across all
devices.

While at it, add debug prints to clearly show the MLO capability
advertisement sent during QMI host capability exchange.

Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
Co-developed-by: Raj Kumar Bhagat <quic_rajkbhag@quicinc.com>
Signed-off-by: Raj Kumar Bhagat <quic_rajkbhag@quicinc.com>
---
drivers/net/wireless/ath/ath12k/core.h | 2 ++
drivers/net/wireless/ath/ath12k/qmi.c | 40 ++++++++++++++++++++++++--
2 files changed, 39 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h
index 619407398a99..a532cfdc7558 100644
--- a/drivers/net/wireless/ath/ath12k/core.h
+++ b/drivers/net/wireless/ath/ath12k/core.h
@@ -845,11 +845,13 @@ struct ath12k_hw_group {
u8 num_hw;
bool mlo_capable;
struct device_node *wsi_node[ATH12K_MAX_SOCS];
+ bool hw_link_id_init_done;
};

/* Holds WSI info specific to each device, excluding WSI group info */
struct ath12k_wsi_info {
u32 index;
+ u32 hw_link_id_base;
};

/* Master structure to hold the hw data which may be used in core module */
diff --git a/drivers/net/wireless/ath/ath12k/qmi.c b/drivers/net/wireless/ath/ath12k/qmi.c
index 689171b7b19f..ab34f4788867 100644
--- a/drivers/net/wireless/ath/ath12k/qmi.c
+++ b/drivers/net/wireless/ath/ath12k/qmi.c
@@ -2016,6 +2016,25 @@ static const struct qmi_elem_info qmi_wlanfw_wlan_ini_resp_msg_v01_ei[] = {
},
};

+static void ath12k_host_cap_hw_link_id_init(struct ath12k_hw_group *ag)
+{
+ struct ath12k_base *ab, *partner_ab;
+ int i, j, hw_id_base;
+
+ for (i = 0; i < ag->num_devices; i++) {
+ hw_id_base = 0;
+ ab = ag->ab[i];
+ for (j = 0; j < ag->num_devices; j++) {
+ partner_ab = ag->ab[j];
+ if (partner_ab->wsi_info.index >= ab->wsi_info.index)
+ continue;
+ hw_id_base += partner_ab->qmi.num_radios;
+ }
+ ab->wsi_info.hw_link_id_base = hw_id_base;
+ }
+ ag->hw_link_id_init_done = true;
+}
+
static int ath12k_host_cap_parse_mlo(struct ath12k_base *ab,
struct qmi_wlanfw_host_cap_req_msg_v01 *req)
{
@@ -2060,7 +2079,17 @@ static int ath12k_host_cap_parse_mlo(struct ath12k_base *ab,
req->mlo_num_chips_valid = 1;
req->mlo_num_chips = ag->num_devices;

+ ath12k_dbg(ab, ATH12K_DBG_QMI, "MLO Capability advertisement:");
+ ath12k_dbg(ab, ATH12K_DBG_QMI, " * device_id: %d", req->mlo_chip_id);
+ ath12k_dbg(ab, ATH12K_DBG_QMI, " * group_id: %d", req->mlo_group_id);
+ ath12k_dbg(ab, ATH12K_DBG_QMI, " * num_devices: %d", req->mlo_num_chips);
+ ath12k_dbg(ab, ATH12K_DBG_QMI, " * Devices info:");
+
mutex_lock(&ag->mutex_lock);
+
+ if (!ag->hw_link_id_init_done)
+ ath12k_host_cap_hw_link_id_init(ag);
+
for (i = 0; i < ag->num_devices; i++) {
info = &req->mlo_chip_info[i];
partner_ab = ag->ab[i];
@@ -2074,12 +2103,17 @@ static int ath12k_host_cap_parse_mlo(struct ath12k_base *ab,
info->chip_id = partner_ab->device_id;
info->num_local_links = partner_ab->qmi.num_radios;

- ath12k_dbg(ab, ATH12K_DBG_QMI, "MLO device id %d num_link %d\n",
- info->chip_id, info->num_local_links);
+ ath12k_dbg(ab, ATH12K_DBG_QMI, " * device_id: %d",
+ info->chip_id);
+ ath12k_dbg(ab, ATH12K_DBG_QMI, " * num_links: %d",
+ info->num_local_links);

for (j = 0; j < info->num_local_links; j++) {
- info->hw_link_id[j] = hw_link_id;
+ info->hw_link_id[j] = partner_ab->wsi_info.hw_link_id_base + j;
info->valid_mlo_link_id[j] = 1;
+ ath12k_dbg(ab, ATH12K_DBG_QMI,
+ " * hw_link_id: %d\n",
+ info->hw_link_id[j]);

hw_link_id++;
}
--
2.34.1