diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2021-11-05 16:42:02 +0100 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2021-11-05 16:42:02 +0100 |
commit | fe91c4725aeed35023ba4f7a1e1adfebb6878c23 (patch) | |
tree | 7f0e5cbbbe3a1e24d3e3b66ae290625d48ec4b2f /drivers/scsi/scsi_lib.c | |
parent | Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hid... (diff) | |
parent | scsi: lpfc: Update lpfc version to 14.0.0.3 (diff) | |
download | linux-fe91c4725aeed35023ba4f7a1e1adfebb6878c23.tar.xz linux-fe91c4725aeed35023ba4f7a1e1adfebb6878c23.zip |
Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull SCSI updates from James Bottomley:
"This consists of the usual driver updates (ufs, smartpqi, lpfc,
target, megaraid_sas, hisi_sas, qla2xxx) and minor updates and bug
fixes.
Notable core changes are the removal of scsi->tag which caused some
churn in obsolete drivers and a sweep through all drivers to call
scsi_done() directly instead of scsi->done() which removes a pointer
indirection from the hot path and a move to register core sysfs files
earlier, which means they're available to KOBJ_ADD processing, which
necessitates switching all drivers to using attribute groups"
* tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (279 commits)
scsi: lpfc: Update lpfc version to 14.0.0.3
scsi: lpfc: Allow fabric node recovery if recovery is in progress before devloss
scsi: lpfc: Fix link down processing to address NULL pointer dereference
scsi: lpfc: Allow PLOGI retry if previous PLOGI was aborted
scsi: lpfc: Fix use-after-free in lpfc_unreg_rpi() routine
scsi: lpfc: Correct sysfs reporting of loop support after SFP status change
scsi: lpfc: Wait for successful restart of SLI3 adapter during host sg_reset
scsi: lpfc: Revert LOG_TRACE_EVENT back to LOG_INIT prior to driver_resource_setup()
scsi: ufs: ufshcd-pltfrm: Fix memory leak due to probe defer
scsi: ufs: mediatek: Avoid sched_clock() misuse
scsi: mpt3sas: Make mpt3sas_dev_attrs static
scsi: scsi_transport_sas: Add 22.5 Gbps link rate definitions
scsi: target: core: Stop using bdevname()
scsi: aha1542: Use memcpy_{from,to}_bvec()
scsi: sr: Add error handling support for add_disk()
scsi: sd: Add error handling support for add_disk()
scsi: target: Perform ALUA group changes in one step
scsi: target: Replace lun_tg_pt_gp_lock with rcu in I/O path
scsi: target: Fix alua_tg_pt_gps_count tracking
scsi: target: Fix ordered tag handling
...
Diffstat (limited to 'drivers/scsi/scsi_lib.c')
-rw-r--r-- | drivers/scsi/scsi_lib.c | 64 |
1 files changed, 42 insertions, 22 deletions
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 9c2b99e12ce3..1344553afe70 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -950,7 +950,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) /* * If there had been no error, but we have leftover bytes in the - * requeues just queue the command up again. + * request just queue the command up again. */ if (likely(result == 0)) scsi_io_completion_reprep(cmd, q); @@ -1530,7 +1530,7 @@ static int scsi_dispatch_cmd(struct scsi_cmnd *cmd) return rtn; done: - cmd->scsi_done(cmd); + scsi_done(cmd); return 0; } @@ -1585,8 +1585,17 @@ static blk_status_t scsi_prepare_cmd(struct request *req) return scsi_cmd_to_driver(cmd)->init_command(cmd); } -static void scsi_mq_done(struct scsi_cmnd *cmd) +void scsi_done(struct scsi_cmnd *cmd) { + switch (cmd->submitter) { + case SUBMITTED_BY_BLOCK_LAYER: + break; + case SUBMITTED_BY_SCSI_ERROR_HANDLER: + return scsi_eh_done(cmd); + case SUBMITTED_BY_SCSI_RESET_IOCTL: + return; + } + if (unlikely(blk_should_fake_timeout(scsi_cmd_to_rq(cmd)->q))) return; if (unlikely(test_and_set_bit(SCMD_STATE_COMPLETE, &cmd->state))) @@ -1594,6 +1603,7 @@ static void scsi_mq_done(struct scsi_cmnd *cmd) trace_scsi_dispatch_cmd_done(cmd); blk_mq_complete_request(scsi_cmd_to_rq(cmd)); } +EXPORT_SYMBOL(scsi_done); static void scsi_mq_put_budget(struct request_queue *q, int budget_token) { @@ -1693,7 +1703,7 @@ static blk_status_t scsi_queue_rq(struct blk_mq_hw_ctx *hctx, scsi_set_resid(cmd, 0); memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); - cmd->scsi_done = scsi_mq_done; + cmd->submitter = SUBMITTED_BY_BLOCK_LAYER; blk_mq_start_request(req); reason = scsi_dispatch_cmd(cmd); @@ -2042,8 +2052,15 @@ scsi_mode_select(struct scsi_device *sdev, int pf, int sp, int modepage, memset(cmd, 0, sizeof(cmd)); cmd[1] = (pf ? 0x10 : 0) | (sp ? 0x01 : 0); - if (sdev->use_10_for_ms) { - if (len > 65535) + /* + * Use MODE SELECT(10) if the device asked for it or if the mode page + * and the mode select header cannot fit within the maximumm 255 bytes + * of the MODE SELECT(6) command. + */ + if (sdev->use_10_for_ms || + len + 4 > 255 || + data->block_descriptor_length > 255) { + if (len > 65535 - 8) return -EINVAL; real_buffer = kmalloc(8 + len, GFP_KERNEL); if (!real_buffer) @@ -2056,15 +2073,13 @@ scsi_mode_select(struct scsi_device *sdev, int pf, int sp, int modepage, real_buffer[3] = data->device_specific; real_buffer[4] = data->longlba ? 0x01 : 0; real_buffer[5] = 0; - real_buffer[6] = data->block_descriptor_length >> 8; - real_buffer[7] = data->block_descriptor_length; + put_unaligned_be16(data->block_descriptor_length, + &real_buffer[6]); cmd[0] = MODE_SELECT_10; - cmd[7] = len >> 8; - cmd[8] = len; + put_unaligned_be16(len, &cmd[7]); } else { - if (len > 255 || data->block_descriptor_length > 255 || - data->longlba) + if (data->longlba) return -EINVAL; real_buffer = kmalloc(4 + len, GFP_KERNEL); @@ -2091,7 +2106,7 @@ EXPORT_SYMBOL_GPL(scsi_mode_select); /** * scsi_mode_sense - issue a mode sense, falling back from 10 to six bytes if necessary. * @sdev: SCSI device to be queried - * @dbd: set if mode sense will allow block descriptors to be returned + * @dbd: set to prevent mode sense from returning block descriptors * @modepage: mode page being requested * @buffer: request buffer (may not be smaller than eight bytes) * @len: length of request buffer. @@ -2126,18 +2141,18 @@ scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, sshdr = &my_sshdr; retry: - use_10_for_ms = sdev->use_10_for_ms; + use_10_for_ms = sdev->use_10_for_ms || len > 255; if (use_10_for_ms) { - if (len < 8) - len = 8; + if (len < 8 || len > 65535) + return -EINVAL; cmd[0] = MODE_SENSE_10; - cmd[8] = len; + put_unaligned_be16(len, &cmd[7]); header_length = 8; } else { if (len < 4) - len = 4; + return -EINVAL; cmd[0] = MODE_SENSE; cmd[4] = len; @@ -2161,9 +2176,15 @@ scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, if ((sshdr->sense_key == ILLEGAL_REQUEST) && (sshdr->asc == 0x20) && (sshdr->ascq == 0)) { /* - * Invalid command operation code + * Invalid command operation code: retry using + * MODE SENSE(6) if this was a MODE SENSE(10) + * request, except if the request mode page is + * too large for MODE SENSE single byte + * allocation length field. */ if (use_10_for_ms) { + if (len > 255) + return -EIO; sdev->use_10_for_ms = 0; goto retry; } @@ -2187,12 +2208,11 @@ scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, data->longlba = 0; data->block_descriptor_length = 0; } else if (use_10_for_ms) { - data->length = buffer[0]*256 + buffer[1] + 2; + data->length = get_unaligned_be16(&buffer[0]) + 2; data->medium_type = buffer[2]; data->device_specific = buffer[3]; data->longlba = buffer[4] & 0x01; - data->block_descriptor_length = buffer[6]*256 - + buffer[7]; + data->block_descriptor_length = get_unaligned_be16(&buffer[6]); } else { data->length = buffer[0] + 1; data->medium_type = buffer[1]; |