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

qcacmn: Enhance hang info feature

Add bus related info in hif layer in order to get bus status
when hang issue happened.

Change-Id: If922e0892e0f65de778b9696bbc56fc63c25c169
CRs-Fixed: 2801350
Kai Liu 4 жил өмнө
parent
commit
4be28ba641

+ 3 - 0
hif/src/ce/ce_main.c

@@ -4486,6 +4486,9 @@ void hif_log_ce_info(struct hif_softc *scn, uint8_t *data,
 	size = sizeof(info) -
 	size = sizeof(info) -
 		(CE_COUNT_MAX - info.ce_count) * sizeof(struct ce_index);
 		(CE_COUNT_MAX - info.ce_count) * sizeof(struct ce_index);
 
 
+	if (*offset + size > QDF_WLAN_HANG_FW_OFFSET)
+		return;
+
 	QDF_HANG_EVT_SET_HDR(&info.tlv_header, HANG_EVT_TAG_CE_INFO,
 	QDF_HANG_EVT_SET_HDR(&info.tlv_header, HANG_EVT_TAG_CE_INFO,
 			     size - QDF_HANG_EVENT_TLV_HDR_SIZE);
 			     size - QDF_HANG_EVENT_TLV_HDR_SIZE);
 
 

+ 13 - 0
hif/src/dispatcher/dummy.c

@@ -387,3 +387,16 @@ int hif_dummy_config_irq_by_ceid(struct hif_softc *scn, int ce_id)
 {
 {
 	return 0;
 	return 0;
 }
 }
+
+/**
+ * hif_dummy_log_bus_info - dummy call
+ * @scn: hif context
+ * @data: hang event data buffer
+ * @offset: offset at which data needs to be written
+ *
+ * Return: None
+ */
+void hif_dummy_log_bus_info(struct hif_softc *scn, uint8_t *data,
+			    unsigned int *offset)
+{
+}

+ 2 - 0
hif/src/dispatcher/dummy.h

@@ -61,3 +61,5 @@ int hif_dummy_map_ce_to_irq(struct hif_softc *scn, int ce_id);
 int hif_dummy_addr_in_boundary(struct hif_softc *scn, uint32_t offset);
 int hif_dummy_addr_in_boundary(struct hif_softc *scn, uint32_t offset);
 void hif_dummy_config_irq_affinity(struct hif_softc *scn);
 void hif_dummy_config_irq_affinity(struct hif_softc *scn);
 int hif_dummy_config_irq_by_ceid(struct hif_softc *scn, int ce_id);
 int hif_dummy_config_irq_by_ceid(struct hif_softc *scn, int ce_id);
+void hif_dummy_log_bus_info(struct hif_softc *scn, uint8_t *data,
+			    unsigned int *offset);

+ 9 - 0
hif/src/dispatcher/multibus.c

@@ -574,3 +574,12 @@ int hif_config_irq_by_ceid(struct hif_softc *hif_sc, int ce_id)
 {
 {
 	return hif_sc->bus_ops.hif_config_irq_by_ceid(hif_sc, ce_id);
 	return hif_sc->bus_ops.hif_config_irq_by_ceid(hif_sc, ce_id);
 }
 }
+
+#ifdef HIF_BUS_LOG_INFO
+void hif_log_bus_info(struct hif_softc *hif_sc, uint8_t *data,
+		      unsigned int *offset)
+{
+	if (hif_sc->bus_ops.hif_log_bus_info)
+		hif_sc->bus_ops.hif_log_bus_info(hif_sc, data, offset);
+}
+#endif

+ 21 - 0
hif/src/dispatcher/multibus.h

@@ -87,6 +87,8 @@ struct hif_bus_ops {
 	bool (*hif_needs_bmi)(struct hif_softc *hif_sc);
 	bool (*hif_needs_bmi)(struct hif_softc *hif_sc);
 	void (*hif_config_irq_affinity)(struct hif_softc *hif_sc);
 	void (*hif_config_irq_affinity)(struct hif_softc *hif_sc);
 	int (*hif_config_irq_by_ceid)(struct hif_softc *hif_sc, int ce_id);
 	int (*hif_config_irq_by_ceid)(struct hif_softc *hif_sc, int ce_id);
+	void (*hif_log_bus_info)(struct hif_softc *scn, uint8_t *data,
+				 unsigned int *offset);
 };
 };
 
 
 #ifdef HIF_SNOC
 #ifdef HIF_SNOC
