diff --git a/Kbuild b/Kbuild index ca766442c3..8c2171e030 100644 --- a/Kbuild +++ b/Kbuild @@ -60,6 +60,10 @@ ifeq ($(CONFIG_DISABLE_CNSS_SRAM_DUMP),y) KBUILD_CPPFLAGS += -DCONFIG_DISABLE_CNSS_SRAM_DUMP endif +ifeq ($(CONFIG_CNSS2_SMMU_DB_SUPPORT),y) +KBUILD_CPPFLAGS += -DCONFIG_CNSS2_SMMU_DB_SUPPORT +endif + obj-$(CONFIG_CNSS2) += cnss2/ obj-$(CONFIG_ICNSS2) += icnss2/ obj-$(CONFIG_CNSS_GENL) += cnss_genl/ diff --git a/cnss2/Kconfig b/cnss2/Kconfig index 09e2b36c0b..cb0157e396 100644 --- a/cnss2/Kconfig +++ b/cnss2/Kconfig @@ -126,3 +126,12 @@ config DISABLE_CNSS_SRAM_DUMP If enabled, CNSS plafrom driver will not dump sram when MHI power on timeout for CNSS QCA6490 chipset only. Since this feature about sram dump costs 4M memory. + +config CNSS2_SMMU_DB_SUPPORT + bool "Enable early trace stop support" + depends on CNSS2 + help + If enabled, CNSS platform driver will notify wlan fw to stop + traces by ringing MHI host doorbell register. This feature helps + to get traces which contain smmu fault address and enables + debugging. diff --git a/cnss2/pci.c b/cnss2/pci.c index 412063466a..daae59e780 100644 --- a/cnss2/pci.c +++ b/cnss2/pci.c @@ -819,6 +819,13 @@ static int cnss_mhi_device_get_sync_atomic(struct cnss_pci_data *pci_priv, timeout_us, in_panic); } +#ifdef CONFIG_CNSS2_SMMU_DB_SUPPORT +static int cnss_mhi_host_notify_db_disable_trace(struct cnss_pci_data *pci_priv) +{ + return mhi_host_notify_db_disable_trace(pci_priv->mhi_ctrl); +} +#endif + static void cnss_mhi_controller_set_bw_scale_cb(struct cnss_pci_data *pci_priv, int (*cb)(struct mhi_controller *mhi_ctrl, @@ -875,6 +882,13 @@ static int cnss_mhi_device_get_sync_atomic(struct cnss_pci_data *pci_priv, return -EOPNOTSUPP; } +#ifdef CONFIG_CNSS2_SMMU_DB_SUPPORT +static int cnss_mhi_host_notify_db_disable_trace(struct cnss_pci_data *pci_priv) +{ + return -EOPNOTSUPP; +} +#endif + static void cnss_mhi_controller_set_bw_scale_cb(struct cnss_pci_data *pci_priv, int (*cb)(struct mhi_controller *mhi_ctrl, @@ -893,6 +907,37 @@ void cnss_mhi_controller_set_base(struct cnss_pci_data *pci_priv, } #endif /* CONFIG_MHI_BUS_MISC */ +#ifdef CONFIG_CNSS2_SMMU_DB_SUPPORT +#define CNSS_MHI_WAKE_TIMEOUT 500000 +static void cnss_pci_smmu_fault_handler_irq(struct iommu_domain *domain, + void *handler_token) +{ + struct cnss_pci_data *pci_priv = handler_token; + int ret = 0; + + ret = cnss_mhi_device_get_sync_atomic(pci_priv, + CNSS_MHI_WAKE_TIMEOUT, true); + if (ret < 0) { + cnss_pr_err("Failed to bring mhi in M0 state, ret %d\n", ret); + return; + } + + ret = cnss_mhi_host_notify_db_disable_trace(pci_priv); + if (ret < 0) + cnss_pr_err("Fail to notify wlan fw to stop trace collection, ret %d\n", ret); +} + +void cnss_register_iommu_fault_handler_irq(struct cnss_pci_data *pci_priv) +{ + qcom_iommu_set_fault_handler_irq(pci_priv->iommu_domain, + cnss_pci_smmu_fault_handler_irq, pci_priv); +} +#else +void cnss_register_iommu_fault_handler_irq(struct cnss_pci_data *pci_priv) +{ +} +#endif + int cnss_pci_check_link_status(struct cnss_pci_data *pci_priv) { u16 device_id; diff --git a/cnss2/pci.h b/cnss2/pci.h index 119aa25a44..101ff03aec 100644 --- a/cnss2/pci.h +++ b/cnss2/pci.h @@ -9,6 +9,7 @@ #include #include +#include #include #if IS_ENABLED(CONFIG_MHI_BUS_MISC) #include @@ -313,4 +314,5 @@ int cnss_pci_get_user_msi_assignment(struct cnss_pci_data *pci_priv, int *num_vectors, u32 *user_base_data, u32 *base_vector); +void cnss_register_iommu_fault_handler_irq(struct cnss_pci_data *pci_priv); #endif /* _CNSS_PCI_H */ diff --git a/cnss2/pci_qcom.c b/cnss2/pci_qcom.c index 70106dc846..42e323afb0 100644 --- a/cnss2/pci_qcom.c +++ b/cnss2/pci_qcom.c @@ -579,6 +579,7 @@ int cnss_pci_init_smmu(struct cnss_pci_data *pci_priv) pci_priv->smmu_s1_enable = true; iommu_set_fault_handler(pci_priv->iommu_domain, cnss_pci_smmu_fault_handler, pci_priv); + cnss_register_iommu_fault_handler_irq(pci_priv); } ret = of_property_read_u32_array(of_node, "qcom,iommu-dma-addr-pool",