Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull SCSI updates from James Bottomley: "This update includes the usual round of major driver updates (hisi_sas, ufs, fnic, cxlflash, be2iscsi, ipr, stex). There's also the usual amount of cosmetic and spelling stuff" * tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (155 commits) scsi: qla4xxx: fix spelling mistake: "Tempalate" -> "Template" scsi: stex: make S6flag static scsi: mac_esp: fix to pass correct device identity to free_irq() scsi: aacraid: pci_alloc_consistent() failures on ARM64 scsi: ufs: make ufshcd_get_lists_status() register operation obvious scsi: ufs: use MASK_EE_STATUS scsi: mac_esp: Replace bogus memory barrier with spinlock scsi: fcoe: make fcoe_e_d_tov and fcoe_r_a_tov static scsi: sd_zbc: Do not write lock zones for reset scsi: sd_zbc: Remove superfluous assignments scsi: sd: sd_zbc: Rename sd_zbc_setup_write_cmnd scsi: Improve scsi_get_sense_info_fld scsi: sd: Cleanup sd_done sense data handling scsi: sd: Improve sd_completed_bytes scsi: sd: Fix function descriptions scsi: mpt3sas: remove redundant wmb scsi: mpt: Move scsi_remove_host() out of mptscsih_remove_host() scsi: sg: reset 'res_in_use' after unlinking reserved array scsi: mvumi: remove code handling zero scsi_sg_count(scmd) case scsi: fusion: fix spelling mistake: "Persistancy" -> "Persistency" ...
This commit is contained in:
@@ -115,6 +115,7 @@ static void sd_rescan(struct device *);
|
||||
static int sd_init_command(struct scsi_cmnd *SCpnt);
|
||||
static void sd_uninit_command(struct scsi_cmnd *SCpnt);
|
||||
static int sd_done(struct scsi_cmnd *);
|
||||
static void sd_eh_reset(struct scsi_cmnd *);
|
||||
static int sd_eh_action(struct scsi_cmnd *, int);
|
||||
static void sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer);
|
||||
static void scsi_disk_release(struct device *cdev);
|
||||
@@ -573,6 +574,7 @@ static struct scsi_driver sd_template = {
|
||||
.uninit_command = sd_uninit_command,
|
||||
.done = sd_done,
|
||||
.eh_action = sd_eh_action,
|
||||
.eh_reset = sd_eh_reset,
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -888,8 +890,8 @@ out:
|
||||
* sd_setup_write_same_cmnd - write the same data to multiple blocks
|
||||
* @cmd: command to prepare
|
||||
*
|
||||
* Will issue either WRITE SAME(10) or WRITE SAME(16) depending on
|
||||
* preference indicated by target device.
|
||||
* Will set up either WRITE SAME(10) or WRITE SAME(16) depending on
|
||||
* the preference indicated by the target device.
|
||||
**/
|
||||
static int sd_setup_write_same_cmnd(struct scsi_cmnd *cmd)
|
||||
{
|
||||
@@ -908,7 +910,7 @@ static int sd_setup_write_same_cmnd(struct scsi_cmnd *cmd)
|
||||
BUG_ON(bio_offset(bio) || bio_iovec(bio).bv_len != sdp->sector_size);
|
||||
|
||||
if (sd_is_zoned(sdkp)) {
|
||||
ret = sd_zbc_setup_write_cmnd(cmd);
|
||||
ret = sd_zbc_write_lock_zone(cmd);
|
||||
if (ret != BLKPREP_OK)
|
||||
return ret;
|
||||
}
|
||||
@@ -980,7 +982,7 @@ static int sd_setup_read_write_cmnd(struct scsi_cmnd *SCpnt)
|
||||
unsigned char protect;
|
||||
|
||||
if (zoned_write) {
|
||||
ret = sd_zbc_setup_write_cmnd(SCpnt);
|
||||
ret = sd_zbc_write_lock_zone(SCpnt);
|
||||
if (ret != BLKPREP_OK)
|
||||
return ret;
|
||||
}
|
||||
@@ -1207,7 +1209,7 @@ static int sd_setup_read_write_cmnd(struct scsi_cmnd *SCpnt)
|
||||
ret = BLKPREP_OK;
|
||||
out:
|
||||
if (zoned_write && ret != BLKPREP_OK)
|
||||
sd_zbc_cancel_write_cmnd(SCpnt);
|
||||
sd_zbc_write_unlock_zone(SCpnt);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1264,8 +1266,8 @@ static void sd_uninit_command(struct scsi_cmnd *SCpnt)
|
||||
|
||||
/**
|
||||
* sd_open - open a scsi disk device
|
||||
* @inode: only i_rdev member may be used
|
||||
* @filp: only f_mode and f_flags may be used
|
||||
* @bdev: Block device of the scsi disk to open
|
||||
* @mode: FMODE_* mask
|
||||
*
|
||||
* Returns 0 if successful. Returns a negated errno value in case
|
||||
* of error.
|
||||
@@ -1341,8 +1343,8 @@ error_out:
|
||||
/**
|
||||
* sd_release - invoked when the (last) close(2) is called on this
|
||||
* scsi disk.
|
||||
* @inode: only i_rdev member may be used
|
||||
* @filp: only f_mode and f_flags may be used
|
||||
* @disk: disk to release
|
||||
* @mode: FMODE_* mask
|
||||
*
|
||||
* Returns 0.
|
||||
*
|
||||
@@ -1398,8 +1400,8 @@ static int sd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
|
||||
|
||||
/**
|
||||
* sd_ioctl - process an ioctl
|
||||
* @inode: only i_rdev/i_bdev members may be used
|
||||
* @filp: only f_mode and f_flags may be used
|
||||
* @bdev: target block device
|
||||
* @mode: FMODE_* mask
|
||||
* @cmd: ioctl command number
|
||||
* @arg: this is third argument given to ioctl(2) system call.
|
||||
* Often contains a pointer.
|
||||
@@ -1761,6 +1763,26 @@ static const struct block_device_operations sd_fops = {
|
||||
.pr_ops = &sd_pr_ops,
|
||||
};
|
||||
|
||||
/**
|
||||
* sd_eh_reset - reset error handling callback
|
||||
* @scmd: sd-issued command that has failed
|
||||
*
|
||||
* This function is called by the SCSI midlayer before starting
|
||||
* SCSI EH. When counting medium access failures we have to be
|
||||
* careful to register it only only once per device and SCSI EH run;
|
||||
* there might be several timed out commands which will cause the
|
||||
* 'max_medium_access_timeouts' counter to trigger after the first
|
||||
* SCSI EH run already and set the device to offline.
|
||||
* So this function resets the internal counter before starting SCSI EH.
|
||||
**/
|
||||
static void sd_eh_reset(struct scsi_cmnd *scmd)
|
||||
{
|
||||
struct scsi_disk *sdkp = scsi_disk(scmd->request->rq_disk);
|
||||
|
||||
/* New SCSI EH run, reset gate variable */
|
||||
sdkp->ignore_medium_access_errors = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* sd_eh_action - error handling callback
|
||||
* @scmd: sd-issued command that has failed
|
||||
@@ -1790,7 +1812,10 @@ static int sd_eh_action(struct scsi_cmnd *scmd, int eh_disp)
|
||||
* process of recovering or has it suffered an internal failure
|
||||
* that prevents access to the storage medium.
|
||||
*/
|
||||
sdkp->medium_access_timed_out++;
|
||||
if (!sdkp->ignore_medium_access_errors) {
|
||||
sdkp->medium_access_timed_out++;
|
||||
sdkp->ignore_medium_access_errors = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the device keeps failing read/write commands but TEST UNIT
|
||||
@@ -1802,7 +1827,7 @@ static int sd_eh_action(struct scsi_cmnd *scmd, int eh_disp)
|
||||
"Medium access timeout failure. Offlining disk!\n");
|
||||
scsi_device_set_state(scmd->device, SDEV_OFFLINE);
|
||||
|
||||
return FAILED;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
return eh_disp;
|
||||
@@ -1810,41 +1835,44 @@ static int sd_eh_action(struct scsi_cmnd *scmd, int eh_disp)
|
||||
|
||||
static unsigned int sd_completed_bytes(struct scsi_cmnd *scmd)
|
||||
{
|
||||
u64 start_lba = blk_rq_pos(scmd->request);
|
||||
u64 end_lba = blk_rq_pos(scmd->request) + (scsi_bufflen(scmd) / 512);
|
||||
u64 factor = scmd->device->sector_size / 512;
|
||||
u64 bad_lba;
|
||||
int info_valid;
|
||||
struct request *req = scmd->request;
|
||||
struct scsi_device *sdev = scmd->device;
|
||||
unsigned int transferred, good_bytes;
|
||||
u64 start_lba, end_lba, bad_lba;
|
||||
|
||||
/*
|
||||
* Some commands have a payload smaller than the device logical
|
||||
* block size (e.g. INQUIRY on a 4K disk).
|
||||
*/
|
||||
if (scsi_bufflen(scmd) <= sdev->sector_size)
|
||||
return 0;
|
||||
|
||||
/* Check if we have a 'bad_lba' information */
|
||||
if (!scsi_get_sense_info_fld(scmd->sense_buffer,
|
||||
SCSI_SENSE_BUFFERSIZE,
|
||||
&bad_lba))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* If the bad lba was reported incorrectly, we have no idea where
|
||||
* the error is.
|
||||
*/
|
||||
start_lba = sectors_to_logical(sdev, blk_rq_pos(req));
|
||||
end_lba = start_lba + bytes_to_logical(sdev, scsi_bufflen(scmd));
|
||||
if (bad_lba < start_lba || bad_lba >= end_lba)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* resid is optional but mostly filled in. When it's unused,
|
||||
* its value is zero, so we assume the whole buffer transferred
|
||||
*/
|
||||
unsigned int transferred = scsi_bufflen(scmd) - scsi_get_resid(scmd);
|
||||
unsigned int good_bytes;
|
||||
transferred = scsi_bufflen(scmd) - scsi_get_resid(scmd);
|
||||
|
||||
info_valid = scsi_get_sense_info_fld(scmd->sense_buffer,
|
||||
SCSI_SENSE_BUFFERSIZE,
|
||||
&bad_lba);
|
||||
if (!info_valid)
|
||||
return 0;
|
||||
|
||||
if (scsi_bufflen(scmd) <= scmd->device->sector_size)
|
||||
return 0;
|
||||
|
||||
/* be careful ... don't want any overflows */
|
||||
do_div(start_lba, factor);
|
||||
do_div(end_lba, factor);
|
||||
|
||||
/* The bad lba was reported incorrectly, we have no idea where
|
||||
* the error is.
|
||||
/* This computation should always be done in terms of the
|
||||
* resolution of the device's medium.
|
||||
*/
|
||||
if (bad_lba < start_lba || bad_lba >= end_lba)
|
||||
return 0;
|
||||
good_bytes = logical_to_bytes(sdev, bad_lba - start_lba);
|
||||
|
||||
/* This computation should always be done in terms of
|
||||
* the resolution of the device's medium.
|
||||
*/
|
||||
good_bytes = (bad_lba - start_lba) * scmd->device->sector_size;
|
||||
return min(good_bytes, transferred);
|
||||
}
|
||||
|
||||
@@ -1866,8 +1894,6 @@ static int sd_done(struct scsi_cmnd *SCpnt)
|
||||
struct request *req = SCpnt->request;
|
||||
int sense_valid = 0;
|
||||
int sense_deferred = 0;
|
||||
unsigned char op = SCpnt->cmnd[0];
|
||||
unsigned char unmap = SCpnt->cmnd[1] & 8;
|
||||
|
||||
switch (req_op(req)) {
|
||||
case REQ_OP_DISCARD:
|
||||
@@ -1941,26 +1967,27 @@ static int sd_done(struct scsi_cmnd *SCpnt)
|
||||
good_bytes = sd_completed_bytes(SCpnt);
|
||||
break;
|
||||
case ILLEGAL_REQUEST:
|
||||
if (sshdr.asc == 0x10) /* DIX: Host detected corruption */
|
||||
switch (sshdr.asc) {
|
||||
case 0x10: /* DIX: Host detected corruption */
|
||||
good_bytes = sd_completed_bytes(SCpnt);
|
||||
/* INVALID COMMAND OPCODE or INVALID FIELD IN CDB */
|
||||
if (sshdr.asc == 0x20 || sshdr.asc == 0x24) {
|
||||
switch (op) {
|
||||
break;
|
||||
case 0x20: /* INVALID COMMAND OPCODE */
|
||||
case 0x24: /* INVALID FIELD IN CDB */
|
||||
switch (SCpnt->cmnd[0]) {
|
||||
case UNMAP:
|
||||
sd_config_discard(sdkp, SD_LBP_DISABLE);
|
||||
break;
|
||||
case WRITE_SAME_16:
|
||||
case WRITE_SAME:
|
||||
if (unmap)
|
||||
if (SCpnt->cmnd[1] & 8) { /* UNMAP */
|
||||
sd_config_discard(sdkp, SD_LBP_DISABLE);
|
||||
else {
|
||||
} else {
|
||||
sdkp->device->no_write_same = 1;
|
||||
sd_config_write_same(sdkp);
|
||||
|
||||
good_bytes = 0;
|
||||
req->__data_len = blk_rq_bytes(req);
|
||||
req->rq_flags |= RQF_QUIET;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -2798,7 +2825,7 @@ static void sd_read_app_tag_own(struct scsi_disk *sdkp, unsigned char *buffer)
|
||||
|
||||
/**
|
||||
* sd_read_block_limits - Query disk device for preferred I/O sizes.
|
||||
* @disk: disk to query
|
||||
* @sdkp: disk to query
|
||||
*/
|
||||
static void sd_read_block_limits(struct scsi_disk *sdkp)
|
||||
{
|
||||
@@ -2864,7 +2891,7 @@ static void sd_read_block_limits(struct scsi_disk *sdkp)
|
||||
|
||||
/**
|
||||
* sd_read_block_characteristics - Query block dev. characteristics
|
||||
* @disk: disk to query
|
||||
* @sdkp: disk to query
|
||||
*/
|
||||
static void sd_read_block_characteristics(struct scsi_disk *sdkp)
|
||||
{
|
||||
@@ -2912,7 +2939,7 @@ static void sd_read_block_characteristics(struct scsi_disk *sdkp)
|
||||
|
||||
/**
|
||||
* sd_read_block_provisioning - Query provisioning VPD page
|
||||
* @disk: disk to query
|
||||
* @sdkp: disk to query
|
||||
*/
|
||||
static void sd_read_block_provisioning(struct scsi_disk *sdkp)
|
||||
{
|
||||
|
Reference in New Issue
Block a user