aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/device_handler
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/device_handler')
-rw-r--r--drivers/scsi/device_handler/scsi_dh_alua.c26
1 files changed, 23 insertions, 3 deletions
diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c
index ac6fddf99e9..5a344885696 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -178,7 +178,8 @@ done:
178 * submit_rtpg - Issue a REPORT TARGET GROUP STATES command 178 * submit_rtpg - Issue a REPORT TARGET GROUP STATES command
179 * @sdev: sdev the command should be sent to 179 * @sdev: sdev the command should be sent to
180 */ 180 */
181static unsigned submit_rtpg(struct scsi_device *sdev, struct alua_dh_data *h) 181static unsigned submit_rtpg(struct scsi_device *sdev, struct alua_dh_data *h,
182 bool rtpg_ext_hdr_req)
182{ 183{
183 struct request *rq; 184 struct request *rq;
184 int err = SCSI_DH_RES_TEMP_UNAVAIL; 185 int err = SCSI_DH_RES_TEMP_UNAVAIL;
@@ -189,7 +190,10 @@ static unsigned submit_rtpg(struct scsi_device *sdev, struct alua_dh_data *h)
189 190
190 /* Prepare the command. */ 191 /* Prepare the command. */
191 rq->cmd[0] = MAINTENANCE_IN; 192 rq->cmd[0] = MAINTENANCE_IN;
192 rq->cmd[1] = MI_REPORT_TARGET_PGS | MI_EXT_HDR_PARAM_FMT; 193 if (rtpg_ext_hdr_req)
194 rq->cmd[1] = MI_REPORT_TARGET_PGS | MI_EXT_HDR_PARAM_FMT;
195 else
196 rq->cmd[1] = MI_REPORT_TARGET_PGS;
193 rq->cmd[6] = (h->bufflen >> 24) & 0xff; 197 rq->cmd[6] = (h->bufflen >> 24) & 0xff;
194 rq->cmd[7] = (h->bufflen >> 16) & 0xff; 198 rq->cmd[7] = (h->bufflen >> 16) & 0xff;
195 rq->cmd[8] = (h->bufflen >> 8) & 0xff; 199 rq->cmd[8] = (h->bufflen >> 8) & 0xff;
@@ -522,6 +526,7 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h)
522 int len, k, off, valid_states = 0; 526 int len, k, off, valid_states = 0;
523 unsigned char *ucp; 527 unsigned char *ucp;
524 unsigned err; 528 unsigned err;
529 bool rtpg_ext_hdr_req = 1;
525 unsigned long expiry, interval = 1000; 530 unsigned long expiry, interval = 1000;
526 unsigned int tpg_desc_tbl_off; 531 unsigned int tpg_desc_tbl_off;
527 unsigned char orig_transition_tmo; 532 unsigned char orig_transition_tmo;
@@ -532,7 +537,7 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h)
532 expiry = round_jiffies_up(jiffies + h->transition_tmo * HZ); 537 expiry = round_jiffies_up(jiffies + h->transition_tmo * HZ);
533 538
534 retry: 539 retry:
535 err = submit_rtpg(sdev, h); 540 err = submit_rtpg(sdev, h, rtpg_ext_hdr_req);
536 541
537 if (err == SCSI_DH_IO && h->senselen > 0) { 542 if (err == SCSI_DH_IO && h->senselen > 0) {
538 err = scsi_normalize_sense(h->sense, SCSI_SENSE_BUFFERSIZE, 543 err = scsi_normalize_sense(h->sense, SCSI_SENSE_BUFFERSIZE,
@@ -540,6 +545,21 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h)
540 if (!err) 545 if (!err)
541 return SCSI_DH_IO; 546 return SCSI_DH_IO;
542 547
548 /*
549 * submit_rtpg() has failed on existing arrays
550 * when requesting extended header info, and
551 * the array doesn't support extended headers,
552 * even though it shouldn't according to T10.
553 * The retry without rtpg_ext_hdr_req set
554 * handles this.
555 */
556 if (rtpg_ext_hdr_req == 1 &&
557 sense_hdr.sense_key == ILLEGAL_REQUEST &&
558 sense_hdr.asc == 0x24 && sense_hdr.ascq == 0) {
559 rtpg_ext_hdr_req = 0;
560 goto retry;
561 }
562
543 err = alua_check_sense(sdev, &sense_hdr); 563 err = alua_check_sense(sdev, &sense_hdr);
544 if (err == ADD_TO_MLQUEUE && time_before(jiffies, expiry)) 564 if (err == ADD_TO_MLQUEUE && time_before(jiffies, expiry))
545 goto retry; 565 goto retry;