diff options
Diffstat (limited to 'drivers/scsi/device_handler')
| -rw-r--r-- | drivers/scsi/device_handler/scsi_dh_alua.c | 26 |
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 | */ |
| 181 | static unsigned submit_rtpg(struct scsi_device *sdev, struct alua_dh_data *h) | 181 | static 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; |
