aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/ufs/ufshcd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/ufs/ufshcd.c')
-rw-r--r--drivers/scsi/ufs/ufshcd.c74
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)
4062static int ufshcd_scsi_add_wlus(struct ufs_hba *hba) 4067static 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
4091remove_sdev_boot: 4099remove_sdev_boot:
4092 scsi_remove_device(hba->sdev_boot); 4100 scsi_remove_device(sdev_boot);
4093remove_sdev_ufs_device: 4101remove_sdev_ufs_device:
4094 scsi_remove_device(hba->sdev_ufs_device); 4102 scsi_remove_device(hba->sdev_ufs_device);
4095out: 4103out:
@@ -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 */
4105static 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;
4720out: 4718out:
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);
5231void ufshcd_remove(struct ufs_hba *hba) 5230void 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);