Merge patch series "Enable context analysis in the SCSI core and UFS driver"

Bart Van Assche <bvanassche@acm.org> says:

Hi Martin,

This patch series enables context analysis for the SCSI core and the UFS
driver. The advantages are as follows:
 - The compiler (only Clang) verifies whether the lock and unlock calls match
   what has been declared via __must_hold(), __acquires() or __releases().
   This is useful for catching locking bugs in error paths.
 - Support for __guarded_by() is enabled. If a member variable is annotated
   with __guarded_by(lock), the compiler will issue a warning if that member
   variable is accessed without holding 'lock'.

Additionally, a patch is included that suppresses KCSAN complaints about SCSI
host state changes.

More information about lock context analysis is available in the cover letter of
[PATCH v5 00/36] Compiler-Based Context- and Locking-Analysis
(https://lore.kernel.org/lkml/20251219154418.3592607-1-elver@google.com/).

Please consider this patch series for the next merge window.

Thanks,

Bart.

Link: https://patch.msgid.link/cover.1786142946.git.bvanassche@acm.org
Signed-off-by: Martin K. Petersen (Oracle) <mkp@kernel.org>
This commit is contained in:
Martin K. Petersen (Oracle) 2026-08-13 22:10:33 -04:00
commit 99d1623c08
17 changed files with 121 additions and 52 deletions

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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 ||

View File

@ -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,

View File

@ -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));
/*

View File

@ -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);

View File

@ -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);

View File

@ -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;
}
/**

View File

@ -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);

View File

@ -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);
}

View File

@ -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;

View File

@ -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

View File

@ -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)

View File

@ -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);

View File

@ -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

View File

@ -2,6 +2,7 @@
#ifndef _SCSI_SCSI_HOST_H
#define _SCSI_SCSI_HOST_H
#include <linux/cleanup.h>
#include <linux/device.h>
#include <linux/list.h>
#include <linux/types.h>
@ -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 */