scsi: ufs: ufshcd: fix possible unclocked register access
authorSubhash Jadavani <subhashj@codeaurora.org>
Thu, 3 May 2018 11:07:17 +0000 (16:37 +0530)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 3 Aug 2018 05:50:32 +0000 (07:50 +0200)
[ Upstream commit b334456ec2021b1addc19806990115e69ec4ac32 ]

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>
Signed-off-by: Sasha Levin <alexander.levin@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/scsi/ufs/ufshcd.c

index 3bb1f6c..5efcfb5 100644 (file)
@@ -6761,9 +6761,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)) {
@@ -6787,9 +6794,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) {