scsi: hpsa: send ioaccel requests with 0 length down raid path
- Block I/O requests with 0 length transfers which go down the ioaccel path. This causes lockup issues down in the basecode. - These issues have been fixed, but there are customers who are experiencing the issues when running older firmware. Reviewed-by: Scott Benesh <scott.benesh@microsemi.com> Reviewed-by: Scott Teel <scott.teel@microsemi.com> Reviewed-by: Kevin Barnett <kevin.barnett@microsemi.com> Signed-off-by: Don Brace <don.brace@microsemi.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
3d38f00c41
commit
b63c64ac5a
|
@ -4591,7 +4591,55 @@ sglist_finished:
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define IO_ACCEL_INELIGIBLE (1)
|
||||
#define BUFLEN 128
|
||||
static inline void warn_zero_length_transfer(struct ctlr_info *h,
|
||||
u8 *cdb, int cdb_len,
|
||||
const char *func)
|
||||
{
|
||||
char buf[BUFLEN];
|
||||
int outlen;
|
||||
int i;
|
||||
|
||||
outlen = scnprintf(buf, BUFLEN,
|
||||
"%s: Blocking zero-length request: CDB:", func);
|
||||
for (i = 0; i < cdb_len; i++)
|
||||
outlen += scnprintf(buf+outlen, BUFLEN - outlen,
|
||||
"%02hhx", cdb[i]);
|
||||
dev_warn(&h->pdev->dev, "%s\n", buf);
|
||||
}
|
||||
|
||||
#define IO_ACCEL_INELIGIBLE 1
|
||||
/* zero-length transfers trigger hardware errors. */
|
||||
static bool is_zero_length_transfer(u8 *cdb)
|
||||
{
|
||||
u32 block_cnt;
|
||||
|
||||
/* Block zero-length transfer sizes on certain commands. */
|
||||
switch (cdb[0]) {
|
||||
case READ_10:
|
||||
case WRITE_10:
|
||||
case VERIFY: /* 0x2F */
|
||||
case WRITE_VERIFY: /* 0x2E */
|
||||
block_cnt = get_unaligned_be16(&cdb[7]);
|
||||
break;
|
||||
case READ_12:
|
||||
case WRITE_12:
|
||||
case VERIFY_12: /* 0xAF */
|
||||
case WRITE_VERIFY_12: /* 0xAE */
|
||||
block_cnt = get_unaligned_be32(&cdb[6]);
|
||||
break;
|
||||
case READ_16:
|
||||
case WRITE_16:
|
||||
case VERIFY_16: /* 0x8F */
|
||||
block_cnt = get_unaligned_be32(&cdb[10]);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return block_cnt == 0;
|
||||
}
|
||||
|
||||
static int fixup_ioaccel_cdb(u8 *cdb, int *cdb_len)
|
||||
{
|
||||
int is_write = 0;
|
||||
|
@ -4658,6 +4706,12 @@ static int hpsa_scsi_ioaccel1_queue_command(struct ctlr_info *h,
|
|||
|
||||
BUG_ON(cmd->cmd_len > IOACCEL1_IOFLAGS_CDBLEN_MAX);
|
||||
|
||||
if (is_zero_length_transfer(cdb)) {
|
||||
warn_zero_length_transfer(h, cdb, cdb_len, __func__);
|
||||
atomic_dec(&phys_disk->ioaccel_cmds_out);
|
||||
return IO_ACCEL_INELIGIBLE;
|
||||
}
|
||||
|
||||
if (fixup_ioaccel_cdb(cdb, &cdb_len)) {
|
||||
atomic_dec(&phys_disk->ioaccel_cmds_out);
|
||||
return IO_ACCEL_INELIGIBLE;
|
||||
|
@ -4822,6 +4876,12 @@ static int hpsa_scsi_ioaccel2_queue_command(struct ctlr_info *h,
|
|||
|
||||
BUG_ON(scsi_sg_count(cmd) > h->maxsgentries);
|
||||
|
||||
if (is_zero_length_transfer(cdb)) {
|
||||
warn_zero_length_transfer(h, cdb, cdb_len, __func__);
|
||||
atomic_dec(&phys_disk->ioaccel_cmds_out);
|
||||
return IO_ACCEL_INELIGIBLE;
|
||||
}
|
||||
|
||||
if (fixup_ioaccel_cdb(cdb, &cdb_len)) {
|
||||
atomic_dec(&phys_disk->ioaccel_cmds_out);
|
||||
return IO_ACCEL_INELIGIBLE;
|
||||
|
|
Loading…
Reference in New Issue