summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2023-06-30 11:57:07 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2023-06-30 11:57:07 -0700
commitca7ce08d6a063e0ccb91dc57f9bc213120d0d1a7 (patch)
tree99ce2811fdf52befc76d2cad95b16040423ecd10 /include
parent1546cd4bfda49fd6faad47eb30f4e744e2d79a8f (diff)
parentaf92c02fb2090692f4920ea4b74870940260cf49 (diff)
Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull SCSI updates from James Bottomley: "Updates to the usual drivers (ufs, pm80xx, libata-scsi, smartpqi, lpfc, qla2xxx). We have a couple of major core changes impacting other systems: - Command Duration Limits, which spills into block and ATA - block level Persistent Reservation Operations, which touches block, nvme, target and dm Both of these are added with merge commits containing a cover letter explaining what's going on" * tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (187 commits) scsi: core: Improve warning message in scsi_device_block() scsi: core: Replace scsi_target_block() with scsi_block_targets() scsi: core: Don't wait for quiesce in scsi_device_block() scsi: core: Don't wait for quiesce in scsi_stop_queue() scsi: core: Merge scsi_internal_device_block() and device_block() scsi: sg: Increase number of devices scsi: bsg: Increase number of devices scsi: qla2xxx: Remove unused nvme_ls_waitq wait queue scsi: ufs: ufs-pci: Add support for Intel Arrow Lake scsi: sd: sd_zbc: Use PAGE_SECTORS_SHIFT scsi: ufs: wb: Add explicit flush_threshold sysfs attribute scsi: ufs: ufs-qcom: Switch to the new ICE API scsi: ufs: dt-bindings: qcom: Add ICE phandle scsi: ufs: ufs-mediatek: Set UFSHCD_QUIRK_MCQ_BROKEN_RTC quirk scsi: ufs: ufs-mediatek: Set UFSHCD_QUIRK_MCQ_BROKEN_INTR quirk scsi: ufs: core: Add host quirk UFSHCD_QUIRK_MCQ_BROKEN_RTC scsi: ufs: core: Add host quirk UFSHCD_QUIRK_MCQ_BROKEN_INTR scsi: ufs: core: Remove dedicated hwq for dev command scsi: ufs: core: mcq: Fix the incorrect OCS value for the device command scsi: ufs: dt-bindings: samsung,exynos: Drop unneeded quotes ...
Diffstat (limited to 'include')
-rw-r--r--include/linux/ata.h11
-rw-r--r--include/linux/blk_types.h10
-rw-r--r--include/linux/libata.h42
-rw-r--r--include/linux/nvme.h51
-rw-r--r--include/linux/pr.h25
-rw-r--r--include/scsi/scsi_cmnd.h5
-rw-r--r--include/scsi/scsi_common.h13
-rw-r--r--include/scsi/scsi_device.h20
-rw-r--r--include/scsi/scsi_host.h6
-rw-r--r--include/scsi/scsi_proto.h5
-rw-r--r--include/target/target_core_backend.h8
-rw-r--r--include/target/target_core_base.h3
-rw-r--r--include/trace/events/scsi.h21
-rw-r--r--include/uapi/linux/ioprio.h100
-rw-r--r--include/ufs/ufshcd.h22
-rw-r--r--include/ufs/ufshci.h25
16 files changed, 309 insertions, 58 deletions
diff --git a/include/linux/ata.h b/include/linux/ata.h
index c224dbddb9b2..792e10a09787 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -322,15 +322,21 @@ enum {
ATA_LOG_SATA_NCQ = 0x10,
ATA_LOG_NCQ_NON_DATA = 0x12,
ATA_LOG_NCQ_SEND_RECV = 0x13,
+ ATA_LOG_CDL = 0x18,
+ ATA_LOG_CDL_SIZE = ATA_SECT_SIZE,
ATA_LOG_IDENTIFY_DEVICE = 0x30,
+ ATA_LOG_SENSE_NCQ = 0x0F,
+ ATA_LOG_SENSE_NCQ_SIZE = ATA_SECT_SIZE * 2,
ATA_LOG_CONCURRENT_POSITIONING_RANGES = 0x47,
/* Identify device log pages: */
+ ATA_LOG_SUPPORTED_CAPABILITIES = 0x03,
+ ATA_LOG_CURRENT_SETTINGS = 0x04,
ATA_LOG_SECURITY = 0x06,
ATA_LOG_SATA_SETTINGS = 0x08,
ATA_LOG_ZONED_INFORMATION = 0x09,
- /* Identify device SATA settings log:*/
+ /* Identify device SATA settings log: */
ATA_LOG_DEVSLP_OFFSET = 0x30,
ATA_LOG_DEVSLP_SIZE = 0x08,
ATA_LOG_DEVSLP_MDAT = 0x00,
@@ -415,6 +421,8 @@ enum {
SETFEATURES_SATA_ENABLE = 0x10, /* Enable use of SATA feature */
SETFEATURES_SATA_DISABLE = 0x90, /* Disable use of SATA feature */
+ SETFEATURES_CDL = 0x0d, /* Enable/disable cmd duration limits */
+
/* SETFEATURE Sector counts for SATA features */
SATA_FPDMA_OFFSET = 0x01, /* FPDMA non-zero buffer offsets */
SATA_FPDMA_AA = 0x02, /* FPDMA Setup FIS Auto-Activate */
@@ -425,6 +433,7 @@ enum {
SATA_DEVSLP = 0x09, /* Device Sleep */
SETFEATURE_SENSE_DATA = 0xC3, /* Sense Data Reporting feature */
+ SETFEATURE_SENSE_DATA_SUCC_NCQ = 0xC4, /* Sense Data for successful NCQ commands */
/* feature values for SET_MAX */
ATA_SET_MAX_ADDR = 0x00,
diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h
index 752a54e3284b..0bad62cca3d0 100644
--- a/include/linux/blk_types.h
+++ b/include/linux/blk_types.h
@@ -103,7 +103,7 @@ typedef u16 blk_short_t;
#define BLK_STS_NOSPC ((__force blk_status_t)3)
#define BLK_STS_TRANSPORT ((__force blk_status_t)4)
#define BLK_STS_TARGET ((__force blk_status_t)5)
-#define BLK_STS_NEXUS ((__force blk_status_t)6)
+#define BLK_STS_RESV_CONFLICT ((__force blk_status_t)6)
#define BLK_STS_MEDIUM ((__force blk_status_t)7)
#define BLK_STS_PROTECTION ((__force blk_status_t)8)
#define BLK_STS_RESOURCE ((__force blk_status_t)9)
@@ -173,6 +173,12 @@ typedef u16 blk_short_t;
*/
#define BLK_STS_OFFLINE ((__force blk_status_t)17)
+/*
+ * BLK_STS_DURATION_LIMIT is returned from the driver when the target device
+ * aborted the command because it exceeded one of its Command Duration Limits.
+ */
+#define BLK_STS_DURATION_LIMIT ((__force blk_status_t)18)
+
/**
* blk_path_error - returns true if error may be path related
* @error: status the request was completed with
@@ -191,7 +197,7 @@ static inline bool blk_path_error(blk_status_t error)
case BLK_STS_NOTSUPP:
case BLK_STS_NOSPC:
case BLK_STS_TARGET:
- case BLK_STS_NEXUS:
+ case BLK_STS_RESV_CONFLICT:
case BLK_STS_MEDIUM:
case BLK_STS_PROTECTION:
return false;
diff --git a/include/linux/libata.h b/include/linux/libata.h
index b19c6028221d..820f7a3a2749 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -94,17 +94,19 @@ enum {
ATA_DFLAG_DMADIR = (1 << 10), /* device requires DMADIR */
ATA_DFLAG_NCQ_SEND_RECV = (1 << 11), /* device supports NCQ SEND and RECV */
ATA_DFLAG_NCQ_PRIO = (1 << 12), /* device supports NCQ priority */
- ATA_DFLAG_CFG_MASK = (1 << 13) - 1,
-
- ATA_DFLAG_PIO = (1 << 13), /* device limited to PIO mode */
- ATA_DFLAG_NCQ_OFF = (1 << 14), /* device limited to non-NCQ mode */
- ATA_DFLAG_SLEEPING = (1 << 15), /* device is sleeping */
- ATA_DFLAG_DUBIOUS_XFER = (1 << 16), /* data transfer not verified */
- ATA_DFLAG_NO_UNLOAD = (1 << 17), /* device doesn't support unload */
- ATA_DFLAG_UNLOCK_HPA = (1 << 18), /* unlock HPA */
- ATA_DFLAG_INIT_MASK = (1 << 19) - 1,
-
- ATA_DFLAG_NCQ_PRIO_ENABLED = (1 << 19), /* Priority cmds sent to dev */
+ ATA_DFLAG_CDL = (1 << 13), /* supports cmd duration limits */
+ ATA_DFLAG_CFG_MASK = (1 << 14) - 1,
+
+ ATA_DFLAG_PIO = (1 << 14), /* device limited to PIO mode */
+ ATA_DFLAG_NCQ_OFF = (1 << 15), /* device limited to non-NCQ mode */
+ ATA_DFLAG_SLEEPING = (1 << 16), /* device is sleeping */
+ ATA_DFLAG_DUBIOUS_XFER = (1 << 17), /* data transfer not verified */
+ ATA_DFLAG_NO_UNLOAD = (1 << 18), /* device doesn't support unload */
+ ATA_DFLAG_UNLOCK_HPA = (1 << 19), /* unlock HPA */
+ ATA_DFLAG_INIT_MASK = (1 << 20) - 1,
+
+ ATA_DFLAG_NCQ_PRIO_ENABLED = (1 << 20), /* Priority cmds sent to dev */
+ ATA_DFLAG_CDL_ENABLED = (1 << 21), /* cmd duration limits is enabled */
ATA_DFLAG_DETACH = (1 << 24),
ATA_DFLAG_DETACHED = (1 << 25),
ATA_DFLAG_DA = (1 << 26), /* device supports Device Attention */
@@ -115,7 +117,8 @@ enum {
ATA_DFLAG_FEATURES_MASK = (ATA_DFLAG_TRUSTED | ATA_DFLAG_DA | \
ATA_DFLAG_DEVSLP | ATA_DFLAG_NCQ_SEND_RECV | \
- ATA_DFLAG_NCQ_PRIO | ATA_DFLAG_FUA),
+ ATA_DFLAG_NCQ_PRIO | ATA_DFLAG_FUA | \
+ ATA_DFLAG_CDL),
ATA_DEV_UNKNOWN = 0, /* unknown device */
ATA_DEV_ATA = 1, /* ATA device */
@@ -206,10 +209,12 @@ enum {
ATA_QCFLAG_CLEAR_EXCL = (1 << 5), /* clear excl_link on completion */
ATA_QCFLAG_QUIET = (1 << 6), /* don't report device error */
ATA_QCFLAG_RETRY = (1 << 7), /* retry after failure */
+ ATA_QCFLAG_HAS_CDL = (1 << 8), /* qc has CDL a descriptor set */
ATA_QCFLAG_EH = (1 << 16), /* cmd aborted and owned by EH */
ATA_QCFLAG_SENSE_VALID = (1 << 17), /* sense data valid */
ATA_QCFLAG_EH_SCHEDULED = (1 << 18), /* EH scheduled (obsolete) */
+ ATA_QCFLAG_EH_SUCCESS_CMD = (1 << 19), /* EH should fetch sense for this successful cmd */
/* host set flags */
ATA_HOST_SIMPLEX = (1 << 0), /* Host is simplex, one DMA channel per host only */
@@ -308,8 +313,10 @@ enum {
ATA_EH_RESET = ATA_EH_SOFTRESET | ATA_EH_HARDRESET,
ATA_EH_ENABLE_LINK = (1 << 3),
ATA_EH_PARK = (1 << 5), /* unload heads and stop I/O */
+ ATA_EH_GET_SUCCESS_SENSE = (1 << 6), /* Get sense data for successful cmd */
- ATA_EH_PERDEV_MASK = ATA_EH_REVALIDATE | ATA_EH_PARK,
+ ATA_EH_PERDEV_MASK = ATA_EH_REVALIDATE | ATA_EH_PARK |
+ ATA_EH_GET_SUCCESS_SENSE,
ATA_EH_ALL_ACTIONS = ATA_EH_REVALIDATE | ATA_EH_RESET |
ATA_EH_ENABLE_LINK,
@@ -709,6 +716,9 @@ struct ata_device {
/* Concurrent positioning ranges */
struct ata_cpr_log *cpr_log;
+ /* Command Duration Limits log support */
+ u8 cdl[ATA_LOG_CDL_SIZE];
+
/* error history */
int spdn_cnt;
/* ering is CLEAR_END, read comment above CLEAR_END */
@@ -860,6 +870,7 @@ struct ata_port {
struct ata_acpi_gtm __acpi_init_gtm; /* use ata_acpi_init_gtm() */
#endif
/* owned by EH */
+ u8 *ncq_sense_buf;
u8 sector_buf[ATA_SECT_SIZE] ____cacheline_aligned;
};
@@ -1178,6 +1189,7 @@ extern int sata_link_hardreset(struct ata_link *link,
bool *online, int (*check_ready)(struct ata_link *));
extern int sata_link_resume(struct ata_link *link, const unsigned long *params,
unsigned long deadline);
+extern int ata_eh_read_sense_success_ncq_log(struct ata_link *link);
extern void ata_eh_analyze_ncq_error(struct ata_link *link);
#else
static inline const unsigned long *
@@ -1215,6 +1227,10 @@ static inline int sata_link_resume(struct ata_link *link,
{
return -EOPNOTSUPP;
}
+static inline int ata_eh_read_sense_success_ncq_log(struct ata_link *link)
+{
+ return -EOPNOTSUPP;
+}
static inline void ata_eh_analyze_ncq_error(struct ata_link *link) { }
#endif
extern int sata_link_debounce(struct ata_link *link,
diff --git a/include/linux/nvme.h b/include/linux/nvme.h
index 779507ac750b..182b6d614eb1 100644
--- a/include/linux/nvme.h
+++ b/include/linux/nvme.h
@@ -759,20 +759,55 @@ enum {
NVME_LBART_ATTRIB_HIDE = 1 << 1,
};
+enum nvme_pr_type {
+ NVME_PR_WRITE_EXCLUSIVE = 1,
+ NVME_PR_EXCLUSIVE_ACCESS = 2,
+ NVME_PR_WRITE_EXCLUSIVE_REG_ONLY = 3,
+ NVME_PR_EXCLUSIVE_ACCESS_REG_ONLY = 4,
+ NVME_PR_WRITE_EXCLUSIVE_ALL_REGS = 5,
+ NVME_PR_EXCLUSIVE_ACCESS_ALL_REGS = 6,
+};
+
+enum nvme_eds {
+ NVME_EXTENDED_DATA_STRUCT = 0x1,
+};
+
+struct nvme_registered_ctrl {
+ __le16 cntlid;
+ __u8 rcsts;
+ __u8 rsvd3[5];
+ __le64 hostid;
+ __le64 rkey;
+};
+
struct nvme_reservation_status {
__le32 gen;
__u8 rtype;
__u8 regctl[2];
__u8 resv5[2];
__u8 ptpls;
- __u8 resv10[13];
- struct {
- __le16 cntlid;
- __u8 rcsts;
- __u8 resv3[5];
- __le64 hostid;
- __le64 rkey;
- } regctl_ds[];
+ __u8 resv10[14];
+ struct nvme_registered_ctrl regctl_ds[];
+};
+
+struct nvme_registered_ctrl_ext {
+ __le16 cntlid;
+ __u8 rcsts;
+ __u8 rsvd3[5];
+ __le64 rkey;
+ __u8 hostid[16];
+ __u8 rsvd32[32];
+};
+
+struct nvme_reservation_status_ext {
+ __le32 gen;
+ __u8 rtype;
+ __u8 regctl[2];
+ __u8 resv5[2];
+ __u8 ptpls;
+ __u8 resv10[14];
+ __u8 rsvd24[40];
+ struct nvme_registered_ctrl_ext regctl_eds[];
};
enum nvme_async_event_type {
diff --git a/include/linux/pr.h b/include/linux/pr.h
index 94ceec713afe..3003daec28a5 100644
--- a/include/linux/pr.h
+++ b/include/linux/pr.h
@@ -4,6 +4,18 @@
#include <uapi/linux/pr.h>
+struct pr_keys {
+ u32 generation;
+ u32 num_keys;
+ u64 keys[];
+};
+
+struct pr_held_reservation {
+ u64 key;
+ u32 generation;
+ enum pr_type type;
+};
+
struct pr_ops {
int (*pr_register)(struct block_device *bdev, u64 old_key, u64 new_key,
u32 flags);
@@ -14,6 +26,19 @@ struct pr_ops {
int (*pr_preempt)(struct block_device *bdev, u64 old_key, u64 new_key,
enum pr_type type, bool abort);
int (*pr_clear)(struct block_device *bdev, u64 key);
+ /*
+ * pr_read_keys - Read the registered keys and return them in the
+ * pr_keys->keys array. The keys array will have been allocated at the
+ * end of the pr_keys struct, and pr_keys->num_keys must be set to the
+ * number of keys the array can hold. If there are more than can fit
+ * in the array, success will still be returned and pr_keys->num_keys
+ * will reflect the total number of keys the device contains, so the
+ * caller can retry with a larger array.
+ */
+ int (*pr_read_keys)(struct block_device *bdev,
+ struct pr_keys *keys_info);
+ int (*pr_read_reservation)(struct block_device *bdev,
+ struct pr_held_reservation *rsv);
};
#endif /* LINUX_PR_H */
diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
index c2cb5f69635c..526def14e7fb 100644
--- a/include/scsi/scsi_cmnd.h
+++ b/include/scsi/scsi_cmnd.h
@@ -52,6 +52,11 @@ struct scsi_pointer {
#define SCMD_TAGGED (1 << 0)
#define SCMD_INITIALIZED (1 << 1)
#define SCMD_LAST (1 << 2)
+/*
+ * libata uses SCSI EH to fetch sense data for successful commands.
+ * SCSI EH should not overwrite scmd->result when SCMD_FORCE_EH_SUCCESS is set.
+ */
+#define SCMD_FORCE_EH_SUCCESS (1 << 3)
#define SCMD_FAIL_IF_RECOVERING (1 << 4)
/* flags preserved across unprep / reprep */
#define SCMD_PRESERVED_FLAGS (SCMD_INITIALIZED | SCMD_FAIL_IF_RECOVERING)
diff --git a/include/scsi/scsi_common.h b/include/scsi/scsi_common.h
index 5b567b43e1b1..fb58715fac86 100644
--- a/include/scsi/scsi_common.h
+++ b/include/scsi/scsi_common.h
@@ -7,8 +7,21 @@
#define _SCSI_COMMON_H_
#include <linux/types.h>
+#include <uapi/linux/pr.h>
#include <scsi/scsi_proto.h>
+enum scsi_pr_type {
+ SCSI_PR_WRITE_EXCLUSIVE = 0x01,
+ SCSI_PR_EXCLUSIVE_ACCESS = 0x03,
+ SCSI_PR_WRITE_EXCLUSIVE_REG_ONLY = 0x05,
+ SCSI_PR_EXCLUSIVE_ACCESS_REG_ONLY = 0x06,
+ SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS = 0x07,
+ SCSI_PR_EXCLUSIVE_ACCESS_ALL_REGS = 0x08,
+};
+
+enum scsi_pr_type block_pr_type_to_scsi(enum pr_type type);
+enum pr_type scsi_pr_type_to_block(enum scsi_pr_type type);
+
static inline unsigned
scsi_varlen_cdb_length(const void *hdr)
{
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index f10a008e5bfa..75b2235b99e2 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -218,6 +218,9 @@ struct scsi_device {
unsigned silence_suspend:1; /* Do not print runtime PM related messages */
unsigned no_vpd_size:1; /* No VPD size reported in header */
+ unsigned cdl_supported:1; /* Command duration limits supported */
+ unsigned cdl_enable:1; /* Enable/disable Command duration limits */
+
unsigned int queue_stopped; /* request queue is quiesced */
bool offline_already; /* Device offline message logged */
@@ -364,6 +367,8 @@ extern int scsi_register_device_handler(struct scsi_device_handler *scsi_dh);
extern void scsi_remove_device(struct scsi_device *);
extern int scsi_unregister_device_handler(struct scsi_device_handler *scsi_dh);
void scsi_attach_vpd(struct scsi_device *sdev);
+void scsi_cdl_check(struct scsi_device *sdev);
+int scsi_cdl_enable(struct scsi_device *sdev, bool enable);
extern struct scsi_device *scsi_device_from_queue(struct request_queue *q);
extern int __must_check scsi_device_get(struct scsi_device *);
@@ -421,10 +426,10 @@ extern int scsi_track_queue_full(struct scsi_device *, int);
extern int scsi_set_medium_removal(struct scsi_device *, char);
-extern int scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage,
- unsigned char *buffer, int len, int timeout,
- int retries, struct scsi_mode_data *data,
- struct scsi_sense_hdr *);
+int scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage,
+ int subpage, unsigned char *buffer, int len, int timeout,
+ int retries, struct scsi_mode_data *data,
+ struct scsi_sense_hdr *);
extern int scsi_mode_select(struct scsi_device *sdev, int pf, int sp,
unsigned char *buffer, int len, int timeout,
int retries, struct scsi_mode_data *data,
@@ -433,8 +438,9 @@ extern int scsi_test_unit_ready(struct scsi_device *sdev, int timeout,
int retries, struct scsi_sense_hdr *sshdr);
extern int scsi_get_vpd_page(struct scsi_device *, u8 page, unsigned char *buf,
int buf_len);
-extern int scsi_report_opcode(struct scsi_device *sdev, unsigned char *buffer,
- unsigned int len, unsigned char opcode);
+int scsi_report_opcode(struct scsi_device *sdev, unsigned char *buffer,
+ unsigned int len, unsigned char opcode,
+ unsigned short sa);
extern int scsi_device_set_state(struct scsi_device *sdev,
enum scsi_device_state state);
extern struct scsi_event *sdev_evt_alloc(enum scsi_device_event evt_type,
@@ -450,7 +456,7 @@ extern void scsi_scan_target(struct device *parent, unsigned int channel,
unsigned int id, u64 lun,
enum scsi_scan_mode rescan);
extern void scsi_target_reap(struct scsi_target *);
-extern void scsi_target_block(struct device *);
+void scsi_block_targets(struct Scsi_Host *shost, struct device *dev);
extern void scsi_target_unblock(struct device *, enum scsi_device_state);
extern void scsi_remove_target(struct device *);
extern const char *scsi_device_state_name(enum scsi_device_state);
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index 0f29799efa02..70b7475dcf56 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -458,6 +458,9 @@ struct scsi_host_template {
/* True if the host uses host-wide tagspace */
unsigned host_tagset:1;
+ /* The queuecommand callback may block. See also BLK_MQ_F_BLOCKING. */
+ unsigned queuecommand_may_block:1;
+
/*
* Countdown for host blocking with no commands outstanding.
*/
@@ -653,6 +656,9 @@ struct Scsi_Host {
/* True if the host uses host-wide tagspace */
unsigned host_tagset:1;
+ /* The queuecommand callback may block. See also BLK_MQ_F_BLOCKING. */
+ unsigned queuecommand_may_block:1;
+
/* Host responded with short (<36 bytes) INQUIRY result */
unsigned short_inquiry:1;
diff --git a/include/scsi/scsi_proto.h b/include/scsi/scsi_proto.h
index fbe5bdfe4d6e..07d65c1f59db 100644
--- a/include/scsi/scsi_proto.h
+++ b/include/scsi/scsi_proto.h
@@ -151,6 +151,11 @@
#define ZO_FINISH_ZONE 0x02
#define ZO_OPEN_ZONE 0x03
#define ZO_RESET_WRITE_POINTER 0x04
+/* values for PR in service action */
+#define READ_KEYS 0x00
+#define READ_RESERVATION 0x01
+#define REPORT_CAPABILITES 0x02
+#define READ_FULL_STATUS 0x03
/* values for variable length command */
#define XDREAD_32 0x03
#define XDWRITE_32 0x04
diff --git a/include/target/target_core_backend.h b/include/target/target_core_backend.h
index a3c193df25b3..739df993aa5e 100644
--- a/include/target/target_core_backend.h
+++ b/include/target/target_core_backend.h
@@ -62,13 +62,17 @@ struct target_backend_ops {
struct configfs_attribute **tb_dev_action_attrs;
};
-struct sbc_ops {
+struct exec_cmd_ops {
sense_reason_t (*execute_rw)(struct se_cmd *cmd, struct scatterlist *,
u32, enum dma_data_direction);
sense_reason_t (*execute_sync_cache)(struct se_cmd *cmd);
sense_reason_t (*execute_write_same)(struct se_cmd *cmd);
sense_reason_t (*execute_unmap)(struct se_cmd *cmd,
sector_t lba, sector_t nolb);
+ sense_reason_t (*execute_pr_out)(struct se_cmd *cmd, u8 sa, u64 key,
+ u64 sa_key, u8 type, bool aptpl);
+ sense_reason_t (*execute_pr_in)(struct se_cmd *cmd, u8 sa,
+ unsigned char *param_data);
};
int transport_backend_register(const struct target_backend_ops *);
@@ -86,7 +90,7 @@ sense_reason_t spc_emulate_report_luns(struct se_cmd *cmd);
sense_reason_t spc_emulate_inquiry_std(struct se_cmd *, unsigned char *);
sense_reason_t spc_emulate_evpd_83(struct se_cmd *, unsigned char *);
-sense_reason_t sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops);
+sense_reason_t sbc_parse_cdb(struct se_cmd *cmd, struct exec_cmd_ops *ops);
u32 sbc_get_device_rev(struct se_device *dev);
u32 sbc_get_device_type(struct se_device *dev);
sector_t sbc_get_write_same_sectors(struct se_cmd *cmd);
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
index 5f8e96f1516f..159567359bbb 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -880,7 +880,8 @@ struct target_opcode_descriptor {
u8 specific_timeout;
u16 nominal_timeout;
u16 recommended_timeout;
- bool (*enabled)(struct se_cmd *cmd);
+ bool (*enabled)(struct target_opcode_descriptor *descr,
+ struct se_cmd *cmd);
void (*update_usage_bits)(u8 *usage_bits,
struct se_device *dev);
u8 usage_bits[];
diff --git a/include/trace/events/scsi.h b/include/trace/events/scsi.h
index a2c7befd451a..8e2d9b1b0e77 100644
--- a/include/trace/events/scsi.h
+++ b/include/trace/events/scsi.h
@@ -269,9 +269,14 @@ DECLARE_EVENT_CLASS(scsi_cmd_done_timeout_template,
__field( unsigned int, prot_sglen )
__field( unsigned char, prot_op )
__dynamic_array(unsigned char, cmnd, cmd->cmd_len)
+ __field( u8, sense_key )
+ __field( u8, asc )
+ __field( u8, ascq )
),
TP_fast_assign(
+ struct scsi_sense_hdr sshdr;
+
__entry->host_no = cmd->device->host->host_no;
__entry->channel = cmd->device->channel;
__entry->id = cmd->device->id;
@@ -285,11 +290,22 @@ DECLARE_EVENT_CLASS(scsi_cmd_done_timeout_template,
__entry->prot_sglen = scsi_prot_sg_count(cmd);
__entry->prot_op = scsi_get_prot_op(cmd);
memcpy(__get_dynamic_array(cmnd), cmd->cmnd, cmd->cmd_len);
+ if (cmd->sense_buffer && SCSI_SENSE_VALID(cmd) &&
+ scsi_command_normalize_sense(cmd, &sshdr)) {
+ __entry->sense_key = sshdr.sense_key;
+ __entry->asc = sshdr.asc;
+ __entry->ascq = sshdr.ascq;
+ } else {
+ __entry->sense_key = 0;
+ __entry->asc = 0;
+ __entry->ascq = 0;
+ }
),
TP_printk("host_no=%u channel=%u id=%u lun=%u data_sgl=%u prot_sgl=%u " \
"prot_op=%s driver_tag=%d scheduler_tag=%d cmnd=(%s %s raw=%s) " \
- "result=(driver=%s host=%s message=%s status=%s)",
+ "result=(driver=%s host=%s message=%s status=%s) "
+ "sense=(key=%#x asc=%#x ascq=%#x)",
__entry->host_no, __entry->channel, __entry->id,
__entry->lun, __entry->data_sglen, __entry->prot_sglen,
show_prot_op_name(__entry->prot_op), __entry->driver_tag,
@@ -299,7 +315,8 @@ DECLARE_EVENT_CLASS(scsi_cmd_done_timeout_template,
"DRIVER_OK",
show_hostbyte_name(((__entry->result) >> 16) & 0xff),
"COMMAND_COMPLETE",
- show_statusbyte_name(__entry->result & 0xff))
+ show_statusbyte_name(__entry->result & 0xff),
+ __entry->sense_key, __entry->asc, __entry->ascq)
);
DEFINE_EVENT(scsi_cmd_done_timeout_template, scsi_dispatch_cmd_done,
diff --git a/include/uapi/linux/ioprio.h b/include/uapi/linux/ioprio.h
index f70f2596a6bf..99440b2e8c35 100644
--- a/include/uapi/linux/ioprio.h
+++ b/include/uapi/linux/ioprio.h
@@ -2,22 +2,23 @@
#ifndef _UAPI_LINUX_IOPRIO_H
#define _UAPI_LINUX_IOPRIO_H
+#include <linux/stddef.h>
+#include <linux/types.h>
+
/*
* Gives us 8 prio classes with 13-bits of data for each class
*/
#define IOPRIO_CLASS_SHIFT 13
-#define IOPRIO_CLASS_MASK 0x07
+#define IOPRIO_NR_CLASSES 8
+#define IOPRIO_CLASS_MASK (IOPRIO_NR_CLASSES - 1)
#define IOPRIO_PRIO_MASK ((1UL << IOPRIO_CLASS_SHIFT) - 1)
#define IOPRIO_PRIO_CLASS(ioprio) \
(((ioprio) >> IOPRIO_CLASS_SHIFT) & IOPRIO_CLASS_MASK)
#define IOPRIO_PRIO_DATA(ioprio) ((ioprio) & IOPRIO_PRIO_MASK)
-#define IOPRIO_PRIO_VALUE(class, data) \
- ((((class) & IOPRIO_CLASS_MASK) << IOPRIO_CLASS_SHIFT) | \
- ((data) & IOPRIO_PRIO_MASK))
/*
- * These are the io priority groups as implemented by the BFQ and mq-deadline
+ * These are the io priority classes as implemented by the BFQ and mq-deadline
* schedulers. RT is the realtime class, it always gets premium service. For
* ATA disks supporting NCQ IO priority, RT class IOs will be processed using
* high priority NCQ commands. BE is the best-effort scheduling class, the
@@ -25,18 +26,30 @@
* served when no one else is using the disk.
*/
enum {
- IOPRIO_CLASS_NONE,
- IOPRIO_CLASS_RT,
- IOPRIO_CLASS_BE,
- IOPRIO_CLASS_IDLE,
+ IOPRIO_CLASS_NONE = 0,
+ IOPRIO_CLASS_RT = 1,
+ IOPRIO_CLASS_BE = 2,
+ IOPRIO_CLASS_IDLE = 3,
+
+ /* Special class to indicate an invalid ioprio value */
+ IOPRIO_CLASS_INVALID = 7,
};
/*
- * The RT and BE priority classes both support up to 8 priority levels.
+ * The RT and BE priority classes both support up to 8 priority levels that
+ * can be specified using the lower 3-bits of the priority data.
*/
-#define IOPRIO_NR_LEVELS 8
-#define IOPRIO_BE_NR IOPRIO_NR_LEVELS
+#define IOPRIO_LEVEL_NR_BITS 3
+#define IOPRIO_NR_LEVELS (1 << IOPRIO_LEVEL_NR_BITS)
+#define IOPRIO_LEVEL_MASK (IOPRIO_NR_LEVELS - 1)
+#define IOPRIO_PRIO_LEVEL(ioprio) ((ioprio) & IOPRIO_LEVEL_MASK)
+
+#define IOPRIO_BE_NR IOPRIO_NR_LEVELS
+/*
+ * Possible values for the "which" argument of the ioprio_get() and
+ * ioprio_set() system calls (see "man ioprio_set").
+ */
enum {
IOPRIO_WHO_PROCESS = 1,
IOPRIO_WHO_PGRP,
@@ -44,9 +57,70 @@ enum {
};
/*
- * Fallback BE priority level.
+ * Fallback BE class priority level.
*/
#define IOPRIO_NORM 4
#define IOPRIO_BE_NORM IOPRIO_NORM
+/*
+ * The 10 bits between the priority class and the priority level are used to
+ * optionally define I/O hints for any combination of I/O priority class and
+ * level. Depending on the kernel configuration, I/O scheduler being used and
+ * the target I/O device being used, hints can influence how I/Os are processed
+ * without affecting the I/O scheduling ordering defined by the I/O priority
+ * class and level.
+ */
+#define IOPRIO_HINT_SHIFT IOPRIO_LEVEL_NR_BITS
+#define IOPRIO_HINT_NR_BITS 10
+#define IOPRIO_NR_HINTS (1 << IOPRIO_HINT_NR_BITS)
+#define IOPRIO_HINT_MASK (IOPRIO_NR_HINTS - 1)
+#define IOPRIO_PRIO_HINT(ioprio) \
+ (((ioprio) >> IOPRIO_HINT_SHIFT) & IOPRIO_HINT_MASK)
+
+/*
+ * I/O hints.
+ */
+enum {
+ /* No hint */
+ IOPRIO_HINT_NONE = 0,
+
+ /*
+ * Device command duration limits: indicate to the device a desired
+ * duration limit for the commands that will be used to process an I/O.
+ * These will currently only be effective for SCSI and ATA devices that
+ * support the command duration limits feature. If this feature is
+ * enabled, then the commands issued to the device to process an I/O with
+ * one of these hints set will have the duration limit index (dld field)
+ * set to the value of the hint.
+ */
+ IOPRIO_HINT_DEV_DURATION_LIMIT_1 = 1,
+ IOPRIO_HINT_DEV_DURATION_LIMIT_2 = 2,
+ IOPRIO_HINT_DEV_DURATION_LIMIT_3 = 3,
+ IOPRIO_HINT_DEV_DURATION_LIMIT_4 = 4,
+ IOPRIO_HINT_DEV_DURATION_LIMIT_5 = 5,
+ IOPRIO_HINT_DEV_DURATION_LIMIT_6 = 6,
+ IOPRIO_HINT_DEV_DURATION_LIMIT_7 = 7,
+};
+
+#define IOPRIO_BAD_VALUE(val, max) ((val) < 0 || (val) >= (max))
+
+/*
+ * Return an I/O priority value based on a class, a level and a hint.
+ */
+static __always_inline __u16 ioprio_value(int class, int level, int hint)
+{
+ if (IOPRIO_BAD_VALUE(class, IOPRIO_NR_CLASSES) ||
+ IOPRIO_BAD_VALUE(level, IOPRIO_NR_LEVELS) ||
+ IOPRIO_BAD_VALUE(hint, IOPRIO_NR_HINTS))
+ return IOPRIO_CLASS_INVALID << IOPRIO_CLASS_SHIFT;
+
+ return (class << IOPRIO_CLASS_SHIFT) |
+ (hint << IOPRIO_HINT_SHIFT) | level;
+}
+
+#define IOPRIO_PRIO_VALUE(class, level) \
+ ioprio_value(class, level, IOPRIO_HINT_NONE)
+#define IOPRIO_PRIO_VALUE_HINT(class, level, hint) \
+ ioprio_value(class, level, hint)
+
#endif /* _UAPI_LINUX_IOPRIO_H */
diff --git a/include/ufs/ufshcd.h b/include/ufs/ufshcd.h
index df1d04f7a542..6dc11fa0ebb1 100644
--- a/include/ufs/ufshcd.h
+++ b/include/ufs/ufshcd.h
@@ -225,7 +225,6 @@ struct ufs_dev_cmd {
struct mutex lock;
struct completion *complete;
struct ufs_query query;
- struct cq_entry *cqe;
};
/**
@@ -611,6 +610,19 @@ enum ufshcd_quirks {
* to reinit the device after switching to maximum gear.
*/
UFSHCD_QUIRK_REINIT_AFTER_MAX_GEAR_SWITCH = 1 << 19,
+
+ /*
+ * Some host raises interrupt (per queue) in addition to
+ * CQES (traditional) when ESI is disabled.
+ * Enable this quirk will disable CQES and use per queue interrupt.
+ */
+ UFSHCD_QUIRK_MCQ_BROKEN_INTR = 1 << 20,
+
+ /*
+ * Some host does not implement SQ Run Time Command (SQRTC) register
+ * thus need this quirk to skip related flow.
+ */
+ UFSHCD_QUIRK_MCQ_BROKEN_RTC = 1 << 21,
};
enum ufshcd_caps {
@@ -1087,6 +1099,7 @@ struct ufs_hba {
* @cq_tail_slot: current slot to which CQ tail pointer is pointing
* @cq_head_slot: current slot to which CQ head pointer is pointing
* @cq_lock: Synchronize between multiple polling instances
+ * @sq_mutex: prevent submission queue concurrent access
*/
struct ufs_hw_queue {
void __iomem *mcq_sq_head;
@@ -1105,6 +1118,8 @@ struct ufs_hw_queue {
u32 cq_tail_slot;
u32 cq_head_slot;
spinlock_t cq_lock;
+ /* prevent concurrent access to submission queue */
+ struct mutex sq_mutex;
};
static inline bool is_mcq_enabled(struct ufs_hba *hba)
@@ -1240,7 +1255,7 @@ void ufshcd_update_evt_hist(struct ufs_hba *hba, u32 id, u32 val);
void ufshcd_hba_stop(struct ufs_hba *hba);
void ufshcd_schedule_eh_work(struct ufs_hba *hba);
void ufshcd_mcq_write_cqis(struct ufs_hba *hba, u32 val, int i);
-unsigned long ufshcd_mcq_poll_cqe_nolock(struct ufs_hba *hba,
+unsigned long ufshcd_mcq_poll_cqe_lock(struct ufs_hba *hba,
struct ufs_hw_queue *hwq);
void ufshcd_mcq_enable_esi(struct ufs_hba *hba);
void ufshcd_mcq_config_esi(struct ufs_hba *hba, struct msi_msg *msg);
@@ -1277,7 +1292,6 @@ extern int ufshcd_system_freeze(struct device *dev);
extern int ufshcd_system_thaw(struct device *dev);
extern int ufshcd_system_restore(struct device *dev);
#endif
-extern int ufshcd_shutdown(struct ufs_hba *hba);
extern int ufshcd_dme_configure_adapt(struct ufs_hba *hba,
int agreed_gear,
@@ -1358,7 +1372,7 @@ void ufshcd_fixup_dev_quirks(struct ufs_hba *hba,
int ufshcd_read_string_desc(struct ufs_hba *hba, u8 desc_index,
u8 **buf, bool ascii);
-int ufshcd_hold(struct ufs_hba *hba, bool async);
+void ufshcd_hold(struct ufs_hba *hba);
void ufshcd_release(struct ufs_hba *hba);
void ufshcd_clkgate_delay_set(struct device *dev, unsigned long value);
diff --git a/include/ufs/ufshci.h b/include/ufs/ufshci.h
index 11424bb03814..146fbea76d98 100644
--- a/include/ufs/ufshci.h
+++ b/include/ufs/ufshci.h
@@ -99,6 +99,9 @@ enum {
enum {
REG_SQHP = 0x0,
REG_SQTP = 0x4,
+ REG_SQRTC = 0x8,
+ REG_SQCTI = 0xC,
+ REG_SQRTS = 0x10,
};
enum {
@@ -111,12 +114,26 @@ enum {
REG_CQIE = 0x4,
};
+enum {
+ SQ_START = 0x0,
+ SQ_STOP = 0x1,
+ SQ_ICU = 0x2,
+};
+
+enum {
+ SQ_STS = 0x1,
+ SQ_CUS = 0x2,
+};
+
+#define SQ_ICU_ERR_CODE_MASK GENMASK(7, 4)
+#define UPIU_COMMAND_TYPE_MASK GENMASK(31, 28)
#define UFS_MASK(mask, offset) ((mask) << (offset))
/* UFS Version 08h */
#define MINOR_VERSION_NUM_MASK UFS_MASK(0xFFFF, 0)
#define MAJOR_VERSION_NUM_MASK UFS_MASK(0xFFFF, 16)
+#define UFSHCD_NUM_RESERVED 1
/*
* Controller UFSHCI version
* - 2.x and newer use the following scheme:
@@ -453,7 +470,7 @@ enum {
};
/* The maximum length of the data byte count field in the PRDT is 256KB */
-#define PRDT_DATA_BYTE_COUNT_MAX (256 * 1024)
+#define PRDT_DATA_BYTE_COUNT_MAX SZ_256K
/* The granularity of the data byte count field in the PRDT is 32-bit */
#define PRDT_DATA_BYTE_COUNT_PAD 4
@@ -503,8 +520,7 @@ struct request_desc_header {
/**
* struct utp_transfer_req_desc - UTP Transfer Request Descriptor (UTRD)
* @header: UTRD header DW-0 to DW-3
- * @command_desc_base_addr_lo: UCD base address low DW-4
- * @command_desc_base_addr_hi: UCD base address high DW-5
+ * @command_desc_base_addr: UCD base address DW 4-5
* @response_upiu_length: response UPIU length DW-6
* @response_upiu_offset: response UPIU offset DW-6
* @prd_table_length: Physical region descriptor length DW-7
@@ -516,8 +532,7 @@ struct utp_transfer_req_desc {
struct request_desc_header header;
/* DW 4-5*/
- __le32 command_desc_base_addr_lo;
- __le32 command_desc_base_addr_hi;
+ __le64 command_desc_base_addr;
/* DW 6 */
__le16 response_upiu_length;