diff options
Diffstat (limited to 'drivers/scsi/ufs/ufshcd.c')
-rw-r--r-- | drivers/scsi/ufs/ufshcd.c | 74 |
1 files changed, 36 insertions, 38 deletions
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 497c38a4a866..59b654467d48 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c | |||
@@ -2844,8 +2844,13 @@ static void ufshcd_slave_destroy(struct scsi_device *sdev) | |||
2844 | hba = shost_priv(sdev->host); | 2844 | hba = shost_priv(sdev->host); |
2845 | scsi_deactivate_tcq(sdev, hba->nutrs); | 2845 | scsi_deactivate_tcq(sdev, hba->nutrs); |
2846 | /* Drop the reference as it won't be needed anymore */ | 2846 | /* Drop the reference as it won't be needed anymore */ |
2847 | if (ufshcd_scsi_to_upiu_lun(sdev->lun) == UFS_UPIU_UFS_DEVICE_WLUN) | 2847 | if (ufshcd_scsi_to_upiu_lun(sdev->lun) == UFS_UPIU_UFS_DEVICE_WLUN) { |
2848 | unsigned long flags; | ||
2849 | |||
2850 | spin_lock_irqsave(hba->host->host_lock, flags); | ||
2848 | hba->sdev_ufs_device = NULL; | 2851 | hba->sdev_ufs_device = NULL; |
2852 | spin_unlock_irqrestore(hba->host->host_lock, flags); | ||
2853 | } | ||
2849 | } | 2854 | } |
2850 | 2855 | ||
2851 | /** | 2856 | /** |
@@ -4062,6 +4067,8 @@ static void ufshcd_init_icc_levels(struct ufs_hba *hba) | |||
4062 | static int ufshcd_scsi_add_wlus(struct ufs_hba *hba) | 4067 | static int ufshcd_scsi_add_wlus(struct ufs_hba *hba) |
4063 | { | 4068 | { |
4064 | int ret = 0; | 4069 | int ret = 0; |
4070 | struct scsi_device *sdev_rpmb; | ||
4071 | struct scsi_device *sdev_boot; | ||
4065 | 4072 | ||
4066 | hba->sdev_ufs_device = __scsi_add_device(hba->host, 0, 0, | 4073 | hba->sdev_ufs_device = __scsi_add_device(hba->host, 0, 0, |
4067 | ufshcd_upiu_wlun_to_scsi_wlun(UFS_UPIU_UFS_DEVICE_WLUN), NULL); | 4074 | ufshcd_upiu_wlun_to_scsi_wlun(UFS_UPIU_UFS_DEVICE_WLUN), NULL); |
@@ -4070,26 +4077,27 @@ static int ufshcd_scsi_add_wlus(struct ufs_hba *hba) | |||
4070 | hba->sdev_ufs_device = NULL; | 4077 | hba->sdev_ufs_device = NULL; |
4071 | goto out; | 4078 | goto out; |
4072 | } | 4079 | } |
4080 | scsi_device_put(hba->sdev_ufs_device); | ||
4073 | 4081 | ||
4074 | hba->sdev_boot = __scsi_add_device(hba->host, 0, 0, | 4082 | sdev_boot = __scsi_add_device(hba->host, 0, 0, |
4075 | ufshcd_upiu_wlun_to_scsi_wlun(UFS_UPIU_BOOT_WLUN), NULL); | 4083 | ufshcd_upiu_wlun_to_scsi_wlun(UFS_UPIU_BOOT_WLUN), NULL); |
4076 | if (IS_ERR(hba->sdev_boot)) { | 4084 | if (IS_ERR(sdev_boot)) { |
4077 | ret = PTR_ERR(hba->sdev_boot); | 4085 | ret = PTR_ERR(sdev_boot); |
4078 | hba->sdev_boot = NULL; | ||
4079 | goto remove_sdev_ufs_device; | 4086 | goto remove_sdev_ufs_device; |
4080 | } | 4087 | } |
4088 | scsi_device_put(sdev_boot); | ||
4081 | 4089 | ||
4082 | hba->sdev_rpmb = __scsi_add_device(hba->host, 0, 0, | 4090 | sdev_rpmb = __scsi_add_device(hba->host, 0, 0, |
4083 | ufshcd_upiu_wlun_to_scsi_wlun(UFS_UPIU_RPMB_WLUN), NULL); | 4091 | ufshcd_upiu_wlun_to_scsi_wlun(UFS_UPIU_RPMB_WLUN), NULL); |
4084 | if (IS_ERR(hba->sdev_rpmb)) { | 4092 | if (IS_ERR(sdev_rpmb)) { |
4085 | ret = PTR_ERR(hba->sdev_rpmb); | 4093 | ret = PTR_ERR(sdev_rpmb); |
4086 | hba->sdev_rpmb = NULL; | ||
4087 | goto remove_sdev_boot; | 4094 | goto remove_sdev_boot; |
4088 | } | 4095 | } |
4096 | scsi_device_put(sdev_rpmb); | ||
4089 | goto out; | 4097 | goto out; |
4090 | 4098 | ||
4091 | remove_sdev_boot: | 4099 | remove_sdev_boot: |
4092 | scsi_remove_device(hba->sdev_boot); | 4100 | scsi_remove_device(sdev_boot); |
4093 | remove_sdev_ufs_device: | 4101 | remove_sdev_ufs_device: |
4094 | scsi_remove_device(hba->sdev_ufs_device); | 4102 | scsi_remove_device(hba->sdev_ufs_device); |
4095 | out: | 4103 | out: |
@@ -4097,30 +4105,6 @@ out: | |||
4097 | } | 4105 | } |
4098 | 4106 | ||
4099 | /** | 4107 | /** |
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 | /** | ||
4124 | * ufshcd_probe_hba - probe hba to detect device and initialize | 4108 | * ufshcd_probe_hba - probe hba to detect device and initialize |
4125 | * @hba: per-adapter instance | 4109 | * @hba: per-adapter instance |
4126 | * | 4110 | * |
@@ -4675,11 +4659,25 @@ static int ufshcd_set_dev_pwr_mode(struct ufs_hba *hba, | |||
4675 | { | 4659 | { |
4676 | unsigned char cmd[6] = { START_STOP }; | 4660 | unsigned char cmd[6] = { START_STOP }; |
4677 | struct scsi_sense_hdr sshdr; | 4661 | struct scsi_sense_hdr sshdr; |
4678 | struct scsi_device *sdp = hba->sdev_ufs_device; | 4662 | struct scsi_device *sdp; |
4663 | unsigned long flags; | ||
4679 | int ret; | 4664 | int ret; |
4680 | 4665 | ||
4681 | if (!sdp || !scsi_device_online(sdp)) | 4666 | spin_lock_irqsave(hba->host->host_lock, flags); |
4682 | return -ENODEV; | 4667 | sdp = hba->sdev_ufs_device; |
4668 | if (sdp) { | ||
4669 | ret = scsi_device_get(sdp); | ||
4670 | if (!ret && !scsi_device_online(sdp)) { | ||
4671 | ret = -ENODEV; | ||
4672 | scsi_device_put(sdp); | ||
4673 | } | ||
4674 | } else { | ||
4675 | ret = -ENODEV; | ||
4676 | } | ||
4677 | spin_unlock_irqrestore(hba->host->host_lock, flags); | ||
4678 | |||
4679 | if (ret) | ||
4680 | return ret; | ||
4683 | 4681 | ||
4684 | /* | 4682 | /* |
4685 | * If scsi commands fail, the scsi mid-layer schedules scsi error- | 4683 | * If scsi commands fail, the scsi mid-layer schedules scsi error- |
@@ -4718,6 +4716,7 @@ static int ufshcd_set_dev_pwr_mode(struct ufs_hba *hba, | |||
4718 | if (!ret) | 4716 | if (!ret) |
4719 | hba->curr_dev_pwr_mode = pwr_mode; | 4717 | hba->curr_dev_pwr_mode = pwr_mode; |
4720 | out: | 4718 | out: |
4719 | scsi_device_put(sdp); | ||
4721 | hba->host->eh_noresume = 0; | 4720 | hba->host->eh_noresume = 0; |
4722 | return ret; | 4721 | return ret; |
4723 | } | 4722 | } |
@@ -5231,7 +5230,6 @@ EXPORT_SYMBOL(ufshcd_shutdown); | |||
5231 | void ufshcd_remove(struct ufs_hba *hba) | 5230 | void ufshcd_remove(struct ufs_hba *hba) |
5232 | { | 5231 | { |
5233 | scsi_remove_host(hba->host); | 5232 | scsi_remove_host(hba->host); |
5234 | ufshcd_scsi_remove_wlus(hba); | ||
5235 | /* disable interrupts */ | 5233 | /* disable interrupts */ |
5236 | ufshcd_disable_intr(hba, hba->intr_mask); | 5234 | ufshcd_disable_intr(hba, hba->intr_mask); |
5237 | ufshcd_hba_stop(hba); | 5235 | ufshcd_hba_stop(hba); |