]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
wifi: ath12k: add QMI PHY capability learn support
authorKarthikeyan Periyasamy <quic_periyasa@quicinc.com>
Tue, 16 Jan 2024 12:33:07 +0000 (14:33 +0200)
committerKalle Valo <quic_kvalo@quicinc.com>
Wed, 17 Jan 2024 08:36:49 +0000 (10:36 +0200)
Currently, the number of PHY is learned from the firmware service ready
event message. However, on the QCN9274 platform, number of PHY is a
variable parameter. To enable MLO capability in the QMI host capability
request message, the driver needs the PHY count information earlier than
the firmware service ready event. Therefore, a new QMI message,
"PHY capability message", is introduced to retrieve this information.
This message allows the driver to fill in the MLO parameter in the QMI
host capability request message. If the new QMI PHY capability message
fails, the default configuration in the HW params will be used.

Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-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>
Acked-by: Jeff Johnson <quic_jjohnson@quicinc.com>
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
Link: https://msgid.link/20240113001659.1022465-3-quic_periyasa@quicinc.com
drivers/net/wireless/ath/ath12k/core.c
drivers/net/wireless/ath/ath12k/qmi.c
drivers/net/wireless/ath/ath12k/qmi.h

index ababe7f01b5b437c0f3d1eb870cded8f45c0b3c8..6cab747ff858d12954c38275178b6bf7ae21d911 100644 (file)
@@ -1174,6 +1174,7 @@ struct ath12k_base *ath12k_core_alloc(struct device *dev, size_t priv_size,
 
        ab->dev = dev;
        ab->hif.bus = bus;
+       ab->qmi.num_radios = U8_MAX;
 
        return ab;
 
index 916dec6267029fd7a96357b2a268577ea5ac4d9c..d20d08023c8178dfe6e7120d9a1a625a3fd38a30 100644 (file)
@@ -528,6 +528,67 @@ static const struct qmi_elem_info qmi_wlanfw_host_cap_resp_msg_v01_ei[] = {
        },
 };
 
