On AHB platforms, firmware operates in two modes: fixed-memory mode where firmware uses hardcoded addresses for memory regions such as BDF and does not request HOST_DDR memory from the host, and dynamic-memory mode where firmware expects the host to provide memory addresses including HOST_DDR after the Q6 read-only region and relies on host allocation for all memory types. Introduce QMI capability negotiation to support both modes. Add a new QMI PHY capability flag dynamic_ddr_support which is advertised by firmware to indicate it supports dynamic memory mode. When the host detects this capability, set the dynamic_mem_support flag in the host capability message to signal the host is ready to provide dynamic memory allocation. This triggers firmware to send the HOST_DDR memory request and use the host-provided address. For backward compatibility, if firmware doesn't advertise dynamic_ddr_support, the firmware continues to operate in fixed-memory mode where firmware uses predefined addresses. Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.6-01243-QCAHKSWPL_SILICONZ-1 Tested-on: IPQ5332 hw1.0 AHB WLAN.WBE.1.6-01275-QCAHKSWPL_SILICONZ-1 Signed-off-by: Aaradhana Sahu --- v3: -Restored QMI_WLANFW_HOST_CAP_REQ_MSG_V01_MAX_LEN change. v2: -Dropped QMI_WLANFW_HOST_CAP_REQ_MSG_V01_MAX_LEN and QMI_WLANFW_PHY_CAP_RESP_MSG_V01_MAX_LEN changes. -Used %u instead of %d in the debug log. --- drivers/net/wireless/ath/ath12k/qmi.c | 50 +++++++++++++++++++++++++-- drivers/net/wireless/ath/ath12k/qmi.h | 8 +++-- 2 files changed, 53 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/qmi.c b/drivers/net/wireless/ath/ath12k/qmi.c index fd762b5d7bb5..e15a0c0120d3 100644 --- a/drivers/net/wireless/ath/ath12k/qmi.c +++ b/drivers/net/wireless/ath/ath12k/qmi.c @@ -506,6 +506,24 @@ static const struct qmi_elem_info qmi_wlanfw_host_cap_req_msg_v01_ei[] = { .offset = offsetof(struct qmi_wlanfw_host_cap_req_msg_v01, feature_list), }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x33, + .offset = offsetof(struct qmi_wlanfw_host_cap_req_msg_v01, + dynamic_mem_support_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x33, + .offset = offsetof(struct qmi_wlanfw_host_cap_req_msg_v01, + dynamic_mem_support), + }, { .data_type = QMI_EOTI, .array_type = NO_ARRAY, @@ -602,6 +620,24 @@ static const struct qmi_elem_info qmi_wlanfw_phy_cap_resp_msg_v01_ei[] = { .offset = offsetof(struct qmi_wlanfw_phy_cap_resp_msg_v01, single_chip_mlo_support), }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x17, + .offset = offsetof(struct qmi_wlanfw_phy_cap_resp_msg_v01, + dynamic_ddr_support_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x17, + .offset = offsetof(struct qmi_wlanfw_phy_cap_resp_msg_v01, + dynamic_ddr_support), + }, { .data_type = QMI_EOTI, .array_type = NO_ARRAY, @@ -2248,6 +2284,11 @@ int ath12k_qmi_host_cap_send(struct ath12k_base *ab) if (ret < 0) goto out; + if (ab->qmi.dynamic_ddr_support) { + req.dynamic_mem_support_valid = 1; + req.dynamic_mem_support = 1; + } + ret = qmi_txn_init(&ab->qmi.handle, &txn, qmi_wlanfw_host_cap_resp_msg_v01_ei, &resp); if (ret < 0) @@ -2319,11 +2360,14 @@ static void ath12k_qmi_phy_cap_send(struct ath12k_base *ab) ab->qmi.num_radios = resp.num_phy; + if (resp.dynamic_ddr_support_valid) + ab->qmi.dynamic_ddr_support = resp.dynamic_ddr_support; + ath12k_dbg(ab, ATH12K_DBG_QMI, - "phy capability resp valid %d single_chip_mlo_support %d valid %d num_phy %d valid %d board_id %d\n", + "phy capability resp valid %d single_chip_mlo_support %d valid %d num_phy %d valid %d board_id %d dynamic_ddr_valid %u dynamic_ddr_support %u\n", resp.single_chip_mlo_support_valid, resp.single_chip_mlo_support, - resp.num_phy_valid, resp.num_phy, - resp.board_id_valid, resp.board_id); + resp.num_phy_valid, resp.num_phy, resp.board_id_valid, resp.board_id, + resp.dynamic_ddr_support_valid, resp.dynamic_ddr_support); return; diff --git a/drivers/net/wireless/ath/ath12k/qmi.h b/drivers/net/wireless/ath/ath12k/qmi.h index 2a63e214eb42..9bdb290e2cce 100644 --- a/drivers/net/wireless/ath/ath12k/qmi.h +++ b/drivers/net/wireless/ath/ath12k/qmi.h @@ -156,9 +156,10 @@ struct ath12k_qmi { struct m3_mem_region aux_uc_mem; unsigned int service_ins_id; struct dev_mem_info dev_mem[ATH12K_QMI_WLFW_MAX_DEV_MEM_NUM_V01]; + u8 dynamic_ddr_support; }; -#define QMI_WLANFW_HOST_CAP_REQ_MSG_V01_MAX_LEN 261 +#define QMI_WLANFW_HOST_CAP_REQ_MSG_V01_MAX_LEN 265 #define QMI_WLANFW_HOST_CAP_REQ_V01 0x0034 #define QMI_WLANFW_HOST_CAP_RESP_MSG_V01_MAX_LEN 7 #define QMI_WLFW_HOST_CAP_RESP_V01 0x0034 @@ -258,7 +259,8 @@ struct qmi_wlanfw_host_cap_req_msg_v01 { struct wlfw_host_mlo_chip_info_s_v01 mlo_chip_info[QMI_WLFW_MAX_NUM_MLO_CHIPS_V01]; u8 feature_list_valid; u64 feature_list; - + u8 dynamic_mem_support_valid; + u8 dynamic_mem_support; }; struct qmi_wlanfw_host_cap_resp_msg_v01 { @@ -281,6 +283,8 @@ struct qmi_wlanfw_phy_cap_resp_msg_v01 { u32 board_id; u8 single_chip_mlo_support_valid; u8 single_chip_mlo_support; + u8 dynamic_ddr_support_valid; + u8 dynamic_ddr_support; }; #define QMI_WLANFW_IND_REGISTER_REQ_MSG_V01_MAX_LEN 54 base-commit: 1547a99cd8d8c1ab3e04dbd92b72b3b5f7cb85a9 -- 2.34.1