mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-19 16:06:45 +07:00
scsi: scsi_debug: Fix request sense
The SCSI REQUEST SENSE command emulation was found to be broken. It is a quite complex command so try and make it do a subset of what it should do. Remove the attempt to mimic SCSI-1 REQUEST SENSE (i.e. return the sense data for the previous failed command). Add some reporting of "pollable" sense data [see spc6r02: 5.12.2]. Keep the IEC mode page MRIE=6 TEST=1 predictive failure reporting. Link: https://lore.kernel.org/r/20200723194819.545573-1-dgilbert@interlog.com Signed-off-by: Douglas Gilbert <dgilbert@interlog.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
02e3e588f0
commit
84905d34f1
@ -1712,68 +1712,62 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* See resp_iec_m_pg() for how this data is manipulated */
|
||||||
static unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0,
|
static unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0x0, 0x0};
|
0, 0, 0x0, 0x0};
|
||||||
|
|
||||||
static int resp_requests(struct scsi_cmnd *scp,
|
static int resp_requests(struct scsi_cmnd *scp,
|
||||||
struct sdebug_dev_info *devip)
|
struct sdebug_dev_info *devip)
|
||||||
{
|
{
|
||||||
unsigned char *sbuff;
|
|
||||||
unsigned char *cmd = scp->cmnd;
|
unsigned char *cmd = scp->cmnd;
|
||||||
unsigned char arr[SCSI_SENSE_BUFFERSIZE];
|
unsigned char arr[SCSI_SENSE_BUFFERSIZE]; /* assume >= 18 bytes */
|
||||||
bool dsense;
|
bool dsense = !!(cmd[1] & 1);
|
||||||
|
int alloc_len = cmd[4];
|
||||||
int len = 18;
|
int len = 18;
|
||||||
|
int stopped_state = atomic_read(&devip->stopped);
|
||||||
|
|
||||||
memset(arr, 0, sizeof(arr));
|
memset(arr, 0, sizeof(arr));
|
||||||
dsense = !!(cmd[1] & 1);
|
if (stopped_state > 0) { /* some "pollable" data [spc6r02: 5.12.2] */
|
||||||
sbuff = scp->sense_buffer;
|
if (dsense) {
|
||||||
if ((iec_m_pg[2] & 0x4) && (6 == (iec_m_pg[3] & 0xf))) {
|
arr[0] = 0x72;
|
||||||
|
arr[1] = NOT_READY;
|
||||||
|
arr[2] = LOGICAL_UNIT_NOT_READY;
|
||||||
|
arr[3] = (stopped_state == 2) ? 0x1 : 0x2;
|
||||||
|
len = 8;
|
||||||
|
} else {
|
||||||
|
arr[0] = 0x70;
|
||||||
|
arr[2] = NOT_READY; /* NO_SENSE in sense_key */
|
||||||
|
arr[7] = 0xa; /* 18 byte sense buffer */
|
||||||
|
arr[12] = LOGICAL_UNIT_NOT_READY;
|
||||||
|
arr[13] = (stopped_state == 2) ? 0x1 : 0x2;
|
||||||
|
}
|
||||||
|
} else if ((iec_m_pg[2] & 0x4) && (6 == (iec_m_pg[3] & 0xf))) {
|
||||||
|
/* Information exceptions control mode page: TEST=1, MRIE=6 */
|
||||||
if (dsense) {
|
if (dsense) {
|
||||||
arr[0] = 0x72;
|
arr[0] = 0x72;
|
||||||
arr[1] = 0x0; /* NO_SENSE in sense_key */
|
arr[1] = 0x0; /* NO_SENSE in sense_key */
|
||||||
arr[2] = THRESHOLD_EXCEEDED;
|
arr[2] = THRESHOLD_EXCEEDED;
|
||||||
arr[3] = 0xff; /* TEST set and MRIE==6 */
|
arr[3] = 0xff; /* Failure prediction(false) */
|
||||||
len = 8;
|
len = 8;
|
||||||
} else {
|
} else {
|
||||||
arr[0] = 0x70;
|
arr[0] = 0x70;
|
||||||
arr[2] = 0x0; /* NO_SENSE in sense_key */
|
arr[2] = 0x0; /* NO_SENSE in sense_key */
|
||||||
arr[7] = 0xa; /* 18 byte sense buffer */
|
arr[7] = 0xa; /* 18 byte sense buffer */
|
||||||
arr[12] = THRESHOLD_EXCEEDED;
|
arr[12] = THRESHOLD_EXCEEDED;
|
||||||
arr[13] = 0xff; /* TEST set and MRIE==6 */
|
arr[13] = 0xff; /* Failure prediction(false) */
|
||||||
}
|
}
|
||||||
} else {
|
} else { /* nothing to report */
|
||||||
memcpy(arr, sbuff, SCSI_SENSE_BUFFERSIZE);
|
if (dsense) {
|
||||||
if (arr[0] >= 0x70 && dsense == sdebug_dsense)
|
|
||||||
; /* have sense and formats match */
|
|
||||||
else if (arr[0] <= 0x70) {
|
|
||||||
if (dsense) {
|
|
||||||
memset(arr, 0, 8);
|
|
||||||
arr[0] = 0x72;
|
|
||||||
len = 8;
|
|
||||||
} else {
|
|
||||||
memset(arr, 0, 18);
|
|
||||||
arr[0] = 0x70;
|
|
||||||
arr[7] = 0xa;
|
|
||||||
}
|
|
||||||
} else if (dsense) {
|
|
||||||
memset(arr, 0, 8);
|
|
||||||
arr[0] = 0x72;
|
|
||||||
arr[1] = sbuff[2]; /* sense key */
|
|
||||||
arr[2] = sbuff[12]; /* asc */
|
|
||||||
arr[3] = sbuff[13]; /* ascq */
|
|
||||||
len = 8;
|
len = 8;
|
||||||
|
memset(arr, 0, len);
|
||||||
|
arr[0] = 0x72;
|
||||||
} else {
|
} else {
|
||||||
memset(arr, 0, 18);
|
memset(arr, 0, len);
|
||||||
arr[0] = 0x70;
|
arr[0] = 0x70;
|
||||||
arr[2] = sbuff[1];
|
|
||||||
arr[7] = 0xa;
|
arr[7] = 0xa;
|
||||||
arr[12] = sbuff[1];
|
|
||||||
arr[13] = sbuff[3];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
mk_sense_buffer(scp, 0, NO_ADDITIONAL_SENSE, 0);
|
return fill_from_dev_buffer(scp, arr, min_t(int, len, alloc_len));
|
||||||
return fill_from_dev_buffer(scp, arr, len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int resp_start_stop(struct scsi_cmnd *scp,
|
static int resp_start_stop(struct scsi_cmnd *scp,
|
||||||
|
Loading…
Reference in New Issue
Block a user