提交 b78205c9 编写于 作者: H Hannes Reinecke 提交者: Jens Axboe

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: NHannes Reinecke <hare@suse.com>
Signed-off-by: NChristoph Hellwig <hch@lst.de>
Acked-by: NMartin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: NJens Axboe <axboe@fb.com>
上级 32782557
...@@ -87,12 +87,6 @@ struct clariion_dh_data { ...@@ -87,12 +87,6 @@ struct clariion_dh_data {
* I/O buffer for both MODE_SELECT and INQUIRY commands. * I/O buffer for both MODE_SELECT and INQUIRY commands.
*/ */
unsigned char buffer[CLARIION_BUFFER_SIZE]; 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 * LUN state
*/ */
...@@ -116,44 +110,38 @@ struct clariion_dh_data { ...@@ -116,44 +110,38 @@ struct clariion_dh_data {
/* /*
* Parse MODE_SELECT cmd reply. * 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; 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);
if ((sshdr.sense_key == 0x05) && (sshdr.asc == 0x04) && sdev_printk(KERN_ERR, sdev, "%s: Found valid sense data 0x%2x, "
(sshdr.ascq == 0x00)) { "0x%2x, 0x%2x while sending CLARiiON trespass "
/* "command.\n", CLARIION_NAME, sshdr->sense_key,
* Array based copy in progress -- do not send sshdr->asc, sshdr->ascq);
* mode_select or copy will be aborted mid-stream.
*/ if (sshdr->sense_key == 0x05 && sshdr->asc == 0x04 &&
sdev_printk(KERN_INFO, sdev, "%s: Array Based Copy in " sshdr->ascq == 0x00) {
"progress while sending CLARiiON trespass " /*
"command.\n", CLARIION_NAME); * Array based copy in progress -- do not send
err = SCSI_DH_DEV_TEMP_BUSY; * mode_select or copy will be aborted mid-stream.
} else if ((sshdr.sense_key == 0x02) && (sshdr.asc == 0x04) && */
(sshdr.ascq == 0x03)) { sdev_printk(KERN_INFO, sdev, "%s: Array Based Copy in "
/* "progress while sending CLARiiON trespass "
* LUN Not Ready - Manual Intervention Required "command.\n", CLARIION_NAME);
* indicates in-progress ucode upgrade (NDU). err = SCSI_DH_DEV_TEMP_BUSY;
*/ } else if (sshdr->sense_key == 0x02 && sshdr->asc == 0x04 &&
sdev_printk(KERN_INFO, sdev, "%s: Detected in-progress " sshdr->ascq == 0x03) {
"ucode upgrade NDU operation while sending " /*
"CLARiiON trespass command.\n", CLARIION_NAME); * LUN Not Ready - Manual Intervention Required
err = SCSI_DH_DEV_TEMP_BUSY; * indicates in-progress ucode upgrade (NDU).
} else */
err = SCSI_DH_DEV_FAILED; sdev_printk(KERN_INFO, sdev, "%s: Detected in-progress "
} else { "ucode upgrade NDU operation while sending "
sdev_printk(KERN_INFO, sdev, "CLARiiON trespass command.\n", CLARIION_NAME);
"%s: failed to send MODE SELECT, no sense available\n", err = SCSI_DH_DEV_TEMP_BUSY;
CLARIION_NAME); } else
} err = SCSI_DH_DEV_FAILED;
return err; return err;
} }
...@@ -257,103 +245,15 @@ static char * parse_sp_model(struct scsi_device *sdev, unsigned char *buffer) ...@@ -257,103 +245,15 @@ static char * parse_sp_model(struct scsi_device *sdev, unsigned char *buffer)
return sp_model; 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, static int send_trespass_cmd(struct scsi_device *sdev,
struct clariion_dh_data *csdev) struct clariion_dh_data *csdev)
{ {
struct request *rq;
unsigned char *page22; 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) { if (csdev->flags & CLARIION_SHORT_TRESPASS) {
page22 = short_trespass; page22 = short_trespass;
...@@ -361,40 +261,37 @@ static int send_trespass_cmd(struct scsi_device *sdev, ...@@ -361,40 +261,37 @@ static int send_trespass_cmd(struct scsi_device *sdev,
/* Set Honor Reservations bit */ /* Set Honor Reservations bit */
page22[6] |= 0x80; page22[6] |= 0x80;
len = sizeof(short_trespass); len = sizeof(short_trespass);
cmd = MODE_SELECT; cdb[0] = MODE_SELECT;
cdb[1] = 0x10;
cdb[4] = len;
} else { } else {
page22 = long_trespass; page22 = long_trespass;
if (!(csdev->flags & CLARIION_HONOR_RESERVATIONS)) if (!(csdev->flags & CLARIION_HONOR_RESERVATIONS))
/* Set Honor Reservations bit */ /* Set Honor Reservations bit */
page22[10] |= 0x80; page22[10] |= 0x80;
len = sizeof(long_trespass); len = sizeof(long_trespass);
cmd = MODE_SELECT_10; cdb[0] = MODE_SELECT_10;
cdb[8] = len;
} }
BUG_ON((len > CLARIION_BUFFER_SIZE)); BUG_ON((len > CLARIION_BUFFER_SIZE));
memcpy(csdev->buffer, page22, len); memcpy(csdev->buffer, page22, len);
rq = get_req(sdev, cmd, csdev->buffer); err = scsi_execute_req_flags(sdev, cdb, DMA_TO_DEVICE,
if (!rq) csdev->buffer, len, &sshdr,
return SCSI_DH_RES_TEMP_UNAVAIL; CLARIION_TIMEOUT * HZ, CLARIION_RETRIES,
NULL, req_flags, 0);
rq->sense = csdev->sense; if (err) {
memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE); if (scsi_sense_valid(&sshdr))
rq->sense_len = csdev->senselen = 0; res = trespass_endio(sdev, &sshdr);
else {
err = blk_execute_rq(sdev->request_queue, NULL, rq, 1);
if (err == -EIO) {
if (rq->sense_len) {
err = trespass_endio(sdev, csdev->sense);
} else {
sdev_printk(KERN_INFO, sdev, sdev_printk(KERN_INFO, sdev,
"%s: failed to send MODE SELECT: %x\n", "%s: failed to send MODE SELECT: %x\n",
CLARIION_NAME, rq->errors); CLARIION_NAME, err);
res = SCSI_DH_IO;
} }
} }
blk_put_request(rq); return res;
return err;
} }
static int clariion_check_sense(struct scsi_device *sdev, static int clariion_check_sense(struct scsi_device *sdev,
...@@ -464,21 +361,7 @@ static int clariion_std_inquiry(struct scsi_device *sdev, ...@@ -464,21 +361,7 @@ static int clariion_std_inquiry(struct scsi_device *sdev,
int err; int err;
char *sp_model; char *sp_model;
err = send_inquiry_cmd(sdev, 0, csdev); sp_model = parse_sp_model(sdev, sdev->inquiry);
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);
if (!sp_model) { if (!sp_model) {
err = SCSI_DH_DEV_UNSUPP; err = SCSI_DH_DEV_UNSUPP;
goto out; goto out;
...@@ -500,30 +383,12 @@ static int clariion_std_inquiry(struct scsi_device *sdev, ...@@ -500,30 +383,12 @@ static int clariion_std_inquiry(struct scsi_device *sdev,
static int clariion_send_inquiry(struct scsi_device *sdev, static int clariion_send_inquiry(struct scsi_device *sdev,
struct clariion_dh_data *csdev) struct clariion_dh_data *csdev)
{ {
int err, retry = CLARIION_RETRIES; int err = SCSI_DH_IO;
retry: if (!scsi_get_vpd_page(sdev, 0xC0, csdev->buffer,
err = send_inquiry_cmd(sdev, 0xC0, csdev); CLARIION_BUFFER_SIZE))
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 {
err = parse_sp_info_reply(sdev, csdev); err = parse_sp_info_reply(sdev, csdev);
}
return err; return err;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册