blob: 6ed43fd19a22a5f01e21996d02c2939ab737161e [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 * vvvvvvvvvvvvvvvvvvvvvvv Original vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
3 * Copyright (C) 1992 Eric Youngdale
4 * Simulate a host adapter with 2 disks attached. Do a lot of checking
5 * to make sure that we are not getting blocks mixed up, and PANIC if
6 * anything out of the ordinary is seen.
7 * ^^^^^^^^^^^^^^^^^^^^^^^ Original ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
8 *
9 * This version is more generic, simulating a variable number of disk
Douglas Gilbert23183912006-09-16 20:30:47 -040010 * (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.
Linus Torvalds1da177e2005-04-16 15:20:36 -070013 *
14 *
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -040015 * For documentation see http://sg.danny.cz/sg/sdebug26.html
Linus Torvalds1da177e2005-04-16 15:20:36 -070016 *
17 * D. Gilbert (dpg) work for Magneto-Optical device test [20010421]
18 * dpg: work for devfs large number of disks [20010809]
19 * forked for lk 2.5 series [20011216, 20020101]
20 * use vmalloc() more inquiry+mode_sense [20020302]
21 * add timers for delayed responses [20020721]
22 * Patrick Mansfield <patmans@us.ibm.com> max_luns+scsi_level [20021031]
23 * Mike Anderson <andmike@us.ibm.com> sysfs work [20021118]
24 * dpg: change style of boot options to "scsi_debug.num_tgts=2" and
25 * module options to "modprobe scsi_debug num_tgts=2" [20021221]
26 */
27
Linus Torvalds1da177e2005-04-16 15:20:36 -070028#include <linux/module.h>
29
30#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070031#include <linux/errno.h>
32#include <linux/timer.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090033#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070034#include <linux/types.h>
35#include <linux/string.h>
36#include <linux/genhd.h>
37#include <linux/fs.h>
38#include <linux/init.h>
39#include <linux/proc_fs.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070040#include <linux/vmalloc.h>
41#include <linux/moduleparam.h>
Jens Axboe852e0342007-07-16 10:19:24 +020042#include <linux/scatterlist.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#include <linux/blkdev.h>
Martin K. Petersenc6a44282009-01-04 03:08:19 -050044#include <linux/crc-t10dif.h>
45
46#include <net/checksum.h>
FUJITA Tomonori9ff26ee2008-03-02 18:30:15 +090047
Martin K. Petersen44d92692009-10-15 14:45:27 -040048#include <asm/unaligned.h>
49
FUJITA Tomonori9ff26ee2008-03-02 18:30:15 +090050#include <scsi/scsi.h>
51#include <scsi/scsi_cmnd.h>
52#include <scsi/scsi_device.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070053#include <scsi/scsi_host.h>
54#include <scsi/scsicam.h>
FUJITA Tomonoria34c4e92008-03-25 09:26:50 +090055#include <scsi/scsi_eh.h>
Martin K. Petersen395cef02009-09-18 17:33:03 -040056#include <scsi/scsi_dbg.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070057
Martin K. Petersenc6a44282009-01-04 03:08:19 -050058#include "sd.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070059#include "scsi_logging.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070060
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -040061#define SCSI_DEBUG_VERSION "1.82"
62static const char * scsi_debug_version_date = "20100324";
Linus Torvalds1da177e2005-04-16 15:20:36 -070063
Douglas Gilbert6f3cbf52007-01-05 00:05:25 -050064/* Additional Sense Code (ASC) */
Douglas Gilbertc65b1442006-06-06 00:11:24 -040065#define NO_ADDITIONAL_SENSE 0x0
66#define LOGICAL_UNIT_NOT_READY 0x4
Akinobu Mitac5af0db2014-02-26 22:57:01 +090067#define LOGICAL_UNIT_COMMUNICATION_FAILURE 0x8
Linus Torvalds1da177e2005-04-16 15:20:36 -070068#define UNRECOVERED_READ_ERR 0x11
Douglas Gilbertc65b1442006-06-06 00:11:24 -040069#define PARAMETER_LIST_LENGTH_ERR 0x1a
Linus Torvalds1da177e2005-04-16 15:20:36 -070070#define INVALID_OPCODE 0x20
71#define ADDR_OUT_OF_RANGE 0x21
Martin K. Petersen395cef02009-09-18 17:33:03 -040072#define INVALID_COMMAND_OPCODE 0x20
Linus Torvalds1da177e2005-04-16 15:20:36 -070073#define INVALID_FIELD_IN_CDB 0x24
Douglas Gilbertc65b1442006-06-06 00:11:24 -040074#define INVALID_FIELD_IN_PARAM_LIST 0x26
Linus Torvalds1da177e2005-04-16 15:20:36 -070075#define POWERON_RESET 0x29
76#define SAVING_PARAMS_UNSUP 0x39
Douglas Gilbert6f3cbf52007-01-05 00:05:25 -050077#define TRANSPORT_PROBLEM 0x4b
Douglas Gilbertc65b1442006-06-06 00:11:24 -040078#define THRESHOLD_EXCEEDED 0x5d
79#define LOW_POWER_COND_ON 0x5e
Linus Torvalds1da177e2005-04-16 15:20:36 -070080
Douglas Gilbert6f3cbf52007-01-05 00:05:25 -050081/* Additional Sense Code Qualifier (ASCQ) */
82#define ACK_NAK_TO 0x3
83
Linus Torvalds1da177e2005-04-16 15:20:36 -070084#define SDEBUG_TAGGED_QUEUING 0 /* 0 | MSG_SIMPLE_TAG | MSG_ORDERED_TAG */
85
86/* Default values for driver parameters */
87#define DEF_NUM_HOST 1
88#define DEF_NUM_TGTS 1
89#define DEF_MAX_LUNS 1
90/* With these defaults, this driver will make 1 host with 1 target
91 * (id 0) containing 1 logical unit (lun 0). That is 1 device.
92 */
Martin K. Petersen5b94e232011-03-08 02:08:11 -050093#define DEF_ATO 1
Linus Torvalds1da177e2005-04-16 15:20:36 -070094#define DEF_DELAY 1
95#define DEF_DEV_SIZE_MB 8
Martin K. Petersen5b94e232011-03-08 02:08:11 -050096#define DEF_DIF 0
97#define DEF_DIX 0
98#define DEF_D_SENSE 0
Linus Torvalds1da177e2005-04-16 15:20:36 -070099#define DEF_EVERY_NTH 0
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500100#define DEF_FAKE_RW 0
101#define DEF_GUARD 0
102#define DEF_LBPU 0
103#define DEF_LBPWS 0
104#define DEF_LBPWS10 0
Eric Sandeenbe1dd782012-03-08 00:03:59 -0600105#define DEF_LBPRZ 1
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500106#define DEF_LOWEST_ALIGNED 0
107#define DEF_NO_LUN_0 0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108#define DEF_NUM_PARTS 0
109#define DEF_OPTS 0
Martin K. Petersene308b3d2010-03-23 01:12:27 -0400110#define DEF_OPT_BLKS 64
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500111#define DEF_PHYSBLK_EXP 0
112#define DEF_PTYPE 0
Martin Pittd9867882012-09-06 12:04:33 +0200113#define DEF_REMOVABLE false
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500114#define DEF_SCSI_LEVEL 5 /* INQUIRY, byte2 [5->SPC-3] */
115#define DEF_SECTOR_SIZE 512
116#define DEF_UNMAP_ALIGNMENT 0
117#define DEF_UNMAP_GRANULARITY 1
Martin K. Petersen60147592010-08-19 11:49:00 -0400118#define DEF_UNMAP_MAX_BLOCKS 0xFFFFFFFF
119#define DEF_UNMAP_MAX_DESC 256
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500120#define DEF_VIRTUAL_GB 0
121#define DEF_VPD_USE_HOSTNO 1
122#define DEF_WRITESAME_LENGTH 0xFFFF
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123
124/* bit mask values for scsi_debug_opts */
125#define SCSI_DEBUG_OPT_NOISE 1
126#define SCSI_DEBUG_OPT_MEDIUM_ERR 2
127#define SCSI_DEBUG_OPT_TIMEOUT 4
128#define SCSI_DEBUG_OPT_RECOVERED_ERR 8
Douglas Gilbert6f3cbf52007-01-05 00:05:25 -0500129#define SCSI_DEBUG_OPT_TRANSPORT_ERR 16
Martin K. Petersenc6a44282009-01-04 03:08:19 -0500130#define SCSI_DEBUG_OPT_DIF_ERR 32
131#define SCSI_DEBUG_OPT_DIX_ERR 64
Martin K. Petersen18a4d0a2012-02-09 13:48:53 -0500132#define SCSI_DEBUG_OPT_MAC_TIMEOUT 128
Christoph Hellwigb57d7c02014-05-01 16:51:51 +0200133#define SCSI_DEBUG_OPT_SHORT_TRANSFER 256
Linus Torvalds1da177e2005-04-16 15:20:36 -0700134/* When "every_nth" > 0 then modulo "every_nth" commands:
135 * - a no response is simulated if SCSI_DEBUG_OPT_TIMEOUT is set
136 * - a RECOVERED_ERROR is simulated on successful read and write
137 * commands if SCSI_DEBUG_OPT_RECOVERED_ERR is set.
Douglas Gilbert6f3cbf52007-01-05 00:05:25 -0500138 * - a TRANSPORT_ERROR is simulated on successful read and write
139 * commands if SCSI_DEBUG_OPT_TRANSPORT_ERR is set.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140 *
141 * When "every_nth" < 0 then after "- every_nth" commands:
142 * - a no response is simulated if SCSI_DEBUG_OPT_TIMEOUT is set
143 * - a RECOVERED_ERROR is simulated on successful read and write
144 * commands if SCSI_DEBUG_OPT_RECOVERED_ERR is set.
Douglas Gilbert6f3cbf52007-01-05 00:05:25 -0500145 * - a TRANSPORT_ERROR is simulated on successful read and write
146 * commands if SCSI_DEBUG_OPT_TRANSPORT_ERR is set.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147 * This will continue until some other action occurs (e.g. the user
148 * writing a new value (other than -1 or 1) to every_nth via sysfs).
149 */
150
151/* when 1==SCSI_DEBUG_OPT_MEDIUM_ERR, a medium error is simulated at this
152 * sector on read commands: */
153#define OPT_MEDIUM_ERR_ADDR 0x1234 /* that's sector 4660 in decimal */
Douglas Gilbert32f7ef72011-03-11 10:43:35 -0500154#define OPT_MEDIUM_ERR_NUM 10 /* number of consecutive medium errs */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155
156/* If REPORT LUNS has luns >= 256 it can choose "flat space" (value 1)
157 * or "peripheral device" addressing (value 0) */
158#define SAM2_LUN_ADDRESS_METHOD 0
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400159#define SAM2_WLUN_REPORT_LUNS 0xc101
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -0400161/* Can queue up to this number of commands. Typically commands that
162 * that have a non-zero delay are queued. */
163#define SCSI_DEBUG_CANQUEUE 255
164
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165static int scsi_debug_add_host = DEF_NUM_HOST;
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500166static int scsi_debug_ato = DEF_ATO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167static int scsi_debug_delay = DEF_DELAY;
168static int scsi_debug_dev_size_mb = DEF_DEV_SIZE_MB;
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500169static int scsi_debug_dif = DEF_DIF;
170static int scsi_debug_dix = DEF_DIX;
171static int scsi_debug_dsense = DEF_D_SENSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172static int scsi_debug_every_nth = DEF_EVERY_NTH;
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500173static int scsi_debug_fake_rw = DEF_FAKE_RW;
Akinobu Mita68aee7b2013-09-18 21:27:27 +0900174static unsigned int scsi_debug_guard = DEF_GUARD;
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500175static int scsi_debug_lowest_aligned = DEF_LOWEST_ALIGNED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176static int scsi_debug_max_luns = DEF_MAX_LUNS;
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -0400177static int scsi_debug_max_queue = SCSI_DEBUG_CANQUEUE;
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400178static int scsi_debug_no_lun_0 = DEF_NO_LUN_0;
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500179static int scsi_debug_no_uld = 0;
180static int scsi_debug_num_parts = DEF_NUM_PARTS;
181static int scsi_debug_num_tgts = DEF_NUM_TGTS; /* targets per host */
Martin K. Petersene308b3d2010-03-23 01:12:27 -0400182static int scsi_debug_opt_blks = DEF_OPT_BLKS;
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500183static int scsi_debug_opts = DEF_OPTS;
184static int scsi_debug_physblk_exp = DEF_PHYSBLK_EXP;
185static int scsi_debug_ptype = DEF_PTYPE; /* SCSI peripheral type (0==disk) */
186static int scsi_debug_scsi_level = DEF_SCSI_LEVEL;
187static int scsi_debug_sector_size = DEF_SECTOR_SIZE;
188static int scsi_debug_virtual_gb = DEF_VIRTUAL_GB;
189static int scsi_debug_vpd_use_hostno = DEF_VPD_USE_HOSTNO;
190static unsigned int scsi_debug_lbpu = DEF_LBPU;
191static unsigned int scsi_debug_lbpws = DEF_LBPWS;
192static unsigned int scsi_debug_lbpws10 = DEF_LBPWS10;
Eric Sandeenbe1dd782012-03-08 00:03:59 -0600193static unsigned int scsi_debug_lbprz = DEF_LBPRZ;
Martin K. Petersen60147592010-08-19 11:49:00 -0400194static unsigned int scsi_debug_unmap_alignment = DEF_UNMAP_ALIGNMENT;
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500195static unsigned int scsi_debug_unmap_granularity = DEF_UNMAP_GRANULARITY;
196static unsigned int scsi_debug_unmap_max_blocks = DEF_UNMAP_MAX_BLOCKS;
197static unsigned int scsi_debug_unmap_max_desc = DEF_UNMAP_MAX_DESC;
198static unsigned int scsi_debug_write_same_length = DEF_WRITESAME_LENGTH;
Martin Pittd9867882012-09-06 12:04:33 +0200199static bool scsi_debug_removable = DEF_REMOVABLE;
Akinobu Mita0759c662014-02-26 22:57:04 +0900200static bool scsi_debug_clustering;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201
202static int scsi_debug_cmnd_count = 0;
203
204#define DEV_READONLY(TGT) (0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400206static unsigned int sdebug_store_sectors;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207static sector_t sdebug_capacity; /* in sectors */
208
209/* old BIOS stuff, kernel may get rid of them but some mode sense pages
210 may still need them */
211static int sdebug_heads; /* heads per disk */
212static int sdebug_cylinders_per; /* cylinders per surface */
213static int sdebug_sectors_per; /* sectors per cylinder */
214
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215#define SDEBUG_MAX_PARTS 4
216
217#define SDEBUG_SENSE_LEN 32
218
Martin K. Petersen395cef02009-09-18 17:33:03 -0400219#define SCSI_DEBUG_MAX_CMD_LEN 32
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +0900220
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500221static unsigned int scsi_debug_lbp(void)
222{
223 return scsi_debug_lbpu | scsi_debug_lbpws | scsi_debug_lbpws10;
224}
225
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226struct sdebug_dev_info {
227 struct list_head dev_list;
228 unsigned char sense_buff[SDEBUG_SENSE_LEN]; /* weak nexus */
229 unsigned int channel;
230 unsigned int target;
Hannes Reinecke9cb78c12014-06-25 15:27:36 +0200231 u64 lun;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700232 struct sdebug_host_info *sdbg_host;
Hannes Reinecke9cb78c12014-06-25 15:27:36 +0200233 u64 wlun;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234 char reset;
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400235 char stopped;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236 char used;
237};
238
239struct sdebug_host_info {
240 struct list_head host_list;
241 struct Scsi_Host *shost;
242 struct device dev;
243 struct list_head dev_info_list;
244};
245
246#define to_sdebug_host(d) \
247 container_of(d, struct sdebug_host_info, dev)
248
249static LIST_HEAD(sdebug_host_list);
250static DEFINE_SPINLOCK(sdebug_host_list_lock);
251
252typedef void (* done_funct_t) (struct scsi_cmnd *);
253
254struct sdebug_queued_cmd {
255 int in_use;
256 struct timer_list cmnd_timer;
257 done_funct_t done_funct;
258 struct scsi_cmnd * a_cmnd;
259 int scsi_result;
260};
261static struct sdebug_queued_cmd queued_arr[SCSI_DEBUG_CANQUEUE];
262
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263static unsigned char * fake_storep; /* ramdisk storage */
Akinobu Mitae18d8be2013-06-29 17:59:18 +0900264static struct sd_dif_tuple *dif_storep; /* protection info */
Martin K. Petersen44d92692009-10-15 14:45:27 -0400265static void *map_storep; /* provisioning map */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266
Martin K. Petersen44d92692009-10-15 14:45:27 -0400267static unsigned long map_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268static int num_aborts = 0;
269static int num_dev_resets = 0;
270static int num_bus_resets = 0;
271static int num_host_resets = 0;
Martin K. Petersenc6a44282009-01-04 03:08:19 -0500272static int dix_writes;
273static int dix_reads;
274static int dif_errors;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275
276static DEFINE_SPINLOCK(queued_arr_lock);
277static DEFINE_RWLOCK(atomic_rw);
278
279static char sdebug_proc_name[] = "scsi_debug";
280
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281static struct bus_type pseudo_lld_bus;
282
283static struct device_driver sdebug_driverfs_driver = {
284 .name = sdebug_proc_name,
285 .bus = &pseudo_lld_bus,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286};
287
288static const int check_condition_result =
289 (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
290
Martin K. Petersenc6a44282009-01-04 03:08:19 -0500291static const int illegal_condition_result =
292 (DRIVER_SENSE << 24) | (DID_ABORT << 16) | SAM_STAT_CHECK_CONDITION;
293
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400294static unsigned char ctrl_m_pg[] = {0xa, 10, 2, 0, 0, 0, 0, 0,
295 0, 0, 0x2, 0x4b};
296static unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0,
297 0, 0, 0x0, 0x0};
298
Akinobu Mita14faa942013-09-18 21:27:24 +0900299static void *fake_store(unsigned long long lba)
300{
301 lba = do_div(lba, sdebug_store_sectors);
302
303 return fake_storep + lba * scsi_debug_sector_size;
304}
305
306static struct sd_dif_tuple *dif_store(sector_t sector)
307{
308 sector = do_div(sector, sdebug_store_sectors);
309
310 return dif_storep + sector;
311}
312
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313static int sdebug_add_adapter(void);
314static void sdebug_remove_adapter(void);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +0900316static void sdebug_max_tgts_luns(void)
317{
318 struct sdebug_host_info *sdbg_host;
319 struct Scsi_Host *hpnt;
320
321 spin_lock(&sdebug_host_list_lock);
322 list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) {
323 hpnt = sdbg_host->shost;
324 if ((hpnt->this_id >= 0) &&
325 (scsi_debug_num_tgts > hpnt->this_id))
326 hpnt->max_id = scsi_debug_num_tgts + 1;
327 else
328 hpnt->max_id = scsi_debug_num_tgts;
329 /* scsi_debug_max_luns; */
330 hpnt->max_lun = SAM2_WLUN_REPORT_LUNS;
331 }
332 spin_unlock(&sdebug_host_list_lock);
333}
334
335static void mk_sense_buffer(struct sdebug_dev_info *devip, int key,
336 int asc, int asq)
337{
338 unsigned char *sbuff;
339
340 sbuff = devip->sense_buff;
341 memset(sbuff, 0, SDEBUG_SENSE_LEN);
342
343 scsi_build_sense_buffer(scsi_debug_dsense, sbuff, key, asc, asq);
344
345 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
346 printk(KERN_INFO "scsi_debug: [sense_key,asc,ascq]: "
347 "[0x%x,0x%x,0x%x]\n", key, asc, asq);
348}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349
FUJITA Tomonori3de9f942008-01-23 01:31:59 +0900350static void get_data_transfer_info(unsigned char *cmd,
Martin K. Petersen395cef02009-09-18 17:33:03 -0400351 unsigned long long *lba, unsigned int *num,
352 u32 *ei_lba)
FUJITA Tomonori3de9f942008-01-23 01:31:59 +0900353{
Martin K. Petersen395cef02009-09-18 17:33:03 -0400354 *ei_lba = 0;
355
FUJITA Tomonori3de9f942008-01-23 01:31:59 +0900356 switch (*cmd) {
Martin K. Petersen395cef02009-09-18 17:33:03 -0400357 case VARIABLE_LENGTH_CMD:
358 *lba = (u64)cmd[19] | (u64)cmd[18] << 8 |
359 (u64)cmd[17] << 16 | (u64)cmd[16] << 24 |
360 (u64)cmd[15] << 32 | (u64)cmd[14] << 40 |
361 (u64)cmd[13] << 48 | (u64)cmd[12] << 56;
362
363 *ei_lba = (u32)cmd[23] | (u32)cmd[22] << 8 |
364 (u32)cmd[21] << 16 | (u32)cmd[20] << 24;
365
366 *num = (u32)cmd[31] | (u32)cmd[30] << 8 | (u32)cmd[29] << 16 |
367 (u32)cmd[28] << 24;
368 break;
369
Martin K. Petersen44d92692009-10-15 14:45:27 -0400370 case WRITE_SAME_16:
FUJITA Tomonori3de9f942008-01-23 01:31:59 +0900371 case WRITE_16:
372 case READ_16:
FUJITA Tomonorid5cdc982008-03-25 17:04:46 +0900373 *lba = (u64)cmd[9] | (u64)cmd[8] << 8 |
374 (u64)cmd[7] << 16 | (u64)cmd[6] << 24 |
375 (u64)cmd[5] << 32 | (u64)cmd[4] << 40 |
376 (u64)cmd[3] << 48 | (u64)cmd[2] << 56;
377
378 *num = (u32)cmd[13] | (u32)cmd[12] << 8 | (u32)cmd[11] << 16 |
379 (u32)cmd[10] << 24;
FUJITA Tomonori3de9f942008-01-23 01:31:59 +0900380 break;
381 case WRITE_12:
382 case READ_12:
FUJITA Tomonorid5cdc982008-03-25 17:04:46 +0900383 *lba = (u32)cmd[5] | (u32)cmd[4] << 8 | (u32)cmd[3] << 16 |
384 (u32)cmd[2] << 24;
385
386 *num = (u32)cmd[9] | (u32)cmd[8] << 8 | (u32)cmd[7] << 16 |
387 (u32)cmd[6] << 24;
FUJITA Tomonori3de9f942008-01-23 01:31:59 +0900388 break;
Martin K. Petersen44d92692009-10-15 14:45:27 -0400389 case WRITE_SAME:
FUJITA Tomonori3de9f942008-01-23 01:31:59 +0900390 case WRITE_10:
391 case READ_10:
FUJITA Tomonoric639d142008-01-23 01:32:01 +0900392 case XDWRITEREAD_10:
FUJITA Tomonorid5cdc982008-03-25 17:04:46 +0900393 *lba = (u32)cmd[5] | (u32)cmd[4] << 8 | (u32)cmd[3] << 16 |
394 (u32)cmd[2] << 24;
395
396 *num = (u32)cmd[8] | (u32)cmd[7] << 8;
FUJITA Tomonori3de9f942008-01-23 01:31:59 +0900397 break;
398 case WRITE_6:
399 case READ_6:
FUJITA Tomonorid5cdc982008-03-25 17:04:46 +0900400 *lba = (u32)cmd[3] | (u32)cmd[2] << 8 |
401 (u32)(cmd[1] & 0x1f) << 16;
FUJITA Tomonori3de9f942008-01-23 01:31:59 +0900402 *num = (0 == cmd[4]) ? 256 : cmd[4];
403 break;
404 default:
405 break;
406 }
407}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409static int scsi_debug_ioctl(struct scsi_device *dev, int cmd, void __user *arg)
410{
411 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) {
412 printk(KERN_INFO "scsi_debug: ioctl: cmd=0x%x\n", cmd);
413 }
414 return -EINVAL;
415 /* return -ENOTTY; // correct return but upsets fdisk */
416}
417
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400418static int check_readiness(struct scsi_cmnd * SCpnt, int reset_only,
419 struct sdebug_dev_info * devip)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420{
421 if (devip->reset) {
422 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
423 printk(KERN_INFO "scsi_debug: Reporting Unit "
424 "attention: power on reset\n");
425 devip->reset = 0;
426 mk_sense_buffer(devip, UNIT_ATTENTION, POWERON_RESET, 0);
427 return check_condition_result;
428 }
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400429 if ((0 == reset_only) && devip->stopped) {
430 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
431 printk(KERN_INFO "scsi_debug: Reporting Not "
432 "ready: initializing command required\n");
433 mk_sense_buffer(devip, NOT_READY, LOGICAL_UNIT_NOT_READY,
434 0x2);
435 return check_condition_result;
436 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437 return 0;
438}
439
440/* Returns 0 if ok else (DID_ERROR << 16). Sets scp->resid . */
FUJITA Tomonori21a61822008-03-09 13:44:30 +0900441static int fill_from_dev_buffer(struct scsi_cmnd *scp, unsigned char *arr,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442 int arr_len)
443{
FUJITA Tomonori21a61822008-03-09 13:44:30 +0900444 int act_len;
FUJITA Tomonori072d0bb2008-01-23 01:32:00 +0900445 struct scsi_data_buffer *sdb = scsi_in(scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446
FUJITA Tomonori072d0bb2008-01-23 01:32:00 +0900447 if (!sdb->length)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448 return 0;
FUJITA Tomonori072d0bb2008-01-23 01:32:00 +0900449 if (!(scsi_bidi_cmnd(scp) || scp->sc_data_direction == DMA_FROM_DEVICE))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450 return (DID_ERROR << 16);
FUJITA Tomonori21a61822008-03-09 13:44:30 +0900451
452 act_len = sg_copy_from_buffer(sdb->table.sgl, sdb->table.nents,
453 arr, arr_len);
Akinobu Mitaa4517512013-07-08 16:01:57 -0700454 sdb->resid = scsi_bufflen(scp) - act_len;
FUJITA Tomonori21a61822008-03-09 13:44:30 +0900455
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456 return 0;
457}
458
459/* Returns number of bytes fetched into 'arr' or -1 if error. */
FUJITA Tomonori21a61822008-03-09 13:44:30 +0900460static int fetch_to_dev_buffer(struct scsi_cmnd *scp, unsigned char *arr,
461 int arr_len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462{
FUJITA Tomonori21a61822008-03-09 13:44:30 +0900463 if (!scsi_bufflen(scp))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464 return 0;
FUJITA Tomonori072d0bb2008-01-23 01:32:00 +0900465 if (!(scsi_bidi_cmnd(scp) || scp->sc_data_direction == DMA_TO_DEVICE))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466 return -1;
FUJITA Tomonori21a61822008-03-09 13:44:30 +0900467
468 return scsi_sg_copy_to_buffer(scp, arr, arr_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469}
470
471
472static const char * inq_vendor_id = "Linux ";
473static const char * inq_product_id = "scsi_debug ";
474static const char * inq_product_rev = "0004";
475
Hannes Reinecke5a09e392006-10-20 09:58:47 +0200476static int inquiry_evpd_83(unsigned char * arr, int port_group_id,
477 int target_dev_id, int dev_id_num,
478 const char * dev_id_str,
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400479 int dev_id_str_len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480{
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400481 int num, port_a;
482 char b[32];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400484 port_a = target_dev_id + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485 /* T10 vendor identifier field format (faked) */
486 arr[0] = 0x2; /* ASCII */
487 arr[1] = 0x1;
488 arr[2] = 0x0;
489 memcpy(&arr[4], inq_vendor_id, 8);
490 memcpy(&arr[12], inq_product_id, 16);
491 memcpy(&arr[28], dev_id_str, dev_id_str_len);
492 num = 8 + 16 + dev_id_str_len;
493 arr[3] = num;
494 num += 4;
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400495 if (dev_id_num >= 0) {
496 /* NAA-5, Logical unit identifier (binary) */
497 arr[num++] = 0x1; /* binary (not necessarily sas) */
498 arr[num++] = 0x3; /* PIV=0, lu, naa */
499 arr[num++] = 0x0;
500 arr[num++] = 0x8;
501 arr[num++] = 0x53; /* naa-5 ieee company id=0x333333 (fake) */
502 arr[num++] = 0x33;
503 arr[num++] = 0x33;
504 arr[num++] = 0x30;
505 arr[num++] = (dev_id_num >> 24);
506 arr[num++] = (dev_id_num >> 16) & 0xff;
507 arr[num++] = (dev_id_num >> 8) & 0xff;
508 arr[num++] = dev_id_num & 0xff;
509 /* Target relative port number */
510 arr[num++] = 0x61; /* proto=sas, binary */
511 arr[num++] = 0x94; /* PIV=1, target port, rel port */
512 arr[num++] = 0x0; /* reserved */
513 arr[num++] = 0x4; /* length */
514 arr[num++] = 0x0; /* reserved */
515 arr[num++] = 0x0; /* reserved */
516 arr[num++] = 0x0;
517 arr[num++] = 0x1; /* relative port A */
518 }
519 /* NAA-5, Target port identifier */
520 arr[num++] = 0x61; /* proto=sas, binary */
521 arr[num++] = 0x93; /* piv=1, target port, naa */
522 arr[num++] = 0x0;
523 arr[num++] = 0x8;
524 arr[num++] = 0x52; /* naa-5, company id=0x222222 (fake) */
525 arr[num++] = 0x22;
526 arr[num++] = 0x22;
527 arr[num++] = 0x20;
528 arr[num++] = (port_a >> 24);
529 arr[num++] = (port_a >> 16) & 0xff;
530 arr[num++] = (port_a >> 8) & 0xff;
531 arr[num++] = port_a & 0xff;
Hannes Reinecke5a09e392006-10-20 09:58:47 +0200532 /* NAA-5, Target port group identifier */
533 arr[num++] = 0x61; /* proto=sas, binary */
534 arr[num++] = 0x95; /* piv=1, target port group id */
535 arr[num++] = 0x0;
536 arr[num++] = 0x4;
537 arr[num++] = 0;
538 arr[num++] = 0;
539 arr[num++] = (port_group_id >> 8) & 0xff;
540 arr[num++] = port_group_id & 0xff;
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400541 /* NAA-5, Target device identifier */
542 arr[num++] = 0x61; /* proto=sas, binary */
543 arr[num++] = 0xa3; /* piv=1, target device, naa */
544 arr[num++] = 0x0;
545 arr[num++] = 0x8;
546 arr[num++] = 0x52; /* naa-5, company id=0x222222 (fake) */
547 arr[num++] = 0x22;
548 arr[num++] = 0x22;
549 arr[num++] = 0x20;
550 arr[num++] = (target_dev_id >> 24);
551 arr[num++] = (target_dev_id >> 16) & 0xff;
552 arr[num++] = (target_dev_id >> 8) & 0xff;
553 arr[num++] = target_dev_id & 0xff;
554 /* SCSI name string: Target device identifier */
555 arr[num++] = 0x63; /* proto=sas, UTF-8 */
556 arr[num++] = 0xa8; /* piv=1, target device, SCSI name string */
557 arr[num++] = 0x0;
558 arr[num++] = 24;
559 memcpy(arr + num, "naa.52222220", 12);
560 num += 12;
561 snprintf(b, sizeof(b), "%08X", target_dev_id);
562 memcpy(arr + num, b, 8);
563 num += 8;
564 memset(arr + num, 0, 4);
565 num += 4;
566 return num;
567}
568
569
570static unsigned char vpd84_data[] = {
571/* from 4th byte */ 0x22,0x22,0x22,0x0,0xbb,0x0,
572 0x22,0x22,0x22,0x0,0xbb,0x1,
573 0x22,0x22,0x22,0x0,0xbb,0x2,
574};
575
576static int inquiry_evpd_84(unsigned char * arr)
577{
578 memcpy(arr, vpd84_data, sizeof(vpd84_data));
579 return sizeof(vpd84_data);
580}
581
582static int inquiry_evpd_85(unsigned char * arr)
583{
584 int num = 0;
585 const char * na1 = "https://www.kernel.org/config";
586 const char * na2 = "http://www.kernel.org/log";
587 int plen, olen;
588
589 arr[num++] = 0x1; /* lu, storage config */
590 arr[num++] = 0x0; /* reserved */
591 arr[num++] = 0x0;
592 olen = strlen(na1);
593 plen = olen + 1;
594 if (plen % 4)
595 plen = ((plen / 4) + 1) * 4;
596 arr[num++] = plen; /* length, null termianted, padded */
597 memcpy(arr + num, na1, olen);
598 memset(arr + num + olen, 0, plen - olen);
599 num += plen;
600
601 arr[num++] = 0x4; /* lu, logging */
602 arr[num++] = 0x0; /* reserved */
603 arr[num++] = 0x0;
604 olen = strlen(na2);
605 plen = olen + 1;
606 if (plen % 4)
607 plen = ((plen / 4) + 1) * 4;
608 arr[num++] = plen; /* length, null terminated, padded */
609 memcpy(arr + num, na2, olen);
610 memset(arr + num + olen, 0, plen - olen);
611 num += plen;
612
613 return num;
614}
615
616/* SCSI ports VPD page */
617static int inquiry_evpd_88(unsigned char * arr, int target_dev_id)
618{
619 int num = 0;
620 int port_a, port_b;
621
622 port_a = target_dev_id + 1;
623 port_b = port_a + 1;
624 arr[num++] = 0x0; /* reserved */
625 arr[num++] = 0x0; /* reserved */
626 arr[num++] = 0x0;
627 arr[num++] = 0x1; /* relative port 1 (primary) */
628 memset(arr + num, 0, 6);
629 num += 6;
630 arr[num++] = 0x0;
631 arr[num++] = 12; /* length tp descriptor */
632 /* naa-5 target port identifier (A) */
633 arr[num++] = 0x61; /* proto=sas, binary */
634 arr[num++] = 0x93; /* PIV=1, target port, NAA */
635 arr[num++] = 0x0; /* reserved */
636 arr[num++] = 0x8; /* length */
637 arr[num++] = 0x52; /* NAA-5, company_id=0x222222 (fake) */
638 arr[num++] = 0x22;
639 arr[num++] = 0x22;
640 arr[num++] = 0x20;
641 arr[num++] = (port_a >> 24);
642 arr[num++] = (port_a >> 16) & 0xff;
643 arr[num++] = (port_a >> 8) & 0xff;
644 arr[num++] = port_a & 0xff;
645
646 arr[num++] = 0x0; /* reserved */
647 arr[num++] = 0x0; /* reserved */
648 arr[num++] = 0x0;
649 arr[num++] = 0x2; /* relative port 2 (secondary) */
650 memset(arr + num, 0, 6);
651 num += 6;
652 arr[num++] = 0x0;
653 arr[num++] = 12; /* length tp descriptor */
654 /* naa-5 target port identifier (B) */
655 arr[num++] = 0x61; /* proto=sas, binary */
656 arr[num++] = 0x93; /* PIV=1, target port, NAA */
657 arr[num++] = 0x0; /* reserved */
658 arr[num++] = 0x8; /* length */
659 arr[num++] = 0x52; /* NAA-5, company_id=0x222222 (fake) */
660 arr[num++] = 0x22;
661 arr[num++] = 0x22;
662 arr[num++] = 0x20;
663 arr[num++] = (port_b >> 24);
664 arr[num++] = (port_b >> 16) & 0xff;
665 arr[num++] = (port_b >> 8) & 0xff;
666 arr[num++] = port_b & 0xff;
667
668 return num;
669}
670
671
672static unsigned char vpd89_data[] = {
673/* from 4th byte */ 0,0,0,0,
674'l','i','n','u','x',' ',' ',' ',
675'S','A','T',' ','s','c','s','i','_','d','e','b','u','g',' ',' ',
676'1','2','3','4',
6770x34,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,
6780xec,0,0,0,
6790x5a,0xc,0xff,0x3f,0x37,0xc8,0x10,0,0,0,0,0,0x3f,0,0,0,
6800,0,0,0,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x20,0x20,0x20,0x20,
6810x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0,0,0,0x40,0x4,0,0x2e,0x33,
6820x38,0x31,0x20,0x20,0x20,0x20,0x54,0x53,0x38,0x33,0x30,0x30,0x33,0x31,
6830x53,0x41,
6840x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
6850x20,0x20,
6860x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
6870x10,0x80,
6880,0,0,0x2f,0,0,0,0x2,0,0x2,0x7,0,0xff,0xff,0x1,0,
6890x3f,0,0xc1,0xff,0x3e,0,0x10,0x1,0xb0,0xf8,0x50,0x9,0,0,0x7,0,
6900x3,0,0x78,0,0x78,0,0xf0,0,0x78,0,0,0,0,0,0,0,
6910,0,0,0,0,0,0,0,0x2,0,0,0,0,0,0,0,
6920x7e,0,0x1b,0,0x6b,0x34,0x1,0x7d,0x3,0x40,0x69,0x34,0x1,0x3c,0x3,0x40,
6930x7f,0x40,0,0,0,0,0xfe,0xfe,0,0,0,0,0,0xfe,0,0,
6940,0,0,0,0,0,0,0,0xb0,0xf8,0x50,0x9,0,0,0,0,
6950,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
6960,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
6970,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
6980x1,0,0xb0,0xf8,0x50,0x9,0xb0,0xf8,0x50,0x9,0x20,0x20,0x2,0,0xb6,0x42,
6990,0x80,0x8a,0,0x6,0x3c,0xa,0x3c,0xff,0xff,0xc6,0x7,0,0x1,0,0x8,
7000xf0,0xf,0,0x10,0x2,0,0x30,0,0,0,0,0,0,0,0x6,0xfe,
7010,0,0x2,0,0x50,0,0x8a,0,0x4f,0x95,0,0,0x21,0,0xb,0,
7020,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
7030,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
7040,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
7050,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
7060,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
7070,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
7080,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
7090,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
7100,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
7110,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
7120,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
7130,0,0,0,0,0,0,0,0,0,0,0,0,0,0xa5,0x51,
714};
715
716static int inquiry_evpd_89(unsigned char * arr)
717{
718 memcpy(arr, vpd89_data, sizeof(vpd89_data));
719 return sizeof(vpd89_data);
720}
721
722
Douglas Gilbert1e49f782009-10-29 01:48:31 -0400723/* Block limits VPD page (SBC-3) */
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400724static unsigned char vpdb0_data[] = {
Douglas Gilbert1e49f782009-10-29 01:48:31 -0400725 /* from 4th byte */ 0,0,0,4, 0,0,0x4,0, 0,0,0,64,
726 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
727 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
728 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400729};
730
731static int inquiry_evpd_b0(unsigned char * arr)
732{
Martin K. Petersenea61fca2009-05-15 00:40:33 -0400733 unsigned int gran;
734
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400735 memcpy(arr, vpdb0_data, sizeof(vpdb0_data));
Martin K. Petersene308b3d2010-03-23 01:12:27 -0400736
737 /* Optimal transfer length granularity */
Martin K. Petersenea61fca2009-05-15 00:40:33 -0400738 gran = 1 << scsi_debug_physblk_exp;
739 arr[2] = (gran >> 8) & 0xff;
740 arr[3] = gran & 0xff;
Martin K. Petersene308b3d2010-03-23 01:12:27 -0400741
742 /* Maximum Transfer Length */
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400743 if (sdebug_store_sectors > 0x400) {
744 arr[4] = (sdebug_store_sectors >> 24) & 0xff;
745 arr[5] = (sdebug_store_sectors >> 16) & 0xff;
746 arr[6] = (sdebug_store_sectors >> 8) & 0xff;
747 arr[7] = sdebug_store_sectors & 0xff;
748 }
Martin K. Petersen44d92692009-10-15 14:45:27 -0400749
Martin K. Petersene308b3d2010-03-23 01:12:27 -0400750 /* Optimal Transfer Length */
751 put_unaligned_be32(scsi_debug_opt_blks, &arr[8]);
752
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500753 if (scsi_debug_lbpu) {
Martin K. Petersene308b3d2010-03-23 01:12:27 -0400754 /* Maximum Unmap LBA Count */
Martin K. Petersen60147592010-08-19 11:49:00 -0400755 put_unaligned_be32(scsi_debug_unmap_max_blocks, &arr[16]);
Martin K. Petersene308b3d2010-03-23 01:12:27 -0400756
757 /* Maximum Unmap Block Descriptor Count */
Martin K. Petersen44d92692009-10-15 14:45:27 -0400758 put_unaligned_be32(scsi_debug_unmap_max_desc, &arr[20]);
759 }
760
Martin K. Petersene308b3d2010-03-23 01:12:27 -0400761 /* Unmap Granularity Alignment */
Martin K. Petersen44d92692009-10-15 14:45:27 -0400762 if (scsi_debug_unmap_alignment) {
763 put_unaligned_be32(scsi_debug_unmap_alignment, &arr[28]);
764 arr[28] |= 0x80; /* UGAVALID */
765 }
766
Martin K. Petersene308b3d2010-03-23 01:12:27 -0400767 /* Optimal Unmap Granularity */
Martin K. Petersen60147592010-08-19 11:49:00 -0400768 put_unaligned_be32(scsi_debug_unmap_granularity, &arr[24]);
769
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500770 /* Maximum WRITE SAME Length */
771 put_unaligned_be64(scsi_debug_write_same_length, &arr[32]);
772
773 return 0x3c; /* Mandatory page length for Logical Block Provisioning */
Martin K. Petersen44d92692009-10-15 14:45:27 -0400774
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400775 return sizeof(vpdb0_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776}
777
Douglas Gilbert1e49f782009-10-29 01:48:31 -0400778/* Block device characteristics VPD page (SBC-3) */
Matthew Wilcoxeac6e8e42008-06-19 10:02:58 -0600779static int inquiry_evpd_b1(unsigned char *arr)
780{
781 memset(arr, 0, 0x3c);
782 arr[0] = 0;
Douglas Gilbert1e49f782009-10-29 01:48:31 -0400783 arr[1] = 1; /* non rotating medium (e.g. solid state) */
784 arr[2] = 0;
785 arr[3] = 5; /* less than 1.8" */
Matthew Wilcoxeac6e8e42008-06-19 10:02:58 -0600786
787 return 0x3c;
788}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789
Eric Sandeenbe1dd782012-03-08 00:03:59 -0600790/* Logical block provisioning VPD page (SBC-3) */
Martin K. Petersen60147592010-08-19 11:49:00 -0400791static int inquiry_evpd_b2(unsigned char *arr)
792{
Martin K. Petersen3f0bc3b2012-03-08 10:48:29 -0500793 memset(arr, 0, 0x4);
Martin K. Petersen60147592010-08-19 11:49:00 -0400794 arr[0] = 0; /* threshold exponent */
795
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500796 if (scsi_debug_lbpu)
Martin K. Petersen60147592010-08-19 11:49:00 -0400797 arr[1] = 1 << 7;
798
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500799 if (scsi_debug_lbpws)
Martin K. Petersen60147592010-08-19 11:49:00 -0400800 arr[1] |= 1 << 6;
801
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500802 if (scsi_debug_lbpws10)
803 arr[1] |= 1 << 5;
804
Eric Sandeenbe1dd782012-03-08 00:03:59 -0600805 if (scsi_debug_lbprz)
806 arr[1] |= 1 << 2;
807
Martin K. Petersen3f0bc3b2012-03-08 10:48:29 -0500808 return 0x4;
Martin K. Petersen60147592010-08-19 11:49:00 -0400809}
810
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811#define SDEBUG_LONG_INQ_SZ 96
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400812#define SDEBUG_MAX_INQ_ARR_SZ 584
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813
814static int resp_inquiry(struct scsi_cmnd * scp, int target,
815 struct sdebug_dev_info * devip)
816{
817 unsigned char pq_pdt;
Hannes Reinecke5a09e392006-10-20 09:58:47 +0200818 unsigned char * arr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819 unsigned char *cmd = (unsigned char *)scp->cmnd;
Hannes Reinecke5a09e392006-10-20 09:58:47 +0200820 int alloc_len, n, ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821
822 alloc_len = (cmd[3] << 8) + cmd[4];
Douglas Gilbert6f3cbf52007-01-05 00:05:25 -0500823 arr = kzalloc(SDEBUG_MAX_INQ_ARR_SZ, GFP_ATOMIC);
824 if (! arr)
825 return DID_REQUEUE << 16;
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400826 if (devip->wlun)
827 pq_pdt = 0x1e; /* present, wlun */
828 else if (scsi_debug_no_lun_0 && (0 == devip->lun))
829 pq_pdt = 0x7f; /* not present, no device type */
830 else
831 pq_pdt = (scsi_debug_ptype & 0x1f);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832 arr[0] = pq_pdt;
833 if (0x2 & cmd[1]) { /* CMDDT bit set */
834 mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
835 0);
Hannes Reinecke5a09e392006-10-20 09:58:47 +0200836 kfree(arr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837 return check_condition_result;
838 } else if (0x1 & cmd[1]) { /* EVPD bit set */
Hannes Reinecke5a09e392006-10-20 09:58:47 +0200839 int lu_id_num, port_group_id, target_dev_id, len;
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400840 char lu_id_str[6];
841 int host_no = devip->sdbg_host->shost->host_no;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842
Hannes Reinecke5a09e392006-10-20 09:58:47 +0200843 port_group_id = (((host_no + 1) & 0x7f) << 8) +
844 (devip->channel & 0x7f);
Douglas Gilbert23183912006-09-16 20:30:47 -0400845 if (0 == scsi_debug_vpd_use_hostno)
846 host_no = 0;
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400847 lu_id_num = devip->wlun ? -1 : (((host_no + 1) * 2000) +
848 (devip->target * 1000) + devip->lun);
849 target_dev_id = ((host_no + 1) * 2000) +
850 (devip->target * 1000) - 3;
851 len = scnprintf(lu_id_str, 6, "%d", lu_id_num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852 if (0 == cmd[2]) { /* supported vital product data pages */
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400853 arr[1] = cmd[2]; /*sanity */
854 n = 4;
855 arr[n++] = 0x0; /* this page */
856 arr[n++] = 0x80; /* unit serial number */
857 arr[n++] = 0x83; /* device identification */
858 arr[n++] = 0x84; /* software interface ident. */
859 arr[n++] = 0x85; /* management network addresses */
860 arr[n++] = 0x86; /* extended inquiry */
861 arr[n++] = 0x87; /* mode page policy */
862 arr[n++] = 0x88; /* SCSI ports */
863 arr[n++] = 0x89; /* ATA information */
864 arr[n++] = 0xb0; /* Block limits (SBC) */
Matthew Wilcoxeac6e8e42008-06-19 10:02:58 -0600865 arr[n++] = 0xb1; /* Block characteristics (SBC) */
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500866 if (scsi_debug_lbp()) /* Logical Block Prov. (SBC) */
867 arr[n++] = 0xb2;
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400868 arr[3] = n - 4; /* number of supported VPD pages */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869 } else if (0x80 == cmd[2]) { /* unit serial number */
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400870 arr[1] = cmd[2]; /*sanity */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871 arr[3] = len;
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400872 memcpy(&arr[4], lu_id_str, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873 } else if (0x83 == cmd[2]) { /* device identification */
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400874 arr[1] = cmd[2]; /*sanity */
Hannes Reinecke5a09e392006-10-20 09:58:47 +0200875 arr[3] = inquiry_evpd_83(&arr[4], port_group_id,
876 target_dev_id, lu_id_num,
877 lu_id_str, len);
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400878 } else if (0x84 == cmd[2]) { /* Software interface ident. */
879 arr[1] = cmd[2]; /*sanity */
880 arr[3] = inquiry_evpd_84(&arr[4]);
881 } else if (0x85 == cmd[2]) { /* Management network addresses */
882 arr[1] = cmd[2]; /*sanity */
883 arr[3] = inquiry_evpd_85(&arr[4]);
884 } else if (0x86 == cmd[2]) { /* extended inquiry */
885 arr[1] = cmd[2]; /*sanity */
886 arr[3] = 0x3c; /* number of following entries */
Martin K. Petersenc6a44282009-01-04 03:08:19 -0500887 if (scsi_debug_dif == SD_DIF_TYPE3_PROTECTION)
888 arr[4] = 0x4; /* SPT: GRD_CHK:1 */
889 else if (scsi_debug_dif)
890 arr[4] = 0x5; /* SPT: GRD_CHK:1, REF_CHK:1 */
891 else
892 arr[4] = 0x0; /* no protection stuff */
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400893 arr[5] = 0x7; /* head of q, ordered + simple q's */
894 } else if (0x87 == cmd[2]) { /* mode page policy */
895 arr[1] = cmd[2]; /*sanity */
896 arr[3] = 0x8; /* number of following entries */
897 arr[4] = 0x2; /* disconnect-reconnect mp */
898 arr[6] = 0x80; /* mlus, shared */
899 arr[8] = 0x18; /* protocol specific lu */
900 arr[10] = 0x82; /* mlus, per initiator port */
901 } else if (0x88 == cmd[2]) { /* SCSI Ports */
902 arr[1] = cmd[2]; /*sanity */
903 arr[3] = inquiry_evpd_88(&arr[4], target_dev_id);
904 } else if (0x89 == cmd[2]) { /* ATA information */
905 arr[1] = cmd[2]; /*sanity */
906 n = inquiry_evpd_89(&arr[4]);
907 arr[2] = (n >> 8);
908 arr[3] = (n & 0xff);
909 } else if (0xb0 == cmd[2]) { /* Block limits (SBC) */
910 arr[1] = cmd[2]; /*sanity */
911 arr[3] = inquiry_evpd_b0(&arr[4]);
Matthew Wilcoxeac6e8e42008-06-19 10:02:58 -0600912 } else if (0xb1 == cmd[2]) { /* Block characteristics (SBC) */
913 arr[1] = cmd[2]; /*sanity */
914 arr[3] = inquiry_evpd_b1(&arr[4]);
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500915 } else if (0xb2 == cmd[2]) { /* Logical Block Prov. (SBC) */
Martin K. Petersen60147592010-08-19 11:49:00 -0400916 arr[1] = cmd[2]; /*sanity */
917 arr[3] = inquiry_evpd_b2(&arr[4]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 } else {
919 /* Illegal request, invalid field in cdb */
920 mk_sense_buffer(devip, ILLEGAL_REQUEST,
921 INVALID_FIELD_IN_CDB, 0);
Hannes Reinecke5a09e392006-10-20 09:58:47 +0200922 kfree(arr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700923 return check_condition_result;
924 }
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400925 len = min(((arr[2] << 8) + arr[3]) + 4, alloc_len);
Hannes Reinecke5a09e392006-10-20 09:58:47 +0200926 ret = fill_from_dev_buffer(scp, arr,
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400927 min(len, SDEBUG_MAX_INQ_ARR_SZ));
Hannes Reinecke5a09e392006-10-20 09:58:47 +0200928 kfree(arr);
929 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930 }
931 /* drops through here for a standard inquiry */
Martin Pittd9867882012-09-06 12:04:33 +0200932 arr[1] = scsi_debug_removable ? 0x80 : 0; /* Removable disk */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933 arr[2] = scsi_debug_scsi_level;
934 arr[3] = 2; /* response_data_format==2 */
935 arr[4] = SDEBUG_LONG_INQ_SZ - 5;
Martin K. Petersenc6a44282009-01-04 03:08:19 -0500936 arr[5] = scsi_debug_dif ? 1 : 0; /* PROTECT bit */
Hannes Reinecke5a09e392006-10-20 09:58:47 +0200937 if (0 == scsi_debug_vpd_use_hostno)
938 arr[5] = 0x10; /* claim: implicit TGPS */
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400939 arr[6] = 0x10; /* claim: MultiP */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940 /* arr[6] |= 0x40; ... claim: EncServ (enclosure services) */
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400941 arr[7] = 0xa; /* claim: LINKED + CMDQUE */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942 memcpy(&arr[8], inq_vendor_id, 8);
943 memcpy(&arr[16], inq_product_id, 16);
944 memcpy(&arr[32], inq_product_rev, 4);
945 /* version descriptors (2 bytes each) follow */
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400946 arr[58] = 0x0; arr[59] = 0x77; /* SAM-3 ANSI */
947 arr[60] = 0x3; arr[61] = 0x14; /* SPC-3 ANSI */
948 n = 62;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949 if (scsi_debug_ptype == 0) {
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400950 arr[n++] = 0x3; arr[n++] = 0x3d; /* SBC-2 ANSI */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951 } else if (scsi_debug_ptype == 1) {
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400952 arr[n++] = 0x3; arr[n++] = 0x60; /* SSC-2 no version */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953 }
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400954 arr[n++] = 0xc; arr[n++] = 0xf; /* SAS-1.1 rev 10 */
Hannes Reinecke5a09e392006-10-20 09:58:47 +0200955 ret = fill_from_dev_buffer(scp, arr,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956 min(alloc_len, SDEBUG_LONG_INQ_SZ));
Hannes Reinecke5a09e392006-10-20 09:58:47 +0200957 kfree(arr);
958 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700959}
960
961static int resp_requests(struct scsi_cmnd * scp,
962 struct sdebug_dev_info * devip)
963{
964 unsigned char * sbuff;
965 unsigned char *cmd = (unsigned char *)scp->cmnd;
966 unsigned char arr[SDEBUG_SENSE_LEN];
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400967 int want_dsense;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968 int len = 18;
969
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400970 memset(arr, 0, sizeof(arr));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971 if (devip->reset == 1)
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400972 mk_sense_buffer(devip, 0, NO_ADDITIONAL_SENSE, 0);
973 want_dsense = !!(cmd[1] & 1) || scsi_debug_dsense;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974 sbuff = devip->sense_buff;
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400975 if ((iec_m_pg[2] & 0x4) && (6 == (iec_m_pg[3] & 0xf))) {
976 if (want_dsense) {
977 arr[0] = 0x72;
978 arr[1] = 0x0; /* NO_SENSE in sense_key */
979 arr[2] = THRESHOLD_EXCEEDED;
980 arr[3] = 0xff; /* TEST set and MRIE==6 */
981 } else {
982 arr[0] = 0x70;
983 arr[2] = 0x0; /* NO_SENSE in sense_key */
984 arr[7] = 0xa; /* 18 byte sense buffer */
985 arr[12] = THRESHOLD_EXCEEDED;
986 arr[13] = 0xff; /* TEST set and MRIE==6 */
987 }
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400988 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989 memcpy(arr, sbuff, SDEBUG_SENSE_LEN);
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400990 if ((cmd[1] & 1) && (! scsi_debug_dsense)) {
991 /* DESC bit set and sense_buff in fixed format */
992 memset(arr, 0, sizeof(arr));
993 arr[0] = 0x72;
994 arr[1] = sbuff[2]; /* sense key */
995 arr[2] = sbuff[12]; /* asc */
996 arr[3] = sbuff[13]; /* ascq */
997 len = 8;
998 }
999 }
1000 mk_sense_buffer(devip, 0, NO_ADDITIONAL_SENSE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001001 return fill_from_dev_buffer(scp, arr, len);
1002}
1003
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001004static int resp_start_stop(struct scsi_cmnd * scp,
1005 struct sdebug_dev_info * devip)
1006{
1007 unsigned char *cmd = (unsigned char *)scp->cmnd;
1008 int power_cond, errsts, start;
1009
1010 if ((errsts = check_readiness(scp, 1, devip)))
1011 return errsts;
1012 power_cond = (cmd[4] & 0xf0) >> 4;
1013 if (power_cond) {
1014 mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
1015 0);
1016 return check_condition_result;
1017 }
1018 start = cmd[4] & 1;
1019 if (start == devip->stopped)
1020 devip->stopped = !start;
1021 return 0;
1022}
1023
FUJITA Tomonori28898872008-03-30 00:59:55 +09001024static sector_t get_sdebug_capacity(void)
1025{
1026 if (scsi_debug_virtual_gb > 0)
Douglas Gilbert5447ed62010-04-25 12:30:23 +02001027 return (sector_t)scsi_debug_virtual_gb *
1028 (1073741824 / scsi_debug_sector_size);
FUJITA Tomonori28898872008-03-30 00:59:55 +09001029 else
1030 return sdebug_store_sectors;
1031}
1032
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033#define SDEBUG_READCAP_ARR_SZ 8
1034static int resp_readcap(struct scsi_cmnd * scp,
1035 struct sdebug_dev_info * devip)
1036{
1037 unsigned char arr[SDEBUG_READCAP_ARR_SZ];
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001038 unsigned int capac;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039 int errsts;
1040
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001041 if ((errsts = check_readiness(scp, 1, devip)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042 return errsts;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001043 /* following just in case virtual_gb changed */
FUJITA Tomonori28898872008-03-30 00:59:55 +09001044 sdebug_capacity = get_sdebug_capacity();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045 memset(arr, 0, SDEBUG_READCAP_ARR_SZ);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001046 if (sdebug_capacity < 0xffffffff) {
1047 capac = (unsigned int)sdebug_capacity - 1;
1048 arr[0] = (capac >> 24);
1049 arr[1] = (capac >> 16) & 0xff;
1050 arr[2] = (capac >> 8) & 0xff;
1051 arr[3] = capac & 0xff;
1052 } else {
1053 arr[0] = 0xff;
1054 arr[1] = 0xff;
1055 arr[2] = 0xff;
1056 arr[3] = 0xff;
1057 }
Martin K. Petersen597136a2008-06-05 00:12:59 -04001058 arr[6] = (scsi_debug_sector_size >> 8) & 0xff;
1059 arr[7] = scsi_debug_sector_size & 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060 return fill_from_dev_buffer(scp, arr, SDEBUG_READCAP_ARR_SZ);
1061}
1062
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001063#define SDEBUG_READCAP16_ARR_SZ 32
1064static int resp_readcap16(struct scsi_cmnd * scp,
1065 struct sdebug_dev_info * devip)
1066{
1067 unsigned char *cmd = (unsigned char *)scp->cmnd;
1068 unsigned char arr[SDEBUG_READCAP16_ARR_SZ];
1069 unsigned long long capac;
1070 int errsts, k, alloc_len;
1071
1072 if ((errsts = check_readiness(scp, 1, devip)))
1073 return errsts;
1074 alloc_len = ((cmd[10] << 24) + (cmd[11] << 16) + (cmd[12] << 8)
1075 + cmd[13]);
1076 /* following just in case virtual_gb changed */
FUJITA Tomonori28898872008-03-30 00:59:55 +09001077 sdebug_capacity = get_sdebug_capacity();
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001078 memset(arr, 0, SDEBUG_READCAP16_ARR_SZ);
1079 capac = sdebug_capacity - 1;
1080 for (k = 0; k < 8; ++k, capac >>= 8)
1081 arr[7 - k] = capac & 0xff;
Martin K. Petersen597136a2008-06-05 00:12:59 -04001082 arr[8] = (scsi_debug_sector_size >> 24) & 0xff;
1083 arr[9] = (scsi_debug_sector_size >> 16) & 0xff;
1084 arr[10] = (scsi_debug_sector_size >> 8) & 0xff;
1085 arr[11] = scsi_debug_sector_size & 0xff;
Martin K. Petersenea61fca2009-05-15 00:40:33 -04001086 arr[13] = scsi_debug_physblk_exp & 0xf;
1087 arr[14] = (scsi_debug_lowest_aligned >> 8) & 0x3f;
Martin K. Petersen44d92692009-10-15 14:45:27 -04001088
Eric Sandeenbe1dd782012-03-08 00:03:59 -06001089 if (scsi_debug_lbp()) {
Martin K. Petersen5b94e232011-03-08 02:08:11 -05001090 arr[14] |= 0x80; /* LBPME */
Eric Sandeenbe1dd782012-03-08 00:03:59 -06001091 if (scsi_debug_lbprz)
1092 arr[14] |= 0x40; /* LBPRZ */
1093 }
Martin K. Petersen44d92692009-10-15 14:45:27 -04001094
Martin K. Petersenea61fca2009-05-15 00:40:33 -04001095 arr[15] = scsi_debug_lowest_aligned & 0xff;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001096
1097 if (scsi_debug_dif) {
1098 arr[12] = (scsi_debug_dif - 1) << 1; /* P_TYPE */
1099 arr[12] |= 1; /* PROT_EN */
1100 }
1101
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001102 return fill_from_dev_buffer(scp, arr,
1103 min(alloc_len, SDEBUG_READCAP16_ARR_SZ));
1104}
1105
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001106#define SDEBUG_MAX_TGTPGS_ARR_SZ 1412
1107
1108static int resp_report_tgtpgs(struct scsi_cmnd * scp,
1109 struct sdebug_dev_info * devip)
1110{
1111 unsigned char *cmd = (unsigned char *)scp->cmnd;
1112 unsigned char * arr;
1113 int host_no = devip->sdbg_host->shost->host_no;
1114 int n, ret, alen, rlen;
1115 int port_group_a, port_group_b, port_a, port_b;
1116
1117 alen = ((cmd[6] << 24) + (cmd[7] << 16) + (cmd[8] << 8)
1118 + cmd[9]);
1119
Douglas Gilbert6f3cbf52007-01-05 00:05:25 -05001120 arr = kzalloc(SDEBUG_MAX_TGTPGS_ARR_SZ, GFP_ATOMIC);
1121 if (! arr)
1122 return DID_REQUEUE << 16;
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001123 /*
1124 * EVPD page 0x88 states we have two ports, one
1125 * real and a fake port with no device connected.
1126 * So we create two port groups with one port each
1127 * and set the group with port B to unavailable.
1128 */
1129 port_a = 0x1; /* relative port A */
1130 port_b = 0x2; /* relative port B */
1131 port_group_a = (((host_no + 1) & 0x7f) << 8) +
1132 (devip->channel & 0x7f);
1133 port_group_b = (((host_no + 1) & 0x7f) << 8) +
1134 (devip->channel & 0x7f) + 0x80;
1135
1136 /*
1137 * The asymmetric access state is cycled according to the host_id.
1138 */
1139 n = 4;
1140 if (0 == scsi_debug_vpd_use_hostno) {
1141 arr[n++] = host_no % 3; /* Asymm access state */
1142 arr[n++] = 0x0F; /* claim: all states are supported */
1143 } else {
1144 arr[n++] = 0x0; /* Active/Optimized path */
1145 arr[n++] = 0x01; /* claim: only support active/optimized paths */
1146 }
1147 arr[n++] = (port_group_a >> 8) & 0xff;
1148 arr[n++] = port_group_a & 0xff;
1149 arr[n++] = 0; /* Reserved */
1150 arr[n++] = 0; /* Status code */
1151 arr[n++] = 0; /* Vendor unique */
1152 arr[n++] = 0x1; /* One port per group */
1153 arr[n++] = 0; /* Reserved */
1154 arr[n++] = 0; /* Reserved */
1155 arr[n++] = (port_a >> 8) & 0xff;
1156 arr[n++] = port_a & 0xff;
1157 arr[n++] = 3; /* Port unavailable */
1158 arr[n++] = 0x08; /* claim: only unavailalbe paths are supported */
1159 arr[n++] = (port_group_b >> 8) & 0xff;
1160 arr[n++] = port_group_b & 0xff;
1161 arr[n++] = 0; /* Reserved */
1162 arr[n++] = 0; /* Status code */
1163 arr[n++] = 0; /* Vendor unique */
1164 arr[n++] = 0x1; /* One port per group */
1165 arr[n++] = 0; /* Reserved */
1166 arr[n++] = 0; /* Reserved */
1167 arr[n++] = (port_b >> 8) & 0xff;
1168 arr[n++] = port_b & 0xff;
1169
1170 rlen = n - 4;
1171 arr[0] = (rlen >> 24) & 0xff;
1172 arr[1] = (rlen >> 16) & 0xff;
1173 arr[2] = (rlen >> 8) & 0xff;
1174 arr[3] = rlen & 0xff;
1175
1176 /*
1177 * Return the smallest value of either
1178 * - The allocated length
1179 * - The constructed command length
1180 * - The maximum array size
1181 */
1182 rlen = min(alen,n);
1183 ret = fill_from_dev_buffer(scp, arr,
1184 min(rlen, SDEBUG_MAX_TGTPGS_ARR_SZ));
1185 kfree(arr);
1186 return ret;
1187}
1188
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189/* <<Following mode page info copied from ST318451LW>> */
1190
1191static int resp_err_recov_pg(unsigned char * p, int pcontrol, int target)
1192{ /* Read-Write Error Recovery page for mode_sense */
1193 unsigned char err_recov_pg[] = {0x1, 0xa, 0xc0, 11, 240, 0, 0, 0,
1194 5, 0, 0xff, 0xff};
1195
1196 memcpy(p, err_recov_pg, sizeof(err_recov_pg));
1197 if (1 == pcontrol)
1198 memset(p + 2, 0, sizeof(err_recov_pg) - 2);
1199 return sizeof(err_recov_pg);
1200}
1201
1202static int resp_disconnect_pg(unsigned char * p, int pcontrol, int target)
1203{ /* Disconnect-Reconnect page for mode_sense */
1204 unsigned char disconnect_pg[] = {0x2, 0xe, 128, 128, 0, 10, 0, 0,
1205 0, 0, 0, 0, 0, 0, 0, 0};
1206
1207 memcpy(p, disconnect_pg, sizeof(disconnect_pg));
1208 if (1 == pcontrol)
1209 memset(p + 2, 0, sizeof(disconnect_pg) - 2);
1210 return sizeof(disconnect_pg);
1211}
1212
1213static int resp_format_pg(unsigned char * p, int pcontrol, int target)
1214{ /* Format device page for mode_sense */
Martin K. Petersen597136a2008-06-05 00:12:59 -04001215 unsigned char format_pg[] = {0x3, 0x16, 0, 0, 0, 0, 0, 0,
1216 0, 0, 0, 0, 0, 0, 0, 0,
1217 0, 0, 0, 0, 0x40, 0, 0, 0};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218
Martin K. Petersen597136a2008-06-05 00:12:59 -04001219 memcpy(p, format_pg, sizeof(format_pg));
1220 p[10] = (sdebug_sectors_per >> 8) & 0xff;
1221 p[11] = sdebug_sectors_per & 0xff;
1222 p[12] = (scsi_debug_sector_size >> 8) & 0xff;
1223 p[13] = scsi_debug_sector_size & 0xff;
Martin Pittd9867882012-09-06 12:04:33 +02001224 if (scsi_debug_removable)
Martin K. Petersen597136a2008-06-05 00:12:59 -04001225 p[20] |= 0x20; /* should agree with INQUIRY */
1226 if (1 == pcontrol)
1227 memset(p + 2, 0, sizeof(format_pg) - 2);
1228 return sizeof(format_pg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001229}
1230
1231static int resp_caching_pg(unsigned char * p, int pcontrol, int target)
1232{ /* Caching page for mode_sense */
1233 unsigned char caching_pg[] = {0x8, 18, 0x14, 0, 0xff, 0xff, 0, 0,
1234 0xff, 0xff, 0xff, 0xff, 0x80, 0x14, 0, 0, 0, 0, 0, 0};
1235
1236 memcpy(p, caching_pg, sizeof(caching_pg));
1237 if (1 == pcontrol)
1238 memset(p + 2, 0, sizeof(caching_pg) - 2);
1239 return sizeof(caching_pg);
1240}
1241
1242static int resp_ctrl_m_pg(unsigned char * p, int pcontrol, int target)
1243{ /* Control mode page for mode_sense */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001244 unsigned char ch_ctrl_m_pg[] = {/* 0xa, 10, */ 0x6, 0, 0, 0, 0, 0,
1245 0, 0, 0, 0};
1246 unsigned char d_ctrl_m_pg[] = {0xa, 10, 2, 0, 0, 0, 0, 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001247 0, 0, 0x2, 0x4b};
1248
1249 if (scsi_debug_dsense)
1250 ctrl_m_pg[2] |= 0x4;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001251 else
1252 ctrl_m_pg[2] &= ~0x4;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001253
1254 if (scsi_debug_ato)
1255 ctrl_m_pg[5] |= 0x80; /* ATO=1 */
1256
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257 memcpy(p, ctrl_m_pg, sizeof(ctrl_m_pg));
1258 if (1 == pcontrol)
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001259 memcpy(p + 2, ch_ctrl_m_pg, sizeof(ch_ctrl_m_pg));
1260 else if (2 == pcontrol)
1261 memcpy(p, d_ctrl_m_pg, sizeof(d_ctrl_m_pg));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262 return sizeof(ctrl_m_pg);
1263}
1264
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001265
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266static int resp_iec_m_pg(unsigned char * p, int pcontrol, int target)
1267{ /* Informational Exceptions control mode page for mode_sense */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001268 unsigned char ch_iec_m_pg[] = {/* 0x1c, 0xa, */ 0x4, 0xf, 0, 0, 0, 0,
1269 0, 0, 0x0, 0x0};
1270 unsigned char d_iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0,
1271 0, 0, 0x0, 0x0};
1272
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273 memcpy(p, iec_m_pg, sizeof(iec_m_pg));
1274 if (1 == pcontrol)
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001275 memcpy(p + 2, ch_iec_m_pg, sizeof(ch_iec_m_pg));
1276 else if (2 == pcontrol)
1277 memcpy(p, d_iec_m_pg, sizeof(d_iec_m_pg));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278 return sizeof(iec_m_pg);
1279}
1280
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001281static int resp_sas_sf_m_pg(unsigned char * p, int pcontrol, int target)
1282{ /* SAS SSP mode page - short format for mode_sense */
1283 unsigned char sas_sf_m_pg[] = {0x19, 0x6,
1284 0x6, 0x0, 0x7, 0xd0, 0x0, 0x0};
1285
1286 memcpy(p, sas_sf_m_pg, sizeof(sas_sf_m_pg));
1287 if (1 == pcontrol)
1288 memset(p + 2, 0, sizeof(sas_sf_m_pg) - 2);
1289 return sizeof(sas_sf_m_pg);
1290}
1291
1292
1293static int resp_sas_pcd_m_spg(unsigned char * p, int pcontrol, int target,
1294 int target_dev_id)
1295{ /* SAS phy control and discover mode page for mode_sense */
1296 unsigned char sas_pcd_m_pg[] = {0x59, 0x1, 0, 0x64, 0, 0x6, 0, 2,
1297 0, 0, 0, 0, 0x10, 0x9, 0x8, 0x0,
1298 0x52, 0x22, 0x22, 0x20, 0x0, 0x0, 0x0, 0x0,
1299 0x51, 0x11, 0x11, 0x10, 0x0, 0x0, 0x0, 0x1,
1300 0x2, 0, 0, 0, 0, 0, 0, 0,
1301 0x88, 0x99, 0, 0, 0, 0, 0, 0,
1302 0, 0, 0, 0, 0, 0, 0, 0,
1303 0, 1, 0, 0, 0x10, 0x9, 0x8, 0x0,
1304 0x52, 0x22, 0x22, 0x20, 0x0, 0x0, 0x0, 0x0,
1305 0x51, 0x11, 0x11, 0x10, 0x0, 0x0, 0x0, 0x1,
1306 0x3, 0, 0, 0, 0, 0, 0, 0,
1307 0x88, 0x99, 0, 0, 0, 0, 0, 0,
1308 0, 0, 0, 0, 0, 0, 0, 0,
1309 };
1310 int port_a, port_b;
1311
1312 port_a = target_dev_id + 1;
1313 port_b = port_a + 1;
1314 memcpy(p, sas_pcd_m_pg, sizeof(sas_pcd_m_pg));
1315 p[20] = (port_a >> 24);
1316 p[21] = (port_a >> 16) & 0xff;
1317 p[22] = (port_a >> 8) & 0xff;
1318 p[23] = port_a & 0xff;
1319 p[48 + 20] = (port_b >> 24);
1320 p[48 + 21] = (port_b >> 16) & 0xff;
1321 p[48 + 22] = (port_b >> 8) & 0xff;
1322 p[48 + 23] = port_b & 0xff;
1323 if (1 == pcontrol)
1324 memset(p + 4, 0, sizeof(sas_pcd_m_pg) - 4);
1325 return sizeof(sas_pcd_m_pg);
1326}
1327
1328static int resp_sas_sha_m_spg(unsigned char * p, int pcontrol)
1329{ /* SAS SSP shared protocol specific port mode subpage */
1330 unsigned char sas_sha_m_pg[] = {0x59, 0x2, 0, 0xc, 0, 0x6, 0x10, 0,
1331 0, 0, 0, 0, 0, 0, 0, 0,
1332 };
1333
1334 memcpy(p, sas_sha_m_pg, sizeof(sas_sha_m_pg));
1335 if (1 == pcontrol)
1336 memset(p + 4, 0, sizeof(sas_sha_m_pg) - 4);
1337 return sizeof(sas_sha_m_pg);
1338}
1339
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340#define SDEBUG_MAX_MSENSE_SZ 256
1341
1342static int resp_mode_sense(struct scsi_cmnd * scp, int target,
1343 struct sdebug_dev_info * devip)
1344{
Douglas Gilbert23183912006-09-16 20:30:47 -04001345 unsigned char dbd, llbaa;
1346 int pcontrol, pcode, subpcode, bd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347 unsigned char dev_spec;
Douglas Gilbert23183912006-09-16 20:30:47 -04001348 int k, alloc_len, msense_6, offset, len, errsts, target_dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349 unsigned char * ap;
1350 unsigned char arr[SDEBUG_MAX_MSENSE_SZ];
1351 unsigned char *cmd = (unsigned char *)scp->cmnd;
1352
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001353 if ((errsts = check_readiness(scp, 1, devip)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354 return errsts;
Douglas Gilbert23183912006-09-16 20:30:47 -04001355 dbd = !!(cmd[1] & 0x8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356 pcontrol = (cmd[2] & 0xc0) >> 6;
1357 pcode = cmd[2] & 0x3f;
1358 subpcode = cmd[3];
1359 msense_6 = (MODE_SENSE == cmd[0]);
Douglas Gilbert23183912006-09-16 20:30:47 -04001360 llbaa = msense_6 ? 0 : !!(cmd[1] & 0x10);
1361 if ((0 == scsi_debug_ptype) && (0 == dbd))
1362 bd_len = llbaa ? 16 : 8;
1363 else
1364 bd_len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365 alloc_len = msense_6 ? cmd[4] : ((cmd[7] << 8) | cmd[8]);
1366 memset(arr, 0, SDEBUG_MAX_MSENSE_SZ);
1367 if (0x3 == pcontrol) { /* Saving values not supported */
1368 mk_sense_buffer(devip, ILLEGAL_REQUEST, SAVING_PARAMS_UNSUP,
1369 0);
1370 return check_condition_result;
1371 }
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001372 target_dev_id = ((devip->sdbg_host->shost->host_no + 1) * 2000) +
1373 (devip->target * 1000) - 3;
Douglas Gilbert23183912006-09-16 20:30:47 -04001374 /* set DPOFUA bit for disks */
1375 if (0 == scsi_debug_ptype)
1376 dev_spec = (DEV_READONLY(target) ? 0x80 : 0x0) | 0x10;
1377 else
1378 dev_spec = 0x0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379 if (msense_6) {
1380 arr[2] = dev_spec;
Douglas Gilbert23183912006-09-16 20:30:47 -04001381 arr[3] = bd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001382 offset = 4;
1383 } else {
1384 arr[3] = dev_spec;
Douglas Gilbert23183912006-09-16 20:30:47 -04001385 if (16 == bd_len)
1386 arr[4] = 0x1; /* set LONGLBA bit */
1387 arr[7] = bd_len; /* assume 255 or less */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001388 offset = 8;
1389 }
1390 ap = arr + offset;
FUJITA Tomonori28898872008-03-30 00:59:55 +09001391 if ((bd_len > 0) && (!sdebug_capacity))
1392 sdebug_capacity = get_sdebug_capacity();
1393
Douglas Gilbert23183912006-09-16 20:30:47 -04001394 if (8 == bd_len) {
1395 if (sdebug_capacity > 0xfffffffe) {
1396 ap[0] = 0xff;
1397 ap[1] = 0xff;
1398 ap[2] = 0xff;
1399 ap[3] = 0xff;
1400 } else {
1401 ap[0] = (sdebug_capacity >> 24) & 0xff;
1402 ap[1] = (sdebug_capacity >> 16) & 0xff;
1403 ap[2] = (sdebug_capacity >> 8) & 0xff;
1404 ap[3] = sdebug_capacity & 0xff;
1405 }
Martin K. Petersen597136a2008-06-05 00:12:59 -04001406 ap[6] = (scsi_debug_sector_size >> 8) & 0xff;
1407 ap[7] = scsi_debug_sector_size & 0xff;
Douglas Gilbert23183912006-09-16 20:30:47 -04001408 offset += bd_len;
1409 ap = arr + offset;
1410 } else if (16 == bd_len) {
1411 unsigned long long capac = sdebug_capacity;
1412
1413 for (k = 0; k < 8; ++k, capac >>= 8)
1414 ap[7 - k] = capac & 0xff;
Martin K. Petersen597136a2008-06-05 00:12:59 -04001415 ap[12] = (scsi_debug_sector_size >> 24) & 0xff;
1416 ap[13] = (scsi_debug_sector_size >> 16) & 0xff;
1417 ap[14] = (scsi_debug_sector_size >> 8) & 0xff;
1418 ap[15] = scsi_debug_sector_size & 0xff;
Douglas Gilbert23183912006-09-16 20:30:47 -04001419 offset += bd_len;
1420 ap = arr + offset;
1421 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001422
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001423 if ((subpcode > 0x0) && (subpcode < 0xff) && (0x19 != pcode)) {
1424 /* TODO: Control Extension page */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001425 mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
1426 0);
1427 return check_condition_result;
1428 }
1429 switch (pcode) {
1430 case 0x1: /* Read-Write error recovery page, direct access */
1431 len = resp_err_recov_pg(ap, pcontrol, target);
1432 offset += len;
1433 break;
1434 case 0x2: /* Disconnect-Reconnect page, all devices */
1435 len = resp_disconnect_pg(ap, pcontrol, target);
1436 offset += len;
1437 break;
1438 case 0x3: /* Format device page, direct access */
1439 len = resp_format_pg(ap, pcontrol, target);
1440 offset += len;
1441 break;
1442 case 0x8: /* Caching page, direct access */
1443 len = resp_caching_pg(ap, pcontrol, target);
1444 offset += len;
1445 break;
1446 case 0xa: /* Control Mode page, all devices */
1447 len = resp_ctrl_m_pg(ap, pcontrol, target);
1448 offset += len;
1449 break;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001450 case 0x19: /* if spc==1 then sas phy, control+discover */
1451 if ((subpcode > 0x2) && (subpcode < 0xff)) {
1452 mk_sense_buffer(devip, ILLEGAL_REQUEST,
1453 INVALID_FIELD_IN_CDB, 0);
1454 return check_condition_result;
1455 }
1456 len = 0;
1457 if ((0x0 == subpcode) || (0xff == subpcode))
1458 len += resp_sas_sf_m_pg(ap + len, pcontrol, target);
1459 if ((0x1 == subpcode) || (0xff == subpcode))
1460 len += resp_sas_pcd_m_spg(ap + len, pcontrol, target,
1461 target_dev_id);
1462 if ((0x2 == subpcode) || (0xff == subpcode))
1463 len += resp_sas_sha_m_spg(ap + len, pcontrol);
1464 offset += len;
1465 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466 case 0x1c: /* Informational Exceptions Mode page, all devices */
1467 len = resp_iec_m_pg(ap, pcontrol, target);
1468 offset += len;
1469 break;
1470 case 0x3f: /* Read all Mode pages */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001471 if ((0 == subpcode) || (0xff == subpcode)) {
1472 len = resp_err_recov_pg(ap, pcontrol, target);
1473 len += resp_disconnect_pg(ap + len, pcontrol, target);
1474 len += resp_format_pg(ap + len, pcontrol, target);
1475 len += resp_caching_pg(ap + len, pcontrol, target);
1476 len += resp_ctrl_m_pg(ap + len, pcontrol, target);
1477 len += resp_sas_sf_m_pg(ap + len, pcontrol, target);
1478 if (0xff == subpcode) {
1479 len += resp_sas_pcd_m_spg(ap + len, pcontrol,
1480 target, target_dev_id);
1481 len += resp_sas_sha_m_spg(ap + len, pcontrol);
1482 }
1483 len += resp_iec_m_pg(ap + len, pcontrol, target);
1484 } else {
1485 mk_sense_buffer(devip, ILLEGAL_REQUEST,
1486 INVALID_FIELD_IN_CDB, 0);
1487 return check_condition_result;
1488 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001489 offset += len;
1490 break;
1491 default:
1492 mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
1493 0);
1494 return check_condition_result;
1495 }
1496 if (msense_6)
1497 arr[0] = offset - 1;
1498 else {
1499 arr[0] = ((offset - 2) >> 8) & 0xff;
1500 arr[1] = (offset - 2) & 0xff;
1501 }
1502 return fill_from_dev_buffer(scp, arr, min(alloc_len, offset));
1503}
1504
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001505#define SDEBUG_MAX_MSELECT_SZ 512
1506
1507static int resp_mode_select(struct scsi_cmnd * scp, int mselect6,
1508 struct sdebug_dev_info * devip)
1509{
1510 int pf, sp, ps, md_len, bd_len, off, spf, pg_len;
1511 int param_len, res, errsts, mpage;
1512 unsigned char arr[SDEBUG_MAX_MSELECT_SZ];
1513 unsigned char *cmd = (unsigned char *)scp->cmnd;
1514
1515 if ((errsts = check_readiness(scp, 1, devip)))
1516 return errsts;
1517 memset(arr, 0, sizeof(arr));
1518 pf = cmd[1] & 0x10;
1519 sp = cmd[1] & 0x1;
1520 param_len = mselect6 ? cmd[4] : ((cmd[7] << 8) + cmd[8]);
1521 if ((0 == pf) || sp || (param_len > SDEBUG_MAX_MSELECT_SZ)) {
1522 mk_sense_buffer(devip, ILLEGAL_REQUEST,
1523 INVALID_FIELD_IN_CDB, 0);
1524 return check_condition_result;
1525 }
1526 res = fetch_to_dev_buffer(scp, arr, param_len);
1527 if (-1 == res)
1528 return (DID_ERROR << 16);
1529 else if ((res < param_len) &&
1530 (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
1531 printk(KERN_INFO "scsi_debug: mode_select: cdb indicated=%d, "
1532 " IO sent=%d bytes\n", param_len, res);
1533 md_len = mselect6 ? (arr[0] + 1) : ((arr[0] << 8) + arr[1] + 2);
1534 bd_len = mselect6 ? arr[3] : ((arr[6] << 8) + arr[7]);
Douglas Gilbert23183912006-09-16 20:30:47 -04001535 if (md_len > 2) {
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001536 mk_sense_buffer(devip, ILLEGAL_REQUEST,
1537 INVALID_FIELD_IN_PARAM_LIST, 0);
1538 return check_condition_result;
1539 }
1540 off = bd_len + (mselect6 ? 4 : 8);
1541 mpage = arr[off] & 0x3f;
1542 ps = !!(arr[off] & 0x80);
1543 if (ps) {
1544 mk_sense_buffer(devip, ILLEGAL_REQUEST,
1545 INVALID_FIELD_IN_PARAM_LIST, 0);
1546 return check_condition_result;
1547 }
1548 spf = !!(arr[off] & 0x40);
1549 pg_len = spf ? ((arr[off + 2] << 8) + arr[off + 3] + 4) :
1550 (arr[off + 1] + 2);
1551 if ((pg_len + off) > param_len) {
1552 mk_sense_buffer(devip, ILLEGAL_REQUEST,
1553 PARAMETER_LIST_LENGTH_ERR, 0);
1554 return check_condition_result;
1555 }
1556 switch (mpage) {
1557 case 0xa: /* Control Mode page */
1558 if (ctrl_m_pg[1] == arr[off + 1]) {
1559 memcpy(ctrl_m_pg + 2, arr + off + 2,
1560 sizeof(ctrl_m_pg) - 2);
1561 scsi_debug_dsense = !!(ctrl_m_pg[2] & 0x4);
1562 return 0;
1563 }
1564 break;
1565 case 0x1c: /* Informational Exceptions Mode page */
1566 if (iec_m_pg[1] == arr[off + 1]) {
1567 memcpy(iec_m_pg + 2, arr + off + 2,
1568 sizeof(iec_m_pg) - 2);
1569 return 0;
1570 }
1571 break;
1572 default:
1573 break;
1574 }
1575 mk_sense_buffer(devip, ILLEGAL_REQUEST,
1576 INVALID_FIELD_IN_PARAM_LIST, 0);
1577 return check_condition_result;
1578}
1579
1580static int resp_temp_l_pg(unsigned char * arr)
1581{
1582 unsigned char temp_l_pg[] = {0x0, 0x0, 0x3, 0x2, 0x0, 38,
1583 0x0, 0x1, 0x3, 0x2, 0x0, 65,
1584 };
1585
1586 memcpy(arr, temp_l_pg, sizeof(temp_l_pg));
1587 return sizeof(temp_l_pg);
1588}
1589
1590static int resp_ie_l_pg(unsigned char * arr)
1591{
1592 unsigned char ie_l_pg[] = {0x0, 0x0, 0x3, 0x3, 0x0, 0x0, 38,
1593 };
1594
1595 memcpy(arr, ie_l_pg, sizeof(ie_l_pg));
1596 if (iec_m_pg[2] & 0x4) { /* TEST bit set */
1597 arr[4] = THRESHOLD_EXCEEDED;
1598 arr[5] = 0xff;
1599 }
1600 return sizeof(ie_l_pg);
1601}
1602
1603#define SDEBUG_MAX_LSENSE_SZ 512
1604
1605static int resp_log_sense(struct scsi_cmnd * scp,
1606 struct sdebug_dev_info * devip)
1607{
Douglas Gilbert23183912006-09-16 20:30:47 -04001608 int ppc, sp, pcontrol, pcode, subpcode, alloc_len, errsts, len, n;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001609 unsigned char arr[SDEBUG_MAX_LSENSE_SZ];
1610 unsigned char *cmd = (unsigned char *)scp->cmnd;
1611
1612 if ((errsts = check_readiness(scp, 1, devip)))
1613 return errsts;
1614 memset(arr, 0, sizeof(arr));
1615 ppc = cmd[1] & 0x2;
1616 sp = cmd[1] & 0x1;
1617 if (ppc || sp) {
1618 mk_sense_buffer(devip, ILLEGAL_REQUEST,
1619 INVALID_FIELD_IN_CDB, 0);
1620 return check_condition_result;
1621 }
1622 pcontrol = (cmd[2] & 0xc0) >> 6;
1623 pcode = cmd[2] & 0x3f;
Douglas Gilbert23183912006-09-16 20:30:47 -04001624 subpcode = cmd[3] & 0xff;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001625 alloc_len = (cmd[7] << 8) + cmd[8];
1626 arr[0] = pcode;
Douglas Gilbert23183912006-09-16 20:30:47 -04001627 if (0 == subpcode) {
1628 switch (pcode) {
1629 case 0x0: /* Supported log pages log page */
1630 n = 4;
1631 arr[n++] = 0x0; /* this page */
1632 arr[n++] = 0xd; /* Temperature */
1633 arr[n++] = 0x2f; /* Informational exceptions */
1634 arr[3] = n - 4;
1635 break;
1636 case 0xd: /* Temperature log page */
1637 arr[3] = resp_temp_l_pg(arr + 4);
1638 break;
1639 case 0x2f: /* Informational exceptions log page */
1640 arr[3] = resp_ie_l_pg(arr + 4);
1641 break;
1642 default:
1643 mk_sense_buffer(devip, ILLEGAL_REQUEST,
1644 INVALID_FIELD_IN_CDB, 0);
1645 return check_condition_result;
1646 }
1647 } else if (0xff == subpcode) {
1648 arr[0] |= 0x40;
1649 arr[1] = subpcode;
1650 switch (pcode) {
1651 case 0x0: /* Supported log pages and subpages log page */
1652 n = 4;
1653 arr[n++] = 0x0;
1654 arr[n++] = 0x0; /* 0,0 page */
1655 arr[n++] = 0x0;
1656 arr[n++] = 0xff; /* this page */
1657 arr[n++] = 0xd;
1658 arr[n++] = 0x0; /* Temperature */
1659 arr[n++] = 0x2f;
1660 arr[n++] = 0x0; /* Informational exceptions */
1661 arr[3] = n - 4;
1662 break;
1663 case 0xd: /* Temperature subpages */
1664 n = 4;
1665 arr[n++] = 0xd;
1666 arr[n++] = 0x0; /* Temperature */
1667 arr[3] = n - 4;
1668 break;
1669 case 0x2f: /* Informational exceptions subpages */
1670 n = 4;
1671 arr[n++] = 0x2f;
1672 arr[n++] = 0x0; /* Informational exceptions */
1673 arr[3] = n - 4;
1674 break;
1675 default:
1676 mk_sense_buffer(devip, ILLEGAL_REQUEST,
1677 INVALID_FIELD_IN_CDB, 0);
1678 return check_condition_result;
1679 }
1680 } else {
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001681 mk_sense_buffer(devip, ILLEGAL_REQUEST,
1682 INVALID_FIELD_IN_CDB, 0);
1683 return check_condition_result;
1684 }
1685 len = min(((arr[2] << 8) + arr[3]) + 4, alloc_len);
1686 return fill_from_dev_buffer(scp, arr,
1687 min(len, SDEBUG_MAX_INQ_ARR_SZ));
1688}
1689
FUJITA Tomonori19789102008-03-30 00:59:56 +09001690static int check_device_access_params(struct sdebug_dev_info *devi,
1691 unsigned long long lba, unsigned int num)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001692{
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001693 if (lba + num > sdebug_capacity) {
FUJITA Tomonori19789102008-03-30 00:59:56 +09001694 mk_sense_buffer(devi, ILLEGAL_REQUEST, ADDR_OUT_OF_RANGE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001695 return check_condition_result;
1696 }
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001697 /* transfer length excessive (tie in to block limits VPD page) */
1698 if (num > sdebug_store_sectors) {
FUJITA Tomonori19789102008-03-30 00:59:56 +09001699 mk_sense_buffer(devi, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001700 return check_condition_result;
1701 }
FUJITA Tomonori19789102008-03-30 00:59:56 +09001702 return 0;
1703}
1704
Akinobu Mitaa4517512013-07-08 16:01:57 -07001705/* Returns number of bytes copied or -1 if error. */
FUJITA Tomonori19789102008-03-30 00:59:56 +09001706static int do_device_access(struct scsi_cmnd *scmd,
1707 struct sdebug_dev_info *devi,
1708 unsigned long long lba, unsigned int num, int write)
1709{
1710 int ret;
Darrick J. Wonga361cc02011-01-31 18:47:54 -08001711 unsigned long long block, rest = 0;
Akinobu Mitaa4517512013-07-08 16:01:57 -07001712 struct scsi_data_buffer *sdb;
1713 enum dma_data_direction dir;
1714 size_t (*func)(struct scatterlist *, unsigned int, void *, size_t,
1715 off_t);
FUJITA Tomonori19789102008-03-30 00:59:56 +09001716
Akinobu Mitaa4517512013-07-08 16:01:57 -07001717 if (write) {
1718 sdb = scsi_out(scmd);
1719 dir = DMA_TO_DEVICE;
1720 func = sg_pcopy_to_buffer;
1721 } else {
1722 sdb = scsi_in(scmd);
1723 dir = DMA_FROM_DEVICE;
1724 func = sg_pcopy_from_buffer;
1725 }
1726
1727 if (!sdb->length)
1728 return 0;
1729 if (!(scsi_bidi_cmnd(scmd) || scmd->sc_data_direction == dir))
1730 return -1;
FUJITA Tomonori19789102008-03-30 00:59:56 +09001731
1732 block = do_div(lba, sdebug_store_sectors);
1733 if (block + num > sdebug_store_sectors)
1734 rest = block + num - sdebug_store_sectors;
1735
Akinobu Mitaa4517512013-07-08 16:01:57 -07001736 ret = func(sdb->table.sgl, sdb->table.nents,
1737 fake_storep + (block * scsi_debug_sector_size),
1738 (num - rest) * scsi_debug_sector_size, 0);
1739 if (ret != (num - rest) * scsi_debug_sector_size)
1740 return ret;
1741
1742 if (rest) {
1743 ret += func(sdb->table.sgl, sdb->table.nents,
1744 fake_storep, rest * scsi_debug_sector_size,
1745 (num - rest) * scsi_debug_sector_size);
1746 }
FUJITA Tomonori19789102008-03-30 00:59:56 +09001747
1748 return ret;
1749}
1750
Akinobu Mita51d648a2013-09-18 21:27:28 +09001751static __be16 dif_compute_csum(const void *buf, int len)
Akinobu Mitabeb40ea2013-06-29 17:59:19 +09001752{
Akinobu Mita51d648a2013-09-18 21:27:28 +09001753 __be16 csum;
Akinobu Mitabeb40ea2013-06-29 17:59:19 +09001754
Akinobu Mita51d648a2013-09-18 21:27:28 +09001755 if (scsi_debug_guard)
1756 csum = (__force __be16)ip_compute_csum(buf, len);
1757 else
Akinobu Mitabeb40ea2013-06-29 17:59:19 +09001758 csum = cpu_to_be16(crc_t10dif(buf, len));
Akinobu Mita51d648a2013-09-18 21:27:28 +09001759
Akinobu Mitabeb40ea2013-06-29 17:59:19 +09001760 return csum;
1761}
1762
1763static int dif_verify(struct sd_dif_tuple *sdt, const void *data,
1764 sector_t sector, u32 ei_lba)
1765{
Akinobu Mita51d648a2013-09-18 21:27:28 +09001766 __be16 csum = dif_compute_csum(data, scsi_debug_sector_size);
Akinobu Mitabeb40ea2013-06-29 17:59:19 +09001767
1768 if (sdt->guard_tag != csum) {
1769 pr_err("%s: GUARD check failed on sector %lu rcvd 0x%04x, data 0x%04x\n",
1770 __func__,
1771 (unsigned long)sector,
1772 be16_to_cpu(sdt->guard_tag),
1773 be16_to_cpu(csum));
1774 return 0x01;
1775 }
1776 if (scsi_debug_dif == SD_DIF_TYPE1_PROTECTION &&
1777 be32_to_cpu(sdt->ref_tag) != (sector & 0xffffffff)) {
1778 pr_err("%s: REF check failed on sector %lu\n",
1779 __func__, (unsigned long)sector);
1780 return 0x03;
1781 }
1782 if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
1783 be32_to_cpu(sdt->ref_tag) != ei_lba) {
1784 pr_err("%s: REF check failed on sector %lu\n",
1785 __func__, (unsigned long)sector);
Akinobu Mitabeb40ea2013-06-29 17:59:19 +09001786 return 0x03;
1787 }
1788 return 0;
1789}
1790
Akinobu Mitabb8c0632013-09-18 21:27:25 +09001791static void dif_copy_prot(struct scsi_cmnd *SCpnt, sector_t sector,
Akinobu Mita65f72f2a2013-09-18 21:27:26 +09001792 unsigned int sectors, bool read)
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001793{
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09001794 size_t resid;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001795 void *paddr;
Akinobu Mita14faa942013-09-18 21:27:24 +09001796 const void *dif_store_end = dif_storep + sdebug_store_sectors;
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09001797 struct sg_mapping_iter miter;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001798
Akinobu Mitae18d8be2013-06-29 17:59:18 +09001799 /* Bytes of protection data to copy into sgl */
1800 resid = sectors * sizeof(*dif_storep);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001801
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09001802 sg_miter_start(&miter, scsi_prot_sglist(SCpnt),
1803 scsi_prot_sg_count(SCpnt), SG_MITER_ATOMIC |
1804 (read ? SG_MITER_TO_SG : SG_MITER_FROM_SG));
1805
1806 while (sg_miter_next(&miter) && resid > 0) {
1807 size_t len = min(miter.length, resid);
Akinobu Mita14faa942013-09-18 21:27:24 +09001808 void *start = dif_store(sector);
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09001809 size_t rest = 0;
Akinobu Mita14faa942013-09-18 21:27:24 +09001810
1811 if (dif_store_end < start + len)
1812 rest = start + len - dif_store_end;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001813
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09001814 paddr = miter.addr;
Akinobu Mita14faa942013-09-18 21:27:24 +09001815
Akinobu Mita65f72f2a2013-09-18 21:27:26 +09001816 if (read)
1817 memcpy(paddr, start, len - rest);
1818 else
1819 memcpy(start, paddr, len - rest);
1820
1821 if (rest) {
1822 if (read)
1823 memcpy(paddr + len - rest, dif_storep, rest);
1824 else
1825 memcpy(dif_storep, paddr + len - rest, rest);
1826 }
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001827
Akinobu Mitae18d8be2013-06-29 17:59:18 +09001828 sector += len / sizeof(*dif_storep);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001829 resid -= len;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001830 }
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09001831 sg_miter_stop(&miter);
Akinobu Mitabb8c0632013-09-18 21:27:25 +09001832}
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001833
Akinobu Mitabb8c0632013-09-18 21:27:25 +09001834static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec,
1835 unsigned int sectors, u32 ei_lba)
1836{
1837 unsigned int i;
1838 struct sd_dif_tuple *sdt;
1839 sector_t sector;
1840
Akinobu Mitac45eabec2014-02-26 22:56:58 +09001841 for (i = 0; i < sectors; i++, ei_lba++) {
Akinobu Mitabb8c0632013-09-18 21:27:25 +09001842 int ret;
1843
1844 sector = start_sec + i;
1845 sdt = dif_store(sector);
1846
Akinobu Mita51d648a2013-09-18 21:27:28 +09001847 if (sdt->app_tag == cpu_to_be16(0xffff))
Akinobu Mitabb8c0632013-09-18 21:27:25 +09001848 continue;
1849
1850 ret = dif_verify(sdt, fake_store(sector), sector, ei_lba);
1851 if (ret) {
1852 dif_errors++;
1853 return ret;
1854 }
Akinobu Mitabb8c0632013-09-18 21:27:25 +09001855 }
1856
Akinobu Mita65f72f2a2013-09-18 21:27:26 +09001857 dif_copy_prot(SCpnt, start_sec, sectors, true);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001858 dix_reads++;
1859
1860 return 0;
1861}
1862
FUJITA Tomonori19789102008-03-30 00:59:56 +09001863static int resp_read(struct scsi_cmnd *SCpnt, unsigned long long lba,
Martin K. Petersen395cef02009-09-18 17:33:03 -04001864 unsigned int num, struct sdebug_dev_info *devip,
1865 u32 ei_lba)
FUJITA Tomonori19789102008-03-30 00:59:56 +09001866{
1867 unsigned long iflags;
1868 int ret;
1869
1870 ret = check_device_access_params(devip, lba, num);
1871 if (ret)
1872 return ret;
1873
Linus Torvalds1da177e2005-04-16 15:20:36 -07001874 if ((SCSI_DEBUG_OPT_MEDIUM_ERR & scsi_debug_opts) &&
Douglas Gilbert32f7ef72011-03-11 10:43:35 -05001875 (lba <= (OPT_MEDIUM_ERR_ADDR + OPT_MEDIUM_ERR_NUM - 1)) &&
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001876 ((lba + num) > OPT_MEDIUM_ERR_ADDR)) {
1877 /* claim unrecoverable read error */
Douglas Gilbert32f7ef72011-03-11 10:43:35 -05001878 mk_sense_buffer(devip, MEDIUM_ERROR, UNRECOVERED_READ_ERR, 0);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001879 /* set info field and valid bit for fixed descriptor */
1880 if (0x70 == (devip->sense_buff[0] & 0x7f)) {
1881 devip->sense_buff[0] |= 0x80; /* Valid bit */
Douglas Gilbert32f7ef72011-03-11 10:43:35 -05001882 ret = (lba < OPT_MEDIUM_ERR_ADDR)
1883 ? OPT_MEDIUM_ERR_ADDR : (int)lba;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001884 devip->sense_buff[3] = (ret >> 24) & 0xff;
1885 devip->sense_buff[4] = (ret >> 16) & 0xff;
1886 devip->sense_buff[5] = (ret >> 8) & 0xff;
1887 devip->sense_buff[6] = ret & 0xff;
1888 }
Douglas Gilberta87e3a62010-12-17 19:16:06 -05001889 scsi_set_resid(SCpnt, scsi_bufflen(SCpnt));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001890 return check_condition_result;
1891 }
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001892
Akinobu Mita6c78cc02014-02-26 22:57:03 +09001893 read_lock_irqsave(&atomic_rw, iflags);
1894
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001895 /* DIX + T10 DIF */
1896 if (scsi_debug_dix && scsi_prot_sg_count(SCpnt)) {
Martin K. Petersen395cef02009-09-18 17:33:03 -04001897 int prot_ret = prot_verify_read(SCpnt, lba, num, ei_lba);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001898
1899 if (prot_ret) {
Akinobu Mita6c78cc02014-02-26 22:57:03 +09001900 read_unlock_irqrestore(&atomic_rw, iflags);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001901 mk_sense_buffer(devip, ABORTED_COMMAND, 0x10, prot_ret);
1902 return illegal_condition_result;
1903 }
1904 }
1905
FUJITA Tomonori19789102008-03-30 00:59:56 +09001906 ret = do_device_access(SCpnt, devip, lba, num, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001907 read_unlock_irqrestore(&atomic_rw, iflags);
Akinobu Mitaa4517512013-07-08 16:01:57 -07001908 if (ret == -1)
1909 return DID_ERROR << 16;
1910
1911 scsi_in(SCpnt)->resid = scsi_bufflen(SCpnt) - ret;
1912
1913 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001914}
1915
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001916void dump_sector(unsigned char *buf, int len)
1917{
1918 int i, j;
1919
1920 printk(KERN_ERR ">>> Sector Dump <<<\n");
1921
1922 for (i = 0 ; i < len ; i += 16) {
1923 printk(KERN_ERR "%04d: ", i);
1924
1925 for (j = 0 ; j < 16 ; j++) {
1926 unsigned char c = buf[i+j];
1927 if (c >= 0x20 && c < 0x7e)
1928 printk(" %c ", buf[i+j]);
1929 else
1930 printk("%02x ", buf[i+j]);
1931 }
1932
1933 printk("\n");
1934 }
1935}
1936
1937static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec,
Martin K. Petersen395cef02009-09-18 17:33:03 -04001938 unsigned int sectors, u32 ei_lba)
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001939{
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09001940 int ret;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001941 struct sd_dif_tuple *sdt;
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09001942 void *daddr;
Akinobu Mita65f72f2a2013-09-18 21:27:26 +09001943 sector_t sector = start_sec;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001944 int ppage_offset;
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09001945 int dpage_offset;
1946 struct sg_mapping_iter diter;
1947 struct sg_mapping_iter piter;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001948
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001949 BUG_ON(scsi_sg_count(SCpnt) == 0);
1950 BUG_ON(scsi_prot_sg_count(SCpnt) == 0);
1951
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09001952 sg_miter_start(&piter, scsi_prot_sglist(SCpnt),
1953 scsi_prot_sg_count(SCpnt),
1954 SG_MITER_ATOMIC | SG_MITER_FROM_SG);
1955 sg_miter_start(&diter, scsi_sglist(SCpnt), scsi_sg_count(SCpnt),
1956 SG_MITER_ATOMIC | SG_MITER_FROM_SG);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001957
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09001958 /* For each protection page */
1959 while (sg_miter_next(&piter)) {
1960 dpage_offset = 0;
1961 if (WARN_ON(!sg_miter_next(&diter))) {
1962 ret = 0x01;
1963 goto out;
1964 }
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001965
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09001966 for (ppage_offset = 0; ppage_offset < piter.length;
1967 ppage_offset += sizeof(struct sd_dif_tuple)) {
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001968 /* If we're at the end of the current
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09001969 * data page advance to the next one
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001970 */
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09001971 if (dpage_offset >= diter.length) {
1972 if (WARN_ON(!sg_miter_next(&diter))) {
1973 ret = 0x01;
1974 goto out;
1975 }
1976 dpage_offset = 0;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001977 }
1978
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09001979 sdt = piter.addr + ppage_offset;
1980 daddr = diter.addr + dpage_offset;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001981
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09001982 ret = dif_verify(sdt, daddr, sector, ei_lba);
Akinobu Mitabeb40ea2013-06-29 17:59:19 +09001983 if (ret) {
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09001984 dump_sector(daddr, scsi_debug_sector_size);
Martin K. Petersen395cef02009-09-18 17:33:03 -04001985 goto out;
1986 }
1987
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001988 sector++;
Martin K. Petersen395cef02009-09-18 17:33:03 -04001989 ei_lba++;
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09001990 dpage_offset += scsi_debug_sector_size;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001991 }
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09001992 diter.consumed = dpage_offset;
1993 sg_miter_stop(&diter);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001994 }
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09001995 sg_miter_stop(&piter);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001996
Akinobu Mita65f72f2a2013-09-18 21:27:26 +09001997 dif_copy_prot(SCpnt, start_sec, sectors, false);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001998 dix_writes++;
1999
2000 return 0;
2001
2002out:
2003 dif_errors++;
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002004 sg_miter_stop(&diter);
2005 sg_miter_stop(&piter);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002006 return ret;
2007}
2008
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002009static unsigned long lba_to_map_index(sector_t lba)
2010{
2011 if (scsi_debug_unmap_alignment) {
2012 lba += scsi_debug_unmap_granularity -
2013 scsi_debug_unmap_alignment;
2014 }
2015 do_div(lba, scsi_debug_unmap_granularity);
2016
2017 return lba;
2018}
2019
2020static sector_t map_index_to_lba(unsigned long index)
2021{
Akinobu Mitaa027b5b2013-08-26 22:08:41 +09002022 sector_t lba = index * scsi_debug_unmap_granularity;
2023
2024 if (scsi_debug_unmap_alignment) {
2025 lba -= scsi_debug_unmap_granularity -
2026 scsi_debug_unmap_alignment;
2027 }
2028
2029 return lba;
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002030}
2031
Martin K. Petersen44d92692009-10-15 14:45:27 -04002032static unsigned int map_state(sector_t lba, unsigned int *num)
2033{
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002034 sector_t end;
2035 unsigned int mapped;
2036 unsigned long index;
2037 unsigned long next;
Martin K. Petersen44d92692009-10-15 14:45:27 -04002038
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002039 index = lba_to_map_index(lba);
2040 mapped = test_bit(index, map_storep);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002041
2042 if (mapped)
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002043 next = find_next_zero_bit(map_storep, map_size, index);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002044 else
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002045 next = find_next_bit(map_storep, map_size, index);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002046
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002047 end = min_t(sector_t, sdebug_store_sectors, map_index_to_lba(next));
Martin K. Petersen44d92692009-10-15 14:45:27 -04002048 *num = end - lba;
2049
2050 return mapped;
2051}
2052
2053static void map_region(sector_t lba, unsigned int len)
2054{
Martin K. Petersen44d92692009-10-15 14:45:27 -04002055 sector_t end = lba + len;
2056
Martin K. Petersen44d92692009-10-15 14:45:27 -04002057 while (lba < end) {
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002058 unsigned long index = lba_to_map_index(lba);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002059
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002060 if (index < map_size)
2061 set_bit(index, map_storep);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002062
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002063 lba = map_index_to_lba(index + 1);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002064 }
2065}
2066
2067static void unmap_region(sector_t lba, unsigned int len)
2068{
Martin K. Petersen44d92692009-10-15 14:45:27 -04002069 sector_t end = lba + len;
2070
Martin K. Petersen44d92692009-10-15 14:45:27 -04002071 while (lba < end) {
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002072 unsigned long index = lba_to_map_index(lba);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002073
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002074 if (lba == map_index_to_lba(index) &&
2075 lba + scsi_debug_unmap_granularity <= end &&
2076 index < map_size) {
2077 clear_bit(index, map_storep);
2078 if (scsi_debug_lbprz) {
Eric Sandeenbe1dd782012-03-08 00:03:59 -06002079 memset(fake_storep +
Akinobu Mitacc34a8e2013-04-16 22:11:57 +09002080 lba * scsi_debug_sector_size, 0,
2081 scsi_debug_sector_size *
2082 scsi_debug_unmap_granularity);
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002083 }
Akinobu Mitae9926b42013-06-29 17:59:17 +09002084 if (dif_storep) {
2085 memset(dif_storep + lba, 0xff,
2086 sizeof(*dif_storep) *
2087 scsi_debug_unmap_granularity);
2088 }
Eric Sandeenbe1dd782012-03-08 00:03:59 -06002089 }
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002090 lba = map_index_to_lba(index + 1);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002091 }
2092}
2093
FUJITA Tomonori19789102008-03-30 00:59:56 +09002094static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba,
Martin K. Petersen395cef02009-09-18 17:33:03 -04002095 unsigned int num, struct sdebug_dev_info *devip,
2096 u32 ei_lba)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002097{
2098 unsigned long iflags;
FUJITA Tomonori19789102008-03-30 00:59:56 +09002099 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002100
FUJITA Tomonori19789102008-03-30 00:59:56 +09002101 ret = check_device_access_params(devip, lba, num);
2102 if (ret)
2103 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002104
Akinobu Mita6c78cc02014-02-26 22:57:03 +09002105 write_lock_irqsave(&atomic_rw, iflags);
2106
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002107 /* DIX + T10 DIF */
2108 if (scsi_debug_dix && scsi_prot_sg_count(SCpnt)) {
Martin K. Petersen395cef02009-09-18 17:33:03 -04002109 int prot_ret = prot_verify_write(SCpnt, lba, num, ei_lba);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002110
2111 if (prot_ret) {
Akinobu Mita6c78cc02014-02-26 22:57:03 +09002112 write_unlock_irqrestore(&atomic_rw, iflags);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002113 mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x10, prot_ret);
2114 return illegal_condition_result;
2115 }
2116 }
2117
FUJITA Tomonori19789102008-03-30 00:59:56 +09002118 ret = do_device_access(SCpnt, devip, lba, num, 1);
Akinobu Mita9ed8d3d2013-04-16 22:11:55 +09002119 if (scsi_debug_lbp())
Martin K. Petersen44d92692009-10-15 14:45:27 -04002120 map_region(lba, num);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002121 write_unlock_irqrestore(&atomic_rw, iflags);
FUJITA Tomonori19789102008-03-30 00:59:56 +09002122 if (-1 == ret)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002123 return (DID_ERROR << 16);
Martin K. Petersen597136a2008-06-05 00:12:59 -04002124 else if ((ret < (num * scsi_debug_sector_size)) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07002125 (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002126 printk(KERN_INFO "scsi_debug: write: cdb indicated=%u, "
Martin K. Petersen597136a2008-06-05 00:12:59 -04002127 " IO sent=%d bytes\n", num * scsi_debug_sector_size, ret);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002128
Linus Torvalds1da177e2005-04-16 15:20:36 -07002129 return 0;
2130}
2131
Martin K. Petersen44d92692009-10-15 14:45:27 -04002132static int resp_write_same(struct scsi_cmnd *scmd, unsigned long long lba,
2133 unsigned int num, struct sdebug_dev_info *devip,
2134 u32 ei_lba, unsigned int unmap)
2135{
2136 unsigned long iflags;
2137 unsigned long long i;
2138 int ret;
2139
2140 ret = check_device_access_params(devip, lba, num);
2141 if (ret)
2142 return ret;
2143
Martin K. Petersen5b94e232011-03-08 02:08:11 -05002144 if (num > scsi_debug_write_same_length) {
2145 mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
2146 0);
2147 return check_condition_result;
2148 }
2149
Martin K. Petersen44d92692009-10-15 14:45:27 -04002150 write_lock_irqsave(&atomic_rw, iflags);
2151
Akinobu Mita9ed8d3d2013-04-16 22:11:55 +09002152 if (unmap && scsi_debug_lbp()) {
Martin K. Petersen44d92692009-10-15 14:45:27 -04002153 unmap_region(lba, num);
2154 goto out;
2155 }
2156
2157 /* Else fetch one logical block */
2158 ret = fetch_to_dev_buffer(scmd,
2159 fake_storep + (lba * scsi_debug_sector_size),
2160 scsi_debug_sector_size);
2161
2162 if (-1 == ret) {
2163 write_unlock_irqrestore(&atomic_rw, iflags);
2164 return (DID_ERROR << 16);
2165 } else if ((ret < (num * scsi_debug_sector_size)) &&
2166 (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
2167 printk(KERN_INFO "scsi_debug: write same: cdb indicated=%u, "
2168 " IO sent=%d bytes\n", num * scsi_debug_sector_size, ret);
2169
2170 /* Copy first sector to remaining blocks */
2171 for (i = 1 ; i < num ; i++)
2172 memcpy(fake_storep + ((lba + i) * scsi_debug_sector_size),
2173 fake_storep + (lba * scsi_debug_sector_size),
2174 scsi_debug_sector_size);
2175
Akinobu Mita9ed8d3d2013-04-16 22:11:55 +09002176 if (scsi_debug_lbp())
Martin K. Petersen44d92692009-10-15 14:45:27 -04002177 map_region(lba, num);
2178out:
2179 write_unlock_irqrestore(&atomic_rw, iflags);
2180
2181 return 0;
2182}
2183
2184struct unmap_block_desc {
2185 __be64 lba;
2186 __be32 blocks;
2187 __be32 __reserved;
2188};
2189
2190static int resp_unmap(struct scsi_cmnd * scmd, struct sdebug_dev_info * devip)
2191{
2192 unsigned char *buf;
2193 struct unmap_block_desc *desc;
2194 unsigned int i, payload_len, descriptors;
2195 int ret;
Akinobu Mita6c78cc02014-02-26 22:57:03 +09002196 unsigned long iflags;
Martin K. Petersen44d92692009-10-15 14:45:27 -04002197
2198 ret = check_readiness(scmd, 1, devip);
2199 if (ret)
2200 return ret;
2201
2202 payload_len = get_unaligned_be16(&scmd->cmnd[7]);
2203 BUG_ON(scsi_bufflen(scmd) != payload_len);
2204
2205 descriptors = (payload_len - 8) / 16;
2206
2207 buf = kmalloc(scsi_bufflen(scmd), GFP_ATOMIC);
2208 if (!buf)
2209 return check_condition_result;
2210
2211 scsi_sg_copy_to_buffer(scmd, buf, scsi_bufflen(scmd));
2212
2213 BUG_ON(get_unaligned_be16(&buf[0]) != payload_len - 2);
2214 BUG_ON(get_unaligned_be16(&buf[2]) != descriptors * 16);
2215
2216 desc = (void *)&buf[8];
2217
Akinobu Mita6c78cc02014-02-26 22:57:03 +09002218 write_lock_irqsave(&atomic_rw, iflags);
2219
Martin K. Petersen44d92692009-10-15 14:45:27 -04002220 for (i = 0 ; i < descriptors ; i++) {
2221 unsigned long long lba = get_unaligned_be64(&desc[i].lba);
2222 unsigned int num = get_unaligned_be32(&desc[i].blocks);
2223
2224 ret = check_device_access_params(devip, lba, num);
2225 if (ret)
2226 goto out;
2227
2228 unmap_region(lba, num);
2229 }
2230
2231 ret = 0;
2232
2233out:
Akinobu Mita6c78cc02014-02-26 22:57:03 +09002234 write_unlock_irqrestore(&atomic_rw, iflags);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002235 kfree(buf);
2236
2237 return ret;
2238}
2239
2240#define SDEBUG_GET_LBA_STATUS_LEN 32
2241
2242static int resp_get_lba_status(struct scsi_cmnd * scmd,
2243 struct sdebug_dev_info * devip)
2244{
2245 unsigned long long lba;
2246 unsigned int alloc_len, mapped, num;
2247 unsigned char arr[SDEBUG_GET_LBA_STATUS_LEN];
2248 int ret;
2249
2250 ret = check_readiness(scmd, 1, devip);
2251 if (ret)
2252 return ret;
2253
2254 lba = get_unaligned_be64(&scmd->cmnd[2]);
2255 alloc_len = get_unaligned_be32(&scmd->cmnd[10]);
2256
2257 if (alloc_len < 24)
2258 return 0;
2259
2260 ret = check_device_access_params(devip, lba, 1);
2261 if (ret)
2262 return ret;
2263
2264 mapped = map_state(lba, &num);
2265
2266 memset(arr, 0, SDEBUG_GET_LBA_STATUS_LEN);
Douglas Gilbertde13e962012-01-19 19:30:00 -05002267 put_unaligned_be32(20, &arr[0]); /* Parameter Data Length */
Martin K. Petersen44d92692009-10-15 14:45:27 -04002268 put_unaligned_be64(lba, &arr[8]); /* LBA */
2269 put_unaligned_be32(num, &arr[16]); /* Number of blocks */
2270 arr[20] = !mapped; /* mapped = 0, unmapped = 1 */
2271
2272 return fill_from_dev_buffer(scmd, arr, SDEBUG_GET_LBA_STATUS_LEN);
2273}
2274
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002275#define SDEBUG_RLUN_ARR_SZ 256
Linus Torvalds1da177e2005-04-16 15:20:36 -07002276
2277static int resp_report_luns(struct scsi_cmnd * scp,
2278 struct sdebug_dev_info * devip)
2279{
2280 unsigned int alloc_len;
Hannes Reinecke9cb78c12014-06-25 15:27:36 +02002281 int lun_cnt, i, upper, num, n;
2282 u64 wlun, lun;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002283 unsigned char *cmd = (unsigned char *)scp->cmnd;
2284 int select_report = (int)cmd[2];
2285 struct scsi_lun *one_lun;
2286 unsigned char arr[SDEBUG_RLUN_ARR_SZ];
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002287 unsigned char * max_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002288
2289 alloc_len = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002290 if ((alloc_len < 4) || (select_report > 2)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002291 mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
2292 0);
2293 return check_condition_result;
2294 }
2295 /* can produce response with up to 16k luns (lun 0 to lun 16383) */
2296 memset(arr, 0, SDEBUG_RLUN_ARR_SZ);
2297 lun_cnt = scsi_debug_max_luns;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002298 if (1 == select_report)
2299 lun_cnt = 0;
2300 else if (scsi_debug_no_lun_0 && (lun_cnt > 0))
2301 --lun_cnt;
2302 wlun = (select_report > 0) ? 1 : 0;
2303 num = lun_cnt + wlun;
2304 arr[2] = ((sizeof(struct scsi_lun) * num) >> 8) & 0xff;
2305 arr[3] = (sizeof(struct scsi_lun) * num) & 0xff;
2306 n = min((int)((SDEBUG_RLUN_ARR_SZ - 8) /
2307 sizeof(struct scsi_lun)), num);
2308 if (n < num) {
2309 wlun = 0;
2310 lun_cnt = n;
2311 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002312 one_lun = (struct scsi_lun *) &arr[8];
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002313 max_addr = arr + SDEBUG_RLUN_ARR_SZ;
2314 for (i = 0, lun = (scsi_debug_no_lun_0 ? 1 : 0);
2315 ((i < lun_cnt) && ((unsigned char *)(one_lun + i) < max_addr));
2316 i++, lun++) {
2317 upper = (lun >> 8) & 0x3f;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002318 if (upper)
2319 one_lun[i].scsi_lun[0] =
2320 (upper | (SAM2_LUN_ADDRESS_METHOD << 6));
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002321 one_lun[i].scsi_lun[1] = lun & 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002322 }
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002323 if (wlun) {
2324 one_lun[i].scsi_lun[0] = (SAM2_WLUN_REPORT_LUNS >> 8) & 0xff;
2325 one_lun[i].scsi_lun[1] = SAM2_WLUN_REPORT_LUNS & 0xff;
2326 i++;
2327 }
2328 alloc_len = (unsigned char *)(one_lun + i) - arr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002329 return fill_from_dev_buffer(scp, arr,
2330 min((int)alloc_len, SDEBUG_RLUN_ARR_SZ));
2331}
2332
FUJITA Tomonoric639d142008-01-23 01:32:01 +09002333static int resp_xdwriteread(struct scsi_cmnd *scp, unsigned long long lba,
2334 unsigned int num, struct sdebug_dev_info *devip)
2335{
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002336 int j;
FUJITA Tomonoric639d142008-01-23 01:32:01 +09002337 unsigned char *kaddr, *buf;
2338 unsigned int offset;
FUJITA Tomonoric639d142008-01-23 01:32:01 +09002339 struct scsi_data_buffer *sdb = scsi_in(scp);
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002340 struct sg_mapping_iter miter;
FUJITA Tomonoric639d142008-01-23 01:32:01 +09002341
2342 /* better not to use temporary buffer. */
2343 buf = kmalloc(scsi_bufflen(scp), GFP_ATOMIC);
Akinobu Mitac5af0db2014-02-26 22:57:01 +09002344 if (!buf) {
2345 mk_sense_buffer(devip, NOT_READY,
2346 LOGICAL_UNIT_COMMUNICATION_FAILURE, 0);
2347 return check_condition_result;
2348 }
FUJITA Tomonoric639d142008-01-23 01:32:01 +09002349
FUJITA Tomonori21a61822008-03-09 13:44:30 +09002350 scsi_sg_copy_to_buffer(scp, buf, scsi_bufflen(scp));
FUJITA Tomonoric639d142008-01-23 01:32:01 +09002351
2352 offset = 0;
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002353 sg_miter_start(&miter, sdb->table.sgl, sdb->table.nents,
2354 SG_MITER_ATOMIC | SG_MITER_TO_SG);
FUJITA Tomonoric639d142008-01-23 01:32:01 +09002355
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002356 while (sg_miter_next(&miter)) {
2357 kaddr = miter.addr;
2358 for (j = 0; j < miter.length; j++)
2359 *(kaddr + j) ^= *(buf + offset + j);
FUJITA Tomonoric639d142008-01-23 01:32:01 +09002360
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002361 offset += miter.length;
FUJITA Tomonoric639d142008-01-23 01:32:01 +09002362 }
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002363 sg_miter_stop(&miter);
FUJITA Tomonoric639d142008-01-23 01:32:01 +09002364 kfree(buf);
2365
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002366 return 0;
FUJITA Tomonoric639d142008-01-23 01:32:01 +09002367}
2368
Linus Torvalds1da177e2005-04-16 15:20:36 -07002369/* When timer goes off this function is called. */
2370static void timer_intr_handler(unsigned long indx)
2371{
2372 struct sdebug_queued_cmd * sqcp;
2373 unsigned long iflags;
2374
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04002375 if (indx >= scsi_debug_max_queue) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002376 printk(KERN_ERR "scsi_debug:timer_intr_handler: indx too "
2377 "large\n");
2378 return;
2379 }
2380 spin_lock_irqsave(&queued_arr_lock, iflags);
2381 sqcp = &queued_arr[(int)indx];
2382 if (! sqcp->in_use) {
2383 printk(KERN_ERR "scsi_debug:timer_intr_handler: Unexpected "
2384 "interrupt\n");
2385 spin_unlock_irqrestore(&queued_arr_lock, iflags);
2386 return;
2387 }
2388 sqcp->in_use = 0;
2389 if (sqcp->done_funct) {
2390 sqcp->a_cmnd->result = sqcp->scsi_result;
2391 sqcp->done_funct(sqcp->a_cmnd); /* callback to mid level */
2392 }
2393 sqcp->done_funct = NULL;
2394 spin_unlock_irqrestore(&queued_arr_lock, iflags);
2395}
2396
Linus Torvalds1da177e2005-04-16 15:20:36 -07002397
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09002398static struct sdebug_dev_info *
2399sdebug_device_create(struct sdebug_host_info *sdbg_host, gfp_t flags)
FUJITA Tomonori5cb2fc02008-03-20 11:09:16 +09002400{
2401 struct sdebug_dev_info *devip;
2402
2403 devip = kzalloc(sizeof(*devip), flags);
2404 if (devip) {
2405 devip->sdbg_host = sdbg_host;
2406 list_add_tail(&devip->dev_list, &sdbg_host->dev_info_list);
2407 }
2408 return devip;
2409}
2410
Linus Torvalds1da177e2005-04-16 15:20:36 -07002411static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev)
2412{
2413 struct sdebug_host_info * sdbg_host;
2414 struct sdebug_dev_info * open_devip = NULL;
2415 struct sdebug_dev_info * devip =
2416 (struct sdebug_dev_info *)sdev->hostdata;
2417
2418 if (devip)
2419 return devip;
FUJITA Tomonorid1e4c9c2008-03-02 18:30:18 +09002420 sdbg_host = *(struct sdebug_host_info **)shost_priv(sdev->host);
2421 if (!sdbg_host) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002422 printk(KERN_ERR "Host info NULL\n");
2423 return NULL;
2424 }
2425 list_for_each_entry(devip, &sdbg_host->dev_info_list, dev_list) {
2426 if ((devip->used) && (devip->channel == sdev->channel) &&
2427 (devip->target == sdev->id) &&
2428 (devip->lun == sdev->lun))
2429 return devip;
2430 else {
2431 if ((!devip->used) && (!open_devip))
2432 open_devip = devip;
2433 }
2434 }
FUJITA Tomonori5cb2fc02008-03-20 11:09:16 +09002435 if (!open_devip) { /* try and make a new one */
2436 open_devip = sdebug_device_create(sdbg_host, GFP_ATOMIC);
2437 if (!open_devip) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002438 printk(KERN_ERR "%s: out of memory at line %d\n",
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07002439 __func__, __LINE__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002440 return NULL;
2441 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002442 }
FUJITA Tomonoria75869d2008-03-20 11:09:17 +09002443
2444 open_devip->channel = sdev->channel;
2445 open_devip->target = sdev->id;
2446 open_devip->lun = sdev->lun;
2447 open_devip->sdbg_host = sdbg_host;
2448 open_devip->reset = 1;
2449 open_devip->used = 1;
2450 memset(open_devip->sense_buff, 0, SDEBUG_SENSE_LEN);
2451 if (scsi_debug_dsense)
2452 open_devip->sense_buff[0] = 0x72;
2453 else {
2454 open_devip->sense_buff[0] = 0x70;
2455 open_devip->sense_buff[7] = 0xa;
2456 }
2457 if (sdev->lun == SAM2_WLUN_REPORT_LUNS)
2458 open_devip->wlun = SAM2_WLUN_REPORT_LUNS & 0xff;
2459
2460 return open_devip;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002461}
2462
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09002463static int scsi_debug_slave_alloc(struct scsi_device *sdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002464{
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09002465 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
Hannes Reinecke9cb78c12014-06-25 15:27:36 +02002466 printk(KERN_INFO "scsi_debug: slave_alloc <%u %u %u %llu>\n",
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09002467 sdp->host->host_no, sdp->channel, sdp->id, sdp->lun);
Nick Piggin75ad23b2008-04-29 14:48:33 +02002468 queue_flag_set_unlocked(QUEUE_FLAG_BIDI, sdp->request_queue);
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09002469 return 0;
2470}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002471
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09002472static int scsi_debug_slave_configure(struct scsi_device *sdp)
2473{
2474 struct sdebug_dev_info *devip;
FUJITA Tomonoria34c4e92008-03-25 09:26:50 +09002475
Linus Torvalds1da177e2005-04-16 15:20:36 -07002476 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
Hannes Reinecke9cb78c12014-06-25 15:27:36 +02002477 printk(KERN_INFO "scsi_debug: slave_configure <%u %u %u %llu>\n",
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09002478 sdp->host->host_no, sdp->channel, sdp->id, sdp->lun);
2479 if (sdp->host->max_cmd_len != SCSI_DEBUG_MAX_CMD_LEN)
2480 sdp->host->max_cmd_len = SCSI_DEBUG_MAX_CMD_LEN;
2481 devip = devInfoReg(sdp);
2482 if (NULL == devip)
2483 return 1; /* no resources, will be marked offline */
2484 sdp->hostdata = devip;
2485 if (sdp->host->cmd_per_lun)
2486 scsi_adjust_queue_depth(sdp, SDEBUG_TAGGED_QUEUING,
2487 sdp->host->cmd_per_lun);
Akinobu Mita6bb5e6e2014-06-02 22:56:49 +09002488 blk_queue_max_segment_size(sdp->request_queue, -1U);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04002489 if (scsi_debug_no_uld)
2490 sdp->no_uld_attach = 1;
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09002491 return 0;
2492}
2493
2494static void scsi_debug_slave_destroy(struct scsi_device *sdp)
2495{
2496 struct sdebug_dev_info *devip =
2497 (struct sdebug_dev_info *)sdp->hostdata;
2498
2499 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
Hannes Reinecke9cb78c12014-06-25 15:27:36 +02002500 printk(KERN_INFO "scsi_debug: slave_destroy <%u %u %u %llu>\n",
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09002501 sdp->host->host_no, sdp->channel, sdp->id, sdp->lun);
2502 if (devip) {
Lucas De Marchi25985ed2011-03-30 22:57:33 -03002503 /* make this slot available for re-use */
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09002504 devip->used = 0;
2505 sdp->hostdata = NULL;
2506 }
2507}
2508
2509/* Returns 1 if found 'cmnd' and deleted its timer. else returns 0 */
2510static int stop_queued_cmnd(struct scsi_cmnd *cmnd)
2511{
2512 unsigned long iflags;
2513 int k;
2514 struct sdebug_queued_cmd *sqcp;
2515
2516 spin_lock_irqsave(&queued_arr_lock, iflags);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04002517 for (k = 0; k < scsi_debug_max_queue; ++k) {
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09002518 sqcp = &queued_arr[k];
2519 if (sqcp->in_use && (cmnd == sqcp->a_cmnd)) {
2520 del_timer_sync(&sqcp->cmnd_timer);
2521 sqcp->in_use = 0;
2522 sqcp->a_cmnd = NULL;
2523 break;
2524 }
2525 }
2526 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04002527 return (k < scsi_debug_max_queue) ? 1 : 0;
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09002528}
2529
2530/* Deletes (stops) timers of all queued commands */
2531static void stop_all_queued(void)
2532{
2533 unsigned long iflags;
2534 int k;
2535 struct sdebug_queued_cmd *sqcp;
2536
2537 spin_lock_irqsave(&queued_arr_lock, iflags);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04002538 for (k = 0; k < scsi_debug_max_queue; ++k) {
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09002539 sqcp = &queued_arr[k];
2540 if (sqcp->in_use && sqcp->a_cmnd) {
2541 del_timer_sync(&sqcp->cmnd_timer);
2542 sqcp->in_use = 0;
2543 sqcp->a_cmnd = NULL;
2544 }
2545 }
2546 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002547}
2548
2549static int scsi_debug_abort(struct scsi_cmnd * SCpnt)
2550{
2551 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
2552 printk(KERN_INFO "scsi_debug: abort\n");
2553 ++num_aborts;
2554 stop_queued_cmnd(SCpnt);
2555 return SUCCESS;
2556}
2557
2558static int scsi_debug_biosparam(struct scsi_device *sdev,
2559 struct block_device * bdev, sector_t capacity, int *info)
2560{
2561 int res;
2562 unsigned char *buf;
2563
2564 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
2565 printk(KERN_INFO "scsi_debug: biosparam\n");
2566 buf = scsi_bios_ptable(bdev);
2567 if (buf) {
2568 res = scsi_partsize(buf, capacity,
2569 &info[2], &info[0], &info[1]);
2570 kfree(buf);
2571 if (! res)
2572 return res;
2573 }
2574 info[0] = sdebug_heads;
2575 info[1] = sdebug_sectors_per;
2576 info[2] = sdebug_cylinders_per;
2577 return 0;
2578}
2579
2580static int scsi_debug_device_reset(struct scsi_cmnd * SCpnt)
2581{
2582 struct sdebug_dev_info * devip;
2583
2584 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
2585 printk(KERN_INFO "scsi_debug: device_reset\n");
2586 ++num_dev_resets;
2587 if (SCpnt) {
2588 devip = devInfoReg(SCpnt->device);
2589 if (devip)
2590 devip->reset = 1;
2591 }
2592 return SUCCESS;
2593}
2594
2595static int scsi_debug_bus_reset(struct scsi_cmnd * SCpnt)
2596{
2597 struct sdebug_host_info *sdbg_host;
2598 struct sdebug_dev_info * dev_info;
2599 struct scsi_device * sdp;
2600 struct Scsi_Host * hp;
2601
2602 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
2603 printk(KERN_INFO "scsi_debug: bus_reset\n");
2604 ++num_bus_resets;
2605 if (SCpnt && ((sdp = SCpnt->device)) && ((hp = sdp->host))) {
FUJITA Tomonorid1e4c9c2008-03-02 18:30:18 +09002606 sdbg_host = *(struct sdebug_host_info **)shost_priv(hp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002607 if (sdbg_host) {
2608 list_for_each_entry(dev_info,
2609 &sdbg_host->dev_info_list,
2610 dev_list)
2611 dev_info->reset = 1;
2612 }
2613 }
2614 return SUCCESS;
2615}
2616
2617static int scsi_debug_host_reset(struct scsi_cmnd * SCpnt)
2618{
2619 struct sdebug_host_info * sdbg_host;
2620 struct sdebug_dev_info * dev_info;
2621
2622 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
2623 printk(KERN_INFO "scsi_debug: host_reset\n");
2624 ++num_host_resets;
2625 spin_lock(&sdebug_host_list_lock);
2626 list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) {
2627 list_for_each_entry(dev_info, &sdbg_host->dev_info_list,
2628 dev_list)
2629 dev_info->reset = 1;
2630 }
2631 spin_unlock(&sdebug_host_list_lock);
2632 stop_all_queued();
2633 return SUCCESS;
2634}
2635
Linus Torvalds1da177e2005-04-16 15:20:36 -07002636/* Initializes timers in queued array */
2637static void __init init_all_queued(void)
2638{
2639 unsigned long iflags;
2640 int k;
2641 struct sdebug_queued_cmd * sqcp;
2642
2643 spin_lock_irqsave(&queued_arr_lock, iflags);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04002644 for (k = 0; k < scsi_debug_max_queue; ++k) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002645 sqcp = &queued_arr[k];
2646 init_timer(&sqcp->cmnd_timer);
2647 sqcp->in_use = 0;
2648 sqcp->a_cmnd = NULL;
2649 }
2650 spin_unlock_irqrestore(&queued_arr_lock, iflags);
2651}
2652
FUJITA Tomonorif58b0ef2008-03-30 00:59:54 +09002653static void __init sdebug_build_parts(unsigned char *ramp,
FUJITA Tomonori5f2578e2008-03-30 00:59:57 +09002654 unsigned long store_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002655{
2656 struct partition * pp;
2657 int starts[SDEBUG_MAX_PARTS + 2];
2658 int sectors_per_part, num_sectors, k;
2659 int heads_by_sects, start_sec, end_sec;
2660
2661 /* assume partition table already zeroed */
FUJITA Tomonorif58b0ef2008-03-30 00:59:54 +09002662 if ((scsi_debug_num_parts < 1) || (store_size < 1048576))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002663 return;
2664 if (scsi_debug_num_parts > SDEBUG_MAX_PARTS) {
2665 scsi_debug_num_parts = SDEBUG_MAX_PARTS;
2666 printk(KERN_WARNING "scsi_debug:build_parts: reducing "
2667 "partitions to %d\n", SDEBUG_MAX_PARTS);
2668 }
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002669 num_sectors = (int)sdebug_store_sectors;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002670 sectors_per_part = (num_sectors - sdebug_sectors_per)
2671 / scsi_debug_num_parts;
2672 heads_by_sects = sdebug_heads * sdebug_sectors_per;
2673 starts[0] = sdebug_sectors_per;
2674 for (k = 1; k < scsi_debug_num_parts; ++k)
2675 starts[k] = ((k * sectors_per_part) / heads_by_sects)
2676 * heads_by_sects;
2677 starts[scsi_debug_num_parts] = num_sectors;
2678 starts[scsi_debug_num_parts + 1] = 0;
2679
2680 ramp[510] = 0x55; /* magic partition markings */
2681 ramp[511] = 0xAA;
2682 pp = (struct partition *)(ramp + 0x1be);
2683 for (k = 0; starts[k + 1]; ++k, ++pp) {
2684 start_sec = starts[k];
2685 end_sec = starts[k + 1] - 1;
2686 pp->boot_ind = 0;
2687
2688 pp->cyl = start_sec / heads_by_sects;
2689 pp->head = (start_sec - (pp->cyl * heads_by_sects))
2690 / sdebug_sectors_per;
2691 pp->sector = (start_sec % sdebug_sectors_per) + 1;
2692
2693 pp->end_cyl = end_sec / heads_by_sects;
2694 pp->end_head = (end_sec - (pp->end_cyl * heads_by_sects))
2695 / sdebug_sectors_per;
2696 pp->end_sector = (end_sec % sdebug_sectors_per) + 1;
2697
Akinobu Mita150c3542013-08-26 22:08:40 +09002698 pp->start_sect = cpu_to_le32(start_sec);
2699 pp->nr_sects = cpu_to_le32(end_sec - start_sec + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002700 pp->sys_ind = 0x83; /* plain Linux partition */
2701 }
2702}
2703
2704static int schedule_resp(struct scsi_cmnd * cmnd,
2705 struct sdebug_dev_info * devip,
2706 done_funct_t done, int scsi_result, int delta_jiff)
2707{
2708 if ((SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) && cmnd) {
2709 if (scsi_result) {
2710 struct scsi_device * sdp = cmnd->device;
2711
Hannes Reinecke9cb78c12014-06-25 15:27:36 +02002712 printk(KERN_INFO "scsi_debug: <%u %u %u %llu> "
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002713 "non-zero result=0x%x\n", sdp->host->host_no,
2714 sdp->channel, sdp->id, sdp->lun, scsi_result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002715 }
2716 }
2717 if (cmnd && devip) {
2718 /* simulate autosense by this driver */
2719 if (SAM_STAT_CHECK_CONDITION == (scsi_result & 0xff))
2720 memcpy(cmnd->sense_buffer, devip->sense_buff,
2721 (SCSI_SENSE_BUFFERSIZE > SDEBUG_SENSE_LEN) ?
2722 SDEBUG_SENSE_LEN : SCSI_SENSE_BUFFERSIZE);
2723 }
2724 if (delta_jiff <= 0) {
2725 if (cmnd)
2726 cmnd->result = scsi_result;
2727 if (done)
2728 done(cmnd);
2729 return 0;
2730 } else {
2731 unsigned long iflags;
2732 int k;
2733 struct sdebug_queued_cmd * sqcp = NULL;
2734
2735 spin_lock_irqsave(&queued_arr_lock, iflags);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04002736 for (k = 0; k < scsi_debug_max_queue; ++k) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002737 sqcp = &queued_arr[k];
2738 if (! sqcp->in_use)
2739 break;
2740 }
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04002741 if (k >= scsi_debug_max_queue) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002742 spin_unlock_irqrestore(&queued_arr_lock, iflags);
2743 printk(KERN_WARNING "scsi_debug: can_queue exceeded\n");
2744 return 1; /* report busy to mid level */
2745 }
2746 sqcp->in_use = 1;
2747 sqcp->a_cmnd = cmnd;
2748 sqcp->scsi_result = scsi_result;
2749 sqcp->done_funct = done;
2750 sqcp->cmnd_timer.function = timer_intr_handler;
2751 sqcp->cmnd_timer.data = k;
2752 sqcp->cmnd_timer.expires = jiffies + delta_jiff;
2753 add_timer(&sqcp->cmnd_timer);
2754 spin_unlock_irqrestore(&queued_arr_lock, iflags);
2755 if (cmnd)
2756 cmnd->result = 0;
2757 return 0;
2758 }
2759}
Douglas Gilbert23183912006-09-16 20:30:47 -04002760/* Note: The following macros create attribute files in the
2761 /sys/module/scsi_debug/parameters directory. Unfortunately this
2762 driver is unaware of a change and cannot trigger auxiliary actions
2763 as it can when the corresponding attribute in the
2764 /sys/bus/pseudo/drivers/scsi_debug directory is changed.
2765 */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002766module_param_named(add_host, scsi_debug_add_host, int, S_IRUGO | S_IWUSR);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05002767module_param_named(ato, scsi_debug_ato, int, S_IRUGO);
Akinobu Mita0759c662014-02-26 22:57:04 +09002768module_param_named(clustering, scsi_debug_clustering, bool, S_IRUGO | S_IWUSR);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002769module_param_named(delay, scsi_debug_delay, int, S_IRUGO | S_IWUSR);
2770module_param_named(dev_size_mb, scsi_debug_dev_size_mb, int, S_IRUGO);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05002771module_param_named(dif, scsi_debug_dif, int, S_IRUGO);
2772module_param_named(dix, scsi_debug_dix, int, S_IRUGO);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002773module_param_named(dsense, scsi_debug_dsense, int, S_IRUGO | S_IWUSR);
2774module_param_named(every_nth, scsi_debug_every_nth, int, S_IRUGO | S_IWUSR);
Douglas Gilbert23183912006-09-16 20:30:47 -04002775module_param_named(fake_rw, scsi_debug_fake_rw, int, S_IRUGO | S_IWUSR);
Akinobu Mita68aee7b2013-09-18 21:27:27 +09002776module_param_named(guard, scsi_debug_guard, uint, S_IRUGO);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05002777module_param_named(lbpu, scsi_debug_lbpu, int, S_IRUGO);
2778module_param_named(lbpws, scsi_debug_lbpws, int, S_IRUGO);
2779module_param_named(lbpws10, scsi_debug_lbpws10, int, S_IRUGO);
Eric Sandeenbe1dd782012-03-08 00:03:59 -06002780module_param_named(lbprz, scsi_debug_lbprz, int, S_IRUGO);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05002781module_param_named(lowest_aligned, scsi_debug_lowest_aligned, int, S_IRUGO);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002782module_param_named(max_luns, scsi_debug_max_luns, int, S_IRUGO | S_IWUSR);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04002783module_param_named(max_queue, scsi_debug_max_queue, int, S_IRUGO | S_IWUSR);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002784module_param_named(no_lun_0, scsi_debug_no_lun_0, int, S_IRUGO | S_IWUSR);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04002785module_param_named(no_uld, scsi_debug_no_uld, int, S_IRUGO);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002786module_param_named(num_parts, scsi_debug_num_parts, int, S_IRUGO);
2787module_param_named(num_tgts, scsi_debug_num_tgts, int, S_IRUGO | S_IWUSR);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05002788module_param_named(opt_blks, scsi_debug_opt_blks, int, S_IRUGO);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002789module_param_named(opts, scsi_debug_opts, int, S_IRUGO | S_IWUSR);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05002790module_param_named(physblk_exp, scsi_debug_physblk_exp, int, S_IRUGO);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002791module_param_named(ptype, scsi_debug_ptype, int, S_IRUGO | S_IWUSR);
Martin Pittd9867882012-09-06 12:04:33 +02002792module_param_named(removable, scsi_debug_removable, bool, S_IRUGO | S_IWUSR);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002793module_param_named(scsi_level, scsi_debug_scsi_level, int, S_IRUGO);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05002794module_param_named(sector_size, scsi_debug_sector_size, int, S_IRUGO);
2795module_param_named(unmap_alignment, scsi_debug_unmap_alignment, int, S_IRUGO);
2796module_param_named(unmap_granularity, scsi_debug_unmap_granularity, int, S_IRUGO);
2797module_param_named(unmap_max_blocks, scsi_debug_unmap_max_blocks, int, S_IRUGO);
2798module_param_named(unmap_max_desc, scsi_debug_unmap_max_desc, int, S_IRUGO);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002799module_param_named(virtual_gb, scsi_debug_virtual_gb, int, S_IRUGO | S_IWUSR);
Douglas Gilbert23183912006-09-16 20:30:47 -04002800module_param_named(vpd_use_hostno, scsi_debug_vpd_use_hostno, int,
2801 S_IRUGO | S_IWUSR);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05002802module_param_named(write_same_length, scsi_debug_write_same_length, int,
2803 S_IRUGO | S_IWUSR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002804
2805MODULE_AUTHOR("Eric Youngdale + Douglas Gilbert");
2806MODULE_DESCRIPTION("SCSI debug adapter driver");
2807MODULE_LICENSE("GPL");
2808MODULE_VERSION(SCSI_DEBUG_VERSION);
2809
2810MODULE_PARM_DESC(add_host, "0..127 hosts allowed(def=1)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05002811MODULE_PARM_DESC(ato, "application tag ownership: 0=disk 1=host (def=1)");
Akinobu Mita0759c662014-02-26 22:57:04 +09002812MODULE_PARM_DESC(clustering, "when set enables larger transfers (def=0)");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002813MODULE_PARM_DESC(delay, "# of jiffies to delay response(def=1)");
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002814MODULE_PARM_DESC(dev_size_mb, "size in MB of ram shared by devs(def=8)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05002815MODULE_PARM_DESC(dif, "data integrity field type: 0-3 (def=0)");
2816MODULE_PARM_DESC(dix, "data integrity extensions mask (def=0)");
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002817MODULE_PARM_DESC(dsense, "use descriptor sense format(def=0 -> fixed)");
Randy Dunlapbeb87c32007-06-11 11:36:40 -07002818MODULE_PARM_DESC(every_nth, "timeout every nth command(def=0)");
Douglas Gilbert23183912006-09-16 20:30:47 -04002819MODULE_PARM_DESC(fake_rw, "fake reads/writes instead of copying (def=0)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05002820MODULE_PARM_DESC(guard, "protection checksum: 0=crc, 1=ip (def=0)");
2821MODULE_PARM_DESC(lbpu, "enable LBP, support UNMAP command (def=0)");
2822MODULE_PARM_DESC(lbpws, "enable LBP, support WRITE SAME(16) with UNMAP bit (def=0)");
2823MODULE_PARM_DESC(lbpws10, "enable LBP, support WRITE SAME(10) with UNMAP bit (def=0)");
Eric Sandeenbe1dd782012-03-08 00:03:59 -06002824MODULE_PARM_DESC(lbprz, "unmapped blocks return 0 on read (def=1)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05002825MODULE_PARM_DESC(lowest_aligned, "lowest aligned lba (def=0)");
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002826MODULE_PARM_DESC(max_luns, "number of LUNs per target to simulate(def=1)");
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04002827MODULE_PARM_DESC(max_queue, "max number of queued commands (1 to 255(def))");
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002828MODULE_PARM_DESC(no_lun_0, "no LU number 0 (def=0 -> have lun 0)");
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04002829MODULE_PARM_DESC(no_uld, "stop ULD (e.g. sd driver) attaching (def=0))");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002830MODULE_PARM_DESC(num_parts, "number of partitions(def=0)");
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002831MODULE_PARM_DESC(num_tgts, "number of targets per host to simulate(def=1)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05002832MODULE_PARM_DESC(opt_blks, "optimal transfer length in block (def=64)");
Douglas Gilbert6f3cbf52007-01-05 00:05:25 -05002833MODULE_PARM_DESC(opts, "1->noise, 2->medium_err, 4->timeout, 8->recovered_err... (def=0)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05002834MODULE_PARM_DESC(physblk_exp, "physical block exponent (def=0)");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002835MODULE_PARM_DESC(ptype, "SCSI peripheral type(def=0[disk])");
Martin Pittd9867882012-09-06 12:04:33 +02002836MODULE_PARM_DESC(removable, "claim to have removable media (def=0)");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002837MODULE_PARM_DESC(scsi_level, "SCSI level to simulate(def=5[SPC-3])");
Martin K. Petersenea61fca2009-05-15 00:40:33 -04002838MODULE_PARM_DESC(sector_size, "logical block size in bytes (def=512)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05002839MODULE_PARM_DESC(unmap_alignment, "lowest aligned thin provisioning lba (def=0)");
2840MODULE_PARM_DESC(unmap_granularity, "thin provisioning granularity in blocks (def=1)");
Martin K. Petersen60147592010-08-19 11:49:00 -04002841MODULE_PARM_DESC(unmap_max_blocks, "max # of blocks can be unmapped in one cmd (def=0xffffffff)");
2842MODULE_PARM_DESC(unmap_max_desc, "max # of ranges that can be unmapped in one cmd (def=256)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05002843MODULE_PARM_DESC(virtual_gb, "virtual gigabyte size (def=0 -> use dev_size_mb)");
2844MODULE_PARM_DESC(vpd_use_hostno, "0 -> dev ids ignore hostno (def=1 -> unique dev ids)");
2845MODULE_PARM_DESC(write_same_length, "Maximum blocks per WRITE SAME cmd (def=0xffff)");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002846
2847static char sdebug_info[256];
2848
2849static const char * scsi_debug_info(struct Scsi_Host * shp)
2850{
2851 sprintf(sdebug_info, "scsi_debug, version %s [%s], "
2852 "dev_size_mb=%d, opts=0x%x", SCSI_DEBUG_VERSION,
2853 scsi_debug_version_date, scsi_debug_dev_size_mb,
2854 scsi_debug_opts);
2855 return sdebug_info;
2856}
2857
2858/* scsi_debug_proc_info
2859 * Used if the driver currently has no own support for /proc/scsi
2860 */
Al Viroc8ed5552013-03-31 01:46:06 -04002861static int scsi_debug_write_info(struct Scsi_Host *host, char *buffer, int length)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002862{
Al Viroc8ed5552013-03-31 01:46:06 -04002863 char arr[16];
2864 int opts;
2865 int minLen = length > 15 ? 15 : length;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002866
Al Viroc8ed5552013-03-31 01:46:06 -04002867 if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
2868 return -EACCES;
2869 memcpy(arr, buffer, minLen);
2870 arr[minLen] = '\0';
2871 if (1 != sscanf(arr, "%d", &opts))
2872 return -EINVAL;
2873 scsi_debug_opts = opts;
2874 if (scsi_debug_every_nth != 0)
2875 scsi_debug_cmnd_count = 0;
2876 return length;
2877}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002878
Al Viroc8ed5552013-03-31 01:46:06 -04002879static int scsi_debug_show_info(struct seq_file *m, struct Scsi_Host *host)
2880{
2881 seq_printf(m, "scsi_debug adapter driver, version "
Linus Torvalds1da177e2005-04-16 15:20:36 -07002882 "%s [%s]\n"
2883 "num_tgts=%d, shared (ram) size=%d MB, opts=0x%x, "
2884 "every_nth=%d(curr:%d)\n"
2885 "delay=%d, max_luns=%d, scsi_level=%d\n"
2886 "sector_size=%d bytes, cylinders=%d, heads=%d, sectors=%d\n"
2887 "number of aborts=%d, device_reset=%d, bus_resets=%d, "
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002888 "host_resets=%d\ndix_reads=%d dix_writes=%d dif_errors=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002889 SCSI_DEBUG_VERSION, scsi_debug_version_date, scsi_debug_num_tgts,
2890 scsi_debug_dev_size_mb, scsi_debug_opts, scsi_debug_every_nth,
2891 scsi_debug_cmnd_count, scsi_debug_delay,
2892 scsi_debug_max_luns, scsi_debug_scsi_level,
Martin K. Petersen597136a2008-06-05 00:12:59 -04002893 scsi_debug_sector_size, sdebug_cylinders_per, sdebug_heads,
2894 sdebug_sectors_per, num_aborts, num_dev_resets, num_bus_resets,
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002895 num_host_resets, dix_reads, dix_writes, dif_errors);
Al Viroc8ed5552013-03-31 01:46:06 -04002896 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002897}
2898
Akinobu Mita82069372013-10-14 22:48:04 +09002899static ssize_t delay_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002900{
2901 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_delay);
2902}
2903
Akinobu Mita82069372013-10-14 22:48:04 +09002904static ssize_t delay_store(struct device_driver *ddp, const char *buf,
2905 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002906{
2907 int delay;
2908 char work[20];
2909
2910 if (1 == sscanf(buf, "%10s", work)) {
2911 if ((1 == sscanf(work, "%d", &delay)) && (delay >= 0)) {
2912 scsi_debug_delay = delay;
2913 return count;
2914 }
2915 }
2916 return -EINVAL;
2917}
Akinobu Mita82069372013-10-14 22:48:04 +09002918static DRIVER_ATTR_RW(delay);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002919
Akinobu Mita82069372013-10-14 22:48:04 +09002920static ssize_t opts_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002921{
2922 return scnprintf(buf, PAGE_SIZE, "0x%x\n", scsi_debug_opts);
2923}
2924
Akinobu Mita82069372013-10-14 22:48:04 +09002925static ssize_t opts_store(struct device_driver *ddp, const char *buf,
2926 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002927{
2928 int opts;
2929 char work[20];
2930
2931 if (1 == sscanf(buf, "%10s", work)) {
2932 if (0 == strnicmp(work,"0x", 2)) {
2933 if (1 == sscanf(&work[2], "%x", &opts))
2934 goto opts_done;
2935 } else {
2936 if (1 == sscanf(work, "%d", &opts))
2937 goto opts_done;
2938 }
2939 }
2940 return -EINVAL;
2941opts_done:
2942 scsi_debug_opts = opts;
2943 scsi_debug_cmnd_count = 0;
2944 return count;
2945}
Akinobu Mita82069372013-10-14 22:48:04 +09002946static DRIVER_ATTR_RW(opts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002947
Akinobu Mita82069372013-10-14 22:48:04 +09002948static ssize_t ptype_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002949{
2950 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_ptype);
2951}
Akinobu Mita82069372013-10-14 22:48:04 +09002952static ssize_t ptype_store(struct device_driver *ddp, const char *buf,
2953 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002954{
2955 int n;
2956
2957 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
2958 scsi_debug_ptype = n;
2959 return count;
2960 }
2961 return -EINVAL;
2962}
Akinobu Mita82069372013-10-14 22:48:04 +09002963static DRIVER_ATTR_RW(ptype);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002964
Akinobu Mita82069372013-10-14 22:48:04 +09002965static ssize_t dsense_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002966{
2967 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dsense);
2968}
Akinobu Mita82069372013-10-14 22:48:04 +09002969static ssize_t dsense_store(struct device_driver *ddp, const char *buf,
2970 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002971{
2972 int n;
2973
2974 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
2975 scsi_debug_dsense = n;
2976 return count;
2977 }
2978 return -EINVAL;
2979}
Akinobu Mita82069372013-10-14 22:48:04 +09002980static DRIVER_ATTR_RW(dsense);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002981
Akinobu Mita82069372013-10-14 22:48:04 +09002982static ssize_t fake_rw_show(struct device_driver *ddp, char *buf)
Douglas Gilbert23183912006-09-16 20:30:47 -04002983{
2984 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_fake_rw);
2985}
Akinobu Mita82069372013-10-14 22:48:04 +09002986static ssize_t fake_rw_store(struct device_driver *ddp, const char *buf,
2987 size_t count)
Douglas Gilbert23183912006-09-16 20:30:47 -04002988{
2989 int n;
2990
2991 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
2992 scsi_debug_fake_rw = n;
2993 return count;
2994 }
2995 return -EINVAL;
2996}
Akinobu Mita82069372013-10-14 22:48:04 +09002997static DRIVER_ATTR_RW(fake_rw);
Douglas Gilbert23183912006-09-16 20:30:47 -04002998
Akinobu Mita82069372013-10-14 22:48:04 +09002999static ssize_t no_lun_0_show(struct device_driver *ddp, char *buf)
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003000{
3001 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_no_lun_0);
3002}
Akinobu Mita82069372013-10-14 22:48:04 +09003003static ssize_t no_lun_0_store(struct device_driver *ddp, const char *buf,
3004 size_t count)
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003005{
3006 int n;
3007
3008 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
3009 scsi_debug_no_lun_0 = n;
3010 return count;
3011 }
3012 return -EINVAL;
3013}
Akinobu Mita82069372013-10-14 22:48:04 +09003014static DRIVER_ATTR_RW(no_lun_0);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003015
Akinobu Mita82069372013-10-14 22:48:04 +09003016static ssize_t num_tgts_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003017{
3018 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_num_tgts);
3019}
Akinobu Mita82069372013-10-14 22:48:04 +09003020static ssize_t num_tgts_store(struct device_driver *ddp, const char *buf,
3021 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003022{
3023 int n;
3024
3025 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
3026 scsi_debug_num_tgts = n;
3027 sdebug_max_tgts_luns();
3028 return count;
3029 }
3030 return -EINVAL;
3031}
Akinobu Mita82069372013-10-14 22:48:04 +09003032static DRIVER_ATTR_RW(num_tgts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003033
Akinobu Mita82069372013-10-14 22:48:04 +09003034static ssize_t dev_size_mb_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003035{
3036 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dev_size_mb);
3037}
Akinobu Mita82069372013-10-14 22:48:04 +09003038static DRIVER_ATTR_RO(dev_size_mb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003039
Akinobu Mita82069372013-10-14 22:48:04 +09003040static ssize_t num_parts_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003041{
3042 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_num_parts);
3043}
Akinobu Mita82069372013-10-14 22:48:04 +09003044static DRIVER_ATTR_RO(num_parts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003045
Akinobu Mita82069372013-10-14 22:48:04 +09003046static ssize_t every_nth_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003047{
3048 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_every_nth);
3049}
Akinobu Mita82069372013-10-14 22:48:04 +09003050static ssize_t every_nth_store(struct device_driver *ddp, const char *buf,
3051 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003052{
3053 int nth;
3054
3055 if ((count > 0) && (1 == sscanf(buf, "%d", &nth))) {
3056 scsi_debug_every_nth = nth;
3057 scsi_debug_cmnd_count = 0;
3058 return count;
3059 }
3060 return -EINVAL;
3061}
Akinobu Mita82069372013-10-14 22:48:04 +09003062static DRIVER_ATTR_RW(every_nth);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003063
Akinobu Mita82069372013-10-14 22:48:04 +09003064static ssize_t max_luns_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003065{
3066 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_max_luns);
3067}
Akinobu Mita82069372013-10-14 22:48:04 +09003068static ssize_t max_luns_store(struct device_driver *ddp, const char *buf,
3069 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003070{
3071 int n;
3072
3073 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
3074 scsi_debug_max_luns = n;
3075 sdebug_max_tgts_luns();
3076 return count;
3077 }
3078 return -EINVAL;
3079}
Akinobu Mita82069372013-10-14 22:48:04 +09003080static DRIVER_ATTR_RW(max_luns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003081
Akinobu Mita82069372013-10-14 22:48:04 +09003082static ssize_t max_queue_show(struct device_driver *ddp, char *buf)
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04003083{
3084 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_max_queue);
3085}
Akinobu Mita82069372013-10-14 22:48:04 +09003086static ssize_t max_queue_store(struct device_driver *ddp, const char *buf,
3087 size_t count)
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04003088{
3089 int n;
3090
3091 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n > 0) &&
3092 (n <= SCSI_DEBUG_CANQUEUE)) {
3093 scsi_debug_max_queue = n;
3094 return count;
3095 }
3096 return -EINVAL;
3097}
Akinobu Mita82069372013-10-14 22:48:04 +09003098static DRIVER_ATTR_RW(max_queue);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04003099
Akinobu Mita82069372013-10-14 22:48:04 +09003100static ssize_t no_uld_show(struct device_driver *ddp, char *buf)
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04003101{
3102 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_no_uld);
3103}
Akinobu Mita82069372013-10-14 22:48:04 +09003104static DRIVER_ATTR_RO(no_uld);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04003105
Akinobu Mita82069372013-10-14 22:48:04 +09003106static ssize_t scsi_level_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003107{
3108 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_scsi_level);
3109}
Akinobu Mita82069372013-10-14 22:48:04 +09003110static DRIVER_ATTR_RO(scsi_level);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003111
Akinobu Mita82069372013-10-14 22:48:04 +09003112static ssize_t virtual_gb_show(struct device_driver *ddp, char *buf)
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003113{
3114 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_virtual_gb);
3115}
Akinobu Mita82069372013-10-14 22:48:04 +09003116static ssize_t virtual_gb_store(struct device_driver *ddp, const char *buf,
3117 size_t count)
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003118{
3119 int n;
3120
3121 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
3122 scsi_debug_virtual_gb = n;
FUJITA Tomonori28898872008-03-30 00:59:55 +09003123
3124 sdebug_capacity = get_sdebug_capacity();
3125
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003126 return count;
3127 }
3128 return -EINVAL;
3129}
Akinobu Mita82069372013-10-14 22:48:04 +09003130static DRIVER_ATTR_RW(virtual_gb);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003131
Akinobu Mita82069372013-10-14 22:48:04 +09003132static ssize_t add_host_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003133{
3134 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_add_host);
3135}
3136
Akinobu Mita82069372013-10-14 22:48:04 +09003137static ssize_t add_host_store(struct device_driver *ddp, const char *buf,
3138 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003139{
FUJITA Tomonorif3df41c2008-03-20 11:09:15 +09003140 int delta_hosts;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003141
FUJITA Tomonorif3df41c2008-03-20 11:09:15 +09003142 if (sscanf(buf, "%d", &delta_hosts) != 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003143 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003144 if (delta_hosts > 0) {
3145 do {
3146 sdebug_add_adapter();
3147 } while (--delta_hosts);
3148 } else if (delta_hosts < 0) {
3149 do {
3150 sdebug_remove_adapter();
3151 } while (++delta_hosts);
3152 }
3153 return count;
3154}
Akinobu Mita82069372013-10-14 22:48:04 +09003155static DRIVER_ATTR_RW(add_host);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003156
Akinobu Mita82069372013-10-14 22:48:04 +09003157static ssize_t vpd_use_hostno_show(struct device_driver *ddp, char *buf)
Douglas Gilbert23183912006-09-16 20:30:47 -04003158{
3159 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_vpd_use_hostno);
3160}
Akinobu Mita82069372013-10-14 22:48:04 +09003161static ssize_t vpd_use_hostno_store(struct device_driver *ddp, const char *buf,
3162 size_t count)
Douglas Gilbert23183912006-09-16 20:30:47 -04003163{
3164 int n;
3165
3166 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
3167 scsi_debug_vpd_use_hostno = n;
3168 return count;
3169 }
3170 return -EINVAL;
3171}
Akinobu Mita82069372013-10-14 22:48:04 +09003172static DRIVER_ATTR_RW(vpd_use_hostno);
Douglas Gilbert23183912006-09-16 20:30:47 -04003173
Akinobu Mita82069372013-10-14 22:48:04 +09003174static ssize_t sector_size_show(struct device_driver *ddp, char *buf)
Martin K. Petersen597136a2008-06-05 00:12:59 -04003175{
3176 return scnprintf(buf, PAGE_SIZE, "%u\n", scsi_debug_sector_size);
3177}
Akinobu Mita82069372013-10-14 22:48:04 +09003178static DRIVER_ATTR_RO(sector_size);
Martin K. Petersen597136a2008-06-05 00:12:59 -04003179
Akinobu Mita82069372013-10-14 22:48:04 +09003180static ssize_t dix_show(struct device_driver *ddp, char *buf)
Martin K. Petersenc6a44282009-01-04 03:08:19 -05003181{
3182 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dix);
3183}
Akinobu Mita82069372013-10-14 22:48:04 +09003184static DRIVER_ATTR_RO(dix);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05003185
Akinobu Mita82069372013-10-14 22:48:04 +09003186static ssize_t dif_show(struct device_driver *ddp, char *buf)
Martin K. Petersenc6a44282009-01-04 03:08:19 -05003187{
3188 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dif);
3189}
Akinobu Mita82069372013-10-14 22:48:04 +09003190static DRIVER_ATTR_RO(dif);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05003191
Akinobu Mita82069372013-10-14 22:48:04 +09003192static ssize_t guard_show(struct device_driver *ddp, char *buf)
Martin K. Petersenc6a44282009-01-04 03:08:19 -05003193{
Akinobu Mita68aee7b2013-09-18 21:27:27 +09003194 return scnprintf(buf, PAGE_SIZE, "%u\n", scsi_debug_guard);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05003195}
Akinobu Mita82069372013-10-14 22:48:04 +09003196static DRIVER_ATTR_RO(guard);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05003197
Akinobu Mita82069372013-10-14 22:48:04 +09003198static ssize_t ato_show(struct device_driver *ddp, char *buf)
Martin K. Petersenc6a44282009-01-04 03:08:19 -05003199{
3200 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_ato);
3201}
Akinobu Mita82069372013-10-14 22:48:04 +09003202static DRIVER_ATTR_RO(ato);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05003203
Akinobu Mita82069372013-10-14 22:48:04 +09003204static ssize_t map_show(struct device_driver *ddp, char *buf)
Martin K. Petersen44d92692009-10-15 14:45:27 -04003205{
3206 ssize_t count;
3207
Martin K. Petersen5b94e232011-03-08 02:08:11 -05003208 if (!scsi_debug_lbp())
Martin K. Petersen44d92692009-10-15 14:45:27 -04003209 return scnprintf(buf, PAGE_SIZE, "0-%u\n",
3210 sdebug_store_sectors);
3211
3212 count = bitmap_scnlistprintf(buf, PAGE_SIZE, map_storep, map_size);
3213
3214 buf[count++] = '\n';
3215 buf[count++] = 0;
3216
3217 return count;
3218}
Akinobu Mita82069372013-10-14 22:48:04 +09003219static DRIVER_ATTR_RO(map);
Martin K. Petersen44d92692009-10-15 14:45:27 -04003220
Akinobu Mita82069372013-10-14 22:48:04 +09003221static ssize_t removable_show(struct device_driver *ddp, char *buf)
Martin Pittd9867882012-09-06 12:04:33 +02003222{
3223 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_removable ? 1 : 0);
3224}
Akinobu Mita82069372013-10-14 22:48:04 +09003225static ssize_t removable_store(struct device_driver *ddp, const char *buf,
3226 size_t count)
Martin Pittd9867882012-09-06 12:04:33 +02003227{
3228 int n;
3229
3230 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
3231 scsi_debug_removable = (n > 0);
3232 return count;
3233 }
3234 return -EINVAL;
3235}
Akinobu Mita82069372013-10-14 22:48:04 +09003236static DRIVER_ATTR_RW(removable);
Martin Pittd9867882012-09-06 12:04:33 +02003237
Akinobu Mita82069372013-10-14 22:48:04 +09003238/* Note: The following array creates attribute files in the
Douglas Gilbert23183912006-09-16 20:30:47 -04003239 /sys/bus/pseudo/drivers/scsi_debug directory. The advantage of these
3240 files (over those found in the /sys/module/scsi_debug/parameters
3241 directory) is that auxiliary actions can be triggered when an attribute
3242 is changed. For example see: sdebug_add_host_store() above.
3243 */
Randy Dunlap6ecaff72006-07-11 20:53:22 -07003244
Akinobu Mita82069372013-10-14 22:48:04 +09003245static struct attribute *sdebug_drv_attrs[] = {
3246 &driver_attr_delay.attr,
3247 &driver_attr_opts.attr,
3248 &driver_attr_ptype.attr,
3249 &driver_attr_dsense.attr,
3250 &driver_attr_fake_rw.attr,
3251 &driver_attr_no_lun_0.attr,
3252 &driver_attr_num_tgts.attr,
3253 &driver_attr_dev_size_mb.attr,
3254 &driver_attr_num_parts.attr,
3255 &driver_attr_every_nth.attr,
3256 &driver_attr_max_luns.attr,
3257 &driver_attr_max_queue.attr,
3258 &driver_attr_no_uld.attr,
3259 &driver_attr_scsi_level.attr,
3260 &driver_attr_virtual_gb.attr,
3261 &driver_attr_add_host.attr,
3262 &driver_attr_vpd_use_hostno.attr,
3263 &driver_attr_sector_size.attr,
3264 &driver_attr_dix.attr,
3265 &driver_attr_dif.attr,
3266 &driver_attr_guard.attr,
3267 &driver_attr_ato.attr,
3268 &driver_attr_map.attr,
3269 &driver_attr_removable.attr,
3270 NULL,
3271};
3272ATTRIBUTE_GROUPS(sdebug_drv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003273
Akinobu Mita11ddcec2014-02-26 22:56:59 +09003274static struct device *pseudo_primary;
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003275
Linus Torvalds1da177e2005-04-16 15:20:36 -07003276static int __init scsi_debug_init(void)
3277{
FUJITA Tomonori5f2578e2008-03-30 00:59:57 +09003278 unsigned long sz;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003279 int host_to_add;
3280 int k;
Randy Dunlap6ecaff72006-07-11 20:53:22 -07003281 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003282
Martin K. Petersen597136a2008-06-05 00:12:59 -04003283 switch (scsi_debug_sector_size) {
3284 case 512:
3285 case 1024:
3286 case 2048:
3287 case 4096:
3288 break;
3289 default:
Martin K. Petersenc6a44282009-01-04 03:08:19 -05003290 printk(KERN_ERR "scsi_debug_init: invalid sector_size %d\n",
Martin K. Petersen597136a2008-06-05 00:12:59 -04003291 scsi_debug_sector_size);
3292 return -EINVAL;
3293 }
3294
Martin K. Petersenc6a44282009-01-04 03:08:19 -05003295 switch (scsi_debug_dif) {
3296
3297 case SD_DIF_TYPE0_PROTECTION:
3298 case SD_DIF_TYPE1_PROTECTION:
Martin K. Petersen395cef02009-09-18 17:33:03 -04003299 case SD_DIF_TYPE2_PROTECTION:
Martin K. Petersenc6a44282009-01-04 03:08:19 -05003300 case SD_DIF_TYPE3_PROTECTION:
3301 break;
3302
3303 default:
Martin K. Petersen395cef02009-09-18 17:33:03 -04003304 printk(KERN_ERR "scsi_debug_init: dif must be 0, 1, 2 or 3\n");
Martin K. Petersenc6a44282009-01-04 03:08:19 -05003305 return -EINVAL;
3306 }
3307
3308 if (scsi_debug_guard > 1) {
3309 printk(KERN_ERR "scsi_debug_init: guard must be 0 or 1\n");
3310 return -EINVAL;
3311 }
3312
3313 if (scsi_debug_ato > 1) {
3314 printk(KERN_ERR "scsi_debug_init: ato must be 0 or 1\n");
3315 return -EINVAL;
3316 }
3317
Martin K. Petersenea61fca2009-05-15 00:40:33 -04003318 if (scsi_debug_physblk_exp > 15) {
3319 printk(KERN_ERR "scsi_debug_init: invalid physblk_exp %u\n",
3320 scsi_debug_physblk_exp);
3321 return -EINVAL;
3322 }
3323
3324 if (scsi_debug_lowest_aligned > 0x3fff) {
3325 printk(KERN_ERR "scsi_debug_init: lowest_aligned too big: %u\n",
3326 scsi_debug_lowest_aligned);
3327 return -EINVAL;
3328 }
3329
Linus Torvalds1da177e2005-04-16 15:20:36 -07003330 if (scsi_debug_dev_size_mb < 1)
3331 scsi_debug_dev_size_mb = 1; /* force minimum 1 MB ramdisk */
FUJITA Tomonori5f2578e2008-03-30 00:59:57 +09003332 sz = (unsigned long)scsi_debug_dev_size_mb * 1048576;
Martin K. Petersen597136a2008-06-05 00:12:59 -04003333 sdebug_store_sectors = sz / scsi_debug_sector_size;
FUJITA Tomonori28898872008-03-30 00:59:55 +09003334 sdebug_capacity = get_sdebug_capacity();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003335
3336 /* play around with geometry, don't waste too much on track 0 */
3337 sdebug_heads = 8;
3338 sdebug_sectors_per = 32;
3339 if (scsi_debug_dev_size_mb >= 16)
3340 sdebug_heads = 32;
3341 else if (scsi_debug_dev_size_mb >= 256)
3342 sdebug_heads = 64;
3343 sdebug_cylinders_per = (unsigned long)sdebug_capacity /
3344 (sdebug_sectors_per * sdebug_heads);
3345 if (sdebug_cylinders_per >= 1024) {
3346 /* other LLDs do this; implies >= 1GB ram disk ... */
3347 sdebug_heads = 255;
3348 sdebug_sectors_per = 63;
3349 sdebug_cylinders_per = (unsigned long)sdebug_capacity /
3350 (sdebug_sectors_per * sdebug_heads);
3351 }
3352
Linus Torvalds1da177e2005-04-16 15:20:36 -07003353 fake_storep = vmalloc(sz);
3354 if (NULL == fake_storep) {
3355 printk(KERN_ERR "scsi_debug_init: out of memory, 1\n");
3356 return -ENOMEM;
3357 }
3358 memset(fake_storep, 0, sz);
3359 if (scsi_debug_num_parts > 0)
FUJITA Tomonorif58b0ef2008-03-30 00:59:54 +09003360 sdebug_build_parts(fake_storep, sz);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003361
Akinobu Mita7cb69d02013-06-29 17:59:16 +09003362 if (scsi_debug_dix) {
Martin K. Petersenc6a44282009-01-04 03:08:19 -05003363 int dif_size;
3364
3365 dif_size = sdebug_store_sectors * sizeof(struct sd_dif_tuple);
3366 dif_storep = vmalloc(dif_size);
3367
3368 printk(KERN_ERR "scsi_debug_init: dif_storep %u bytes @ %p\n",
3369 dif_size, dif_storep);
3370
3371 if (dif_storep == NULL) {
3372 printk(KERN_ERR "scsi_debug_init: out of mem. (DIX)\n");
3373 ret = -ENOMEM;
3374 goto free_vm;
3375 }
3376
3377 memset(dif_storep, 0xff, dif_size);
3378 }
3379
Martin K. Petersen5b94e232011-03-08 02:08:11 -05003380 /* Logical Block Provisioning */
3381 if (scsi_debug_lbp()) {
Martin K. Petersen60147592010-08-19 11:49:00 -04003382 scsi_debug_unmap_max_blocks =
3383 clamp(scsi_debug_unmap_max_blocks, 0U, 0xffffffffU);
3384
3385 scsi_debug_unmap_max_desc =
3386 clamp(scsi_debug_unmap_max_desc, 0U, 256U);
3387
3388 scsi_debug_unmap_granularity =
3389 clamp(scsi_debug_unmap_granularity, 1U, 0xffffffffU);
3390
3391 if (scsi_debug_unmap_alignment &&
Akinobu Mitaac170782013-04-16 22:11:56 +09003392 scsi_debug_unmap_granularity <=
3393 scsi_debug_unmap_alignment) {
Martin K. Petersen44d92692009-10-15 14:45:27 -04003394 printk(KERN_ERR
Akinobu Mitaac170782013-04-16 22:11:56 +09003395 "%s: ERR: unmap_granularity <= unmap_alignment\n",
Martin K. Petersen44d92692009-10-15 14:45:27 -04003396 __func__);
3397 return -EINVAL;
3398 }
3399
Akinobu Mitab90ebc32013-04-16 22:11:58 +09003400 map_size = lba_to_map_index(sdebug_store_sectors - 1) + 1;
3401 map_storep = vmalloc(BITS_TO_LONGS(map_size) * sizeof(long));
Martin K. Petersen44d92692009-10-15 14:45:27 -04003402
3403 printk(KERN_INFO "scsi_debug_init: %lu provisioning blocks\n",
3404 map_size);
3405
3406 if (map_storep == NULL) {
3407 printk(KERN_ERR "scsi_debug_init: out of mem. (MAP)\n");
3408 ret = -ENOMEM;
3409 goto free_vm;
3410 }
3411
Akinobu Mitab90ebc32013-04-16 22:11:58 +09003412 bitmap_zero(map_storep, map_size);
Martin K. Petersen44d92692009-10-15 14:45:27 -04003413
3414 /* Map first 1KB for partition table */
3415 if (scsi_debug_num_parts)
3416 map_region(0, 2);
3417 }
3418
Nicholas Bellinger9b906772010-09-06 17:24:28 -07003419 pseudo_primary = root_device_register("pseudo_0");
3420 if (IS_ERR(pseudo_primary)) {
3421 printk(KERN_WARNING "scsi_debug: root_device_register() error\n");
3422 ret = PTR_ERR(pseudo_primary);
Randy Dunlap6ecaff72006-07-11 20:53:22 -07003423 goto free_vm;
3424 }
3425 ret = bus_register(&pseudo_lld_bus);
3426 if (ret < 0) {
3427 printk(KERN_WARNING "scsi_debug: bus_register error: %d\n",
3428 ret);
3429 goto dev_unreg;
3430 }
3431 ret = driver_register(&sdebug_driverfs_driver);
3432 if (ret < 0) {
3433 printk(KERN_WARNING "scsi_debug: driver_register error: %d\n",
3434 ret);
3435 goto bus_unreg;
3436 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003437
Randy Dunlap6ecaff72006-07-11 20:53:22 -07003438 init_all_queued();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003439
Linus Torvalds1da177e2005-04-16 15:20:36 -07003440 host_to_add = scsi_debug_add_host;
3441 scsi_debug_add_host = 0;
3442
3443 for (k = 0; k < host_to_add; k++) {
3444 if (sdebug_add_adapter()) {
3445 printk(KERN_ERR "scsi_debug_init: "
3446 "sdebug_add_adapter failed k=%d\n", k);
3447 break;
3448 }
3449 }
3450
3451 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) {
3452 printk(KERN_INFO "scsi_debug_init: built %d host(s)\n",
3453 scsi_debug_add_host);
3454 }
3455 return 0;
Randy Dunlap6ecaff72006-07-11 20:53:22 -07003456
Randy Dunlap6ecaff72006-07-11 20:53:22 -07003457bus_unreg:
3458 bus_unregister(&pseudo_lld_bus);
3459dev_unreg:
Nicholas Bellinger9b906772010-09-06 17:24:28 -07003460 root_device_unregister(pseudo_primary);
Randy Dunlap6ecaff72006-07-11 20:53:22 -07003461free_vm:
Martin K. Petersen44d92692009-10-15 14:45:27 -04003462 if (map_storep)
3463 vfree(map_storep);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05003464 if (dif_storep)
3465 vfree(dif_storep);
Randy Dunlap6ecaff72006-07-11 20:53:22 -07003466 vfree(fake_storep);
3467
3468 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003469}
3470
3471static void __exit scsi_debug_exit(void)
3472{
3473 int k = scsi_debug_add_host;
3474
3475 stop_all_queued();
3476 for (; k; k--)
3477 sdebug_remove_adapter();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003478 driver_unregister(&sdebug_driverfs_driver);
3479 bus_unregister(&pseudo_lld_bus);
Nicholas Bellinger9b906772010-09-06 17:24:28 -07003480 root_device_unregister(pseudo_primary);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003481
Martin K. Petersenc6a44282009-01-04 03:08:19 -05003482 if (dif_storep)
3483 vfree(dif_storep);
3484
Linus Torvalds1da177e2005-04-16 15:20:36 -07003485 vfree(fake_storep);
3486}
3487
3488device_initcall(scsi_debug_init);
3489module_exit(scsi_debug_exit);
3490
Linus Torvalds1da177e2005-04-16 15:20:36 -07003491static void sdebug_release_adapter(struct device * dev)
3492{
3493 struct sdebug_host_info *sdbg_host;
3494
3495 sdbg_host = to_sdebug_host(dev);
3496 kfree(sdbg_host);
3497}
3498
3499static int sdebug_add_adapter(void)
3500{
3501 int k, devs_per_host;
3502 int error = 0;
3503 struct sdebug_host_info *sdbg_host;
FUJITA Tomonori8b40228f2008-03-20 11:09:18 +09003504 struct sdebug_dev_info *sdbg_devinfo, *tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003505
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003506 sdbg_host = kzalloc(sizeof(*sdbg_host),GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003507 if (NULL == sdbg_host) {
3508 printk(KERN_ERR "%s: out of memory at line %d\n",
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07003509 __func__, __LINE__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003510 return -ENOMEM;
3511 }
3512
Linus Torvalds1da177e2005-04-16 15:20:36 -07003513 INIT_LIST_HEAD(&sdbg_host->dev_info_list);
3514
3515 devs_per_host = scsi_debug_num_tgts * scsi_debug_max_luns;
3516 for (k = 0; k < devs_per_host; k++) {
FUJITA Tomonori5cb2fc02008-03-20 11:09:16 +09003517 sdbg_devinfo = sdebug_device_create(sdbg_host, GFP_KERNEL);
3518 if (!sdbg_devinfo) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003519 printk(KERN_ERR "%s: out of memory at line %d\n",
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07003520 __func__, __LINE__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003521 error = -ENOMEM;
3522 goto clean;
3523 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003524 }
3525
3526 spin_lock(&sdebug_host_list_lock);
3527 list_add_tail(&sdbg_host->host_list, &sdebug_host_list);
3528 spin_unlock(&sdebug_host_list_lock);
3529
3530 sdbg_host->dev.bus = &pseudo_lld_bus;
Nicholas Bellinger9b906772010-09-06 17:24:28 -07003531 sdbg_host->dev.parent = pseudo_primary;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003532 sdbg_host->dev.release = &sdebug_release_adapter;
Kay Sievers71610f52008-12-03 22:41:36 +01003533 dev_set_name(&sdbg_host->dev, "adapter%d", scsi_debug_add_host);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003534
3535 error = device_register(&sdbg_host->dev);
3536
3537 if (error)
3538 goto clean;
3539
3540 ++scsi_debug_add_host;
3541 return error;
3542
3543clean:
FUJITA Tomonori8b40228f2008-03-20 11:09:18 +09003544 list_for_each_entry_safe(sdbg_devinfo, tmp, &sdbg_host->dev_info_list,
3545 dev_list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003546 list_del(&sdbg_devinfo->dev_list);
3547 kfree(sdbg_devinfo);
3548 }
3549
3550 kfree(sdbg_host);
3551 return error;
3552}
3553
3554static void sdebug_remove_adapter(void)
3555{
3556 struct sdebug_host_info * sdbg_host = NULL;
3557
3558 spin_lock(&sdebug_host_list_lock);
3559 if (!list_empty(&sdebug_host_list)) {
3560 sdbg_host = list_entry(sdebug_host_list.prev,
3561 struct sdebug_host_info, host_list);
3562 list_del(&sdbg_host->host_list);
3563 }
3564 spin_unlock(&sdebug_host_list_lock);
3565
3566 if (!sdbg_host)
3567 return;
3568
3569 device_unregister(&sdbg_host->dev);
3570 --scsi_debug_add_host;
3571}
3572
FUJITA Tomonori639db472008-03-20 11:09:19 +09003573static
Jeff Garzikf2812332010-11-16 02:10:29 -05003574int scsi_debug_queuecommand_lck(struct scsi_cmnd *SCpnt, done_funct_t done)
FUJITA Tomonori639db472008-03-20 11:09:19 +09003575{
3576 unsigned char *cmd = (unsigned char *) SCpnt->cmnd;
3577 int len, k;
3578 unsigned int num;
3579 unsigned long long lba;
Martin K. Petersen395cef02009-09-18 17:33:03 -04003580 u32 ei_lba;
FUJITA Tomonori639db472008-03-20 11:09:19 +09003581 int errsts = 0;
3582 int target = SCpnt->device->id;
3583 struct sdebug_dev_info *devip = NULL;
3584 int inj_recovered = 0;
3585 int inj_transport = 0;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05003586 int inj_dif = 0;
3587 int inj_dix = 0;
Christoph Hellwigb57d7c02014-05-01 16:51:51 +02003588 int inj_short = 0;
FUJITA Tomonori639db472008-03-20 11:09:19 +09003589 int delay_override = 0;
Martin K. Petersen44d92692009-10-15 14:45:27 -04003590 int unmap = 0;
FUJITA Tomonori639db472008-03-20 11:09:19 +09003591
3592 scsi_set_resid(SCpnt, 0);
3593 if ((SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) && cmd) {
3594 printk(KERN_INFO "scsi_debug: cmd ");
3595 for (k = 0, len = SCpnt->cmd_len; k < len; ++k)
3596 printk("%02x ", (int)cmd[k]);
3597 printk("\n");
3598 }
3599
3600 if (target == SCpnt->device->host->hostt->this_id) {
3601 printk(KERN_INFO "scsi_debug: initiator's id used as "
3602 "target!\n");
3603 return schedule_resp(SCpnt, NULL, done,
3604 DID_NO_CONNECT << 16, 0);
3605 }
3606
3607 if ((SCpnt->device->lun >= scsi_debug_max_luns) &&
3608 (SCpnt->device->lun != SAM2_WLUN_REPORT_LUNS))
3609 return schedule_resp(SCpnt, NULL, done,
3610 DID_NO_CONNECT << 16, 0);
3611 devip = devInfoReg(SCpnt->device);
3612 if (NULL == devip)
3613 return schedule_resp(SCpnt, NULL, done,
3614 DID_NO_CONNECT << 16, 0);
3615
3616 if ((scsi_debug_every_nth != 0) &&
3617 (++scsi_debug_cmnd_count >= abs(scsi_debug_every_nth))) {
3618 scsi_debug_cmnd_count = 0;
3619 if (scsi_debug_every_nth < -1)
3620 scsi_debug_every_nth = -1;
3621 if (SCSI_DEBUG_OPT_TIMEOUT & scsi_debug_opts)
3622 return 0; /* ignore command causing timeout */
Martin K. Petersen18a4d0a2012-02-09 13:48:53 -05003623 else if (SCSI_DEBUG_OPT_MAC_TIMEOUT & scsi_debug_opts &&
3624 scsi_medium_access_command(SCpnt))
3625 return 0; /* time out reads and writes */
FUJITA Tomonori639db472008-03-20 11:09:19 +09003626 else if (SCSI_DEBUG_OPT_RECOVERED_ERR & scsi_debug_opts)
3627 inj_recovered = 1; /* to reads and writes below */
3628 else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & scsi_debug_opts)
3629 inj_transport = 1; /* to reads and writes below */
Martin K. Petersenc6a44282009-01-04 03:08:19 -05003630 else if (SCSI_DEBUG_OPT_DIF_ERR & scsi_debug_opts)
3631 inj_dif = 1; /* to reads and writes below */
3632 else if (SCSI_DEBUG_OPT_DIX_ERR & scsi_debug_opts)
3633 inj_dix = 1; /* to reads and writes below */
Christoph Hellwigb57d7c02014-05-01 16:51:51 +02003634 else if (SCSI_DEBUG_OPT_SHORT_TRANSFER & scsi_debug_opts)
3635 inj_short = 1;
FUJITA Tomonori639db472008-03-20 11:09:19 +09003636 }
3637
3638 if (devip->wlun) {
3639 switch (*cmd) {
3640 case INQUIRY:
3641 case REQUEST_SENSE:
3642 case TEST_UNIT_READY:
3643 case REPORT_LUNS:
3644 break; /* only allowable wlun commands */
3645 default:
3646 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
3647 printk(KERN_INFO "scsi_debug: Opcode: 0x%x "
3648 "not supported for wlun\n", *cmd);
3649 mk_sense_buffer(devip, ILLEGAL_REQUEST,
3650 INVALID_OPCODE, 0);
3651 errsts = check_condition_result;
3652 return schedule_resp(SCpnt, devip, done, errsts,
3653 0);
3654 }
3655 }
3656
3657 switch (*cmd) {
3658 case INQUIRY: /* mandatory, ignore unit attention */
3659 delay_override = 1;
3660 errsts = resp_inquiry(SCpnt, target, devip);
3661 break;
3662 case REQUEST_SENSE: /* mandatory, ignore unit attention */
3663 delay_override = 1;
3664 errsts = resp_requests(SCpnt, devip);
3665 break;
3666 case REZERO_UNIT: /* actually this is REWIND for SSC */
3667 case START_STOP:
3668 errsts = resp_start_stop(SCpnt, devip);
3669 break;
3670 case ALLOW_MEDIUM_REMOVAL:
3671 errsts = check_readiness(SCpnt, 1, devip);
3672 if (errsts)
3673 break;
3674 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
3675 printk(KERN_INFO "scsi_debug: Medium removal %s\n",
3676 cmd[4] ? "inhibited" : "enabled");
3677 break;
3678 case SEND_DIAGNOSTIC: /* mandatory */
3679 errsts = check_readiness(SCpnt, 1, devip);
3680 break;
3681 case TEST_UNIT_READY: /* mandatory */
3682 delay_override = 1;
3683 errsts = check_readiness(SCpnt, 0, devip);
3684 break;
3685 case RESERVE:
3686 errsts = check_readiness(SCpnt, 1, devip);
3687 break;
3688 case RESERVE_10:
3689 errsts = check_readiness(SCpnt, 1, devip);
3690 break;
3691 case RELEASE:
3692 errsts = check_readiness(SCpnt, 1, devip);
3693 break;
3694 case RELEASE_10:
3695 errsts = check_readiness(SCpnt, 1, devip);
3696 break;
3697 case READ_CAPACITY:
3698 errsts = resp_readcap(SCpnt, devip);
3699 break;
3700 case SERVICE_ACTION_IN:
Martin K. Petersen44d92692009-10-15 14:45:27 -04003701 if (cmd[1] == SAI_READ_CAPACITY_16)
3702 errsts = resp_readcap16(SCpnt, devip);
3703 else if (cmd[1] == SAI_GET_LBA_STATUS) {
3704
Martin K. Petersen5b94e232011-03-08 02:08:11 -05003705 if (scsi_debug_lbp() == 0) {
Martin K. Petersen44d92692009-10-15 14:45:27 -04003706 mk_sense_buffer(devip, ILLEGAL_REQUEST,
3707 INVALID_COMMAND_OPCODE, 0);
3708 errsts = check_condition_result;
3709 } else
3710 errsts = resp_get_lba_status(SCpnt, devip);
3711 } else {
FUJITA Tomonori639db472008-03-20 11:09:19 +09003712 mk_sense_buffer(devip, ILLEGAL_REQUEST,
3713 INVALID_OPCODE, 0);
3714 errsts = check_condition_result;
FUJITA Tomonori639db472008-03-20 11:09:19 +09003715 }
FUJITA Tomonori639db472008-03-20 11:09:19 +09003716 break;
3717 case MAINTENANCE_IN:
3718 if (MI_REPORT_TARGET_PGS != cmd[1]) {
3719 mk_sense_buffer(devip, ILLEGAL_REQUEST,
3720 INVALID_OPCODE, 0);
3721 errsts = check_condition_result;
3722 break;
3723 }
3724 errsts = resp_report_tgtpgs(SCpnt, devip);
3725 break;
3726 case READ_16:
3727 case READ_12:
3728 case READ_10:
Martin K. Petersen395cef02009-09-18 17:33:03 -04003729 /* READ{10,12,16} and DIF Type 2 are natural enemies */
3730 if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
3731 cmd[1] & 0xe0) {
3732 mk_sense_buffer(devip, ILLEGAL_REQUEST,
3733 INVALID_COMMAND_OPCODE, 0);
3734 errsts = check_condition_result;
3735 break;
3736 }
3737
3738 if ((scsi_debug_dif == SD_DIF_TYPE1_PROTECTION ||
3739 scsi_debug_dif == SD_DIF_TYPE3_PROTECTION) &&
3740 (cmd[1] & 0xe0) == 0)
3741 printk(KERN_ERR "Unprotected RD/WR to DIF device\n");
3742
3743 /* fall through */
FUJITA Tomonori639db472008-03-20 11:09:19 +09003744 case READ_6:
Martin K. Petersen395cef02009-09-18 17:33:03 -04003745read:
FUJITA Tomonori639db472008-03-20 11:09:19 +09003746 errsts = check_readiness(SCpnt, 0, devip);
3747 if (errsts)
3748 break;
3749 if (scsi_debug_fake_rw)
3750 break;
Martin K. Petersen395cef02009-09-18 17:33:03 -04003751 get_data_transfer_info(cmd, &lba, &num, &ei_lba);
Christoph Hellwigb57d7c02014-05-01 16:51:51 +02003752
3753 if (inj_short)
3754 num /= 2;
3755
Martin K. Petersen395cef02009-09-18 17:33:03 -04003756 errsts = resp_read(SCpnt, lba, num, devip, ei_lba);
FUJITA Tomonori639db472008-03-20 11:09:19 +09003757 if (inj_recovered && (0 == errsts)) {
3758 mk_sense_buffer(devip, RECOVERED_ERROR,
3759 THRESHOLD_EXCEEDED, 0);
3760 errsts = check_condition_result;
3761 } else if (inj_transport && (0 == errsts)) {
3762 mk_sense_buffer(devip, ABORTED_COMMAND,
3763 TRANSPORT_PROBLEM, ACK_NAK_TO);
3764 errsts = check_condition_result;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05003765 } else if (inj_dif && (0 == errsts)) {
3766 mk_sense_buffer(devip, ABORTED_COMMAND, 0x10, 1);
3767 errsts = illegal_condition_result;
3768 } else if (inj_dix && (0 == errsts)) {
3769 mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x10, 1);
3770 errsts = illegal_condition_result;
FUJITA Tomonori639db472008-03-20 11:09:19 +09003771 }
3772 break;
3773 case REPORT_LUNS: /* mandatory, ignore unit attention */
3774 delay_override = 1;
3775 errsts = resp_report_luns(SCpnt, devip);
3776 break;
3777 case VERIFY: /* 10 byte SBC-2 command */
3778 errsts = check_readiness(SCpnt, 0, devip);
3779 break;
3780 case WRITE_16:
3781 case WRITE_12:
3782 case WRITE_10:
Martin K. Petersen395cef02009-09-18 17:33:03 -04003783 /* WRITE{10,12,16} and DIF Type 2 are natural enemies */
3784 if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
3785 cmd[1] & 0xe0) {
3786 mk_sense_buffer(devip, ILLEGAL_REQUEST,
3787 INVALID_COMMAND_OPCODE, 0);
3788 errsts = check_condition_result;
3789 break;
3790 }
3791
3792 if ((scsi_debug_dif == SD_DIF_TYPE1_PROTECTION ||
3793 scsi_debug_dif == SD_DIF_TYPE3_PROTECTION) &&
3794 (cmd[1] & 0xe0) == 0)
3795 printk(KERN_ERR "Unprotected RD/WR to DIF device\n");
3796
3797 /* fall through */
FUJITA Tomonori639db472008-03-20 11:09:19 +09003798 case WRITE_6:
Martin K. Petersen395cef02009-09-18 17:33:03 -04003799write:
FUJITA Tomonori639db472008-03-20 11:09:19 +09003800 errsts = check_readiness(SCpnt, 0, devip);
3801 if (errsts)
3802 break;
3803 if (scsi_debug_fake_rw)
3804 break;
Martin K. Petersen395cef02009-09-18 17:33:03 -04003805 get_data_transfer_info(cmd, &lba, &num, &ei_lba);
3806 errsts = resp_write(SCpnt, lba, num, devip, ei_lba);
FUJITA Tomonori639db472008-03-20 11:09:19 +09003807 if (inj_recovered && (0 == errsts)) {
3808 mk_sense_buffer(devip, RECOVERED_ERROR,
3809 THRESHOLD_EXCEEDED, 0);
3810 errsts = check_condition_result;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05003811 } else if (inj_dif && (0 == errsts)) {
3812 mk_sense_buffer(devip, ABORTED_COMMAND, 0x10, 1);
3813 errsts = illegal_condition_result;
3814 } else if (inj_dix && (0 == errsts)) {
3815 mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x10, 1);
3816 errsts = illegal_condition_result;
FUJITA Tomonori639db472008-03-20 11:09:19 +09003817 }
3818 break;
Martin K. Petersen44d92692009-10-15 14:45:27 -04003819 case WRITE_SAME_16:
Martin K. Petersen5b94e232011-03-08 02:08:11 -05003820 case WRITE_SAME:
Martin K. Petersen60147592010-08-19 11:49:00 -04003821 if (cmd[1] & 0x8) {
Martin K. Petersen5b94e232011-03-08 02:08:11 -05003822 if ((*cmd == WRITE_SAME_16 && scsi_debug_lbpws == 0) ||
3823 (*cmd == WRITE_SAME && scsi_debug_lbpws10 == 0)) {
Martin K. Petersen60147592010-08-19 11:49:00 -04003824 mk_sense_buffer(devip, ILLEGAL_REQUEST,
3825 INVALID_FIELD_IN_CDB, 0);
3826 errsts = check_condition_result;
3827 } else
3828 unmap = 1;
3829 }
3830 if (errsts)
3831 break;
Martin K. Petersen44d92692009-10-15 14:45:27 -04003832 errsts = check_readiness(SCpnt, 0, devip);
3833 if (errsts)
3834 break;
3835 get_data_transfer_info(cmd, &lba, &num, &ei_lba);
3836 errsts = resp_write_same(SCpnt, lba, num, devip, ei_lba, unmap);
3837 break;
3838 case UNMAP:
3839 errsts = check_readiness(SCpnt, 0, devip);
3840 if (errsts)
3841 break;
3842
Martin K. Petersen5b94e232011-03-08 02:08:11 -05003843 if (scsi_debug_unmap_max_desc == 0 || scsi_debug_lbpu == 0) {
Martin K. Petersen44d92692009-10-15 14:45:27 -04003844 mk_sense_buffer(devip, ILLEGAL_REQUEST,
3845 INVALID_COMMAND_OPCODE, 0);
3846 errsts = check_condition_result;
3847 } else
3848 errsts = resp_unmap(SCpnt, devip);
3849 break;
FUJITA Tomonori639db472008-03-20 11:09:19 +09003850 case MODE_SENSE:
3851 case MODE_SENSE_10:
3852 errsts = resp_mode_sense(SCpnt, target, devip);
3853 break;
3854 case MODE_SELECT:
3855 errsts = resp_mode_select(SCpnt, 1, devip);
3856 break;
3857 case MODE_SELECT_10:
3858 errsts = resp_mode_select(SCpnt, 0, devip);
3859 break;
3860 case LOG_SENSE:
3861 errsts = resp_log_sense(SCpnt, devip);
3862 break;
3863 case SYNCHRONIZE_CACHE:
3864 delay_override = 1;
3865 errsts = check_readiness(SCpnt, 0, devip);
3866 break;
3867 case WRITE_BUFFER:
3868 errsts = check_readiness(SCpnt, 1, devip);
3869 break;
3870 case XDWRITEREAD_10:
3871 if (!scsi_bidi_cmnd(SCpnt)) {
3872 mk_sense_buffer(devip, ILLEGAL_REQUEST,
3873 INVALID_FIELD_IN_CDB, 0);
3874 errsts = check_condition_result;
3875 break;
3876 }
3877
3878 errsts = check_readiness(SCpnt, 0, devip);
3879 if (errsts)
3880 break;
3881 if (scsi_debug_fake_rw)
3882 break;
Martin K. Petersen395cef02009-09-18 17:33:03 -04003883 get_data_transfer_info(cmd, &lba, &num, &ei_lba);
3884 errsts = resp_read(SCpnt, lba, num, devip, ei_lba);
FUJITA Tomonori639db472008-03-20 11:09:19 +09003885 if (errsts)
3886 break;
Martin K. Petersen395cef02009-09-18 17:33:03 -04003887 errsts = resp_write(SCpnt, lba, num, devip, ei_lba);
FUJITA Tomonori639db472008-03-20 11:09:19 +09003888 if (errsts)
3889 break;
3890 errsts = resp_xdwriteread(SCpnt, lba, num, devip);
3891 break;
Martin K. Petersen395cef02009-09-18 17:33:03 -04003892 case VARIABLE_LENGTH_CMD:
3893 if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION) {
3894
3895 if ((cmd[10] & 0xe0) == 0)
3896 printk(KERN_ERR
3897 "Unprotected RD/WR to DIF device\n");
3898
3899 if (cmd[9] == READ_32) {
3900 BUG_ON(SCpnt->cmd_len < 32);
3901 goto read;
3902 }
3903
3904 if (cmd[9] == WRITE_32) {
3905 BUG_ON(SCpnt->cmd_len < 32);
3906 goto write;
3907 }
3908 }
3909
3910 mk_sense_buffer(devip, ILLEGAL_REQUEST,
3911 INVALID_FIELD_IN_CDB, 0);
3912 errsts = check_condition_result;
3913 break;
3914
FUJITA Tomonori639db472008-03-20 11:09:19 +09003915 default:
3916 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
3917 printk(KERN_INFO "scsi_debug: Opcode: 0x%x not "
3918 "supported\n", *cmd);
3919 errsts = check_readiness(SCpnt, 1, devip);
3920 if (errsts)
3921 break; /* Unit attention takes precedence */
3922 mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_OPCODE, 0);
3923 errsts = check_condition_result;
3924 break;
3925 }
3926 return schedule_resp(SCpnt, devip, done, errsts,
3927 (delay_override ? 0 : scsi_debug_delay));
3928}
3929
Jeff Garzikf2812332010-11-16 02:10:29 -05003930static DEF_SCSI_QCMD(scsi_debug_queuecommand)
3931
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +09003932static struct scsi_host_template sdebug_driver_template = {
Al Viroc8ed5552013-03-31 01:46:06 -04003933 .show_info = scsi_debug_show_info,
3934 .write_info = scsi_debug_write_info,
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +09003935 .proc_name = sdebug_proc_name,
3936 .name = "SCSI DEBUG",
3937 .info = scsi_debug_info,
3938 .slave_alloc = scsi_debug_slave_alloc,
3939 .slave_configure = scsi_debug_slave_configure,
3940 .slave_destroy = scsi_debug_slave_destroy,
3941 .ioctl = scsi_debug_ioctl,
3942 .queuecommand = scsi_debug_queuecommand,
3943 .eh_abort_handler = scsi_debug_abort,
3944 .eh_bus_reset_handler = scsi_debug_bus_reset,
3945 .eh_device_reset_handler = scsi_debug_device_reset,
3946 .eh_host_reset_handler = scsi_debug_host_reset,
3947 .bios_param = scsi_debug_biosparam,
3948 .can_queue = SCSI_DEBUG_CANQUEUE,
3949 .this_id = 7,
Akinobu Mita6bb5e6e2014-06-02 22:56:49 +09003950 .sg_tablesize = SCSI_MAX_SG_CHAIN_SEGMENTS,
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +09003951 .cmd_per_lun = 16,
Akinobu Mita6bb5e6e2014-06-02 22:56:49 +09003952 .max_sectors = -1U,
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +09003953 .use_clustering = DISABLE_CLUSTERING,
3954 .module = THIS_MODULE,
3955};
3956
Linus Torvalds1da177e2005-04-16 15:20:36 -07003957static int sdebug_driver_probe(struct device * dev)
3958{
3959 int error = 0;
3960 struct sdebug_host_info *sdbg_host;
3961 struct Scsi_Host *hpnt;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05003962 int host_prot;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003963
3964 sdbg_host = to_sdebug_host(dev);
3965
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04003966 sdebug_driver_template.can_queue = scsi_debug_max_queue;
Akinobu Mita0759c662014-02-26 22:57:04 +09003967 if (scsi_debug_clustering)
3968 sdebug_driver_template.use_clustering = ENABLE_CLUSTERING;
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04003969 hpnt = scsi_host_alloc(&sdebug_driver_template, sizeof(sdbg_host));
3970 if (NULL == hpnt) {
3971 printk(KERN_ERR "%s: scsi_register failed\n", __func__);
3972 error = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003973 return error;
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04003974 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003975
3976 sdbg_host->shost = hpnt;
3977 *((struct sdebug_host_info **)hpnt->hostdata) = sdbg_host;
3978 if ((hpnt->this_id >= 0) && (scsi_debug_num_tgts > hpnt->this_id))
3979 hpnt->max_id = scsi_debug_num_tgts + 1;
3980 else
3981 hpnt->max_id = scsi_debug_num_tgts;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003982 hpnt->max_lun = SAM2_WLUN_REPORT_LUNS; /* = scsi_debug_max_luns; */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003983
Martin K. Petersenc6a44282009-01-04 03:08:19 -05003984 host_prot = 0;
3985
3986 switch (scsi_debug_dif) {
3987
3988 case SD_DIF_TYPE1_PROTECTION:
3989 host_prot = SHOST_DIF_TYPE1_PROTECTION;
3990 if (scsi_debug_dix)
3991 host_prot |= SHOST_DIX_TYPE1_PROTECTION;
3992 break;
3993
3994 case SD_DIF_TYPE2_PROTECTION:
3995 host_prot = SHOST_DIF_TYPE2_PROTECTION;
3996 if (scsi_debug_dix)
3997 host_prot |= SHOST_DIX_TYPE2_PROTECTION;
3998 break;
3999
4000 case SD_DIF_TYPE3_PROTECTION:
4001 host_prot = SHOST_DIF_TYPE3_PROTECTION;
4002 if (scsi_debug_dix)
4003 host_prot |= SHOST_DIX_TYPE3_PROTECTION;
4004 break;
4005
4006 default:
4007 if (scsi_debug_dix)
4008 host_prot |= SHOST_DIX_TYPE0_PROTECTION;
4009 break;
4010 }
4011
4012 scsi_host_set_prot(hpnt, host_prot);
4013
4014 printk(KERN_INFO "scsi_debug: host protection%s%s%s%s%s%s%s\n",
4015 (host_prot & SHOST_DIF_TYPE1_PROTECTION) ? " DIF1" : "",
4016 (host_prot & SHOST_DIF_TYPE2_PROTECTION) ? " DIF2" : "",
4017 (host_prot & SHOST_DIF_TYPE3_PROTECTION) ? " DIF3" : "",
4018 (host_prot & SHOST_DIX_TYPE0_PROTECTION) ? " DIX0" : "",
4019 (host_prot & SHOST_DIX_TYPE1_PROTECTION) ? " DIX1" : "",
4020 (host_prot & SHOST_DIX_TYPE2_PROTECTION) ? " DIX2" : "",
4021 (host_prot & SHOST_DIX_TYPE3_PROTECTION) ? " DIX3" : "");
4022
4023 if (scsi_debug_guard == 1)
4024 scsi_host_set_guard(hpnt, SHOST_DIX_GUARD_IP);
4025 else
4026 scsi_host_set_guard(hpnt, SHOST_DIX_GUARD_CRC);
4027
Linus Torvalds1da177e2005-04-16 15:20:36 -07004028 error = scsi_add_host(hpnt, &sdbg_host->dev);
4029 if (error) {
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07004030 printk(KERN_ERR "%s: scsi_add_host failed\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004031 error = -ENODEV;
4032 scsi_host_put(hpnt);
4033 } else
4034 scsi_scan_host(hpnt);
4035
4036
4037 return error;
4038}
4039
4040static int sdebug_driver_remove(struct device * dev)
4041{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004042 struct sdebug_host_info *sdbg_host;
FUJITA Tomonori8b40228f2008-03-20 11:09:18 +09004043 struct sdebug_dev_info *sdbg_devinfo, *tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004044
4045 sdbg_host = to_sdebug_host(dev);
4046
4047 if (!sdbg_host) {
4048 printk(KERN_ERR "%s: Unable to locate host info\n",
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07004049 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004050 return -ENODEV;
4051 }
4052
4053 scsi_remove_host(sdbg_host->shost);
4054
FUJITA Tomonori8b40228f2008-03-20 11:09:18 +09004055 list_for_each_entry_safe(sdbg_devinfo, tmp, &sdbg_host->dev_info_list,
4056 dev_list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004057 list_del(&sdbg_devinfo->dev_list);
4058 kfree(sdbg_devinfo);
4059 }
4060
4061 scsi_host_put(sdbg_host->shost);
4062 return 0;
4063}
4064
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09004065static int pseudo_lld_bus_match(struct device *dev,
4066 struct device_driver *dev_driver)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004067{
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09004068 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004069}
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09004070
4071static struct bus_type pseudo_lld_bus = {
4072 .name = "pseudo",
4073 .match = pseudo_lld_bus_match,
4074 .probe = sdebug_driver_probe,
4075 .remove = sdebug_driver_remove,
Akinobu Mita82069372013-10-14 22:48:04 +09004076 .drv_groups = sdebug_drv_groups,
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09004077};