| @@ -744,6 +744,8 @@ static void ufshcd_exit_clk_gating(struct ufs_hba *hba) · 743 unmodified lines |
| 744 | 744 | if (!ufshcd_is_clkgating_allowed(hba)) |
| 745 | 745 | return; |
| 746 | 746 | device_remove_file(hba->dev, &hba->clk_gating.delay_attr); |
| 747 | + cancel_work_sync(&hba->clk_gating.ungate_work); |
| 748 | + cancel_delayed_work_sync(&hba->clk_gating.gate_work); |
| 747 | 749 | } |
| 748 | 750 | |
| 749 | 751 | /* Must be called with host lock acquired */ |
| @@ -2246,6 +2248,22 @@ static int ufshcd_uic_hibern8_exit(struct ufs_hba *hba) · 1496 unmodified lines |
| 2246 | 2248 | return ret; |
| 2247 | 2249 | } |
| 2248 | 2250 | |
| 2251 | + /** |
| 2252 | + * ufshcd_init_pwr_info - setting the POR (power on reset) |
| 2253 | + * values in hba power info |
| 2254 | + * @hba: per-adapter instance |
| 2255 | + */ |
| 2256 | +static void ufshcd_init_pwr_info(struct ufs_hba *hba) |
| 2257 | +{ |
| 2258 | + hba->pwr_info.gear_rx = UFS_PWM_G1; |
| 2259 | + hba->pwr_info.gear_tx = UFS_PWM_G1; |
| 2260 | + hba->pwr_info.lane_rx = 1; |
| 2261 | + hba->pwr_info.lane_tx = 1; |
| 2262 | + hba->pwr_info.pwr_rx = SLOWAUTO_MODE; |
| 2263 | + hba->pwr_info.pwr_tx = SLOWAUTO_MODE; |
| 2264 | + hba->pwr_info.hs_rate = 0; |
| 2265 | +} |
| 2266 | + |
| 2249 | 2267 | /** |
| 2250 | 2268 | * ufshcd_get_max_pwr_mode - reads the max power mode negotiated with device |
| 2251 | 2269 | * @hba: per-adapter instance |
| @@ -2844,8 +2862,13 @@ static void ufshcd_slave_destroy(struct scsi_device *sdev) · 592 unmodified lines |
| 2844 | 2862 | hba = shost_priv(sdev->host); |
| 2845 | 2863 | scsi_deactivate_tcq(sdev, hba->nutrs); |
| 2846 | 2864 | /* Drop the reference as it won't be needed anymore */ |
| 2847 | | − if (ufshcd_scsi_to_upiu_lun(sdev->lun) == UFS_UPIU_UFS_DEVICE_WLUN) |
| 2865 | + if (ufshcd_scsi_to_upiu_lun(sdev->lun) == UFS_UPIU_UFS_DEVICE_WLUN) { |
| 2866 | + unsigned long flags; |
| 2867 | + |
| 2868 | + spin_lock_irqsave(hba->host->host_lock, flags); |
| 2848 | 2869 | hba->sdev_ufs_device = NULL; |
| 2870 | + spin_unlock_irqrestore(hba->host->host_lock, flags); |
| 2871 | + } |
| 2849 | 2872 | } |
| 2850 | 2873 | |
| 2851 | 2874 | /** |
| @@ -4062,6 +4085,8 @@ static void ufshcd_init_icc_levels(struct ufs_hba *hba) · 1210 unmodified lines |
| 4062 | 4085 | static int ufshcd_scsi_add_wlus(struct ufs_hba *hba) |
| 4063 | 4086 | { |
| 4064 | 4087 | int ret = 0; |
| 4088 | + struct scsi_device *sdev_rpmb; |
| 4089 | + struct scsi_device *sdev_boot; |
| 4065 | 4090 | |
| 4066 | 4091 | hba->sdev_ufs_device = __scsi_add_device(hba->host, 0, 0, |
| 4067 | 4092 | ufshcd_upiu_wlun_to_scsi_wlun(UFS_UPIU_UFS_DEVICE_WLUN), NULL); |
| @@ -4070,56 +4095,33 @@ static int ufshcd_scsi_add_wlus(struct ufs_hba *hba) · 2 unmodified lines |
| 4070 | 4095 | hba->sdev_ufs_device = NULL; |
| 4071 | 4096 | goto out; |
| 4072 | 4097 | } |
| 4098 | + scsi_device_put(hba->sdev_ufs_device); |
| 4073 | 4099 | |
| 4074 | | − hba->sdev_boot = __scsi_add_device(hba->host, 0, 0, |
| 4100 | + sdev_boot = __scsi_add_device(hba->host, 0, 0, |
| 4075 | 4101 | ufshcd_upiu_wlun_to_scsi_wlun(UFS_UPIU_BOOT_WLUN), NULL); |
| 4076 | | − if (IS_ERR(hba->sdev_boot)) { |
| 4077 | | − ret = PTR_ERR(hba->sdev_boot); |
| 4078 | | − hba->sdev_boot = NULL; |
| 4102 | + if (IS_ERR(sdev_boot)) { |
| 4103 | + ret = PTR_ERR(sdev_boot); |
| 4079 | 4104 | goto remove_sdev_ufs_device; |
| 4080 | 4105 | } |
| 4106 | + scsi_device_put(sdev_boot); |
| 4081 | 4107 | |
| 4082 | | − hba->sdev_rpmb = __scsi_add_device(hba->host, 0, 0, |
| 4108 | + sdev_rpmb = __scsi_add_device(hba->host, 0, 0, |
| 4083 | 4109 | ufshcd_upiu_wlun_to_scsi_wlun(UFS_UPIU_RPMB_WLUN), NULL); |
| 4084 | | − if (IS_ERR(hba->sdev_rpmb)) { |
| 4085 | | − ret = PTR_ERR(hba->sdev_rpmb); |
| 4086 | | − hba->sdev_rpmb = NULL; |
| 4110 | + if (IS_ERR(sdev_rpmb)) { |
| 4111 | + ret = PTR_ERR(sdev_rpmb); |
| 4087 | 4112 | goto remove_sdev_boot; |
| 4088 | 4113 | } |
| 4114 | + scsi_device_put(sdev_rpmb); |
| 4089 | 4115 | goto out; |
| 4090 | 4116 | |
| 4091 | 4117 | remove_sdev_boot: |
| 4092 | | − scsi_remove_device(hba->sdev_boot); |
| 4118 | + scsi_remove_device(sdev_boot); |
| 4093 | 4119 | remove_sdev_ufs_device: |
| 4094 | 4120 | scsi_remove_device(hba->sdev_ufs_device); |
| 4095 | 4121 | out: |
| 4096 | 4122 | return ret; |
| 4097 | 4123 | } |
| 4098 | 4124 | |
| 4099 | | −/** |
| 4100 | | − * ufshcd_scsi_remove_wlus - Removes the W-LUs which were added by |
| 4101 | | − * ufshcd_scsi_add_wlus() |
| 4102 | | − * @hba: per-adapter instance |
| 4103 | | − * |
| 4104 | | − */ |
| 4105 | | −static void ufshcd_scsi_remove_wlus(struct ufs_hba *hba) |
| 4106 | | −{ |
| 4107 | | − if (hba->sdev_ufs_device) { |
| 4108 | | − scsi_remove_device(hba->sdev_ufs_device); |
| 4109 | | − hba->sdev_ufs_device = NULL; |
| 4110 | | − } |
| 4111 | | − |
| 4112 | | − if (hba->sdev_boot) { |
| 4113 | | − scsi_remove_device(hba->sdev_boot); |
| 4114 | | − hba->sdev_boot = NULL; |
| 4115 | | − } |
| 4116 | | − |
| 4117 | | − if (hba->sdev_rpmb) { |
| 4118 | | − scsi_remove_device(hba->sdev_rpmb); |
| 4119 | | − hba->sdev_rpmb = NULL; |
| 4120 | | − } |
| 4121 | | −} |
| 4122 | | − |
| 4123 | 4125 | /** |
| 4124 | 4126 | * ufshcd_probe_hba - probe hba to detect device and initialize |
| 4125 | 4127 | * @hba: per-adapter instance |
| @@ -4134,6 +4136,8 @@ static int ufshcd_probe_hba(struct ufs_hba *hba) · 8 unmodified lines |
| 4134 | 4136 | if (ret) |
| 4135 | 4137 | goto out; |
| 4136 | 4138 | |
| 4139 | + ufshcd_init_pwr_info(hba); |
| 4140 | + |
| 4137 | 4141 | /* UniPro link is active now */ |
| 4138 | 4142 | ufshcd_set_link_active(hba); |
| 4139 | 4143 | |
| @@ -4264,12 +4268,18 @@ static int ufshcd_config_vreg_load(struct device *dev, struct ufs_vreg *vreg, · 124 unmodified lines |
| 4264 | 4268 | static inline int ufshcd_config_vreg_lpm(struct ufs_hba *hba, |
| 4265 | 4269 | struct ufs_vreg *vreg) |
| 4266 | 4270 | { |
| 4271 | + if (!vreg) |
| 4272 | + return 0; |
| 4273 | + |
| 4267 | 4274 | return ufshcd_config_vreg_load(hba->dev, vreg, UFS_VREG_LPM_LOAD_UA); |
| 4268 | 4275 | } |
| 4269 | 4276 | |
| 4270 | 4277 | static inline int ufshcd_config_vreg_hpm(struct ufs_hba *hba, |
| 4271 | 4278 | struct ufs_vreg *vreg) |
| 4272 | 4279 | { |
| 4280 | + if (!vreg) |
| 4281 | + return 0; |
| 4282 | + |
| 4273 | 4283 | return ufshcd_config_vreg_load(hba->dev, vreg, vreg->max_uA); |
| 4274 | 4284 | } |
| 4275 | 4285 | |
| @@ -4471,7 +4481,7 @@ out: · 195 unmodified lines |
| 4471 | 4481 | if (!IS_ERR_OR_NULL(clki->clk) && clki->enabled) |
| 4472 | 4482 | clk_disable_unprepare(clki->clk); |
| 4473 | 4483 | } |
| 4474 | | − } else if (!ret && on) { |
| 4484 | + } else if (on) { |
| 4475 | 4485 | spin_lock_irqsave(hba->host->host_lock, flags); |
| 4476 | 4486 | hba->clk_gating.state = CLKS_ON; |
| 4477 | 4487 | spin_unlock_irqrestore(hba->host->host_lock, flags); |
| @@ -4675,11 +4685,25 @@ static int ufshcd_set_dev_pwr_mode(struct ufs_hba *hba, · 197 unmodified lines |
| 4675 | 4685 | { |
| 4676 | 4686 | unsigned char cmd[6] = { START_STOP }; |
| 4677 | 4687 | struct scsi_sense_hdr sshdr; |
| 4678 | | − struct scsi_device *sdp = hba->sdev_ufs_device; |
| 4688 | + struct scsi_device *sdp; |
| 4689 | + unsigned long flags; |
| 4679 | 4690 | int ret; |
| 4680 | 4691 | |
| 4681 | | − if (!sdp || !scsi_device_online(sdp)) |
| 4682 | | − return -ENODEV; |
| 4692 | + spin_lock_irqsave(hba->host->host_lock, flags); |
| 4693 | + sdp = hba->sdev_ufs_device; |
| 4694 | + if (sdp) { |
| 4695 | + ret = scsi_device_get(sdp); |
| 4696 | + if (!ret && !scsi_device_online(sdp)) { |
| 4697 | + ret = -ENODEV; |
| 4698 | + scsi_device_put(sdp); |
| 4699 | + } |
| 4700 | + } else { |
| 4701 | + ret = -ENODEV; |
| 4702 | + } |
| 4703 | + spin_unlock_irqrestore(hba->host->host_lock, flags); |
| 4704 | + |
| 4705 | + if (ret) |
| 4706 | + return ret; |
| 4683 | 4707 | |
| 4684 | 4708 | /* |
| 4685 | 4709 | * If scsi commands fail, the scsi mid-layer schedules scsi error- |
| @@ -4718,6 +4742,7 @@ static int ufshcd_set_dev_pwr_mode(struct ufs_hba *hba, · 32 unmodified lines |
| 4718 | 4742 | if (!ret) |
| 4719 | 4743 | hba->curr_dev_pwr_mode = pwr_mode; |
| 4720 | 4744 | out: |
| 4745 | + scsi_device_put(sdp); |
| 4721 | 4746 | hba->host->eh_noresume = 0; |
| 4722 | 4747 | return ret; |
| 4723 | 4748 | } |
| @@ -5087,7 +5112,7 @@ int ufshcd_system_suspend(struct ufs_hba *hba) · 363 unmodified lines |
| 5087 | 5112 | int ret = 0; |
| 5088 | 5113 | |
| 5089 | 5114 | if (!hba || !hba->is_powered) |
| 5090 | | − goto out; |
| 5115 | + return 0; |
| 5091 | 5116 | |
| 5092 | 5117 | if (pm_runtime_suspended(hba->dev)) { |
| 5093 | 5118 | if (hba->rpm_lvl == hba->spm_lvl) |
| @@ -5231,7 +5256,6 @@ EXPORT_SYMBOL(ufshcd_shutdown); · 137 unmodified lines |
| 5231 | 5256 | void ufshcd_remove(struct ufs_hba *hba) |
| 5232 | 5257 | { |
| 5233 | 5258 | scsi_remove_host(hba->host); |
| 5234 | | − ufshcd_scsi_remove_wlus(hba); |
| 5235 | 5259 | /* disable interrupts */ |
| 5236 | 5260 | ufshcd_disable_intr(hba, hba->intr_mask); |
| 5237 | 5261 | ufshcd_hba_stop(hba); |