@@ -264,4 +266,23 @@ void hif_config_irq_affinity(struct hif_softc *hif_sc);
  * Return: 0 on success, negative value on error.
  * Return: 0 on success, negative value on error.
  */
  */
 int hif_config_irq_by_ceid(struct hif_softc *hif_sc, int ce_id);
 int hif_config_irq_by_ceid(struct hif_softc *hif_sc, int ce_id);
+
+#ifdef HIF_BUS_LOG_INFO
+/**
+ * hif_log_bus_info() - API to log bus related info
+ * @scn: hif handle
+ * @data: hang event data buffer
+ * @offset: offset at which data needs to be written
+ *
+ * Return:  None
+ */
+void hif_log_bus_info(struct hif_softc *scn, uint8_t *data,
+		      unsigned int *offset);
+#else
+static inline
+void hif_log_bus_info(struct hif_softc *scn, uint8_t *data,
+		      unsigned int *offset)
+{
+}
+#endif
 #endif /* _MULTIBUS_H_ */
 #endif /* _MULTIBUS_H_ */

+ 2 - 0
hif/src/dispatcher/multibus_ahb.c

@@ -74,6 +74,8 @@ QDF_STATUS hif_initialize_ahb_ops(struct hif_bus_ops *bus_ops)
 	bus_ops->hif_config_irq_affinity =
 	bus_ops->hif_config_irq_affinity =
 		&hif_dummy_config_irq_affinity;
 		&hif_dummy_config_irq_affinity;
 	bus_ops->hif_config_irq_by_ceid = &hif_ahb_configure_irq_by_ceid;
 	bus_ops->hif_config_irq_by_ceid = &hif_ahb_configure_irq_by_ceid;
+	bus_ops->hif_log_bus_info = &hif_dummy_log_bus_info;
+
 	return QDF_STATUS_SUCCESS;
 	return QDF_STATUS_SUCCESS;
 }
 }
 
 

+ 1 - 0
hif/src/dispatcher/multibus_ipci.c

@@ -78,6 +78,7 @@ QDF_STATUS hif_initialize_ipci_ops(struct hif_softc *hif_sc)
 	bus_ops->hif_config_irq_affinity =
 	bus_ops->hif_config_irq_affinity =
 		&hif_dummy_config_irq_affinity;
 		&hif_dummy_config_irq_affinity;
 	bus_ops->hif_config_irq_by_ceid = &hif_dummy_config_irq_by_ceid;
 	bus_ops->hif_config_irq_by_ceid = &hif_dummy_config_irq_by_ceid;
+	bus_ops->hif_log_bus_info = &hif_dummy_log_bus_info;
 
 
 	return QDF_STATUS_SUCCESS;
 	return QDF_STATUS_SUCCESS;
 }
 }

+ 2 - 0
hif/src/dispatcher/multibus_pci.c

@@ -92,6 +92,8 @@ QDF_STATUS hif_initialize_pci_ops(struct hif_softc *hif_sc)
 	bus_ops->hif_config_irq_affinity =
 	bus_ops->hif_config_irq_affinity =
 		&hif_pci_config_irq_affinity;
 		&hif_pci_config_irq_affinity;
 	bus_ops->hif_config_irq_by_ceid = &hif_ce_msi_configure_irq_by_ceid;
 	bus_ops->hif_config_irq_by_ceid = &hif_ce_msi_configure_irq_by_ceid;
+	bus_ops->hif_log_bus_info = &hif_log_pcie_info;
+
 	return QDF_STATUS_SUCCESS;
 	return QDF_STATUS_SUCCESS;
 }
 }
 
 

+ 2 - 1
hif/src/dispatcher/multibus_sdio.c

@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved.
  *
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
  * any purpose with or without fee is hereby granted, provided that the
@@ -66,6 +66,7 @@ QDF_STATUS hif_initialize_sdio_ops(struct hif_softc *hif_sc)
 		&hif_dummy_disable_power_management;
 		&hif_dummy_disable_power_management;
 	bus_ops->hif_addr_in_boundary = &hif_dummy_addr_in_boundary;
 	bus_ops->hif_addr_in_boundary = &hif_dummy_addr_in_boundary;
 	bus_ops->hif_needs_bmi = &hif_sdio_needs_bmi;
 	bus_ops->hif_needs_bmi = &hif_sdio_needs_bmi;
+	bus_ops->hif_log_bus_info = &hif_dummy_log_bus_info;
 
 
 	return QDF_STATUS_SUCCESS;
 	return QDF_STATUS_SUCCESS;
 }
 }

+ 1 - 0
hif/src/dispatcher/multibus_snoc.c

