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
This commit is contained in:
Kai Liu
2020-10-20 22:22:39 +08:00
committed by snandini
parent 43b866f124
commit 4be28ba641
18 changed files with 117 additions and 11 deletions

View File

@@ -4486,6 +4486,9 @@ void hif_log_ce_info(struct hif_softc *scn, uint8_t *data,
size = sizeof(info) -
(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,
size - QDF_HANG_EVENT_TLV_HDR_SIZE);

View File

@@ -387,3 +387,16 @@ int hif_dummy_config_irq_by_ceid(struct hif_softc *scn, int ce_id)
{
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)
{
}

View File

@@ -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);
void hif_dummy_config_irq_affinity(struct hif_softc *scn);
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);

View File

@@ -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);
}
#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

View File

@@ -87,6 +87,8 @@ struct hif_bus_ops {
bool (*hif_needs_bmi)(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);
void (*hif_log_bus_info)(struct hif_softc *scn, uint8_t *data,
unsigned int *offset);
};
#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.
*/
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_ */

View File

@@ -74,6 +74,8 @@ QDF_STATUS hif_initialize_ahb_ops(struct hif_bus_ops *bus_ops)
bus_ops->hif_config_irq_affinity =
&hif_dummy_config_irq_affinity;
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;
}

View File

@@ -78,6 +78,7 @@ QDF_STATUS hif_initialize_ipci_ops(struct hif_softc *hif_sc)
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_log_bus_info = &hif_dummy_log_bus_info;
return QDF_STATUS_SUCCESS;
}

View File

@@ -92,6 +92,8 @@ QDF_STATUS hif_initialize_pci_ops(struct hif_softc *hif_sc)
bus_ops->hif_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_log_bus_info = &hif_log_pcie_info;
return QDF_STATUS_SUCCESS;
}

View File

@@ -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
* 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;
bus_ops->hif_addr_in_boundary = &hif_dummy_addr_in_boundary;
bus_ops->hif_needs_bmi = &hif_sdio_needs_bmi;
bus_ops->hif_log_bus_info = &hif_dummy_log_bus_info;
return QDF_STATUS_SUCCESS;
}

View File

@@ -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_config_irq_affinity = &hif_dummy_config_irq_affinity;
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;
}

View File

@@ -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
* 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_map_ce_to_irq = &hif_dummy_map_ce_to_irq;
bus_ops->hif_needs_bmi = &hif_usb_needs_bmi;
bus_ops->hif_log_bus_info = &hif_dummy_log_bus_info;
return QDF_STATUS_SUCCESS;
}

View File

@@ -466,7 +466,7 @@ void hif_get_cfg_from_psoc(struct hif_softc *scn,
}
#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
* hang event data
@@ -493,6 +493,8 @@ int hif_recovery_notifier_cb(struct notifier_block *block, unsigned long state,
if (!hif_handle)
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,
&notif_data->offset);

View File

@@ -54,6 +54,7 @@
#include "pci_api.h"
#include "ahb_api.h"
#include "wlan_cfg.h"
#include "qdf_hang_event_notifier.h"
/* Maximum ms timeout for host to wake up target */
#define PCIE_WAKE_TIMEOUT 1000
@@ -2338,6 +2339,33 @@ static int __hif_check_link_status(struct hif_softc *scn)
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
*

View File

@@ -57,6 +57,11 @@ struct hif_tasklet_entry {
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
* @magic: cookie
@@ -190,4 +195,14 @@ void hif_print_pci_stats(struct hif_pci_softc *pci_scn)
{
}
#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__ */

View File

@@ -163,9 +163,6 @@ void htc_log_hang_credit_history(struct notifier_block *block, void *data)
if (!htc_hang_data)
return;
if (htc_hang_data->offset >= QDF_WLAN_MAX_HOST_OFFSET)
return;
total_len = sizeof(struct htc_hang_data_fixed_param);
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_buf_ptr = htc_hang_data->hang_data + htc_hang_data->offset;
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,
HANG_EVT_TAG_HTC_CREDIT_HIST,
QDF_HANG_GET_STRUCT_TLVLEN(struct htc_hang_data_fixed_param));

View File

@@ -43,6 +43,7 @@
* @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_CE_INFO: Copy Engine hang event tag
* @HANG_EVT_TAG_BUS_INFO: Bus hang event tag
*/
enum hang_event_tag {
HANG_EVT_TAG_CDS,
@@ -53,10 +54,11 @@ enum hang_event_tag {
HANG_EVT_TAG_WMI_CMD_HIST,
HANG_EVT_TAG_HTC_CREDIT_HIST,
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) \
(((uint16_t *)(tlv_buf))[0]) = (((tag) << 8) | ((len) & 0x000000FF))

View File

@@ -1345,6 +1345,7 @@ enum qdf_suspend_type {
* @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_HAL_REG_WRITE_FAILURE: HAL register writing failures
* @QDF_SUSPEND_NO_CREDIT: host lack of credit after suspend
*/
enum qdf_hang_reason {
QDF_REASON_UNSPECIFIED,
@@ -1369,6 +1370,7 @@ enum qdf_hang_reason {
QDF_VDEV_PEER_DELETE_ALL_RESPONSE_TIMED_OUT,
QDF_WMI_BUF_SEQUENCE_MISMATCH,
QDF_HAL_REG_WRITE_FAILURE,
QDF_SUSPEND_NO_CREDIT,
};
/**

View File

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