mirror of
https://github.com/torvalds/linux.git
synced 2026-09-23 13:14:02 +02:00
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:
commit
99d1623c08
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 ||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user