diff options
author | Martin K. Petersen <martin.petersen@oracle.com> | 2008-06-05 00:12:59 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-07-12 09:22:24 -0400 |
commit | 597136ab70a6dccba5c40ee6eed88e881412429b (patch) | |
tree | 7f4967eee599d280437e7b5b679f18fb189c064c /drivers/scsi/scsi_debug.c | |
parent | 3f27e3ed11e67c5ee19d560a50eafd93cf8c6682 (diff) |
[SCSI] scsi_debug: Runtime-configurable sector size
Make scsi_debug sector size configurable at load time instead of being
a #define. Handy for testing 4KB sectors.
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Acked-by: Douglas Gilbert <dougg@torque.net>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/scsi_debug.c')
-rw-r--r-- | drivers/scsi/scsi_debug.c | 98 |
1 files changed, 59 insertions, 39 deletions
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index f6600bfb5bde..3901125455c9 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c | |||
@@ -94,6 +94,7 @@ static const char * scsi_debug_version_date = "20070104"; | |||
94 | #define DEF_VIRTUAL_GB 0 | 94 | #define DEF_VIRTUAL_GB 0 |
95 | #define DEF_FAKE_RW 0 | 95 | #define DEF_FAKE_RW 0 |
96 | #define DEF_VPD_USE_HOSTNO 1 | 96 | #define DEF_VPD_USE_HOSTNO 1 |
97 | #define DEF_SECTOR_SIZE 512 | ||
97 | 98 | ||
98 | /* bit mask values for scsi_debug_opts */ | 99 | /* bit mask values for scsi_debug_opts */ |
99 | #define SCSI_DEBUG_OPT_NOISE 1 | 100 | #define SCSI_DEBUG_OPT_NOISE 1 |
@@ -142,6 +143,7 @@ static int scsi_debug_no_lun_0 = DEF_NO_LUN_0; | |||
142 | static int scsi_debug_virtual_gb = DEF_VIRTUAL_GB; | 143 | static int scsi_debug_virtual_gb = DEF_VIRTUAL_GB; |
143 | static int scsi_debug_fake_rw = DEF_FAKE_RW; | 144 | static int scsi_debug_fake_rw = DEF_FAKE_RW; |
144 | static int scsi_debug_vpd_use_hostno = DEF_VPD_USE_HOSTNO; | 145 | static int scsi_debug_vpd_use_hostno = DEF_VPD_USE_HOSTNO; |
146 | static int scsi_debug_sector_size = DEF_SECTOR_SIZE; | ||
145 | 147 | ||
146 | static int scsi_debug_cmnd_count = 0; | 148 | static int scsi_debug_cmnd_count = 0; |
147 | 149 | ||
@@ -157,11 +159,6 @@ static int sdebug_heads; /* heads per disk */ | |||
157 | static int sdebug_cylinders_per; /* cylinders per surface */ | 159 | static int sdebug_cylinders_per; /* cylinders per surface */ |
158 | static int sdebug_sectors_per; /* sectors per cylinder */ | 160 | static int sdebug_sectors_per; /* sectors per cylinder */ |
159 | 161 | ||
160 | /* default sector size is 512 bytes, 2**9 bytes */ | ||
161 | #define POW2_SECT_SIZE 9 | ||
162 | #define SECT_SIZE (1 << POW2_SECT_SIZE) | ||
163 | #define SECT_SIZE_PER(TGT) SECT_SIZE | ||
164 | |||
165 | #define SDEBUG_MAX_PARTS 4 | 162 | #define SDEBUG_MAX_PARTS 4 |
166 | 163 | ||
167 | #define SDEBUG_SENSE_LEN 32 | 164 | #define SDEBUG_SENSE_LEN 32 |
@@ -878,8 +875,8 @@ static int resp_readcap(struct scsi_cmnd * scp, | |||
878 | arr[2] = 0xff; | 875 | arr[2] = 0xff; |
879 | arr[3] = 0xff; | 876 | arr[3] = 0xff; |
880 | } | 877 | } |
881 | arr[6] = (SECT_SIZE_PER(target) >> 8) & 0xff; | 878 | arr[6] = (scsi_debug_sector_size >> 8) & 0xff; |
882 | arr[7] = SECT_SIZE_PER(target) & 0xff; | 879 | arr[7] = scsi_debug_sector_size & 0xff; |
883 | return fill_from_dev_buffer(scp, arr, SDEBUG_READCAP_ARR_SZ); | 880 | return fill_from_dev_buffer(scp, arr, SDEBUG_READCAP_ARR_SZ); |
884 | } | 881 | } |
885 | 882 | ||
@@ -902,10 +899,10 @@ static int resp_readcap16(struct scsi_cmnd * scp, | |||
902 | capac = sdebug_capacity - 1; | 899 | capac = sdebug_capacity - 1; |
903 | for (k = 0; k < 8; ++k, capac >>= 8) | 900 | for (k = 0; k < 8; ++k, capac >>= 8) |
904 | arr[7 - k] = capac & 0xff; | 901 | arr[7 - k] = capac & 0xff; |
905 | arr[8] = (SECT_SIZE_PER(target) >> 24) & 0xff; | 902 | arr[8] = (scsi_debug_sector_size >> 24) & 0xff; |
906 | arr[9] = (SECT_SIZE_PER(target) >> 16) & 0xff; | 903 | arr[9] = (scsi_debug_sector_size >> 16) & 0xff; |
907 | arr[10] = (SECT_SIZE_PER(target) >> 8) & 0xff; | 904 | arr[10] = (scsi_debug_sector_size >> 8) & 0xff; |
908 | arr[11] = SECT_SIZE_PER(target) & 0xff; | 905 | arr[11] = scsi_debug_sector_size & 0xff; |
909 | return fill_from_dev_buffer(scp, arr, | 906 | return fill_from_dev_buffer(scp, arr, |
910 | min(alloc_len, SDEBUG_READCAP16_ARR_SZ)); | 907 | min(alloc_len, SDEBUG_READCAP16_ARR_SZ)); |
911 | } | 908 | } |
@@ -1019,20 +1016,20 @@ static int resp_disconnect_pg(unsigned char * p, int pcontrol, int target) | |||
1019 | 1016 | ||
1020 | static int resp_format_pg(unsigned char * p, int pcontrol, int target) | 1017 | static int resp_format_pg(unsigned char * p, int pcontrol, int target) |
1021 | { /* Format device page for mode_sense */ | 1018 | { /* Format device page for mode_sense */ |
1022 | unsigned char format_pg[] = {0x3, 0x16, 0, 0, 0, 0, 0, 0, | 1019 | unsigned char format_pg[] = {0x3, 0x16, 0, 0, 0, 0, 0, 0, |
1023 | 0, 0, 0, 0, 0, 0, 0, 0, | 1020 | 0, 0, 0, 0, 0, 0, 0, 0, |
1024 | 0, 0, 0, 0, 0x40, 0, 0, 0}; | 1021 | 0, 0, 0, 0, 0x40, 0, 0, 0}; |
1025 | 1022 | ||
1026 | memcpy(p, format_pg, sizeof(format_pg)); | 1023 | memcpy(p, format_pg, sizeof(format_pg)); |
1027 | p[10] = (sdebug_sectors_per >> 8) & 0xff; | 1024 | p[10] = (sdebug_sectors_per >> 8) & 0xff; |
1028 | p[11] = sdebug_sectors_per & 0xff; | 1025 | p[11] = sdebug_sectors_per & 0xff; |
1029 | p[12] = (SECT_SIZE >> 8) & 0xff; | 1026 | p[12] = (scsi_debug_sector_size >> 8) & 0xff; |
1030 | p[13] = SECT_SIZE & 0xff; | 1027 | p[13] = scsi_debug_sector_size & 0xff; |
1031 | if (DEV_REMOVEABLE(target)) | 1028 | if (DEV_REMOVEABLE(target)) |
1032 | p[20] |= 0x20; /* should agree with INQUIRY */ | 1029 | p[20] |= 0x20; /* should agree with INQUIRY */ |
1033 | if (1 == pcontrol) | 1030 | if (1 == pcontrol) |
1034 | memset(p + 2, 0, sizeof(format_pg) - 2); | 1031 | memset(p + 2, 0, sizeof(format_pg) - 2); |
1035 | return sizeof(format_pg); | 1032 | return sizeof(format_pg); |
1036 | } | 1033 | } |
1037 | 1034 | ||
1038 | static int resp_caching_pg(unsigned char * p, int pcontrol, int target) | 1035 | static int resp_caching_pg(unsigned char * p, int pcontrol, int target) |
@@ -1206,8 +1203,8 @@ static int resp_mode_sense(struct scsi_cmnd * scp, int target, | |||
1206 | ap[2] = (sdebug_capacity >> 8) & 0xff; | 1203 | ap[2] = (sdebug_capacity >> 8) & 0xff; |
1207 | ap[3] = sdebug_capacity & 0xff; | 1204 | ap[3] = sdebug_capacity & 0xff; |
1208 | } | 1205 | } |
1209 | ap[6] = (SECT_SIZE_PER(target) >> 8) & 0xff; | 1206 | ap[6] = (scsi_debug_sector_size >> 8) & 0xff; |
1210 | ap[7] = SECT_SIZE_PER(target) & 0xff; | 1207 | ap[7] = scsi_debug_sector_size & 0xff; |
1211 | offset += bd_len; | 1208 | offset += bd_len; |
1212 | ap = arr + offset; | 1209 | ap = arr + offset; |
1213 | } else if (16 == bd_len) { | 1210 | } else if (16 == bd_len) { |
@@ -1215,10 +1212,10 @@ static int resp_mode_sense(struct scsi_cmnd * scp, int target, | |||
1215 | 1212 | ||
1216 | for (k = 0; k < 8; ++k, capac >>= 8) | 1213 | for (k = 0; k < 8; ++k, capac >>= 8) |
1217 | ap[7 - k] = capac & 0xff; | 1214 | ap[7 - k] = capac & 0xff; |
1218 | ap[12] = (SECT_SIZE_PER(target) >> 24) & 0xff; | 1215 | ap[12] = (scsi_debug_sector_size >> 24) & 0xff; |
1219 | ap[13] = (SECT_SIZE_PER(target) >> 16) & 0xff; | 1216 | ap[13] = (scsi_debug_sector_size >> 16) & 0xff; |
1220 | ap[14] = (SECT_SIZE_PER(target) >> 8) & 0xff; | 1217 | ap[14] = (scsi_debug_sector_size >> 8) & 0xff; |
1221 | ap[15] = SECT_SIZE_PER(target) & 0xff; | 1218 | ap[15] = scsi_debug_sector_size & 0xff; |
1222 | offset += bd_len; | 1219 | offset += bd_len; |
1223 | ap = arr + offset; | 1220 | ap = arr + offset; |
1224 | } | 1221 | } |
@@ -1519,10 +1516,10 @@ static int do_device_access(struct scsi_cmnd *scmd, | |||
1519 | if (block + num > sdebug_store_sectors) | 1516 | if (block + num > sdebug_store_sectors) |
1520 | rest = block + num - sdebug_store_sectors; | 1517 | rest = block + num - sdebug_store_sectors; |
1521 | 1518 | ||
1522 | ret = func(scmd, fake_storep + (block * SECT_SIZE), | 1519 | ret = func(scmd, fake_storep + (block * scsi_debug_sector_size), |
1523 | (num - rest) * SECT_SIZE); | 1520 | (num - rest) * scsi_debug_sector_size); |
1524 | if (!ret && rest) | 1521 | if (!ret && rest) |
1525 | ret = func(scmd, fake_storep, rest * SECT_SIZE); | 1522 | ret = func(scmd, fake_storep, rest * scsi_debug_sector_size); |
1526 | 1523 | ||
1527 | return ret; | 1524 | return ret; |
1528 | } | 1525 | } |
@@ -1575,10 +1572,10 @@ static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba, | |||
1575 | write_unlock_irqrestore(&atomic_rw, iflags); | 1572 | write_unlock_irqrestore(&atomic_rw, iflags); |
1576 | if (-1 == ret) | 1573 | if (-1 == ret) |
1577 | return (DID_ERROR << 16); | 1574 | return (DID_ERROR << 16); |
1578 | else if ((ret < (num * SECT_SIZE)) && | 1575 | else if ((ret < (num * scsi_debug_sector_size)) && |
1579 | (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)) | 1576 | (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)) |
1580 | printk(KERN_INFO "scsi_debug: write: cdb indicated=%u, " | 1577 | printk(KERN_INFO "scsi_debug: write: cdb indicated=%u, " |
1581 | " IO sent=%d bytes\n", num * SECT_SIZE, ret); | 1578 | " IO sent=%d bytes\n", num * scsi_debug_sector_size, ret); |
1582 | return 0; | 1579 | return 0; |
1583 | } | 1580 | } |
1584 | 1581 | ||
@@ -2085,6 +2082,7 @@ module_param_named(scsi_level, scsi_debug_scsi_level, int, S_IRUGO); | |||
2085 | module_param_named(virtual_gb, scsi_debug_virtual_gb, int, S_IRUGO | S_IWUSR); | 2082 | module_param_named(virtual_gb, scsi_debug_virtual_gb, int, S_IRUGO | S_IWUSR); |
2086 | module_param_named(vpd_use_hostno, scsi_debug_vpd_use_hostno, int, | 2083 | module_param_named(vpd_use_hostno, scsi_debug_vpd_use_hostno, int, |
2087 | S_IRUGO | S_IWUSR); | 2084 | S_IRUGO | S_IWUSR); |
2085 | module_param_named(sector_size, scsi_debug_sector_size, int, S_IRUGO); | ||
2088 | 2086 | ||
2089 | MODULE_AUTHOR("Eric Youngdale + Douglas Gilbert"); | 2087 | MODULE_AUTHOR("Eric Youngdale + Douglas Gilbert"); |
2090 | MODULE_DESCRIPTION("SCSI debug adapter driver"); | 2088 | MODULE_DESCRIPTION("SCSI debug adapter driver"); |
@@ -2106,6 +2104,7 @@ MODULE_PARM_DESC(ptype, "SCSI peripheral type(def=0[disk])"); | |||
2106 | MODULE_PARM_DESC(scsi_level, "SCSI level to simulate(def=5[SPC-3])"); | 2104 | MODULE_PARM_DESC(scsi_level, "SCSI level to simulate(def=5[SPC-3])"); |
2107 | MODULE_PARM_DESC(virtual_gb, "virtual gigabyte size (def=0 -> use dev_size_mb)"); | 2105 | MODULE_PARM_DESC(virtual_gb, "virtual gigabyte size (def=0 -> use dev_size_mb)"); |
2108 | MODULE_PARM_DESC(vpd_use_hostno, "0 -> dev ids ignore hostno (def=1 -> unique dev ids)"); | 2106 | MODULE_PARM_DESC(vpd_use_hostno, "0 -> dev ids ignore hostno (def=1 -> unique dev ids)"); |
2107 | MODULE_PARM_DESC(sector_size, "hardware sector size in bytes (def=512)"); | ||
2109 | 2108 | ||
2110 | 2109 | ||
2111 | static char sdebug_info[256]; | 2110 | static char sdebug_info[256]; |
@@ -2158,8 +2157,9 @@ static int scsi_debug_proc_info(struct Scsi_Host *host, char *buffer, char **sta | |||
2158 | scsi_debug_dev_size_mb, scsi_debug_opts, scsi_debug_every_nth, | 2157 | scsi_debug_dev_size_mb, scsi_debug_opts, scsi_debug_every_nth, |
2159 | scsi_debug_cmnd_count, scsi_debug_delay, | 2158 | scsi_debug_cmnd_count, scsi_debug_delay, |
2160 | scsi_debug_max_luns, scsi_debug_scsi_level, | 2159 | scsi_debug_max_luns, scsi_debug_scsi_level, |
2161 | SECT_SIZE, sdebug_cylinders_per, sdebug_heads, sdebug_sectors_per, | 2160 | scsi_debug_sector_size, sdebug_cylinders_per, sdebug_heads, |
2162 | num_aborts, num_dev_resets, num_bus_resets, num_host_resets); | 2161 | sdebug_sectors_per, num_aborts, num_dev_resets, num_bus_resets, |
2162 | num_host_resets); | ||
2163 | if (pos < offset) { | 2163 | if (pos < offset) { |
2164 | len = 0; | 2164 | len = 0; |
2165 | begin = pos; | 2165 | begin = pos; |
@@ -2434,6 +2434,12 @@ static ssize_t sdebug_vpd_use_hostno_store(struct device_driver * ddp, | |||
2434 | DRIVER_ATTR(vpd_use_hostno, S_IRUGO | S_IWUSR, sdebug_vpd_use_hostno_show, | 2434 | DRIVER_ATTR(vpd_use_hostno, S_IRUGO | S_IWUSR, sdebug_vpd_use_hostno_show, |
2435 | sdebug_vpd_use_hostno_store); | 2435 | sdebug_vpd_use_hostno_store); |
2436 | 2436 | ||
2437 | static ssize_t sdebug_sector_size_show(struct device_driver * ddp, char * buf) | ||
2438 | { | ||
2439 | return scnprintf(buf, PAGE_SIZE, "%u\n", scsi_debug_sector_size); | ||
2440 | } | ||
2441 | DRIVER_ATTR(sector_size, S_IRUGO, sdebug_sector_size_show, NULL); | ||
2442 | |||
2437 | /* Note: The following function creates attribute files in the | 2443 | /* Note: The following function creates attribute files in the |
2438 | /sys/bus/pseudo/drivers/scsi_debug directory. The advantage of these | 2444 | /sys/bus/pseudo/drivers/scsi_debug directory. The advantage of these |
2439 | files (over those found in the /sys/module/scsi_debug/parameters | 2445 | files (over those found in the /sys/module/scsi_debug/parameters |
@@ -2459,11 +2465,13 @@ static int do_create_driverfs_files(void) | |||
2459 | ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_scsi_level); | 2465 | ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_scsi_level); |
2460 | ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_virtual_gb); | 2466 | ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_virtual_gb); |
2461 | ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_vpd_use_hostno); | 2467 | ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_vpd_use_hostno); |
2468 | ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_sector_size); | ||
2462 | return ret; | 2469 | return ret; |
2463 | } | 2470 | } |
2464 | 2471 | ||
2465 | static void do_remove_driverfs_files(void) | 2472 | static void do_remove_driverfs_files(void) |
2466 | { | 2473 | { |
2474 | driver_remove_file(&sdebug_driverfs_driver, &driver_attr_sector_size); | ||
2467 | driver_remove_file(&sdebug_driverfs_driver, &driver_attr_vpd_use_hostno); | 2475 | driver_remove_file(&sdebug_driverfs_driver, &driver_attr_vpd_use_hostno); |
2468 | driver_remove_file(&sdebug_driverfs_driver, &driver_attr_virtual_gb); | 2476 | driver_remove_file(&sdebug_driverfs_driver, &driver_attr_virtual_gb); |
2469 | driver_remove_file(&sdebug_driverfs_driver, &driver_attr_scsi_level); | 2477 | driver_remove_file(&sdebug_driverfs_driver, &driver_attr_scsi_level); |
@@ -2499,10 +2507,22 @@ static int __init scsi_debug_init(void) | |||
2499 | int k; | 2507 | int k; |
2500 | int ret; | 2508 | int ret; |
2501 | 2509 | ||
2510 | switch (scsi_debug_sector_size) { | ||
2511 | case 512: | ||
2512 | case 1024: | ||
2513 | case 2048: | ||
2514 | case 4096: | ||
2515 | break; | ||
2516 | default: | ||
2517 | printk(KERN_ERR "scsi_debug_init: invalid sector_size %u\n", | ||
2518 | scsi_debug_sector_size); | ||
2519 | return -EINVAL; | ||
2520 | } | ||
2521 | |||
2502 | if (scsi_debug_dev_size_mb < 1) | 2522 | if (scsi_debug_dev_size_mb < 1) |
2503 | scsi_debug_dev_size_mb = 1; /* force minimum 1 MB ramdisk */ | 2523 | scsi_debug_dev_size_mb = 1; /* force minimum 1 MB ramdisk */ |
2504 | sz = (unsigned long)scsi_debug_dev_size_mb * 1048576; | 2524 | sz = (unsigned long)scsi_debug_dev_size_mb * 1048576; |
2505 | sdebug_store_sectors = sz / SECT_SIZE; | 2525 | sdebug_store_sectors = sz / scsi_debug_sector_size; |
2506 | sdebug_capacity = get_sdebug_capacity(); | 2526 | sdebug_capacity = get_sdebug_capacity(); |
2507 | 2527 | ||
2508 | /* play around with geometry, don't waste too much on track 0 */ | 2528 | /* play around with geometry, don't waste too much on track 0 */ |