Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 213335
b: refs/heads/master
c: 6014759
h: refs/heads/master
i:
  213333: 1daa68a
  213331: bd2d401
  213327: ece3312
v: v3
  • Loading branch information
Martin K. Petersen authored and James Bottomley committed Sep 9, 2010
1 parent 3cfa7c6 commit a09a4a0
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 32 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 47259658ed9fad837541b738f9375d38022daa14
refs/heads/master: 6014759c929b4ce8c068810b8d05f31969df5897
100 changes: 69 additions & 31 deletions trunk/drivers/scsi/scsi_debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,12 @@ static const char * scsi_debug_version_date = "20100324";
#define DEF_PHYSBLK_EXP 0
#define DEF_LOWEST_ALIGNED 0
#define DEF_OPT_BLKS 64
#define DEF_UNMAP_MAX_BLOCKS 0
#define DEF_UNMAP_MAX_DESC 0
#define DEF_UNMAP_GRANULARITY 0
#define DEF_UNMAP_MAX_BLOCKS 0xFFFFFFFF
#define DEF_UNMAP_MAX_DESC 256
#define DEF_UNMAP_GRANULARITY 1
#define DEF_UNMAP_ALIGNMENT 0
#define DEF_TPWS 0
#define DEF_TPU 0

/* bit mask values for scsi_debug_opts */
#define SCSI_DEBUG_OPT_NOISE 1
Expand Down Expand Up @@ -177,10 +179,12 @@ static int scsi_debug_ato = DEF_ATO;
static int scsi_debug_physblk_exp = DEF_PHYSBLK_EXP;
static int scsi_debug_lowest_aligned = DEF_LOWEST_ALIGNED;
static int scsi_debug_opt_blks = DEF_OPT_BLKS;
static int scsi_debug_unmap_max_desc = DEF_UNMAP_MAX_DESC;
static int scsi_debug_unmap_max_blocks = DEF_UNMAP_MAX_BLOCKS;
static int scsi_debug_unmap_granularity = DEF_UNMAP_GRANULARITY;
static int scsi_debug_unmap_alignment = DEF_UNMAP_ALIGNMENT;
static unsigned int scsi_debug_unmap_max_desc = DEF_UNMAP_MAX_DESC;
static unsigned int scsi_debug_unmap_max_blocks = DEF_UNMAP_MAX_BLOCKS;
static unsigned int scsi_debug_unmap_granularity = DEF_UNMAP_GRANULARITY;
static unsigned int scsi_debug_unmap_alignment = DEF_UNMAP_ALIGNMENT;
static unsigned int scsi_debug_tpws = DEF_TPWS;
static unsigned int scsi_debug_tpu = DEF_TPU;

static int scsi_debug_cmnd_count = 0;

Expand Down Expand Up @@ -723,16 +727,9 @@ static int inquiry_evpd_b0(unsigned char * arr)
/* Optimal Transfer Length */
put_unaligned_be32(scsi_debug_opt_blks, &arr[8]);

if (scsi_debug_unmap_max_desc) {
unsigned int blocks;

if (scsi_debug_unmap_max_blocks)
blocks = scsi_debug_unmap_max_blocks;
else
blocks = 0xffffffff;

if (scsi_debug_tpu) {
/* Maximum Unmap LBA Count */
put_unaligned_be32(blocks, &arr[16]);
put_unaligned_be32(scsi_debug_unmap_max_blocks, &arr[16]);

/* Maximum Unmap Block Descriptor Count */
put_unaligned_be32(scsi_debug_unmap_max_desc, &arr[20]);
Expand All @@ -745,10 +742,9 @@ static int inquiry_evpd_b0(unsigned char * arr)
}

/* Optimal Unmap Granularity */
if (scsi_debug_unmap_granularity) {
put_unaligned_be32(scsi_debug_unmap_granularity, &arr[24]);
return 0x3c; /* Mandatory page length for thin provisioning */
}
put_unaligned_be32(scsi_debug_unmap_granularity, &arr[24]);

return 0x3c; /* Mandatory page length for thin provisioning */

return sizeof(vpdb0_data);
}
Expand All @@ -765,6 +761,21 @@ static int inquiry_evpd_b1(unsigned char *arr)
return 0x3c;
}

