aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin K. Petersen <martin.petersen@oracle.com>2008-06-05 00:12:59 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-07-12 09:22:24 -0400
commit597136ab70a6dccba5c40ee6eed88e881412429b (patch)
tree7f4967eee599d280437e7b5b679f18fb189c064c
parent3f27e3ed11e67c5ee19d560a50eafd93cf8c6682 (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>
-rw-r--r--drivers/scsi/scsi_debug.c98
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;
142static int scsi_debug_virtual_gb = DEF_VIRTUAL_GB; 143static int scsi_debug_virtual_gb = DEF_VIRTUAL_GB;
143static int scsi_debug_fake_rw = DEF_FAKE_RW; 144static int scsi_debug_fake_rw = DEF_FAKE_RW;
144static int scsi_debug_vpd_use_hostno = DEF_VPD_USE_HOSTNO; 145static int scsi_debug_vpd_use_hostno = DEF_VPD_USE_HOSTNO;
146static int scsi_debug_sector_size = DEF_SECTOR_SIZE;
145 147
146static int scsi_debug_cmnd_count = 0; 148static int scsi_debug_cmnd_count = 0;
147 149
@@ -157,11 +159,6 @@ static int sdebug_heads; /* heads per disk */
157static int sdebug_cylinders_per; /* cylinders per surface */ 159static int sdebug_cylinders_per; /* cylinders per surface */
158static int sdebug_sectors_per; /* sectors per cylinder */ 160static 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
1020static int resp_format_pg(unsigned char * p, int pcontrol, int target) 1017static 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
1038static int resp_caching_pg(unsigned char * p, int pcontrol, int target) 1035static 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);
2085module_param_named(virtual_gb, scsi_debug_virtual_gb, int, S_IRUGO | S_IWUSR); 2082module_param_named(virtual_gb, scsi_debug_virtual_gb, int, S_IRUGO | S_IWUSR);
2086module_param_named(vpd_use_hostno, scsi_debug_vpd_use_hostno, int, 2083module_param_named(vpd_use_hostno, scsi_debug_vpd_use_hostno, int,
2087 S_IRUGO | S_IWUSR); 2084 S_IRUGO | S_IWUSR);
2085module_param_named(sector_size, scsi_debug_sector_size, int, S_IRUGO);
2088 2086
2089MODULE_AUTHOR("Eric Youngdale + Douglas Gilbert"); 2087MODULE_AUTHOR("Eric Youngdale + Douglas Gilbert");
2090MODULE_DESCRIPTION("SCSI debug adapter driver"); 2088MODULE_DESCRIPTION("SCSI debug adapter driver");
@@ -2106,6 +2104,7 @@ MODULE_PARM_DESC(ptype, "SCSI peripheral type(def=0[disk])");
2106MODULE_PARM_DESC(scsi_level, "SCSI level to simulate(def=5[SPC-3])"); 2104MODULE_PARM_DESC(scsi_level, "SCSI level to simulate(def=5[SPC-3])");
2107MODULE_PARM_DESC(virtual_gb, "virtual gigabyte size (def=0 -> use dev_size_mb)"); 2105MODULE_PARM_DESC(virtual_gb, "virtual gigabyte size (def=0 -> use dev_size_mb)");
2108MODULE_PARM_DESC(vpd_use_hostno, "0 -> dev ids ignore hostno (def=1 -> unique dev ids)"); 2106MODULE_PARM_DESC(vpd_use_hostno, "0 -> dev ids ignore hostno (def=1 -> unique dev ids)");
2107MODULE_PARM_DESC(sector_size, "hardware sector size in bytes (def=512)");
2109 2108
2110 2109
2111static char sdebug_info[256]; 2110static 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,
2434DRIVER_ATTR(vpd_use_hostno, S_IRUGO | S_IWUSR, sdebug_vpd_use_hostno_show, 2434DRIVER_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
2437static 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}
2441DRIVER_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
2465static void do_remove_driverfs_files(void) 2472static 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 */