aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYaniv Gardi <ygardi@codeaurora.org>2016-03-10 10:37:15 -0500
committerMartin K. Petersen <martin.petersen@oracle.com>2016-03-14 21:04:45 -0400
commitafdfff59a0e0c5527610d3bc5d338a0da03dd23d (patch)
treea13954a029ee78eaf9b37ddc25be5e66a832dcda
parenta70e91b8bbaa3924d6598f9b4d1d468d2c88e6d3 (diff)
scsi: ufs: handle non spec compliant bkops behaviour by device
We are seeing that some devices are raising the urgent bkops exception events even when BKOPS status doesn't indicate performace impacted or critical. Handle these device by determining their urgent bkops status at runtime. Reviewed-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org> Signed-off-by: Yaniv Gardi <ygardi@codeaurora.org> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-rw-r--r--drivers/scsi/ufs/ufshcd.c53
-rw-r--r--drivers/scsi/ufs/ufshcd.h6
2 files changed, 52 insertions, 7 deletions
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index b429a57984a2..82a4b1c3a837 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -3763,7 +3763,7 @@ out:
3763 */ 3763 */
3764static int ufshcd_urgent_bkops(struct ufs_hba *hba) 3764static int ufshcd_urgent_bkops(struct ufs_hba *hba)
3765{ 3765{
3766 return ufshcd_bkops_ctrl(hba, BKOPS_STATUS_PERF_IMPACT); 3766 return ufshcd_bkops_ctrl(hba, hba->urgent_bkops_lvl);
3767} 3767}
3768 3768
3769static inline int ufshcd_get_ee_status(struct ufs_hba *hba, u32 *status) 3769static inline int ufshcd_get_ee_status(struct ufs_hba *hba, u32 *status)
@@ -3772,6 +3772,43 @@ static inline int ufshcd_get_ee_status(struct ufs_hba *hba, u32 *status)
3772 QUERY_ATTR_IDN_EE_STATUS, 0, 0, status); 3772 QUERY_ATTR_IDN_EE_STATUS, 0, 0, status);
3773} 3773}
3774 3774
3775static void ufshcd_bkops_exception_event_handler(struct ufs_hba *hba)
3776{
3777 int err;
3778 u32 curr_status = 0;
3779
3780 if (hba->is_urgent_bkops_lvl_checked)
3781 goto enable_auto_bkops;
3782
3783 err = ufshcd_get_bkops_status(hba, &curr_status);
3784 if (err) {
3785 dev_err(hba->dev, "%s: failed to get BKOPS status %d\n",
3786 __func__, err);
3787 goto out;
3788 }
3789
3790 /*
3791 * We are seeing that some devices are raising the urgent bkops
3792 * exception events even when BKOPS status doesn't indicate performace
3793 * impacted or critical. Handle these device by determining their urgent
3794 * bkops status at runtime.
3795 */
3796 if (curr_status < BKOPS_STATUS_PERF_IMPACT) {
3797 dev_err(hba->dev, "%s: device raised urgent BKOPS exception for bkops status %d\n",
3798 __func__, curr_status);
3799 /* update the current status as the urgent bkops level */
3800 hba->urgent_bkops_lvl = curr_status;
3801 hba->is_urgent_bkops_lvl_checked = true;
3802 }
3803
3804enable_auto_bkops:
3805 err = ufshcd_enable_auto_bkops(hba);
3806out:
3807 if (err < 0)
3808 dev_err(hba->dev, "%s: failed to handle urgent bkops %d\n",
3809 __func__, err);
3810}
3811
3775/** 3812/**
3776 * ufshcd_exception_event_handler - handle exceptions raised by device 3813 * ufshcd_exception_event_handler - handle exceptions raised by device
3777 * @work: pointer to work data 3814 * @work: pointer to work data
@@ -3795,12 +3832,10 @@ static void ufshcd_exception_event_handler(struct work_struct *work)
3795 } 3832 }
3796 3833
3797 status &= hba->ee_ctrl_mask; 3834 status &= hba->ee_ctrl_mask;
3798 if (status & MASK_EE_URGENT_BKOPS) { 3835
3799 err = ufshcd_urgent_bkops(hba); 3836 if (status & MASK_EE_URGENT_BKOPS)
3800 if (err < 0) 3837 ufshcd_bkops_exception_event_handler(hba);
3801 dev_err(hba->dev, "%s: failed to handle urgent bkops %d\n", 3838
3802 __func__, err);
3803 }
3804out: 3839out:
3805 pm_runtime_put_sync(hba->dev); 3840 pm_runtime_put_sync(hba->dev);
3806 return; 3841 return;
@@ -4832,6 +4867,10 @@ static int ufshcd_probe_hba(struct ufs_hba *hba)
4832 4867
4833 ufshcd_init_pwr_info(hba); 4868 ufshcd_init_pwr_info(hba);
4834 4869
4870 /* set the default level for urgent bkops */
4871 hba->urgent_bkops_lvl = BKOPS_STATUS_PERF_IMPACT;
4872 hba->is_urgent_bkops_lvl_checked = false;
4873
4835 /* UniPro link is active now */ 4874 /* UniPro link is active now */
4836 ufshcd_set_link_active(hba); 4875 ufshcd_set_link_active(hba);
4837 4876
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 77e79c00ef8c..65f29aa881d6 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -383,6 +383,9 @@ struct ufs_init_prefetch {
383 * @clk_list_head: UFS host controller clocks list node head 383 * @clk_list_head: UFS host controller clocks list node head
384 * @pwr_info: holds current power mode 384 * @pwr_info: holds current power mode
385 * @max_pwr_info: keeps the device max valid pwm 385 * @max_pwr_info: keeps the device max valid pwm
386 * @urgent_bkops_lvl: keeps track of urgent bkops level for device
387 * @is_urgent_bkops_lvl_checked: keeps track if the urgent bkops level for
388 * device is known or not.
386 */ 389 */
387struct ufs_hba { 390struct ufs_hba {
388 void __iomem *mmio_base; 391 void __iomem *mmio_base;
@@ -538,6 +541,9 @@ struct ufs_hba {
538 struct devfreq *devfreq; 541 struct devfreq *devfreq;
539 struct ufs_clk_scaling clk_scaling; 542 struct ufs_clk_scaling clk_scaling;
540 bool is_sys_suspended; 543 bool is_sys_suspended;
544
545 enum bkops_status urgent_bkops_lvl;
546 bool is_urgent_bkops_lvl_checked;
541}; 547};
542 548
543/* Returns true if clocks can be gated. Otherwise false */ 549/* Returns true if clocks can be gated. Otherwise false */