scsi: aacraid: Reworked scsi command submission path

Moved the READ and WRITE switch cases to the top. Added a  default
case to the switch case and replaced duplicate scsi result value with a
macro.

The idea is that since most of scsi commands we care about performance
wise are read or write, we need to process them first.

Internally the compiler (GCC) converts a switch case into either a jump
table or a bunch of if else conditions, so placing the often used read,
write cases at the top is an effort in optimization.

Signed-off-by: Raghava Aditya Renukunta <RaghavaAditya.Renukunta@microsemi.com>
Signed-off-by: Dave Carroll <David.Carroll@microsemi.com>
Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
Raghava Aditya Renukunta 2017-02-02 15:53:20 -08:00 committed by Martin K. Petersen
parent c83b11e31c
commit c4e2fbca37

View File

@ -106,6 +106,8 @@
#define ASENCODE_LUN_FAILED_SELF_CONFIG 0x00 #define ASENCODE_LUN_FAILED_SELF_CONFIG 0x00
#define ASENCODE_OVERLAPPED_COMMAND 0x00 #define ASENCODE_OVERLAPPED_COMMAND 0x00
#define AAC_STAT_GOOD (DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD)
#define BYTE0(x) (unsigned char)(x) #define BYTE0(x) (unsigned char)(x)
#define BYTE1(x) (unsigned char)((x) >> 8) #define BYTE1(x) (unsigned char)((x) >> 8)
#define BYTE2(x) (unsigned char)((x) >> 16) #define BYTE2(x) (unsigned char)((x) >> 16)
@ -2476,8 +2478,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
if((cid >= dev->maximum_num_containers) || if((cid >= dev->maximum_num_containers) ||
(scsicmd->device->lun != 0)) { (scsicmd->device->lun != 0)) {
scsicmd->result = DID_NO_CONNECT << 16; scsicmd->result = DID_NO_CONNECT << 16;
scsicmd->scsi_done(scsicmd); goto scsi_done_ret;
return 0;
} }
/* /*
@ -2512,8 +2513,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
return aac_send_srb_fib(scsicmd); return aac_send_srb_fib(scsicmd);
} else { } else {
scsicmd->result = DID_NO_CONNECT << 16; scsicmd->result = DID_NO_CONNECT << 16;
scsicmd->scsi_done(scsicmd); goto scsi_done_ret;
return 0;
} }
} }
} }
@ -2531,13 +2531,34 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data, memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
min_t(size_t, sizeof(dev->fsa_dev[cid].sense_data), min_t(size_t, sizeof(dev->fsa_dev[cid].sense_data),
SCSI_SENSE_BUFFERSIZE)); SCSI_SENSE_BUFFERSIZE));
scsicmd->scsi_done(scsicmd); goto scsi_done_ret;
return 0;
} }
/* Handle commands here that don't really require going out to the adapter */
switch (scsicmd->cmnd[0]) { switch (scsicmd->cmnd[0]) {
case READ_6:
case READ_10:
case READ_12:
case READ_16:
if (dev->in_reset)
return -1;
return aac_read(scsicmd);
case WRITE_6:
case WRITE_10:
case WRITE_12:
case WRITE_16:
if (dev->in_reset)
return -1;
return aac_write(scsicmd);
case SYNCHRONIZE_CACHE:
if (((aac_cache & 6) == 6) && dev->cache_protected) {
scsicmd->result = AAC_STAT_GOOD;
break;
}
/* Issue FIB to tell Firmware to flush it's cache */
if ((aac_cache & 6) != 2)
return aac_synchronize(scsicmd);
case INQUIRY: case INQUIRY:
{ {
struct inquiry_data inq_data; struct inquiry_data inq_data;
@ -2560,8 +2581,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
arr[1] = scsicmd->cmnd[2]; arr[1] = scsicmd->cmnd[2];
scsi_sg_copy_from_buffer(scsicmd, &inq_data, scsi_sg_copy_from_buffer(scsicmd, &inq_data,
sizeof(inq_data)); sizeof(inq_data));
scsicmd->result = DID_OK << 16 | scsicmd->result = AAC_STAT_GOOD;
COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
} else if (scsicmd->cmnd[2] == 0x80) { } else if (scsicmd->cmnd[2] == 0x80) {
/* unit serial number page */ /* unit serial number page */
arr[3] = setinqserial(dev, &arr[4], arr[3] = setinqserial(dev, &arr[4],
@ -2572,8 +2592,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
if (aac_wwn != 2) if (aac_wwn != 2)
return aac_get_container_serial( return aac_get_container_serial(
scsicmd); scsicmd);
scsicmd->result = DID_OK << 16 | scsicmd->result = AAC_STAT_GOOD;
COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
} else if (scsicmd->cmnd[2] == 0x83) { } else if (scsicmd->cmnd[2] == 0x83) {
/* vpd page 0x83 - Device Identification Page */ /* vpd page 0x83 - Device Identification Page */
char *sno = (char *)&inq_data; char *sno = (char *)&inq_data;
@ -2582,8 +2601,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
if (aac_wwn != 2) if (aac_wwn != 2)
return aac_get_container_serial( return aac_get_container_serial(
scsicmd); scsicmd);
scsicmd->result = DID_OK << 16 | scsicmd->result = AAC_STAT_GOOD;
COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
} else { } else {
/* vpd page not implemented */ /* vpd page not implemented */
scsicmd->result = DID_OK << 16 | scsicmd->result = DID_OK << 16 |
@ -2598,8 +2616,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
sizeof(dev->fsa_dev[cid].sense_data), sizeof(dev->fsa_dev[cid].sense_data),
SCSI_SENSE_BUFFERSIZE)); SCSI_SENSE_BUFFERSIZE));
} }
scsicmd->scsi_done(scsicmd); break;
return 0;
} }
inq_data.inqd_ver = 2; /* claim compliance to SCSI-2 */ inq_data.inqd_ver = 2; /* claim compliance to SCSI-2 */
inq_data.inqd_rdf = 2; /* A response data format value of two indicates that the data shall be in the format specified in SCSI-2 */ inq_data.inqd_rdf = 2; /* A response data format value of two indicates that the data shall be in the format specified in SCSI-2 */
@ -2615,9 +2632,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
inq_data.inqd_pdt = INQD_PDT_PROC; /* Processor device */ inq_data.inqd_pdt = INQD_PDT_PROC; /* Processor device */
scsi_sg_copy_from_buffer(scsicmd, &inq_data, scsi_sg_copy_from_buffer(scsicmd, &inq_data,
sizeof(inq_data)); sizeof(inq_data));
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; scsicmd->result = AAC_STAT_GOOD;
scsicmd->scsi_done(scsicmd); break;
return 0;
} }
if (dev->in_reset) if (dev->in_reset)
return -1; return -1;
@ -2665,10 +2681,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
/* Do not cache partition table for arrays */ /* Do not cache partition table for arrays */
scsicmd->device->removable = 1; scsicmd->device->removable = 1;
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; scsicmd->result = AAC_STAT_GOOD;
scsicmd->scsi_done(scsicmd); break;
return 0;
} }
case READ_CAPACITY: case READ_CAPACITY:
@ -2693,11 +2707,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
scsi_sg_copy_from_buffer(scsicmd, cp, sizeof(cp)); scsi_sg_copy_from_buffer(scsicmd, cp, sizeof(cp));
/* Do not cache partition table for arrays */ /* Do not cache partition table for arrays */
scsicmd->device->removable = 1; scsicmd->device->removable = 1;
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | scsicmd->result = AAC_STAT_GOOD;
SAM_STAT_GOOD; break;
scsicmd->scsi_done(scsicmd);
return 0;
} }
case MODE_SENSE: case MODE_SENSE:
@ -2775,10 +2786,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
scsi_sg_copy_from_buffer(scsicmd, scsi_sg_copy_from_buffer(scsicmd,
(char *)&mpd, (char *)&mpd,
mode_buf_length); mode_buf_length);
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; scsicmd->result = AAC_STAT_GOOD;
scsicmd->scsi_done(scsicmd); break;
return 0;
} }
case MODE_SENSE_10: case MODE_SENSE_10:
{ {
@ -2854,18 +2863,17 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
(char *)&mpd10, (char *)&mpd10,
mode_buf_length); mode_buf_length);
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; scsicmd->result = AAC_STAT_GOOD;
scsicmd->scsi_done(scsicmd); break;
return 0;
} }
case REQUEST_SENSE: case REQUEST_SENSE:
dprintk((KERN_DEBUG "REQUEST SENSE command.\n")); dprintk((KERN_DEBUG "REQUEST SENSE command.\n"));
memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data, sizeof (struct sense_data)); memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
memset(&dev->fsa_dev[cid].sense_data, 0, sizeof (struct sense_data)); sizeof(struct sense_data));
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; memset(&dev->fsa_dev[cid].sense_data, 0,
scsicmd->scsi_done(scsicmd); sizeof(struct sense_data));
return 0; scsicmd->result = AAC_STAT_GOOD;
break;
case ALLOW_MEDIUM_REMOVAL: case ALLOW_MEDIUM_REMOVAL:
dprintk((KERN_DEBUG "LOCK command.\n")); dprintk((KERN_DEBUG "LOCK command.\n"));
@ -2874,9 +2882,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
else else
fsa_dev_ptr[cid].locked = 0; fsa_dev_ptr[cid].locked = 0;
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; scsicmd->result = AAC_STAT_GOOD;
scsicmd->scsi_done(scsicmd); break;
return 0;
/* /*
* These commands are all No-Ops * These commands are all No-Ops
*/ */
@ -2892,80 +2899,41 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
min_t(size_t, min_t(size_t,
sizeof(dev->fsa_dev[cid].sense_data), sizeof(dev->fsa_dev[cid].sense_data),
SCSI_SENSE_BUFFERSIZE)); SCSI_SENSE_BUFFERSIZE));
scsicmd->scsi_done(scsicmd); break;
return 0;
} }
/* FALLTHRU */
case RESERVE: case RESERVE:
case RELEASE: case RELEASE:
case REZERO_UNIT: case REZERO_UNIT:
case REASSIGN_BLOCKS: case REASSIGN_BLOCKS:
case SEEK_10: case SEEK_10:
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; scsicmd->result = AAC_STAT_GOOD;
scsicmd->scsi_done(scsicmd); break;
return 0;
case START_STOP: case START_STOP:
return aac_start_stop(scsicmd); return aac_start_stop(scsicmd);
}
switch (scsicmd->cmnd[0]) /* FALLTHRU */
{ default:
case READ_6: /*
case READ_10: * Unhandled commands
case READ_12: */
case READ_16: dprintk((KERN_WARNING "Unhandled SCSI Command: 0x%x.\n",
if (dev->in_reset) scsicmd->cmnd[0]));
return -1; scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 |
/* SAM_STAT_CHECK_CONDITION;
* Hack to keep track of ordinal number of the device that set_sense(&dev->fsa_dev[cid].sense_data,
* corresponds to a container. Needed to convert
* containers to /dev/sd device names
*/
if (scsicmd->request->rq_disk)
strlcpy(fsa_dev_ptr[cid].devname,
scsicmd->request->rq_disk->disk_name,
min(sizeof(fsa_dev_ptr[cid].devname),
sizeof(scsicmd->request->rq_disk->disk_name) + 1));
return aac_read(scsicmd);
case WRITE_6:
case WRITE_10:
case WRITE_12:
case WRITE_16:
if (dev->in_reset)
return -1;
return aac_write(scsicmd);
case SYNCHRONIZE_CACHE:
if (((aac_cache & 6) == 6) && dev->cache_protected) {
scsicmd->result = DID_OK << 16 |
COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
scsicmd->scsi_done(scsicmd);
return 0;
}
/* Issue FIB to tell Firmware to flush it's cache */
if ((aac_cache & 6) != 2)
return aac_synchronize(scsicmd);
/* FALLTHRU */
default:
/*
* Unhandled commands
*/
dprintk((KERN_WARNING "Unhandled SCSI Command: 0x%x.\n", scsicmd->cmnd[0]));
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
set_sense(&dev->fsa_dev[cid].sense_data,
ILLEGAL_REQUEST, SENCODE_INVALID_COMMAND, ILLEGAL_REQUEST, SENCODE_INVALID_COMMAND,
ASENCODE_INVALID_COMMAND, 0, 0); ASENCODE_INVALID_COMMAND, 0, 0);
memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data, memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
min_t(size_t, min_t(size_t,
sizeof(dev->fsa_dev[cid].sense_data), sizeof(dev->fsa_dev[cid].sense_data),
SCSI_SENSE_BUFFERSIZE)); SCSI_SENSE_BUFFERSIZE));
scsicmd->scsi_done(scsicmd);
return 0;
} }
scsi_done_ret:
scsicmd->scsi_done(scsicmd);
return 0;
} }
static int query_disk(struct aac_dev *dev, void __user *arg) static int query_disk(struct aac_dev *dev, void __user *arg)