aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_debug.c
diff options
context:
space:
mode:
authorDouglas Gilbert <dougg@torque.net>2006-09-16 20:30:47 -0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-09-23 18:37:44 -0400
commit231839102b54512ced7d3ee7fc9b8bcf5e3b583b (patch)
tree0136daa29d7f67c17da2dc02780a6dadcd4fb615 /drivers/scsi/scsi_debug.c
parentc9802cd9574a80444e689c7525627b40d7dc3a06 (diff)
[SCSI] scsi_debug version 1.80
See http://www.torque.net/sg/sdebug26.html for more information on the scsi_debug driver. ChangeLog: - add 'vpd_use_hostno' parameter to allow simulated hosts to see the same set of targets (and luns). For testing multipath software. - add 'fake_rw' parameter to ignore the data in READ and WRITE commands - add support for log subpages (new in SPC-4) - yield appropriate block descriptor for MODE SENSE commands (only for pdt=0 (i.e. disks)) - REQUEST SENSE response no longer shows the stopped power condition (SAT changed to agree with SPC-3) Signed-off-by: Douglas Gilbert <dougg@torque.net> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/scsi_debug.c')
-rw-r--r--drivers/scsi/scsi_debug.c230
1 files changed, 189 insertions, 41 deletions
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index a80303c6b3fd..9c0f35820e3e 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -1,5 +1,4 @@
1/* 1/*
2 * linux/kernel/scsi_debug.c
3 * vvvvvvvvvvvvvvvvvvvvvvv Original vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv 2 * vvvvvvvvvvvvvvvvvvvvvvv Original vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
4 * Copyright (C) 1992 Eric Youngdale 3 * Copyright (C) 1992 Eric Youngdale
5 * Simulate a host adapter with 2 disks attached. Do a lot of checking 4 * Simulate a host adapter with 2 disks attached. Do a lot of checking
@@ -8,7 +7,9 @@
8 * ^^^^^^^^^^^^^^^^^^^^^^^ Original ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 7 * ^^^^^^^^^^^^^^^^^^^^^^^ Original ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
9 * 8 *
10 * This version is more generic, simulating a variable number of disk 9 * This version is more generic, simulating a variable number of disk
11 * (or disk like devices) sharing a common amount of RAM 10 * (or disk like devices) sharing a common amount of RAM. To be more
11 * realistic, the simulated devices have the transport attributes of
12 * SAS disks.
12 * 13 *
13 * 14 *
14 * For documentation see http://www.torque.net/sg/sdebug26.html 15 * For documentation see http://www.torque.net/sg/sdebug26.html
@@ -50,8 +51,8 @@
50#include "scsi_logging.h" 51#include "scsi_logging.h"
51#include "scsi_debug.h" 52#include "scsi_debug.h"
52 53
53#define SCSI_DEBUG_VERSION "1.79" 54#define SCSI_DEBUG_VERSION "1.80"
54static const char * scsi_debug_version_date = "20060604"; 55static const char * scsi_debug_version_date = "20060914";
55 56
56/* Additional Sense Code (ASC) used */ 57/* Additional Sense Code (ASC) used */
57#define NO_ADDITIONAL_SENSE 0x0 58#define NO_ADDITIONAL_SENSE 0x0
@@ -86,6 +87,8 @@ static const char * scsi_debug_version_date = "20060604";
86#define DEF_D_SENSE 0 87#define DEF_D_SENSE 0
87#define DEF_NO_LUN_0 0 88#define DEF_NO_LUN_0 0
88#define DEF_VIRTUAL_GB 0 89#define DEF_VIRTUAL_GB 0
90#define DEF_FAKE_RW 0
91#define DEF_VPD_USE_HOSTNO 1
89 92
90/* bit mask values for scsi_debug_opts */ 93/* bit mask values for scsi_debug_opts */
91#define SCSI_DEBUG_OPT_NOISE 1 94#define SCSI_DEBUG_OPT_NOISE 1
@@ -127,6 +130,8 @@ static int scsi_debug_ptype = DEF_PTYPE; /* SCSI peripheral type (0==disk) */
127static int scsi_debug_dsense = DEF_D_SENSE; 130static int scsi_debug_dsense = DEF_D_SENSE;
128static int scsi_debug_no_lun_0 = DEF_NO_LUN_0; 131static int scsi_debug_no_lun_0 = DEF_NO_LUN_0;
129static int scsi_debug_virtual_gb = DEF_VIRTUAL_GB; 132static int scsi_debug_virtual_gb = DEF_VIRTUAL_GB;
133static int scsi_debug_fake_rw = DEF_FAKE_RW;
134static int scsi_debug_vpd_use_hostno = DEF_VPD_USE_HOSTNO;
130 135
131static int scsi_debug_cmnd_count = 0; 136static int scsi_debug_cmnd_count = 0;
132 137
@@ -423,6 +428,8 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done)
423 case READ_6: 428 case READ_6:
424 if ((errsts = check_readiness(SCpnt, 0, devip))) 429 if ((errsts = check_readiness(SCpnt, 0, devip)))
425 break; 430 break;
431 if (scsi_debug_fake_rw)
432 break;
426 if ((*cmd) == READ_16) { 433 if ((*cmd) == READ_16) {
427 for (lba = 0, j = 0; j < 8; ++j) { 434 for (lba = 0, j = 0; j < 8; ++j) {
428 if (j > 0) 435 if (j > 0)
@@ -465,6 +472,8 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done)
465 case WRITE_6: 472 case WRITE_6:
466 if ((errsts = check_readiness(SCpnt, 0, devip))) 473 if ((errsts = check_readiness(SCpnt, 0, devip)))
467 break; 474 break;
475 if (scsi_debug_fake_rw)
476 break;
468 if ((*cmd) == WRITE_16) { 477 if ((*cmd) == WRITE_16) {
469 for (lba = 0, j = 0; j < 8; ++j) { 478 for (lba = 0, j = 0; j < 8; ++j) {
470 if (j > 0) 479 if (j > 0)
@@ -941,6 +950,8 @@ static int resp_inquiry(struct scsi_cmnd * scp, int target,
941 char lu_id_str[6]; 950 char lu_id_str[6];
942 int host_no = devip->sdbg_host->shost->host_no; 951 int host_no = devip->sdbg_host->shost->host_no;
943 952
953 if (0 == scsi_debug_vpd_use_hostno)
954 host_no = 0;
944 lu_id_num = devip->wlun ? -1 : (((host_no + 1) * 2000) + 955 lu_id_num = devip->wlun ? -1 : (((host_no + 1) * 2000) +
945 (devip->target * 1000) + devip->lun); 956 (devip->target * 1000) + devip->lun);
946 target_dev_id = ((host_no + 1) * 2000) + 957 target_dev_id = ((host_no + 1) * 2000) +
@@ -1059,19 +1070,6 @@ static int resp_requests(struct scsi_cmnd * scp,
1059 arr[12] = THRESHOLD_EXCEEDED; 1070 arr[12] = THRESHOLD_EXCEEDED;
1060 arr[13] = 0xff; /* TEST set and MRIE==6 */ 1071 arr[13] = 0xff; /* TEST set and MRIE==6 */
1061 } 1072 }
1062 } else if (devip->stopped) {
1063 if (want_dsense) {
1064 arr[0] = 0x72;
1065 arr[1] = 0x0; /* NO_SENSE in sense_key */
1066 arr[2] = LOW_POWER_COND_ON;
1067 arr[3] = 0x0; /* TEST set and MRIE==6 */
1068 } else {
1069 arr[0] = 0x70;
1070 arr[2] = 0x0; /* NO_SENSE in sense_key */
1071 arr[7] = 0xa; /* 18 byte sense buffer */
1072 arr[12] = LOW_POWER_COND_ON;
1073 arr[13] = 0x0; /* TEST set and MRIE==6 */
1074 }
1075 } else { 1073 } else {
1076 memcpy(arr, sbuff, SDEBUG_SENSE_LEN); 1074 memcpy(arr, sbuff, SDEBUG_SENSE_LEN);
1077 if ((cmd[1] & 1) && (! scsi_debug_dsense)) { 1075 if ((cmd[1] & 1) && (! scsi_debug_dsense)) {
@@ -1325,21 +1323,26 @@ static int resp_sas_sha_m_spg(unsigned char * p, int pcontrol)
1325static int resp_mode_sense(struct scsi_cmnd * scp, int target, 1323static int resp_mode_sense(struct scsi_cmnd * scp, int target,
1326 struct sdebug_dev_info * devip) 1324 struct sdebug_dev_info * devip)
1327{ 1325{
1328 unsigned char dbd; 1326 unsigned char dbd, llbaa;
1329 int pcontrol, pcode, subpcode; 1327 int pcontrol, pcode, subpcode, bd_len;
1330 unsigned char dev_spec; 1328 unsigned char dev_spec;
1331 int alloc_len, msense_6, offset, len, errsts, target_dev_id; 1329 int k, alloc_len, msense_6, offset, len, errsts, target_dev_id;
1332 unsigned char * ap; 1330 unsigned char * ap;
1333 unsigned char arr[SDEBUG_MAX_MSENSE_SZ]; 1331 unsigned char arr[SDEBUG_MAX_MSENSE_SZ];
1334 unsigned char *cmd = (unsigned char *)scp->cmnd; 1332 unsigned char *cmd = (unsigned char *)scp->cmnd;
1335 1333
1336 if ((errsts = check_readiness(scp, 1, devip))) 1334 if ((errsts = check_readiness(scp, 1, devip)))
1337 return errsts; 1335 return errsts;
1338 dbd = cmd[1] & 0x8; 1336 dbd = !!(cmd[1] & 0x8);
1339 pcontrol = (cmd[2] & 0xc0) >> 6; 1337 pcontrol = (cmd[2] & 0xc0) >> 6;
1340 pcode = cmd[2] & 0x3f; 1338 pcode = cmd[2] & 0x3f;
1341 subpcode = cmd[3]; 1339 subpcode = cmd[3];
1342 msense_6 = (MODE_SENSE == cmd[0]); 1340 msense_6 = (MODE_SENSE == cmd[0]);
1341 llbaa = msense_6 ? 0 : !!(cmd[1] & 0x10);
1342 if ((0 == scsi_debug_ptype) && (0 == dbd))
1343 bd_len = llbaa ? 16 : 8;
1344 else
1345 bd_len = 0;
1343 alloc_len = msense_6 ? cmd[4] : ((cmd[7] << 8) | cmd[8]); 1346 alloc_len = msense_6 ? cmd[4] : ((cmd[7] << 8) | cmd[8]);
1344 memset(arr, 0, SDEBUG_MAX_MSENSE_SZ); 1347 memset(arr, 0, SDEBUG_MAX_MSENSE_SZ);
1345 if (0x3 == pcontrol) { /* Saving values not supported */ 1348 if (0x3 == pcontrol) { /* Saving values not supported */
@@ -1349,15 +1352,58 @@ static int resp_mode_sense(struct scsi_cmnd * scp, int target,
1349 } 1352 }
1350 target_dev_id = ((devip->sdbg_host->shost->host_no + 1) * 2000) + 1353 target_dev_id = ((devip->sdbg_host->shost->host_no + 1) * 2000) +
1351 (devip->target * 1000) - 3; 1354 (devip->target * 1000) - 3;
1352 dev_spec = DEV_READONLY(target) ? 0x80 : 0x0; 1355 /* set DPOFUA bit for disks */
1356 if (0 == scsi_debug_ptype)
1357 dev_spec = (DEV_READONLY(target) ? 0x80 : 0x0) | 0x10;
1358 else
1359 dev_spec = 0x0;
1353 if (msense_6) { 1360 if (msense_6) {
1354 arr[2] = dev_spec; 1361 arr[2] = dev_spec;
1362 arr[3] = bd_len;
1355 offset = 4; 1363 offset = 4;
1356 } else { 1364 } else {
1357 arr[3] = dev_spec; 1365 arr[3] = dev_spec;
1366 if (16 == bd_len)
1367 arr[4] = 0x1; /* set LONGLBA bit */
1368 arr[7] = bd_len; /* assume 255 or less */
1358 offset = 8; 1369 offset = 8;
1359 } 1370 }
1360 ap = arr + offset; 1371 ap = arr + offset;
1372 if ((bd_len > 0) && (0 == sdebug_capacity)) {
1373 if (scsi_debug_virtual_gb > 0) {
1374 sdebug_capacity = 2048 * 1024;
1375 sdebug_capacity *= scsi_debug_virtual_gb;
1376 } else
1377 sdebug_capacity = sdebug_store_sectors;
1378 }
1379 if (8 == bd_len) {
1380 if (sdebug_capacity > 0xfffffffe) {
1381 ap[0] = 0xff;
1382 ap[1] = 0xff;
1383 ap[2] = 0xff;
1384 ap[3] = 0xff;
1385 } else {
1386 ap[0] = (sdebug_capacity >> 24) & 0xff;
1387 ap[1] = (sdebug_capacity >> 16) & 0xff;
1388 ap[2] = (sdebug_capacity >> 8) & 0xff;
1389 ap[3] = sdebug_capacity & 0xff;
1390 }
1391 ap[6] = (SECT_SIZE_PER(target) >> 8) & 0xff;
1392 ap[7] = SECT_SIZE_PER(target) & 0xff;
1393 offset += bd_len;
1394 ap = arr + offset;
1395 } else if (16 == bd_len) {
1396 unsigned long long capac = sdebug_capacity;
1397
1398 for (k = 0; k < 8; ++k, capac >>= 8)
1399 ap[7 - k] = capac & 0xff;
1400 ap[12] = (SECT_SIZE_PER(target) >> 24) & 0xff;
1401 ap[13] = (SECT_SIZE_PER(target) >> 16) & 0xff;
1402 ap[14] = (SECT_SIZE_PER(target) >> 8) & 0xff;
1403 ap[15] = SECT_SIZE_PER(target) & 0xff;
1404 offset += bd_len;
1405 ap = arr + offset;
1406 }
1361 1407
1362 if ((subpcode > 0x0) && (subpcode < 0xff) && (0x19 != pcode)) { 1408 if ((subpcode > 0x0) && (subpcode < 0xff) && (0x19 != pcode)) {
1363 /* TODO: Control Extension page */ 1409 /* TODO: Control Extension page */
@@ -1471,7 +1517,7 @@ static int resp_mode_select(struct scsi_cmnd * scp, int mselect6,
1471 " IO sent=%d bytes\n", param_len, res); 1517 " IO sent=%d bytes\n", param_len, res);
1472 md_len = mselect6 ? (arr[0] + 1) : ((arr[0] << 8) + arr[1] + 2); 1518 md_len = mselect6 ? (arr[0] + 1) : ((arr[0] << 8) + arr[1] + 2);
1473 bd_len = mselect6 ? arr[3] : ((arr[6] << 8) + arr[7]); 1519 bd_len = mselect6 ? arr[3] : ((arr[6] << 8) + arr[7]);
1474 if ((md_len > 2) || (0 != bd_len)) { 1520 if (md_len > 2) {
1475 mk_sense_buffer(devip, ILLEGAL_REQUEST, 1521 mk_sense_buffer(devip, ILLEGAL_REQUEST,
1476 INVALID_FIELD_IN_PARAM_LIST, 0); 1522 INVALID_FIELD_IN_PARAM_LIST, 0);
1477 return check_condition_result; 1523 return check_condition_result;
@@ -1544,7 +1590,7 @@ static int resp_ie_l_pg(unsigned char * arr)
1544static int resp_log_sense(struct scsi_cmnd * scp, 1590static int resp_log_sense(struct scsi_cmnd * scp,
1545 struct sdebug_dev_info * devip) 1591 struct sdebug_dev_info * devip)
1546{ 1592{
1547 int ppc, sp, pcontrol, pcode, alloc_len, errsts, len, n; 1593 int ppc, sp, pcontrol, pcode, subpcode, alloc_len, errsts, len, n;
1548 unsigned char arr[SDEBUG_MAX_LSENSE_SZ]; 1594 unsigned char arr[SDEBUG_MAX_LSENSE_SZ];
1549 unsigned char *cmd = (unsigned char *)scp->cmnd; 1595 unsigned char *cmd = (unsigned char *)scp->cmnd;
1550 1596
@@ -1560,23 +1606,63 @@ static int resp_log_sense(struct scsi_cmnd * scp,
1560 } 1606 }
1561 pcontrol = (cmd[2] & 0xc0) >> 6; 1607 pcontrol = (cmd[2] & 0xc0) >> 6;
1562 pcode = cmd[2] & 0x3f; 1608 pcode = cmd[2] & 0x3f;
1609 subpcode = cmd[3] & 0xff;
1563 alloc_len = (cmd[7] << 8) + cmd[8]; 1610 alloc_len = (cmd[7] << 8) + cmd[8];
1564 arr[0] = pcode; 1611 arr[0] = pcode;
1565 switch (pcode) { 1612 if (0 == subpcode) {
1566 case 0x0: /* Supported log pages log page */ 1613 switch (pcode) {
1567 n = 4; 1614 case 0x0: /* Supported log pages log page */
1568 arr[n++] = 0x0; /* this page */ 1615 n = 4;
1569 arr[n++] = 0xd; /* Temperature */ 1616 arr[n++] = 0x0; /* this page */
1570 arr[n++] = 0x2f; /* Informational exceptions */ 1617 arr[n++] = 0xd; /* Temperature */
1571 arr[3] = n - 4; 1618 arr[n++] = 0x2f; /* Informational exceptions */
1572 break; 1619 arr[3] = n - 4;
1573 case 0xd: /* Temperature log page */ 1620 break;
1574 arr[3] = resp_temp_l_pg(arr + 4); 1621 case 0xd: /* Temperature log page */
1575 break; 1622 arr[3] = resp_temp_l_pg(arr + 4);
1576 case 0x2f: /* Informational exceptions log page */ 1623 break;
1577 arr[3] = resp_ie_l_pg(arr + 4); 1624 case 0x2f: /* Informational exceptions log page */
1578 break; 1625 arr[3] = resp_ie_l_pg(arr + 4);
1579 default: 1626 break;
1627 default:
1628 mk_sense_buffer(devip, ILLEGAL_REQUEST,
1629 INVALID_FIELD_IN_CDB, 0);
1630 return check_condition_result;
1631 }
1632 } else if (0xff == subpcode) {
1633 arr[0] |= 0x40;
1634 arr[1] = subpcode;
1635 switch (pcode) {
1636 case 0x0: /* Supported log pages and subpages log page */
1637 n = 4;
1638 arr[n++] = 0x0;
1639 arr[n++] = 0x0; /* 0,0 page */
1640 arr[n++] = 0x0;
1641 arr[n++] = 0xff; /* this page */
1642 arr[n++] = 0xd;
1643 arr[n++] = 0x0; /* Temperature */
1644 arr[n++] = 0x2f;
1645 arr[n++] = 0x0; /* Informational exceptions */
1646 arr[3] = n - 4;
1647 break;
1648 case 0xd: /* Temperature subpages */
1649 n = 4;
1650 arr[n++] = 0xd;
1651 arr[n++] = 0x0; /* Temperature */
1652 arr[3] = n - 4;
1653 break;
1654 case 0x2f: /* Informational exceptions subpages */
1655 n = 4;
1656 arr[n++] = 0x2f;
1657 arr[n++] = 0x0; /* Informational exceptions */
1658 arr[3] = n - 4;
1659 break;
1660 default:
1661 mk_sense_buffer(devip, ILLEGAL_REQUEST,
1662 INVALID_FIELD_IN_CDB, 0);
1663 return check_condition_result;
1664 }
1665 } else {
1580 mk_sense_buffer(devip, ILLEGAL_REQUEST, 1666 mk_sense_buffer(devip, ILLEGAL_REQUEST,
1581 INVALID_FIELD_IN_CDB, 0); 1667 INVALID_FIELD_IN_CDB, 0);
1582 return check_condition_result; 1668 return check_condition_result;
@@ -2151,11 +2237,18 @@ static int schedule_resp(struct scsi_cmnd * cmnd,
2151 } 2237 }
2152} 2238}
2153 2239
2240/* Note: The following macros create attribute files in the
2241 /sys/module/scsi_debug/parameters directory. Unfortunately this
2242 driver is unaware of a change and cannot trigger auxiliary actions
2243 as it can when the corresponding attribute in the
2244 /sys/bus/pseudo/drivers/scsi_debug directory is changed.
2245 */
2154module_param_named(add_host, scsi_debug_add_host, int, S_IRUGO | S_IWUSR); 2246module_param_named(add_host, scsi_debug_add_host, int, S_IRUGO | S_IWUSR);
2155module_param_named(delay, scsi_debug_delay, int, S_IRUGO | S_IWUSR); 2247module_param_named(delay, scsi_debug_delay, int, S_IRUGO | S_IWUSR);
2156module_param_named(dev_size_mb, scsi_debug_dev_size_mb, int, S_IRUGO); 2248module_param_named(dev_size_mb, scsi_debug_dev_size_mb, int, S_IRUGO);
2157module_param_named(dsense, scsi_debug_dsense, int, S_IRUGO | S_IWUSR); 2249module_param_named(dsense, scsi_debug_dsense, int, S_IRUGO | S_IWUSR);
2158module_param_named(every_nth, scsi_debug_every_nth, int, S_IRUGO | S_IWUSR); 2250module_param_named(every_nth, scsi_debug_every_nth, int, S_IRUGO | S_IWUSR);
2251module_param_named(fake_rw, scsi_debug_fake_rw, int, S_IRUGO | S_IWUSR);
2159module_param_named(max_luns, scsi_debug_max_luns, int, S_IRUGO | S_IWUSR); 2252module_param_named(max_luns, scsi_debug_max_luns, int, S_IRUGO | S_IWUSR);
2160module_param_named(no_lun_0, scsi_debug_no_lun_0, int, S_IRUGO | S_IWUSR); 2253module_param_named(no_lun_0, scsi_debug_no_lun_0, int, S_IRUGO | S_IWUSR);
2161module_param_named(num_parts, scsi_debug_num_parts, int, S_IRUGO); 2254module_param_named(num_parts, scsi_debug_num_parts, int, S_IRUGO);
@@ -2164,6 +2257,8 @@ module_param_named(opts, scsi_debug_opts, int, S_IRUGO | S_IWUSR);
2164module_param_named(ptype, scsi_debug_ptype, int, S_IRUGO | S_IWUSR); 2257module_param_named(ptype, scsi_debug_ptype, int, S_IRUGO | S_IWUSR);
2165module_param_named(scsi_level, scsi_debug_scsi_level, int, S_IRUGO); 2258module_param_named(scsi_level, scsi_debug_scsi_level, int, S_IRUGO);
2166module_param_named(virtual_gb, scsi_debug_virtual_gb, int, S_IRUGO | S_IWUSR); 2259module_param_named(virtual_gb, scsi_debug_virtual_gb, int, S_IRUGO | S_IWUSR);
2260module_param_named(vpd_use_hostno, scsi_debug_vpd_use_hostno, int,
2261 S_IRUGO | S_IWUSR);
2167 2262
2168MODULE_AUTHOR("Eric Youngdale + Douglas Gilbert"); 2263MODULE_AUTHOR("Eric Youngdale + Douglas Gilbert");
2169MODULE_DESCRIPTION("SCSI debug adapter driver"); 2264MODULE_DESCRIPTION("SCSI debug adapter driver");
@@ -2175,6 +2270,7 @@ MODULE_PARM_DESC(delay, "# of jiffies to delay response(def=1)");
2175MODULE_PARM_DESC(dev_size_mb, "size in MB of ram shared by devs(def=8)"); 2270MODULE_PARM_DESC(dev_size_mb, "size in MB of ram shared by devs(def=8)");
2176MODULE_PARM_DESC(dsense, "use descriptor sense format(def=0 -> fixed)"); 2271MODULE_PARM_DESC(dsense, "use descriptor sense format(def=0 -> fixed)");
2177MODULE_PARM_DESC(every_nth, "timeout every nth command(def=100)"); 2272MODULE_PARM_DESC(every_nth, "timeout every nth command(def=100)");
2273MODULE_PARM_DESC(fake_rw, "fake reads/writes instead of copying (def=0)");
2178MODULE_PARM_DESC(max_luns, "number of LUNs per target to simulate(def=1)"); 2274MODULE_PARM_DESC(max_luns, "number of LUNs per target to simulate(def=1)");
2179MODULE_PARM_DESC(no_lun_0, "no LU number 0 (def=0 -> have lun 0)"); 2275MODULE_PARM_DESC(no_lun_0, "no LU number 0 (def=0 -> have lun 0)");
2180MODULE_PARM_DESC(num_parts, "number of partitions(def=0)"); 2276MODULE_PARM_DESC(num_parts, "number of partitions(def=0)");
@@ -2183,6 +2279,7 @@ MODULE_PARM_DESC(opts, "1->noise, 2->medium_error, 4->... (def=0)");
2183MODULE_PARM_DESC(ptype, "SCSI peripheral type(def=0[disk])"); 2279MODULE_PARM_DESC(ptype, "SCSI peripheral type(def=0[disk])");
2184MODULE_PARM_DESC(scsi_level, "SCSI level to simulate(def=5[SPC-3])"); 2280MODULE_PARM_DESC(scsi_level, "SCSI level to simulate(def=5[SPC-3])");
2185MODULE_PARM_DESC(virtual_gb, "virtual gigabyte size (def=0 -> use dev_size_mb)"); 2281MODULE_PARM_DESC(virtual_gb, "virtual gigabyte size (def=0 -> use dev_size_mb)");
2282MODULE_PARM_DESC(vpd_use_hostno, "0 -> dev ids ignore hostno (def=1 -> unique dev ids)");
2186 2283
2187 2284
2188static char sdebug_info[256]; 2285static char sdebug_info[256];
@@ -2334,6 +2431,24 @@ static ssize_t sdebug_dsense_store(struct device_driver * ddp,
2334DRIVER_ATTR(dsense, S_IRUGO | S_IWUSR, sdebug_dsense_show, 2431DRIVER_ATTR(dsense, S_IRUGO | S_IWUSR, sdebug_dsense_show,
2335 sdebug_dsense_store); 2432 sdebug_dsense_store);
2336 2433
2434static ssize_t sdebug_fake_rw_show(struct device_driver * ddp, char * buf)
2435{
2436 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_fake_rw);
2437}
2438static ssize_t sdebug_fake_rw_store(struct device_driver * ddp,
2439 const char * buf, size_t count)
2440{
2441 int n;
2442
2443 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
2444 scsi_debug_fake_rw = n;
2445 return count;
2446 }
2447 return -EINVAL;
2448}
2449DRIVER_ATTR(fake_rw, S_IRUGO | S_IWUSR, sdebug_fake_rw_show,
2450 sdebug_fake_rw_store);
2451
2337static ssize_t sdebug_no_lun_0_show(struct device_driver * ddp, char * buf) 2452static ssize_t sdebug_no_lun_0_show(struct device_driver * ddp, char * buf)
2338{ 2453{
2339 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_no_lun_0); 2454 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_no_lun_0);
@@ -2487,6 +2602,31 @@ static ssize_t sdebug_add_host_store(struct device_driver * ddp,
2487DRIVER_ATTR(add_host, S_IRUGO | S_IWUSR, sdebug_add_host_show, 2602DRIVER_ATTR(add_host, S_IRUGO | S_IWUSR, sdebug_add_host_show,
2488 sdebug_add_host_store); 2603 sdebug_add_host_store);
2489 2604
2605static ssize_t sdebug_vpd_use_hostno_show(struct device_driver * ddp,
2606 char * buf)
2607{
2608 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_vpd_use_hostno);
2609}
2610static ssize_t sdebug_vpd_use_hostno_store(struct device_driver * ddp,
2611 const char * buf, size_t count)
2612{
2613 int n;
2614
2615 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
2616 scsi_debug_vpd_use_hostno = n;
2617 return count;
2618 }
2619 return -EINVAL;
2620}
2621DRIVER_ATTR(vpd_use_hostno, S_IRUGO | S_IWUSR, sdebug_vpd_use_hostno_show,
2622 sdebug_vpd_use_hostno_store);
2623
2624/* Note: The following function creates attribute files in the
2625 /sys/bus/pseudo/drivers/scsi_debug directory. The advantage of these
2626 files (over those found in the /sys/module/scsi_debug/parameters
2627 directory) is that auxiliary actions can be triggered when an attribute
2628 is changed. For example see: sdebug_add_host_store() above.
2629 */
2490static int do_create_driverfs_files(void) 2630static int do_create_driverfs_files(void)
2491{ 2631{
2492 int ret; 2632 int ret;
@@ -2496,23 +2636,31 @@ static int do_create_driverfs_files(void)
2496 ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_dev_size_mb); 2636 ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_dev_size_mb);
2497 ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_dsense); 2637 ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_dsense);
2498 ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_every_nth); 2638 ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_every_nth);
2639 ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_fake_rw);
2499 ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_max_luns); 2640 ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_max_luns);
2500 ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_num_tgts); 2641 ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_no_lun_0);
2501 ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_num_parts); 2642 ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_num_parts);
2643 ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_num_tgts);
2502 ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_ptype); 2644 ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_ptype);
2503 ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_opts); 2645 ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_opts);
2504 ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_scsi_level); 2646 ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_scsi_level);
2647 ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_virtual_gb);
2648 ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_vpd_use_hostno);
2505 return ret; 2649 return ret;
2506} 2650}
2507 2651
2508static void do_remove_driverfs_files(void) 2652static void do_remove_driverfs_files(void)
2509{ 2653{
2654 driver_remove_file(&sdebug_driverfs_driver, &driver_attr_vpd_use_hostno);
2655 driver_remove_file(&sdebug_driverfs_driver, &driver_attr_virtual_gb);
2510 driver_remove_file(&sdebug_driverfs_driver, &driver_attr_scsi_level); 2656 driver_remove_file(&sdebug_driverfs_driver, &driver_attr_scsi_level);
2511 driver_remove_file(&sdebug_driverfs_driver, &driver_attr_opts); 2657 driver_remove_file(&sdebug_driverfs_driver, &driver_attr_opts);
2512 driver_remove_file(&sdebug_driverfs_driver, &driver_attr_ptype); 2658 driver_remove_file(&sdebug_driverfs_driver, &driver_attr_ptype);
2513 driver_remove_file(&sdebug_driverfs_driver, &driver_attr_num_parts);
2514 driver_remove_file(&sdebug_driverfs_driver, &driver_attr_num_tgts); 2659 driver_remove_file(&sdebug_driverfs_driver, &driver_attr_num_tgts);
2660 driver_remove_file(&sdebug_driverfs_driver, &driver_attr_num_parts);
2661 driver_remove_file(&sdebug_driverfs_driver, &driver_attr_no_lun_0);
2515 driver_remove_file(&sdebug_driverfs_driver, &driver_attr_max_luns); 2662 driver_remove_file(&sdebug_driverfs_driver, &driver_attr_max_luns);
2663 driver_remove_file(&sdebug_driverfs_driver, &driver_attr_fake_rw);
2516 driver_remove_file(&sdebug_driverfs_driver, &driver_attr_every_nth); 2664 driver_remove_file(&sdebug_driverfs_driver, &driver_attr_every_nth);
2517 driver_remove_file(&sdebug_driverfs_driver, &driver_attr_dsense); 2665 driver_remove_file(&sdebug_driverfs_driver, &driver_attr_dsense);
2518 driver_remove_file(&sdebug_driverfs_driver, &driver_attr_dev_size_mb); 2666 driver_remove_file(&sdebug_driverfs_driver, &driver_attr_dev_size_mb);