diff --git a/cnss2/debug.c b/cnss2/debug.c index cb7560e850..4598181a42 100644 --- a/cnss2/debug.c +++ b/cnss2/debug.c @@ -914,6 +914,39 @@ static const struct file_operations cnss_dynamic_feature_fops = { .llseek = seq_lseek, }; +static int cnss_smmu_fault_timestamp_show(struct seq_file *s, void *data) +{ + struct cnss_plat_data *plat_priv = s->private; + struct cnss_pci_data *pci_priv = plat_priv->bus_priv; + + if (!pci_priv) + return -ENODEV; + + seq_printf(s, "smmu irq cb entry timestamp : %llu ns\n", + pci_priv->smmu_fault_timestamp[SMMU_CB_ENTRY]); + seq_printf(s, "smmu irq cb before doorbell ring timestamp : %llu ns\n", + pci_priv->smmu_fault_timestamp[SMMU_CB_DOORBELL_RING]); + seq_printf(s, "smmu irq cb after doorbell ring timestamp : %llu ns\n", + pci_priv->smmu_fault_timestamp[SMMU_CB_EXIT]); + + return 0; +} + +static int cnss_smmu_fault_timestamp_open(struct inode *inode, + struct file *file) +{ + return single_open(file, cnss_smmu_fault_timestamp_show, + inode->i_private); +} + +static const struct file_operations cnss_smmu_fault_timestamp_fops = { + .read = seq_read, + .release = single_release, + .open = cnss_smmu_fault_timestamp_open, + .owner = THIS_MODULE, + .llseek = seq_lseek, +}; + #ifdef CONFIG_DEBUG_FS #ifdef CONFIG_CNSS2_DEBUG static int cnss_create_debug_only_node(struct cnss_plat_data *plat_priv) @@ -932,6 +965,8 @@ static int cnss_create_debug_only_node(struct cnss_plat_data *plat_priv) &cnss_control_params_debug_fops); debugfs_create_file("dynamic_feature", 0600, root_dentry, plat_priv, &cnss_dynamic_feature_fops); + debugfs_create_file("cnss_smmu_fault_timestamp", 0600, root_dentry, + plat_priv, &cnss_smmu_fault_timestamp_fops); return 0; } diff --git a/cnss2/pci.c b/cnss2/pci.c index 932817f12e..f6761cd076 100644 --- a/cnss2/pci.c +++ b/cnss2/pci.c @@ -909,12 +909,23 @@ void cnss_mhi_controller_set_base(struct cnss_pci_data *pci_priv, #ifdef CONFIG_CNSS2_SMMU_DB_SUPPORT #define CNSS_MHI_WAKE_TIMEOUT 500000 + +static void cnss_record_smmu_fault_timestamp(struct cnss_pci_data *pci_priv, + enum cnss_smmu_fault_time id) +{ + if (id >= SMMU_CB_MAX) + return; + + pci_priv->smmu_fault_timestamp[id] = sched_clock(); +} + 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; + cnss_record_smmu_fault_timestamp(pci_priv, SMMU_CB_ENTRY); ret = cnss_mhi_device_get_sync_atomic(pci_priv, CNSS_MHI_WAKE_TIMEOUT, true); if (ret < 0) { @@ -922,9 +933,12 @@ static void cnss_pci_smmu_fault_handler_irq(struct iommu_domain *domain, return; } + cnss_record_smmu_fault_timestamp(pci_priv, SMMU_CB_DOORBELL_RING); 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); + + cnss_record_smmu_fault_timestamp(pci_priv, SMMU_CB_EXIT); } void cnss_register_iommu_fault_handler_irq(struct cnss_pci_data *pci_priv) diff --git a/cnss2/pci.h b/cnss2/pci.h index 101ff03aec..7ea38898bf 100644 --- a/cnss2/pci.h +++ b/cnss2/pci.h @@ -19,6 +19,7 @@ #endif #include #include +#include #include "main.h" @@ -72,6 +73,13 @@ enum cnss_pci_reg_dev_mask { REG_MASK_PEACH, }; +enum cnss_smmu_fault_time { + SMMU_CB_ENTRY, + SMMU_CB_DOORBELL_RING, + SMMU_CB_EXIT, + SMMU_CB_MAX, +}; + struct cnss_msi_user { char *name; int num_vectors; @@ -169,6 +177,7 @@ struct cnss_pci_data { u8 iommu_geometry; bool drv_supported; bool is_smmu_fault; + unsigned long long smmu_fault_timestamp[SMMU_CB_MAX]; }; static inline void cnss_set_pci_priv(struct pci_dev *pci_dev, void *data)