summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2026-10-13 18:36:09 +0100
committerMark Brown <broonie@kernel.org>2026-10-13 18:36:12 +0100
commit98a2eaef035eb4ce89a04004afcbf0097393fcf2 (patch)
tree619abd779f85d120954bca59dbaeccca7a08e8f2
parent53262cb205c8864559a465a68a4ee8879a915ea3 (diff)
parent2f4880c22e838d54eae9ab153b0f8dce60531bf1 (diff)
downloadlinux-next-98a2eaef035eb4ce89a04004afcbf0097393fcf2.tar.gz
linux-next-98a2eaef035eb4ce89a04004afcbf0097393fcf2.zip
Merge branch 'for-next' of https://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git
-rw-r--r--Documentation/scsi/scsi_mid_low_api.rst24
-rw-r--r--MAINTAINERS1
-rw-r--r--drivers/ata/libata-scsi.c2
-rw-r--r--drivers/scsi/bfa/bfa_fcs.c88
-rw-r--r--drivers/scsi/scsi_debug.c143
-rw-r--r--drivers/scsi/scsi_error.c1
-rw-r--r--drivers/scsi/scsi_lib.c3
-rw-r--r--drivers/scsi/st.c97
-rw-r--r--drivers/scsi/st.h2
-rw-r--r--drivers/ufs/core/ufs-rpmb.c3
10 files changed, 243 insertions, 121 deletions
diff --git a/Documentation/scsi/scsi_mid_low_api.rst b/Documentation/scsi/scsi_mid_low_api.rst
index 5489e9d07ab7..84cf61b2d6ae 100644
--- a/Documentation/scsi/scsi_mid_low_api.rst
+++ b/Documentation/scsi/scsi_mid_low_api.rst
@@ -865,7 +865,7 @@ Details::
*
* Other types of errors that are detected immediately may be
* flagged by setting scp->result to an appropriate value,
- * invoking the scp->scsi_done callback, and then returning 0
+ * invoking the scsi_done() function, and then returning 0
* from this function. If the command is not performed
* immediately (and the LLD is starting (or will start) the given
* command) then this function should place 0 in scp->result and
@@ -873,11 +873,11 @@ Details::
*
* Command ownership. If the driver returns zero, it owns the
* command and must take responsibility for ensuring the
- * scp->scsi_done callback is executed. Note: the driver may
- * call scp->scsi_done before returning zero, but after it has
- * called scp->scsi_done, it may not return any value other than
+ * scsi_done() function is called. Note: the driver may
+ * call scsi_done() before returning zero, but after it has
+ * called scsi_done(), it may not return any value other than
* zero. If the driver makes a non-zero return, it must not
- * execute the command's scsi_done callback at any time.
+ * call scsi_done(scp) at any time.
*
* Locks: up to and including 2.6.36, struct Scsi_Host::host_lock
* held on entry (with "irqsave") and is expected to be
@@ -887,16 +887,16 @@ Details::
* Calling context: in interrupt (soft irq) or process context
*
* Notes: This function should be relatively fast. Normally it
- * will not wait for IO to complete. Hence the scp->scsi_done
- * callback is invoked (often directly from an interrupt service
+ * will not wait for IO to complete. Hence the scsi_done()
+ * function is invoked (often directly from an interrupt service
* routine) some time after this function has returned. In some
* cases (e.g. pseudo adapter drivers that manufacture the
- * response to a SCSI INQUIRY) the scp->scsi_done callback may be
- * invoked before this function returns. If the scp->scsi_done
- * callback is not invoked within a certain period the SCSI mid
+ * response to a SCSI INQUIRY) the scsi_done() function may be
+ * invoked before this function returns. If the scsi_done()
+ * function is not invoked within a certain period the SCSI mid
* level will commence error processing. If a status of CHECK
- * CONDITION is placed in "result" when the scp->scsi_done
- * callback is invoked, then the LLD driver should perform
+ * CONDITION is placed in "result" when the scsi_done()
+ * function is invoked, then the LLD driver should perform
* autosense and fill in the struct scsi_cmnd::sense_buffer
* array. The scsi_cmnd::sense_buffer array is zeroed prior to
* the mid level queuing a command to an LLD.
diff --git a/MAINTAINERS b/MAINTAINERS
index d63e12a7d038..91a48b225f55 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -28590,7 +28590,6 @@ F: lib/union_find.c
UNIVERSAL FLASH STORAGE HOST CONTROLLER DRIVER
R: Alim Akhtar <alim.akhtar@samsung.com>
-R: Avri Altman <avri.altman@wdc.com>
R: Bart Van Assche <bvanassche@acm.org>
L: linux-scsi@vger.kernel.org
S: Supported
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index eb08cb978a97..5cde90fe594e 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -3583,7 +3583,7 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
unsigned int multi_count = 1 << (cdb[1] >> 5);
if (!dev->multi_count) {
- ata_scsi_set_sense(dev, scmd, ABORTED_COMMAND, 0, 0);
+ ata_scsi_set_sense(dev, scmd, ABORTED_COMMAND, NO_ADDITIONAL_SENSE_INFORMATION);
return 1;
}
diff --git a/drivers/scsi/bfa/bfa_fcs.c b/drivers/scsi/bfa/bfa_fcs.c
index 9b57312f43f5..3e5d3a141f32 100644
--- a/drivers/scsi/bfa/bfa_fcs.c
+++ b/drivers/scsi/bfa/bfa_fcs.c
@@ -760,53 +760,16 @@ bfa_fcs_fabric_psymb_init(struct bfa_fcs_fabric_s *fabric)
bfa_ioc_get_adapter_model(&fabric->fcs->bfa->ioc, model);
- /* Model name/number */
- strscpy(port_cfg->sym_name.symname, model,
- BFA_SYMNAME_MAXLEN);
- strlcat(port_cfg->sym_name.symname, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
- BFA_SYMNAME_MAXLEN);
-
- /* Driver Version */
- strlcat(port_cfg->sym_name.symname, driver_info->version,
- BFA_SYMNAME_MAXLEN);
- strlcat(port_cfg->sym_name.symname, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
- BFA_SYMNAME_MAXLEN);
-
- /* Host machine name */
- strlcat(port_cfg->sym_name.symname,
- driver_info->host_machine_name,
- BFA_SYMNAME_MAXLEN);
- strlcat(port_cfg->sym_name.symname, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
- BFA_SYMNAME_MAXLEN);
-
- /*
- * Host OS Info :
- * If OS Patch Info is not there, do not truncate any bytes from the
- * OS name string and instead copy the entire OS info string (64 bytes).
- */
- if (driver_info->host_os_patch[0] == '\0') {
- strlcat(port_cfg->sym_name.symname,
- driver_info->host_os_name,
- BFA_SYMNAME_MAXLEN);
- strlcat(port_cfg->sym_name.symname,
- BFA_FCS_PORT_SYMBNAME_SEPARATOR,
- BFA_SYMNAME_MAXLEN);
- } else {
- strlcat(port_cfg->sym_name.symname,
- driver_info->host_os_name,
- BFA_SYMNAME_MAXLEN);
- strlcat(port_cfg->sym_name.symname,
- BFA_FCS_PORT_SYMBNAME_SEPARATOR,
- BFA_SYMNAME_MAXLEN);
-
- /* Append host OS Patch Info */
- strlcat(port_cfg->sym_name.symname,
- driver_info->host_os_patch,
- BFA_SYMNAME_MAXLEN);
- }
-
- /* null terminate */
- port_cfg->sym_name.symname[BFA_SYMNAME_MAXLEN - 1] = 0;
+ snprintf(port_cfg->sym_name.symname, BFA_SYMNAME_MAXLEN,
+ "%s" BFA_FCS_PORT_SYMBNAME_SEPARATOR
+ "%s" BFA_FCS_PORT_SYMBNAME_SEPARATOR
+ "%s" BFA_FCS_PORT_SYMBNAME_SEPARATOR
+ "%s" BFA_FCS_PORT_SYMBNAME_SEPARATOR
+ "%s",
+ model, driver_info->version,
+ driver_info->host_machine_name,
+ driver_info->host_os_name,
+ driver_info->host_os_patch);
}
/*
@@ -821,30 +784,13 @@ bfa_fcs_fabric_nsymb_init(struct bfa_fcs_fabric_s *fabric)
bfa_ioc_get_adapter_model(&fabric->fcs->bfa->ioc, model);
- /* Model name/number */
- strscpy(port_cfg->node_sym_name.symname, model,
- BFA_SYMNAME_MAXLEN);
- strlcat(port_cfg->node_sym_name.symname,
- BFA_FCS_PORT_SYMBNAME_SEPARATOR,
- BFA_SYMNAME_MAXLEN);
-
- /* Driver Version */
- strlcat(port_cfg->node_sym_name.symname, (char *)driver_info->version,
- BFA_SYMNAME_MAXLEN);
- strlcat(port_cfg->node_sym_name.symname,
- BFA_FCS_PORT_SYMBNAME_SEPARATOR,
- BFA_SYMNAME_MAXLEN);
-
- /* Host machine name */
- strlcat(port_cfg->node_sym_name.symname,
- driver_info->host_machine_name,
- BFA_SYMNAME_MAXLEN);
- strlcat(port_cfg->node_sym_name.symname,
- BFA_FCS_PORT_SYMBNAME_SEPARATOR,
- BFA_SYMNAME_MAXLEN);
-
- /* null terminate */
- port_cfg->node_sym_name.symname[BFA_SYMNAME_MAXLEN - 1] = 0;
+ /* Model name/number, Driver Version, Host machine name */
+ snprintf(port_cfg->node_sym_name.symname, BFA_SYMNAME_MAXLEN,
+ "%s" BFA_FCS_PORT_SYMBNAME_SEPARATOR
+ "%s" BFA_FCS_PORT_SYMBNAME_SEPARATOR
+ "%s" BFA_FCS_PORT_SYMBNAME_SEPARATOR,
+ model, (char *)driver_info->version,
+ driver_info->host_machine_name);
}
/*
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 6941809dfdb7..e679df1993aa 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -3980,6 +3980,16 @@ static int check_zbc_access_params(struct scsi_cmnd *scp,
UNALIGNED_WRITE_COMMAND);
return check_condition_result;
}
+ /*
+ * Writes must end on a physical block boundary, that is, the
+ * transfer length must be a multiple of the physical block
+ * size.
+ */
+ if (!IS_ALIGNED(lba + num, 1U << sdebug_physblk_exp)) {
+ mk_sense_buffer(scp, ILLEGAL_REQUEST,
+ UNALIGNED_WRITE_COMMAND);
+ return check_condition_result;
+ }
}
/* Handle implicit open of closed and empty zones */
@@ -4263,6 +4273,8 @@ static int do_device_access(struct sdeb_store_info *sip, struct scsi_cmnd *scp,
u64 block;
enum dma_data_direction dir;
struct scsi_data_buffer *sdb = &scp->sdb;
+ struct scsi_device *sdp = scp->device;
+ struct sdebug_dev_info *devip = (struct sdebug_dev_info *)sdp->hostdata;
u8 *fsp;
int i, total = 0;
@@ -4290,6 +4302,25 @@ static int do_device_access(struct sdeb_store_info *sip, struct scsi_cmnd *scp,
fsp = sip->storep;
+ /*
+ * A write to a sequential write required zone has to end on a physical
+ * block boundary, so if the data-out buffer does not hold all of the
+ * data that the command asks for, write up to the last whole physical
+ * block that it does hold. What is left over is reported as part of
+ * the residual.
+ */
+ if (do_write && sdebug_dev_is_zoned(devip)) {
+ struct sdeb_zone_state *zsp = zbc_zone(devip, lba);
+
+ if (zsp->z_type == ZBC_ZTYPE_SWR) {
+ u32 avail = (sdb->length - sg_skip)
+ >> ilog2(sdebug_sector_size);
+
+ if (avail < num)
+ num = round_down(avail, 1U << sdebug_physblk_exp);
+ }
+ }
+
block = do_div(lba, sdebug_store_sectors);
/* Only allow 1x atomic write or multiple non-atomic writes at any given time */
@@ -4845,6 +4876,11 @@ static unsigned int map_state(struct sdeb_store_info *sip, sector_t lba,
return mapped;
}
+/*
+ * Callers may map the whole range of a write without checking how much of
+ * it was written. SBC-6 4.7.4.6.2 allows a deallocated LBA to become mapped
+ * at any time, and only requires an LBA that was written to be mapped.
+ */
static void map_region(struct sdeb_store_info *sip, sector_t lba,
unsigned int len)
{
@@ -4953,12 +4989,11 @@ static int corrupt_lbas(struct sdebug_dev_info *devip, u64 lba, u32 num,
{
struct sdeb_store_info *sip = devip2sip(devip, false);
bool meta_data_locked = false;
+ bool lbp = scsi_debug_lbp();
u32 block, num_mapped, b, i;
int error = 0;
- if (sdebug_dev_is_zoned(devip) ||
- sdebug_dix ||
- scsi_debug_lbp()) {
+ if (sdebug_dev_is_zoned(devip) || sdebug_dix || lbp) {
sdeb_meta_write_lock(sip);
meta_data_locked = true;
}
@@ -4975,8 +5010,7 @@ static int corrupt_lbas(struct sdebug_dev_info *devip, u64 lba, u32 num,
goto out_unlock;
}
- if (scsi_debug_lbp() &&
- (!map_state(sip, lba, &num_mapped) || num > num_mapped)) {
+ if (lbp && (!map_state(sip, lba, &num_mapped) || num > num_mapped)) {
pr_err("can't modify unmapped logical blocks: %llu:%u",
lba, num);
error = -EINVAL;
@@ -5035,6 +5069,7 @@ static int resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
struct sdeb_store_info *sip = devip2sip(devip, true);
u8 *cmd = scp->cmnd;
bool meta_data_locked = false;
+ bool lbp = scsi_debug_lbp();
if (unlikely(sdebug_opts & SDEBUG_OPT_UNALIGNED_WRITE &&
atomic_read(&sdeb_inject_pending))) {
@@ -5101,8 +5136,7 @@ static int resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
}
if (sdebug_dev_is_zoned(devip) ||
- (sdebug_dix && scsi_prot_sg_count(scp)) ||
- scsi_debug_lbp()) {
+ (sdebug_dix && scsi_prot_sg_count(scp)) || lbp) {
sdeb_meta_write_lock(sip);
meta_data_locked = true;
}
@@ -5147,12 +5181,12 @@ static int resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
}
ret = do_device_access(sip, scp, 0, lba, num, group, true, false);
- if (unlikely(scsi_debug_lbp()))
+ if (unlikely(lbp))
map_region(sip, lba, num);
- /* If ZBC zone then bump its write pointer */
- if (sdebug_dev_is_zoned(devip))
- zbc_inc_wp(devip, lba, num);
+ /* If ZBC zone then bump its write pointer over the data written */
+ if (sdebug_dev_is_zoned(devip) && ret > 0)
+ zbc_inc_wp(devip, lba, ret >> ilog2(sdebug_sector_size));
if (meta_data_locked)
sdeb_meta_write_unlock(sip);
@@ -5164,6 +5198,9 @@ static int resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
"%s: write: cdb indicated=%u, IO sent=%d bytes\n",
my_name, num * sdebug_sector_size, ret);
+ if (ret < scsi_bufflen(scp))
+ scsi_set_resid(scp, scsi_bufflen(scp) - ret);
+
if (unlikely((sdebug_opts & SDEBUG_OPT_RECOV_DIF_DIX) &&
atomic_read(&sdeb_inject_pending))) {
if (sdebug_opts & SDEBUG_OPT_RECOVERED_ERR) {
@@ -5199,7 +5236,8 @@ static int resp_write_scat(struct scsi_cmnd *scp,
struct sdeb_store_info *sip = devip2sip(devip, true);
u8 wrprotect;
u16 lbdof, num_lrd, k;
- u32 num, num_by, bt_len, lbdof_blen, sg_off, cum_lb;
+ u32 num, bt_len, lbdof_blen, cum_lb;
+ u64 num_by, sg_off;
u32 lb_size = sdebug_sector_size;
u32 ei_lba;
u64 lba;
@@ -5235,8 +5273,10 @@ static int resp_write_scat(struct scsi_cmnd *scp,
"Unprotected WR to DIF device\n");
}
}
- if ((num_lrd == 0) || (bt_len == 0))
+ if (num_lrd == 0 || bt_len == 0) {
+ scsi_set_resid(scp, scsi_bufflen(scp));
return 0; /* T10 says these do-nothings are not errors */
+ }
if (lbdof == 0) {
if (sdebug_verbose)
sdev_printk(KERN_INFO, scp->device,
@@ -5275,14 +5315,14 @@ static int resp_write_scat(struct scsi_cmnd *scp,
num = get_unaligned_be32(up + 8);
if (sdebug_verbose)
sdev_printk(KERN_INFO, scp->device,
- "%s: k=%d LBA=0x%llx num=%u sg_off=%u\n",
+ "%s: k=%d LBA=0x%llx num=%u sg_off=%llu\n",
my_name, k, lba, num, sg_off);
if (num == 0)
continue;
ret = check_device_access_params(scp, lba, num, true);
if (ret)
goto err_out_unlock;
- num_by = num * lb_size;
+ num_by = (u64)num * lb_size;
ei_lba = is_16 ? 0 : get_unaligned_be32(up + 12);
if ((cum_lb + num) > bt_len) {
@@ -5313,10 +5353,13 @@ static int resp_write_scat(struct scsi_cmnd *scp,
* Write ranges atomically to keep as close to pre-atomic
* writes behaviour as possible.
*/
- ret = do_device_access(sip, scp, sg_off, lba, num, group, true, true);
- /* If ZBC zone then bump its write pointer */
- if (sdebug_dev_is_zoned(devip))
- zbc_inc_wp(devip, lba, num);
+ ret = do_device_access(sip, scp,
+ min_t(u64, sg_off, scsi_bufflen(scp)),
+ lba, num, group, true, true);
+ /* If ZBC zone then bump its write pointer over the data written */
+ if (sdebug_dev_is_zoned(devip) && ret > 0)
+ zbc_inc_wp(devip, lba,
+ ret >> ilog2(sdebug_sector_size));
if (unlikely(scsi_debug_lbp()))
map_region(sip, lba, num);
if (unlikely(-1 == ret)) {
@@ -5324,11 +5367,13 @@ static int resp_write_scat(struct scsi_cmnd *scp,
goto err_out_unlock;
} else if (unlikely(sdebug_verbose && (ret < num_by)))
sdev_printk(KERN_INFO, scp->device,
- "%s: write: cdb indicated=%u, IO sent=%d bytes\n",
+ "%s: write: cdb indicated=%llu, IO sent=%d bytes\n",
my_name, num_by, ret);
if (unlikely((sdebug_opts & SDEBUG_OPT_RECOV_DIF_DIX) &&
atomic_read(&sdeb_inject_pending))) {
+ /* This range has been written */
+ sg_off += num_by;
if (sdebug_opts & SDEBUG_OPT_RECOVERED_ERR) {
mk_sense_buffer(scp, RECOVERED_ERROR,
FAILURE_PREDICTION_THRESHOLD_EXCEEDED);
@@ -5354,6 +5399,13 @@ static int resp_write_scat(struct scsi_cmnd *scp,
}
ret = 0;
err_out_unlock:
+ /*
+ * sg_off counts what the command asked for, which can exceed the
+ * buffer: lbdof is not validated against it, and a range is counted
+ * in full even if do_device_access() copied less.
+ */
+ if (scsi_bufflen(scp) > sg_off)
+ scsi_set_resid(scp, scsi_bufflen(scp) - sg_off);
sdeb_meta_write_unlock(sip);
err_out:
kfree(lrdp);
@@ -5374,8 +5426,9 @@ static int resp_write_same(struct scsi_cmnd *scp, u64 lba, u32 num,
u8 *fs1p;
u8 *fsp;
bool meta_data_locked = false;
+ bool lbp = scsi_debug_lbp();
- if (sdebug_dev_is_zoned(devip) || scsi_debug_lbp()) {
+ if (sdebug_dev_is_zoned(devip) || lbp) {
sdeb_meta_write_lock(sip);
meta_data_locked = true;
}
@@ -5384,7 +5437,7 @@ static int resp_write_same(struct scsi_cmnd *scp, u64 lba, u32 num,
if (ret)
goto out;
- if (unmap && scsi_debug_lbp()) {
+ if (unmap && lbp) {
unmap_region(sip, lba, num);
goto out;
}
@@ -5414,7 +5467,7 @@ static int resp_write_same(struct scsi_cmnd *scp, u64 lba, u32 num,
block = do_div(lbaa, sdebug_store_sectors);
memmove(fsp + (block * lb_size), fs1p, lb_size);
}
- if (scsi_debug_lbp())
+ if (lbp)
map_region(sip, lba, num);
/* If ZBC zone then bump its write pointer */
if (sdebug_dev_is_zoned(devip))
@@ -5575,8 +5628,8 @@ static int resp_comp_write(struct scsi_cmnd *scp,
"indicated=%u, IO sent=%d bytes\n", my_name,
dnum * lb_size, ret);
- sdeb_data_write_lock(sip);
sdeb_meta_write_lock(sip);
+ sdeb_data_write_lock(sip);
if (!comp_write_worker(sip, lba, num, arr, false)) {
mk_sense_buffer(scp, MISCOMPARE,
MISCOMPARE_DURING_VERIFY_OPERATION);
@@ -5584,12 +5637,12 @@ static int resp_comp_write(struct scsi_cmnd *scp,
goto cleanup_unlock;
}
- /* Cover sip->map_storep (which map_region()) sets with data lock */
+ /* Cover sip->map_storep (which map_region() sets) with the meta lock */
if (scsi_debug_lbp())
map_region(sip, lba, num);
cleanup_unlock:
- sdeb_meta_write_unlock(sip);
sdeb_data_write_unlock(sip);
+ sdeb_meta_write_unlock(sip);
cleanup_free:
kfree(arr);
return retval;
@@ -6158,6 +6211,7 @@ static int resp_atomic_write(struct scsi_cmnd *scp,
u8 *cmd = scp->cmnd;
u16 boundary, len;
u64 lba, lba_tmp;
+ bool lbp = scsi_debug_lbp();
int ret;
if (!scsi_debug_atomic_write()) {
@@ -6202,11 +6256,34 @@ static int resp_atomic_write(struct scsi_cmnd *scp,
}
}
+ ret = check_device_access_params(scp, lba, len, true);
+ if (ret)
+ return ret;
+
+ /*
+ * Short atomic writes are not allowed: SBC-6 4.28.2 requires an
+ * atomic write that cannot complete to leave its LBAs unaltered, and
+ * do_device_access() would already have written part of it.
+ */
+ if (scsi_bufflen(scp) < len * sdebug_sector_size)
+ return DID_ERROR << 16;
+
+ if (lbp)
+ sdeb_meta_write_lock(sip);
+
ret = do_device_access(sip, scp, 0, lba, len, 0, true, true);
+ if (lbp) {
+ map_region(sip, lba, len);
+ sdeb_meta_write_unlock(sip);
+ }
+
if (unlikely(ret == -1))
return DID_ERROR << 16;
if (unlikely(ret != len * sdebug_sector_size))
return DID_ERROR << 16;
+
+ if (ret < scsi_bufflen(scp))
+ scsi_set_resid(scp, scsi_bufflen(scp) - ret);
return 0;
}
@@ -8656,8 +8733,8 @@ static int __init scsi_debug_init(void)
return -EINVAL;
}
- if (sdebug_physblk_exp > 15) {
- pr_err("invalid physblk_exp %u\n", sdebug_physblk_exp);
+ if (sdebug_physblk_exp < 0 || sdebug_physblk_exp > 15) {
+ pr_err("invalid physblk_exp %d\n", sdebug_physblk_exp);
return -EINVAL;
}
@@ -8734,6 +8811,16 @@ static int __init scsi_debug_init(void)
sdebug_dev_size_mb = DEF_ZBC_DEV_SIZE_MB;
}
+ if (sdeb_zbc_in_use && sdebug_lowest_aligned) {
+ pr_err("lowest_aligned is not supported by a zoned device\n");
+ return -EINVAL;
+ }
+
+ if (sdeb_zbc_in_use && sdebug_atomic_wr) {
+ pr_err("atomic_wr is not supported by a zoned device\n");
+ return -EINVAL;
+ }
+
if (sdebug_dev_size_mb == DEF_DEV_SIZE_PRE_INIT)
sdebug_dev_size_mb = DEF_DEV_SIZE_MB;
if (sdebug_dev_size_mb < 1)
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 2e0b1909dc69..75442d60c30e 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -270,7 +270,6 @@ scsi_abort_command(struct scsi_cmnd *scmd)
spin_lock_irqsave(&shost->host_lock, flags);
if (shost->eh_deadline != -1 && !shost->last_reset)
shost->last_reset = jiffies;
- BUG_ON(!list_empty(&scmd->eh_entry));
list_add_tail(&scmd->eh_entry, &shost->eh_abort_list);
spin_unlock_irqrestore(&shost->host_lock, flags);
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index db64470f5229..f695a6605815 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -1322,7 +1322,6 @@ void scsi_init_command(struct scsi_device *dev, struct scsi_cmnd *cmd)
}
cmd->device = dev;
- INIT_LIST_HEAD(&cmd->eh_entry);
INIT_DELAYED_WORK(&cmd->abort_work, scmd_eh_abort_handler);
}
@@ -1590,8 +1589,6 @@ static void scsi_complete(struct request *rq)
return;
}
- INIT_LIST_HEAD(&cmd->eh_entry);
-
atomic_inc(&cmd->device->iodone_cnt);
if (cmd->result)
atomic_inc(&cmd->device->ioerr_cnt);
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 1ca9753cb734..3dc6723e80a8 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -368,6 +368,8 @@ static int st_chk_result(struct scsi_tape *STp, struct st_request * SRpnt)
if (ctr != STp->por_ctr) {
STp->por_ctr = ctr;
STp->pos_unknown = 1; /* ASC => power on / reset */
+ /* The reset allowed medium removal; relock at next access */
+ STp->door_locked = ST_UNLOCKED;
st_printk(KERN_WARNING, STp, "Power on/reset recognized.");
}
@@ -428,6 +430,7 @@ static int st_chk_result(struct scsi_tape *STp, struct st_request * SRpnt)
ASC_POWER_ON_RESET_OR_BUS_DEVICE_RESET_OCCURRED &&
!STp->pos_unknown) {
STp->pos_unknown = 1;
+ STp->door_locked = ST_UNLOCKED;
st_printk(KERN_WARNING, STp, "Power on/reset recognized.");
}
@@ -2688,6 +2691,30 @@ static int do_load_unload(struct scsi_tape *STp, struct file *filp, int load_cod
else {
STp->rew_at_close = STp->autorew_dev;
retval = check_tape(STp, filp);
+ /*
+ * LOAD leaves the medium at the beginning of partition
+ * 0. check_tape() records that only for a new session;
+ * without a new-medium unit attention (the medium was
+ * already loaded) the partition and the partition state
+ * would be left as before the load. Reset them as a
+ * new session does, for all partitions: a stale
+ * ST_WRITING state would make st_flush() write a
+ * filemark at the beginning of partition 0.
+ */
+ if (retval == CHKRES_READY) {
+ int i;
+
+ STp->partition = STp->new_partition = 0;
+ for (i = 0; i < ST_NBR_PARTITIONS; i++) {
+ STps = &(STp->ps[i]);
+ STps->rw = ST_IDLE;
+ STps->eof = ST_NOEOF;
+ STps->at_sm = 0;
+ STps->last_block_valid = 0;
+ STps->drv_block = 0;
+ STps->drv_file = 0;
+ }
+ }
if (retval > 0)
retval = 0;
}
@@ -2941,9 +2968,11 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon
direction = DMA_TO_DEVICE;
memset((STp->buffer)->b_data, 0, 12);
- if (cmd_in == MTSETDRVBUFFER)
+ if (cmd_in == MTSETDRVBUFFER) {
(STp->buffer)->b_data[2] = (arg & 7) << 4;
- else
+ STp->drv_buffer_changed = 1; /* At least we tried ;-) */
+ STp->changed_drv_buffer = arg & 7;
+ } else
(STp->buffer)->b_data[2] =
STp->drv_buffer << 4;
(STp->buffer)->b_data[3] = 8; /* block descriptor length */
@@ -3589,6 +3618,26 @@ out:
return retval;
}
+/*
+ * Re-apply a drive buffering mode, density and block size that were changed
+ * by the user before a device reset (a negative value means "not changed").
+ * The buffering mode goes first: the other MODE SELECTs send the current
+ * STp->drv_buffer. A unit attention still pending after the operation
+ * (e.g. new medium after a load) fails the first MODE SELECT, so retry each
+ * once. As in the other post-reset restore path, errors are ignored and one
+ * setting failing does not prevent restoring the others.
+ */
+static void st_restore_changed_settings(struct scsi_tape *STp, int drv_buffer,
+ int density, int blksize)
+{
+ if (drv_buffer >= 0 && st_int_ioctl(STp, MTSETDRVBUFFER, drv_buffer))
+ st_int_ioctl(STp, MTSETDRVBUFFER, drv_buffer);
+ if (density >= 0 && st_int_ioctl(STp, MTSETDENSITY, density))
+ st_int_ioctl(STp, MTSETDENSITY, density);
+ if (blksize >= 0 && st_int_ioctl(STp, MTSETBLK, blksize))
+ st_int_ioctl(STp, MTSETBLK, blksize);
+}
+
/* The ioctl command */
static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
{
@@ -3597,6 +3646,7 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
int retval = 0;
unsigned int blk;
bool cmd_mtiocget;
+ int restore_drv_buffer = -1, restore_density = -1, restore_blksize = -1;
struct scsi_tape *STp = file->private_data;
struct st_modedef *STm;
struct st_partstat *STps;
@@ -3739,10 +3789,26 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
STp->partition = 0;
switch_partition(STp);
}
+ if (STp->drv_buffer_changed)
+ st_int_ioctl(STp, MTSETDRVBUFFER,
+ STp->changed_drv_buffer);
if (STp->density_changed)
st_int_ioctl(STp, MTSETDENSITY, STp->changed_density);
if (STp->blksize_changed)
st_int_ioctl(STp, MTSETBLK, STp->changed_blksize);
+ } else if (mtc.mt_op == MTLOAD || mtc.mt_op == MTRETEN) {
+ /*
+ * The same medium ends up at BOT, so the settings
+ * apply as with MTREW. The operation may start a
+ * new session, which clears the "changed" flags:
+ * save the values and restore them afterwards.
+ */
+ if (STp->drv_buffer_changed)
+ restore_drv_buffer = STp->changed_drv_buffer;
+ if (STp->density_changed)
+ restore_density = STp->changed_density;
+ if (STp->blksize_changed)
+ restore_blksize = STp->changed_blksize;
}
}
@@ -3822,6 +3888,15 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
if (mtc.mt_op == MTLOAD) {
retval = do_load_unload(STp, file, max(1, mtc.mt_count));
+ /*
+ * Restore only if the drive is ready: after an
+ * immediate-mode load with O_NONBLOCK, check_tape()
+ * does not wait and the drive may still be loading.
+ */
+ if (!retval && STp->ready == ST_READY)
+ st_restore_changed_settings(STp, restore_drv_buffer,
+ restore_density,
+ restore_blksize);
goto out;
}
@@ -3840,6 +3915,22 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
retval = st_compression(STp, (mtc.mt_count & 1));
else
retval = st_int_ioctl(STp, mtc.mt_op, mtc.mt_count);
+ if (!retval && mtc.mt_op == MTRETEN && !STp->immediate &&
+ (restore_drv_buffer >= 0 || restore_density >= 0 ||
+ restore_blksize >= 0)) {
+ /*
+ * Retension reloads the medium and the drive may
+ * report a new medium. Let check_tape() start the new
+ * session (applying the mode defaults) now, as for
+ * MTLOAD; otherwise it happens at the next open and
+ * overrides the restored settings.
+ */
+ if (check_tape(STp, file) >= 0 &&
+ STp->ready == ST_READY)
+ st_restore_changed_settings(STp, restore_drv_buffer,
+ restore_density,
+ restore_blksize);
+ }
goto out;
}
if (!STm->defined) {
@@ -4445,7 +4536,7 @@ static int st_probe(struct scsi_device *SDp)
tpnt->modes[0].defined = 1;
tpnt->density_changed = tpnt->compression_changed =
- tpnt->blksize_changed = 0;
+ tpnt->blksize_changed = tpnt->drv_buffer_changed = 0;
mutex_init(&tpnt->lock);
idr_preload(GFP_KERNEL);
diff --git a/drivers/scsi/st.h b/drivers/scsi/st.h
index 0d7c4b8c2c8a..c580024880c3 100644
--- a/drivers/scsi/st.h
+++ b/drivers/scsi/st.h
@@ -162,10 +162,12 @@ struct scsi_tape {
unsigned char in_use;
unsigned char blksize_changed;
unsigned char density_changed;
+ unsigned char drv_buffer_changed;
unsigned char compression_changed;
unsigned char drv_buffer;
unsigned char density;
unsigned char changed_density;
+ unsigned char changed_drv_buffer;
unsigned char door_locked;
unsigned char autorew_dev; /* auto-rewind device */
unsigned char rew_at_close; /* rewind necessary at close */
diff --git a/drivers/ufs/core/ufs-rpmb.c b/drivers/ufs/core/ufs-rpmb.c
index 50ef63afd528..65f2d71cf073 100644
--- a/drivers/ufs/core/ufs-rpmb.c
+++ b/drivers/ufs/core/ufs-rpmb.c
@@ -47,7 +47,8 @@ static int ufs_sec_submit(struct ufs_hba *hba, u16 spsp, void *buffer, size_t le
{
.sense_key = UNIT_ATTENTION,
.sense_code =
- POWER_ON_RESET_OR_BUS_DEVICE_RESET_OCCURRED,
+ scsi_sense_code(ASC_POWER_ON_RESET_OR_BUS_DEVICE_RESET_OCCURRED,
+ SCMD_FAILURE_ASCQ_ANY),
.allowed = UFS_RPMB_UA_RETRIES,
.result = SAM_STAT_CHECK_CONDITION,
},