@@ -77,6 +77,7 @@ QDF_STATUS hif_initialize_snoc_ops(struct hif_bus_ops *bus_ops)
 	bus_ops->hif_needs_bmi = &hif_snoc_needs_bmi;
 	bus_ops->hif_needs_bmi = &hif_snoc_needs_bmi;
 	bus_ops->hif_config_irq_affinity = &hif_dummy_config_irq_affinity;
 	bus_ops->hif_config_irq_affinity = &hif_dummy_config_irq_affinity;
 	bus_ops->hif_config_irq_by_ceid = &hif_dummy_config_irq_by_ceid;
 	bus_ops->hif_config_irq_by_ceid = &hif_dummy_config_irq_by_ceid;
+	bus_ops->hif_log_bus_info = &hif_dummy_log_bus_info;
 
 
 	return QDF_STATUS_SUCCESS;
 	return QDF_STATUS_SUCCESS;
 }
 }

+ 2 - 1
hif/src/dispatcher/multibus_usb.c

@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018,2020 The Linux Foundation. All rights reserved.
  *
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
  * any purpose with or without fee is hereby granted, provided that the
@@ -67,6 +67,7 @@ QDF_STATUS hif_initialize_usb_ops(struct hif_bus_ops *bus_ops)
 	bus_ops->hif_bus_reset_resume = &hif_usb_bus_reset_resume;
 	bus_ops->hif_bus_reset_resume = &hif_usb_bus_reset_resume;
 	bus_ops->hif_map_ce_to_irq = &hif_dummy_map_ce_to_irq;
 	bus_ops->hif_map_ce_to_irq = &hif_dummy_map_ce_to_irq;
 	bus_ops->hif_needs_bmi = &hif_usb_needs_bmi;
 	bus_ops->hif_needs_bmi = &hif_usb_needs_bmi;
+	bus_ops->hif_log_bus_info = &hif_dummy_log_bus_info;
 
 
 	return QDF_STATUS_SUCCESS;
 	return QDF_STATUS_SUCCESS;
 }
 }

+ 3 - 1
hif/src/hif_main.c

@@ -466,7 +466,7 @@ void hif_get_cfg_from_psoc(struct hif_softc *scn,
 }
 }
 #endif /* WLAN_CE_INTERRUPT_THRESHOLD_CONFIG */
 #endif /* WLAN_CE_INTERRUPT_THRESHOLD_CONFIG */
 
 
-#ifdef HIF_CE_LOG_INFO
+#if defined(HIF_CE_LOG_INFO) || defined(HIF_BUS_LOG_INFO)
 /**
 /**
  * hif_recovery_notifier_cb - Recovery notifier callback to log
  * hif_recovery_notifier_cb - Recovery notifier callback to log
  *  hang event data
  *  hang event data
@@ -493,6 +493,8 @@ int hif_recovery_notifier_cb(struct notifier_block *block, unsigned long state,
 	if (!hif_handle)
 	if (!hif_handle)
 		return -EINVAL;
 		return -EINVAL;
 
 
+	hif_log_bus_info(hif_handle, notif_data->hang_data,
+			 &notif_data->offset);
 	hif_log_ce_info(hif_handle, notif_data->hang_data,
 	hif_log_ce_info(hif_handle, notif_data->hang_data,
 			&notif_data->offset);
 			&notif_data->offset);
 
 

+ 28 - 0
hif/src/pcie/if_pci.c

@@ -54,6 +54,7 @@
 #include "pci_api.h"
 #include "pci_api.h"
 #include "ahb_api.h"
 #include "ahb_api.h"
 #include "wlan_cfg.h"
 #include "wlan_cfg.h"
+#include "qdf_hang_event_notifier.h"
 
 
 /* Maximum ms timeout for host to wake up target */
 /* Maximum ms timeout for host to wake up target */
 #define PCIE_WAKE_TIMEOUT 1000
 #define PCIE_WAKE_TIMEOUT 1000
@@ -2338,6 +2339,33 @@ static int __hif_check_link_status(struct hif_softc *scn)
 	return -EACCES;
 	return -EACCES;
 }
 }
 
 