+static const struct qmi_elem_info qmi_wlanfw_phy_cap_req_msg_v01_ei[] = {
+       {
+               .data_type      = QMI_EOTI,
+               .array_type     = NO_ARRAY,
+               .tlv_type       = QMI_COMMON_TLV_TYPE,
+       },
+};
+
+static const struct qmi_elem_info qmi_wlanfw_phy_cap_resp_msg_v01_ei[] = {
+       {
+               .data_type      = QMI_STRUCT,
+               .elem_len       = 1,
+               .elem_size      = sizeof(struct qmi_response_type_v01),
+               .array_type     = NO_ARRAY,
+               .tlv_type       = 0x02,
+               .offset         = offsetof(struct qmi_wlanfw_phy_cap_resp_msg_v01, resp),
+               .ei_array       = qmi_response_type_v01_ei,
+       },
+       {
+               .data_type      = QMI_OPT_FLAG,
+               .elem_len       = 1,
+               .elem_size      = sizeof(u8),
+               .array_type     = NO_ARRAY,
+               .tlv_type       = 0x10,
+               .offset         = offsetof(struct qmi_wlanfw_phy_cap_resp_msg_v01,
+                                          num_phy_valid),
+       },
+       {
+               .data_type      = QMI_UNSIGNED_1_BYTE,
+               .elem_len       = 1,
+               .elem_size      = sizeof(u8),
+               .array_type     = NO_ARRAY,
+               .tlv_type       = 0x10,
+               .offset         = offsetof(struct qmi_wlanfw_phy_cap_resp_msg_v01,
+                                          num_phy),
+       },
+       {
+               .data_type      = QMI_OPT_FLAG,
+               .elem_len       = 1,
+               .elem_size      = sizeof(u8),
+               .array_type     = NO_ARRAY,
+               .tlv_type       = 0x11,
+               .offset         = offsetof(struct qmi_wlanfw_phy_cap_resp_msg_v01,
+                                          board_id_valid),
+       },
+       {
+               .data_type      = QMI_UNSIGNED_4_BYTE,
+               .elem_len       = 1,
+               .elem_size      = sizeof(u32),
+               .array_type     = NO_ARRAY,
+               .tlv_type       = 0x11,
+               .offset         = offsetof(struct qmi_wlanfw_phy_cap_resp_msg_v01,
+                                          board_id),
+       },
+       {
+               .data_type      = QMI_EOTI,
+               .array_type     = NO_ARRAY,
+               .tlv_type       = QMI_COMMON_TLV_TYPE,
+       },
+};
+
 static const struct qmi_elem_info qmi_wlanfw_ind_register_req_msg_v01_ei[] = {
        {
                .data_type      = QMI_OPT_FLAG,
@@ -1900,8 +1961,12 @@ static void ath12k_host_cap_parse_mlo(struct ath12k_base *ab,
        u8 hw_link_id = 0;
        int i;
 
-       if (!ab->hw_params->def_num_link)
+       if (!ab->qmi.num_radios || ab->qmi.num_radios == U8_MAX) {
+               ath12k_dbg(ab, ATH12K_DBG_QMI,
+                          "skip QMI MLO cap due to invalid num_radio %d\n",
+                          ab->qmi.num_radios);
                return;
+       }
 
        req->mlo_capable_valid = 1;
        req->mlo_capable = 1;
@@ -1919,7 +1984,7 @@ static void ath12k_host_cap_parse_mlo(struct ath12k_base *ab,
 
        info = &req->mlo_chip_info[0];
        info->chip_id = 0;
-       info->num_local_links = ab->hw_params->def_num_link;
+       info->num_local_links = ab->qmi.num_radios;
 
        for (i = 0; i < info->num_local_links; i++) {
                info->hw_link_id[i] = hw_link_id;
@@ -2008,6 +2073,59 @@ out:
        return ret;
 }
 
+static void ath12k_qmi_phy_cap_send(struct ath12k_base *ab)
+{
+       struct qmi_wlanfw_phy_cap_req_msg_v01 req = {};
+       struct qmi_wlanfw_phy_cap_resp_msg_v01 resp = {};
+       struct qmi_txn txn;
+       int ret;
+
+       ret = qmi_txn_init(&ab->qmi.handle, &txn,
+                          qmi_wlanfw_phy_cap_resp_msg_v01_ei, &resp);
+       if (ret < 0)
+               goto out;
+
+       ret = qmi_send_request(&ab->qmi.handle, NULL, &txn,
+                              QMI_WLANFW_PHY_CAP_REQ_V01,
+                              QMI_WLANFW_PHY_CAP_REQ_MSG_V01_MAX_LEN,
+                              qmi_wlanfw_phy_cap_req_msg_v01_ei, &req);
+       if (ret < 0) {
+               qmi_txn_cancel(&txn);
+               ath12k_warn(ab, "failed to send phy capability request: %d\n", ret);
+               goto out;
+       }
+
+       ret = qmi_txn_wait(&txn, msecs_to_jiffies(ATH12K_QMI_WLANFW_TIMEOUT_MS));
+       if (ret < 0)
+               goto out;
+
+       if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
+               ret = -EOPNOTSUPP;
+               goto out;
+       }
+
+       if (!resp.num_phy_valid) {
+               ret = -ENODATA;
+               goto out;
+       }
+
+       ab->qmi.num_radios = resp.num_phy;
+
+       ath12k_dbg(ab, ATH12K_DBG_QMI, "phy capability resp valid %d num_phy %d valid %d board_id %d\n",
+                  resp.num_phy_valid, resp.num_phy,
+                  resp.board_id_valid, resp.board_id);
+
+       return;
+
+out:
+       /* If PHY capability not advertised then rely on default num link */
+       ab->qmi.num_radios = ab->hw_params->def_num_link;
+
+       ath12k_dbg(ab, ATH12K_DBG_QMI,
+                  "no valid response from PHY capability, choose default num_phy %d\n",
+                  ab->qmi.num_radios);
+}
+
 static int ath12k_qmi_fw_ind_register_send(struct ath12k_base *ab)
 {
        struct qmi_wlanfw_ind_register_req_msg_v01 *req;
@@ -2794,6 +2912,8 @@ static int ath12k_qmi_event_server_arrive(struct ath12k_qmi *qmi)
        struct ath12k_base *ab = qmi->ab;
        int ret;
 
+       ath12k_qmi_phy_cap_send(ab);
+
        ret = ath12k_qmi_fw_ind_register_send(ab);
        if (ret < 0) {
                ath12k_warn(ab, "qmi failed to send FW indication QMI:%d\n", ret);
index e25bbaa125e83346e5cc7541aac196e89215a8ad..bfed22c310be4ae6d1a10a07fdf15ada5b39ae32 100644 (file)
@@ -141,6 +141,7 @@ struct ath12k_qmi {
        u32 target_mem_mode;
        bool target_mem_delayed;
        u8 cal_done;
+       u8 num_radios;
        struct target_info target;
        struct m3_mem_region m3_mem;
        unsigned int service_ins_id;
@@ -251,6 +252,22 @@ struct qmi_wlanfw_host_cap_resp_msg_v01 {
        struct qmi_response_type_v01 resp;
 };
 
+#define QMI_WLANFW_PHY_CAP_REQ_MSG_V01_MAX_LEN         0
+#define QMI_WLANFW_PHY_CAP_REQ_V01                     0x0057
+#define QMI_WLANFW_PHY_CAP_RESP_MSG_V01_MAX_LEN                18
+#define QMI_WLANFW_PHY_CAP_RESP_V01                    0x0057
+
+struct qmi_wlanfw_phy_cap_req_msg_v01 {
+};
+
+struct qmi_wlanfw_phy_cap_resp_msg_v01 {
+       struct qmi_response_type_v01 resp;
+       u8 num_phy_valid;
+       u8 num_phy;
+       u8 board_id_valid;
+       u32 board_id;
+};
+
 #define QMI_WLANFW_IND_REGISTER_REQ_MSG_V01_MAX_LEN            54
 #define QMI_WLANFW_IND_REGISTER_REQ_V01                                0x0020
 #define QMI_WLANFW_IND_REGISTER_RESP_MSG_V01_MAX_LEN           18