OSDN Git Service

Merge tag 'v4.4.214' into 10
[sagit-ice-cold/kernel_xiaomi_msm8998.git] / drivers / scsi / ufs / ufshcd.c
index 02f8977..368db1a 100644 (file)
@@ -389,8 +389,8 @@ static int ufshcd_devfreq_get_dev_status(struct device *dev,
 
 #if IS_ENABLED(CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND)
 static struct devfreq_simple_ondemand_data ufshcd_ondemand_data = {
-       .upthreshold = 35,
-       .downdifferential = 30,
+       .upthreshold = 70,
+       .downdifferential = 65,
        .simple_scaling = 1,
 };
 
@@ -400,7 +400,7 @@ static void *gov_data;
 #endif
 
 static struct devfreq_dev_profile ufs_devfreq_profile = {
-       .polling_ms     = 40,
+       .polling_ms     = 60,
        .target         = ufshcd_devfreq_target,
        .get_dev_status = ufshcd_devfreq_get_dev_status,
 };
@@ -558,6 +558,7 @@ static void ufshcd_cmd_log_init(struct ufs_hba *hba)
        }
 }
 
+#ifdef CONFIG_TRACEPOINTS
 static void __ufshcd_cmd_log(struct ufs_hba *hba, char *str, char *cmd_type,
                             unsigned int tag, u8 cmd_id, u8 idn, u8 lun,
                             sector_t lba, int transfer_len, u8 opcode)
@@ -586,6 +587,7 @@ static void __ufshcd_cmd_log(struct ufs_hba *hba, char *str, char *cmd_type,
 
        ufshcd_add_command_trace(hba, entry, opcode);
 }
+#endif
 
 static void ufshcd_cmd_log(struct ufs_hba *hba, char *str, char *cmd_type,
        unsigned int tag, u8 cmd_id, u8 idn)
@@ -629,6 +631,7 @@ static void ufshcd_cmd_log_init(struct ufs_hba *hba)
 {
 }
 
+#ifdef CONFIG_TRACEPOINTS
 static void __ufshcd_cmd_log(struct ufs_hba *hba, char *str, char *cmd_type,
                             unsigned int tag, u8 cmd_id, u8 idn, u8 lun,
                             sector_t lba, int transfer_len, u8 opcode)
@@ -644,6 +647,7 @@ static void __ufshcd_cmd_log(struct ufs_hba *hba, char *str, char *cmd_type,
 
        ufshcd_add_command_trace(hba, &entry, opcode);
 }
+#endif
 
 static void ufshcd_dme_cmd_log(struct ufs_hba *hba, char *str, u8 cmd_id)
 {
@@ -2419,6 +2423,9 @@ static inline void ufshcd_hba_capabilities(struct ufs_hba *hba)
        hba->nutrs = (hba->capabilities & MASK_TRANSFER_REQUESTS_SLOTS) + 1;
        hba->nutmrs =
        ((hba->capabilities & MASK_TASK_MANAGEMENT_REQUEST_SLOTS) >> 16) + 1;
+
+       /* disable auto hibern8 */
+       hba->capabilities &= ~MASK_AUTO_HIBERN8_SUPPORT;
 }
 
 /**
@@ -3666,10 +3673,10 @@ static int __ufshcd_query_descriptor(struct ufs_hba *hba,
                goto out_unlock;
        }
 
-       hba->dev_cmd.query.descriptor = NULL;
        *buf_len = be16_to_cpu(response->upiu_res.length);
 
 out_unlock:
+       hba->dev_cmd.query.descriptor = NULL;
        mutex_unlock(&hba->dev_cmd.lock);
 out:
        ufshcd_release_all(hba);
@@ -5405,8 +5412,15 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
                         * UFS device needs urgent BKOPs.
                         */
                        if (!hba->pm_op_in_progress &&
-                           ufshcd_is_exception_event(lrbp->ucd_rsp_ptr))
-                               schedule_work(&hba->eeh_work);
+                           ufshcd_is_exception_event(lrbp->ucd_rsp_ptr)) {
+                               /*
+                                * Prevent suspend once eeh_work is scheduled
+                                * to avoid deadlock between ufshcd_suspend
+                                * and exception event handler.
+                                */
+                               if (schedule_work(&hba->eeh_work))
+                                       pm_runtime_get_noresume(hba->dev);
+                       }
                        break;
                case UPIU_TRANSACTION_REJECT_UPIU:
                        /* TODO: handle Reject UPIU Response */
@@ -5983,6 +5997,13 @@ static void ufshcd_exception_event_handler(struct work_struct *work)
 
 out:
        ufshcd_scsi_unblock_requests(hba);
+       /*
+        * pm_runtime_get_noresume is called while scheduling
+        * eeh_work to avoid suspend racing with exception work.
+        * Hence decrement usage counter using pm_runtime_put_noidle
+        * to allow suspend on completion of exception event handler.
+        */
+       pm_runtime_put_noidle(hba->dev);
        pm_runtime_put(hba->dev);
        return;
 }
@@ -6291,6 +6312,7 @@ static void ufshcd_rls_handler(struct work_struct *work)
        hba = container_of(work, struct ufs_hba, rls_work);
        pm_runtime_get_sync(hba->dev);
        ufshcd_scsi_block_requests(hba);
+       down_write(&hba->lock);
        ret = ufshcd_wait_for_doorbell_clr(hba, U64_MAX);
        if (ret) {
                dev_err(hba->dev,
@@ -6324,6 +6346,7 @@ static void ufshcd_rls_handler(struct work_struct *work)
                hba->restore_needed = false;
 
 out:
+       up_write(&hba->lock);
        ufshcd_scsi_unblock_requests(hba);
        pm_runtime_put_sync(hba->dev);
 }
@@ -7565,7 +7588,8 @@ static int ufshcd_probe_hba(struct ufs_hba *hba)
                        ufshcd_init_icc_levels(hba);
 
                /* Add required well known logical units to scsi mid layer */
-               if (ufshcd_scsi_add_wlus(hba))
+               ret = ufshcd_scsi_add_wlus(hba);
+               if (ret)
                        goto out;
 
                /* Initialize devfreq after UFS device is detected */
@@ -9372,6 +9396,9 @@ int ufshcd_shutdown(struct ufs_hba *hba)
 {
        int ret = 0;
 
+       if (!hba->is_powered)
+               goto out;
+
        if (ufshcd_is_ufs_dev_poweroff(hba) && ufshcd_is_link_off(hba))
                goto out;