Commit bd7f0ef2 authored by Martin K. Petersen's avatar Martin K. Petersen

Merge patch series "scsi: sshdr and retry fixes"

Mike Christie <michael.christie@oracle.com> says:

The following patches were made over Linus tree (Martin's 6.7 branch
was missing some changes to sd.c). They only contain the sshdr and
rdac retry fixes from the "Allow scsi_execute users to control
retries" patchset.

The patches in this set are reviewed and tested but the changes to how
we do retries will take a little longer and require more testing, so I
broke up the series to make them easier to review.

Link: https://lore.kernel.org/r/20231004210013.5601-1-michael.christie@oracle.comSigned-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parents 1caddfc5 f7d7129c
...@@ -82,7 +82,7 @@ static int hp_sw_tur(struct scsi_device *sdev, struct hp_sw_dh_data *h) ...@@ -82,7 +82,7 @@ static int hp_sw_tur(struct scsi_device *sdev, struct hp_sw_dh_data *h)
{ {
unsigned char cmd[6] = { TEST_UNIT_READY }; unsigned char cmd[6] = { TEST_UNIT_READY };
struct scsi_sense_hdr sshdr; struct scsi_sense_hdr sshdr;
int ret = SCSI_DH_OK, res; int ret, res;
blk_opf_t opf = REQ_OP_DRV_IN | REQ_FAILFAST_DEV | blk_opf_t opf = REQ_OP_DRV_IN | REQ_FAILFAST_DEV |
REQ_FAILFAST_TRANSPORT | REQ_FAILFAST_DRIVER; REQ_FAILFAST_TRANSPORT | REQ_FAILFAST_DRIVER;
const struct scsi_exec_args exec_args = { const struct scsi_exec_args exec_args = {
...@@ -92,19 +92,18 @@ static int hp_sw_tur(struct scsi_device *sdev, struct hp_sw_dh_data *h) ...@@ -92,19 +92,18 @@ static int hp_sw_tur(struct scsi_device *sdev, struct hp_sw_dh_data *h)
retry: retry:
res = scsi_execute_cmd(sdev, cmd, opf, NULL, 0, HP_SW_TIMEOUT, res = scsi_execute_cmd(sdev, cmd, opf, NULL, 0, HP_SW_TIMEOUT,
HP_SW_RETRIES, &exec_args); HP_SW_RETRIES, &exec_args);
if (res) { if (res > 0 && scsi_sense_valid(&sshdr)) {
if (scsi_sense_valid(&sshdr)) ret = tur_done(sdev, h, &sshdr);
ret = tur_done(sdev, h, &sshdr); } else if (res == 0) {
else {
sdev_printk(KERN_WARNING, sdev,
"%s: sending tur failed with %x\n",
HP_SW_NAME, res);
ret = SCSI_DH_IO;
}
} else {
h->path_state = HP_SW_PATH_ACTIVE; h->path_state = HP_SW_PATH_ACTIVE;
ret = SCSI_DH_OK; ret = SCSI_DH_OK;
} else {
sdev_printk(KERN_WARNING, sdev,
"%s: sending tur failed with %x\n",
HP_SW_NAME, res);
ret = SCSI_DH_IO;
} }
if (ret == SCSI_DH_IMM_RETRY) if (ret == SCSI_DH_IMM_RETRY)
goto retry; goto retry;
...@@ -122,7 +121,7 @@ static int hp_sw_start_stop(struct hp_sw_dh_data *h) ...@@ -122,7 +121,7 @@ static int hp_sw_start_stop(struct hp_sw_dh_data *h)
unsigned char cmd[6] = { START_STOP, 0, 0, 0, 1, 0 }; unsigned char cmd[6] = { START_STOP, 0, 0, 0, 1, 0 };
struct scsi_sense_hdr sshdr; struct scsi_sense_hdr sshdr;
struct scsi_device *sdev = h->sdev; struct scsi_device *sdev = h->sdev;
int res, rc = SCSI_DH_OK; int res, rc;
int retry_cnt = HP_SW_RETRIES; int retry_cnt = HP_SW_RETRIES;
blk_opf_t opf = REQ_OP_DRV_IN | REQ_FAILFAST_DEV | blk_opf_t opf = REQ_OP_DRV_IN | REQ_FAILFAST_DEV |
REQ_FAILFAST_TRANSPORT | REQ_FAILFAST_DRIVER; REQ_FAILFAST_TRANSPORT | REQ_FAILFAST_DRIVER;
...@@ -133,35 +132,37 @@ static int hp_sw_start_stop(struct hp_sw_dh_data *h) ...@@ -133,35 +132,37 @@ static int hp_sw_start_stop(struct hp_sw_dh_data *h)
retry: retry:
res = scsi_execute_cmd(sdev, cmd, opf, NULL, 0, HP_SW_TIMEOUT, res = scsi_execute_cmd(sdev, cmd, opf, NULL, 0, HP_SW_TIMEOUT,
HP_SW_RETRIES, &exec_args); HP_SW_RETRIES, &exec_args);
if (res) { if (!res) {
if (!scsi_sense_valid(&sshdr)) { return SCSI_DH_OK;
sdev_printk(KERN_WARNING, sdev, } else if (res < 0 || !scsi_sense_valid(&sshdr)) {
"%s: sending start_stop_unit failed, " sdev_printk(KERN_WARNING, sdev,
"no sense available\n", HP_SW_NAME); "%s: sending start_stop_unit failed, "
return SCSI_DH_IO; "no sense available\n", HP_SW_NAME);
} return SCSI_DH_IO;
switch (sshdr.sense_key) { }
case NOT_READY:
if (sshdr.asc == 0x04 && sshdr.ascq == 3) { switch (sshdr.sense_key) {
/* case NOT_READY:
* LUN not ready - manual intervention required if (sshdr.asc == 0x04 && sshdr.ascq == 3) {
* /*
* Switch-over in progress, retry. * LUN not ready - manual intervention required
*/ *
if (--retry_cnt) * Switch-over in progress, retry.
goto retry; */
rc = SCSI_DH_RETRY; if (--retry_cnt)
break; goto retry;
} rc = SCSI_DH_RETRY;
fallthrough; break;
default:
sdev_printk(KERN_WARNING, sdev,
"%s: sending start_stop_unit failed, "
"sense %x/%x/%x\n", HP_SW_NAME,
sshdr.sense_key, sshdr.asc, sshdr.ascq);
rc = SCSI_DH_IO;
} }
fallthrough;
default:
sdev_printk(KERN_WARNING, sdev,
"%s: sending start_stop_unit failed, "
"sense %x/%x/%x\n", HP_SW_NAME,
sshdr.sense_key, sshdr.asc, sshdr.ascq);
rc = SCSI_DH_IO;
} }
return rc; return rc;
} }
......
...@@ -530,7 +530,7 @@ static void send_mode_select(struct work_struct *work) ...@@ -530,7 +530,7 @@ static void send_mode_select(struct work_struct *work)
container_of(work, struct rdac_controller, ms_work); container_of(work, struct rdac_controller, ms_work);
struct scsi_device *sdev = ctlr->ms_sdev; struct scsi_device *sdev = ctlr->ms_sdev;
struct rdac_dh_data *h = sdev->handler_data; struct rdac_dh_data *h = sdev->handler_data;
int err = SCSI_DH_OK, retry_cnt = RDAC_RETRY_COUNT; int rc, err, retry_cnt = RDAC_RETRY_COUNT;
struct rdac_queue_data *tmp, *qdata; struct rdac_queue_data *tmp, *qdata;
LIST_HEAD(list); LIST_HEAD(list);
unsigned char cdb[MAX_COMMAND_SIZE]; unsigned char cdb[MAX_COMMAND_SIZE];
...@@ -558,20 +558,23 @@ static void send_mode_select(struct work_struct *work) ...@@ -558,20 +558,23 @@ static void send_mode_select(struct work_struct *work)
(char *) h->ctlr->array_name, h->ctlr->index, (char *) h->ctlr->array_name, h->ctlr->index,
(retry_cnt == RDAC_RETRY_COUNT) ? "queueing" : "retrying"); (retry_cnt == RDAC_RETRY_COUNT) ? "queueing" : "retrying");
if (scsi_execute_cmd(sdev, cdb, opf, &h->ctlr->mode_select, data_size, rc = scsi_execute_cmd(sdev, cdb, opf, &h->ctlr->mode_select, data_size,
RDAC_TIMEOUT * HZ, RDAC_RETRIES, &exec_args)) { RDAC_TIMEOUT * HZ, RDAC_RETRIES, &exec_args);
if (!rc) {
h->state = RDAC_STATE_ACTIVE;
RDAC_LOG(RDAC_LOG_FAILOVER, sdev, "array %s, ctlr %d, "
"MODE_SELECT completed",
(char *) h->ctlr->array_name, h->ctlr->index);
err = SCSI_DH_OK;
} else if (rc < 0) {
err = SCSI_DH_IO;
} else {
err = mode_select_handle_sense(sdev, &sshdr); err = mode_select_handle_sense(sdev, &sshdr);
if (err == SCSI_DH_RETRY && retry_cnt--) if (err == SCSI_DH_RETRY && retry_cnt--)
goto retry; goto retry;
if (err == SCSI_DH_IMM_RETRY) if (err == SCSI_DH_IMM_RETRY)
goto retry; goto retry;
} }
if (err == SCSI_DH_OK) {
h->state = RDAC_STATE_ACTIVE;
RDAC_LOG(RDAC_LOG_FAILOVER, sdev, "array %s, ctlr %d, "
"MODE_SELECT completed",
(char *) h->ctlr->array_name, h->ctlr->index);
}
list_for_each_entry_safe(qdata, tmp, &list, entry) { list_for_each_entry_safe(qdata, tmp, &list, entry) {
list_del(&qdata->entry); list_del(&qdata->entry);
......
...@@ -692,7 +692,7 @@ int scsi_cdl_enable(struct scsi_device *sdev, bool enable) ...@@ -692,7 +692,7 @@ int scsi_cdl_enable(struct scsi_device *sdev, bool enable)
ret = scsi_mode_select(sdev, 1, 0, buf_data, len, 5 * HZ, 3, ret = scsi_mode_select(sdev, 1, 0, buf_data, len, 5 * HZ, 3,
&data, &sshdr); &data, &sshdr);
if (ret) { if (ret) {
if (scsi_sense_valid(&sshdr)) if (ret > 0 && scsi_sense_valid(&sshdr))
scsi_print_sense_hdr(sdev, scsi_print_sense_hdr(sdev,
dev_name(&sdev->sdev_gendev), &sshdr); dev_name(&sdev->sdev_gendev), &sshdr);
return ret; return ret;
......
...@@ -2299,10 +2299,10 @@ scsi_test_unit_ready(struct scsi_device *sdev, int timeout, int retries, ...@@ -2299,10 +2299,10 @@ scsi_test_unit_ready(struct scsi_device *sdev, int timeout, int retries,
do { do {
result = scsi_execute_cmd(sdev, cmd, REQ_OP_DRV_IN, NULL, 0, result = scsi_execute_cmd(sdev, cmd, REQ_OP_DRV_IN, NULL, 0,
timeout, 1, &exec_args); timeout, 1, &exec_args);
if (sdev->removable && scsi_sense_valid(sshdr) && if (sdev->removable && result > 0 && scsi_sense_valid(sshdr) &&
sshdr->sense_key == UNIT_ATTENTION) sshdr->sense_key == UNIT_ATTENTION)
sdev->changed = 1; sdev->changed = 1;
} while (scsi_sense_valid(sshdr) && } while (result > 0 && scsi_sense_valid(sshdr) &&
sshdr->sense_key == UNIT_ATTENTION && --retries); sshdr->sense_key == UNIT_ATTENTION && --retries);
return result; return result;
......
...@@ -676,10 +676,10 @@ spi_dv_device_echo_buffer(struct scsi_device *sdev, u8 *buffer, ...@@ -676,10 +676,10 @@ spi_dv_device_echo_buffer(struct scsi_device *sdev, u8 *buffer,
for (r = 0; r < retries; r++) { for (r = 0; r < retries; r++) {
result = spi_execute(sdev, spi_write_buffer, REQ_OP_DRV_OUT, result = spi_execute(sdev, spi_write_buffer, REQ_OP_DRV_OUT,
buffer, len, &sshdr); buffer, len, &sshdr);
if(result || !scsi_device_online(sdev)) { if (result || !scsi_device_online(sdev)) {
scsi_device_set_state(sdev, SDEV_QUIESCE); scsi_device_set_state(sdev, SDEV_QUIESCE);
if (scsi_sense_valid(&sshdr) if (result > 0 && scsi_sense_valid(&sshdr)
&& sshdr.sense_key == ILLEGAL_REQUEST && sshdr.sense_key == ILLEGAL_REQUEST
/* INVALID FIELD IN CDB */ /* INVALID FIELD IN CDB */
&& sshdr.asc == 0x24 && sshdr.ascq == 0x00) && sshdr.asc == 0x24 && sshdr.ascq == 0x00)
......
...@@ -143,7 +143,7 @@ cache_type_store(struct device *dev, struct device_attribute *attr, ...@@ -143,7 +143,7 @@ cache_type_store(struct device *dev, struct device_attribute *attr,
struct scsi_mode_data data; struct scsi_mode_data data;
struct scsi_sense_hdr sshdr; struct scsi_sense_hdr sshdr;
static const char temp[] = "temporary "; static const char temp[] = "temporary ";
int len; int len, ret;
if (sdp->type != TYPE_DISK && sdp->type != TYPE_ZBC) if (sdp->type != TYPE_DISK && sdp->type != TYPE_ZBC)
/* no cache control on RBC devices; theoretically they /* no cache control on RBC devices; theoretically they
...@@ -190,9 +190,10 @@ cache_type_store(struct device *dev, struct device_attribute *attr, ...@@ -190,9 +190,10 @@ cache_type_store(struct device *dev, struct device_attribute *attr,
*/ */
data.device_specific = 0; data.device_specific = 0;
if (scsi_mode_select(sdp, 1, sp, buffer_data, len, SD_TIMEOUT, ret = scsi_mode_select(sdp, 1, sp, buffer_data, len, SD_TIMEOUT,
sdkp->max_retries, &data, &sshdr)) { sdkp->max_retries, &data, &sshdr);
if (scsi_sense_valid(&sshdr)) if (ret) {
if (ret > 0 && scsi_sense_valid(&sshdr))
sd_print_sense_hdr(sdkp, &sshdr); sd_print_sense_hdr(sdkp, &sshdr);
return -EINVAL; return -EINVAL;
} }
...@@ -2180,19 +2181,21 @@ sd_spinup_disk(struct scsi_disk *sdkp) ...@@ -2180,19 +2181,21 @@ sd_spinup_disk(struct scsi_disk *sdkp)
sdkp->max_retries, sdkp->max_retries,
&exec_args); &exec_args);
/* if (the_result > 0) {
* If the drive has indicated to us that it /*
* doesn't have any media in it, don't bother * If the drive has indicated to us that it
* with any more polling. * doesn't have any media in it, don't bother
*/ * with any more polling.
if (media_not_present(sdkp, &sshdr)) { */
if (media_was_present) if (media_not_present(sdkp, &sshdr)) {
sd_printk(KERN_NOTICE, sdkp, "Media removed, stopped polling\n"); if (media_was_present)
return; sd_printk(KERN_NOTICE, sdkp,
} "Media removed, stopped polling\n");
return;
}
if (the_result)
sense_valid = scsi_sense_valid(&sshdr); sense_valid = scsi_sense_valid(&sshdr);
}
retries++; retries++;
} while (retries < 3 && } while (retries < 3 &&
(!scsi_status_is_good(the_result) || (!scsi_status_is_good(the_result) ||
...@@ -2388,11 +2391,10 @@ static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp, ...@@ -2388,11 +2391,10 @@ static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp,
the_result = scsi_execute_cmd(sdp, cmd, REQ_OP_DRV_IN, the_result = scsi_execute_cmd(sdp, cmd, REQ_OP_DRV_IN,
buffer, RC16_LEN, SD_TIMEOUT, buffer, RC16_LEN, SD_TIMEOUT,
sdkp->max_retries, &exec_args); sdkp->max_retries, &exec_args);
if (media_not_present(sdkp, &sshdr))
return -ENODEV;
if (the_result > 0) { if (the_result > 0) {
if (media_not_present(sdkp, &sshdr))
return -ENODEV;
sense_valid = scsi_sense_valid(&sshdr); sense_valid = scsi_sense_valid(&sshdr);
if (sense_valid && if (sense_valid &&
sshdr.sense_key == ILLEGAL_REQUEST && sshdr.sense_key == ILLEGAL_REQUEST &&
...@@ -2889,7 +2891,7 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer) ...@@ -2889,7 +2891,7 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer)
} }
bad_sense: bad_sense:
if (scsi_sense_valid(&sshdr) && if (res == -EIO && scsi_sense_valid(&sshdr) &&
sshdr.sense_key == ILLEGAL_REQUEST && sshdr.sense_key == ILLEGAL_REQUEST &&
sshdr.asc == 0x24 && sshdr.ascq == 0x0) sshdr.asc == 0x24 && sshdr.ascq == 0x0)
/* Invalid field in CDB */ /* Invalid field in CDB */
...@@ -2937,7 +2939,7 @@ static void sd_read_app_tag_own(struct scsi_disk *sdkp, unsigned char *buffer) ...@@ -2937,7 +2939,7 @@ static void sd_read_app_tag_own(struct scsi_disk *sdkp, unsigned char *buffer)
sd_first_printk(KERN_WARNING, sdkp, sd_first_printk(KERN_WARNING, sdkp,
"getting Control mode page failed, assume no ATO\n"); "getting Control mode page failed, assume no ATO\n");
if (scsi_sense_valid(&sshdr)) if (res == -EIO && scsi_sense_valid(&sshdr))
sd_print_sense_hdr(sdkp, &sshdr); sd_print_sense_hdr(sdkp, &sshdr);
return; return;
......
...@@ -177,7 +177,8 @@ static unsigned int sr_get_events(struct scsi_device *sdev) ...@@ -177,7 +177,8 @@ static unsigned int sr_get_events(struct scsi_device *sdev)
result = scsi_execute_cmd(sdev, cmd, REQ_OP_DRV_IN, buf, sizeof(buf), result = scsi_execute_cmd(sdev, cmd, REQ_OP_DRV_IN, buf, sizeof(buf),
SR_TIMEOUT, MAX_RETRIES, &exec_args); SR_TIMEOUT, MAX_RETRIES, &exec_args);
if (scsi_sense_valid(&sshdr) && sshdr.sense_key == UNIT_ATTENTION) if (result > 0 && scsi_sense_valid(&sshdr) &&
sshdr.sense_key == UNIT_ATTENTION)
return DISK_EVENT_MEDIA_CHANGE; return DISK_EVENT_MEDIA_CHANGE;
if (result || be16_to_cpu(eh->data_len) < sizeof(*med)) if (result || be16_to_cpu(eh->data_len) < sizeof(*med))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment