Commit 53a65445 authored by Karthikeyan Periyasamy's avatar Karthikeyan Periyasamy Committed by Kalle Valo

wifi: ath12k: add QMI PHY capability learn support

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: default avatarKarthikeyan Periyasamy <quic_periyasa@quicinc.com>
Acked-by: default avatarJeff Johnson <quic_jjohnson@quicinc.com>
Signed-off-by: default avatarKalle Valo <quic_kvalo@quicinc.com>
Link: https://msgid.link/20240113001659.1022465-3-quic_periyasa@quicinc.com
parent 76fece36
...@@ -1174,6 +1174,7 @@ struct ath12k_base *ath12k_core_alloc(struct device *dev, size_t priv_size, ...@@ -1174,6 +1174,7 @@ struct ath12k_base *ath12k_core_alloc(struct device *dev, size_t priv_size,
ab->dev = dev; ab->dev = dev;
ab->hif.bus = bus; ab->hif.bus = bus;
ab->qmi.num_radios = U8_MAX;
return ab; return ab;
......
...@@ -528,6 +528,67 @@ static const struct qmi_elem_info qmi_wlanfw_host_cap_resp_msg_v01_ei[] = { ...@@ -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[] = { static const struct qmi_elem_info qmi_wlanfw_ind_register_req_msg_v01_ei[] = {
{ {
.data_type = QMI_OPT_FLAG, .data_type = QMI_OPT_FLAG,
...@@ -1900,8 +1961,12 @@ static void ath12k_host_cap_parse_mlo(struct ath12k_base *ab, ...@@ -1900,8 +1961,12 @@ static void ath12k_host_cap_parse_mlo(struct ath12k_base *ab,
u8 hw_link_id = 0; u8 hw_link_id = 0;
int i; 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; return;
}
req->mlo_capable_valid = 1; req->mlo_capable_valid = 1;
req->mlo_capable = 1; req->mlo_capable = 1;
...@@ -1919,7 +1984,7 @@ static void ath12k_host_cap_parse_mlo(struct ath12k_base *ab, ...@@ -1919,7 +1984,7 @@ static void ath12k_host_cap_parse_mlo(struct ath12k_base *ab,
info = &req->mlo_chip_info[0]; info = &req->mlo_chip_info[0];
info->chip_id = 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++) { for (i = 0; i < info->num_local_links; i++) {
info->hw_link_id[i] = hw_link_id; info->hw_link_id[i] = hw_link_id;
...@@ -2008,6 +2073,59 @@ static int ath12k_qmi_host_cap_send(struct ath12k_base *ab) ...@@ -2008,6 +2073,59 @@ static int ath12k_qmi_host_cap_send(struct ath12k_base *ab)
return ret; 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) static int ath12k_qmi_fw_ind_register_send(struct ath12k_base *ab)
{ {
struct qmi_wlanfw_ind_register_req_msg_v01 *req; struct qmi_wlanfw_ind_register_req_msg_v01 *req;
...@@ -2794,6 +2912,8 @@ static int ath12k_qmi_event_server_arrive(struct ath12k_qmi *qmi) ...@@ -2794,6 +2912,8 @@ static int ath12k_qmi_event_server_arrive(struct ath12k_qmi *qmi)
struct ath12k_base *ab = qmi->ab; struct ath12k_base *ab = qmi->ab;
int ret; int ret;
ath12k_qmi_phy_cap_send(ab);
ret = ath12k_qmi_fw_ind_register_send(ab); ret = ath12k_qmi_fw_ind_register_send(ab);
if (ret < 0) { if (ret < 0) {
ath12k_warn(ab, "qmi failed to send FW indication QMI:%d\n", ret); ath12k_warn(ab, "qmi failed to send FW indication QMI:%d\n", ret);
......
...@@ -141,6 +141,7 @@ struct ath12k_qmi { ...@@ -141,6 +141,7 @@ struct ath12k_qmi {
u32 target_mem_mode; u32 target_mem_mode;
bool target_mem_delayed; bool target_mem_delayed;
u8 cal_done; u8 cal_done;
u8 num_radios;
struct target_info target; struct target_info target;
struct m3_mem_region m3_mem; struct m3_mem_region m3_mem;
unsigned int service_ins_id; unsigned int service_ins_id;
...@@ -251,6 +252,22 @@ struct qmi_wlanfw_host_cap_resp_msg_v01 { ...@@ -251,6 +252,22 @@ struct qmi_wlanfw_host_cap_resp_msg_v01 {
struct qmi_response_type_v01 resp; 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_MSG_V01_MAX_LEN 54
#define QMI_WLANFW_IND_REGISTER_REQ_V01 0x0020 #define QMI_WLANFW_IND_REGISTER_REQ_V01 0x0020
#define QMI_WLANFW_IND_REGISTER_RESP_MSG_V01_MAX_LEN 18 #define QMI_WLANFW_IND_REGISTER_RESP_MSG_V01_MAX_LEN 18
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment