Commit 760f3b03 authored by Douglas Gilbert's avatar Douglas Gilbert Committed by Martin K. Petersen

scsi_debug: vpd and mode page work

Cleanup some mode and vpd pages. Stop reporting SBC (disk) pages when
peripheral type is something else (e.g. tape). Update version
descriptors. Expand LBPRZ flag handling.
Signed-off-by: default avatarDouglas Gilbert <dgilbert@interlog.com>
Reviewed-by: default avatarHannes Reinecke <hare@suse.com>
Reviewed-by: default avatarBart Van Assche <bart.vanassche@sandisk.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent c4837394
...@@ -125,7 +125,7 @@ static const char *sdebug_version_date = "20160430"; ...@@ -125,7 +125,7 @@ static const char *sdebug_version_date = "20160430";
#define DEF_PHYSBLK_EXP 0 #define DEF_PHYSBLK_EXP 0
#define DEF_PTYPE TYPE_DISK #define DEF_PTYPE TYPE_DISK
#define DEF_REMOVABLE false #define DEF_REMOVABLE false
#define DEF_SCSI_LEVEL 6 /* INQUIRY, byte2 [6->SPC-4] */ #define DEF_SCSI_LEVEL 7 /* INQUIRY, byte2 [6->SPC-4; 7->SPC-5] */
#define DEF_SECTOR_SIZE 512 #define DEF_SECTOR_SIZE 512
#define DEF_UNMAP_ALIGNMENT 0 #define DEF_UNMAP_ALIGNMENT 0
#define DEF_UNMAP_GRANULARITY 1 #define DEF_UNMAP_GRANULARITY 1
...@@ -661,7 +661,11 @@ static const int device_qfull_result = ...@@ -661,7 +661,11 @@ static const int device_qfull_result =
(DID_OK << 16) | (COMMAND_COMPLETE << 8) | SAM_STAT_TASK_SET_FULL; (DID_OK << 16) | (COMMAND_COMPLETE << 8) | SAM_STAT_TASK_SET_FULL;
static inline unsigned int scsi_debug_lbp(void) /* Only do the extra work involved in logical block provisioning if one or
* more of the lbpu, lbpws or lbpws10 parameters are given and we are doing
* real reads and writes (i.e. not skipping them for speed).
*/
static inline bool scsi_debug_lbp(void)
{ {
return 0 == sdebug_fake_rw && return 0 == sdebug_fake_rw &&
(sdebug_lbpu || sdebug_lbpws || sdebug_lbpws10); (sdebug_lbpu || sdebug_lbpws || sdebug_lbpws10);
...@@ -922,10 +926,10 @@ static const u64 naa5_comp_b = 0x5333333000000000ULL; ...@@ -922,10 +926,10 @@ static const u64 naa5_comp_b = 0x5333333000000000ULL;
static const u64 naa5_comp_c = 0x5111111000000000ULL; static const u64 naa5_comp_c = 0x5111111000000000ULL;
/* Device identification VPD page. Returns number of bytes placed in arr */ /* Device identification VPD page. Returns number of bytes placed in arr */
static int inquiry_evpd_83(unsigned char * arr, int port_group_id, static int inquiry_vpd_83(unsigned char *arr, int port_group_id,
int target_dev_id, int dev_id_num, int target_dev_id, int dev_id_num,
const char * dev_id_str, const char *dev_id_str,
int dev_id_str_len) int dev_id_str_len)
{ {
int num, port_a; int num, port_a;
char b[32]; char b[32];
...@@ -1004,14 +1008,14 @@ static unsigned char vpd84_data[] = { ...@@ -1004,14 +1008,14 @@ static unsigned char vpd84_data[] = {
}; };
/* Software interface identification VPD page */ /* Software interface identification VPD page */
static int inquiry_evpd_84(unsigned char * arr) static int inquiry_vpd_84(unsigned char *arr)
{ {
memcpy(arr, vpd84_data, sizeof(vpd84_data)); memcpy(arr, vpd84_data, sizeof(vpd84_data));
return sizeof(vpd84_data); return sizeof(vpd84_data);
} }
/* Management network addresses VPD page */ /* Management network addresses VPD page */
static int inquiry_evpd_85(unsigned char * arr) static int inquiry_vpd_85(unsigned char *arr)
{ {
int num = 0; int num = 0;
const char * na1 = "https://www.kernel.org/config"; const char * na1 = "https://www.kernel.org/config";
...@@ -1046,7 +1050,7 @@ static int inquiry_evpd_85(unsigned char * arr) ...@@ -1046,7 +1050,7 @@ static int inquiry_evpd_85(unsigned char * arr)
} }
/* SCSI ports VPD page */ /* SCSI ports VPD page */
static int inquiry_evpd_88(unsigned char * arr, int target_dev_id) static int inquiry_vpd_88(unsigned char *arr, int target_dev_id)
{ {
int num = 0; int num = 0;
int port_a, port_b; int port_a, port_b;
...@@ -1133,7 +1137,7 @@ static unsigned char vpd89_data[] = { ...@@ -1133,7 +1137,7 @@ static unsigned char vpd89_data[] = {
}; };
/* ATA Information VPD page */ /* ATA Information VPD page */
static int inquiry_evpd_89(unsigned char * arr) static int inquiry_vpd_89(unsigned char *arr)
{ {
memcpy(arr, vpd89_data, sizeof(vpd89_data)); memcpy(arr, vpd89_data, sizeof(vpd89_data));
return sizeof(vpd89_data); return sizeof(vpd89_data);
...@@ -1148,7 +1152,7 @@ static unsigned char vpdb0_data[] = { ...@@ -1148,7 +1152,7 @@ static unsigned char vpdb0_data[] = {
}; };
/* Block limits VPD page (SBC-3) */ /* Block limits VPD page (SBC-3) */
static int inquiry_evpd_b0(unsigned char * arr) static int inquiry_vpd_b0(unsigned char *arr)
{ {
unsigned int gran; unsigned int gran;
...@@ -1191,7 +1195,7 @@ static int inquiry_evpd_b0(unsigned char * arr) ...@@ -1191,7 +1195,7 @@ static int inquiry_evpd_b0(unsigned char * arr)
} }
/* Block device characteristics VPD page (SBC-3) */ /* Block device characteristics VPD page (SBC-3) */
static int inquiry_evpd_b1(unsigned char *arr) static int inquiry_vpd_b1(unsigned char *arr)
{ {
memset(arr, 0, 0x3c); memset(arr, 0, 0x3c);
arr[0] = 0; arr[0] = 0;
...@@ -1202,24 +1206,22 @@ static int inquiry_evpd_b1(unsigned char *arr) ...@@ -1202,24 +1206,22 @@ static int inquiry_evpd_b1(unsigned char *arr)
return 0x3c; return 0x3c;
} }
/* Logical block provisioning VPD page (SBC-3) */ /* Logical block provisioning VPD page (SBC-4) */
static int inquiry_evpd_b2(unsigned char *arr) static int inquiry_vpd_b2(unsigned char *arr)
{ {
memset(arr, 0, 0x4); memset(arr, 0, 0x4);
arr[0] = 0; /* threshold exponent */ arr[0] = 0; /* threshold exponent */
if (sdebug_lbpu) if (sdebug_lbpu)
arr[1] = 1 << 7; arr[1] = 1 << 7;
if (sdebug_lbpws) if (sdebug_lbpws)
arr[1] |= 1 << 6; arr[1] |= 1 << 6;
if (sdebug_lbpws10) if (sdebug_lbpws10)
arr[1] |= 1 << 5; arr[1] |= 1 << 5;
if (sdebug_lbprz && scsi_debug_lbp())
if (sdebug_lbprz) arr[1] |= (sdebug_lbprz & 0x7) << 2; /* sbc4r07 and later */
arr[1] |= 1 << 2; /* anc_sup=0; dp=0 (no provisioning group descriptor) */
/* minimum_percentage=0; provisioning_type=0 (unknown) */
/* threshold_percentage=0 */
return 0x4; return 0x4;
} }
...@@ -1232,12 +1234,13 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) ...@@ -1232,12 +1234,13 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
unsigned char * arr; unsigned char * arr;
unsigned char *cmd = scp->cmnd; unsigned char *cmd = scp->cmnd;
int alloc_len, n, ret; int alloc_len, n, ret;
bool have_wlun; bool have_wlun, is_disk;
alloc_len = get_unaligned_be16(cmd + 3); alloc_len = get_unaligned_be16(cmd + 3);
arr = kzalloc(SDEBUG_MAX_INQ_ARR_SZ, GFP_ATOMIC); arr = kzalloc(SDEBUG_MAX_INQ_ARR_SZ, GFP_ATOMIC);
if (! arr) if (! arr)
return DID_REQUEUE << 16; return DID_REQUEUE << 16;
is_disk = (sdebug_ptype == TYPE_DISK);
have_wlun = scsi_is_wlun(scp->device->lun); have_wlun = scsi_is_wlun(scp->device->lun);
if (have_wlun) if (have_wlun)
pq_pdt = TYPE_WLUN; /* present, wlun */ pq_pdt = TYPE_WLUN; /* present, wlun */
...@@ -1275,11 +1278,12 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) ...@@ -1275,11 +1278,12 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
arr[n++] = 0x86; /* extended inquiry */ arr[n++] = 0x86; /* extended inquiry */
arr[n++] = 0x87; /* mode page policy */ arr[n++] = 0x87; /* mode page policy */
arr[n++] = 0x88; /* SCSI ports */ arr[n++] = 0x88; /* SCSI ports */
arr[n++] = 0x89; /* ATA information */ if (is_disk) { /* SBC only */
arr[n++] = 0xb0; /* Block limits (SBC) */ arr[n++] = 0x89; /* ATA information */
arr[n++] = 0xb1; /* Block characteristics (SBC) */ arr[n++] = 0xb0; /* Block limits */
if (scsi_debug_lbp()) /* Logical Block Prov. (SBC) */ arr[n++] = 0xb1; /* Block characteristics */
arr[n++] = 0xb2; arr[n++] = 0xb2; /* Logical Block Prov */
}
arr[3] = n - 4; /* number of supported VPD pages */ arr[3] = n - 4; /* number of supported VPD pages */
} else if (0x80 == cmd[2]) { /* unit serial number */ } else if (0x80 == cmd[2]) { /* unit serial number */
arr[1] = cmd[2]; /*sanity */ arr[1] = cmd[2]; /*sanity */
...@@ -1287,21 +1291,21 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) ...@@ -1287,21 +1291,21 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
memcpy(&arr[4], lu_id_str, len); memcpy(&arr[4], lu_id_str, len);
} else if (0x83 == cmd[2]) { /* device identification */ } else if (0x83 == cmd[2]) { /* device identification */
arr[1] = cmd[2]; /*sanity */ arr[1] = cmd[2]; /*sanity */
arr[3] = inquiry_evpd_83(&arr[4], port_group_id, arr[3] = inquiry_vpd_83(&arr[4], port_group_id,
target_dev_id, lu_id_num, target_dev_id, lu_id_num,
lu_id_str, len); lu_id_str, len);
} else if (0x84 == cmd[2]) { /* Software interface ident. */ } else if (0x84 == cmd[2]) { /* Software interface ident. */
arr[1] = cmd[2]; /*sanity */ arr[1] = cmd[2]; /*sanity */
arr[3] = inquiry_evpd_84(&arr[4]); arr[3] = inquiry_vpd_84(&arr[4]);
} else if (0x85 == cmd[2]) { /* Management network addresses */ } else if (0x85 == cmd[2]) { /* Management network addresses */
arr[1] = cmd[2]; /*sanity */ arr[1] = cmd[2]; /*sanity */
arr[3] = inquiry_evpd_85(&arr[4]); arr[3] = inquiry_vpd_85(&arr[4]);
} else if (0x86 == cmd[2]) { /* extended inquiry */ } else if (0x86 == cmd[2]) { /* extended inquiry */
arr[1] = cmd[2]; /*sanity */ arr[1] = cmd[2]; /*sanity */
arr[3] = 0x3c; /* number of following entries */ arr[3] = 0x3c; /* number of following entries */
if (sdebug_dif == SD_DIF_TYPE3_PROTECTION) if (sdebug_dif == SD_DIF_TYPE3_PROTECTION)
arr[4] = 0x4; /* SPT: GRD_CHK:1 */ arr[4] = 0x4; /* SPT: GRD_CHK:1 */
else if (sdebug_dif) else if (have_dif_prot)
arr[4] = 0x5; /* SPT: GRD_CHK:1, REF_CHK:1 */ arr[4] = 0x5; /* SPT: GRD_CHK:1, REF_CHK:1 */
else else
arr[4] = 0x0; /* no protection stuff */ arr[4] = 0x0; /* no protection stuff */
...@@ -1315,20 +1319,20 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) ...@@ -1315,20 +1319,20 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
arr[10] = 0x82; /* mlus, per initiator port */ arr[10] = 0x82; /* mlus, per initiator port */
} else if (0x88 == cmd[2]) { /* SCSI Ports */ } else if (0x88 == cmd[2]) { /* SCSI Ports */
arr[1] = cmd[2]; /*sanity */ arr[1] = cmd[2]; /*sanity */
arr[3] = inquiry_evpd_88(&arr[4], target_dev_id); arr[3] = inquiry_vpd_88(&arr[4], target_dev_id);
} else if (0x89 == cmd[2]) { /* ATA information */ } else if (is_disk && 0x89 == cmd[2]) { /* ATA information */
arr[1] = cmd[2]; /*sanity */ arr[1] = cmd[2]; /*sanity */
n = inquiry_evpd_89(&arr[4]); n = inquiry_vpd_89(&arr[4]);
put_unaligned_be16(n, arr + 2); put_unaligned_be16(n, arr + 2);
} else if (0xb0 == cmd[2]) { /* Block limits (SBC) */ } else if (is_disk && 0xb0 == cmd[2]) { /* Block limits */
arr[1] = cmd[2]; /*sanity */ arr[1] = cmd[2]; /*sanity */
arr[3] = inquiry_evpd_b0(&arr[4]); arr[3] = inquiry_vpd_b0(&arr[4]);
} else if (0xb1 == cmd[2]) { /* Block characteristics (SBC) */ } else if (is_disk && 0xb1 == cmd[2]) { /* Block char. */
arr[1] = cmd[2]; /*sanity */ arr[1] = cmd[2]; /*sanity */
arr[3] = inquiry_evpd_b1(&arr[4]); arr[3] = inquiry_vpd_b1(&arr[4]);
} else if (0xb2 == cmd[2]) { /* Logical Block Prov. (SBC) */ } else if (is_disk && 0xb2 == cmd[2]) { /* LB Prov. */
arr[1] = cmd[2]; /*sanity */ arr[1] = cmd[2]; /*sanity */
arr[3] = inquiry_evpd_b2(&arr[4]); arr[3] = inquiry_vpd_b2(&arr[4]);
} else { } else {
mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, -1); mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, -1);
kfree(arr); kfree(arr);
...@@ -1355,15 +1359,17 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) ...@@ -1355,15 +1359,17 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
memcpy(&arr[16], inq_product_id, 16); memcpy(&arr[16], inq_product_id, 16);
memcpy(&arr[32], inq_product_rev, 4); memcpy(&arr[32], inq_product_rev, 4);
/* version descriptors (2 bytes each) follow */ /* version descriptors (2 bytes each) follow */
arr[58] = 0x0; arr[59] = 0xa2; /* SAM-5 rev 4 */ put_unaligned_be16(0xc0, arr + 58); /* SAM-6 no version claimed */
arr[60] = 0x4; arr[61] = 0x68; /* SPC-4 rev 37 */ put_unaligned_be16(0x5c0, arr + 60); /* SPC-5 no version claimed */
n = 62; n = 62;
if (sdebug_ptype == TYPE_DISK) { if (is_disk) { /* SBC-4 no version claimed */
arr[n++] = 0x4; arr[n++] = 0xc5; /* SBC-4 rev 36 */ put_unaligned_be16(0x600, arr + n);
} else if (sdebug_ptype == TYPE_TAPE) { n += 2;
arr[n++] = 0x5; arr[n++] = 0x25; /* SSC-4 rev 3 */ } else if (sdebug_ptype == TYPE_TAPE) { /* SSC-4 rev 3 */
} put_unaligned_be16(0x525, arr + n);
arr[n++] = 0x20; arr[n++] = 0xe6; /* SPL-3 rev 7 */ n += 2;
}
put_unaligned_be16(0x2100, arr + n); /* SPL-4 no version claimed */
ret = fill_from_dev_buffer(scp, arr, ret = fill_from_dev_buffer(scp, arr,
min(alloc_len, SDEBUG_LONG_INQ_SZ)); min(alloc_len, SDEBUG_LONG_INQ_SZ));
kfree(arr); kfree(arr);
...@@ -1499,13 +1505,17 @@ static int resp_readcap16(struct scsi_cmnd * scp, ...@@ -1499,13 +1505,17 @@ static int resp_readcap16(struct scsi_cmnd * scp,
if (scsi_debug_lbp()) { if (scsi_debug_lbp()) {
arr[14] |= 0x80; /* LBPME */ arr[14] |= 0x80; /* LBPME */
if (sdebug_lbprz) /* from sbc4r07, this LBPRZ field is 1 bit, but the LBPRZ in
arr[14] |= 0x40; /* LBPRZ */ * the LB Provisioning VPD page is 3 bits. Note that lbprz=2
* in the wider field maps to 0 in this field.
*/
if (sdebug_lbprz & 1) /* precisely what the draft requires */
arr[14] |= 0x40;
} }
arr[15] = sdebug_lowest_aligned & 0xff; arr[15] = sdebug_lowest_aligned & 0xff;
if (sdebug_dif) { if (have_dif_prot) {
arr[12] = (sdebug_dif - 1) << 1; /* P_TYPE */ arr[12] = (sdebug_dif - 1) << 1; /* P_TYPE */
arr[12] |= 1; /* PROT_EN */ arr[12] |= 1; /* PROT_EN */
} }
...@@ -1935,22 +1945,23 @@ static int resp_sas_sha_m_spg(unsigned char * p, int pcontrol) ...@@ -1935,22 +1945,23 @@ static int resp_sas_sha_m_spg(unsigned char * p, int pcontrol)
static int resp_mode_sense(struct scsi_cmnd *scp, static int resp_mode_sense(struct scsi_cmnd *scp,
struct sdebug_dev_info *devip) struct sdebug_dev_info *devip)
{ {
unsigned char dbd, llbaa;
int pcontrol, pcode, subpcode, bd_len; int pcontrol, pcode, subpcode, bd_len;
unsigned char dev_spec; unsigned char dev_spec;
int alloc_len, msense_6, offset, len, target_dev_id; int alloc_len, offset, len, target_dev_id;
int target = scp->device->id; int target = scp->device->id;
unsigned char * ap; unsigned char * ap;
unsigned char arr[SDEBUG_MAX_MSENSE_SZ]; unsigned char arr[SDEBUG_MAX_MSENSE_SZ];
unsigned char *cmd = scp->cmnd; unsigned char *cmd = scp->cmnd;
bool dbd, llbaa, msense_6, is_disk, bad_pcode;
dbd = !!(cmd[1] & 0x8); dbd = !!(cmd[1] & 0x8); /* disable block descriptors */
pcontrol = (cmd[2] & 0xc0) >> 6; pcontrol = (cmd[2] & 0xc0) >> 6;
pcode = cmd[2] & 0x3f; pcode = cmd[2] & 0x3f;
subpcode = cmd[3]; subpcode = cmd[3];
msense_6 = (MODE_SENSE == cmd[0]); msense_6 = (MODE_SENSE == cmd[0]);
llbaa = msense_6 ? 0 : !!(cmd[1] & 0x10); llbaa = msense_6 ? false : !!(cmd[1] & 0x10);
if ((sdebug_ptype == TYPE_DISK) && (dbd == 0)) is_disk = (sdebug_ptype == TYPE_DISK);
if (is_disk && !dbd)
bd_len = llbaa ? 16 : 8; bd_len = llbaa ? 16 : 8;
else else
bd_len = 0; bd_len = 0;
...@@ -1963,7 +1974,7 @@ static int resp_mode_sense(struct scsi_cmnd *scp, ...@@ -1963,7 +1974,7 @@ static int resp_mode_sense(struct scsi_cmnd *scp,
target_dev_id = ((devip->sdbg_host->shost->host_no + 1) * 2000) + target_dev_id = ((devip->sdbg_host->shost->host_no + 1) * 2000) +
(devip->target * 1000) - 3; (devip->target * 1000) - 3;
/* for disks set DPOFUA bit and clear write protect (WP) bit */ /* for disks set DPOFUA bit and clear write protect (WP) bit */
if (sdebug_ptype == TYPE_DISK) if (is_disk)
dev_spec = 0x10; /* =0x90 if WP=1 implies read-only */ dev_spec = 0x10; /* =0x90 if WP=1 implies read-only */
else else
dev_spec = 0x0; dev_spec = 0x0;
...@@ -2002,6 +2013,8 @@ static int resp_mode_sense(struct scsi_cmnd *scp, ...@@ -2002,6 +2013,8 @@ static int resp_mode_sense(struct scsi_cmnd *scp,
mk_sense_invalid_fld(scp, SDEB_IN_CDB, 3, -1); mk_sense_invalid_fld(scp, SDEB_IN_CDB, 3, -1);
return check_condition_result; return check_condition_result;
} }
bad_pcode = false;
switch (pcode) { switch (pcode) {
case 0x1: /* Read-Write error recovery page, direct access */ case 0x1: /* Read-Write error recovery page, direct access */
len = resp_err_recov_pg(ap, pcontrol, target); len = resp_err_recov_pg(ap, pcontrol, target);
...@@ -2012,12 +2025,18 @@ static int resp_mode_sense(struct scsi_cmnd *scp, ...@@ -2012,12 +2025,18 @@ static int resp_mode_sense(struct scsi_cmnd *scp,
offset += len; offset += len;
break; break;
case 0x3: /* Format device page, direct access */ case 0x3: /* Format device page, direct access */
len = resp_format_pg(ap, pcontrol, target); if (is_disk) {
offset += len; len = resp_format_pg(ap, pcontrol, target);
offset += len;
} else
bad_pcode = true;
break; break;
case 0x8: /* Caching page, direct access */ case 0x8: /* Caching page, direct access */
len = resp_caching_pg(ap, pcontrol, target); if (is_disk) {
offset += len; len = resp_caching_pg(ap, pcontrol, target);
offset += len;
} else
bad_pcode = true;
break; break;
case 0xa: /* Control Mode page, all devices */ case 0xa: /* Control Mode page, all devices */
len = resp_ctrl_m_pg(ap, pcontrol, target); len = resp_ctrl_m_pg(ap, pcontrol, target);
...@@ -2046,8 +2065,12 @@ static int resp_mode_sense(struct scsi_cmnd *scp, ...@@ -2046,8 +2065,12 @@ static int resp_mode_sense(struct scsi_cmnd *scp,
if ((0 == subpcode) || (0xff == subpcode)) { if ((0 == subpcode) || (0xff == subpcode)) {
len = resp_err_recov_pg(ap, pcontrol, target); len = resp_err_recov_pg(ap, pcontrol, target);
len += resp_disconnect_pg(ap + len, pcontrol, target); len += resp_disconnect_pg(ap + len, pcontrol, target);
len += resp_format_pg(ap + len, pcontrol, target); if (is_disk) {
len += resp_caching_pg(ap + len, pcontrol, target); len += resp_format_pg(ap + len, pcontrol,
target);
len += resp_caching_pg(ap + len, pcontrol,
target);
}
len += resp_ctrl_m_pg(ap + len, pcontrol, target); len += resp_ctrl_m_pg(ap + len, pcontrol, target);
len += resp_sas_sf_m_pg(ap + len, pcontrol, target); len += resp_sas_sf_m_pg(ap + len, pcontrol, target);
if (0xff == subpcode) { if (0xff == subpcode) {
...@@ -2056,13 +2079,17 @@ static int resp_mode_sense(struct scsi_cmnd *scp, ...@@ -2056,13 +2079,17 @@ static int resp_mode_sense(struct scsi_cmnd *scp,
len += resp_sas_sha_m_spg(ap + len, pcontrol); len += resp_sas_sha_m_spg(ap + len, pcontrol);
} }
len += resp_iec_m_pg(ap + len, pcontrol, target); len += resp_iec_m_pg(ap + len, pcontrol, target);
offset += len;
} else { } else {
mk_sense_invalid_fld(scp, SDEB_IN_CDB, 3, -1); mk_sense_invalid_fld(scp, SDEB_IN_CDB, 3, -1);
return check_condition_result; return check_condition_result;
} }
offset += len;
break; break;
default: default:
bad_pcode = true;
break;
}
if (bad_pcode) {
mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, 5); mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, 5);
return check_condition_result; return check_condition_result;
} }
...@@ -2753,9 +2780,10 @@ static void unmap_region(sector_t lba, unsigned int len) ...@@ -2753,9 +2780,10 @@ static void unmap_region(sector_t lba, unsigned int len)
lba + sdebug_unmap_granularity <= end && lba + sdebug_unmap_granularity <= end &&
index < map_size) { index < map_size) {
clear_bit(index, map_storep); clear_bit(index, map_storep);
if (sdebug_lbprz) { if (sdebug_lbprz) { /* for LBPRZ=2 return 0xff_s */
memset(fake_storep + memset(fake_storep +
lba * sdebug_sector_size, 0, lba * sdebug_sector_size,
(sdebug_lbprz & 1) ? 0 : 0xff,
sdebug_sector_size * sdebug_sector_size *
sdebug_unmap_granularity); sdebug_unmap_granularity);
} }
...@@ -4098,7 +4126,8 @@ MODULE_PARM_DESC(host_lock, "host_lock is ignored (def=0)"); ...@@ -4098,7 +4126,8 @@ MODULE_PARM_DESC(host_lock, "host_lock is ignored (def=0)");
MODULE_PARM_DESC(lbpu, "enable LBP, support UNMAP command (def=0)"); MODULE_PARM_DESC(lbpu, "enable LBP, support UNMAP command (def=0)");
MODULE_PARM_DESC(lbpws, "enable LBP, support WRITE SAME(16) with UNMAP bit (def=0)"); MODULE_PARM_DESC(lbpws, "enable LBP, support WRITE SAME(16) with UNMAP bit (def=0)");
MODULE_PARM_DESC(lbpws10, "enable LBP, support WRITE SAME(10) with UNMAP bit (def=0)"); MODULE_PARM_DESC(lbpws10, "enable LBP, support WRITE SAME(10) with UNMAP bit (def=0)");
MODULE_PARM_DESC(lbprz, "unmapped blocks return 0 on read (def=1)"); MODULE_PARM_DESC(lbprz,
"on read unmapped LBs return 0 when 1 (def), return 0xff when 2");
MODULE_PARM_DESC(lowest_aligned, "lowest aligned lba (def=0)"); MODULE_PARM_DESC(lowest_aligned, "lowest aligned lba (def=0)");
MODULE_PARM_DESC(max_luns, "number of LUNs per target to simulate(def=1)"); MODULE_PARM_DESC(max_luns, "number of LUNs per target to simulate(def=1)");
MODULE_PARM_DESC(max_queue, "max number of queued commands (1 to max(def))"); MODULE_PARM_DESC(max_queue, "max number of queued commands (1 to max(def))");
...@@ -4112,7 +4141,7 @@ MODULE_PARM_DESC(opts, "1->noise, 2->medium_err, 4->timeout, 8->recovered_err... ...@@ -4112,7 +4141,7 @@ MODULE_PARM_DESC(opts, "1->noise, 2->medium_err, 4->timeout, 8->recovered_err...
MODULE_PARM_DESC(physblk_exp, "physical block exponent (def=0)"); MODULE_PARM_DESC(physblk_exp, "physical block exponent (def=0)");
MODULE_PARM_DESC(ptype, "SCSI peripheral type(def=0[disk])"); MODULE_PARM_DESC(ptype, "SCSI peripheral type(def=0[disk])");
MODULE_PARM_DESC(removable, "claim to have removable media (def=0)"); MODULE_PARM_DESC(removable, "claim to have removable media (def=0)");
MODULE_PARM_DESC(scsi_level, "SCSI level to simulate(def=6[SPC-4])"); MODULE_PARM_DESC(scsi_level, "SCSI level to simulate(def=7[SPC-5])");
MODULE_PARM_DESC(sector_size, "logical block size in bytes (def=512)"); MODULE_PARM_DESC(sector_size, "logical block size in bytes (def=512)");
MODULE_PARM_DESC(statistics, "collect statistics on commands, queues (def=0)"); MODULE_PARM_DESC(statistics, "collect statistics on commands, queues (def=0)");
MODULE_PARM_DESC(strict, "stricter checks: reserved field in cdb (def=0)"); MODULE_PARM_DESC(strict, "stricter checks: reserved field in cdb (def=0)");
...@@ -4125,21 +4154,21 @@ MODULE_PARM_DESC(virtual_gb, "virtual gigabyte (GiB) size (def=0 -> use dev_size ...@@ -4125,21 +4154,21 @@ MODULE_PARM_DESC(virtual_gb, "virtual gigabyte (GiB) size (def=0 -> use dev_size
MODULE_PARM_DESC(vpd_use_hostno, "0 -> dev ids ignore hostno (def=1 -> unique dev ids)"); MODULE_PARM_DESC(vpd_use_hostno, "0 -> dev ids ignore hostno (def=1 -> unique dev ids)");
MODULE_PARM_DESC(write_same_length, "Maximum blocks per WRITE SAME cmd (def=0xffff)"); MODULE_PARM_DESC(write_same_length, "Maximum blocks per WRITE SAME cmd (def=0xffff)");
static char sdebug_info[256]; #define SDEBUG_INFO_LEN 256
static char sdebug_info[SDEBUG_INFO_LEN];
static const char * scsi_debug_info(struct Scsi_Host * shp) static const char * scsi_debug_info(struct Scsi_Host * shp)
{ {
int k; int k;
k = scnprintf(sdebug_info, sizeof(sdebug_info), k = scnprintf(sdebug_info, SDEBUG_INFO_LEN, "%s: version %s [%s]\n",
"%s: version %s [%s], dev_size_mb=%d, opts=0x%x\n", my_name, SDEBUG_VERSION, sdebug_version_date);
my_name, SDEBUG_VERSION, sdebug_version_date, if (k >= (SDEBUG_INFO_LEN - 1))
sdebug_dev_size_mb, sdebug_opts);
if (k >= (sizeof(sdebug_info) - 1))
return sdebug_info; return sdebug_info;
scnprintf(sdebug_info + k, sizeof(sdebug_info) - k, scnprintf(sdebug_info + k, SDEBUG_INFO_LEN - k,
"%s: submit_queues=%d, statistics=%d\n", my_name, " dev_size_mb=%d, opts=0x%x, submit_queues=%d, %s=%d",
submit_queues, (int)sdebug_statistics); sdebug_dev_size_mb, sdebug_opts, submit_queues,
"statistics", (int)sdebug_statistics);
return sdebug_info; return sdebug_info;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment