aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/device_handler
diff options
context:
space:
mode:
authorRob Evers <revers@redhat.com>2012-05-18 14:08:55 -0400
committerJames Bottomley <JBottomley@Parallels.com>2012-07-20 03:58:33 -0400
commit8e67ce6072a0ab7fcefbbd2913fa4eaf3fdd8d68 (patch)
tree6dec5de54afc11f0a1cc91b3f00ba114bc792da3 /drivers/scsi/device_handler
parent3588c5a21aef8c8dcc3b30d72c62971e97af1322 (diff)
[SCSI] scsi_dh_alua: retry alua rtpg extended header for illegal request response
Some storage arrays are known to return 'illegal request' when an rtpg extended header request is made. T10 says the array should ignore the bit, and return the non-extended rtpg as the array doesn't support the request. Working around this by retrying the rtpg request without the extended header bit set when the extended rtpg request results in illegal request. Signed-off-by: Rob Evers <revers@redhat.com> Reviewed-by: Babu Moger <babu.moger@netapp.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
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 ac6fddf99e99..5a3448856962 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;