/* Thin provisioning VPD page (SBC-3) */
static int inquiry_evpd_b2(unsigned char *arr)
{
memset(arr, 0, 0x8);
arr[0] = 0; /* threshold exponent */

if (scsi_debug_tpu)
arr[1] = 1 << 7;

if (scsi_debug_tpws)
arr[1] |= 1 << 6;

return 0x8;
}

#define SDEBUG_LONG_INQ_SZ 96
#define SDEBUG_MAX_INQ_ARR_SZ 584

Expand Down Expand Up @@ -820,6 +831,7 @@ static int resp_inquiry(struct scsi_cmnd * scp, int target,
arr[n++] = 0x89; /* ATA information */
arr[n++] = 0xb0; /* Block limits (SBC) */
arr[n++] = 0xb1; /* Block characteristics (SBC) */
arr[n++] = 0xb2; /* Thin provisioning (SBC) */
arr[3] = n - 4; /* number of supported VPD pages */
} else if (0x80 == cmd[2]) { /* unit serial number */
arr[1] = cmd[2]; /*sanity */
Expand Down Expand Up @@ -867,6 +879,9 @@ static int resp_inquiry(struct scsi_cmnd * scp, int target,
} else if (0xb1 == cmd[2]) { /* Block characteristics (SBC) */
arr[1] = cmd[2]; /*sanity */
arr[3] = inquiry_evpd_b1(&arr[4]);
} else if (0xb2 == cmd[2]) { /* Thin provisioning (SBC) */
arr[1] = cmd[2]; /*sanity */
arr[3] = inquiry_evpd_b2(&arr[4]);
} else {
/* Illegal request, invalid field in cdb */
mk_sense_buffer(devip, ILLEGAL_REQUEST,
Expand Down Expand Up @@ -1038,7 +1053,7 @@ static int resp_readcap16(struct scsi_cmnd * scp,
arr[13] = scsi_debug_physblk_exp & 0xf;
arr[14] = (scsi_debug_lowest_aligned >> 8) & 0x3f;

if (scsi_debug_unmap_granularity)
if (scsi_debug_tpu || scsi_debug_tpws)
arr[14] |= 0x80; /* TPE */

arr[15] = scsi_debug_lowest_aligned & 0xff;
Expand Down Expand Up @@ -2708,6 +2723,8 @@ module_param_named(unmap_max_blocks, scsi_debug_unmap_max_blocks, int, S_IRUGO);
module_param_named(unmap_max_desc, scsi_debug_unmap_max_desc, int, S_IRUGO);
module_param_named(unmap_granularity, scsi_debug_unmap_granularity, int, S_IRUGO);
module_param_named(unmap_alignment, scsi_debug_unmap_alignment, int, S_IRUGO);
module_param_named(tpu, scsi_debug_tpu, int, S_IRUGO);
module_param_named(tpws, scsi_debug_tpws, int, S_IRUGO);

MODULE_AUTHOR("Eric Youngdale + Douglas Gilbert");
MODULE_DESCRIPTION("SCSI debug adapter driver");
Expand Down Expand Up @@ -2739,10 +2756,12 @@ MODULE_PARM_DESC(dix, "data integrity extensions mask (def=0)");
MODULE_PARM_DESC(dif, "data integrity field type: 0-3 (def=0)");
MODULE_PARM_DESC(guard, "protection checksum: 0=crc, 1=ip (def=0)");
MODULE_PARM_DESC(ato, "application tag ownership: 0=disk 1=host (def=1)");
MODULE_PARM_DESC(unmap_max_blocks, "max # of blocks can be unmapped in one cmd (def=0)");
MODULE_PARM_DESC(unmap_max_desc, "max # of ranges that can be unmapped in one cmd (def=0)");
MODULE_PARM_DESC(unmap_granularity, "thin provisioning granularity in blocks (def=0)");
MODULE_PARM_DESC(unmap_max_blocks, "max # of blocks can be unmapped in one cmd (def=0xffffffff)");
MODULE_PARM_DESC(unmap_max_desc, "max # of ranges that can be unmapped in one cmd (def=256)");
MODULE_PARM_DESC(unmap_granularity, "thin provisioning granularity in blocks (def=1)");
MODULE_PARM_DESC(unmap_alignment, "lowest aligned thin provisioning lba (def=0)");
MODULE_PARM_DESC(tpu, "enable TP, support UNMAP command (def=0)");
MODULE_PARM_DESC(tpws, "enable TP, support WRITE SAME(16) with UNMAP bit (def=0)");

static char sdebug_info[256];

Expand Down Expand Up @@ -3130,7 +3149,7 @@ static ssize_t sdebug_map_show(struct device_driver *ddp, char *buf)
{
ssize_t count;

if (scsi_debug_unmap_granularity == 0)
if (scsi_debug_tpu == 0 && scsi_debug_tpws == 0)
return scnprintf(buf, PAGE_SIZE, "0-%u\n",
sdebug_store_sectors);

Expand Down Expand Up @@ -3322,10 +3341,21 @@ static int __init scsi_debug_init(void)
memset(dif_storep, 0xff, dif_size);
}

if (scsi_debug_unmap_granularity) {
/* Thin Provisioning */
if (scsi_debug_tpu || scsi_debug_tpws) {
unsigned int map_bytes;

if (scsi_debug_unmap_granularity < scsi_debug_unmap_alignment) {
scsi_debug_unmap_max_blocks =
clamp(scsi_debug_unmap_max_blocks, 0U, 0xffffffffU);

scsi_debug_unmap_max_desc =
clamp(scsi_debug_unmap_max_desc, 0U, 256U);

scsi_debug_unmap_granularity =
clamp(scsi_debug_unmap_granularity, 1U, 0xffffffffU);

if (scsi_debug_unmap_alignment &&
scsi_debug_unmap_granularity < scsi_debug_unmap_alignment) {
printk(KERN_ERR
"%s: ERR: unmap_granularity < unmap_alignment\n",
__func__);
Expand Down Expand Up @@ -3642,7 +3672,7 @@ int scsi_debug_queuecommand(struct scsi_cmnd *SCpnt, done_funct_t done)
errsts = resp_readcap16(SCpnt, devip);
else if (cmd[1] == SAI_GET_LBA_STATUS) {

if (scsi_debug_unmap_max_desc == 0) {
if (scsi_debug_tpu == 0 && scsi_debug_tpws == 0) {
mk_sense_buffer(devip, ILLEGAL_REQUEST,
INVALID_COMMAND_OPCODE, 0);
errsts = check_condition_result;
Expand Down Expand Up @@ -3753,8 +3783,16 @@ int scsi_debug_queuecommand(struct scsi_cmnd *SCpnt, done_funct_t done)
}
break;
case WRITE_SAME_16:
if (cmd[1] & 0x8)
unmap = 1;
if (cmd[1] & 0x8) {
if (scsi_debug_tpws == 0) {
mk_sense_buffer(devip, ILLEGAL_REQUEST,
INVALID_FIELD_IN_CDB, 0);
errsts = check_condition_result;
} else
unmap = 1;
}
if (errsts)
break;
/* fall through */
case WRITE_SAME:
errsts = check_readiness(SCpnt, 0, devip);
Expand All @@ -3768,7 +3806,7 @@ int scsi_debug_queuecommand(struct scsi_cmnd *SCpnt, done_funct_t done)
if (errsts)
break;

if (scsi_debug_unmap_max_desc == 0) {
if (scsi_debug_unmap_max_desc == 0 || scsi_debug_tpu == 0) {
mk_sense_buffer(devip, ILLEGAL_REQUEST,
INVALID_COMMAND_OPCODE, 0);
errsts = check_condition_result;
Expand Down

0 comments on commit a09a4a0

Please sign in to comment.