From 5c518e884c4b9cfef5e6322b51f7a6286b385942 Mon Sep 17 00:00:00 2001 From: Aasir Rasheed Date: Thu, 5 Nov 2020 12:05:20 +0530 Subject: [PATCH] icnss: Update FW_INIT_DONE QMI indication with hang event params Update FW_INIT_DONE QMI indication with hang event address offset and length. Change-Id: I4a9c9f796329c01feefd4188f0894a3fe4462584 Signed-off-by: Aasir Rasheed --- .../cnss_utils/wlan_firmware_service_v01.c | 36 +++++++++++ .../cnss_utils/wlan_firmware_service_v01.h | 8 ++- drivers/soc/qcom/icnss2/main.c | 3 +- drivers/soc/qcom/icnss2/qmi.c | 59 +++++++++++++++++++ 4 files changed, 102 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/cnss_utils/wlan_firmware_service_v01.c b/drivers/net/wireless/cnss_utils/wlan_firmware_service_v01.c index b5d348cad289..5b212bc22fc1 100644 --- a/drivers/net/wireless/cnss_utils/wlan_firmware_service_v01.c +++ b/drivers/net/wireless/cnss_utils/wlan_firmware_service_v01.c @@ -3205,6 +3205,42 @@ struct qmi_elem_info wlfw_fw_mem_ready_ind_msg_v01_ei[] = { EXPORT_SYMBOL(wlfw_fw_mem_ready_ind_msg_v01_ei); struct qmi_elem_info wlfw_fw_init_done_ind_msg_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_fw_init_done_ind_msg_v01, + hang_data_addr_offset_valid), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct wlfw_fw_init_done_ind_msg_v01, + hang_data_addr_offset), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct wlfw_fw_init_done_ind_msg_v01, + hang_data_length_valid), + }, + { + .data_type = QMI_UNSIGNED_2_BYTE, + .elem_len = 1, + .elem_size = sizeof(u16), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct wlfw_fw_init_done_ind_msg_v01, + hang_data_length), + }, { .data_type = QMI_EOTI, .array_type = NO_ARRAY, diff --git a/drivers/net/wireless/cnss_utils/wlan_firmware_service_v01.h b/drivers/net/wireless/cnss_utils/wlan_firmware_service_v01.h index cdd81b429a97..41bc96173c62 100644 --- a/drivers/net/wireless/cnss_utils/wlan_firmware_service_v01.h +++ b/drivers/net/wireless/cnss_utils/wlan_firmware_service_v01.h @@ -768,9 +768,13 @@ struct wlfw_fw_mem_ready_ind_msg_v01 { extern struct qmi_elem_info wlfw_fw_mem_ready_ind_msg_v01_ei[]; struct wlfw_fw_init_done_ind_msg_v01 { - char placeholder; + u8 hang_data_addr_offset_valid; + u32 hang_data_addr_offset; + u8 hang_data_length_valid; + u16 hang_data_length; }; -#define WLFW_FW_INIT_DONE_IND_MSG_V01_MAX_MSG_LEN 0 + +#define WLFW_FW_INIT_DONE_IND_MSG_V01_MAX_MSG_LEN 12 extern struct qmi_elem_info wlfw_fw_init_done_ind_msg_v01_ei[]; struct wlfw_rejuvenate_ind_msg_v01 { diff --git a/drivers/soc/qcom/icnss2/main.c b/drivers/soc/qcom/icnss2/main.c index 370b8a9109c0..8e3861e92c30 100644 --- a/drivers/soc/qcom/icnss2/main.c +++ b/drivers/soc/qcom/icnss2/main.c @@ -1176,8 +1176,7 @@ static int icnss_driver_event_pd_service_down(struct icnss_priv *priv, if (priv->force_err_fatal) ICNSS_ASSERT(0); - if (priv->device_id == ADRASTEA_DEVICE_ID) - icnss_send_hang_event_data(priv); + icnss_send_hang_event_data(priv); if (priv->early_crash_ind) { icnss_pr_dbg("PD Down ignored as early indication is processed: %d, state: 0x%lx\n", diff --git a/drivers/soc/qcom/icnss2/qmi.c b/drivers/soc/qcom/icnss2/qmi.c index 5673f9114899..efe5d5d6677c 100644 --- a/drivers/soc/qcom/icnss2/qmi.c +++ b/drivers/soc/qcom/icnss2/qmi.c @@ -1752,6 +1752,10 @@ static void fw_init_done_ind_cb(struct qmi_handle *qmi, struct qmi_txn *txn, const void *data) { struct icnss_priv *priv = container_of(qmi, struct icnss_priv, qmi); + struct device *dev = &priv->pdev->dev; + const struct wlfw_fw_init_done_ind_msg_v01 *ind_msg = data; + uint64_t msa_base_addr = priv->msa_pa; + phys_addr_t hang_data_phy_addr; icnss_pr_dbg("Received QMI WLFW FW initialization done indication\n"); @@ -1760,8 +1764,63 @@ static void fw_init_done_ind_cb(struct qmi_handle *qmi, return; } + /* Check if the length is valid & + * the length should not be 0 and + * should be <= WLFW_MAX_HANG_EVENT_DATA_SIZE(400) + */ + + if (ind_msg->hang_data_length_valid && + ind_msg->hang_data_length && + ind_msg->hang_data_length <= WLFW_MAX_HANG_EVENT_DATA_SIZE) + priv->hang_event_data_len = ind_msg->hang_data_length; + else + goto out; + + /* Check if the offset is valid & + * the offset should be in range of 0 to msa_mem_size-hang_data_length + */ + + if (ind_msg->hang_data_addr_offset_valid && + (ind_msg->hang_data_addr_offset <= (priv->msa_mem_size - + ind_msg->hang_data_length))) + hang_data_phy_addr = msa_base_addr + + ind_msg->hang_data_addr_offset; + else + goto out; + + if (priv->hang_event_data_pa == hang_data_phy_addr) + goto exit; + + priv->hang_event_data_pa = hang_data_phy_addr; + priv->hang_event_data_va = devm_ioremap(dev, priv->hang_event_data_pa, + ind_msg->hang_data_length); + + if (!priv->hang_event_data_va) { + icnss_pr_err("Hang Data ioremap failed: phy addr: %pa\n", + &priv->hang_event_data_pa); + goto fail; + } + +exit: + icnss_pr_dbg("Hang Event Data details,Offset:0x%x, Length:0x%x,va_addr: 0x%pK\n", + ind_msg->hang_data_addr_offset, + ind_msg->hang_data_length, + priv->hang_event_data_va); + + goto post; + +out: + icnss_pr_err("Invalid Hang Data details, Offset:0x%x, Length:0x%x", + ind_msg->hang_data_addr_offset, + ind_msg->hang_data_length); +fail: + priv->hang_event_data_va = NULL; + priv->hang_event_data_pa = 0; + priv->hang_event_data_len = 0; +post: icnss_driver_event_post(priv, ICNSS_DRIVER_EVENT_FW_INIT_DONE_IND, 0, NULL); + } static void wlfw_qdss_trace_req_mem_ind_cb(struct qmi_handle *qmi,