Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 46c969d1 authored by Dov Levenglick's avatar Dov Levenglick
Browse files

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: default avatarDov Levenglick <dovl@codeaurora.org>
parent 3a1a7680
Loading
Loading
Loading
Loading
+41 −0
Original line number Diff line number Diff line
@@ -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;
+23 −0
Original line number Diff line number Diff line
@@ -223,6 +223,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) \
@@ -389,6 +391,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;

@@ -405,6 +410,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;

@@ -417,6 +425,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
@@ -455,6 +466,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];

@@ -488,6 +502,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);
@@ -521,6 +538,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,
@@ -8148,6 +8168,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");
+19 −0
Original line number Diff line number Diff line
@@ -294,6 +294,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
@@ -411,6 +412,20 @@ enum clk_gating_state {
	REQ_CLKS_ON,
};

/* 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_clk_gating - UFS clock gating related info
 * @gate_work: worker to turn off clocks after some delay as specified in
@@ -576,6 +591,7 @@ struct ufshcd_pm_qos {
 * @hibern8_on_idle: UFS Hibern8 on idle related data
 * @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
 */
struct ufs_hba {
	void __iomem *mmio_base;
@@ -749,6 +765,9 @@ struct ufs_hba {

	/* Number of requests aborts */
	int req_abort_count;

	/* Bitmask for enabling debug prints */
	u32 ufshcd_dbg_print;
};

/* Returns true if clocks can be gated. Otherwise false */