Эх сурвалжийг харах

cnss2: Get hang event params over target cap qmi response

Add change to get hang event params over target cap response.
With this change hard-coding of hang data address and offset
is removed if valid hang data params are received over QMI.

Change-Id: Ife163cf66d5880cd9a658a841e5d4a73816fd982
Mohammed Siddiq 3 жил өмнө
parent
commit
42f4e0431a
3 өөрчлөгдсөн 43 нэмэгдсэн , 4 устгасан
  1. 3 0
      cnss2/main.h
  2. 24 3
      cnss2/pci.c
  3. 16 1
      cnss2/qmi.c

+ 3 - 0
cnss2/main.h

@@ -57,6 +57,7 @@
 #define FW_V2_NUMBER                    2
 #define POWER_ON_RETRY_MAX_TIMES        3
 #define POWER_ON_RETRY_DELAY_MS         500
+#define WLFW_MAX_HANG_EVENT_DATA_SIZE   384
 
 #define CNSS_EVENT_SYNC   BIT(0)
 #define CNSS_EVENT_UNINTERRUPTIBLE BIT(1)
@@ -541,6 +542,8 @@ struct cnss_plat_data {
 	bool adsp_pc_enabled;
 	u64 feature_list;
 	u32 is_converged_dt;
+	u16 hang_event_data_len;
+	u32 hang_data_addr_offset;
 };
 
 #if IS_ENABLED(CONFIG_ARCH_QCOM)

+ 24 - 3
cnss2/pci.c

@@ -5322,6 +5322,7 @@ static void cnss_pci_send_hang_event(struct cnss_pci_data *pci_priv)
 	struct cnss_hang_event hang_event;
 	void *hang_data_va = NULL;
 	u64 offset = 0;
+	u16 length = 0;
 	int i = 0;
 
 	if (!fw_mem || !plat_priv->fw_mem_seg_len)
@@ -5331,9 +5332,20 @@ static void cnss_pci_send_hang_event(struct cnss_pci_data *pci_priv)
 	switch (pci_priv->device_id) {
 	case QCA6390_DEVICE_ID:
 		offset = HST_HANG_DATA_OFFSET;
+		length = HANG_DATA_LENGTH;
 		break;
 	case QCA6490_DEVICE_ID:
-		offset = HSP_HANG_DATA_OFFSET;
+		/* Fallback to hard-coded values if hang event params not
+		 * present in QMI. Once all the firmware branches have the
+		 * fix to send params over QMI, this can be removed.
+		 */
+		if (plat_priv->hang_event_data_len) {
+			offset = plat_priv->hang_data_addr_offset;
+			length = plat_priv->hang_event_data_len;
+		} else {
+			offset = HSP_HANG_DATA_OFFSET;
+			length = HANG_DATA_LENGTH;
+		}
 		break;
 	default:
 		cnss_pr_err("Skip Hang Event Data as unsupported Device ID received: %d\n",
@@ -5344,15 +5356,19 @@ static void cnss_pci_send_hang_event(struct cnss_pci_data *pci_priv)
 	for (i = 0; i < plat_priv->fw_mem_seg_len; i++) {
 		if (fw_mem[i].type == QMI_WLFW_MEM_TYPE_DDR_V01 &&
 		    fw_mem[i].va) {
+			/* The offset must be < (fw_mem size- hangdata length) */
+			if (!(offset <= fw_mem[i].size - length))
+				goto exit;
+
 			hang_data_va = fw_mem[i].va + offset;
 			hang_event.hang_event_data = kmemdup(hang_data_va,
-							     HANG_DATA_LENGTH,
+							     length,
 							     GFP_ATOMIC);
 			if (!hang_event.hang_event_data) {
 				cnss_pr_dbg("Hang data memory alloc failed\n");
 				return;
 			}
-			hang_event.hang_event_data_len = HANG_DATA_LENGTH;
+			hang_event.hang_event_data_len = length;
 			break;
 		}
 	}
@@ -5361,6 +5377,11 @@ static void cnss_pci_send_hang_event(struct cnss_pci_data *pci_priv)
 
 	kfree(hang_event.hang_event_data);
 	hang_event.hang_event_data = NULL;
+	return;
+exit:
+	cnss_pr_dbg("Invalid hang event params, offset:0x%x, length:0x%x\n",
+		    plat_priv->hang_data_addr_offset,
+		    plat_priv->hang_event_data_len);
 }
 
 void cnss_pci_collect_dump_info(struct cnss_pci_data *pci_priv, bool in_panic)

+ 16 - 1
cnss2/qmi.c

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/module.h>
@@ -516,6 +516,18 @@ int cnss_wlfw_tgt_cap_send_sync(struct cnss_plat_data *plat_priv)
 		plat_priv->fw_pcie_gen_switch =
 			!!(resp->fw_caps & QMI_WLFW_HOST_PCIE_GEN_SWITCH_V01);
 
+	if (resp->hang_data_length_valid &&
+	    resp->hang_data_length &&
+	    resp->hang_data_length <= WLFW_MAX_HANG_EVENT_DATA_SIZE)
+		plat_priv->hang_event_data_len = resp->hang_data_length;
+	else
+		plat_priv->hang_event_data_len = 0;
+
+	if (resp->hang_data_addr_offset_valid)
+		plat_priv->hang_data_addr_offset = resp->hang_data_addr_offset;
+	else
+		plat_priv->hang_data_addr_offset = 0;
+
 	cnss_pr_dbg("Target capability: chip_id: 0x%x, chip_family: 0x%x, board_id: 0x%x, soc_id: 0x%x, otp_version: 0x%x\n",
 		    plat_priv->chip_info.chip_id,
 		    plat_priv->chip_info.chip_family,
@@ -525,6 +537,9 @@ int cnss_wlfw_tgt_cap_send_sync(struct cnss_plat_data *plat_priv)
 		    plat_priv->fw_version_info.fw_version,
 		    plat_priv->fw_version_info.fw_build_timestamp,
 		    plat_priv->fw_build_id);
+	cnss_pr_dbg("Hang event params, Length: 0x%x, Offset Address: 0x%x\n",
+		    plat_priv->hang_event_data_len,
+		    plat_priv->hang_data_addr_offset);
 
 	kfree(req);
 	kfree(resp);