+#ifdef HIF_BUS_LOG_INFO
+void hif_log_pcie_info(struct hif_softc *scn, uint8_t *data,
+		       unsigned int *offset)
+{
+	struct hif_pci_softc *sc = HIF_GET_PCI_SOFTC(scn);
+	struct hang_event_bus_info info = {0};
+	size_t size;
+
+	if (!sc) {
+		hif_err("HIF Bus Context is Invalid");
+		return;
+	}
+
+	pfrm_read_config_word(sc->pdev, PCI_DEVICE_ID, &info.dev_id);
+
+	size = sizeof(info);
+	QDF_HANG_EVT_SET_HDR(&info.tlv_header, HANG_EVT_TAG_BUS_INFO,
+			     size - QDF_HANG_EVENT_TLV_HDR_SIZE);
+
+	if (*offset + size > QDF_WLAN_HANG_FW_OFFSET)
+		return;
+
+	qdf_mem_copy(data + *offset, &info, size);
+	*offset = *offset + size;
+}
+#endif
+
 /**
 /**
  * hif_pci_bus_resume(): prepare hif for resume
  * hif_pci_bus_resume(): prepare hif for resume
  *
  *

+ 15 - 0
hif/src/pcie/if_pci.h

@@ -57,6 +57,11 @@ struct hif_tasklet_entry {
 	void *hif_handler; /* struct hif_pci_softc */
 	void *hif_handler; /* struct hif_pci_softc */
 };
 };
 
 
+struct hang_event_bus_info {
+	uint16_t tlv_header;
+	uint16_t dev_id;
+} qdf_packed;
+
 /**
 /**
  * struct hif_msi_info - Structure to hold msi info
  * struct hif_msi_info - Structure to hold msi info
  * @magic: cookie
  * @magic: cookie
@@ -190,4 +195,14 @@ void hif_print_pci_stats(struct hif_pci_softc *pci_scn)
 {
 {
 }
 }
 #endif /* FORCE_WAKE */
 #endif /* FORCE_WAKE */
+#ifdef HIF_BUS_LOG_INFO
+void hif_log_pcie_info(struct hif_softc *scn, uint8_t *data,
+		       unsigned int *offset);
+#else
+static inline
+void hif_log_pcie_info(struct hif_softc *scn, uint8_t *data,
+		       unsigned int *offset)
+{
+}
+#endif
 #endif /* __ATH_PCI_H__ */
 #endif /* __ATH_PCI_H__ */

+ 4 - 3
htc/htc_credit_history.c

@@ -163,9 +163,6 @@ void htc_log_hang_credit_history(struct notifier_block *block, void *data)
 	if (!htc_hang_data)
 	if (!htc_hang_data)
 		return;
 		return;
 
 
-	if (htc_hang_data->offset >= QDF_WLAN_MAX_HOST_OFFSET)
-		return;
-
 	total_len = sizeof(struct htc_hang_data_fixed_param);
 	total_len = sizeof(struct htc_hang_data_fixed_param);
 	qdf_spin_lock_bh(&g_htc_credit_lock);
 	qdf_spin_lock_bh(&g_htc_credit_lock);
 
 
@@ -184,6 +181,10 @@ void htc_log_hang_credit_history(struct notifier_block *block, void *data)
 						&htc_credit_history_buffer[idx];
 						&htc_credit_history_buffer[idx];
 		htc_buf_ptr = htc_hang_data->hang_data + htc_hang_data->offset;
 		htc_buf_ptr = htc_hang_data->hang_data + htc_hang_data->offset;
 		cmd = (struct htc_hang_data_fixed_param *)htc_buf_ptr;
 		cmd = (struct htc_hang_data_fixed_param *)htc_buf_ptr;
+
+		if (htc_hang_data->offset + total_len > QDF_WLAN_HANG_FW_OFFSET)
+			return;
+
 		QDF_HANG_EVT_SET_HDR(&cmd->tlv_header,
 		QDF_HANG_EVT_SET_HDR(&cmd->tlv_header,
 				     HANG_EVT_TAG_HTC_CREDIT_HIST,
 				     HANG_EVT_TAG_HTC_CREDIT_HIST,
 		QDF_HANG_GET_STRUCT_TLVLEN(struct htc_hang_data_fixed_param));
 		QDF_HANG_GET_STRUCT_TLVLEN(struct htc_hang_data_fixed_param));

+ 4 - 2
qdf/inc/qdf_hang_event_notifier.h

@@ -43,6 +43,7 @@
  * @HANG_EVT_TAG_WMI_CMD_HIST: HTC event tag wmi command history hang event tag
  * @HANG_EVT_TAG_WMI_CMD_HIST: HTC event tag wmi command history hang event tag
  * @HANG_EVT_TAG_DP_PEER_INFO: DP peer info hang event tag
  * @HANG_EVT_TAG_DP_PEER_INFO: DP peer info hang event tag
  * @HANG_EVT_TAG_CE_INFO: Copy Engine hang event tag
  * @HANG_EVT_TAG_CE_INFO: Copy Engine hang event tag
