diff options
author | Yaniv Gardi <ygardi@codeaurora.org> | 2015-03-31 11:50:23 +0300 |
---|---|---|
committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-22 10:59:45 -0700 |
commit | 11a3ec924ee96a2f472f3485ac915430235a2610 (patch) | |
tree | 57c8dfdc041b23c4ff12f9542eaaf4ca307c3639 /drivers/scsi/ufs | |
parent | 3f8adb02aab70723ec239d901aa5f3525dc2ee08 (diff) |
scsi: ufs: add debugfs to reset and restore the UFS controller
This change adds a debugfs capability to initiate a reset and restore
procedure to the UFS controller by executing:
echo 1 > /sys/kernel/debug/ufshcd0/reset_controller
This capability is necessary for testing purposes of the the reset
and restore procedure.
Change-Id: I126e2d80d2ac63be6107aee29fa03dce4f56e83a
Signed-off-by: Yaniv Gardi <ygardi@codeaurora.org>
Diffstat (limited to 'drivers/scsi/ufs')
-rw-r--r-- | drivers/scsi/ufs/ufs-debugfs.c | 53 | ||||
-rw-r--r-- | drivers/scsi/ufs/ufshcd.h | 1 |
2 files changed, 54 insertions, 0 deletions
diff --git a/drivers/scsi/ufs/ufs-debugfs.c b/drivers/scsi/ufs/ufs-debugfs.c index 0df02f2e03b2..9fd019c0d808 100644 --- a/drivers/scsi/ufs/ufs-debugfs.c +++ b/drivers/scsi/ufs/ufs-debugfs.c @@ -1331,6 +1331,48 @@ static const struct file_operations ufsdbg_req_stats_desc = { .write = ufsdbg_req_stats_write, }; + +static int ufsdbg_reset_controller_show(struct seq_file *file, void *data) +{ + seq_puts(file, "echo 1 > /sys/kernel/debug/.../reset_controller\n"); + seq_puts(file, "resets the UFS controller and restores its operational state\n\n"); + + return 0; +} + +static int ufsdbg_reset_controller_open(struct inode *inode, struct file *file) +{ + return single_open(file, ufsdbg_reset_controller_show, + inode->i_private); +} + +static ssize_t ufsdbg_reset_controller_write(struct file *filp, + const char __user *ubuf, size_t cnt, loff_t *ppos) +{ + struct ufs_hba *hba = filp->f_mapping->host->i_private; + unsigned long flags; + + spin_lock_irqsave(hba->host->host_lock, flags); + + /* + * simulating a dummy error in order to "convince" + * eh_work to actually reset the controller + */ + hba->saved_err |= INT_FATAL_ERRORS; + hba->silence_err_logs = true; + schedule_work(&hba->eh_work); + + spin_unlock_irqrestore(hba->host->host_lock, flags); + + return cnt; +} + +static const struct file_operations ufsdbg_reset_controller = { + .open = ufsdbg_reset_controller_open, + .read = seq_read, + .write = ufsdbg_reset_controller_write, +}; + void ufsdbg_add_debugfs(struct ufs_hba *hba) { char root_name[sizeof("ufshcd00")]; @@ -1463,6 +1505,17 @@ void ufsdbg_add_debugfs(struct ufs_hba *hba) goto err; } + hba->debugfs_files.reset_controller = + debugfs_create_file("reset_controller", S_IRUSR | S_IWUSR, + hba->debugfs_files.debugfs_root, hba, + &ufsdbg_reset_controller); + if (!hba->debugfs_files.reset_controller) { + dev_err(hba->dev, + "%s: failed create reset_controller debugfs entry", + __func__); + goto err; + } + ufsdbg_setup_fault_injection(hba); if (hba->vops && hba->vops->add_debugfs) diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 486f8d09ec90..58126491f624 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -476,6 +476,7 @@ struct debugfs_files { struct dentry *req_stats; u32 dme_local_attr_id; u32 dme_peer_attr_id; + struct dentry *reset_controller; #ifdef CONFIG_UFS_FAULT_INJECTION struct dentry *err_inj_codes; struct dentry *err_inj_scenario; |