diff options
| author | Dov Levenglick <dovl@codeaurora.org> | 2014-12-18 09:13:44 +0200 |
|---|---|---|
| committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-22 10:58:25 -0700 |
| commit | f6786d1fec861506b3e3339cd4f6066c75cdb203 (patch) | |
| tree | 832493e9840f6fed13ab3a401c9ccdeb7ec6c2af | |
| parent | 1fd1c6a6970c8d44a0e29463e9a8d378ec9bea84 (diff) | |
scsi: ufs: add print suppressing debugfs mechanism
Provides a mechanism for the userspace to suppress specific
debug prints via the debugfs. This is useful in order to avoid
cases where too much printing would cause watchdog timers to expire.
Change-Id: I1ab068cd616ddac767ec5f30ab130e3b1ac34e15
Signed-off-by: Dov Levenglick <dovl@codeaurora.org>
[imaund@codeaurora.org: Resolved context conflicts]
Signed-off-by: Ian Maund <imaund@codeaurora.org>
[subhashj@codeaurora.org: resolved trivial merge conflicts]
Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
| -rw-r--r-- | drivers/scsi/ufs/debugfs.c | 41 | ||||
| -rw-r--r-- | drivers/scsi/ufs/ufshcd.c | 23 | ||||
| -rw-r--r-- | include/linux/scsi/ufs/ufshcd.h | 19 |
3 files changed, 83 insertions, 0 deletions
diff --git a/drivers/scsi/ufs/debugfs.c b/drivers/scsi/ufs/debugfs.c index 6b00aab43a99..fd682fbdbc30 100644 --- a/drivers/scsi/ufs/debugfs.c +++ b/drivers/scsi/ufs/debugfs.c @@ -917,6 +917,36 @@ DEFINE_SIMPLE_ATTRIBUTE(ufsdbg_dme_peer_read_ops, ufsdbg_dme_peer_set_attr_id, "%llu\n"); +static int ufsdbg_dbg_print_en_read(void *data, u64 *attr_val) +{ + struct ufs_hba *hba = data; + + if (!hba) + return -EINVAL; + + *attr_val = (u64)hba->ufshcd_dbg_print; + return 0; +} + +static int ufsdbg_dbg_print_en_set(void *data, u64 attr_id) +{ + struct ufs_hba *hba = data; + + if (!hba) + return -EINVAL; + + if (attr_id & ~UFSHCD_DBG_PRINT_ALL) + return -EINVAL; + + hba->ufshcd_dbg_print = (u32)attr_id; + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(ufsdbg_dbg_print_en_ops, + ufsdbg_dbg_print_en_read, + ufsdbg_dbg_print_en_set, + "%llu\n"); + void ufsdbg_add_debugfs(struct ufs_hba *hba) { if (!hba) { @@ -1022,6 +1052,17 @@ void ufsdbg_add_debugfs(struct ufs_hba *hba) goto err; } + hba->debugfs_files.dbg_print_en = + debugfs_create_file("dbg_print_en", S_IRUSR | S_IWUSR, + hba->debugfs_files.debugfs_root, hba, + &ufsdbg_dbg_print_en_ops); + if (!hba->debugfs_files.dbg_print_en) { + dev_err(hba->dev, + "%s: failed create dbg_print_en debugfs entry\n", + __func__); + goto err; + } + ufsdbg_setup_fault_injection(hba); return; diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index ccf1718e01c7..6945e41e864d 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -226,6 +226,8 @@ enum { UFSHCD_INT_CLEAR, }; +#define DEFAULT_UFSHCD_DBG_PRINT_EN UFSHCD_DBG_PRINT_ALL + #define ufshcd_set_eh_in_progress(h) \ (h->eh_flags |= UFSHCD_EH_IN_PROGRESS) #define ufshcd_eh_in_progress(h) \ @@ -396,6 +398,9 @@ static void ufshcd_print_clk_freqs(struct ufs_hba *hba) struct ufs_clk_info *clki; struct list_head *head = &hba->clk_list_head; + if (!(hba->ufshcd_dbg_print & UFSHCD_DBG_PRINT_CLK_FREQ_EN)) + return; + if (!head || list_empty(head)) return; @@ -412,6 +417,9 @@ static void ufshcd_print_uic_err_hist(struct ufs_hba *hba, { int i; + if (!(hba->ufshcd_dbg_print & UFSHCD_DBG_PRINT_UIC_ERR_HIST_EN)) + return; + for (i = 0; i < UIC_ERR_REG_HIST_LENGTH; i++) { int p = (i + err_hist->pos - 1) % UIC_ERR_REG_HIST_LENGTH; @@ -424,6 +432,9 @@ static void ufshcd_print_uic_err_hist(struct ufs_hba *hba, static void ufshcd_print_host_regs(struct ufs_hba *hba) { + if (!(hba->ufshcd_dbg_print & UFSHCD_DBG_PRINT_HOST_REGS_EN)) + return; + /* * hex_dump reads its data without the readl macro. This might * cause inconsistency issues on some platform, as the printed @@ -462,6 +473,9 @@ void ufshcd_print_trs(struct ufs_hba *hba, unsigned long bitmap, bool pr_prdt) int prdt_length; int tag; + if (!(hba->ufshcd_dbg_print & UFSHCD_DBG_PRINT_TRS_EN)) + return; + for_each_set_bit(tag, &bitmap, hba->nutrs) { lrbp = &hba->lrb[tag]; @@ -495,6 +509,9 @@ static void ufshcd_print_tmrs(struct ufs_hba *hba, unsigned long bitmap) struct utp_task_req_desc *tmrdp; int tag; + if (!(hba->ufshcd_dbg_print & UFSHCD_DBG_PRINT_TMRS_EN)) + return; + for_each_set_bit(tag, &bitmap, hba->nutmrs) { tmrdp = &hba->utmrdl_base_addr[tag]; dev_err(hba->dev, "TM[%d] - Task Management Header", tag); @@ -528,6 +545,9 @@ static void ufshcd_print_pwr_info(struct ufs_hba *hba) "INVALID MODE", }; + if (!(hba->ufshcd_dbg_print & UFSHCD_DBG_PRINT_PWR_EN)) + return; + dev_err(hba->dev, "%s:[RX, TX]: gear=[%d, %d], lane[%d, %d], pwr[%s, %s], rate = %d\n", __func__, hba->pwr_info.gear_rx, hba->pwr_info.gear_tx, @@ -8220,6 +8240,9 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) /* Get Interrupt bit mask per version */ hba->intr_mask = ufshcd_get_intr_mask(hba); + /* Enable debug prints */ + hba->ufshcd_dbg_print = DEFAULT_UFSHCD_DBG_PRINT_EN; + err = ufshcd_set_dma_mask(hba); if (err) { dev_err(hba->dev, "set dma mask failed\n"); diff --git a/include/linux/scsi/ufs/ufshcd.h b/include/linux/scsi/ufs/ufshcd.h index 76e08ee8c1ae..e3a5c23f39ea 100644 --- a/include/linux/scsi/ufs/ufshcd.h +++ b/include/linux/scsi/ufs/ufshcd.h @@ -486,6 +486,7 @@ struct debugfs_files { struct dentry *power_mode; struct dentry *dme_local_read; struct dentry *dme_peer_read; + struct dentry *dbg_print_en; u32 dme_local_attr_id; u32 dme_peer_attr_id; #ifdef CONFIG_UFS_FAULT_INJECTION @@ -538,6 +539,20 @@ struct ufshcd_pm_qos { bool is_suspended; }; +/* UFS Host Controller debug print bitmask */ +#define UFSHCD_DBG_PRINT_CLK_FREQ_EN UFS_BIT(0) +#define UFSHCD_DBG_PRINT_UIC_ERR_HIST_EN UFS_BIT(1) +#define UFSHCD_DBG_PRINT_HOST_REGS_EN UFS_BIT(2) +#define UFSHCD_DBG_PRINT_TRS_EN UFS_BIT(3) +#define UFSHCD_DBG_PRINT_TMRS_EN UFS_BIT(4) +#define UFSHCD_DBG_PRINT_PWR_EN UFS_BIT(5) + +#define UFSHCD_DBG_PRINT_ALL \ + (UFSHCD_DBG_PRINT_CLK_FREQ_EN | \ + UFSHCD_DBG_PRINT_UIC_ERR_HIST_EN | \ + UFSHCD_DBG_PRINT_HOST_REGS_EN | UFSHCD_DBG_PRINT_TRS_EN | \ + UFSHCD_DBG_PRINT_TMRS_EN | UFSHCD_DBG_PRINT_PWR_EN) + /** * struct ufs_hba - per adapter private structure * @mmio_base: UFSHCI base register address @@ -585,6 +600,7 @@ struct ufshcd_pm_qos { * @auto_bkops_enabled: to track whether bkops is enabled in device * @ufs_stats: ufshcd statistics to be used via debugfs * @debugfs_files: debugfs files associated with the ufs stats + * @ufshcd_dbg_print: Bitmask for enabling debug prints * @vreg_info: UFS device voltage regulator information * @clk_list_head: UFS host controller clocks list node head * @pwr_info: holds current power mode @@ -737,6 +753,9 @@ struct ufs_hba { /* Number of lanes available (1 or 2) for Rx/Tx */ u32 lanes_per_direction; + /* Bitmask for enabling debug prints */ + u32 ufshcd_dbg_print; + struct ufs_pa_layer_attr pwr_info; struct ufs_pwr_mode_info max_pwr_info; |
