diff options
author | 2018-05-03 16:37:17 +0530 | |
---|---|---|
committer | 2018-05-18 12:20:48 -0400 | |
commit | b334456ec2021b1addc19806990115e69ec4ac32 (patch) | |
tree | fa7afd9cdb493b268b308369ccb2848d1f80421a /drivers/scsi/ufs | |
parent | scsi: ufs: fix exception event handling (diff) | |
download | linux-b334456ec2021b1addc19806990115e69ec4ac32.tar.gz linux-b334456ec2021b1addc19806990115e69ec4ac32.tar.bz2 linux-b334456ec2021b1addc19806990115e69ec4ac32.zip |
scsi: ufs: ufshcd: fix possible unclocked register access
Vendor specific setup_clocks ops may depend on clocks managed by ufshcd
driver so if the vendor specific setup_clocks callback is called when
the required clocks are turned off, it results into unclocked register
access.
This change make sure that required clocks are enabled before vendor
specific setup_clocks callback is called.
Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
Signed-off-by: Venkat Gopalakrishnan <venkatg@codeaurora.org>
Signed-off-by: Can Guo <cang@codeaurora.org>
Signed-off-by: Asutosh Das <asutoshd@codeaurora.org>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi/ufs')
-rw-r--r-- | drivers/scsi/ufs/ufshcd.c | 26 |
1 files changed, 20 insertions, 6 deletions
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 4dc48804c17b..79591934ef45 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -6912,9 +6912,16 @@ static int __ufshcd_setup_clocks(struct ufs_hba *hba, bool on, if (list_empty(head)) goto out; - ret = ufshcd_vops_setup_clocks(hba, on, PRE_CHANGE); - if (ret) - return ret; + /* + * vendor specific setup_clocks ops may depend on clocks managed by + * this standard driver hence call the vendor specific setup_clocks + * before disabling the clocks managed here. + */ + if (!on) { + ret = ufshcd_vops_setup_clocks(hba, on, PRE_CHANGE); + if (ret) + return ret; + } list_for_each_entry(clki, head, list) { if (!IS_ERR_OR_NULL(clki->clk)) { @@ -6938,9 +6945,16 @@ static int __ufshcd_setup_clocks(struct ufs_hba *hba, bool on, } } - ret = ufshcd_vops_setup_clocks(hba, on, POST_CHANGE); - if (ret) - return ret; + /* + * vendor specific setup_clocks ops may depend on clocks managed by + * this standard driver hence call the vendor specific setup_clocks + * after enabling the clocks managed here. + */ + if (on) { + ret = ufshcd_vops_setup_clocks(hba, on, POST_CHANGE); + if (ret) + return ret; + } out: if (ret) { |