| @@ -744,6 +744,8 @@ static void ufshcd_exit_clk_gating(struct ufs_hba *hba) · 743 unmodified lines |
| 744 | if (!ufshcd_is_clkgating_allowed(hba)) | 744 | if (!ufshcd_is_clkgating_allowed(hba)) |
| 745 | return; | 745 | return; |
| 746 | device_remove_file(hba->dev, &hba->clk_gating.delay_attr); | 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 | /* Must be called with host lock acquired */ | 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 | return ret; | 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 | * ufshcd_get_max_pwr_mode - reads the max power mode negotiated with device | 2268 | * ufshcd_get_max_pwr_mode - reads the max power mode negotiated with device |
| 2251 | * @hba: per-adapter instance | 2269 | * @hba: per-adapter instance |
| @@ -2844,8 +2862,13 @@ static void ufshcd_slave_destroy(struct scsi_device *sdev) · 592 unmodified lines |
| 2844 | hba = shost_priv(sdev->host); | 2862 | hba = shost_priv(sdev->host); |
| 2845 | scsi_deactivate_tcq(sdev, hba->nutrs); | 2863 | scsi_deactivate_tcq(sdev, hba->nutrs); |
| 2846 | /* Drop the reference as it won't be needed anymore */ | 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 | hba->sdev_ufs_device = NULL; | 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 | static int ufshcd_scsi_add_wlus(struct ufs_hba *hba) | 4085 | static int ufshcd_scsi_add_wlus(struct ufs_hba *hba) |
| 4063 | { | 4086 | { |
| 4064 | int ret = 0; | 4087 | int ret = 0; |
| | 4088 | struct scsi_device *sdev_rpmb; |
| | 4089 | struct scsi_device *sdev_boot; |
| 4065 | | 4090 | |
| 4066 | hba->sdev_ufs_device = __scsi_add_device(hba->host, 0, 0, | 4091 | hba->sdev_ufs_device = __scsi_add_device(hba->host, 0, 0, |
| 4067 | ufshcd_upiu_wlun_to_scsi_wlun(UFS_UPIU_UFS_DEVICE_WLUN), NULL); | 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 | hba->sdev_ufs_device = NULL; | 4095 | hba->sdev_ufs_device = NULL; |
| 4071 | goto out; | 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 | ufshcd_upiu_wlun_to_scsi_wlun(UFS_UPIU_BOOT_WLUN), NULL); | 4101 | ufshcd_upiu_wlun_to_scsi_wlun(UFS_UPIU_BOOT_WLUN), NULL); |
| 4076 | if (IS_ERR(hba->sdev_boot)) { | 4102 | if (IS_ERR(sdev_boot)) { |
| 4077 | ret = PTR_ERR(hba->sdev_boot); | 4103 | ret = PTR_ERR(sdev_boot); |
| 4078 | hba->sdev_boot = NULL; | | |
| 4079 | goto remove_sdev_ufs_device; | 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 | ufshcd_upiu_wlun_to_scsi_wlun(UFS_UPIU_RPMB_WLUN), NULL); | 4109 | ufshcd_upiu_wlun_to_scsi_wlun(UFS_UPIU_RPMB_WLUN), NULL); |
| 4084 | if (IS_ERR(hba->sdev_rpmb)) { | 4110 | if (IS_ERR(sdev_rpmb)) { |
| 4085 | ret = PTR_ERR(hba->sdev_rpmb); | 4111 | ret = PTR_ERR(sdev_rpmb); |
| 4086 | hba->sdev_rpmb = NULL; | | |
| 4087 | goto remove_sdev_boot; | 4112 | goto remove_sdev_boot; |
| 4088 | } | 4113 | } |
| | 4114 | scsi_device_put(sdev_rpmb); |
| 4089 | goto out; | 4115 | goto out; |
| 4090 | | 4116 | |
| 4091 | remove_sdev_boot: | 4117 | remove_sdev_boot: |
| 4092 | scsi_remove_device(hba->sdev_boot); | 4118 | scsi_remove_device(sdev_boot); |
| 4093 | remove_sdev_ufs_device: | 4119 | remove_sdev_ufs_device: |
| 4094 | scsi_remove_device(hba->sdev_ufs_device); | 4120 | scsi_remove_device(hba->sdev_ufs_device); |
| 4095 | out: | 4121 | out: |
| 4096 | return ret; | 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 | * ufshcd_probe_hba - probe hba to detect device and initialize | 4126 | * ufshcd_probe_hba - probe hba to detect device and initialize |
| 4125 | * @hba: per-adapter instance | 4127 | * @hba: per-adapter instance |
| @@ -4134,6 +4136,8 @@ static int ufshcd_probe_hba(struct ufs_hba *hba) · 8 unmodified lines |
| 4134 | if (ret) | 4136 | if (ret) |
| 4135 | goto out; | 4137 | goto out; |
| 4136 | | 4138 | |
| | 4139 | ufshcd_init_pwr_info(hba); |
| | 4140 | |
| 4137 | /* UniPro link is active now */ | 4141 | /* UniPro link is active now */ |
| 4138 | ufshcd_set_link_active(hba); | 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 | static inline int ufshcd_config_vreg_lpm(struct ufs_hba *hba, | 4268 | static inline int ufshcd_config_vreg_lpm(struct ufs_hba *hba, |
| 4265 | struct ufs_vreg *vreg) | 4269 | struct ufs_vreg *vreg) |
| 4266 | { | 4270 | { |
| | 4271 | if (!vreg) |
| | 4272 | return 0; |
| | 4273 | |
| 4267 | return ufshcd_config_vreg_load(hba->dev, vreg, UFS_VREG_LPM_LOAD_UA); | 4274 | return ufshcd_config_vreg_load(hba->dev, vreg, UFS_VREG_LPM_LOAD_UA); |
| 4268 | } | 4275 | } |
| 4269 | | 4276 | |
| 4270 | static inline int ufshcd_config_vreg_hpm(struct ufs_hba *hba, | 4277 | static inline int ufshcd_config_vreg_hpm(struct ufs_hba *hba, |
| 4271 | struct ufs_vreg *vreg) | 4278 | struct ufs_vreg *vreg) |
| 4272 | { | 4279 | { |
| | 4280 | if (!vreg) |
| | 4281 | return 0; |
| | 4282 | |
| 4273 | return ufshcd_config_vreg_load(hba->dev, vreg, vreg->max_uA); | 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 | if (!IS_ERR_OR_NULL(clki->clk) && clki->enabled) | 4481 | if (!IS_ERR_OR_NULL(clki->clk) && clki->enabled) |
| 4472 | clk_disable_unprepare(clki->clk); | 4482 | clk_disable_unprepare(clki->clk); |
| 4473 | } | 4483 | } |
| 4474 | } else if (!ret && on) { | 4484 | } else if (on) { |
| 4475 | spin_lock_irqsave(hba->host->host_lock, flags); | 4485 | spin_lock_irqsave(hba->host->host_lock, flags); |
| 4476 | hba->clk_gating.state = CLKS_ON; | 4486 | hba->clk_gating.state = CLKS_ON; |
| 4477 | spin_unlock_irqrestore(hba->host->host_lock, flags); | 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 | unsigned char cmd[6] = { START_STOP }; | 4686 | unsigned char cmd[6] = { START_STOP }; |
| 4677 | struct scsi_sense_hdr sshdr; | 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 | int ret; | 4690 | int ret; |
| 4680 | | 4691 | |
| 4681 | if (!sdp || !scsi_device_online(sdp)) | 4692 | spin_lock_irqsave(hba->host->host_lock, flags); |
| 4682 | return -ENODEV; | 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 | * If scsi commands fail, the scsi mid-layer schedules scsi error- | 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 | if (!ret) | 4742 | if (!ret) |
| 4719 | hba->curr_dev_pwr_mode = pwr_mode; | 4743 | hba->curr_dev_pwr_mode = pwr_mode; |
| 4720 | out: | 4744 | out: |
| | 4745 | scsi_device_put(sdp); |
| 4721 | hba->host->eh_noresume = 0; | 4746 | hba->host->eh_noresume = 0; |
| 4722 | return ret; | 4747 | return ret; |
| 4723 | } | 4748 | } |
| @@ -5087,7 +5112,7 @@ int ufshcd_system_suspend(struct ufs_hba *hba) · 363 unmodified lines |
| 5087 | int ret = 0; | 5112 | int ret = 0; |
| 5088 | | 5113 | |
| 5089 | if (!hba || !hba->is_powered) | 5114 | if (!hba || !hba->is_powered) |
| 5090 | goto out; | 5115 | return 0; |
| 5091 | | 5116 | |
| 5092 | if (pm_runtime_suspended(hba->dev)) { | 5117 | if (pm_runtime_suspended(hba->dev)) { |
| 5093 | if (hba->rpm_lvl == hba->spm_lvl) | 5118 | if (hba->rpm_lvl == hba->spm_lvl) |
| @@ -5231,7 +5256,6 @@ EXPORT_SYMBOL(ufshcd_shutdown); · 137 unmodified lines |
| 5231 | void ufshcd_remove(struct ufs_hba *hba) | 5256 | void ufshcd_remove(struct ufs_hba *hba) |
| 5232 | { | 5257 | { |
| 5233 | scsi_remove_host(hba->host); | 5258 | scsi_remove_host(hba->host); |
| 5234 | ufshcd_scsi_remove_wlus(hba); | | |
| 5235 | /* disable interrupts */ | 5259 | /* disable interrupts */ |
| 5236 | ufshcd_disable_intr(hba, hba->intr_mask); | 5260 | ufshcd_disable_intr(hba, hba->intr_mask); |
| 5237 | ufshcd_hba_stop(hba); | 5261 | ufshcd_hba_stop(hba); |