Commit ec61600c authored by Douglas Gilbert's avatar Douglas Gilbert Committed by James Bottomley

scsi_debug version 1.69 for lk 2.5.66

As people are using scsi_debug to simulate a large
number of disks to play with the dev_t expansion,
some problems have come to light.

Changelog:
   - change num_devs to num_tgts
       so now the user can independently modify the
       number of hosts (add_host), the number of targets
       per host (num_tgts) and the number of luns per
       target (max_luns)
   - num_tgts sets scsi_host::max_id after allowance is
     made for the initiator's target id
   - max_luns default changed to 1 and it is sysfs
     writeable
   - REPORT LUN response cleaned up. Could now possibly
     generate a response indicatimg there were up to
     16,384 logical units available
   - clean up sense buffer generation

Updated http://www.torque.net/sg/sdebug25.html
parent ed36188d
...@@ -20,8 +20,8 @@ ...@@ -20,8 +20,8 @@
* add timers for delayed responses [20020721] * add timers for delayed responses [20020721]
* Patrick Mansfield <patmans@us.ibm.com> max_luns+scsi_level [20021031] * Patrick Mansfield <patmans@us.ibm.com> max_luns+scsi_level [20021031]
* Mike Anderson <andmike@us.ibm.com> sysfs work [20021118] * Mike Anderson <andmike@us.ibm.com> sysfs work [20021118]
* dpg: change style of boot options to "scsi_debug.num_devs=2" and * dpg: change style of boot options to "scsi_debug.num_tgts=2" and
* module options to "modprobe scsi_debug num_devs=2" [20021221] * module options to "modprobe scsi_debug num_tgts=2" [20021221]
*/ */
#include <linux/config.h> #include <linux/config.h>
...@@ -54,18 +54,31 @@ ...@@ -54,18 +54,31 @@
#include "scsi_debug.h" #include "scsi_debug.h"
static const char * scsi_debug_version_str = "Version: 1.68 (20030314)"; static const char * scsi_debug_version_str = "Version: 1.69 (20030329)";
/* Additional Sense Code (ASC) used */
#define NO_ADDED_SENSE 0x0
#define UNRECOVERED_READ_ERR 0x11
#define INVALID_OPCODE 0x20
#define ADDR_OUT_OF_RANGE 0x21
#define INVALID_FIELD_IN_CDB 0x24
#define POWERON_RESET 0x29
#define SAVING_PARAMS_UNSUP 0x39
#define THRESHHOLD_EXCEEDED 0x5d
#define SDEBUG_TAGGED_QUEUING 0 /* 0 | MSG_SIMPLE_TAG | MSG_ORDERED_TAG */ #define SDEBUG_TAGGED_QUEUING 0 /* 0 | MSG_SIMPLE_TAG | MSG_ORDERED_TAG */
/* Default values for driver parameters */ /* Default values for driver parameters */
#define DEF_NUM_DEVS 1 #define DEF_NUM_HOST 1
#define DEF_NUM_TGTS 1
#define DEF_MAX_LUNS 1
/* With these defaults, this driver will make 1 host with 1 target
* (id 0) containing 1 logical unit (lun 0). That is 1 device.
*/
#define DEF_DEV_SIZE_MB 8 #define DEF_DEV_SIZE_MB 8
#define DEF_EVERY_NTH 0 #define DEF_EVERY_NTH 0
#define DEF_DELAY 1 #define DEF_DELAY 1
#define DEF_MAX_LUNS 2
#define DEF_SCSI_LEVEL 3 #define DEF_SCSI_LEVEL 3
#define DEF_NUM_HOST 1
#define DEF_OPTS 0 #define DEF_OPTS 0
/* bit mask values for scsi_debug_opts */ /* bit mask values for scsi_debug_opts */
...@@ -83,8 +96,12 @@ static const char * scsi_debug_version_str = "Version: 1.68 (20030314)"; ...@@ -83,8 +96,12 @@ static const char * scsi_debug_version_str = "Version: 1.68 (20030314)";
* sector on read commands: */ * sector on read commands: */
#define OPT_MEDIUM_ERR_ADDR 0x1234 /* that's sector 4660 in decimal */ #define OPT_MEDIUM_ERR_ADDR 0x1234 /* that's sector 4660 in decimal */
/* If REPORT LUNS has luns >= 256 it can choose "flat space" (value 1)
* or "peripheral device" addressing (value 0) */
#define SAM2_LUN_ADDRESS_METHOD 0
static int scsi_debug_dev_size_mb = DEF_DEV_SIZE_MB; static int scsi_debug_dev_size_mb = DEF_DEV_SIZE_MB;
static int scsi_debug_num_devs = DEF_NUM_DEVS; /* max devs per host */ static int scsi_debug_num_tgts = DEF_NUM_TGTS; /* targets per host */
static int scsi_debug_opts = DEF_OPTS; static int scsi_debug_opts = DEF_OPTS;
static int scsi_debug_every_nth = DEF_EVERY_NTH; static int scsi_debug_every_nth = DEF_EVERY_NTH;
static int scsi_debug_cmnd_count = 0; static int scsi_debug_cmnd_count = 0;
...@@ -303,7 +320,7 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done) ...@@ -303,7 +320,7 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done)
sbuff = devip->sense_buff; sbuff = devip->sense_buff;
memcpy(buff, sbuff, (bufflen < SDEBUG_SENSE_LEN) ? memcpy(buff, sbuff, (bufflen < SDEBUG_SENSE_LEN) ?
bufflen : SDEBUG_SENSE_LEN); bufflen : SDEBUG_SENSE_LEN);
mk_sense_buffer(devip, 0, 0x0, 0, 7); mk_sense_buffer(devip, 0, NO_ADDED_SENSE, 0, 7);
} else { } else {
memset(buff, 0, bufflen); memset(buff, 0, bufflen);
buff[0] = 0x70; buff[0] = 0x70;
...@@ -384,7 +401,8 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done) ...@@ -384,7 +401,8 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done)
} }
errsts = resp_read(SCpnt, upper_blk, block, num, devip); errsts = resp_read(SCpnt, upper_blk, block, num, devip);
if (inj_recovered && (0 == errsts)) { if (inj_recovered && (0 == errsts)) {
mk_sense_buffer(devip, RECOVERED_ERROR, 0x5d, 0, 14); mk_sense_buffer(devip, RECOVERED_ERROR,
THRESHHOLD_EXCEEDED, 0, 18);
errsts = check_condition_result; errsts = check_condition_result;
} }
break; break;
...@@ -421,7 +439,8 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done) ...@@ -421,7 +439,8 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done)
} }
errsts = resp_write(SCpnt, upper_blk, block, num, devip); errsts = resp_write(SCpnt, upper_blk, block, num, devip);
if (inj_recovered && (0 == errsts)) { if (inj_recovered && (0 == errsts)) {
mk_sense_buffer(devip, RECOVERED_ERROR, 0x5d, 0, 14); mk_sense_buffer(devip, RECOVERED_ERROR,
THRESHHOLD_EXCEEDED, 0, 18);
errsts = check_condition_result; errsts = check_condition_result;
} }
break; break;
...@@ -435,7 +454,7 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done) ...@@ -435,7 +454,7 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done)
default: default:
if ((errsts = check_reset(SCpnt, devip))) if ((errsts = check_reset(SCpnt, devip)))
break; break;
mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x20, 0, 14); mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_OPCODE, 0, 18);
errsts = check_condition_result; errsts = check_condition_result;
break; break;
} }
...@@ -455,7 +474,7 @@ static int check_reset(struct scsi_cmnd * SCpnt, struct sdebug_dev_info * devip) ...@@ -455,7 +474,7 @@ static int check_reset(struct scsi_cmnd * SCpnt, struct sdebug_dev_info * devip)
{ {
if (devip->reset) { if (devip->reset) {
devip->reset = 0; devip->reset = 0;
mk_sense_buffer(devip, UNIT_ATTENTION, 0x29, 0, 14); mk_sense_buffer(devip, UNIT_ATTENTION, POWERON_RESET, 0, 18);
return check_condition_result; return check_condition_result;
} }
return 0; return 0;
...@@ -516,7 +535,8 @@ static int resp_inquiry(unsigned char * cmd, int target, unsigned char * buff, ...@@ -516,7 +535,8 @@ static int resp_inquiry(unsigned char * cmd, int target, unsigned char * buff,
pq_pdt = PERIPH_DEVICE_TYPE(target); pq_pdt = PERIPH_DEVICE_TYPE(target);
arr[0] = pq_pdt; arr[0] = pq_pdt;
if (0x2 & cmd[1]) { /* CMDDT bit set */ if (0x2 & cmd[1]) { /* CMDDT bit set */
mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x24, 0, 14); mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
0, 18);
return check_condition_result; return check_condition_result;
} else if (0x1 & cmd[1]) { /* EVPD bit set */ } else if (0x1 & cmd[1]) { /* EVPD bit set */
int dev_id_num, len; int dev_id_num, len;
...@@ -541,7 +561,8 @@ static int resp_inquiry(unsigned char * cmd, int target, unsigned char * buff, ...@@ -541,7 +561,8 @@ static int resp_inquiry(unsigned char * cmd, int target, unsigned char * buff,
dev_id_str, len); dev_id_str, len);
} else { } else {
/* Illegal request, invalid field in cdb */ /* Illegal request, invalid field in cdb */
mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x24, 0, 14); mk_sense_buffer(devip, ILLEGAL_REQUEST,
INVALID_FIELD_IN_CDB, 0, 18);
return check_condition_result; return check_condition_result;
} }
memcpy(buff, arr, min_len); memcpy(buff, arr, min_len);
...@@ -654,7 +675,8 @@ static int resp_mode_sense(unsigned char * cmd, int target, ...@@ -654,7 +675,8 @@ static int resp_mode_sense(unsigned char * cmd, int target,
memset(buff, 0, bufflen); memset(buff, 0, bufflen);
memset(arr, 0, SDEBUG_MAX_MSENSE_SZ); memset(arr, 0, SDEBUG_MAX_MSENSE_SZ);
if (0x3 == pcontrol) { /* Saving values not supported */ if (0x3 == pcontrol) { /* Saving values not supported */
mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x39, 0, 14); mk_sense_buffer(devip, ILLEGAL_REQUEST, SAVING_PARAMS_UNSUP,
0, 18);
return check_condition_result; return check_condition_result;
} }
dev_spec = DEV_READONLY(target) ? 0x80 : 0x0; dev_spec = DEV_READONLY(target) ? 0x80 : 0x0;
...@@ -697,7 +719,8 @@ static int resp_mode_sense(unsigned char * cmd, int target, ...@@ -697,7 +719,8 @@ static int resp_mode_sense(unsigned char * cmd, int target,
offset += len; offset += len;
break; break;
default: default:
mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x24, 0, 14); mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
0, 18);
return check_condition_result; return check_condition_result;
} }
if (msense_6) if (msense_6)
...@@ -721,13 +744,15 @@ static int resp_read(struct scsi_cmnd * SCpnt, int upper_blk, int block, ...@@ -721,13 +744,15 @@ static int resp_read(struct scsi_cmnd * SCpnt, int upper_blk, int block,
unsigned long iflags; unsigned long iflags;
if (upper_blk || (block + num > sdebug_capacity)) { if (upper_blk || (block + num > sdebug_capacity)) {
mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x21, 0, 14); mk_sense_buffer(devip, ILLEGAL_REQUEST, ADDR_OUT_OF_RANGE,
0, 18);
return check_condition_result; return check_condition_result;
} }
if ((SCSI_DEBUG_OPT_MEDIUM_ERR & scsi_debug_opts) && if ((SCSI_DEBUG_OPT_MEDIUM_ERR & scsi_debug_opts) &&
(block <= OPT_MEDIUM_ERR_ADDR) && (block <= OPT_MEDIUM_ERR_ADDR) &&
((block + num) > OPT_MEDIUM_ERR_ADDR)) { ((block + num) > OPT_MEDIUM_ERR_ADDR)) {
mk_sense_buffer(devip, MEDIUM_ERROR, 0x11, 0, 14); mk_sense_buffer(devip, MEDIUM_ERROR, UNRECOVERED_READ_ERR,
0, 18);
/* claim unrecoverable read error */ /* claim unrecoverable read error */
return check_condition_result; return check_condition_result;
} }
...@@ -770,7 +795,8 @@ static int resp_write(struct scsi_cmnd * SCpnt, int upper_blk, int block, ...@@ -770,7 +795,8 @@ static int resp_write(struct scsi_cmnd * SCpnt, int upper_blk, int block,
unsigned long iflags; unsigned long iflags;
if (upper_blk || (block + num > sdebug_capacity)) { if (upper_blk || (block + num > sdebug_capacity)) {
mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x21, 0, 14); mk_sense_buffer(devip, ILLEGAL_REQUEST, ADDR_OUT_OF_RANGE,
0, 18);
return check_condition_result; return check_condition_result;
} }
...@@ -805,23 +831,33 @@ static int resp_write(struct scsi_cmnd * SCpnt, int upper_blk, int block, ...@@ -805,23 +831,33 @@ static int resp_write(struct scsi_cmnd * SCpnt, int upper_blk, int block,
static int resp_report_luns(unsigned char * cmd, unsigned char * buff, static int resp_report_luns(unsigned char * cmd, unsigned char * buff,
int bufflen, struct sdebug_dev_info * devip) int bufflen, struct sdebug_dev_info * devip)
{ {
unsigned int alloc_len, lun_cnt, i; unsigned int alloc_len;
int lun_cnt, i, upper;
int select_report = (int)cmd[2]; int select_report = (int)cmd[2];
ScsiLun *one_lun; ScsiLun *one_lun;
alloc_len = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24); alloc_len = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24);
if ((alloc_len < 16) || (select_report > 2)) { if ((alloc_len < 16) || (select_report > 2)) {
mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x24, 0, 14); mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
0, 18);
return check_condition_result; return check_condition_result;
} }
if (bufflen > 3) { if (bufflen > 8) { /* can produce response with up to 16k luns
lun_cnt = min((int)(bufflen / sizeof(ScsiLun)), (lun 0 to lun 16383) */
(int)scsi_debug_max_luns);
memset(buff, 0, bufflen); memset(buff, 0, bufflen);
buff[3] = 8 * lun_cnt; lun_cnt = scsi_debug_max_luns;
one_lun = (ScsiLun*) &buff[0]; buff[2] = ((sizeof(ScsiLun) * lun_cnt) >> 8) & 0xff;
for (i = 0; i < lun_cnt; i++) buff[3] = (sizeof(ScsiLun) * lun_cnt) & 0xff;
one_lun[i].scsi_lun[1] = i; lun_cnt = min((int)((bufflen - 8) / sizeof(ScsiLun)),
lun_cnt);
one_lun = (ScsiLun*) &buff[8];
for (i = 0; i < lun_cnt; i++) {
upper = (i >> 8) & 0x3f;
if (upper)
one_lun[i].scsi_lun[0] =
(upper | (SAM2_LUN_ADDRESS_METHOD << 6));
one_lun[i].scsi_lun[1] = i & 0xff;
}
} }
return 0; return 0;
} }
...@@ -1101,7 +1137,7 @@ static int schedule_resp(struct scsi_cmnd * cmnd, ...@@ -1101,7 +1137,7 @@ static int schedule_resp(struct scsi_cmnd * cmnd,
if ((SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) && cmnd) { if ((SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) && cmnd) {
printk(KERN_INFO "scsi_debug: cmd "); printk(KERN_INFO "scsi_debug: cmd ");
for (k = 0, num = cmnd->cmd_len; k < num; ++k) for (k = 0, num = cmnd->cmd_len; k < num; ++k)
printk("%02x ", (int)cmnd->cmnd[k]); printk("%02x ", (int)cmnd->cmnd[k]);
printk("\n"); printk("\n");
if (scsi_result) { if (scsi_result) {
struct scsi_device * sdp = cmnd->device; struct scsi_device * sdp = cmnd->device;
...@@ -1159,7 +1195,7 @@ static int schedule_resp(struct scsi_cmnd * cmnd, ...@@ -1159,7 +1195,7 @@ static int schedule_resp(struct scsi_cmnd * cmnd,
* of sysfs parameters (which module_param doesn't yet support). * of sysfs parameters (which module_param doesn't yet support).
* Sysfs parameters defined explicitly below. * Sysfs parameters defined explicitly below.
*/ */
module_param_named(num_devs, scsi_debug_num_devs, int, 0); module_param_named(num_tgts, scsi_debug_num_tgts, int, 0);
module_param_named(max_luns, scsi_debug_max_luns, int, 0); module_param_named(max_luns, scsi_debug_max_luns, int, 0);
module_param_named(scsi_level, scsi_debug_scsi_level, int, 0); module_param_named(scsi_level, scsi_debug_scsi_level, int, 0);
module_param_named(dev_size_mb, scsi_debug_dev_size_mb, int, 0); module_param_named(dev_size_mb, scsi_debug_dev_size_mb, int, 0);
...@@ -1172,7 +1208,7 @@ MODULE_AUTHOR("Eric Youngdale + Douglas Gilbert"); ...@@ -1172,7 +1208,7 @@ MODULE_AUTHOR("Eric Youngdale + Douglas Gilbert");
MODULE_DESCRIPTION("SCSI debug adapter driver"); MODULE_DESCRIPTION("SCSI debug adapter driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_PARM_DESC(num_devs, "number of SCSI devices per host to simulate"); MODULE_PARM_DESC(num_tgts, "number of SCSI targets per host to simulate");
MODULE_PARM_DESC(max_luns, "number of SCSI LUNs per target to simulate"); MODULE_PARM_DESC(max_luns, "number of SCSI LUNs per target to simulate");
MODULE_PARM_DESC(scsi_level, "SCSI level to simulate"); MODULE_PARM_DESC(scsi_level, "SCSI level to simulate");
MODULE_PARM_DESC(dev_size_mb, "size in MB of ram shared by devs"); MODULE_PARM_DESC(dev_size_mb, "size in MB of ram shared by devs");
...@@ -1186,9 +1222,9 @@ static char sdebug_info[256]; ...@@ -1186,9 +1222,9 @@ static char sdebug_info[256];
static const char * scsi_debug_info(struct Scsi_Host * shp) static const char * scsi_debug_info(struct Scsi_Host * shp)
{ {
sprintf(sdebug_info, "scsi_debug, %s, num_devs=%d, " sprintf(sdebug_info, "scsi_debug, %s, num_tgts=%d, "
"dev_size_mb=%d, opts=0x%x", scsi_debug_version_str, "dev_size_mb=%d, opts=0x%x", scsi_debug_version_str,
scsi_debug_num_devs, scsi_debug_dev_size_mb, scsi_debug_num_tgts, scsi_debug_dev_size_mb,
scsi_debug_opts); scsi_debug_opts);
return sdebug_info; return sdebug_info;
} }
...@@ -1221,13 +1257,13 @@ static int scsi_debug_proc_info(char *buffer, char **start, off_t offset, ...@@ -1221,13 +1257,13 @@ static int scsi_debug_proc_info(char *buffer, char **start, off_t offset,
} }
begin = 0; begin = 0;
pos = len = sprintf(buffer, "scsi_debug adapter driver, %s\n" pos = len = sprintf(buffer, "scsi_debug adapter driver, %s\n"
"num_devs=%d, shared (ram) size=%d MB, opts=0x%x, " "num_tgts=%d, shared (ram) size=%d MB, opts=0x%x, "
"every_nth=%d(curr:%d)\n" "every_nth=%d(curr:%d)\n"
"delay=%d, max_luns=%d, scsi_level=%d\n" "delay=%d, max_luns=%d, scsi_level=%d\n"
"sector_size=%d bytes, cylinders=%d, heads=%d, sectors=%d\n" "sector_size=%d bytes, cylinders=%d, heads=%d, sectors=%d\n"
"number of aborts=%d, device_reset=%d, bus_resets=%d, " "number of aborts=%d, device_reset=%d, bus_resets=%d, "
"host_resets=%d\n", "host_resets=%d\n",
scsi_debug_version_str, scsi_debug_num_devs, scsi_debug_version_str, scsi_debug_num_tgts,
scsi_debug_dev_size_mb, scsi_debug_opts, scsi_debug_every_nth, scsi_debug_dev_size_mb, scsi_debug_opts, scsi_debug_every_nth,
scsi_debug_cmnd_count, scsi_debug_delay, scsi_debug_cmnd_count, scsi_debug_delay,
scsi_debug_max_luns, scsi_debug_scsi_level, scsi_debug_max_luns, scsi_debug_scsi_level,
...@@ -1295,23 +1331,23 @@ static ssize_t sdebug_opts_store(struct device_driver * ddp, ...@@ -1295,23 +1331,23 @@ static ssize_t sdebug_opts_store(struct device_driver * ddp,
DRIVER_ATTR(opts, S_IRUGO | S_IWUSR, sdebug_opts_show, DRIVER_ATTR(opts, S_IRUGO | S_IWUSR, sdebug_opts_show,
sdebug_opts_store) sdebug_opts_store)
static ssize_t sdebug_num_devs_show(struct device_driver * ddp, char * buf) static ssize_t sdebug_num_tgts_show(struct device_driver * ddp, char * buf)
{ {
return snprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_num_devs); return snprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_num_tgts);
} }
static ssize_t sdebug_num_devs_store(struct device_driver * ddp, static ssize_t sdebug_num_tgts_store(struct device_driver * ddp,
const char * buf, size_t count) const char * buf, size_t count)
{ {
int n; int n;
if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) { if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
scsi_debug_num_devs = n; scsi_debug_num_tgts = n;
return count; return count;
} }
return -EINVAL; return -EINVAL;
} }
DRIVER_ATTR(num_devs, S_IRUGO | S_IWUSR, sdebug_num_devs_show, DRIVER_ATTR(num_tgts, S_IRUGO | S_IWUSR, sdebug_num_tgts_show,
sdebug_num_devs_store) sdebug_num_tgts_store)
static ssize_t sdebug_dev_size_mb_show(struct device_driver * ddp, char * buf) static ssize_t sdebug_dev_size_mb_show(struct device_driver * ddp, char * buf)
{ {
...@@ -1342,7 +1378,19 @@ static ssize_t sdebug_max_luns_show(struct device_driver * ddp, char * buf) ...@@ -1342,7 +1378,19 @@ static ssize_t sdebug_max_luns_show(struct device_driver * ddp, char * buf)
{ {
return snprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_max_luns); return snprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_max_luns);
} }
DRIVER_ATTR(max_luns, S_IRUGO, sdebug_max_luns_show, NULL) static ssize_t sdebug_max_luns_store(struct device_driver * ddp,
const char * buf, size_t count)
{
int n;
if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
scsi_debug_max_luns = n;
return count;
}
return -EINVAL;
}
DRIVER_ATTR(max_luns, S_IRUGO | S_IWUSR, sdebug_max_luns_show,
sdebug_max_luns_store)
static ssize_t sdebug_scsi_level_show(struct device_driver * ddp, char * buf) static ssize_t sdebug_scsi_level_show(struct device_driver * ddp, char * buf)
{ {
...@@ -1391,7 +1439,7 @@ static void do_create_driverfs_files() ...@@ -1391,7 +1439,7 @@ static void do_create_driverfs_files()
{ {
driver_create_file(&sdebug_driverfs_driver, &driver_attr_delay); driver_create_file(&sdebug_driverfs_driver, &driver_attr_delay);
driver_create_file(&sdebug_driverfs_driver, &driver_attr_opts); driver_create_file(&sdebug_driverfs_driver, &driver_attr_opts);
driver_create_file(&sdebug_driverfs_driver, &driver_attr_num_devs); driver_create_file(&sdebug_driverfs_driver, &driver_attr_num_tgts);
driver_create_file(&sdebug_driverfs_driver, &driver_attr_dev_size_mb); driver_create_file(&sdebug_driverfs_driver, &driver_attr_dev_size_mb);
driver_create_file(&sdebug_driverfs_driver, &driver_attr_every_nth); driver_create_file(&sdebug_driverfs_driver, &driver_attr_every_nth);
driver_create_file(&sdebug_driverfs_driver, &driver_attr_max_luns); driver_create_file(&sdebug_driverfs_driver, &driver_attr_max_luns);
...@@ -1406,7 +1454,7 @@ static void do_remove_driverfs_files() ...@@ -1406,7 +1454,7 @@ static void do_remove_driverfs_files()
driver_remove_file(&sdebug_driverfs_driver, &driver_attr_max_luns); driver_remove_file(&sdebug_driverfs_driver, &driver_attr_max_luns);
driver_remove_file(&sdebug_driverfs_driver, &driver_attr_every_nth); driver_remove_file(&sdebug_driverfs_driver, &driver_attr_every_nth);
driver_remove_file(&sdebug_driverfs_driver, &driver_attr_dev_size_mb); driver_remove_file(&sdebug_driverfs_driver, &driver_attr_dev_size_mb);
driver_remove_file(&sdebug_driverfs_driver, &driver_attr_num_devs); driver_remove_file(&sdebug_driverfs_driver, &driver_attr_num_tgts);
driver_remove_file(&sdebug_driverfs_driver, &driver_attr_opts); driver_remove_file(&sdebug_driverfs_driver, &driver_attr_opts);
driver_remove_file(&sdebug_driverfs_driver, &driver_attr_delay); driver_remove_file(&sdebug_driverfs_driver, &driver_attr_delay);
} }
...@@ -1567,7 +1615,7 @@ static void sdebug_remove_adapter() ...@@ -1567,7 +1615,7 @@ static void sdebug_remove_adapter()
static int sdebug_driver_probe(struct device * dev) static int sdebug_driver_probe(struct device * dev)
{ {
int k; int k, devs_per_host;
int error = 0; int error = 0;
struct sdebug_host_info *sdbg_host; struct sdebug_host_info *sdbg_host;
struct sdebug_dev_info *sdbg_devinfo; struct sdebug_dev_info *sdbg_devinfo;
...@@ -1584,7 +1632,8 @@ static int sdebug_driver_probe(struct device * dev) ...@@ -1584,7 +1632,8 @@ static int sdebug_driver_probe(struct device * dev)
INIT_LIST_HEAD(&sdbg_host->dev_info_list); INIT_LIST_HEAD(&sdbg_host->dev_info_list);
for (k = 0; k < scsi_debug_num_devs; k++) { devs_per_host = scsi_debug_num_tgts * scsi_debug_max_luns;
for (k = 0; k < devs_per_host; k++) {
sdbg_devinfo = kmalloc(sizeof(*sdbg_devinfo),GFP_KERNEL); sdbg_devinfo = kmalloc(sizeof(*sdbg_devinfo),GFP_KERNEL);
if (NULL == sdbg_devinfo) { if (NULL == sdbg_devinfo) {
printk(KERN_ERR "%s: out of memory at line %d\n", printk(KERN_ERR "%s: out of memory at line %d\n",
...@@ -1608,7 +1657,11 @@ static int sdebug_driver_probe(struct device * dev) ...@@ -1608,7 +1657,11 @@ static int sdebug_driver_probe(struct device * dev)
sdbg_host->shost = hpnt; sdbg_host->shost = hpnt;
sdbg_host->dev = dev; sdbg_host->dev = dev;
hpnt->max_lun = scsi_debug_max_luns; if ((hpnt->this_id >= 0) && (scsi_debug_num_tgts > hpnt->this_id))
hpnt->max_id = scsi_debug_num_tgts + 1;
else
hpnt->max_id = scsi_debug_num_tgts;
hpnt->max_lun = scsi_debug_max_luns;
error = scsi_add_host(hpnt, sdbg_host->dev); error = scsi_add_host(hpnt, sdbg_host->dev);
if (error) { if (error) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment