mirror of
https://github.com/torvalds/linux
synced 2024-11-05 18:23:50 +00:00
scsi_dh_emc: switch to scsi_execute_req_flags()
Switch to scsi_execute_req_flags() and scsi_get_vpd_page() instead of open-coding it. Using scsi_execute_req_flags() will set REQ_QUIET and REQ_PREEMPT, but this is okay as we're evaluating the errors anyway and should be able to send the command even if the device is quiesced. Signed-off-by: Hannes Reinecke <hare@suse.com> Signed-off-by: Christoph Hellwig <hch@lst.de> Acked-by: Martin K. Petersen <martin.petersen@oracle.com> Signed-off-by: Jens Axboe <axboe@fb.com>
This commit is contained in:
parent
3278255741
commit
b78205c932
1 changed files with 54 additions and 189 deletions
|
@ -87,12 +87,6 @@ struct clariion_dh_data {
|
|||
* I/O buffer for both MODE_SELECT and INQUIRY commands.
|
||||
*/
|
||||
unsigned char buffer[CLARIION_BUFFER_SIZE];
|
||||
/*
|
||||
* SCSI sense buffer for commands -- assumes serial issuance
|
||||
* and completion sequence of all commands for same multipath.
|
||||
*/
|
||||
unsigned char sense[SCSI_SENSE_BUFFERSIZE];
|
||||
unsigned int senselen;
|
||||
/*
|
||||
* LUN state
|
||||
*/
|
||||
|
@ -116,44 +110,38 @@ struct clariion_dh_data {
|
|||
/*
|
||||
* Parse MODE_SELECT cmd reply.
|
||||
*/
|
||||
static int trespass_endio(struct scsi_device *sdev, char *sense)
|
||||
static int trespass_endio(struct scsi_device *sdev,
|
||||
struct scsi_sense_hdr *sshdr)
|
||||
{
|
||||
int err = SCSI_DH_IO;
|
||||
struct scsi_sense_hdr sshdr;
|
||||
|
||||
if (!scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, &sshdr)) {
|
||||
sdev_printk(KERN_ERR, sdev, "%s: Found valid sense data 0x%2x, "
|
||||
"0x%2x, 0x%2x while sending CLARiiON trespass "
|
||||
"command.\n", CLARIION_NAME, sshdr.sense_key,
|
||||
sshdr.asc, sshdr.ascq);
|
||||
sdev_printk(KERN_ERR, sdev, "%s: Found valid sense data 0x%2x, "
|
||||
"0x%2x, 0x%2x while sending CLARiiON trespass "
|
||||
"command.\n", CLARIION_NAME, sshdr->sense_key,
|
||||
sshdr->asc, sshdr->ascq);
|
||||
|
||||
if ((sshdr.sense_key == 0x05) && (sshdr.asc == 0x04) &&
|
||||
(sshdr.ascq == 0x00)) {
|
||||
/*
|
||||
* Array based copy in progress -- do not send
|
||||
* mode_select or copy will be aborted mid-stream.
|
||||
*/
|
||||
sdev_printk(KERN_INFO, sdev, "%s: Array Based Copy in "
|
||||
"progress while sending CLARiiON trespass "
|
||||
"command.\n", CLARIION_NAME);
|
||||
err = SCSI_DH_DEV_TEMP_BUSY;
|
||||
} else if ((sshdr.sense_key == 0x02) && (sshdr.asc == 0x04) &&
|
||||
(sshdr.ascq == 0x03)) {
|
||||
/*
|
||||
* LUN Not Ready - Manual Intervention Required
|
||||
* indicates in-progress ucode upgrade (NDU).
|
||||
*/
|
||||
sdev_printk(KERN_INFO, sdev, "%s: Detected in-progress "
|
||||
"ucode upgrade NDU operation while sending "
|
||||
"CLARiiON trespass command.\n", CLARIION_NAME);
|
||||
err = SCSI_DH_DEV_TEMP_BUSY;
|
||||
} else
|
||||
err = SCSI_DH_DEV_FAILED;
|
||||
} else {
|
||||
sdev_printk(KERN_INFO, sdev,
|
||||
"%s: failed to send MODE SELECT, no sense available\n",
|
||||
CLARIION_NAME);
|
||||
}
|
||||
if (sshdr->sense_key == 0x05 && sshdr->asc == 0x04 &&
|
||||
sshdr->ascq == 0x00) {
|
||||
/*
|
||||
* Array based copy in progress -- do not send
|
||||
* mode_select or copy will be aborted mid-stream.
|
||||
*/
|
||||
sdev_printk(KERN_INFO, sdev, "%s: Array Based Copy in "
|
||||
"progress while sending CLARiiON trespass "
|
||||
"command.\n", CLARIION_NAME);
|
||||
err = SCSI_DH_DEV_TEMP_BUSY;
|
||||
} else if (sshdr->sense_key == 0x02 && sshdr->asc == 0x04 &&
|
||||
sshdr->ascq == 0x03) {
|
||||
/*
|
||||
* LUN Not Ready - Manual Intervention Required
|
||||
* indicates in-progress ucode upgrade (NDU).
|
||||
*/
|
||||
sdev_printk(KERN_INFO, sdev, "%s: Detected in-progress "
|
||||
"ucode upgrade NDU operation while sending "
|
||||
"CLARiiON trespass command.\n", CLARIION_NAME);
|
||||
err = SCSI_DH_DEV_TEMP_BUSY;
|
||||
} else
|
||||
err = SCSI_DH_DEV_FAILED;
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -257,103 +245,15 @@ static char * parse_sp_model(struct scsi_device *sdev, unsigned char *buffer)
|
|||
return sp_model;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get block request for REQ_BLOCK_PC command issued to path. Currently
|
||||
* limited to MODE_SELECT (trespass) and INQUIRY (VPD page 0xC0) commands.
|
||||
*
|
||||
* Uses data and sense buffers in hardware handler context structure and
|
||||
* assumes serial servicing of commands, both issuance and completion.
|
||||
*/
|
||||
static struct request *get_req(struct scsi_device *sdev, int cmd,
|
||||
unsigned char *buffer)
|
||||
{
|
||||
struct request *rq;
|
||||
int len = 0;
|
||||
|
||||
rq = blk_get_request(sdev->request_queue,
|
||||
(cmd != INQUIRY) ? WRITE : READ, GFP_NOIO);
|
||||
if (IS_ERR(rq)) {
|
||||
sdev_printk(KERN_INFO, sdev, "get_req: blk_get_request failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
blk_rq_set_block_pc(rq);
|
||||
rq->cmd_len = COMMAND_SIZE(cmd);
|
||||
rq->cmd[0] = cmd;
|
||||
|
||||
switch (cmd) {
|
||||
case MODE_SELECT:
|
||||
len = sizeof(short_trespass);
|
||||
rq->cmd[1] = 0x10;
|
||||
rq->cmd[4] = len;
|
||||
break;
|
||||
case MODE_SELECT_10:
|
||||
len = sizeof(long_trespass);
|
||||
rq->cmd[1] = 0x10;
|
||||
rq->cmd[8] = len;
|
||||
break;
|
||||
case INQUIRY:
|
||||
len = CLARIION_BUFFER_SIZE;
|
||||
rq->cmd[4] = len;
|
||||
memset(buffer, 0, len);
|
||||
break;
|
||||
default:
|
||||
BUG_ON(1);
|
||||
break;
|
||||
}
|
||||
|
||||
rq->cmd_flags |= REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT |
|
||||
REQ_FAILFAST_DRIVER;
|
||||
rq->timeout = CLARIION_TIMEOUT;
|
||||
rq->retries = CLARIION_RETRIES;
|
||||
|
||||
if (blk_rq_map_kern(rq->q, rq, buffer, len, GFP_NOIO)) {
|
||||
blk_put_request(rq);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return rq;
|
||||
}
|
||||
|
||||
static int send_inquiry_cmd(struct scsi_device *sdev, int page,
|
||||
struct clariion_dh_data *csdev)
|
||||
{
|
||||
struct request *rq = get_req(sdev, INQUIRY, csdev->buffer);
|
||||
int err;
|
||||
|
||||
if (!rq)
|
||||
return SCSI_DH_RES_TEMP_UNAVAIL;
|
||||
|
||||
rq->sense = csdev->sense;
|
||||
memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
|
||||
rq->sense_len = csdev->senselen = 0;
|
||||
|
||||
rq->cmd[0] = INQUIRY;
|
||||
if (page != 0) {
|
||||
rq->cmd[1] = 1;
|
||||
rq->cmd[2] = page;
|
||||
}
|
||||
err = blk_execute_rq(sdev->request_queue, NULL, rq, 1);
|
||||
if (err == -EIO) {
|
||||
sdev_printk(KERN_INFO, sdev,
|
||||
"%s: failed to send %s INQUIRY: %x\n",
|
||||
CLARIION_NAME, page?"EVPD":"standard",
|
||||
rq->errors);
|
||||
csdev->senselen = rq->sense_len;
|
||||
err = SCSI_DH_IO;
|
||||
}
|
||||
|
||||
blk_put_request(rq);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int send_trespass_cmd(struct scsi_device *sdev,
|
||||
struct clariion_dh_data *csdev)
|
||||
{
|
||||
struct request *rq;
|
||||
unsigned char *page22;
|
||||
int err, len, cmd;
|
||||
unsigned char cdb[COMMAND_SIZE(MODE_SELECT)];
|
||||
int err, res = SCSI_DH_OK, len;
|
||||
struct scsi_sense_hdr sshdr;
|
||||
u64 req_flags = REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT |
|
||||
REQ_FAILFAST_DRIVER;
|
||||
|
||||
if (csdev->flags & CLARIION_SHORT_TRESPASS) {
|
||||
page22 = short_trespass;
|
||||
|
@ -361,40 +261,37 @@ static int send_trespass_cmd(struct scsi_device *sdev,
|
|||
/* Set Honor Reservations bit */
|
||||
page22[6] |= 0x80;
|
||||
len = sizeof(short_trespass);
|
||||
cmd = MODE_SELECT;
|
||||
cdb[0] = MODE_SELECT;
|
||||
cdb[1] = 0x10;
|
||||
cdb[4] = len;
|
||||
} else {
|
||||
page22 = long_trespass;
|
||||
if (!(csdev->flags & CLARIION_HONOR_RESERVATIONS))
|
||||
/* Set Honor Reservations bit */
|
||||
page22[10] |= 0x80;
|
||||
len = sizeof(long_trespass);
|
||||
cmd = MODE_SELECT_10;
|
||||
cdb[0] = MODE_SELECT_10;
|
||||
cdb[8] = len;
|
||||
}
|
||||
BUG_ON((len > CLARIION_BUFFER_SIZE));
|
||||
memcpy(csdev->buffer, page22, len);
|
||||
|
||||
rq = get_req(sdev, cmd, csdev->buffer);
|
||||
if (!rq)
|
||||
return SCSI_DH_RES_TEMP_UNAVAIL;
|
||||
|
||||
rq->sense = csdev->sense;
|
||||
memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
|
||||
rq->sense_len = csdev->senselen = 0;
|
||||
|
||||
err = blk_execute_rq(sdev->request_queue, NULL, rq, 1);
|
||||
if (err == -EIO) {
|
||||
if (rq->sense_len) {
|
||||
err = trespass_endio(sdev, csdev->sense);
|
||||
} else {
|
||||
err = scsi_execute_req_flags(sdev, cdb, DMA_TO_DEVICE,
|
||||
csdev->buffer, len, &sshdr,
|
||||
CLARIION_TIMEOUT * HZ, CLARIION_RETRIES,
|
||||
NULL, req_flags, 0);
|
||||
if (err) {
|
||||
if (scsi_sense_valid(&sshdr))
|
||||
res = trespass_endio(sdev, &sshdr);
|
||||
else {
|
||||
sdev_printk(KERN_INFO, sdev,
|
||||
"%s: failed to send MODE SELECT: %x\n",
|
||||
CLARIION_NAME, rq->errors);
|
||||
CLARIION_NAME, err);
|
||||
res = SCSI_DH_IO;
|
||||
}
|
||||
}
|
||||
|
||||
blk_put_request(rq);
|
||||
|
||||
return err;
|
||||
return res;
|
||||
}
|
||||
|
||||
static int clariion_check_sense(struct scsi_device *sdev,
|
||||
|
@ -464,21 +361,7 @@ static int clariion_std_inquiry(struct scsi_device *sdev,
|
|||
int err;
|
||||
char *sp_model;
|
||||
|
||||
err = send_inquiry_cmd(sdev, 0, csdev);
|
||||
if (err != SCSI_DH_OK && csdev->senselen) {
|
||||
struct scsi_sense_hdr sshdr;
|
||||
|
||||
if (scsi_normalize_sense(csdev->sense, SCSI_SENSE_BUFFERSIZE,
|
||||
&sshdr)) {
|
||||
sdev_printk(KERN_ERR, sdev, "%s: INQUIRY sense code "
|
||||
"%02x/%02x/%02x\n", CLARIION_NAME,
|
||||
sshdr.sense_key, sshdr.asc, sshdr.ascq);
|
||||
}
|
||||
err = SCSI_DH_IO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
sp_model = parse_sp_model(sdev, csdev->buffer);
|
||||
sp_model = parse_sp_model(sdev, sdev->inquiry);
|
||||
if (!sp_model) {
|
||||
err = SCSI_DH_DEV_UNSUPP;
|
||||
goto out;
|
||||
|
@ -500,30 +383,12 @@ static int clariion_std_inquiry(struct scsi_device *sdev,
|
|||
static int clariion_send_inquiry(struct scsi_device *sdev,
|
||||
struct clariion_dh_data *csdev)
|
||||
{
|
||||
int err, retry = CLARIION_RETRIES;
|
||||
int err = SCSI_DH_IO;
|
||||
|
||||
retry:
|
||||
err = send_inquiry_cmd(sdev, 0xC0, csdev);
|
||||
if (err != SCSI_DH_OK && csdev->senselen) {
|
||||
struct scsi_sense_hdr sshdr;
|
||||
|
||||
err = scsi_normalize_sense(csdev->sense, SCSI_SENSE_BUFFERSIZE,
|
||||
&sshdr);
|
||||
if (!err)
|
||||
return SCSI_DH_IO;
|
||||
|
||||
err = clariion_check_sense(sdev, &sshdr);
|
||||
if (retry > 0 && err == ADD_TO_MLQUEUE) {
|
||||
retry--;
|
||||
goto retry;
|
||||
}
|
||||
sdev_printk(KERN_ERR, sdev, "%s: INQUIRY sense code "
|
||||
"%02x/%02x/%02x\n", CLARIION_NAME,
|
||||
sshdr.sense_key, sshdr.asc, sshdr.ascq);
|
||||
err = SCSI_DH_IO;
|
||||
} else {
|
||||
if (!scsi_get_vpd_page(sdev, 0xC0, csdev->buffer,
|
||||
CLARIION_BUFFER_SIZE))
|
||||
err = parse_sp_info_reply(sdev, csdev);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue