aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_debug.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/scsi_debug.c')
-rw-r--r--drivers/scsi/scsi_debug.c100
1 files changed, 69 insertions, 31 deletions
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index b02bdc6c2cd..06329d47b38 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -109,10 +109,12 @@ static const char * scsi_debug_version_date = "20100324";
109#define DEF_PHYSBLK_EXP 0 109#define DEF_PHYSBLK_EXP 0
110#define DEF_LOWEST_ALIGNED 0 110#define DEF_LOWEST_ALIGNED 0
111#define DEF_OPT_BLKS 64 111#define DEF_OPT_BLKS 64
112#define DEF_UNMAP_MAX_BLOCKS 0 112#define DEF_UNMAP_MAX_BLOCKS 0xFFFFFFFF
113#define DEF_UNMAP_MAX_DESC 0 113#define DEF_UNMAP_MAX_DESC 256
114#define DEF_UNMAP_GRANULARITY 0 114#define DEF_UNMAP_GRANULARITY 1
115#define DEF_UNMAP_ALIGNMENT 0 115#define DEF_UNMAP_ALIGNMENT 0
116#define DEF_TPWS 0
117#define DEF_TPU 0
116 118
117/* bit mask values for scsi_debug_opts */ 119/* bit mask values for scsi_debug_opts */
118#define SCSI_DEBUG_OPT_NOISE 1 120#define SCSI_DEBUG_OPT_NOISE 1
@@ -177,10 +179,12 @@ static int scsi_debug_ato = DEF_ATO;
177static int scsi_debug_physblk_exp = DEF_PHYSBLK_EXP; 179static int scsi_debug_physblk_exp = DEF_PHYSBLK_EXP;
178static int scsi_debug_lowest_aligned = DEF_LOWEST_ALIGNED; 180static int scsi_debug_lowest_aligned = DEF_LOWEST_ALIGNED;
179static int scsi_debug_opt_blks = DEF_OPT_BLKS; 181static int scsi_debug_opt_blks = DEF_OPT_BLKS;
180static int scsi_debug_unmap_max_desc = DEF_UNMAP_MAX_DESC; 182static unsigned int scsi_debug_unmap_max_desc = DEF_UNMAP_MAX_DESC;
181static int scsi_debug_unmap_max_blocks = DEF_UNMAP_MAX_BLOCKS; 183static unsigned int scsi_debug_unmap_max_blocks = DEF_UNMAP_MAX_BLOCKS;
182static int scsi_debug_unmap_granularity = DEF_UNMAP_GRANULARITY; 184static unsigned int scsi_debug_unmap_granularity = DEF_UNMAP_GRANULARITY;
183static int scsi_debug_unmap_alignment = DEF_UNMAP_ALIGNMENT; 185static unsigned int scsi_debug_unmap_alignment = DEF_UNMAP_ALIGNMENT;
186static unsigned int scsi_debug_tpws = DEF_TPWS;
187static unsigned int scsi_debug_tpu = DEF_TPU;
184 188
185static int scsi_debug_cmnd_count = 0; 189static int scsi_debug_cmnd_count = 0;
186 190
@@ -723,16 +727,9 @@ static int inquiry_evpd_b0(unsigned char * arr)
723 /* Optimal Transfer Length */ 727 /* Optimal Transfer Length */
724 put_unaligned_be32(scsi_debug_opt_blks, &arr[8]); 728 put_unaligned_be32(scsi_debug_opt_blks, &arr[8]);
725 729
726 if (scsi_debug_unmap_max_desc) { 730 if (scsi_debug_tpu) {
727 unsigned int blocks;
728
729 if (scsi_debug_unmap_max_blocks)
730 blocks = scsi_debug_unmap_max_blocks;
731 else
732 blocks = 0xffffffff;
733
734 /* Maximum Unmap LBA Count */ 731 /* Maximum Unmap LBA Count */
735 put_unaligned_be32(blocks, &arr[16]); 732 put_unaligned_be32(scsi_debug_unmap_max_blocks, &arr[16]);
736 733
737 /* Maximum Unmap Block Descriptor Count */ 734 /* Maximum Unmap Block Descriptor Count */
738 put_unaligned_be32(scsi_debug_unmap_max_desc, &arr[20]); 735 put_unaligned_be32(scsi_debug_unmap_max_desc, &arr[20]);
@@ -745,10 +742,9 @@ static int inquiry_evpd_b0(unsigned char * arr)
745 } 742 }
746 743
747 /* Optimal Unmap Granularity */ 744 /* Optimal Unmap Granularity */
748 if (scsi_debug_unmap_granularity) { 745 put_unaligned_be32(scsi_debug_unmap_granularity, &arr[24]);
749 put_unaligned_be32(scsi_debug_unmap_granularity, &arr[24]); 746
750 return 0x3c; /* Mandatory page length for thin provisioning */ 747 return 0x3c; /* Mandatory page length for thin provisioning */
751 }
752 748
753 return sizeof(vpdb0_data); 749 return sizeof(vpdb0_data);
754} 750}
@@ -765,6 +761,21 @@ static int inquiry_evpd_b1(unsigned char *arr)
765 return 0x3c; 761 return 0x3c;
766} 762}
767 763
764/* Thin provisioning VPD page (SBC-3) */
765static int inquiry_evpd_b2(unsigned char *arr)
766{
767 memset(arr, 0, 0x8);
768 arr[0] = 0; /* threshold exponent */
769
770 if (scsi_debug_tpu)
771 arr[1] = 1 << 7;
772
773 if (scsi_debug_tpws)
774 arr[1] |= 1 << 6;
775
776 return 0x8;
777}
778
768#define SDEBUG_LONG_INQ_SZ 96 779#define SDEBUG_LONG_INQ_SZ 96
769#define SDEBUG_MAX_INQ_ARR_SZ 584 780#define SDEBUG_MAX_INQ_ARR_SZ 584
770 781
@@ -820,6 +831,7 @@ static int resp_inquiry(struct scsi_cmnd * scp, int target,
820 arr[n++] = 0x89; /* ATA information */ 831 arr[n++] = 0x89; /* ATA information */
821 arr[n++] = 0xb0; /* Block limits (SBC) */ 832 arr[n++] = 0xb0; /* Block limits (SBC) */
822 arr[n++] = 0xb1; /* Block characteristics (SBC) */ 833 arr[n++] = 0xb1; /* Block characteristics (SBC) */
834 arr[n++] = 0xb2; /* Thin provisioning (SBC) */
823 arr[3] = n - 4; /* number of supported VPD pages */ 835 arr[3] = n - 4; /* number of supported VPD pages */
824 } else if (0x80 == cmd[2]) { /* unit serial number */ 836 } else if (0x80 == cmd[2]) { /* unit serial number */
825 arr[1] = cmd[2]; /*sanity */ 837 arr[1] = cmd[2]; /*sanity */
@@ -867,6 +879,9 @@ static int resp_inquiry(struct scsi_cmnd * scp, int target,
867 } else if (0xb1 == cmd[2]) { /* Block characteristics (SBC) */ 879 } else if (0xb1 == cmd[2]) { /* Block characteristics (SBC) */
868 arr[1] = cmd[2]; /*sanity */ 880 arr[1] = cmd[2]; /*sanity */
869 arr[3] = inquiry_evpd_b1(&arr[4]); 881 arr[3] = inquiry_evpd_b1(&arr[4]);
882 } else if (0xb2 == cmd[2]) { /* Thin provisioning (SBC) */
883 arr[1] = cmd[2]; /*sanity */
884 arr[3] = inquiry_evpd_b2(&arr[4]);
870 } else { 885 } else {
871 /* Illegal request, invalid field in cdb */ 886 /* Illegal request, invalid field in cdb */
872 mk_sense_buffer(devip, ILLEGAL_REQUEST, 887 mk_sense_buffer(devip, ILLEGAL_REQUEST,
@@ -1038,7 +1053,7 @@ static int resp_readcap16(struct scsi_cmnd * scp,
1038 arr[13] = scsi_debug_physblk_exp & 0xf; 1053 arr[13] = scsi_debug_physblk_exp & 0xf;
1039 arr[14] = (scsi_debug_lowest_aligned >> 8) & 0x3f; 1054 arr[14] = (scsi_debug_lowest_aligned >> 8) & 0x3f;
1040 1055
1041 if (scsi_debug_unmap_granularity) 1056 if (scsi_debug_tpu || scsi_debug_tpws)
1042 arr[14] |= 0x80; /* TPE */ 1057 arr[14] |= 0x80; /* TPE */
1043 1058
1044 arr[15] = scsi_debug_lowest_aligned & 0xff; 1059 arr[15] = scsi_debug_lowest_aligned & 0xff;
@@ -2708,6 +2723,8 @@ module_param_named(unmap_max_blocks, scsi_debug_unmap_max_blocks, int, S_IRUGO);
2708module_param_named(unmap_max_desc, scsi_debug_unmap_max_desc, int, S_IRUGO); 2723module_param_named(unmap_max_desc, scsi_debug_unmap_max_desc, int, S_IRUGO);
2709module_param_named(unmap_granularity, scsi_debug_unmap_granularity, int, S_IRUGO); 2724module_param_named(unmap_granularity, scsi_debug_unmap_granularity, int, S_IRUGO);
2710module_param_named(unmap_alignment, scsi_debug_unmap_alignment, int, S_IRUGO); 2725module_param_named(unmap_alignment, scsi_debug_unmap_alignment, int, S_IRUGO);
2726module_param_named(tpu, scsi_debug_tpu, int, S_IRUGO);
2727module_param_named(tpws, scsi_debug_tpws, int, S_IRUGO);
2711 2728
2712MODULE_AUTHOR("Eric Youngdale + Douglas Gilbert"); 2729MODULE_AUTHOR("Eric Youngdale + Douglas Gilbert");
2713MODULE_DESCRIPTION("SCSI debug adapter driver"); 2730MODULE_DESCRIPTION("SCSI debug adapter driver");
@@ -2739,10 +2756,12 @@ MODULE_PARM_DESC(dix, "data integrity extensions mask (def=0)");
2739MODULE_PARM_DESC(dif, "data integrity field type: 0-3 (def=0)"); 2756MODULE_PARM_DESC(dif, "data integrity field type: 0-3 (def=0)");
2740MODULE_PARM_DESC(guard, "protection checksum: 0=crc, 1=ip (def=0)"); 2757MODULE_PARM_DESC(guard, "protection checksum: 0=crc, 1=ip (def=0)");
2741MODULE_PARM_DESC(ato, "application tag ownership: 0=disk 1=host (def=1)"); 2758MODULE_PARM_DESC(ato, "application tag ownership: 0=disk 1=host (def=1)");
2742MODULE_PARM_DESC(unmap_max_blocks, "max # of blocks can be unmapped in one cmd (def=0)"); 2759MODULE_PARM_DESC(unmap_max_blocks, "max # of blocks can be unmapped in one cmd (def=0xffffffff)");
2743MODULE_PARM_DESC(unmap_max_desc, "max # of ranges that can be unmapped in one cmd (def=0)"); 2760MODULE_PARM_DESC(unmap_max_desc, "max # of ranges that can be unmapped in one cmd (def=256)");
2744MODULE_PARM_DESC(unmap_granularity, "thin provisioning granularity in blocks (def=0)"); 2761MODULE_PARM_DESC(unmap_granularity, "thin provisioning granularity in blocks (def=1)");
2745MODULE_PARM_DESC(unmap_alignment, "lowest aligned thin provisioning lba (def=0)"); 2762MODULE_PARM_DESC(unmap_alignment, "lowest aligned thin provisioning lba (def=0)");
2763MODULE_PARM_DESC(tpu, "enable TP, support UNMAP command (def=0)");
2764MODULE_PARM_DESC(tpws, "enable TP, support WRITE SAME(16) with UNMAP bit (def=0)");
2746 2765
2747static char sdebug_info[256]; 2766static char sdebug_info[256];
2748 2767
@@ -3130,7 +3149,7 @@ static ssize_t sdebug_map_show(struct device_driver *ddp, char *buf)
3130{ 3149{
3131 ssize_t count; 3150 ssize_t count;
3132 3151
3133 if (scsi_debug_unmap_granularity == 0) 3152 if (scsi_debug_tpu == 0 && scsi_debug_tpws == 0)
3134 return scnprintf(buf, PAGE_SIZE, "0-%u\n", 3153 return scnprintf(buf, PAGE_SIZE, "0-%u\n",
3135 sdebug_store_sectors); 3154 sdebug_store_sectors);
3136 3155
@@ -3322,10 +3341,21 @@ static int __init scsi_debug_init(void)
3322 memset(dif_storep, 0xff, dif_size); 3341 memset(dif_storep, 0xff, dif_size);
3323 } 3342 }
3324 3343
3325 if (scsi_debug_unmap_granularity) { 3344 /* Thin Provisioning */
3345 if (scsi_debug_tpu || scsi_debug_tpws) {
3326 unsigned int map_bytes; 3346 unsigned int map_bytes;
3327 3347
3328 if (scsi_debug_unmap_granularity < scsi_debug_unmap_alignment) { 3348 scsi_debug_unmap_max_blocks =
3349 clamp(scsi_debug_unmap_max_blocks, 0U, 0xffffffffU);
3350
3351 scsi_debug_unmap_max_desc =
3352 clamp(scsi_debug_unmap_max_desc, 0U, 256U);
3353
3354 scsi_debug_unmap_granularity =
3355 clamp(scsi_debug_unmap_granularity, 1U, 0xffffffffU);
3356
3357 if (scsi_debug_unmap_alignment &&
3358 scsi_debug_unmap_granularity < scsi_debug_unmap_alignment) {
3329 printk(KERN_ERR 3359 printk(KERN_ERR
3330 "%s: ERR: unmap_granularity < unmap_alignment\n", 3360 "%s: ERR: unmap_granularity < unmap_alignment\n",
3331 __func__); 3361 __func__);
@@ -3642,7 +3672,7 @@ int scsi_debug_queuecommand(struct scsi_cmnd *SCpnt, done_funct_t done)
3642 errsts = resp_readcap16(SCpnt, devip); 3672 errsts = resp_readcap16(SCpnt, devip);
3643 else if (cmd[1] == SAI_GET_LBA_STATUS) { 3673 else if (cmd[1] == SAI_GET_LBA_STATUS) {
3644 3674
3645 if (scsi_debug_unmap_max_desc == 0) { 3675 if (scsi_debug_tpu == 0 && scsi_debug_tpws == 0) {
3646 mk_sense_buffer(devip, ILLEGAL_REQUEST, 3676 mk_sense_buffer(devip, ILLEGAL_REQUEST,
3647 INVALID_COMMAND_OPCODE, 0); 3677 INVALID_COMMAND_OPCODE, 0);
3648 errsts = check_condition_result; 3678 errsts = check_condition_result;
@@ -3753,8 +3783,16 @@ write:
3753 } 3783 }
3754 break; 3784 break;
3755 case WRITE_SAME_16: 3785 case WRITE_SAME_16:
3756 if (cmd[1] & 0x8) 3786 if (cmd[1] & 0x8) {
3757 unmap = 1; 3787 if (scsi_debug_tpws == 0) {
3788 mk_sense_buffer(devip, ILLEGAL_REQUEST,
3789 INVALID_FIELD_IN_CDB, 0);
3790 errsts = check_condition_result;
3791 } else
3792 unmap = 1;
3793 }
3794 if (errsts)
3795 break;
3758 /* fall through */ 3796 /* fall through */
3759 case WRITE_SAME: 3797 case WRITE_SAME:
3760 errsts = check_readiness(SCpnt, 0, devip); 3798 errsts = check_readiness(SCpnt, 0, devip);
@@ -3768,7 +3806,7 @@ write:
3768 if (errsts) 3806 if (errsts)
3769 break; 3807 break;
3770 3808
3771 if (scsi_debug_unmap_max_desc == 0) { 3809 if (scsi_debug_unmap_max_desc == 0 || scsi_debug_tpu == 0) {
3772 mk_sense_buffer(devip, ILLEGAL_REQUEST, 3810 mk_sense_buffer(devip, ILLEGAL_REQUEST,
3773 INVALID_COMMAND_OPCODE, 0); 3811 INVALID_COMMAND_OPCODE, 0);
3774 errsts = check_condition_result; 3812 errsts = check_condition_result;