diff --git a/cnss2/main.c b/cnss2/main.c index 091aa069bc..d5c5879842 100644 --- a/cnss2/main.c +++ b/cnss2/main.c @@ -315,6 +315,39 @@ int cnss_get_platform_cap(struct device *dev, struct cnss_platform_cap *cap) } EXPORT_SYMBOL(cnss_get_platform_cap); +/** + * cnss_get_fw_cap - Check whether FW supports specific capability or not + * @dev: Device + * @fw_cap: FW Capability which needs to be checked + * + * Return: TRUE if supported, FALSE on failure or if not supported + */ +bool cnss_get_fw_cap(struct device *dev, enum cnss_fw_caps fw_cap) +{ + struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev); + bool ret = false; + + if (!plat_priv) + return ret; + + if (!plat_priv->fw_caps) + return ret; + + switch (fw_cap) { + case CNSS_FW_CAP_DIRECT_LINK_SUPPORT: + ret = !!(plat_priv->fw_caps & + QMI_WLFW_DIRECT_LINK_SUPPORT_V01); + break; + default: + cnss_pr_err("Invalid FW Capability: 0x%x\n", fw_cap); + } + + cnss_pr_dbg("FW Capability 0x%x is %s\n", fw_cap, + ret ? "supported" : "not supported"); + return ret; +} +EXPORT_SYMBOL(cnss_get_fw_cap); + void cnss_request_pm_qos(struct device *dev, u32 qos_val) { struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev); diff --git a/cnss2/main.h b/cnss2/main.h index a315d430dc..1d88c1ebea 100644 --- a/cnss2/main.h +++ b/cnss2/main.h @@ -547,6 +547,7 @@ struct cnss_plat_data { u8 set_wlaon_pwr_ctrl; struct cnss_tcs_info tcs_info; bool fw_pcie_gen_switch; + u64 fw_caps; u8 pcie_gen_speed; struct cnss_dms_data dms; int power_up_error; diff --git a/cnss2/qmi.c b/cnss2/qmi.c index 2bb8e25b6a..74d7a0604d 100644 --- a/cnss2/qmi.c +++ b/cnss2/qmi.c @@ -566,9 +566,11 @@ int cnss_wlfw_tgt_cap_send_sync(struct cnss_plat_data *plat_priv) plat_priv->dev_mem_info[i].size); } } - if (resp->fw_caps_valid) + if (resp->fw_caps_valid) { plat_priv->fw_pcie_gen_switch = !!(resp->fw_caps & QMI_WLFW_HOST_PCIE_GEN_SWITCH_V01); + plat_priv->fw_caps = resp->fw_caps; + } if (resp->hang_data_length_valid && resp->hang_data_length && diff --git a/cnss_utils/wlan_firmware_service_v01.c b/cnss_utils/wlan_firmware_service_v01.c index 6db47107b0..c26635fd06 100644 --- a/cnss_utils/wlan_firmware_service_v01.c +++ b/cnss_utils/wlan_firmware_service_v01.c @@ -2104,6 +2104,26 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { wlfw_cap_resp_msg_v01, regdb_support), }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x25, + .offset = offsetof(struct + wlfw_cap_resp_msg_v01, + rxgainlut_support_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x25, + .offset = offsetof(struct + wlfw_cap_resp_msg_v01, + rxgainlut_support), + }, { .data_type = QMI_EOTI, .array_type = NO_ARRAY, @@ -6094,6 +6114,75 @@ struct qmi_elem_info wlfw_ini_file_download_resp_msg_v01_ei[] = { }; EXPORT_SYMBOL(wlfw_ini_file_download_resp_msg_v01_ei); +struct qmi_elem_info wlfw_phy_cap_req_msg_v01_ei[] = { + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; +EXPORT_SYMBOL(wlfw_phy_cap_req_msg_v01_ei); + +struct qmi_elem_info wlfw_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 + wlfw_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 + wlfw_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 + wlfw_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 + wlfw_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 + wlfw_phy_cap_resp_msg_v01, + board_id), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; +EXPORT_SYMBOL(wlfw_phy_cap_resp_msg_v01_ei); + /** * wlfw_is_valid_dt_node_found - Check if valid device tree node present * diff --git a/cnss_utils/wlan_firmware_service_v01.h b/cnss_utils/wlan_firmware_service_v01.h index fddc5921e3..7c9d8ddf58 100644 --- a/cnss_utils/wlan_firmware_service_v01.h +++ b/cnss_utils/wlan_firmware_service_v01.h @@ -26,6 +26,7 @@ #define QMI_WLFW_FW_READY_IND_V01 0x0021 #define QMI_WLFW_QDSS_TRACE_MEM_INFO_RESP_V01 0x0040 #define QMI_WLFW_CAL_UPDATE_REQ_V01 0x0029 +#define QMI_WLFW_PHY_CAP_REQ_V01 0x0057 #define QMI_WLFW_REQUEST_MEM_IND_V01 0x0035 #define QMI_WLFW_QDSS_TRACE_DATA_RESP_V01 0x0042 #define QMI_WLFW_RESPOND_MEM_RESP_V01 0x0036 @@ -68,6 +69,7 @@ #define QMI_WLFW_QDSS_TRACE_REQ_MEM_IND_V01 0x003F #define QMI_WLFW_INITIATE_CAL_DOWNLOAD_IND_V01 0x0028 #define QMI_WLFW_ATHDIAG_WRITE_RESP_V01 0x0031 +#define QMI_WLFW_PHY_CAP_RESP_V01 0x0057 #define QMI_WLFW_QDSS_TRACE_CONFIG_DOWNLOAD_RESP_V01 0x0044 #define QMI_WLFW_SOC_WAKE_RESP_V01 0x004F #define QMI_WLFW_GET_INFO_RESP_V01 0x004A @@ -310,6 +312,7 @@ enum wlfw_ini_file_type_v01 { #define QMI_WLFW_CBC_FILE_DOWNLOAD_V01 ((u64)0x02ULL) #define QMI_WLFW_HOST_PCIE_GEN_SWITCH_V01 ((u64)0x01ULL) +#define QMI_WLFW_DIRECT_LINK_SUPPORT_V01 ((u64)0x02ULL) struct wlfw_ce_tgt_pipe_cfg_s_v01 { u32 pipe_num; @@ -610,9 +613,11 @@ struct wlfw_cap_resp_msg_v01 { u8 regdb_mandatory; u8 regdb_support_valid; u8 regdb_support; + u8 rxgainlut_support_valid; + u8 rxgainlut_support; }; -#define WLFW_CAP_RESP_MSG_V01_MAX_MSG_LEN 1142 +#define WLFW_CAP_RESP_MSG_V01_MAX_MSG_LEN 1146 extern struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[]; struct wlfw_bdf_download_req_msg_v01 { @@ -1344,4 +1349,20 @@ struct wlfw_ini_file_download_resp_msg_v01 { #define WLFW_INI_FILE_DOWNLOAD_RESP_MSG_V01_MAX_MSG_LEN 7 extern struct qmi_elem_info wlfw_ini_file_download_resp_msg_v01_ei[]; +struct wlfw_phy_cap_req_msg_v01 { + char placeholder; +}; +#define WLFW_PHY_CAP_REQ_MSG_V01_MAX_MSG_LEN 0 +extern struct qmi_elem_info wlfw_phy_cap_req_msg_v01_ei[]; + +struct wlfw_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 WLFW_PHY_CAP_RESP_MSG_V01_MAX_MSG_LEN 18 +extern struct qmi_elem_info wlfw_phy_cap_resp_msg_v01_ei[]; + #endif diff --git a/inc/cnss2.h b/inc/cnss2.h index 28fcf80f9e..255a2cc08d 100644 --- a/inc/cnss2.h +++ b/inc/cnss2.h @@ -204,6 +204,10 @@ enum cnss_recovery_reason { CNSS_REASON_TIMEOUT, }; +enum cnss_fw_caps { + CNSS_FW_CAP_DIRECT_LINK_SUPPORT, +}; + enum cnss_remote_mem_type { CNSS_REMOTE_MEM_TYPE_FW, CNSS_REMOTE_MEM_TYPE_QDSS, @@ -299,4 +303,5 @@ extern struct kobject *cnss_get_wifi_kobj(struct device *dev); extern int cnss_send_buffer_to_afcmem(struct device *dev, char *afcdb, uint32_t len, uint8_t slotid); extern int cnss_reset_afcmem(struct device *dev, uint8_t slotid); +extern bool cnss_get_fw_cap(struct device *dev, enum cnss_fw_caps fw_cap); #endif /* _NET_CNSS2_H */