+ * @HANG_EVT_TAG_BUS_INFO: Bus hang event tag
  */
  */
 enum hang_event_tag {
 enum hang_event_tag {
 	HANG_EVT_TAG_CDS,
 	HANG_EVT_TAG_CDS,
@@ -53,10 +54,11 @@ enum hang_event_tag {
 	HANG_EVT_TAG_WMI_CMD_HIST,
 	HANG_EVT_TAG_WMI_CMD_HIST,
 	HANG_EVT_TAG_HTC_CREDIT_HIST,
 	HANG_EVT_TAG_HTC_CREDIT_HIST,
 	HANG_EVT_TAG_DP_PEER_INFO,
 	HANG_EVT_TAG_DP_PEER_INFO,
-	HANG_EVT_TAG_CE_INFO
+	HANG_EVT_TAG_CE_INFO,
+	HANG_EVT_TAG_BUS_INFO
 };
 };
 
 
-#define QDF_HANG_EVENT_TLV_HDR_SIZE   (sizeof(uint32_t))
+#define QDF_HANG_EVENT_TLV_HDR_SIZE   (sizeof(uint16_t))
 
 
 #define QDF_HANG_EVT_SET_HDR(tlv_buf, tag, len) \
 #define QDF_HANG_EVT_SET_HDR(tlv_buf, tag, len) \
 	(((uint16_t *)(tlv_buf))[0]) = (((tag) << 8) | ((len) & 0x000000FF))
 	(((uint16_t *)(tlv_buf))[0]) = (((tag) << 8) | ((len) & 0x000000FF))

+ 2 - 0
qdf/inc/qdf_types.h

@@ -1345,6 +1345,7 @@ enum qdf_suspend_type {
  * @QDF_VDEV_PEER_DELETE_ALL_RESPONSE_TIMED_OUT: Peer delete all resp timeout
  * @QDF_VDEV_PEER_DELETE_ALL_RESPONSE_TIMED_OUT: Peer delete all resp timeout
  * @QDF_WMI_BUF_SEQUENCE_MISMATCH: WMI Tx completion buffer sequence mismatch
  * @QDF_WMI_BUF_SEQUENCE_MISMATCH: WMI Tx completion buffer sequence mismatch
  * @QDF_HAL_REG_WRITE_FAILURE: HAL register writing failures
  * @QDF_HAL_REG_WRITE_FAILURE: HAL register writing failures
+ * @QDF_SUSPEND_NO_CREDIT: host lack of credit after suspend
  */
  */
 enum qdf_hang_reason {
 enum qdf_hang_reason {
 	QDF_REASON_UNSPECIFIED,
 	QDF_REASON_UNSPECIFIED,
@@ -1369,6 +1370,7 @@ enum qdf_hang_reason {
 	QDF_VDEV_PEER_DELETE_ALL_RESPONSE_TIMED_OUT,
 	QDF_VDEV_PEER_DELETE_ALL_RESPONSE_TIMED_OUT,
 	QDF_WMI_BUF_SEQUENCE_MISMATCH,
 	QDF_WMI_BUF_SEQUENCE_MISMATCH,
 	QDF_HAL_REG_WRITE_FAILURE,
 	QDF_HAL_REG_WRITE_FAILURE,
+	QDF_SUSPEND_NO_CREDIT,
 };
 };
 
 
 /**
 /**

+ 3 - 3
wmi/src/wmi_hang_event.c

@@ -53,9 +53,6 @@ static void wmi_log_history(struct notifier_block *block, void *data,
 	if (!wmi_handle)
 	if (!wmi_handle)
 		return;
 		return;
 
 
-	if (wmi_hang_data->offset >= QDF_WLAN_MAX_HOST_OFFSET)
-		return;
-
 	if (wmi_history)
 	if (wmi_history)
 		wmi_log = &wmi_handle->log_info.wmi_event_log_buf_info;
 		wmi_log = &wmi_handle->log_info.wmi_event_log_buf_info;
 	else
 	else
@@ -75,6 +72,9 @@ static void wmi_log_history(struct notifier_block *block, void *data,
 		pos = *wmi_log->p_buf_tail_idx - 1;
 		pos = *wmi_log->p_buf_tail_idx - 1;
 
 
 	while (nread--) {
 	while (nread--) {
+		if (wmi_hang_data->offset + total_len > QDF_WLAN_HANG_FW_OFFSET)
+			return;
+
 		switch (wmi_history) {
 		switch (wmi_history) {
 		case WMI_EVT_HIST:
 		case WMI_EVT_HIST:
 			wmi_buf_ptr = (wmi_hang_data->hang_data +
 			wmi_buf_ptr = (wmi_hang_data->hang_data +