diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 098f35219e7d..72eb395ccf1d 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -14,6 +14,28 @@ # satisfy certain initialization assumptions in the SCSI layer. # *!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*! +CONTEXT_ANALYSIS_constants.o := y +CONTEXT_ANALYSIS_scsi.o := y +CONTEXT_ANALYSIS_scsi_common.o := y +CONTEXT_ANALYSIS_scsi_devinfo.o := y +CONTEXT_ANALYSIS_scsi_dh.o := y +CONTEXT_ANALYSIS_scsi_error.o := y +CONTEXT_ANALYSIS_scsi_ioctl.o := y +CONTEXT_ANALYSIS_scsi_lib.o := y +CONTEXT_ANALYSIS_scsi_lib_dma.o := y +CONTEXT_ANALYSIS_scsi_logging.o := y +CONTEXT_ANALYSIS_scsi_netlink.o := y +CONTEXT_ANALYSIS_scsi_pm.o := y +CONTEXT_ANALYSIS_scsi_proc.o := y +CONTEXT_ANALYSIS_scsi_scan.o := y +CONTEXT_ANALYSIS_scsi_sysfs.o := y +CONTEXT_ANALYSIS_scsi_trace.o := y +CONTEXT_ANALYSIS_scsicam.o := y +CONTEXT_ANALYSIS_sd.o := y +CONTEXT_ANALYSIS_sd_dif.o := y +CONTEXT_ANALYSIS_sd_zbc.o := y +CONTEXT_ANALYSIS_sr.o := y +CONTEXT_ANALYSIS_sr_ioctl.o := y CFLAGS_aha152x.o = -DAHA152X_STAT -DAUTOCONF diff --git a/drivers/scsi/device_handler/Makefile b/drivers/scsi/device_handler/Makefile index 0a603aefd2bb..5aa282a63e24 100644 --- a/drivers/scsi/device_handler/Makefile +++ b/drivers/scsi/device_handler/Makefile @@ -2,6 +2,9 @@ # # SCSI Device Handler # + +CONTEXT_ANALYSIS := y + obj-$(CONFIG_SCSI_DH_RDAC) += scsi_dh_rdac.o obj-$(CONFIG_SCSI_DH_HP_SW) += scsi_dh_hp_sw.o obj-$(CONFIG_SCSI_DH_EMC) += scsi_dh_emc.o diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index d512080268af..9610dd7aa85f 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -73,8 +73,9 @@ static struct class shost_class = { * transition is illegal. **/ int scsi_host_set_state(struct Scsi_Host *shost, enum scsi_host_state state) + __must_hold(shost->host_lock) { - enum scsi_host_state oldstate = shost->shost_state; + enum scsi_host_state oldstate = READ_ONCE(shost->shost_state); if (state == oldstate) return 0; @@ -145,7 +146,7 @@ int scsi_host_set_state(struct Scsi_Host *shost, enum scsi_host_state state) } break; } - shost->shost_state = state; + WRITE_ONCE(shost->shost_state, state); return 0; illegal: @@ -276,7 +277,8 @@ int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev, if (error) goto out_disable_runtime_pm; - scsi_host_set_state(shost, SHOST_RUNNING); + scoped_guard(spinlock_irq, shost->host_lock) + scsi_host_set_state(shost, SHOST_RUNNING); get_device(shost->shost_gendev.parent); device_enable_async_suspend(&shost->shost_dev); @@ -350,6 +352,7 @@ EXPORT_SYMBOL(scsi_add_host_with_dma); static void scsi_host_dev_release(struct device *dev) { struct Scsi_Host *shost = dev_to_shost(dev); + enum scsi_host_state state = scsi_get_host_state(shost); struct device *parent = dev->parent; /* Wait for functions invoked through call_rcu(&scmd->rcu, ...) */ @@ -362,7 +365,7 @@ static void scsi_host_dev_release(struct device *dev) if (shost->work_q) destroy_workqueue(shost->work_q); - if (shost->shost_state == SHOST_CREATED) { + if (state == SHOST_CREATED) { /* * Free the shost_dev device name and remove the proc host dir * here if scsi_host_{alloc,put}() have been called but neither @@ -378,7 +381,7 @@ static void scsi_host_dev_release(struct device *dev) ida_free(&host_index_ida, shost->host_no); - if (shost->shost_state != SHOST_CREATED) + if (state != SHOST_CREATED) put_device(parent); kfree(shost); } @@ -411,8 +414,8 @@ struct Scsi_Host *scsi_host_alloc(const struct scsi_host_template *sht, int priv return NULL; shost->host_lock = &shost->default_lock; - spin_lock_init(shost->host_lock); - shost->shost_state = SHOST_CREATED; + scoped_guard(spinlock_init, shost->host_lock) + shost->shost_state = SHOST_CREATED; INIT_LIST_HEAD(&shost->__devices); INIT_LIST_HEAD(&shost->__targets); INIT_LIST_HEAD(&shost->eh_abort_list); @@ -598,7 +601,7 @@ EXPORT_SYMBOL(scsi_host_lookup); **/ struct Scsi_Host *scsi_host_get(struct Scsi_Host *shost) { - if ((shost->shost_state == SHOST_DEL) || + if (scsi_get_host_state(shost) == SHOST_DEL || !get_device(&shost->shost_gendev)) return NULL; return shost; diff --git a/drivers/scsi/leapraid/leapraid_func.c b/drivers/scsi/leapraid/leapraid_func.c index 3e1aeceab994..089d0810bd13 100644 --- a/drivers/scsi/leapraid/leapraid_func.c +++ b/drivers/scsi/leapraid/leapraid_func.c @@ -37,7 +37,7 @@ static noinline bool leapraid_shost_in_recovery(struct Scsi_Host *shost) { enum scsi_host_state state; - state = READ_ONCE(shost->shost_state); + state = scsi_get_host_state(shost); return state == SHOST_RECOVERY || state == SHOST_CANCEL_RECOVERY || state == SHOST_DEL_RECOVERY || diff --git a/drivers/scsi/leapraid/leapraid_os.c b/drivers/scsi/leapraid/leapraid_os.c index 2f3d4ac7490c..a8e1c9f33896 100644 --- a/drivers/scsi/leapraid/leapraid_os.c +++ b/drivers/scsi/leapraid/leapraid_os.c @@ -808,7 +808,7 @@ static bool leapraid_should_queuecommand(struct leapraid_adapter *adapter, goto no_connect; if (sdev_priv->block && - scmd->device->host->shost_state == SHOST_RECOVERY && + scsi_get_host_state(scmd->device->host) == SHOST_RECOVERY && scmd->cmnd[0] == TEST_UNIT_READY) { scsi_build_sense(scmd, 0, UNIT_ATTENTION, LEAPRAID_SCSI_ASC_POWER_ON_RESET, diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index ecd365d78ae3..f0152b043e18 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -3072,7 +3072,7 @@ static int megasas_reset_bus_host(struct scsi_cmnd *scmd) scmd_printk(KERN_INFO, scmd, "SCSI host state: %d SCSI host busy: %d FW outstanding: %d\n", - scmd->device->host->shost_state, + scsi_get_host_state(scmd->device->host), scsi_host_busy(scmd->device->host), atomic_read(&instance->fw_outstanding)); /* diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c index 402d1f35d214..f80a21ec161b 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_os.c +++ b/drivers/scsi/mpi3mr/mpi3mr_os.c @@ -5172,7 +5172,7 @@ static enum scsi_qc_status mpi3mr_qcmd(struct Scsi_Host *shost, /* Avoid error handling escalation when device is removed or blocked */ - if (scmd->device->host->shost_state == SHOST_RECOVERY && + if (scsi_get_host_state(scmd->device->host) == SHOST_RECOVERY && scmd->cmnd[0] == TEST_UNIT_READY && (stgt_priv_data->dev_removed || (dev_handle == MPI3MR_INVALID_DEV_HANDLE))) { scsi_build_sense(scmd, 0, UNIT_ATTENTION, 0x29, 0x07); diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index dea78688cc9b..0e12009a87f6 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -5472,7 +5472,7 @@ static enum scsi_qc_status scsih_qcmd(struct Scsi_Host *shost, * Avoid error handling escallation when device is disconnected */ if (handle == MPT3SAS_INVALID_DEVICE_HANDLE || sas_device_priv_data->block) { - if (scmd->device->host->shost_state == SHOST_RECOVERY && + if (scsi_get_host_state(scmd->device->host) == SHOST_RECOVERY && scmd->cmnd[0] == TEST_UNIT_READY) { scsi_build_sense(scmd, 0, UNIT_ATTENTION, 0x29, 0x07); scsi_done(scmd); diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index d598ab4126f8..c9d9fc7c81fb 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -9411,11 +9411,9 @@ static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd) * This routine finds that if reset host is called in EH * scenario or from some application like sg_reset **/ -static int qla4xxx_is_eh_active(struct Scsi_Host *shost) +static bool qla4xxx_is_eh_active(struct Scsi_Host *shost) { - if (shost->shost_state == SHOST_RECOVERY) - return 1; - return 0; + return scsi_get_host_state(shost) == SHOST_RECOVERY; } /** diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 686cef2406b3..2e07b686090f 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1663,10 +1663,9 @@ static enum scsi_qc_status scsi_dispatch_cmd(struct scsi_cmnd *cmd) goto done; } - if (unlikely(host->shost_state == SHOST_DEL)) { + if (unlikely(scsi_get_host_state(host) == SHOST_DEL)) { cmd->result = (DID_NO_CONNECT << 16); goto done; - } trace_scsi_dispatch_cmd_start(cmd); diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index e27da038603a..3b82e80e807a 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -1169,6 +1169,7 @@ static unsigned char *scsi_inq_str(unsigned char *buf, unsigned char *inq, /** * scsi_probe_and_add_lun - probe a LUN, if a LUN is found add it + * @shost: SCSI host pointer * @starget: pointer to target device structure * @lun: LUN of target device * @bflagsp: store bflags here if not NULL @@ -1188,17 +1189,18 @@ static unsigned char *scsi_inq_str(unsigned char *buf, unsigned char *inq, * attached at the LUN * - SCSI_SCAN_LUN_PRESENT: a new scsi_device was allocated and initialized **/ -static int scsi_probe_and_add_lun(struct scsi_target *starget, +static int scsi_probe_and_add_lun(struct Scsi_Host *shost, + struct scsi_target *starget, u64 lun, blist_flags_t *bflagsp, struct scsi_device **sdevp, enum scsi_scan_mode rescan, void *hostdata) + __must_hold(&shost->scan_mutex) { struct scsi_device *sdev; unsigned char *result; blist_flags_t bflags; int res = SCSI_SCAN_NO_RESPONSE, result_len = 256; - struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); /* * The rescan flag is used as an optimization, the first scan of a @@ -1334,6 +1336,7 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, /** * scsi_sequential_lun_scan - sequentially scan a SCSI target + * @shost: SCSI host pointer * @starget: pointer to target structure to scan * @bflags: black/white list flag for LUN 0 * @scsi_level: Which version of the standard does this device adhere to @@ -1346,13 +1349,14 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, * * Modifies sdevscan->lun. **/ -static void scsi_sequential_lun_scan(struct scsi_target *starget, +static void scsi_sequential_lun_scan(struct Scsi_Host *shost, + struct scsi_target *starget, blist_flags_t bflags, int scsi_level, enum scsi_scan_mode rescan) + __must_hold(&shost->scan_mutex) { uint max_dev_lun; u64 sparse_lun, lun; - struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); SCSI_LOG_SCAN_BUS(3, starget_printk(KERN_INFO, starget, "scsi scan: Sequential scan\n")); @@ -1412,14 +1416,15 @@ static void scsi_sequential_lun_scan(struct scsi_target *starget, * sparse_lun. */ for (lun = 1; lun < max_dev_lun; ++lun) - if ((scsi_probe_and_add_lun(starget, lun, NULL, NULL, rescan, - NULL) != SCSI_SCAN_LUN_PRESENT) && + if (scsi_probe_and_add_lun(shost, starget, lun, NULL, NULL, + rescan, NULL) != SCSI_SCAN_LUN_PRESENT && !sparse_lun) return; } /** * scsi_report_lun_scan - Scan using SCSI REPORT LUN results + * @shost: SCSI host pointer * @starget: which target * @bflags: Zero or a mix of BLIST_NOLUN, BLIST_REPORTLUN2, or BLIST_NOREPORTLUN * @rescan: nonzero if we can skip code only needed on first scan @@ -1438,8 +1443,10 @@ static void scsi_sequential_lun_scan(struct scsi_target *starget, * 0: scan completed (or no memory, so further scanning is futile) * 1: could not scan with REPORT LUN **/ -static int scsi_report_lun_scan(struct scsi_target *starget, blist_flags_t bflags, - enum scsi_scan_mode rescan) +static int scsi_report_lun_scan(struct Scsi_Host *shost, + struct scsi_target *starget, blist_flags_t bflags, + enum scsi_scan_mode rescan) + __must_hold(&shost->scan_mutex) { unsigned char scsi_cmd[MAX_COMMAND_SIZE]; unsigned int length; @@ -1448,7 +1455,6 @@ static int scsi_report_lun_scan(struct scsi_target *starget, blist_flags_t bflag int result; struct scsi_lun *lunp, *lun_data; struct scsi_device *sdev; - struct Scsi_Host *shost = dev_to_shost(&starget->dev); struct scsi_failure failure_defs[] = { { .sense = UNIT_ATTENTION, @@ -1594,7 +1600,7 @@ static int scsi_report_lun_scan(struct scsi_target *starget, blist_flags_t bflag } else { int res; - res = scsi_probe_and_add_lun(starget, + res = scsi_probe_and_add_lun(shost, starget, lun, NULL, NULL, rescan, NULL); if (res == SCSI_SCAN_NO_RESPONSE) { /* @@ -1641,7 +1647,7 @@ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel, scsi_complete_async_scans(); if (scsi_host_scan_allowed(shost) && scsi_autopm_get_host(shost) == 0) { - scsi_probe_and_add_lun(starget, lun, NULL, &sdev, + scsi_probe_and_add_lun(shost, starget, lun, NULL, &sdev, SCSI_SCAN_RESCAN, hostdata); scsi_autopm_put_host(shost); } @@ -1763,10 +1769,11 @@ int scsi_rescan_device(struct scsi_device *sdev) } EXPORT_SYMBOL(scsi_rescan_device); -static void __scsi_scan_target(struct device *parent, unsigned int channel, - unsigned int id, u64 lun, enum scsi_scan_mode rescan) +static void __scsi_scan_target(struct Scsi_Host *shost, struct device *parent, + unsigned int channel, unsigned int id, u64 lun, + enum scsi_scan_mode rescan) + __must_hold(&shost->scan_mutex) { - struct Scsi_Host *shost = dev_to_shost(parent); blist_flags_t bflags = 0; int res; struct scsi_target *starget; @@ -1786,7 +1793,8 @@ static void __scsi_scan_target(struct device *parent, unsigned int channel, /* * Scan for a specific host/chan/id/lun. */ - scsi_probe_and_add_lun(starget, lun, NULL, NULL, rescan, NULL); + scsi_probe_and_add_lun(shost, starget, lun, NULL, NULL, rescan, + NULL); goto out_reap; } @@ -1794,14 +1802,15 @@ static void __scsi_scan_target(struct device *parent, unsigned int channel, * Scan LUN 0, if there is some response, scan further. Ideally, we * would not configure LUN 0 until all LUNs are scanned. */ - res = scsi_probe_and_add_lun(starget, 0, &bflags, NULL, rescan, NULL); + res = scsi_probe_and_add_lun(shost, starget, 0, &bflags, NULL, rescan, + NULL); if (res == SCSI_SCAN_LUN_PRESENT || res == SCSI_SCAN_TARGET_PRESENT) { - if (scsi_report_lun_scan(starget, bflags, rescan) != 0) + if (scsi_report_lun_scan(shost, starget, bflags, rescan) != 0) /* * The REPORT LUN did not scan the target, * do a sequential scan. */ - scsi_sequential_lun_scan(starget, bflags, + scsi_sequential_lun_scan(shost, starget, bflags, starget->scsi_level, rescan); } @@ -1851,7 +1860,7 @@ void scsi_scan_target(struct device *parent, unsigned int channel, scsi_complete_async_scans(); if (scsi_host_scan_allowed(shost) && scsi_autopm_get_host(shost) == 0) { - __scsi_scan_target(parent, channel, id, lun, rescan); + __scsi_scan_target(shost, parent, channel, id, lun, rescan); scsi_autopm_put_host(shost); } mutex_unlock(&shost->scan_mutex); @@ -1861,6 +1870,7 @@ EXPORT_SYMBOL(scsi_scan_target); static void scsi_scan_channel(struct Scsi_Host *shost, unsigned int channel, unsigned int id, u64 lun, enum scsi_scan_mode rescan) + __must_hold(&shost->scan_mutex) { uint order_id; @@ -1882,11 +1892,11 @@ static void scsi_scan_channel(struct Scsi_Host *shost, unsigned int channel, order_id = shost->max_id - id - 1; else order_id = id; - __scsi_scan_target(&shost->shost_gendev, channel, + __scsi_scan_target(shost, &shost->shost_gendev, channel, order_id, lun, rescan); } else - __scsi_scan_target(&shost->shost_gendev, channel, + __scsi_scan_target(shost, &shost->shost_gendev, channel, id, lun, rescan); } diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index dfc3559e7e04..9480432f650b 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -214,8 +214,9 @@ store_shost_state(struct device *dev, struct device_attribute *attr, if (!state) return -EINVAL; - if (scsi_host_set_state(shost, state)) - return -EINVAL; + scoped_guard(spinlock_irq, shost->host_lock) + if (scsi_host_set_state(shost, state)) + return -EINVAL; return count; } @@ -223,7 +224,7 @@ static ssize_t show_shost_state(struct device *dev, struct device_attribute *attr, char *buf) { struct Scsi_Host *shost = class_to_shost(dev); - const char *name = scsi_host_state_name(shost->shost_state); + const char *name = scsi_host_state_name(scsi_get_host_state(shost)); if (!name) return -EINVAL; diff --git a/drivers/ufs/core/Makefile b/drivers/ufs/core/Makefile index ce7d16d2cf35..67ab9ffbdf5d 100644 --- a/drivers/ufs/core/Makefile +++ b/drivers/ufs/core/Makefile @@ -1,5 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 +CONTEXT_ANALYSIS := y + obj-$(CONFIG_SCSI_UFSHCD) += ufshcd-core.o ufshcd-core-y += ufshcd.o ufs-sysfs.o ufs-mcq.o ufs-txeq.o ufshcd-core-$(CONFIG_RPMB) += ufs-rpmb.o diff --git a/drivers/ufs/core/ufs-debugfs.c b/drivers/ufs/core/ufs-debugfs.c index be527209540d..ed1de70e2ec1 100644 --- a/drivers/ufs/core/ufs-debugfs.c +++ b/drivers/ufs/core/ufs-debugfs.c @@ -65,8 +65,10 @@ static int ee_usr_mask_get(void *data, u64 *val) return 0; } +token_context_lock(ufs_debugfs); + static int ufs_debugfs_get_user_access(struct ufs_hba *hba) -__acquires(&hba->host_sem) + __cond_acquires(0, ufs_debugfs) { down(&hba->host_sem); if (!ufshcd_is_user_access_allowed(hba)) { @@ -74,14 +76,16 @@ __acquires(&hba->host_sem) return -EBUSY; } ufshcd_rpm_get_sync(hba); + __acquire(ufs_debugfs); return 0; } static void ufs_debugfs_put_user_access(struct ufs_hba *hba) -__releases(&hba->host_sem) + __releases(ufs_debugfs) { ufshcd_rpm_put_sync(hba); up(&hba->host_sem); + __release(ufs_debugfs); } static int ee_usr_mask_set(void *data, u64 val) diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c index a51e071916cf..67745d2796d0 100644 --- a/drivers/ufs/core/ufshcd.c +++ b/drivers/ufs/core/ufshcd.c @@ -1317,6 +1317,7 @@ static int ufshcd_wait_for_pending_cmds(struct ufs_hba *hba, break; } + __set_current_state(TASK_UNINTERRUPTIBLE); io_schedule_timeout(msecs_to_jiffies(20)); if (ktime_to_us(ktime_sub(ktime_get(), start)) > wait_timeout_us) { @@ -1353,6 +1354,8 @@ static int ufshcd_wait_for_pending_cmds(struct ufs_hba *hba, * On failure, all acquired locks are released and the tagset is unquiesced. */ int ufshcd_pause_command_processing(struct ufs_hba *hba, u64 timeout_us) + __cond_acquires(0, &hba->host->scan_mutex) + __cond_acquires(0, &hba->clk_scaling_lock) { int ret = 0; @@ -1377,6 +1380,8 @@ int ufshcd_pause_command_processing(struct ufs_hba *hba, u64 timeout_us) * This function resumes command submissions. */ void ufshcd_resume_command_processing(struct ufs_hba *hba) + __releases(&hba->clk_scaling_lock) + __releases(&hba->host->scan_mutex) { up_write(&hba->clk_scaling_lock); blk_mq_unquiesce_tagset(&hba->host->tag_set); @@ -1446,6 +1451,9 @@ static int ufshcd_scale_gear(struct ufs_hba *hba, u32 target_gear, bool scale_up * Return: 0 upon success; -EBUSY upon timeout. */ static int ufshcd_clock_scaling_prepare(struct ufs_hba *hba, u64 timeout_us) + __cond_acquires(0, &hba->host->scan_mutex) + __cond_acquires(0, &hba->wb_mutex) + __cond_acquires(0, &hba->clk_scaling_lock) { int ret = 0; /* @@ -1475,6 +1483,9 @@ static int ufshcd_clock_scaling_prepare(struct ufs_hba *hba, u64 timeout_us) } static void ufshcd_clock_scaling_unprepare(struct ufs_hba *hba, int err) + __releases(&hba->clk_scaling_lock) + __releases(&hba->wb_mutex) + __releases(&hba->host->scan_mutex) { up_write(&hba->clk_scaling_lock); mutex_unlock(&hba->wb_mutex); @@ -3304,6 +3315,8 @@ ufshcd_dev_cmd_completion(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) } static void ufshcd_dev_man_lock(struct ufs_hba *hba) + __acquires(&hba->dev_cmd.lock) + __acquires_shared(&hba->clk_scaling_lock) { ufshcd_hold(hba); mutex_lock(&hba->dev_cmd.lock); @@ -3311,6 +3324,8 @@ static void ufshcd_dev_man_lock(struct ufs_hba *hba) } static void ufshcd_dev_man_unlock(struct ufs_hba *hba) + __releases_shared(&hba->clk_scaling_lock) + __releases(&hba->dev_cmd.lock) { up_read(&hba->clk_scaling_lock); mutex_unlock(&hba->dev_cmd.lock); diff --git a/drivers/ufs/host/Makefile b/drivers/ufs/host/Makefile index 65d8bb23ab7b..7d8db67eb23c 100644 --- a/drivers/ufs/host/Makefile +++ b/drivers/ufs/host/Makefile @@ -1,5 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 +CONTEXT_ANALYSIS := y + obj-$(CONFIG_SCSI_UFS_DWC_TC_PCI) += tc-dwc-g210-pci.o ufshcd-dwc.o tc-dwc-g210.o obj-$(CONFIG_SCSI_UFS_DWC_TC_PLATFORM) += tc-dwc-g210-pltfrm.o ufshcd-dwc.o tc-dwc-g210.o obj-$(CONFIG_SCSI_UFS_CDNS_PLATFORM) += cdns-pltfrm.o diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 7e2011830ba4..c9754771bf29 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -2,6 +2,7 @@ #ifndef _SCSI_SCSI_HOST_H #define _SCSI_SCSI_HOST_H +#include #include #include #include @@ -727,7 +728,7 @@ struct Scsi_Host { unsigned int irq; - enum scsi_host_state shost_state; + enum scsi_host_state shost_state __guarded_by(host_lock); /* ldm bits */ struct device shost_gendev, shost_dev; @@ -785,11 +786,18 @@ static inline struct Scsi_Host *dev_to_shost(struct device *dev) return container_of(dev, struct Scsi_Host, shost_gendev); } +static inline enum scsi_host_state scsi_get_host_state(struct Scsi_Host *shost) +{ + return context_unsafe(READ_ONCE(shost->shost_state)); +} + static inline int scsi_host_in_recovery(struct Scsi_Host *shost) { - return shost->shost_state == SHOST_RECOVERY || - shost->shost_state == SHOST_CANCEL_RECOVERY || - shost->shost_state == SHOST_DEL_RECOVERY || + enum scsi_host_state state = scsi_get_host_state(shost); + + return state == SHOST_RECOVERY || + state == SHOST_CANCEL_RECOVERY || + state == SHOST_DEL_RECOVERY || shost->tmf_in_progress; } @@ -835,8 +843,9 @@ static inline struct device *scsi_get_device(struct Scsi_Host *shost) **/ static inline int scsi_host_scan_allowed(struct Scsi_Host *shost) { - return shost->shost_state == SHOST_RUNNING || - shost->shost_state == SHOST_RECOVERY; + enum scsi_host_state state = scsi_get_host_state(shost); + + return state == SHOST_RUNNING || state == SHOST_RECOVERY; } extern void scsi_unblock_requests(struct Scsi_Host *); @@ -940,6 +949,7 @@ static inline unsigned char scsi_host_get_guard(struct Scsi_Host *shost) return shost->prot_guard_type; } -extern int scsi_host_set_state(struct Scsi_Host *, enum scsi_host_state); +int scsi_host_set_state(struct Scsi_Host *shost, enum scsi_host_state state) + __must_hold(shost->host_lock); #endif /* _SCSI_SCSI_HOST_H */