blob: dfcc45bb03b1f30e808e611a567c2f76cc734d3c [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
Tomas Winklerc12879702015-07-28 16:54:20 +030028
29#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
30
Linus Torvalds1da177e2005-04-16 15:20:36 -070031#include <linux/module.h>
32
33#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070034#include <linux/errno.h>
35#include <linux/timer.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090036#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070037#include <linux/types.h>
38#include <linux/string.h>
39#include <linux/genhd.h>
40#include <linux/fs.h>
41#include <linux/init.h>
42#include <linux/proc_fs.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#include <linux/vmalloc.h>
44#include <linux/moduleparam.h>
Jens Axboe852e0342007-07-16 10:19:24 +020045#include <linux/scatterlist.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070046#include <linux/blkdev.h>
Martin K. Petersenc6a44282009-01-04 03:08:19 -050047#include <linux/crc-t10dif.h>
Douglas Gilbertcbf67842014-07-26 11:55:35 -040048#include <linux/spinlock.h>
49#include <linux/interrupt.h>
50#include <linux/atomic.h>
51#include <linux/hrtimer.h>
Martin K. Petersenc6a44282009-01-04 03:08:19 -050052
53#include <net/checksum.h>
FUJITA Tomonori9ff26ee2008-03-02 18:30:15 +090054
Martin K. Petersen44d92692009-10-15 14:45:27 -040055#include <asm/unaligned.h>
56
FUJITA Tomonori9ff26ee2008-03-02 18:30:15 +090057#include <scsi/scsi.h>
58#include <scsi/scsi_cmnd.h>
59#include <scsi/scsi_device.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070060#include <scsi/scsi_host.h>
61#include <scsi/scsicam.h>
FUJITA Tomonoria34c4e92008-03-25 09:26:50 +090062#include <scsi/scsi_eh.h>
Douglas Gilbertcbf67842014-07-26 11:55:35 -040063#include <scsi/scsi_tcq.h>
Martin K. Petersen395cef02009-09-18 17:33:03 -040064#include <scsi/scsi_dbg.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070065
Martin K. Petersenc6a44282009-01-04 03:08:19 -050066#include "sd.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070067#include "scsi_logging.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070068
Douglas Gilbert22017ed2014-11-24 23:04:47 -050069#define SCSI_DEBUG_VERSION "1.85"
70static const char *scsi_debug_version_date = "20141022";
Douglas Gilbertcbf67842014-07-26 11:55:35 -040071
72#define MY_NAME "scsi_debug"
Linus Torvalds1da177e2005-04-16 15:20:36 -070073
Douglas Gilbert6f3cbf52007-01-05 00:05:25 -050074/* Additional Sense Code (ASC) */
Douglas Gilbertc65b1442006-06-06 00:11:24 -040075#define NO_ADDITIONAL_SENSE 0x0
76#define LOGICAL_UNIT_NOT_READY 0x4
Douglas Gilbertc2248fc2014-11-24 20:46:29 -050077#define LOGICAL_UNIT_COMMUNICATION_FAILURE 0x8
Linus Torvalds1da177e2005-04-16 15:20:36 -070078#define UNRECOVERED_READ_ERR 0x11
Douglas Gilbertc65b1442006-06-06 00:11:24 -040079#define PARAMETER_LIST_LENGTH_ERR 0x1a
Linus Torvalds1da177e2005-04-16 15:20:36 -070080#define INVALID_OPCODE 0x20
Douglas Gilbert22017ed2014-11-24 23:04:47 -050081#define LBA_OUT_OF_RANGE 0x21
Linus Torvalds1da177e2005-04-16 15:20:36 -070082#define INVALID_FIELD_IN_CDB 0x24
Douglas Gilbertc65b1442006-06-06 00:11:24 -040083#define INVALID_FIELD_IN_PARAM_LIST 0x26
Douglas Gilbertcbf67842014-07-26 11:55:35 -040084#define UA_RESET_ASC 0x29
85#define UA_CHANGED_ASC 0x2a
Ewan D. Milne19c8ead2014-12-04 11:49:27 -050086#define TARGET_CHANGED_ASC 0x3f
87#define LUNS_CHANGED_ASCQ 0x0e
Douglas Gilbert22017ed2014-11-24 23:04:47 -050088#define INSUFF_RES_ASC 0x55
89#define INSUFF_RES_ASCQ 0x3
Douglas Gilbertcbf67842014-07-26 11:55:35 -040090#define POWER_ON_RESET_ASCQ 0x0
91#define BUS_RESET_ASCQ 0x2 /* scsi bus reset occurred */
92#define MODE_CHANGED_ASCQ 0x1 /* mode parameters changed */
Douglas Gilbert22017ed2014-11-24 23:04:47 -050093#define CAPACITY_CHANGED_ASCQ 0x9
Linus Torvalds1da177e2005-04-16 15:20:36 -070094#define SAVING_PARAMS_UNSUP 0x39
Douglas Gilbert6f3cbf52007-01-05 00:05:25 -050095#define TRANSPORT_PROBLEM 0x4b
Douglas Gilbertc65b1442006-06-06 00:11:24 -040096#define THRESHOLD_EXCEEDED 0x5d
97#define LOW_POWER_COND_ON 0x5e
Douglas Gilbert22017ed2014-11-24 23:04:47 -050098#define MISCOMPARE_VERIFY_ASC 0x1d
Ewan D. Milneacafd0b2014-12-04 11:49:28 -050099#define MICROCODE_CHANGED_ASCQ 0x1 /* with TARGET_CHANGED_ASC */
100#define MICROCODE_CHANGED_WO_RESET_ASCQ 0x16
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101
Douglas Gilbert6f3cbf52007-01-05 00:05:25 -0500102/* Additional Sense Code Qualifier (ASCQ) */
103#define ACK_NAK_TO 0x3
104
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105
106/* Default values for driver parameters */
107#define DEF_NUM_HOST 1
108#define DEF_NUM_TGTS 1
109#define DEF_MAX_LUNS 1
110/* With these defaults, this driver will make 1 host with 1 target
111 * (id 0) containing 1 logical unit (lun 0). That is 1 device.
112 */
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500113#define DEF_ATO 1
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400114#define DEF_DELAY 1 /* if > 0 unit is a jiffy */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115#define DEF_DEV_SIZE_MB 8
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500116#define DEF_DIF 0
117#define DEF_DIX 0
118#define DEF_D_SENSE 0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119#define DEF_EVERY_NTH 0
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500120#define DEF_FAKE_RW 0
121#define DEF_GUARD 0
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400122#define DEF_HOST_LOCK 0
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500123#define DEF_LBPU 0
124#define DEF_LBPWS 0
125#define DEF_LBPWS10 0
Eric Sandeenbe1dd782012-03-08 00:03:59 -0600126#define DEF_LBPRZ 1
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500127#define DEF_LOWEST_ALIGNED 0
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400128#define DEF_NDELAY 0 /* if > 0 unit is a nanosecond */
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500129#define DEF_NO_LUN_0 0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130#define DEF_NUM_PARTS 0
131#define DEF_OPTS 0
Martin K. Petersene308b3d2010-03-23 01:12:27 -0400132#define DEF_OPT_BLKS 64
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500133#define DEF_PHYSBLK_EXP 0
134#define DEF_PTYPE 0
Martin Pittd9867882012-09-06 12:04:33 +0200135#define DEF_REMOVABLE false
Douglas Gilberte46b0342014-08-05 12:21:53 +0200136#define DEF_SCSI_LEVEL 6 /* INQUIRY, byte2 [6->SPC-4] */
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500137#define DEF_SECTOR_SIZE 512
138#define DEF_UNMAP_ALIGNMENT 0
139#define DEF_UNMAP_GRANULARITY 1
Martin K. Petersen60147592010-08-19 11:49:00 -0400140#define DEF_UNMAP_MAX_BLOCKS 0xFFFFFFFF
141#define DEF_UNMAP_MAX_DESC 256
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500142#define DEF_VIRTUAL_GB 0
143#define DEF_VPD_USE_HOSTNO 1
144#define DEF_WRITESAME_LENGTH 0xFFFF
Douglas Gilbertc2248fc2014-11-24 20:46:29 -0500145#define DEF_STRICT 0
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400146#define DELAY_OVERRIDDEN -9999
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147
148/* bit mask values for scsi_debug_opts */
149#define SCSI_DEBUG_OPT_NOISE 1
150#define SCSI_DEBUG_OPT_MEDIUM_ERR 2
151#define SCSI_DEBUG_OPT_TIMEOUT 4
152#define SCSI_DEBUG_OPT_RECOVERED_ERR 8
Douglas Gilbert6f3cbf52007-01-05 00:05:25 -0500153#define SCSI_DEBUG_OPT_TRANSPORT_ERR 16
Martin K. Petersenc6a44282009-01-04 03:08:19 -0500154#define SCSI_DEBUG_OPT_DIF_ERR 32
155#define SCSI_DEBUG_OPT_DIX_ERR 64
Martin K. Petersen18a4d0a2012-02-09 13:48:53 -0500156#define SCSI_DEBUG_OPT_MAC_TIMEOUT 128
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400157#define SCSI_DEBUG_OPT_SHORT_TRANSFER 0x100
158#define SCSI_DEBUG_OPT_Q_NOISE 0x200
159#define SCSI_DEBUG_OPT_ALL_TSF 0x400
160#define SCSI_DEBUG_OPT_RARE_TSF 0x800
161#define SCSI_DEBUG_OPT_N_WCE 0x1000
162#define SCSI_DEBUG_OPT_RESET_NOISE 0x2000
163#define SCSI_DEBUG_OPT_NO_CDB_NOISE 0x4000
164#define SCSI_DEBUG_OPT_ALL_NOISE (0x1 | 0x200 | 0x2000)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165/* When "every_nth" > 0 then modulo "every_nth" commands:
166 * - a no response is simulated if SCSI_DEBUG_OPT_TIMEOUT is set
167 * - a RECOVERED_ERROR is simulated on successful read and write
168 * commands if SCSI_DEBUG_OPT_RECOVERED_ERR is set.
Douglas Gilbert6f3cbf52007-01-05 00:05:25 -0500169 * - a TRANSPORT_ERROR is simulated on successful read and write
170 * commands if SCSI_DEBUG_OPT_TRANSPORT_ERR is set.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171 *
172 * When "every_nth" < 0 then after "- every_nth" commands:
173 * - a no response is simulated if SCSI_DEBUG_OPT_TIMEOUT is set
174 * - a RECOVERED_ERROR is simulated on successful read and write
175 * commands if SCSI_DEBUG_OPT_RECOVERED_ERR is set.
Douglas Gilbert6f3cbf52007-01-05 00:05:25 -0500176 * - a TRANSPORT_ERROR is simulated on successful read and write
177 * commands if SCSI_DEBUG_OPT_TRANSPORT_ERR is set.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178 * This will continue until some other action occurs (e.g. the user
179 * writing a new value (other than -1 or 1) to every_nth via sysfs).
180 */
181
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400182/* As indicated in SAM-5 and SPC-4 Unit Attentions (UAs)are returned in
183 * priority order. In the subset implemented here lower numbers have higher
184 * priority. The UA numbers should be a sequence starting from 0 with
185 * SDEBUG_NUM_UAS being 1 higher than the highest numbered UA. */
186#define SDEBUG_UA_POR 0 /* Power on, reset, or bus device reset */
187#define SDEBUG_UA_BUS_RESET 1
188#define SDEBUG_UA_MODE_CHANGED 2
Douglas Gilbert0d01c5d2014-11-24 20:27:51 -0500189#define SDEBUG_UA_CAPACITY_CHANGED 3
Ewan D. Milne19c8ead2014-12-04 11:49:27 -0500190#define SDEBUG_UA_LUNS_CHANGED 4
Ewan D. Milneacafd0b2014-12-04 11:49:28 -0500191#define SDEBUG_UA_MICROCODE_CHANGED 5 /* simulate firmware change */
192#define SDEBUG_UA_MICROCODE_CHANGED_WO_RESET 6
193#define SDEBUG_NUM_UAS 7
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400194
195/* for check_readiness() */
Douglas Gilbertc2248fc2014-11-24 20:46:29 -0500196#define UAS_ONLY 1 /* check for UAs only */
197#define UAS_TUR 0 /* if no UAs then check if media access possible */
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400198
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199/* when 1==SCSI_DEBUG_OPT_MEDIUM_ERR, a medium error is simulated at this
200 * sector on read commands: */
201#define OPT_MEDIUM_ERR_ADDR 0x1234 /* that's sector 4660 in decimal */
Douglas Gilbert32f7ef72011-03-11 10:43:35 -0500202#define OPT_MEDIUM_ERR_NUM 10 /* number of consecutive medium errs */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203
204/* If REPORT LUNS has luns >= 256 it can choose "flat space" (value 1)
205 * or "peripheral device" addressing (value 0) */
206#define SAM2_LUN_ADDRESS_METHOD 0
207
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400208/* SCSI_DEBUG_CANQUEUE is the maximum number of commands that can be queued
209 * (for response) at one time. Can be reduced by max_queue option. Command
210 * responses are not queued when delay=0 and ndelay=0. The per-device
211 * DEF_CMD_PER_LUN can be changed via sysfs:
212 * /sys/class/scsi_device/<h:c:t:l>/device/queue_depth but cannot exceed
213 * SCSI_DEBUG_CANQUEUE. */
214#define SCSI_DEBUG_CANQUEUE_WORDS 9 /* a WORD is bits in a long */
215#define SCSI_DEBUG_CANQUEUE (SCSI_DEBUG_CANQUEUE_WORDS * BITS_PER_LONG)
216#define DEF_CMD_PER_LUN 255
217
218#if DEF_CMD_PER_LUN > SCSI_DEBUG_CANQUEUE
219#warning "Expect DEF_CMD_PER_LUN <= SCSI_DEBUG_CANQUEUE"
220#endif
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -0400221
Douglas Gilbertc2248fc2014-11-24 20:46:29 -0500222/* SCSI opcodes (first byte of cdb) mapped onto these indexes */
223enum sdeb_opcode_index {
224 SDEB_I_INVALID_OPCODE = 0,
225 SDEB_I_INQUIRY = 1,
226 SDEB_I_REPORT_LUNS = 2,
227 SDEB_I_REQUEST_SENSE = 3,
228 SDEB_I_TEST_UNIT_READY = 4,
229 SDEB_I_MODE_SENSE = 5, /* 6, 10 */
230 SDEB_I_MODE_SELECT = 6, /* 6, 10 */
231 SDEB_I_LOG_SENSE = 7,
232 SDEB_I_READ_CAPACITY = 8, /* 10; 16 is in SA_IN(16) */
233 SDEB_I_READ = 9, /* 6, 10, 12, 16 */
234 SDEB_I_WRITE = 10, /* 6, 10, 12, 16 */
235 SDEB_I_START_STOP = 11,
236 SDEB_I_SERV_ACT_IN = 12, /* 12, 16 */
237 SDEB_I_SERV_ACT_OUT = 13, /* 12, 16 */
238 SDEB_I_MAINT_IN = 14,
239 SDEB_I_MAINT_OUT = 15,
240 SDEB_I_VERIFY = 16, /* 10 only */
241 SDEB_I_VARIABLE_LEN = 17,
242 SDEB_I_RESERVE = 18, /* 6, 10 */
243 SDEB_I_RELEASE = 19, /* 6, 10 */
244 SDEB_I_ALLOW_REMOVAL = 20, /* PREVENT ALLOW MEDIUM REMOVAL */
245 SDEB_I_REZERO_UNIT = 21, /* REWIND in SSC */
246 SDEB_I_ATA_PT = 22, /* 12, 16 */
247 SDEB_I_SEND_DIAG = 23,
248 SDEB_I_UNMAP = 24,
249 SDEB_I_XDWRITEREAD = 25, /* 10 only */
250 SDEB_I_WRITE_BUFFER = 26,
251 SDEB_I_WRITE_SAME = 27, /* 10, 16 */
252 SDEB_I_SYNC_CACHE = 28, /* 10 only */
253 SDEB_I_COMP_WRITE = 29,
254 SDEB_I_LAST_ELEMENT = 30, /* keep this last */
255};
256
257static const unsigned char opcode_ind_arr[256] = {
258/* 0x0; 0x0->0x1f: 6 byte cdbs */
259 SDEB_I_TEST_UNIT_READY, SDEB_I_REZERO_UNIT, 0, SDEB_I_REQUEST_SENSE,
260 0, 0, 0, 0,
261 SDEB_I_READ, 0, SDEB_I_WRITE, 0, 0, 0, 0, 0,
262 0, 0, SDEB_I_INQUIRY, 0, 0, SDEB_I_MODE_SELECT, SDEB_I_RESERVE,
263 SDEB_I_RELEASE,
264 0, 0, SDEB_I_MODE_SENSE, SDEB_I_START_STOP, 0, SDEB_I_SEND_DIAG,
265 SDEB_I_ALLOW_REMOVAL, 0,
266/* 0x20; 0x20->0x3f: 10 byte cdbs */
267 0, 0, 0, 0, 0, SDEB_I_READ_CAPACITY, 0, 0,
268 SDEB_I_READ, 0, SDEB_I_WRITE, 0, 0, 0, 0, SDEB_I_VERIFY,
269 0, 0, 0, 0, 0, SDEB_I_SYNC_CACHE, 0, 0,
270 0, 0, 0, SDEB_I_WRITE_BUFFER, 0, 0, 0, 0,
271/* 0x40; 0x40->0x5f: 10 byte cdbs */
272 0, SDEB_I_WRITE_SAME, SDEB_I_UNMAP, 0, 0, 0, 0, 0,
273 0, 0, 0, 0, 0, SDEB_I_LOG_SENSE, 0, 0,
274 0, 0, 0, SDEB_I_XDWRITEREAD, 0, SDEB_I_MODE_SELECT, SDEB_I_RESERVE,
275 SDEB_I_RELEASE,
276 0, 0, SDEB_I_MODE_SENSE, 0, 0, 0, 0, 0,
277/* 0x60; 0x60->0x7d are reserved */
278 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
279 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
280 0, SDEB_I_VARIABLE_LEN,
281/* 0x80; 0x80->0x9f: 16 byte cdbs */
282 0, 0, 0, 0, 0, SDEB_I_ATA_PT, 0, 0,
283 SDEB_I_READ, SDEB_I_COMP_WRITE, SDEB_I_WRITE, 0, 0, 0, 0, 0,
284 0, 0, 0, SDEB_I_WRITE_SAME, 0, 0, 0, 0,
285 0, 0, 0, 0, 0, 0, SDEB_I_SERV_ACT_IN, SDEB_I_SERV_ACT_OUT,
286/* 0xa0; 0xa0->0xbf: 12 byte cdbs */
287 SDEB_I_REPORT_LUNS, SDEB_I_ATA_PT, 0, SDEB_I_MAINT_IN,
288 SDEB_I_MAINT_OUT, 0, 0, 0,
289 SDEB_I_READ, SDEB_I_SERV_ACT_OUT, SDEB_I_WRITE, SDEB_I_SERV_ACT_IN,
290 0, 0, 0, 0,
291 0, 0, 0, 0, 0, 0, 0, 0,
292 0, 0, 0, 0, 0, 0, 0, 0,
293/* 0xc0; 0xc0->0xff: vendor specific */
294 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
295 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
296 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
297 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
298};
299
300#define F_D_IN 1
301#define F_D_OUT 2
302#define F_D_OUT_MAYBE 4 /* WRITE SAME, NDOB bit */
303#define F_D_UNKN 8
304#define F_RL_WLUN_OK 0x10
305#define F_SKIP_UA 0x20
306#define F_DELAY_OVERR 0x40
307#define F_SA_LOW 0x80 /* cdb byte 1, bits 4 to 0 */
308#define F_SA_HIGH 0x100 /* as used by variable length cdbs */
309#define F_INV_OP 0x200
310#define F_FAKE_RW 0x400
311#define F_M_ACCESS 0x800 /* media access */
312
313#define FF_RESPOND (F_RL_WLUN_OK | F_SKIP_UA | F_DELAY_OVERR)
314#define FF_DIRECT_IO (F_M_ACCESS | F_FAKE_RW)
315#define FF_SA (F_SA_HIGH | F_SA_LOW)
316
317struct sdebug_dev_info;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -0500318static int resp_inquiry(struct scsi_cmnd *, struct sdebug_dev_info *);
319static int resp_report_luns(struct scsi_cmnd *, struct sdebug_dev_info *);
320static int resp_requests(struct scsi_cmnd *, struct sdebug_dev_info *);
321static int resp_mode_sense(struct scsi_cmnd *, struct sdebug_dev_info *);
322static int resp_mode_select(struct scsi_cmnd *, struct sdebug_dev_info *);
323static int resp_log_sense(struct scsi_cmnd *, struct sdebug_dev_info *);
324static int resp_readcap(struct scsi_cmnd *, struct sdebug_dev_info *);
325static int resp_read_dt0(struct scsi_cmnd *, struct sdebug_dev_info *);
326static int resp_write_dt0(struct scsi_cmnd *, struct sdebug_dev_info *);
327static int resp_start_stop(struct scsi_cmnd *, struct sdebug_dev_info *);
328static int resp_readcap16(struct scsi_cmnd *, struct sdebug_dev_info *);
329static int resp_get_lba_status(struct scsi_cmnd *, struct sdebug_dev_info *);
330static int resp_report_tgtpgs(struct scsi_cmnd *, struct sdebug_dev_info *);
331static int resp_unmap(struct scsi_cmnd *, struct sdebug_dev_info *);
Douglas Gilbert38d5c832014-11-24 21:27:12 -0500332static int resp_rsup_opcodes(struct scsi_cmnd *, struct sdebug_dev_info *);
333static int resp_rsup_tmfs(struct scsi_cmnd *, struct sdebug_dev_info *);
Douglas Gilbertc2248fc2014-11-24 20:46:29 -0500334static int resp_write_same_10(struct scsi_cmnd *, struct sdebug_dev_info *);
335static int resp_write_same_16(struct scsi_cmnd *, struct sdebug_dev_info *);
336static int resp_xdwriteread_10(struct scsi_cmnd *, struct sdebug_dev_info *);
Douglas Gilbert38d5c832014-11-24 21:27:12 -0500337static int resp_comp_write(struct scsi_cmnd *, struct sdebug_dev_info *);
Ewan D. Milneacafd0b2014-12-04 11:49:28 -0500338static int resp_write_buffer(struct scsi_cmnd *, struct sdebug_dev_info *);
Douglas Gilbertc2248fc2014-11-24 20:46:29 -0500339
340struct opcode_info_t {
341 u8 num_attached; /* 0 if this is it (i.e. a leaf); use 0xff
342 * for terminating element */
343 u8 opcode; /* if num_attached > 0, preferred */
344 u16 sa; /* service action */
345 u32 flags; /* OR-ed set of SDEB_F_* */
346 int (*pfp)(struct scsi_cmnd *, struct sdebug_dev_info *);
347 const struct opcode_info_t *arrp; /* num_attached elements or NULL */
348 u8 len_mask[16]; /* len=len_mask[0], then mask for cdb[1]... */
349 /* ignore cdb bytes after position 15 */
350};
351
352static const struct opcode_info_t msense_iarr[1] = {
353 {0, 0x1a, 0, F_D_IN, NULL, NULL,
354 {6, 0xe8, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
355};
356
357static const struct opcode_info_t mselect_iarr[1] = {
358 {0, 0x15, 0, F_D_OUT, NULL, NULL,
359 {6, 0xf1, 0, 0, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
360};
361
362static const struct opcode_info_t read_iarr[3] = {
363 {0, 0x28, 0, F_D_IN | FF_DIRECT_IO, resp_read_dt0, NULL,/* READ(10) */
364 {10, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xc7, 0, 0,
365 0, 0, 0, 0} },
366 {0, 0x8, 0, F_D_IN | FF_DIRECT_IO, resp_read_dt0, NULL, /* READ(6) */
367 {6, 0xff, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
368 {0, 0xa8, 0, F_D_IN | FF_DIRECT_IO, resp_read_dt0, NULL,/* READ(12) */
369 {12, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f,
370 0xc7, 0, 0, 0, 0} },
371};
372
373static const struct opcode_info_t write_iarr[3] = {
374 {0, 0x2a, 0, F_D_OUT | FF_DIRECT_IO, resp_write_dt0, NULL, /* 10 */
375 {10, 0xfb, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xc7, 0, 0,
376 0, 0, 0, 0} },
377 {0, 0xa, 0, F_D_OUT | FF_DIRECT_IO, resp_write_dt0, NULL, /* 6 */
378 {6, 0xff, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
379 {0, 0xaa, 0, F_D_OUT | FF_DIRECT_IO, resp_write_dt0, NULL, /* 12 */
380 {12, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f,
381 0xc7, 0, 0, 0, 0} },
382};
383
384static const struct opcode_info_t sa_in_iarr[1] = {
385 {0, 0x9e, 0x12, F_SA_LOW | F_D_IN, resp_get_lba_status, NULL,
386 {16, 0x12, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
387 0xff, 0xff, 0xff, 0, 0xc7} },
388};
389
390static const struct opcode_info_t vl_iarr[1] = { /* VARIABLE LENGTH */
391 {0, 0x7f, 0xb, F_SA_HIGH | F_D_OUT | FF_DIRECT_IO, resp_write_dt0,
392 NULL, {32, 0xc7, 0, 0, 0, 0, 0x1f, 0x18, 0x0, 0xb, 0xfa,
393 0, 0xff, 0xff, 0xff, 0xff} }, /* WRITE(32) */
394};
395
396static const struct opcode_info_t maint_in_iarr[2] = {
Douglas Gilbert38d5c832014-11-24 21:27:12 -0500397 {0, 0xa3, 0xc, F_SA_LOW | F_D_IN, resp_rsup_opcodes, NULL,
Douglas Gilbertc2248fc2014-11-24 20:46:29 -0500398 {12, 0xc, 0x87, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0,
399 0xc7, 0, 0, 0, 0} },
Douglas Gilbert38d5c832014-11-24 21:27:12 -0500400 {0, 0xa3, 0xd, F_SA_LOW | F_D_IN, resp_rsup_tmfs, NULL,
Douglas Gilbertc2248fc2014-11-24 20:46:29 -0500401 {12, 0xd, 0x80, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0, 0xc7, 0, 0,
402 0, 0} },
403};
404
405static const struct opcode_info_t write_same_iarr[1] = {
406 {0, 0x93, 0, F_D_OUT_MAYBE | FF_DIRECT_IO, resp_write_same_16, NULL,
407 {16, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
408 0xff, 0xff, 0xff, 0x1f, 0xc7} },
409};
410
411static const struct opcode_info_t reserve_iarr[1] = {
412 {0, 0x16, 0, F_D_OUT, NULL, NULL, /* RESERVE(6) */
413 {6, 0x1f, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
414};
415
416static const struct opcode_info_t release_iarr[1] = {
417 {0, 0x17, 0, F_D_OUT, NULL, NULL, /* RELEASE(6) */
418 {6, 0x1f, 0xff, 0, 0, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
419};
420
421
422/* This array is accessed via SDEB_I_* values. Make sure all are mapped,
423 * plus the terminating elements for logic that scans this table such as
424 * REPORT SUPPORTED OPERATION CODES. */
425static const struct opcode_info_t opcode_info_arr[SDEB_I_LAST_ELEMENT + 1] = {
426/* 0 */
427 {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL,
428 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
429 {0, 0x12, 0, FF_RESPOND | F_D_IN, resp_inquiry, NULL,
430 {6, 0xe3, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
431 {0, 0xa0, 0, FF_RESPOND | F_D_IN, resp_report_luns, NULL,
432 {12, 0xe3, 0xff, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0, 0xc7, 0, 0,
433 0, 0} },
434 {0, 0x3, 0, FF_RESPOND | F_D_IN, resp_requests, NULL,
435 {6, 0xe1, 0, 0, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
436 {0, 0x0, 0, F_M_ACCESS | F_RL_WLUN_OK, NULL, NULL,/* TEST UNIT READY */
437 {6, 0, 0, 0, 0, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
438 {1, 0x5a, 0, F_D_IN, resp_mode_sense, msense_iarr,
439 {10, 0xf8, 0xff, 0xff, 0, 0, 0, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0,
440 0} },
441 {1, 0x55, 0, F_D_OUT, resp_mode_select, mselect_iarr,
442 {10, 0xf1, 0, 0, 0, 0, 0, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0} },
443 {0, 0x4d, 0, F_D_IN, resp_log_sense, NULL,
444 {10, 0xe3, 0xff, 0xff, 0, 0xff, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0,
445 0, 0, 0} },
446 {0, 0x25, 0, F_D_IN, resp_readcap, NULL,
447 {10, 0xe1, 0xff, 0xff, 0xff, 0xff, 0, 0, 0x1, 0xc7, 0, 0, 0, 0,
448 0, 0} },
449 {3, 0x88, 0, F_D_IN | FF_DIRECT_IO, resp_read_dt0, read_iarr,
450 {16, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
451 0xff, 0xff, 0xff, 0x9f, 0xc7} }, /* READ(16) */
452/* 10 */
453 {3, 0x8a, 0, F_D_OUT | FF_DIRECT_IO, resp_write_dt0, write_iarr,
454 {16, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
455 0xff, 0xff, 0xff, 0x9f, 0xc7} }, /* WRITE(16) */
456 {0, 0x1b, 0, 0, resp_start_stop, NULL, /* START STOP UNIT */
457 {6, 0x1, 0, 0xf, 0xf7, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
458 {1, 0x9e, 0x10, F_SA_LOW | F_D_IN, resp_readcap16, sa_in_iarr,
459 {16, 0x10, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
460 0xff, 0xff, 0xff, 0x1, 0xc7} }, /* READ CAPACITY(16) */
461 {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, /* SA OUT */
462 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
463 {2, 0xa3, 0xa, F_SA_LOW | F_D_IN, resp_report_tgtpgs, maint_in_iarr,
464 {12, 0xea, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0, 0xc7, 0, 0, 0,
465 0} },
466 {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, /* MAINT OUT */
467 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
468 {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, /* VERIFY */
469 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
470 {1, 0x7f, 0x9, F_SA_HIGH | F_D_IN | FF_DIRECT_IO, resp_read_dt0,
471 vl_iarr, {32, 0xc7, 0, 0, 0, 0, 0x1f, 0x18, 0x0, 0x9, 0xfe, 0,
472 0xff, 0xff, 0xff, 0xff} },/* VARIABLE LENGTH, READ(32) */
473 {1, 0x56, 0, F_D_OUT, NULL, reserve_iarr, /* RESERVE(10) */
474 {10, 0xff, 0xff, 0xff, 0, 0, 0, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0,
475 0} },
476 {1, 0x57, 0, F_D_OUT, NULL, release_iarr, /* RELEASE(10) */
477 {10, 0x13, 0xff, 0xff, 0, 0, 0, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0,
478 0} },
479/* 20 */
480 {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, /* ALLOW REMOVAL */
481 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
482 {0, 0x1, 0, 0, resp_start_stop, NULL, /* REWIND ?? */
483 {6, 0x1, 0, 0, 0, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
484 {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, /* ATA_PT */
485 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
486 {0, 0x1d, F_D_OUT, 0, NULL, NULL, /* SEND DIAGNOSTIC */
487 {6, 0xf7, 0, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
488 {0, 0x42, 0, F_D_OUT | FF_DIRECT_IO, resp_unmap, NULL, /* UNMAP */
489 {10, 0x1, 0, 0, 0, 0, 0x1f, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0} },
490 {0, 0x53, 0, F_D_IN | F_D_OUT | FF_DIRECT_IO, resp_xdwriteread_10,
491 NULL, {10, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xc7,
492 0, 0, 0, 0, 0, 0} },
Ewan D. Milneacafd0b2014-12-04 11:49:28 -0500493 {0, 0x3b, 0, F_D_OUT_MAYBE, resp_write_buffer, NULL,
494 {10, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7, 0, 0,
495 0, 0, 0, 0} }, /* WRITE_BUFFER */
Douglas Gilbertc2248fc2014-11-24 20:46:29 -0500496 {1, 0x41, 0, F_D_OUT_MAYBE | FF_DIRECT_IO, resp_write_same_10,
497 write_same_iarr, {10, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff,
498 0xff, 0xc7, 0, 0, 0, 0, 0, 0} },
499 {0, 0x35, 0, F_DELAY_OVERR | FF_DIRECT_IO, NULL, NULL, /* SYNC_CACHE */
500 {10, 0x7, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xc7, 0, 0,
501 0, 0, 0, 0} },
Douglas Gilbert38d5c832014-11-24 21:27:12 -0500502 {0, 0x89, 0, F_D_OUT | FF_DIRECT_IO, resp_comp_write, NULL,
Douglas Gilbertc2248fc2014-11-24 20:46:29 -0500503 {16, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0,
504 0, 0xff, 0x1f, 0xc7} }, /* COMPARE AND WRITE */
505
506/* 30 */
507 {0xff, 0, 0, 0, NULL, NULL, /* terminating element */
508 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
509};
510
Douglas Gilbert817fd662014-11-24 20:18:02 -0500511struct sdebug_scmd_extra_t {
512 bool inj_recovered;
513 bool inj_transport;
514 bool inj_dif;
515 bool inj_dix;
516 bool inj_short;
517};
518
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519static int scsi_debug_add_host = DEF_NUM_HOST;
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500520static int scsi_debug_ato = DEF_ATO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521static int scsi_debug_delay = DEF_DELAY;
522static int scsi_debug_dev_size_mb = DEF_DEV_SIZE_MB;
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500523static int scsi_debug_dif = DEF_DIF;
524static int scsi_debug_dix = DEF_DIX;
525static int scsi_debug_dsense = DEF_D_SENSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526static int scsi_debug_every_nth = DEF_EVERY_NTH;
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500527static int scsi_debug_fake_rw = DEF_FAKE_RW;
Akinobu Mita68aee7b2013-09-18 21:27:27 +0900528static unsigned int scsi_debug_guard = DEF_GUARD;
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500529static int scsi_debug_lowest_aligned = DEF_LOWEST_ALIGNED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530static int scsi_debug_max_luns = DEF_MAX_LUNS;
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -0400531static int scsi_debug_max_queue = SCSI_DEBUG_CANQUEUE;
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400532static atomic_t retired_max_queue; /* if > 0 then was prior max_queue */
533static int scsi_debug_ndelay = DEF_NDELAY;
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400534static int scsi_debug_no_lun_0 = DEF_NO_LUN_0;
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500535static int scsi_debug_no_uld = 0;
536static int scsi_debug_num_parts = DEF_NUM_PARTS;
537static int scsi_debug_num_tgts = DEF_NUM_TGTS; /* targets per host */
Martin K. Petersene308b3d2010-03-23 01:12:27 -0400538static int scsi_debug_opt_blks = DEF_OPT_BLKS;
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500539static int scsi_debug_opts = DEF_OPTS;
540static int scsi_debug_physblk_exp = DEF_PHYSBLK_EXP;
541static int scsi_debug_ptype = DEF_PTYPE; /* SCSI peripheral type (0==disk) */
542static int scsi_debug_scsi_level = DEF_SCSI_LEVEL;
543static int scsi_debug_sector_size = DEF_SECTOR_SIZE;
544static int scsi_debug_virtual_gb = DEF_VIRTUAL_GB;
545static int scsi_debug_vpd_use_hostno = DEF_VPD_USE_HOSTNO;
546static unsigned int scsi_debug_lbpu = DEF_LBPU;
547static unsigned int scsi_debug_lbpws = DEF_LBPWS;
548static unsigned int scsi_debug_lbpws10 = DEF_LBPWS10;
Eric Sandeenbe1dd782012-03-08 00:03:59 -0600549static unsigned int scsi_debug_lbprz = DEF_LBPRZ;
Martin K. Petersen60147592010-08-19 11:49:00 -0400550static unsigned int scsi_debug_unmap_alignment = DEF_UNMAP_ALIGNMENT;
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500551static unsigned int scsi_debug_unmap_granularity = DEF_UNMAP_GRANULARITY;
552static unsigned int scsi_debug_unmap_max_blocks = DEF_UNMAP_MAX_BLOCKS;
553static unsigned int scsi_debug_unmap_max_desc = DEF_UNMAP_MAX_DESC;
554static unsigned int scsi_debug_write_same_length = DEF_WRITESAME_LENGTH;
Martin Pittd9867882012-09-06 12:04:33 +0200555static bool scsi_debug_removable = DEF_REMOVABLE;
Akinobu Mita0759c662014-02-26 22:57:04 +0900556static bool scsi_debug_clustering;
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400557static bool scsi_debug_host_lock = DEF_HOST_LOCK;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -0500558static bool scsi_debug_strict = DEF_STRICT;
Douglas Gilbert817fd662014-11-24 20:18:02 -0500559static bool sdebug_any_injecting_opt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400561static atomic_t sdebug_cmnd_count;
562static atomic_t sdebug_completions;
563static atomic_t sdebug_a_tsf; /* counter of 'almost' TSFs */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564
565#define DEV_READONLY(TGT) (0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400567static unsigned int sdebug_store_sectors;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568static sector_t sdebug_capacity; /* in sectors */
569
570/* old BIOS stuff, kernel may get rid of them but some mode sense pages
571 may still need them */
572static int sdebug_heads; /* heads per disk */
573static int sdebug_cylinders_per; /* cylinders per surface */
574static int sdebug_sectors_per; /* sectors per cylinder */
575
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576#define SDEBUG_MAX_PARTS 4
577
Martin K. Petersen395cef02009-09-18 17:33:03 -0400578#define SCSI_DEBUG_MAX_CMD_LEN 32
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +0900579
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500580static unsigned int scsi_debug_lbp(void)
581{
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400582 return ((0 == scsi_debug_fake_rw) &&
583 (scsi_debug_lbpu | scsi_debug_lbpws | scsi_debug_lbpws10));
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500584}
585
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586struct sdebug_dev_info {
587 struct list_head dev_list;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588 unsigned int channel;
589 unsigned int target;
Hannes Reinecke9cb78c12014-06-25 15:27:36 +0200590 u64 lun;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591 struct sdebug_host_info *sdbg_host;
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400592 unsigned long uas_bm[1];
593 atomic_t num_in_q;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -0500594 char stopped; /* TODO: should be atomic */
595 bool used;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596};
597
598struct sdebug_host_info {
599 struct list_head host_list;
600 struct Scsi_Host *shost;
601 struct device dev;
602 struct list_head dev_info_list;
603};
604
605#define to_sdebug_host(d) \
606 container_of(d, struct sdebug_host_info, dev)
607
608static LIST_HEAD(sdebug_host_list);
609static DEFINE_SPINLOCK(sdebug_host_list_lock);
610
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400611
612struct sdebug_hrtimer { /* ... is derived from hrtimer */
613 struct hrtimer hrt; /* must be first element */
614 int qa_indx;
615};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616
617struct sdebug_queued_cmd {
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400618 /* in_use flagged by a bit in queued_in_use_bm[] */
619 struct timer_list *cmnd_timerp;
620 struct tasklet_struct *tletp;
621 struct sdebug_hrtimer *sd_hrtp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622 struct scsi_cmnd * a_cmnd;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623};
624static struct sdebug_queued_cmd queued_arr[SCSI_DEBUG_CANQUEUE];
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400625static unsigned long queued_in_use_bm[SCSI_DEBUG_CANQUEUE_WORDS];
626
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628static unsigned char * fake_storep; /* ramdisk storage */
Akinobu Mitae18d8be2013-06-29 17:59:18 +0900629static struct sd_dif_tuple *dif_storep; /* protection info */
Martin K. Petersen44d92692009-10-15 14:45:27 -0400630static void *map_storep; /* provisioning map */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631
Martin K. Petersen44d92692009-10-15 14:45:27 -0400632static unsigned long map_size;
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400633static int num_aborts;
634static int num_dev_resets;
635static int num_target_resets;
636static int num_bus_resets;
637static int num_host_resets;
Martin K. Petersenc6a44282009-01-04 03:08:19 -0500638static int dix_writes;
639static int dix_reads;
640static int dif_errors;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641
642static DEFINE_SPINLOCK(queued_arr_lock);
643static DEFINE_RWLOCK(atomic_rw);
644
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400645static char sdebug_proc_name[] = MY_NAME;
646static const char *my_name = MY_NAME;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648static struct bus_type pseudo_lld_bus;
649
650static struct device_driver sdebug_driverfs_driver = {
651 .name = sdebug_proc_name,
652 .bus = &pseudo_lld_bus,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653};
654
655static const int check_condition_result =
656 (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
657
Martin K. Petersenc6a44282009-01-04 03:08:19 -0500658static const int illegal_condition_result =
659 (DRIVER_SENSE << 24) | (DID_ABORT << 16) | SAM_STAT_CHECK_CONDITION;
660
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400661static const int device_qfull_result =
662 (DID_OK << 16) | (COMMAND_COMPLETE << 8) | SAM_STAT_TASK_SET_FULL;
663
664static unsigned char caching_pg[] = {0x8, 18, 0x14, 0, 0xff, 0xff, 0, 0,
665 0xff, 0xff, 0xff, 0xff, 0x80, 0x14, 0, 0,
666 0, 0, 0, 0};
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400667static unsigned char ctrl_m_pg[] = {0xa, 10, 2, 0, 0, 0, 0, 0,
668 0, 0, 0x2, 0x4b};
669static unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0,
670 0, 0, 0x0, 0x0};
671
Akinobu Mita14faa942013-09-18 21:27:24 +0900672static void *fake_store(unsigned long long lba)
673{
674 lba = do_div(lba, sdebug_store_sectors);
675
676 return fake_storep + lba * scsi_debug_sector_size;
677}
678
679static struct sd_dif_tuple *dif_store(sector_t sector)
680{
681 sector = do_div(sector, sdebug_store_sectors);
682
683 return dif_storep + sector;
684}
685
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686static int sdebug_add_adapter(void);
687static void sdebug_remove_adapter(void);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +0900689static void sdebug_max_tgts_luns(void)
690{
691 struct sdebug_host_info *sdbg_host;
692 struct Scsi_Host *hpnt;
693
694 spin_lock(&sdebug_host_list_lock);
695 list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) {
696 hpnt = sdbg_host->shost;
697 if ((hpnt->this_id >= 0) &&
698 (scsi_debug_num_tgts > hpnt->this_id))
699 hpnt->max_id = scsi_debug_num_tgts + 1;
700 else
701 hpnt->max_id = scsi_debug_num_tgts;
702 /* scsi_debug_max_luns; */
Tomas Winklerf2d3fd22015-07-28 16:54:25 +0300703 hpnt->max_lun = SCSI_W_LUN_REPORT_LUNS + 1;
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +0900704 }
705 spin_unlock(&sdebug_host_list_lock);
706}
707
Douglas Gilbert22017ed2014-11-24 23:04:47 -0500708enum sdeb_cmd_data {SDEB_IN_DATA = 0, SDEB_IN_CDB = 1};
709
710/* Set in_bit to -1 to indicate no bit position of invalid field */
711static void
712mk_sense_invalid_fld(struct scsi_cmnd *scp, enum sdeb_cmd_data c_d,
713 int in_byte, int in_bit)
714{
715 unsigned char *sbuff;
716 u8 sks[4];
717 int sl, asc;
718
719 sbuff = scp->sense_buffer;
720 if (!sbuff) {
721 sdev_printk(KERN_ERR, scp->device,
722 "%s: sense_buffer is NULL\n", __func__);
723 return;
724 }
725 asc = c_d ? INVALID_FIELD_IN_CDB : INVALID_FIELD_IN_PARAM_LIST;
726 memset(sbuff, 0, SCSI_SENSE_BUFFERSIZE);
727 scsi_build_sense_buffer(scsi_debug_dsense, sbuff, ILLEGAL_REQUEST,
728 asc, 0);
729 memset(sks, 0, sizeof(sks));
730 sks[0] = 0x80;
731 if (c_d)
732 sks[0] |= 0x40;
733 if (in_bit >= 0) {
734 sks[0] |= 0x8;
735 sks[0] |= 0x7 & in_bit;
736 }
737 put_unaligned_be16(in_byte, sks + 1);
738 if (scsi_debug_dsense) {
739 sl = sbuff[7] + 8;
740 sbuff[7] = sl;
741 sbuff[sl] = 0x2;
742 sbuff[sl + 1] = 0x6;
743 memcpy(sbuff + sl + 4, sks, 3);
744 } else
745 memcpy(sbuff + 15, sks, 3);
746 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
747 sdev_printk(KERN_INFO, scp->device, "%s: [sense_key,asc,ascq"
748 "]: [0x5,0x%x,0x0] %c byte=%d, bit=%d\n",
749 my_name, asc, c_d ? 'C' : 'D', in_byte, in_bit);
750}
751
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400752static void mk_sense_buffer(struct scsi_cmnd *scp, int key, int asc, int asq)
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +0900753{
754 unsigned char *sbuff;
755
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400756 sbuff = scp->sense_buffer;
757 if (!sbuff) {
758 sdev_printk(KERN_ERR, scp->device,
759 "%s: sense_buffer is NULL\n", __func__);
760 return;
761 }
762 memset(sbuff, 0, SCSI_SENSE_BUFFERSIZE);
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +0900763
764 scsi_build_sense_buffer(scsi_debug_dsense, sbuff, key, asc, asq);
765
766 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400767 sdev_printk(KERN_INFO, scp->device,
768 "%s: [sense_key,asc,ascq]: [0x%x,0x%x,0x%x]\n",
769 my_name, key, asc, asq);
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +0900770}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771
Douglas Gilbert22017ed2014-11-24 23:04:47 -0500772static void
773mk_sense_invalid_opcode(struct scsi_cmnd *scp)
774{
775 mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_OPCODE, 0);
776}
777
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778static int scsi_debug_ioctl(struct scsi_device *dev, int cmd, void __user *arg)
779{
780 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400781 if (0x1261 == cmd)
782 sdev_printk(KERN_INFO, dev,
783 "%s: BLKFLSBUF [0x1261]\n", __func__);
784 else if (0x5331 == cmd)
785 sdev_printk(KERN_INFO, dev,
786 "%s: CDROM_GET_CAPABILITY [0x5331]\n",
787 __func__);
788 else
789 sdev_printk(KERN_INFO, dev, "%s: cmd=0x%x\n",
790 __func__, cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791 }
792 return -EINVAL;
793 /* return -ENOTTY; // correct return but upsets fdisk */
794}
795
Ewan D. Milne19c8ead2014-12-04 11:49:27 -0500796static void clear_luns_changed_on_target(struct sdebug_dev_info *devip)
797{
798 struct sdebug_host_info *sdhp;
799 struct sdebug_dev_info *dp;
800
801 spin_lock(&sdebug_host_list_lock);
802 list_for_each_entry(sdhp, &sdebug_host_list, host_list) {
803 list_for_each_entry(dp, &sdhp->dev_info_list, dev_list) {
804 if ((devip->sdbg_host == dp->sdbg_host) &&
805 (devip->target == dp->target))
806 clear_bit(SDEBUG_UA_LUNS_CHANGED, dp->uas_bm);
807 }
808 }
809 spin_unlock(&sdebug_host_list_lock);
810}
811
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400812static int check_readiness(struct scsi_cmnd *SCpnt, int uas_only,
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400813 struct sdebug_dev_info * devip)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814{
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400815 int k;
816 bool debug = !!(SCSI_DEBUG_OPT_NOISE & scsi_debug_opts);
817
818 k = find_first_bit(devip->uas_bm, SDEBUG_NUM_UAS);
819 if (k != SDEBUG_NUM_UAS) {
820 const char *cp = NULL;
821
822 switch (k) {
823 case SDEBUG_UA_POR:
824 mk_sense_buffer(SCpnt, UNIT_ATTENTION,
825 UA_RESET_ASC, POWER_ON_RESET_ASCQ);
826 if (debug)
827 cp = "power on reset";
828 break;
829 case SDEBUG_UA_BUS_RESET:
830 mk_sense_buffer(SCpnt, UNIT_ATTENTION,
831 UA_RESET_ASC, BUS_RESET_ASCQ);
832 if (debug)
833 cp = "bus reset";
834 break;
835 case SDEBUG_UA_MODE_CHANGED:
836 mk_sense_buffer(SCpnt, UNIT_ATTENTION,
837 UA_CHANGED_ASC, MODE_CHANGED_ASCQ);
838 if (debug)
839 cp = "mode parameters changed";
840 break;
Douglas Gilbert0d01c5d2014-11-24 20:27:51 -0500841 case SDEBUG_UA_CAPACITY_CHANGED:
842 mk_sense_buffer(SCpnt, UNIT_ATTENTION,
843 UA_CHANGED_ASC, CAPACITY_CHANGED_ASCQ);
844 if (debug)
845 cp = "capacity data changed";
Ewan D. Milnef49accf2014-12-04 11:49:25 -0500846 break;
Ewan D. Milneacafd0b2014-12-04 11:49:28 -0500847 case SDEBUG_UA_MICROCODE_CHANGED:
848 mk_sense_buffer(SCpnt, UNIT_ATTENTION,
849 TARGET_CHANGED_ASC, MICROCODE_CHANGED_ASCQ);
850 if (debug)
851 cp = "microcode has been changed";
852 break;
853 case SDEBUG_UA_MICROCODE_CHANGED_WO_RESET:
854 mk_sense_buffer(SCpnt, UNIT_ATTENTION,
855 TARGET_CHANGED_ASC,
856 MICROCODE_CHANGED_WO_RESET_ASCQ);
857 if (debug)
858 cp = "microcode has been changed without reset";
859 break;
Ewan D. Milne19c8ead2014-12-04 11:49:27 -0500860 case SDEBUG_UA_LUNS_CHANGED:
861 /*
862 * SPC-3 behavior is to report a UNIT ATTENTION with
863 * ASC/ASCQ REPORTED LUNS DATA HAS CHANGED on every LUN
864 * on the target, until a REPORT LUNS command is
865 * received. SPC-4 behavior is to report it only once.
866 * NOTE: scsi_debug_scsi_level does not use the same
867 * values as struct scsi_device->scsi_level.
868 */
869 if (scsi_debug_scsi_level >= 6) /* SPC-4 and above */
870 clear_luns_changed_on_target(devip);
871 mk_sense_buffer(SCpnt, UNIT_ATTENTION,
872 TARGET_CHANGED_ASC,
873 LUNS_CHANGED_ASCQ);
874 if (debug)
875 cp = "reported luns data has changed";
876 break;
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400877 default:
878 pr_warn("%s: unexpected unit attention code=%d\n",
879 __func__, k);
880 if (debug)
881 cp = "unknown";
882 break;
883 }
884 clear_bit(k, devip->uas_bm);
885 if (debug)
886 sdev_printk(KERN_INFO, SCpnt->device,
887 "%s reports: Unit attention: %s\n",
888 my_name, cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889 return check_condition_result;
890 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400891 if ((UAS_TUR == uas_only) && devip->stopped) {
892 mk_sense_buffer(SCpnt, NOT_READY, LOGICAL_UNIT_NOT_READY,
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400893 0x2);
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400894 if (debug)
895 sdev_printk(KERN_INFO, SCpnt->device,
896 "%s reports: Not ready: %s\n", my_name,
897 "initializing command required");
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400898 return check_condition_result;
899 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900 return 0;
901}
902
903/* Returns 0 if ok else (DID_ERROR << 16). Sets scp->resid . */
FUJITA Tomonori21a61822008-03-09 13:44:30 +0900904static int fill_from_dev_buffer(struct scsi_cmnd *scp, unsigned char *arr,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905 int arr_len)
906{
FUJITA Tomonori21a61822008-03-09 13:44:30 +0900907 int act_len;
FUJITA Tomonori072d0bb2008-01-23 01:32:00 +0900908 struct scsi_data_buffer *sdb = scsi_in(scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909
FUJITA Tomonori072d0bb2008-01-23 01:32:00 +0900910 if (!sdb->length)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911 return 0;
FUJITA Tomonori072d0bb2008-01-23 01:32:00 +0900912 if (!(scsi_bidi_cmnd(scp) || scp->sc_data_direction == DMA_FROM_DEVICE))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 return (DID_ERROR << 16);
FUJITA Tomonori21a61822008-03-09 13:44:30 +0900914
915 act_len = sg_copy_from_buffer(sdb->table.sgl, sdb->table.nents,
916 arr, arr_len);
Akinobu Mitaa4517512013-07-08 16:01:57 -0700917 sdb->resid = scsi_bufflen(scp) - act_len;
FUJITA Tomonori21a61822008-03-09 13:44:30 +0900918
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919 return 0;
920}
921
922/* Returns number of bytes fetched into 'arr' or -1 if error. */
FUJITA Tomonori21a61822008-03-09 13:44:30 +0900923static int fetch_to_dev_buffer(struct scsi_cmnd *scp, unsigned char *arr,
924 int arr_len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925{
FUJITA Tomonori21a61822008-03-09 13:44:30 +0900926 if (!scsi_bufflen(scp))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927 return 0;
FUJITA Tomonori072d0bb2008-01-23 01:32:00 +0900928 if (!(scsi_bidi_cmnd(scp) || scp->sc_data_direction == DMA_TO_DEVICE))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929 return -1;
FUJITA Tomonori21a61822008-03-09 13:44:30 +0900930
931 return scsi_sg_copy_to_buffer(scp, arr, arr_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700932}
933
934
935static const char * inq_vendor_id = "Linux ";
936static const char * inq_product_id = "scsi_debug ";
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400937static const char *inq_product_rev = "0184"; /* version less '.' */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400939/* Device identification VPD page. Returns number of bytes placed in arr */
Hannes Reinecke5a09e392006-10-20 09:58:47 +0200940static int inquiry_evpd_83(unsigned char * arr, int port_group_id,
941 int target_dev_id, int dev_id_num,
942 const char * dev_id_str,
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400943 int dev_id_str_len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700944{
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400945 int num, port_a;
946 char b[32];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700947
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400948 port_a = target_dev_id + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949 /* T10 vendor identifier field format (faked) */
950 arr[0] = 0x2; /* ASCII */
951 arr[1] = 0x1;
952 arr[2] = 0x0;
953 memcpy(&arr[4], inq_vendor_id, 8);
954 memcpy(&arr[12], inq_product_id, 16);
955 memcpy(&arr[28], dev_id_str, dev_id_str_len);
956 num = 8 + 16 + dev_id_str_len;
957 arr[3] = num;
958 num += 4;
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400959 if (dev_id_num >= 0) {
960 /* NAA-5, Logical unit identifier (binary) */
961 arr[num++] = 0x1; /* binary (not necessarily sas) */
962 arr[num++] = 0x3; /* PIV=0, lu, naa */
963 arr[num++] = 0x0;
964 arr[num++] = 0x8;
965 arr[num++] = 0x53; /* naa-5 ieee company id=0x333333 (fake) */
966 arr[num++] = 0x33;
967 arr[num++] = 0x33;
968 arr[num++] = 0x30;
969 arr[num++] = (dev_id_num >> 24);
970 arr[num++] = (dev_id_num >> 16) & 0xff;
971 arr[num++] = (dev_id_num >> 8) & 0xff;
972 arr[num++] = dev_id_num & 0xff;
973 /* Target relative port number */
974 arr[num++] = 0x61; /* proto=sas, binary */
975 arr[num++] = 0x94; /* PIV=1, target port, rel port */
976 arr[num++] = 0x0; /* reserved */
977 arr[num++] = 0x4; /* length */
978 arr[num++] = 0x0; /* reserved */
979 arr[num++] = 0x0; /* reserved */
980 arr[num++] = 0x0;
981 arr[num++] = 0x1; /* relative port A */
982 }
983 /* NAA-5, Target port identifier */
984 arr[num++] = 0x61; /* proto=sas, binary */
985 arr[num++] = 0x93; /* piv=1, target port, naa */
986 arr[num++] = 0x0;
987 arr[num++] = 0x8;
988 arr[num++] = 0x52; /* naa-5, company id=0x222222 (fake) */
989 arr[num++] = 0x22;
990 arr[num++] = 0x22;
991 arr[num++] = 0x20;
992 arr[num++] = (port_a >> 24);
993 arr[num++] = (port_a >> 16) & 0xff;
994 arr[num++] = (port_a >> 8) & 0xff;
995 arr[num++] = port_a & 0xff;
Hannes Reinecke5a09e392006-10-20 09:58:47 +0200996 /* NAA-5, Target port group identifier */
997 arr[num++] = 0x61; /* proto=sas, binary */
998 arr[num++] = 0x95; /* piv=1, target port group id */
999 arr[num++] = 0x0;
1000 arr[num++] = 0x4;
1001 arr[num++] = 0;
1002 arr[num++] = 0;
1003 arr[num++] = (port_group_id >> 8) & 0xff;
1004 arr[num++] = port_group_id & 0xff;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001005 /* NAA-5, Target device identifier */
1006 arr[num++] = 0x61; /* proto=sas, binary */
1007 arr[num++] = 0xa3; /* piv=1, target device, naa */
1008 arr[num++] = 0x0;
1009 arr[num++] = 0x8;
1010 arr[num++] = 0x52; /* naa-5, company id=0x222222 (fake) */
1011 arr[num++] = 0x22;
1012 arr[num++] = 0x22;
1013 arr[num++] = 0x20;
1014 arr[num++] = (target_dev_id >> 24);
1015 arr[num++] = (target_dev_id >> 16) & 0xff;
1016 arr[num++] = (target_dev_id >> 8) & 0xff;
1017 arr[num++] = target_dev_id & 0xff;
1018 /* SCSI name string: Target device identifier */
1019 arr[num++] = 0x63; /* proto=sas, UTF-8 */
1020 arr[num++] = 0xa8; /* piv=1, target device, SCSI name string */
1021 arr[num++] = 0x0;
1022 arr[num++] = 24;
1023 memcpy(arr + num, "naa.52222220", 12);
1024 num += 12;
1025 snprintf(b, sizeof(b), "%08X", target_dev_id);
1026 memcpy(arr + num, b, 8);
1027 num += 8;
1028 memset(arr + num, 0, 4);
1029 num += 4;
1030 return num;
1031}
1032
1033
1034static unsigned char vpd84_data[] = {
1035/* from 4th byte */ 0x22,0x22,0x22,0x0,0xbb,0x0,
1036 0x22,0x22,0x22,0x0,0xbb,0x1,
1037 0x22,0x22,0x22,0x0,0xbb,0x2,
1038};
1039
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001040/* Software interface identification VPD page */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001041static int inquiry_evpd_84(unsigned char * arr)
1042{
1043 memcpy(arr, vpd84_data, sizeof(vpd84_data));
1044 return sizeof(vpd84_data);
1045}
1046
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001047/* Management network addresses VPD page */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001048static int inquiry_evpd_85(unsigned char * arr)
1049{
1050 int num = 0;
1051 const char * na1 = "https://www.kernel.org/config";
1052 const char * na2 = "http://www.kernel.org/log";
1053 int plen, olen;
1054
1055 arr[num++] = 0x1; /* lu, storage config */
1056 arr[num++] = 0x0; /* reserved */
1057 arr[num++] = 0x0;
1058 olen = strlen(na1);
1059 plen = olen + 1;
1060 if (plen % 4)
1061 plen = ((plen / 4) + 1) * 4;
1062 arr[num++] = plen; /* length, null termianted, padded */
1063 memcpy(arr + num, na1, olen);
1064 memset(arr + num + olen, 0, plen - olen);
1065 num += plen;
1066
1067 arr[num++] = 0x4; /* lu, logging */
1068 arr[num++] = 0x0; /* reserved */
1069 arr[num++] = 0x0;
1070 olen = strlen(na2);
1071 plen = olen + 1;
1072 if (plen % 4)
1073 plen = ((plen / 4) + 1) * 4;
1074 arr[num++] = plen; /* length, null terminated, padded */
1075 memcpy(arr + num, na2, olen);
1076 memset(arr + num + olen, 0, plen - olen);
1077 num += plen;
1078
1079 return num;
1080}
1081
1082/* SCSI ports VPD page */
1083static int inquiry_evpd_88(unsigned char * arr, int target_dev_id)
1084{
1085 int num = 0;
1086 int port_a, port_b;
1087
1088 port_a = target_dev_id + 1;
1089 port_b = port_a + 1;
1090 arr[num++] = 0x0; /* reserved */
1091 arr[num++] = 0x0; /* reserved */
1092 arr[num++] = 0x0;
1093 arr[num++] = 0x1; /* relative port 1 (primary) */
1094 memset(arr + num, 0, 6);
1095 num += 6;
1096 arr[num++] = 0x0;
1097 arr[num++] = 12; /* length tp descriptor */
1098 /* naa-5 target port identifier (A) */
1099 arr[num++] = 0x61; /* proto=sas, binary */
1100 arr[num++] = 0x93; /* PIV=1, target port, NAA */
1101 arr[num++] = 0x0; /* reserved */
1102 arr[num++] = 0x8; /* length */
1103 arr[num++] = 0x52; /* NAA-5, company_id=0x222222 (fake) */
1104 arr[num++] = 0x22;
1105 arr[num++] = 0x22;
1106 arr[num++] = 0x20;
1107 arr[num++] = (port_a >> 24);
1108 arr[num++] = (port_a >> 16) & 0xff;
1109 arr[num++] = (port_a >> 8) & 0xff;
1110 arr[num++] = port_a & 0xff;
1111
1112 arr[num++] = 0x0; /* reserved */
1113 arr[num++] = 0x0; /* reserved */
1114 arr[num++] = 0x0;
1115 arr[num++] = 0x2; /* relative port 2 (secondary) */
1116 memset(arr + num, 0, 6);
1117 num += 6;
1118 arr[num++] = 0x0;
1119 arr[num++] = 12; /* length tp descriptor */
1120 /* naa-5 target port identifier (B) */
1121 arr[num++] = 0x61; /* proto=sas, binary */
1122 arr[num++] = 0x93; /* PIV=1, target port, NAA */
1123 arr[num++] = 0x0; /* reserved */
1124 arr[num++] = 0x8; /* length */
1125 arr[num++] = 0x52; /* NAA-5, company_id=0x222222 (fake) */
1126 arr[num++] = 0x22;
1127 arr[num++] = 0x22;
1128 arr[num++] = 0x20;
1129 arr[num++] = (port_b >> 24);
1130 arr[num++] = (port_b >> 16) & 0xff;
1131 arr[num++] = (port_b >> 8) & 0xff;
1132 arr[num++] = port_b & 0xff;
1133
1134 return num;
1135}
1136
1137
1138static unsigned char vpd89_data[] = {
1139/* from 4th byte */ 0,0,0,0,
1140'l','i','n','u','x',' ',' ',' ',
1141'S','A','T',' ','s','c','s','i','_','d','e','b','u','g',' ',' ',
1142'1','2','3','4',
11430x34,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,
11440xec,0,0,0,
11450x5a,0xc,0xff,0x3f,0x37,0xc8,0x10,0,0,0,0,0,0x3f,0,0,0,
11460,0,0,0,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x20,0x20,0x20,0x20,
11470x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0,0,0,0x40,0x4,0,0x2e,0x33,
11480x38,0x31,0x20,0x20,0x20,0x20,0x54,0x53,0x38,0x33,0x30,0x30,0x33,0x31,
11490x53,0x41,
11500x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
11510x20,0x20,
11520x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
11530x10,0x80,
11540,0,0,0x2f,0,0,0,0x2,0,0x2,0x7,0,0xff,0xff,0x1,0,
11550x3f,0,0xc1,0xff,0x3e,0,0x10,0x1,0xb0,0xf8,0x50,0x9,0,0,0x7,0,
11560x3,0,0x78,0,0x78,0,0xf0,0,0x78,0,0,0,0,0,0,0,
11570,0,0,0,0,0,0,0,0x2,0,0,0,0,0,0,0,
11580x7e,0,0x1b,0,0x6b,0x34,0x1,0x7d,0x3,0x40,0x69,0x34,0x1,0x3c,0x3,0x40,
11590x7f,0x40,0,0,0,0,0xfe,0xfe,0,0,0,0,0,0xfe,0,0,
11600,0,0,0,0,0,0,0,0xb0,0xf8,0x50,0x9,0,0,0,0,
11610,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
11620,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
11630,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
11640x1,0,0xb0,0xf8,0x50,0x9,0xb0,0xf8,0x50,0x9,0x20,0x20,0x2,0,0xb6,0x42,
11650,0x80,0x8a,0,0x6,0x3c,0xa,0x3c,0xff,0xff,0xc6,0x7,0,0x1,0,0x8,
11660xf0,0xf,0,0x10,0x2,0,0x30,0,0,0,0,0,0,0,0x6,0xfe,
11670,0,0x2,0,0x50,0,0x8a,0,0x4f,0x95,0,0,0x21,0,0xb,0,
11680,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
11690,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
11700,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
11710,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
11720,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
11730,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
11740,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
11750,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
11760,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
11770,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
11780,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
11790,0,0,0,0,0,0,0,0,0,0,0,0,0,0xa5,0x51,
1180};
1181
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001182/* ATA Information VPD page */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001183static int inquiry_evpd_89(unsigned char * arr)
1184{
1185 memcpy(arr, vpd89_data, sizeof(vpd89_data));
1186 return sizeof(vpd89_data);
1187}
1188
1189
1190static unsigned char vpdb0_data[] = {
Douglas Gilbert1e49f782009-10-29 01:48:31 -04001191 /* from 4th byte */ 0,0,0,4, 0,0,0x4,0, 0,0,0,64,
1192 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1193 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1194 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001195};
1196
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001197/* Block limits VPD page (SBC-3) */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001198static int inquiry_evpd_b0(unsigned char * arr)
1199{
Martin K. Petersenea61fca2009-05-15 00:40:33 -04001200 unsigned int gran;
1201
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001202 memcpy(arr, vpdb0_data, sizeof(vpdb0_data));
Martin K. Petersene308b3d2010-03-23 01:12:27 -04001203
1204 /* Optimal transfer length granularity */
Martin K. Petersenea61fca2009-05-15 00:40:33 -04001205 gran = 1 << scsi_debug_physblk_exp;
1206 arr[2] = (gran >> 8) & 0xff;
1207 arr[3] = gran & 0xff;
Martin K. Petersene308b3d2010-03-23 01:12:27 -04001208
1209 /* Maximum Transfer Length */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001210 if (sdebug_store_sectors > 0x400) {
1211 arr[4] = (sdebug_store_sectors >> 24) & 0xff;
1212 arr[5] = (sdebug_store_sectors >> 16) & 0xff;
1213 arr[6] = (sdebug_store_sectors >> 8) & 0xff;
1214 arr[7] = sdebug_store_sectors & 0xff;
1215 }
Martin K. Petersen44d92692009-10-15 14:45:27 -04001216
Martin K. Petersene308b3d2010-03-23 01:12:27 -04001217 /* Optimal Transfer Length */
1218 put_unaligned_be32(scsi_debug_opt_blks, &arr[8]);
1219
Martin K. Petersen5b94e232011-03-08 02:08:11 -05001220 if (scsi_debug_lbpu) {
Martin K. Petersene308b3d2010-03-23 01:12:27 -04001221 /* Maximum Unmap LBA Count */
Martin K. Petersen60147592010-08-19 11:49:00 -04001222 put_unaligned_be32(scsi_debug_unmap_max_blocks, &arr[16]);
Martin K. Petersene308b3d2010-03-23 01:12:27 -04001223
1224 /* Maximum Unmap Block Descriptor Count */
Martin K. Petersen44d92692009-10-15 14:45:27 -04001225 put_unaligned_be32(scsi_debug_unmap_max_desc, &arr[20]);
1226 }
1227
Martin K. Petersene308b3d2010-03-23 01:12:27 -04001228 /* Unmap Granularity Alignment */
Martin K. Petersen44d92692009-10-15 14:45:27 -04001229 if (scsi_debug_unmap_alignment) {
1230 put_unaligned_be32(scsi_debug_unmap_alignment, &arr[28]);
1231 arr[28] |= 0x80; /* UGAVALID */
1232 }
1233
Martin K. Petersene308b3d2010-03-23 01:12:27 -04001234 /* Optimal Unmap Granularity */
Martin K. Petersen60147592010-08-19 11:49:00 -04001235 put_unaligned_be32(scsi_debug_unmap_granularity, &arr[24]);
1236
Martin K. Petersen5b94e232011-03-08 02:08:11 -05001237 /* Maximum WRITE SAME Length */
1238 put_unaligned_be64(scsi_debug_write_same_length, &arr[32]);
1239
1240 return 0x3c; /* Mandatory page length for Logical Block Provisioning */
Martin K. Petersen44d92692009-10-15 14:45:27 -04001241
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001242 return sizeof(vpdb0_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001243}
1244
Douglas Gilbert1e49f782009-10-29 01:48:31 -04001245/* Block device characteristics VPD page (SBC-3) */
Matthew Wilcoxeac6e8e42008-06-19 10:02:58 -06001246static int inquiry_evpd_b1(unsigned char *arr)
1247{
1248 memset(arr, 0, 0x3c);
1249 arr[0] = 0;
Douglas Gilbert1e49f782009-10-29 01:48:31 -04001250 arr[1] = 1; /* non rotating medium (e.g. solid state) */
1251 arr[2] = 0;
1252 arr[3] = 5; /* less than 1.8" */
Matthew Wilcoxeac6e8e42008-06-19 10:02:58 -06001253
1254 return 0x3c;
1255}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256
Eric Sandeenbe1dd782012-03-08 00:03:59 -06001257/* Logical block provisioning VPD page (SBC-3) */
Martin K. Petersen60147592010-08-19 11:49:00 -04001258static int inquiry_evpd_b2(unsigned char *arr)
1259{
Martin K. Petersen3f0bc3b2012-03-08 10:48:29 -05001260 memset(arr, 0, 0x4);
Martin K. Petersen60147592010-08-19 11:49:00 -04001261 arr[0] = 0; /* threshold exponent */
1262
Martin K. Petersen5b94e232011-03-08 02:08:11 -05001263 if (scsi_debug_lbpu)
Martin K. Petersen60147592010-08-19 11:49:00 -04001264 arr[1] = 1 << 7;
1265
Martin K. Petersen5b94e232011-03-08 02:08:11 -05001266 if (scsi_debug_lbpws)
Martin K. Petersen60147592010-08-19 11:49:00 -04001267 arr[1] |= 1 << 6;
1268
Martin K. Petersen5b94e232011-03-08 02:08:11 -05001269 if (scsi_debug_lbpws10)
1270 arr[1] |= 1 << 5;
1271
Eric Sandeenbe1dd782012-03-08 00:03:59 -06001272 if (scsi_debug_lbprz)
1273 arr[1] |= 1 << 2;
1274
Martin K. Petersen3f0bc3b2012-03-08 10:48:29 -05001275 return 0x4;
Martin K. Petersen60147592010-08-19 11:49:00 -04001276}
1277
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278#define SDEBUG_LONG_INQ_SZ 96
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001279#define SDEBUG_MAX_INQ_ARR_SZ 584
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001281static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282{
1283 unsigned char pq_pdt;
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001284 unsigned char * arr;
Douglas Gilbert01123ef2014-08-05 12:20:02 +02001285 unsigned char *cmd = scp->cmnd;
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001286 int alloc_len, n, ret;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001287 bool have_wlun;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001288
1289 alloc_len = (cmd[3] << 8) + cmd[4];
Douglas Gilbert6f3cbf52007-01-05 00:05:25 -05001290 arr = kzalloc(SDEBUG_MAX_INQ_ARR_SZ, GFP_ATOMIC);
1291 if (! arr)
1292 return DID_REQUEUE << 16;
Tomas Winkler34d55432015-07-28 16:54:21 +03001293 have_wlun = (scp->device->lun == SCSI_W_LUN_REPORT_LUNS);
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001294 if (have_wlun)
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001295 pq_pdt = 0x1e; /* present, wlun */
1296 else if (scsi_debug_no_lun_0 && (0 == devip->lun))
1297 pq_pdt = 0x7f; /* not present, no device type */
1298 else
1299 pq_pdt = (scsi_debug_ptype & 0x1f);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300 arr[0] = pq_pdt;
1301 if (0x2 & cmd[1]) { /* CMDDT bit set */
Douglas Gilbert22017ed2014-11-24 23:04:47 -05001302 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 1, 1);
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001303 kfree(arr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304 return check_condition_result;
1305 } else if (0x1 & cmd[1]) { /* EVPD bit set */
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001306 int lu_id_num, port_group_id, target_dev_id, len;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001307 char lu_id_str[6];
1308 int host_no = devip->sdbg_host->shost->host_no;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001310 port_group_id = (((host_no + 1) & 0x7f) << 8) +
1311 (devip->channel & 0x7f);
Douglas Gilbert23183912006-09-16 20:30:47 -04001312 if (0 == scsi_debug_vpd_use_hostno)
1313 host_no = 0;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001314 lu_id_num = have_wlun ? -1 : (((host_no + 1) * 2000) +
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001315 (devip->target * 1000) + devip->lun);
1316 target_dev_id = ((host_no + 1) * 2000) +
1317 (devip->target * 1000) - 3;
1318 len = scnprintf(lu_id_str, 6, "%d", lu_id_num);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319 if (0 == cmd[2]) { /* supported vital product data pages */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001320 arr[1] = cmd[2]; /*sanity */
1321 n = 4;
1322 arr[n++] = 0x0; /* this page */
1323 arr[n++] = 0x80; /* unit serial number */
1324 arr[n++] = 0x83; /* device identification */
1325 arr[n++] = 0x84; /* software interface ident. */
1326 arr[n++] = 0x85; /* management network addresses */
1327 arr[n++] = 0x86; /* extended inquiry */
1328 arr[n++] = 0x87; /* mode page policy */
1329 arr[n++] = 0x88; /* SCSI ports */
1330 arr[n++] = 0x89; /* ATA information */
1331 arr[n++] = 0xb0; /* Block limits (SBC) */
Matthew Wilcoxeac6e8e42008-06-19 10:02:58 -06001332 arr[n++] = 0xb1; /* Block characteristics (SBC) */
Martin K. Petersen5b94e232011-03-08 02:08:11 -05001333 if (scsi_debug_lbp()) /* Logical Block Prov. (SBC) */
1334 arr[n++] = 0xb2;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001335 arr[3] = n - 4; /* number of supported VPD pages */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336 } else if (0x80 == cmd[2]) { /* unit serial number */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001337 arr[1] = cmd[2]; /*sanity */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338 arr[3] = len;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001339 memcpy(&arr[4], lu_id_str, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340 } else if (0x83 == cmd[2]) { /* device identification */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001341 arr[1] = cmd[2]; /*sanity */
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001342 arr[3] = inquiry_evpd_83(&arr[4], port_group_id,
1343 target_dev_id, lu_id_num,
1344 lu_id_str, len);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001345 } else if (0x84 == cmd[2]) { /* Software interface ident. */
1346 arr[1] = cmd[2]; /*sanity */
1347 arr[3] = inquiry_evpd_84(&arr[4]);
1348 } else if (0x85 == cmd[2]) { /* Management network addresses */
1349 arr[1] = cmd[2]; /*sanity */
1350 arr[3] = inquiry_evpd_85(&arr[4]);
1351 } else if (0x86 == cmd[2]) { /* extended inquiry */
1352 arr[1] = cmd[2]; /*sanity */
1353 arr[3] = 0x3c; /* number of following entries */
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001354 if (scsi_debug_dif == SD_DIF_TYPE3_PROTECTION)
1355 arr[4] = 0x4; /* SPT: GRD_CHK:1 */
1356 else if (scsi_debug_dif)
1357 arr[4] = 0x5; /* SPT: GRD_CHK:1, REF_CHK:1 */
1358 else
1359 arr[4] = 0x0; /* no protection stuff */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001360 arr[5] = 0x7; /* head of q, ordered + simple q's */
1361 } else if (0x87 == cmd[2]) { /* mode page policy */
1362 arr[1] = cmd[2]; /*sanity */
1363 arr[3] = 0x8; /* number of following entries */
1364 arr[4] = 0x2; /* disconnect-reconnect mp */
1365 arr[6] = 0x80; /* mlus, shared */
1366 arr[8] = 0x18; /* protocol specific lu */
1367 arr[10] = 0x82; /* mlus, per initiator port */
1368 } else if (0x88 == cmd[2]) { /* SCSI Ports */
1369 arr[1] = cmd[2]; /*sanity */
1370 arr[3] = inquiry_evpd_88(&arr[4], target_dev_id);
1371 } else if (0x89 == cmd[2]) { /* ATA information */
1372 arr[1] = cmd[2]; /*sanity */
1373 n = inquiry_evpd_89(&arr[4]);
1374 arr[2] = (n >> 8);
1375 arr[3] = (n & 0xff);
1376 } else if (0xb0 == cmd[2]) { /* Block limits (SBC) */
1377 arr[1] = cmd[2]; /*sanity */
1378 arr[3] = inquiry_evpd_b0(&arr[4]);
Matthew Wilcoxeac6e8e42008-06-19 10:02:58 -06001379 } else if (0xb1 == cmd[2]) { /* Block characteristics (SBC) */
1380 arr[1] = cmd[2]; /*sanity */
1381 arr[3] = inquiry_evpd_b1(&arr[4]);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05001382 } else if (0xb2 == cmd[2]) { /* Logical Block Prov. (SBC) */
Martin K. Petersen60147592010-08-19 11:49:00 -04001383 arr[1] = cmd[2]; /*sanity */
1384 arr[3] = inquiry_evpd_b2(&arr[4]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385 } else {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05001386 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, -1);
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001387 kfree(arr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001388 return check_condition_result;
1389 }
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001390 len = min(((arr[2] << 8) + arr[3]) + 4, alloc_len);
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001391 ret = fill_from_dev_buffer(scp, arr,
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001392 min(len, SDEBUG_MAX_INQ_ARR_SZ));
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001393 kfree(arr);
1394 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001395 }
1396 /* drops through here for a standard inquiry */
Martin Pittd9867882012-09-06 12:04:33 +02001397 arr[1] = scsi_debug_removable ? 0x80 : 0; /* Removable disk */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001398 arr[2] = scsi_debug_scsi_level;
1399 arr[3] = 2; /* response_data_format==2 */
1400 arr[4] = SDEBUG_LONG_INQ_SZ - 5;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001401 arr[5] = scsi_debug_dif ? 1 : 0; /* PROTECT bit */
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001402 if (0 == scsi_debug_vpd_use_hostno)
1403 arr[5] = 0x10; /* claim: implicit TGPS */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001404 arr[6] = 0x10; /* claim: MultiP */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001405 /* arr[6] |= 0x40; ... claim: EncServ (enclosure services) */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001406 arr[7] = 0xa; /* claim: LINKED + CMDQUE */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001407 memcpy(&arr[8], inq_vendor_id, 8);
1408 memcpy(&arr[16], inq_product_id, 16);
1409 memcpy(&arr[32], inq_product_rev, 4);
1410 /* version descriptors (2 bytes each) follow */
Douglas Gilberte46b0342014-08-05 12:21:53 +02001411 arr[58] = 0x0; arr[59] = 0xa2; /* SAM-5 rev 4 */
1412 arr[60] = 0x4; arr[61] = 0x68; /* SPC-4 rev 37 */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001413 n = 62;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414 if (scsi_debug_ptype == 0) {
Douglas Gilberte46b0342014-08-05 12:21:53 +02001415 arr[n++] = 0x4; arr[n++] = 0xc5; /* SBC-4 rev 36 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416 } else if (scsi_debug_ptype == 1) {
Douglas Gilberte46b0342014-08-05 12:21:53 +02001417 arr[n++] = 0x5; arr[n++] = 0x25; /* SSC-4 rev 3 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418 }
Douglas Gilberte46b0342014-08-05 12:21:53 +02001419 arr[n++] = 0x20; arr[n++] = 0xe6; /* SPL-3 rev 7 */
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001420 ret = fill_from_dev_buffer(scp, arr,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421 min(alloc_len, SDEBUG_LONG_INQ_SZ));
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001422 kfree(arr);
1423 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424}
1425
1426static int resp_requests(struct scsi_cmnd * scp,
1427 struct sdebug_dev_info * devip)
1428{
1429 unsigned char * sbuff;
Douglas Gilbert01123ef2014-08-05 12:20:02 +02001430 unsigned char *cmd = scp->cmnd;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001431 unsigned char arr[SCSI_SENSE_BUFFERSIZE];
Tomas Winkler2492fc02015-07-28 16:54:26 +03001432 bool dsense;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433 int len = 18;
1434
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001435 memset(arr, 0, sizeof(arr));
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001436 dsense = !!(cmd[1] & 1);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001437 sbuff = scp->sense_buffer;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001438 if ((iec_m_pg[2] & 0x4) && (6 == (iec_m_pg[3] & 0xf))) {
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001439 if (dsense) {
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001440 arr[0] = 0x72;
1441 arr[1] = 0x0; /* NO_SENSE in sense_key */
1442 arr[2] = THRESHOLD_EXCEEDED;
1443 arr[3] = 0xff; /* TEST set and MRIE==6 */
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001444 len = 8;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001445 } else {
1446 arr[0] = 0x70;
1447 arr[2] = 0x0; /* NO_SENSE in sense_key */
1448 arr[7] = 0xa; /* 18 byte sense buffer */
1449 arr[12] = THRESHOLD_EXCEEDED;
1450 arr[13] = 0xff; /* TEST set and MRIE==6 */
1451 }
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001452 } else {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001453 memcpy(arr, sbuff, SCSI_SENSE_BUFFERSIZE);
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001454 if (arr[0] >= 0x70 && dsense == scsi_debug_dsense)
1455 ; /* have sense and formats match */
1456 else if (arr[0] <= 0x70) {
1457 if (dsense) {
1458 memset(arr, 0, 8);
1459 arr[0] = 0x72;
1460 len = 8;
1461 } else {
1462 memset(arr, 0, 18);
1463 arr[0] = 0x70;
1464 arr[7] = 0xa;
1465 }
1466 } else if (dsense) {
1467 memset(arr, 0, 8);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001468 arr[0] = 0x72;
1469 arr[1] = sbuff[2]; /* sense key */
1470 arr[2] = sbuff[12]; /* asc */
1471 arr[3] = sbuff[13]; /* ascq */
1472 len = 8;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001473 } else {
1474 memset(arr, 0, 18);
1475 arr[0] = 0x70;
1476 arr[2] = sbuff[1];
1477 arr[7] = 0xa;
1478 arr[12] = sbuff[1];
1479 arr[13] = sbuff[3];
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001480 }
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001481
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001482 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001483 mk_sense_buffer(scp, 0, NO_ADDITIONAL_SENSE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484 return fill_from_dev_buffer(scp, arr, len);
1485}
1486
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001487static int resp_start_stop(struct scsi_cmnd * scp,
1488 struct sdebug_dev_info * devip)
1489{
Douglas Gilbert01123ef2014-08-05 12:20:02 +02001490 unsigned char *cmd = scp->cmnd;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001491 int power_cond, start;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001492
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001493 power_cond = (cmd[4] & 0xf0) >> 4;
1494 if (power_cond) {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05001495 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 4, 7);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001496 return check_condition_result;
1497 }
1498 start = cmd[4] & 1;
1499 if (start == devip->stopped)
1500 devip->stopped = !start;
1501 return 0;
1502}
1503
FUJITA Tomonori28898872008-03-30 00:59:55 +09001504static sector_t get_sdebug_capacity(void)
1505{
1506 if (scsi_debug_virtual_gb > 0)
Douglas Gilbert5447ed62010-04-25 12:30:23 +02001507 return (sector_t)scsi_debug_virtual_gb *
1508 (1073741824 / scsi_debug_sector_size);
FUJITA Tomonori28898872008-03-30 00:59:55 +09001509 else
1510 return sdebug_store_sectors;
1511}
1512
Linus Torvalds1da177e2005-04-16 15:20:36 -07001513#define SDEBUG_READCAP_ARR_SZ 8
1514static int resp_readcap(struct scsi_cmnd * scp,
1515 struct sdebug_dev_info * devip)
1516{
1517 unsigned char arr[SDEBUG_READCAP_ARR_SZ];
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001518 unsigned int capac;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001520 /* following just in case virtual_gb changed */
FUJITA Tomonori28898872008-03-30 00:59:55 +09001521 sdebug_capacity = get_sdebug_capacity();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001522 memset(arr, 0, SDEBUG_READCAP_ARR_SZ);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001523 if (sdebug_capacity < 0xffffffff) {
1524 capac = (unsigned int)sdebug_capacity - 1;
1525 arr[0] = (capac >> 24);
1526 arr[1] = (capac >> 16) & 0xff;
1527 arr[2] = (capac >> 8) & 0xff;
1528 arr[3] = capac & 0xff;
1529 } else {
1530 arr[0] = 0xff;
1531 arr[1] = 0xff;
1532 arr[2] = 0xff;
1533 arr[3] = 0xff;
1534 }
Martin K. Petersen597136a2008-06-05 00:12:59 -04001535 arr[6] = (scsi_debug_sector_size >> 8) & 0xff;
1536 arr[7] = scsi_debug_sector_size & 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001537 return fill_from_dev_buffer(scp, arr, SDEBUG_READCAP_ARR_SZ);
1538}
1539
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001540#define SDEBUG_READCAP16_ARR_SZ 32
1541static int resp_readcap16(struct scsi_cmnd * scp,
1542 struct sdebug_dev_info * devip)
1543{
Douglas Gilbert01123ef2014-08-05 12:20:02 +02001544 unsigned char *cmd = scp->cmnd;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001545 unsigned char arr[SDEBUG_READCAP16_ARR_SZ];
1546 unsigned long long capac;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001547 int k, alloc_len;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001548
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001549 alloc_len = ((cmd[10] << 24) + (cmd[11] << 16) + (cmd[12] << 8)
1550 + cmd[13]);
1551 /* following just in case virtual_gb changed */
FUJITA Tomonori28898872008-03-30 00:59:55 +09001552 sdebug_capacity = get_sdebug_capacity();
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001553 memset(arr, 0, SDEBUG_READCAP16_ARR_SZ);
1554 capac = sdebug_capacity - 1;
1555 for (k = 0; k < 8; ++k, capac >>= 8)
1556 arr[7 - k] = capac & 0xff;
Martin K. Petersen597136a2008-06-05 00:12:59 -04001557 arr[8] = (scsi_debug_sector_size >> 24) & 0xff;
1558 arr[9] = (scsi_debug_sector_size >> 16) & 0xff;
1559 arr[10] = (scsi_debug_sector_size >> 8) & 0xff;
1560 arr[11] = scsi_debug_sector_size & 0xff;
Martin K. Petersenea61fca2009-05-15 00:40:33 -04001561 arr[13] = scsi_debug_physblk_exp & 0xf;
1562 arr[14] = (scsi_debug_lowest_aligned >> 8) & 0x3f;
Martin K. Petersen44d92692009-10-15 14:45:27 -04001563
Eric Sandeenbe1dd782012-03-08 00:03:59 -06001564 if (scsi_debug_lbp()) {
Martin K. Petersen5b94e232011-03-08 02:08:11 -05001565 arr[14] |= 0x80; /* LBPME */
Eric Sandeenbe1dd782012-03-08 00:03:59 -06001566 if (scsi_debug_lbprz)
1567 arr[14] |= 0x40; /* LBPRZ */
1568 }
Martin K. Petersen44d92692009-10-15 14:45:27 -04001569
Martin K. Petersenea61fca2009-05-15 00:40:33 -04001570 arr[15] = scsi_debug_lowest_aligned & 0xff;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001571
1572 if (scsi_debug_dif) {
1573 arr[12] = (scsi_debug_dif - 1) << 1; /* P_TYPE */
1574 arr[12] |= 1; /* PROT_EN */
1575 }
1576
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001577 return fill_from_dev_buffer(scp, arr,
1578 min(alloc_len, SDEBUG_READCAP16_ARR_SZ));
1579}
1580
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001581#define SDEBUG_MAX_TGTPGS_ARR_SZ 1412
1582
1583static int resp_report_tgtpgs(struct scsi_cmnd * scp,
1584 struct sdebug_dev_info * devip)
1585{
Douglas Gilbert01123ef2014-08-05 12:20:02 +02001586 unsigned char *cmd = scp->cmnd;
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001587 unsigned char * arr;
1588 int host_no = devip->sdbg_host->shost->host_no;
1589 int n, ret, alen, rlen;
1590 int port_group_a, port_group_b, port_a, port_b;
1591
1592 alen = ((cmd[6] << 24) + (cmd[7] << 16) + (cmd[8] << 8)
1593 + cmd[9]);
1594
Douglas Gilbert6f3cbf52007-01-05 00:05:25 -05001595 arr = kzalloc(SDEBUG_MAX_TGTPGS_ARR_SZ, GFP_ATOMIC);
1596 if (! arr)
1597 return DID_REQUEUE << 16;
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001598 /*
1599 * EVPD page 0x88 states we have two ports, one
1600 * real and a fake port with no device connected.
1601 * So we create two port groups with one port each
1602 * and set the group with port B to unavailable.
1603 */
1604 port_a = 0x1; /* relative port A */
1605 port_b = 0x2; /* relative port B */
1606 port_group_a = (((host_no + 1) & 0x7f) << 8) +
1607 (devip->channel & 0x7f);
1608 port_group_b = (((host_no + 1) & 0x7f) << 8) +
1609 (devip->channel & 0x7f) + 0x80;
1610
1611 /*
1612 * The asymmetric access state is cycled according to the host_id.
1613 */
1614 n = 4;
1615 if (0 == scsi_debug_vpd_use_hostno) {
1616 arr[n++] = host_no % 3; /* Asymm access state */
1617 arr[n++] = 0x0F; /* claim: all states are supported */
1618 } else {
1619 arr[n++] = 0x0; /* Active/Optimized path */
1620 arr[n++] = 0x01; /* claim: only support active/optimized paths */
1621 }
1622 arr[n++] = (port_group_a >> 8) & 0xff;
1623 arr[n++] = port_group_a & 0xff;
1624 arr[n++] = 0; /* Reserved */
1625 arr[n++] = 0; /* Status code */
1626 arr[n++] = 0; /* Vendor unique */
1627 arr[n++] = 0x1; /* One port per group */
1628 arr[n++] = 0; /* Reserved */
1629 arr[n++] = 0; /* Reserved */
1630 arr[n++] = (port_a >> 8) & 0xff;
1631 arr[n++] = port_a & 0xff;
1632 arr[n++] = 3; /* Port unavailable */
1633 arr[n++] = 0x08; /* claim: only unavailalbe paths are supported */
1634 arr[n++] = (port_group_b >> 8) & 0xff;
1635 arr[n++] = port_group_b & 0xff;
1636 arr[n++] = 0; /* Reserved */
1637 arr[n++] = 0; /* Status code */
1638 arr[n++] = 0; /* Vendor unique */
1639 arr[n++] = 0x1; /* One port per group */
1640 arr[n++] = 0; /* Reserved */
1641 arr[n++] = 0; /* Reserved */
1642 arr[n++] = (port_b >> 8) & 0xff;
1643 arr[n++] = port_b & 0xff;
1644
1645 rlen = n - 4;
1646 arr[0] = (rlen >> 24) & 0xff;
1647 arr[1] = (rlen >> 16) & 0xff;
1648 arr[2] = (rlen >> 8) & 0xff;
1649 arr[3] = rlen & 0xff;
1650
1651 /*
1652 * Return the smallest value of either
1653 * - The allocated length
1654 * - The constructed command length
1655 * - The maximum array size
1656 */
1657 rlen = min(alen,n);
1658 ret = fill_from_dev_buffer(scp, arr,
1659 min(rlen, SDEBUG_MAX_TGTPGS_ARR_SZ));
1660 kfree(arr);
1661 return ret;
1662}
1663
Douglas Gilbert38d5c832014-11-24 21:27:12 -05001664static int
1665resp_rsup_opcodes(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
1666{
1667 bool rctd;
1668 u8 reporting_opts, req_opcode, sdeb_i, supp;
1669 u16 req_sa, u;
1670 u32 alloc_len, a_len;
1671 int k, offset, len, errsts, count, bump, na;
1672 const struct opcode_info_t *oip;
1673 const struct opcode_info_t *r_oip;
1674 u8 *arr;
1675 u8 *cmd = scp->cmnd;
1676
1677 rctd = !!(cmd[2] & 0x80);
1678 reporting_opts = cmd[2] & 0x7;
1679 req_opcode = cmd[3];
1680 req_sa = get_unaligned_be16(cmd + 4);
1681 alloc_len = get_unaligned_be32(cmd + 6);
Colin Ian King6d310df2015-01-22 11:20:40 +00001682 if (alloc_len < 4 || alloc_len > 0xffff) {
Douglas Gilbert38d5c832014-11-24 21:27:12 -05001683 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 6, -1);
1684 return check_condition_result;
1685 }
1686 if (alloc_len > 8192)
1687 a_len = 8192;
1688 else
1689 a_len = alloc_len;
Sasha Levin99531e62015-01-17 17:47:37 -05001690 arr = kzalloc((a_len < 256) ? 320 : a_len + 64, GFP_ATOMIC);
Douglas Gilbert38d5c832014-11-24 21:27:12 -05001691 if (NULL == arr) {
1692 mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC,
1693 INSUFF_RES_ASCQ);
1694 return check_condition_result;
1695 }
1696 switch (reporting_opts) {
1697 case 0: /* all commands */
1698 /* count number of commands */
1699 for (count = 0, oip = opcode_info_arr;
1700 oip->num_attached != 0xff; ++oip) {
1701 if (F_INV_OP & oip->flags)
1702 continue;
1703 count += (oip->num_attached + 1);
1704 }
1705 bump = rctd ? 20 : 8;
1706 put_unaligned_be32(count * bump, arr);
1707 for (offset = 4, oip = opcode_info_arr;
1708 oip->num_attached != 0xff && offset < a_len; ++oip) {
1709 if (F_INV_OP & oip->flags)
1710 continue;
1711 na = oip->num_attached;
1712 arr[offset] = oip->opcode;
1713 put_unaligned_be16(oip->sa, arr + offset + 2);
1714 if (rctd)
1715 arr[offset + 5] |= 0x2;
1716 if (FF_SA & oip->flags)
1717 arr[offset + 5] |= 0x1;
1718 put_unaligned_be16(oip->len_mask[0], arr + offset + 6);
1719 if (rctd)
1720 put_unaligned_be16(0xa, arr + offset + 8);
1721 r_oip = oip;
1722 for (k = 0, oip = oip->arrp; k < na; ++k, ++oip) {
1723 if (F_INV_OP & oip->flags)
1724 continue;
1725 offset += bump;
1726 arr[offset] = oip->opcode;
1727 put_unaligned_be16(oip->sa, arr + offset + 2);
1728 if (rctd)
1729 arr[offset + 5] |= 0x2;
1730 if (FF_SA & oip->flags)
1731 arr[offset + 5] |= 0x1;
1732 put_unaligned_be16(oip->len_mask[0],
1733 arr + offset + 6);
1734 if (rctd)
1735 put_unaligned_be16(0xa,
1736 arr + offset + 8);
1737 }
1738 oip = r_oip;
1739 offset += bump;
1740 }
1741 break;
1742 case 1: /* one command: opcode only */
1743 case 2: /* one command: opcode plus service action */
1744 case 3: /* one command: if sa==0 then opcode only else opcode+sa */
1745 sdeb_i = opcode_ind_arr[req_opcode];
1746 oip = &opcode_info_arr[sdeb_i];
1747 if (F_INV_OP & oip->flags) {
1748 supp = 1;
1749 offset = 4;
1750 } else {
1751 if (1 == reporting_opts) {
1752 if (FF_SA & oip->flags) {
1753 mk_sense_invalid_fld(scp, SDEB_IN_CDB,
1754 2, 2);
1755 kfree(arr);
1756 return check_condition_result;
1757 }
1758 req_sa = 0;
1759 } else if (2 == reporting_opts &&
1760 0 == (FF_SA & oip->flags)) {
1761 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 4, -1);
1762 kfree(arr); /* point at requested sa */
1763 return check_condition_result;
1764 }
1765 if (0 == (FF_SA & oip->flags) &&
1766 req_opcode == oip->opcode)
1767 supp = 3;
1768 else if (0 == (FF_SA & oip->flags)) {
1769 na = oip->num_attached;
1770 for (k = 0, oip = oip->arrp; k < na;
1771 ++k, ++oip) {
1772 if (req_opcode == oip->opcode)
1773 break;
1774 }
1775 supp = (k >= na) ? 1 : 3;
1776 } else if (req_sa != oip->sa) {
1777 na = oip->num_attached;
1778 for (k = 0, oip = oip->arrp; k < na;
1779 ++k, ++oip) {
1780 if (req_sa == oip->sa)
1781 break;
1782 }
1783 supp = (k >= na) ? 1 : 3;
1784 } else
1785 supp = 3;
1786 if (3 == supp) {
1787 u = oip->len_mask[0];
1788 put_unaligned_be16(u, arr + 2);
1789 arr[4] = oip->opcode;
1790 for (k = 1; k < u; ++k)
1791 arr[4 + k] = (k < 16) ?
1792 oip->len_mask[k] : 0xff;
1793 offset = 4 + u;
1794 } else
1795 offset = 4;
1796 }
1797 arr[1] = (rctd ? 0x80 : 0) | supp;
1798 if (rctd) {
1799 put_unaligned_be16(0xa, arr + offset);
1800 offset += 12;
1801 }
1802 break;
1803 default:
1804 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, 2);
1805 kfree(arr);
1806 return check_condition_result;
1807 }
1808 offset = (offset < a_len) ? offset : a_len;
1809 len = (offset < alloc_len) ? offset : alloc_len;
1810 errsts = fill_from_dev_buffer(scp, arr, len);
1811 kfree(arr);
1812 return errsts;
1813}
1814
1815static int
1816resp_rsup_tmfs(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
1817{
1818 bool repd;
1819 u32 alloc_len, len;
1820 u8 arr[16];
1821 u8 *cmd = scp->cmnd;
1822
1823 memset(arr, 0, sizeof(arr));
1824 repd = !!(cmd[2] & 0x80);
1825 alloc_len = get_unaligned_be32(cmd + 6);
1826 if (alloc_len < 4) {
1827 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 6, -1);
1828 return check_condition_result;
1829 }
1830 arr[0] = 0xc8; /* ATS | ATSS | LURS */
1831 arr[1] = 0x1; /* ITNRS */
1832 if (repd) {
1833 arr[3] = 0xc;
1834 len = 16;
1835 } else
1836 len = 4;
1837
1838 len = (len < alloc_len) ? len : alloc_len;
1839 return fill_from_dev_buffer(scp, arr, len);
1840}
1841
Linus Torvalds1da177e2005-04-16 15:20:36 -07001842/* <<Following mode page info copied from ST318451LW>> */
1843
1844static int resp_err_recov_pg(unsigned char * p, int pcontrol, int target)
1845{ /* Read-Write Error Recovery page for mode_sense */
1846 unsigned char err_recov_pg[] = {0x1, 0xa, 0xc0, 11, 240, 0, 0, 0,
1847 5, 0, 0xff, 0xff};
1848
1849 memcpy(p, err_recov_pg, sizeof(err_recov_pg));
1850 if (1 == pcontrol)
1851 memset(p + 2, 0, sizeof(err_recov_pg) - 2);
1852 return sizeof(err_recov_pg);
1853}
1854
1855static int resp_disconnect_pg(unsigned char * p, int pcontrol, int target)
1856{ /* Disconnect-Reconnect page for mode_sense */
1857 unsigned char disconnect_pg[] = {0x2, 0xe, 128, 128, 0, 10, 0, 0,
1858 0, 0, 0, 0, 0, 0, 0, 0};
1859
1860 memcpy(p, disconnect_pg, sizeof(disconnect_pg));
1861 if (1 == pcontrol)
1862 memset(p + 2, 0, sizeof(disconnect_pg) - 2);
1863 return sizeof(disconnect_pg);
1864}
1865
1866static int resp_format_pg(unsigned char * p, int pcontrol, int target)
1867{ /* Format device page for mode_sense */
Martin K. Petersen597136a2008-06-05 00:12:59 -04001868 unsigned char format_pg[] = {0x3, 0x16, 0, 0, 0, 0, 0, 0,
1869 0, 0, 0, 0, 0, 0, 0, 0,
1870 0, 0, 0, 0, 0x40, 0, 0, 0};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001871
Martin K. Petersen597136a2008-06-05 00:12:59 -04001872 memcpy(p, format_pg, sizeof(format_pg));
1873 p[10] = (sdebug_sectors_per >> 8) & 0xff;
1874 p[11] = sdebug_sectors_per & 0xff;
1875 p[12] = (scsi_debug_sector_size >> 8) & 0xff;
1876 p[13] = scsi_debug_sector_size & 0xff;
Martin Pittd9867882012-09-06 12:04:33 +02001877 if (scsi_debug_removable)
Martin K. Petersen597136a2008-06-05 00:12:59 -04001878 p[20] |= 0x20; /* should agree with INQUIRY */
1879 if (1 == pcontrol)
1880 memset(p + 2, 0, sizeof(format_pg) - 2);
1881 return sizeof(format_pg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001882}
1883
1884static int resp_caching_pg(unsigned char * p, int pcontrol, int target)
1885{ /* Caching page for mode_sense */
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001886 unsigned char ch_caching_pg[] = {/* 0x8, 18, */ 0x4, 0, 0, 0, 0, 0,
1887 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
1888 unsigned char d_caching_pg[] = {0x8, 18, 0x14, 0, 0xff, 0xff, 0, 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001889 0xff, 0xff, 0xff, 0xff, 0x80, 0x14, 0, 0, 0, 0, 0, 0};
1890
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001891 if (SCSI_DEBUG_OPT_N_WCE & scsi_debug_opts)
1892 caching_pg[2] &= ~0x4; /* set WCE=0 (default WCE=1) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001893 memcpy(p, caching_pg, sizeof(caching_pg));
1894 if (1 == pcontrol)
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001895 memcpy(p + 2, ch_caching_pg, sizeof(ch_caching_pg));
1896 else if (2 == pcontrol)
1897 memcpy(p, d_caching_pg, sizeof(d_caching_pg));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001898 return sizeof(caching_pg);
1899}
1900
1901static int resp_ctrl_m_pg(unsigned char * p, int pcontrol, int target)
1902{ /* Control mode page for mode_sense */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001903 unsigned char ch_ctrl_m_pg[] = {/* 0xa, 10, */ 0x6, 0, 0, 0, 0, 0,
1904 0, 0, 0, 0};
1905 unsigned char d_ctrl_m_pg[] = {0xa, 10, 2, 0, 0, 0, 0, 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001906 0, 0, 0x2, 0x4b};
1907
1908 if (scsi_debug_dsense)
1909 ctrl_m_pg[2] |= 0x4;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001910 else
1911 ctrl_m_pg[2] &= ~0x4;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001912
1913 if (scsi_debug_ato)
1914 ctrl_m_pg[5] |= 0x80; /* ATO=1 */
1915
Linus Torvalds1da177e2005-04-16 15:20:36 -07001916 memcpy(p, ctrl_m_pg, sizeof(ctrl_m_pg));
1917 if (1 == pcontrol)
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001918 memcpy(p + 2, ch_ctrl_m_pg, sizeof(ch_ctrl_m_pg));
1919 else if (2 == pcontrol)
1920 memcpy(p, d_ctrl_m_pg, sizeof(d_ctrl_m_pg));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001921 return sizeof(ctrl_m_pg);
1922}
1923
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001924
Linus Torvalds1da177e2005-04-16 15:20:36 -07001925static int resp_iec_m_pg(unsigned char * p, int pcontrol, int target)
1926{ /* Informational Exceptions control mode page for mode_sense */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001927 unsigned char ch_iec_m_pg[] = {/* 0x1c, 0xa, */ 0x4, 0xf, 0, 0, 0, 0,
1928 0, 0, 0x0, 0x0};
1929 unsigned char d_iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0,
1930 0, 0, 0x0, 0x0};
1931
Linus Torvalds1da177e2005-04-16 15:20:36 -07001932 memcpy(p, iec_m_pg, sizeof(iec_m_pg));
1933 if (1 == pcontrol)
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001934 memcpy(p + 2, ch_iec_m_pg, sizeof(ch_iec_m_pg));
1935 else if (2 == pcontrol)
1936 memcpy(p, d_iec_m_pg, sizeof(d_iec_m_pg));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001937 return sizeof(iec_m_pg);
1938}
1939
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001940static int resp_sas_sf_m_pg(unsigned char * p, int pcontrol, int target)
1941{ /* SAS SSP mode page - short format for mode_sense */
1942 unsigned char sas_sf_m_pg[] = {0x19, 0x6,
1943 0x6, 0x0, 0x7, 0xd0, 0x0, 0x0};
1944
1945 memcpy(p, sas_sf_m_pg, sizeof(sas_sf_m_pg));
1946 if (1 == pcontrol)
1947 memset(p + 2, 0, sizeof(sas_sf_m_pg) - 2);
1948 return sizeof(sas_sf_m_pg);
1949}
1950
1951
1952static int resp_sas_pcd_m_spg(unsigned char * p, int pcontrol, int target,
1953 int target_dev_id)
1954{ /* SAS phy control and discover mode page for mode_sense */
1955 unsigned char sas_pcd_m_pg[] = {0x59, 0x1, 0, 0x64, 0, 0x6, 0, 2,
1956 0, 0, 0, 0, 0x10, 0x9, 0x8, 0x0,
1957 0x52, 0x22, 0x22, 0x20, 0x0, 0x0, 0x0, 0x0,
1958 0x51, 0x11, 0x11, 0x10, 0x0, 0x0, 0x0, 0x1,
1959 0x2, 0, 0, 0, 0, 0, 0, 0,
1960 0x88, 0x99, 0, 0, 0, 0, 0, 0,
1961 0, 0, 0, 0, 0, 0, 0, 0,
1962 0, 1, 0, 0, 0x10, 0x9, 0x8, 0x0,
1963 0x52, 0x22, 0x22, 0x20, 0x0, 0x0, 0x0, 0x0,
1964 0x51, 0x11, 0x11, 0x10, 0x0, 0x0, 0x0, 0x1,
1965 0x3, 0, 0, 0, 0, 0, 0, 0,
1966 0x88, 0x99, 0, 0, 0, 0, 0, 0,
1967 0, 0, 0, 0, 0, 0, 0, 0,
1968 };
1969 int port_a, port_b;
1970
1971 port_a = target_dev_id + 1;
1972 port_b = port_a + 1;
1973 memcpy(p, sas_pcd_m_pg, sizeof(sas_pcd_m_pg));
1974 p[20] = (port_a >> 24);
1975 p[21] = (port_a >> 16) & 0xff;
1976 p[22] = (port_a >> 8) & 0xff;
1977 p[23] = port_a & 0xff;
1978 p[48 + 20] = (port_b >> 24);
1979 p[48 + 21] = (port_b >> 16) & 0xff;
1980 p[48 + 22] = (port_b >> 8) & 0xff;
1981 p[48 + 23] = port_b & 0xff;
1982 if (1 == pcontrol)
1983 memset(p + 4, 0, sizeof(sas_pcd_m_pg) - 4);
1984 return sizeof(sas_pcd_m_pg);
1985}
1986
1987static int resp_sas_sha_m_spg(unsigned char * p, int pcontrol)
1988{ /* SAS SSP shared protocol specific port mode subpage */
1989 unsigned char sas_sha_m_pg[] = {0x59, 0x2, 0, 0xc, 0, 0x6, 0x10, 0,
1990 0, 0, 0, 0, 0, 0, 0, 0,
1991 };
1992
1993 memcpy(p, sas_sha_m_pg, sizeof(sas_sha_m_pg));
1994 if (1 == pcontrol)
1995 memset(p + 4, 0, sizeof(sas_sha_m_pg) - 4);
1996 return sizeof(sas_sha_m_pg);
1997}
1998
Linus Torvalds1da177e2005-04-16 15:20:36 -07001999#define SDEBUG_MAX_MSENSE_SZ 256
2000
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002001static int
2002resp_mode_sense(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002003{
Douglas Gilbert23183912006-09-16 20:30:47 -04002004 unsigned char dbd, llbaa;
2005 int pcontrol, pcode, subpcode, bd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002006 unsigned char dev_spec;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002007 int k, alloc_len, msense_6, offset, len, target_dev_id;
2008 int target = scp->device->id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002009 unsigned char * ap;
2010 unsigned char arr[SDEBUG_MAX_MSENSE_SZ];
Douglas Gilbert01123ef2014-08-05 12:20:02 +02002011 unsigned char *cmd = scp->cmnd;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002012
Douglas Gilbert23183912006-09-16 20:30:47 -04002013 dbd = !!(cmd[1] & 0x8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014 pcontrol = (cmd[2] & 0xc0) >> 6;
2015 pcode = cmd[2] & 0x3f;
2016 subpcode = cmd[3];
2017 msense_6 = (MODE_SENSE == cmd[0]);
Douglas Gilbert23183912006-09-16 20:30:47 -04002018 llbaa = msense_6 ? 0 : !!(cmd[1] & 0x10);
2019 if ((0 == scsi_debug_ptype) && (0 == dbd))
2020 bd_len = llbaa ? 16 : 8;
2021 else
2022 bd_len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002023 alloc_len = msense_6 ? cmd[4] : ((cmd[7] << 8) | cmd[8]);
2024 memset(arr, 0, SDEBUG_MAX_MSENSE_SZ);
2025 if (0x3 == pcontrol) { /* Saving values not supported */
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002026 mk_sense_buffer(scp, ILLEGAL_REQUEST, SAVING_PARAMS_UNSUP, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002027 return check_condition_result;
2028 }
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002029 target_dev_id = ((devip->sdbg_host->shost->host_no + 1) * 2000) +
2030 (devip->target * 1000) - 3;
Douglas Gilbert23183912006-09-16 20:30:47 -04002031 /* set DPOFUA bit for disks */
2032 if (0 == scsi_debug_ptype)
2033 dev_spec = (DEV_READONLY(target) ? 0x80 : 0x0) | 0x10;
2034 else
2035 dev_spec = 0x0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002036 if (msense_6) {
2037 arr[2] = dev_spec;
Douglas Gilbert23183912006-09-16 20:30:47 -04002038 arr[3] = bd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002039 offset = 4;
2040 } else {
2041 arr[3] = dev_spec;
Douglas Gilbert23183912006-09-16 20:30:47 -04002042 if (16 == bd_len)
2043 arr[4] = 0x1; /* set LONGLBA bit */
2044 arr[7] = bd_len; /* assume 255 or less */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002045 offset = 8;
2046 }
2047 ap = arr + offset;
FUJITA Tomonori28898872008-03-30 00:59:55 +09002048 if ((bd_len > 0) && (!sdebug_capacity))
2049 sdebug_capacity = get_sdebug_capacity();
2050
Douglas Gilbert23183912006-09-16 20:30:47 -04002051 if (8 == bd_len) {
2052 if (sdebug_capacity > 0xfffffffe) {
2053 ap[0] = 0xff;
2054 ap[1] = 0xff;
2055 ap[2] = 0xff;
2056 ap[3] = 0xff;
2057 } else {
2058 ap[0] = (sdebug_capacity >> 24) & 0xff;
2059 ap[1] = (sdebug_capacity >> 16) & 0xff;
2060 ap[2] = (sdebug_capacity >> 8) & 0xff;
2061 ap[3] = sdebug_capacity & 0xff;
2062 }
Martin K. Petersen597136a2008-06-05 00:12:59 -04002063 ap[6] = (scsi_debug_sector_size >> 8) & 0xff;
2064 ap[7] = scsi_debug_sector_size & 0xff;
Douglas Gilbert23183912006-09-16 20:30:47 -04002065 offset += bd_len;
2066 ap = arr + offset;
2067 } else if (16 == bd_len) {
2068 unsigned long long capac = sdebug_capacity;
2069
2070 for (k = 0; k < 8; ++k, capac >>= 8)
2071 ap[7 - k] = capac & 0xff;
Martin K. Petersen597136a2008-06-05 00:12:59 -04002072 ap[12] = (scsi_debug_sector_size >> 24) & 0xff;
2073 ap[13] = (scsi_debug_sector_size >> 16) & 0xff;
2074 ap[14] = (scsi_debug_sector_size >> 8) & 0xff;
2075 ap[15] = scsi_debug_sector_size & 0xff;
Douglas Gilbert23183912006-09-16 20:30:47 -04002076 offset += bd_len;
2077 ap = arr + offset;
2078 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002079
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002080 if ((subpcode > 0x0) && (subpcode < 0xff) && (0x19 != pcode)) {
2081 /* TODO: Control Extension page */
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002082 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 3, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002083 return check_condition_result;
2084 }
2085 switch (pcode) {
2086 case 0x1: /* Read-Write error recovery page, direct access */
2087 len = resp_err_recov_pg(ap, pcontrol, target);
2088 offset += len;
2089 break;
2090 case 0x2: /* Disconnect-Reconnect page, all devices */
2091 len = resp_disconnect_pg(ap, pcontrol, target);
2092 offset += len;
2093 break;
2094 case 0x3: /* Format device page, direct access */
2095 len = resp_format_pg(ap, pcontrol, target);
2096 offset += len;
2097 break;
2098 case 0x8: /* Caching page, direct access */
2099 len = resp_caching_pg(ap, pcontrol, target);
2100 offset += len;
2101 break;
2102 case 0xa: /* Control Mode page, all devices */
2103 len = resp_ctrl_m_pg(ap, pcontrol, target);
2104 offset += len;
2105 break;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002106 case 0x19: /* if spc==1 then sas phy, control+discover */
2107 if ((subpcode > 0x2) && (subpcode < 0xff)) {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002108 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 3, -1);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002109 return check_condition_result;
2110 }
2111 len = 0;
2112 if ((0x0 == subpcode) || (0xff == subpcode))
2113 len += resp_sas_sf_m_pg(ap + len, pcontrol, target);
2114 if ((0x1 == subpcode) || (0xff == subpcode))
2115 len += resp_sas_pcd_m_spg(ap + len, pcontrol, target,
2116 target_dev_id);
2117 if ((0x2 == subpcode) || (0xff == subpcode))
2118 len += resp_sas_sha_m_spg(ap + len, pcontrol);
2119 offset += len;
2120 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002121 case 0x1c: /* Informational Exceptions Mode page, all devices */
2122 len = resp_iec_m_pg(ap, pcontrol, target);
2123 offset += len;
2124 break;
2125 case 0x3f: /* Read all Mode pages */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002126 if ((0 == subpcode) || (0xff == subpcode)) {
2127 len = resp_err_recov_pg(ap, pcontrol, target);
2128 len += resp_disconnect_pg(ap + len, pcontrol, target);
2129 len += resp_format_pg(ap + len, pcontrol, target);
2130 len += resp_caching_pg(ap + len, pcontrol, target);
2131 len += resp_ctrl_m_pg(ap + len, pcontrol, target);
2132 len += resp_sas_sf_m_pg(ap + len, pcontrol, target);
2133 if (0xff == subpcode) {
2134 len += resp_sas_pcd_m_spg(ap + len, pcontrol,
2135 target, target_dev_id);
2136 len += resp_sas_sha_m_spg(ap + len, pcontrol);
2137 }
2138 len += resp_iec_m_pg(ap + len, pcontrol, target);
2139 } else {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002140 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 3, -1);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002141 return check_condition_result;
2142 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002143 offset += len;
2144 break;
2145 default:
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002146 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, 5);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002147 return check_condition_result;
2148 }
2149 if (msense_6)
2150 arr[0] = offset - 1;
2151 else {
2152 arr[0] = ((offset - 2) >> 8) & 0xff;
2153 arr[1] = (offset - 2) & 0xff;
2154 }
2155 return fill_from_dev_buffer(scp, arr, min(alloc_len, offset));
2156}
2157
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002158#define SDEBUG_MAX_MSELECT_SZ 512
2159
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002160static int
2161resp_mode_select(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002162{
2163 int pf, sp, ps, md_len, bd_len, off, spf, pg_len;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002164 int param_len, res, mpage;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002165 unsigned char arr[SDEBUG_MAX_MSELECT_SZ];
Douglas Gilbert01123ef2014-08-05 12:20:02 +02002166 unsigned char *cmd = scp->cmnd;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002167 int mselect6 = (MODE_SELECT == cmd[0]);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002168
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002169 memset(arr, 0, sizeof(arr));
2170 pf = cmd[1] & 0x10;
2171 sp = cmd[1] & 0x1;
2172 param_len = mselect6 ? cmd[4] : ((cmd[7] << 8) + cmd[8]);
2173 if ((0 == pf) || sp || (param_len > SDEBUG_MAX_MSELECT_SZ)) {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002174 mk_sense_invalid_fld(scp, SDEB_IN_CDB, mselect6 ? 4 : 7, -1);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002175 return check_condition_result;
2176 }
2177 res = fetch_to_dev_buffer(scp, arr, param_len);
2178 if (-1 == res)
2179 return (DID_ERROR << 16);
2180 else if ((res < param_len) &&
2181 (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002182 sdev_printk(KERN_INFO, scp->device,
2183 "%s: cdb indicated=%d, IO sent=%d bytes\n",
2184 __func__, param_len, res);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002185 md_len = mselect6 ? (arr[0] + 1) : ((arr[0] << 8) + arr[1] + 2);
2186 bd_len = mselect6 ? arr[3] : ((arr[6] << 8) + arr[7]);
Douglas Gilbert23183912006-09-16 20:30:47 -04002187 if (md_len > 2) {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002188 mk_sense_invalid_fld(scp, SDEB_IN_DATA, 0, -1);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002189 return check_condition_result;
2190 }
2191 off = bd_len + (mselect6 ? 4 : 8);
2192 mpage = arr[off] & 0x3f;
2193 ps = !!(arr[off] & 0x80);
2194 if (ps) {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002195 mk_sense_invalid_fld(scp, SDEB_IN_DATA, off, 7);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002196 return check_condition_result;
2197 }
2198 spf = !!(arr[off] & 0x40);
2199 pg_len = spf ? ((arr[off + 2] << 8) + arr[off + 3] + 4) :
2200 (arr[off + 1] + 2);
2201 if ((pg_len + off) > param_len) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002202 mk_sense_buffer(scp, ILLEGAL_REQUEST,
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002203 PARAMETER_LIST_LENGTH_ERR, 0);
2204 return check_condition_result;
2205 }
2206 switch (mpage) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002207 case 0x8: /* Caching Mode page */
2208 if (caching_pg[1] == arr[off + 1]) {
2209 memcpy(caching_pg + 2, arr + off + 2,
2210 sizeof(caching_pg) - 2);
2211 goto set_mode_changed_ua;
2212 }
2213 break;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002214 case 0xa: /* Control Mode page */
2215 if (ctrl_m_pg[1] == arr[off + 1]) {
2216 memcpy(ctrl_m_pg + 2, arr + off + 2,
2217 sizeof(ctrl_m_pg) - 2);
2218 scsi_debug_dsense = !!(ctrl_m_pg[2] & 0x4);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002219 goto set_mode_changed_ua;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002220 }
2221 break;
2222 case 0x1c: /* Informational Exceptions Mode page */
2223 if (iec_m_pg[1] == arr[off + 1]) {
2224 memcpy(iec_m_pg + 2, arr + off + 2,
2225 sizeof(iec_m_pg) - 2);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002226 goto set_mode_changed_ua;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002227 }
2228 break;
2229 default:
2230 break;
2231 }
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002232 mk_sense_invalid_fld(scp, SDEB_IN_DATA, off, 5);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002233 return check_condition_result;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002234set_mode_changed_ua:
2235 set_bit(SDEBUG_UA_MODE_CHANGED, devip->uas_bm);
2236 return 0;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002237}
2238
2239static int resp_temp_l_pg(unsigned char * arr)
2240{
2241 unsigned char temp_l_pg[] = {0x0, 0x0, 0x3, 0x2, 0x0, 38,
2242 0x0, 0x1, 0x3, 0x2, 0x0, 65,
2243 };
2244
2245 memcpy(arr, temp_l_pg, sizeof(temp_l_pg));
2246 return sizeof(temp_l_pg);
2247}
2248
2249static int resp_ie_l_pg(unsigned char * arr)
2250{
2251 unsigned char ie_l_pg[] = {0x0, 0x0, 0x3, 0x3, 0x0, 0x0, 38,
2252 };
2253
2254 memcpy(arr, ie_l_pg, sizeof(ie_l_pg));
2255 if (iec_m_pg[2] & 0x4) { /* TEST bit set */
2256 arr[4] = THRESHOLD_EXCEEDED;
2257 arr[5] = 0xff;
2258 }
2259 return sizeof(ie_l_pg);
2260}
2261
2262#define SDEBUG_MAX_LSENSE_SZ 512
2263
2264static int resp_log_sense(struct scsi_cmnd * scp,
2265 struct sdebug_dev_info * devip)
2266{
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002267 int ppc, sp, pcontrol, pcode, subpcode, alloc_len, len, n;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002268 unsigned char arr[SDEBUG_MAX_LSENSE_SZ];
Douglas Gilbert01123ef2014-08-05 12:20:02 +02002269 unsigned char *cmd = scp->cmnd;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002270
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002271 memset(arr, 0, sizeof(arr));
2272 ppc = cmd[1] & 0x2;
2273 sp = cmd[1] & 0x1;
2274 if (ppc || sp) {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002275 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 1, ppc ? 1 : 0);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002276 return check_condition_result;
2277 }
2278 pcontrol = (cmd[2] & 0xc0) >> 6;
2279 pcode = cmd[2] & 0x3f;
Douglas Gilbert23183912006-09-16 20:30:47 -04002280 subpcode = cmd[3] & 0xff;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002281 alloc_len = (cmd[7] << 8) + cmd[8];
2282 arr[0] = pcode;
Douglas Gilbert23183912006-09-16 20:30:47 -04002283 if (0 == subpcode) {
2284 switch (pcode) {
2285 case 0x0: /* Supported log pages log page */
2286 n = 4;
2287 arr[n++] = 0x0; /* this page */
2288 arr[n++] = 0xd; /* Temperature */
2289 arr[n++] = 0x2f; /* Informational exceptions */
2290 arr[3] = n - 4;
2291 break;
2292 case 0xd: /* Temperature log page */
2293 arr[3] = resp_temp_l_pg(arr + 4);
2294 break;
2295 case 0x2f: /* Informational exceptions log page */
2296 arr[3] = resp_ie_l_pg(arr + 4);
2297 break;
2298 default:
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002299 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, 5);
Douglas Gilbert23183912006-09-16 20:30:47 -04002300 return check_condition_result;
2301 }
2302 } else if (0xff == subpcode) {
2303 arr[0] |= 0x40;
2304 arr[1] = subpcode;
2305 switch (pcode) {
2306 case 0x0: /* Supported log pages and subpages log page */
2307 n = 4;
2308 arr[n++] = 0x0;
2309 arr[n++] = 0x0; /* 0,0 page */
2310 arr[n++] = 0x0;
2311 arr[n++] = 0xff; /* this page */
2312 arr[n++] = 0xd;
2313 arr[n++] = 0x0; /* Temperature */
2314 arr[n++] = 0x2f;
2315 arr[n++] = 0x0; /* Informational exceptions */
2316 arr[3] = n - 4;
2317 break;
2318 case 0xd: /* Temperature subpages */
2319 n = 4;
2320 arr[n++] = 0xd;
2321 arr[n++] = 0x0; /* Temperature */
2322 arr[3] = n - 4;
2323 break;
2324 case 0x2f: /* Informational exceptions subpages */
2325 n = 4;
2326 arr[n++] = 0x2f;
2327 arr[n++] = 0x0; /* Informational exceptions */
2328 arr[3] = n - 4;
2329 break;
2330 default:
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002331 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, 5);
Douglas Gilbert23183912006-09-16 20:30:47 -04002332 return check_condition_result;
2333 }
2334 } else {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002335 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 3, -1);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002336 return check_condition_result;
2337 }
2338 len = min(((arr[2] << 8) + arr[3]) + 4, alloc_len);
2339 return fill_from_dev_buffer(scp, arr,
2340 min(len, SDEBUG_MAX_INQ_ARR_SZ));
2341}
2342
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002343static int check_device_access_params(struct scsi_cmnd *scp,
FUJITA Tomonori19789102008-03-30 00:59:56 +09002344 unsigned long long lba, unsigned int num)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002345{
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002346 if (lba + num > sdebug_capacity) {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002347 mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002348 return check_condition_result;
2349 }
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002350 /* transfer length excessive (tie in to block limits VPD page) */
2351 if (num > sdebug_store_sectors) {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002352 /* needs work to find which cdb byte 'num' comes from */
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002353 mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002354 return check_condition_result;
2355 }
FUJITA Tomonori19789102008-03-30 00:59:56 +09002356 return 0;
2357}
2358
Akinobu Mitaa4517512013-07-08 16:01:57 -07002359/* Returns number of bytes copied or -1 if error. */
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002360static int
2361do_device_access(struct scsi_cmnd *scmd, u64 lba, u32 num, bool do_write)
FUJITA Tomonori19789102008-03-30 00:59:56 +09002362{
2363 int ret;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002364 u64 block, rest = 0;
Akinobu Mitaa4517512013-07-08 16:01:57 -07002365 struct scsi_data_buffer *sdb;
2366 enum dma_data_direction dir;
FUJITA Tomonori19789102008-03-30 00:59:56 +09002367
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002368 if (do_write) {
Akinobu Mitaa4517512013-07-08 16:01:57 -07002369 sdb = scsi_out(scmd);
2370 dir = DMA_TO_DEVICE;
Akinobu Mitaa4517512013-07-08 16:01:57 -07002371 } else {
2372 sdb = scsi_in(scmd);
2373 dir = DMA_FROM_DEVICE;
Akinobu Mitaa4517512013-07-08 16:01:57 -07002374 }
2375
2376 if (!sdb->length)
2377 return 0;
2378 if (!(scsi_bidi_cmnd(scmd) || scmd->sc_data_direction == dir))
2379 return -1;
FUJITA Tomonori19789102008-03-30 00:59:56 +09002380
2381 block = do_div(lba, sdebug_store_sectors);
2382 if (block + num > sdebug_store_sectors)
2383 rest = block + num - sdebug_store_sectors;
2384
Dave Gordon386ecb12015-06-30 14:58:57 -07002385 ret = sg_copy_buffer(sdb->table.sgl, sdb->table.nents,
Akinobu Mitaa4517512013-07-08 16:01:57 -07002386 fake_storep + (block * scsi_debug_sector_size),
Dave Gordon386ecb12015-06-30 14:58:57 -07002387 (num - rest) * scsi_debug_sector_size, 0, do_write);
Akinobu Mitaa4517512013-07-08 16:01:57 -07002388 if (ret != (num - rest) * scsi_debug_sector_size)
2389 return ret;
2390
2391 if (rest) {
Dave Gordon386ecb12015-06-30 14:58:57 -07002392 ret += sg_copy_buffer(sdb->table.sgl, sdb->table.nents,
Akinobu Mitaa4517512013-07-08 16:01:57 -07002393 fake_storep, rest * scsi_debug_sector_size,
Dave Gordon386ecb12015-06-30 14:58:57 -07002394 (num - rest) * scsi_debug_sector_size, do_write);
Akinobu Mitaa4517512013-07-08 16:01:57 -07002395 }
FUJITA Tomonori19789102008-03-30 00:59:56 +09002396
2397 return ret;
2398}
2399
Douglas Gilbert38d5c832014-11-24 21:27:12 -05002400/* If fake_store(lba,num) compares equal to arr(num), then copy top half of
2401 * arr into fake_store(lba,num) and return true. If comparison fails then
2402 * return false. */
2403static bool
2404comp_write_worker(u64 lba, u32 num, const u8 *arr)
2405{
2406 bool res;
2407 u64 block, rest = 0;
2408 u32 store_blks = sdebug_store_sectors;
2409 u32 lb_size = scsi_debug_sector_size;
2410
2411 block = do_div(lba, store_blks);
2412 if (block + num > store_blks)
2413 rest = block + num - store_blks;
2414
2415 res = !memcmp(fake_storep + (block * lb_size), arr,
2416 (num - rest) * lb_size);
2417 if (!res)
2418 return res;
2419 if (rest)
2420 res = memcmp(fake_storep, arr + ((num - rest) * lb_size),
2421 rest * lb_size);
2422 if (!res)
2423 return res;
2424 arr += num * lb_size;
2425 memcpy(fake_storep + (block * lb_size), arr, (num - rest) * lb_size);
2426 if (rest)
2427 memcpy(fake_storep, arr + ((num - rest) * lb_size),
2428 rest * lb_size);
2429 return res;
2430}
2431
Akinobu Mita51d648a2013-09-18 21:27:28 +09002432static __be16 dif_compute_csum(const void *buf, int len)
Akinobu Mitabeb40ea2013-06-29 17:59:19 +09002433{
Akinobu Mita51d648a2013-09-18 21:27:28 +09002434 __be16 csum;
Akinobu Mitabeb40ea2013-06-29 17:59:19 +09002435
Akinobu Mita51d648a2013-09-18 21:27:28 +09002436 if (scsi_debug_guard)
2437 csum = (__force __be16)ip_compute_csum(buf, len);
2438 else
Akinobu Mitabeb40ea2013-06-29 17:59:19 +09002439 csum = cpu_to_be16(crc_t10dif(buf, len));
Akinobu Mita51d648a2013-09-18 21:27:28 +09002440
Akinobu Mitabeb40ea2013-06-29 17:59:19 +09002441 return csum;
2442}
2443
2444static int dif_verify(struct sd_dif_tuple *sdt, const void *data,
2445 sector_t sector, u32 ei_lba)
2446{
Akinobu Mita51d648a2013-09-18 21:27:28 +09002447 __be16 csum = dif_compute_csum(data, scsi_debug_sector_size);
Akinobu Mitabeb40ea2013-06-29 17:59:19 +09002448
2449 if (sdt->guard_tag != csum) {
Tomas Winklerc12879702015-07-28 16:54:20 +03002450 pr_err("GUARD check failed on sector %lu rcvd 0x%04x, data 0x%04x\n",
Akinobu Mitabeb40ea2013-06-29 17:59:19 +09002451 (unsigned long)sector,
2452 be16_to_cpu(sdt->guard_tag),
2453 be16_to_cpu(csum));
2454 return 0x01;
2455 }
2456 if (scsi_debug_dif == SD_DIF_TYPE1_PROTECTION &&
2457 be32_to_cpu(sdt->ref_tag) != (sector & 0xffffffff)) {
Tomas Winklerc12879702015-07-28 16:54:20 +03002458 pr_err("REF check failed on sector %lu\n",
2459 (unsigned long)sector);
Akinobu Mitabeb40ea2013-06-29 17:59:19 +09002460 return 0x03;
2461 }
2462 if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
2463 be32_to_cpu(sdt->ref_tag) != ei_lba) {
Tomas Winklerc12879702015-07-28 16:54:20 +03002464 pr_err("REF check failed on sector %lu\n",
2465 (unsigned long)sector);
Akinobu Mitabeb40ea2013-06-29 17:59:19 +09002466 return 0x03;
2467 }
2468 return 0;
2469}
2470
Akinobu Mitabb8c0632013-09-18 21:27:25 +09002471static void dif_copy_prot(struct scsi_cmnd *SCpnt, sector_t sector,
Akinobu Mita65f72f2a2013-09-18 21:27:26 +09002472 unsigned int sectors, bool read)
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002473{
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002474 size_t resid;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002475 void *paddr;
Akinobu Mita14faa942013-09-18 21:27:24 +09002476 const void *dif_store_end = dif_storep + sdebug_store_sectors;
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002477 struct sg_mapping_iter miter;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002478
Akinobu Mitae18d8be2013-06-29 17:59:18 +09002479 /* Bytes of protection data to copy into sgl */
2480 resid = sectors * sizeof(*dif_storep);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002481
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002482 sg_miter_start(&miter, scsi_prot_sglist(SCpnt),
2483 scsi_prot_sg_count(SCpnt), SG_MITER_ATOMIC |
2484 (read ? SG_MITER_TO_SG : SG_MITER_FROM_SG));
2485
2486 while (sg_miter_next(&miter) && resid > 0) {
2487 size_t len = min(miter.length, resid);
Akinobu Mita14faa942013-09-18 21:27:24 +09002488 void *start = dif_store(sector);
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002489 size_t rest = 0;
Akinobu Mita14faa942013-09-18 21:27:24 +09002490
2491 if (dif_store_end < start + len)
2492 rest = start + len - dif_store_end;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002493
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002494 paddr = miter.addr;
Akinobu Mita14faa942013-09-18 21:27:24 +09002495
Akinobu Mita65f72f2a2013-09-18 21:27:26 +09002496 if (read)
2497 memcpy(paddr, start, len - rest);
2498 else
2499 memcpy(start, paddr, len - rest);
2500
2501 if (rest) {
2502 if (read)
2503 memcpy(paddr + len - rest, dif_storep, rest);
2504 else
2505 memcpy(dif_storep, paddr + len - rest, rest);
2506 }
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002507
Akinobu Mitae18d8be2013-06-29 17:59:18 +09002508 sector += len / sizeof(*dif_storep);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002509 resid -= len;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002510 }
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002511 sg_miter_stop(&miter);
Akinobu Mitabb8c0632013-09-18 21:27:25 +09002512}
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002513
Akinobu Mitabb8c0632013-09-18 21:27:25 +09002514static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec,
2515 unsigned int sectors, u32 ei_lba)
2516{
2517 unsigned int i;
2518 struct sd_dif_tuple *sdt;
2519 sector_t sector;
2520
Akinobu Mitac45eabec2014-02-26 22:56:58 +09002521 for (i = 0; i < sectors; i++, ei_lba++) {
Akinobu Mitabb8c0632013-09-18 21:27:25 +09002522 int ret;
2523
2524 sector = start_sec + i;
2525 sdt = dif_store(sector);
2526
Akinobu Mita51d648a2013-09-18 21:27:28 +09002527 if (sdt->app_tag == cpu_to_be16(0xffff))
Akinobu Mitabb8c0632013-09-18 21:27:25 +09002528 continue;
2529
2530 ret = dif_verify(sdt, fake_store(sector), sector, ei_lba);
2531 if (ret) {
2532 dif_errors++;
2533 return ret;
2534 }
Akinobu Mitabb8c0632013-09-18 21:27:25 +09002535 }
2536
Akinobu Mita65f72f2a2013-09-18 21:27:26 +09002537 dif_copy_prot(SCpnt, start_sec, sectors, true);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002538 dix_reads++;
2539
2540 return 0;
2541}
2542
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002543static int
2544resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
FUJITA Tomonori19789102008-03-30 00:59:56 +09002545{
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002546 u8 *cmd = scp->cmnd;
2547 u64 lba;
2548 u32 num;
2549 u32 ei_lba;
FUJITA Tomonori19789102008-03-30 00:59:56 +09002550 unsigned long iflags;
2551 int ret;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002552 bool check_prot;
FUJITA Tomonori19789102008-03-30 00:59:56 +09002553
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002554 switch (cmd[0]) {
2555 case READ_16:
2556 ei_lba = 0;
2557 lba = get_unaligned_be64(cmd + 2);
2558 num = get_unaligned_be32(cmd + 10);
2559 check_prot = true;
2560 break;
2561 case READ_10:
2562 ei_lba = 0;
2563 lba = get_unaligned_be32(cmd + 2);
2564 num = get_unaligned_be16(cmd + 7);
2565 check_prot = true;
2566 break;
2567 case READ_6:
2568 ei_lba = 0;
2569 lba = (u32)cmd[3] | (u32)cmd[2] << 8 |
2570 (u32)(cmd[1] & 0x1f) << 16;
2571 num = (0 == cmd[4]) ? 256 : cmd[4];
2572 check_prot = true;
2573 break;
2574 case READ_12:
2575 ei_lba = 0;
2576 lba = get_unaligned_be32(cmd + 2);
2577 num = get_unaligned_be32(cmd + 6);
2578 check_prot = true;
2579 break;
2580 case XDWRITEREAD_10:
2581 ei_lba = 0;
2582 lba = get_unaligned_be32(cmd + 2);
2583 num = get_unaligned_be16(cmd + 7);
2584 check_prot = false;
2585 break;
2586 default: /* assume READ(32) */
2587 lba = get_unaligned_be64(cmd + 12);
2588 ei_lba = get_unaligned_be32(cmd + 20);
2589 num = get_unaligned_be32(cmd + 28);
2590 check_prot = false;
2591 break;
2592 }
2593 if (check_prot) {
2594 if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
2595 (cmd[1] & 0xe0)) {
2596 mk_sense_invalid_opcode(scp);
2597 return check_condition_result;
2598 }
2599 if ((scsi_debug_dif == SD_DIF_TYPE1_PROTECTION ||
2600 scsi_debug_dif == SD_DIF_TYPE3_PROTECTION) &&
2601 (cmd[1] & 0xe0) == 0)
2602 sdev_printk(KERN_ERR, scp->device, "Unprotected RD "
2603 "to DIF device\n");
2604 }
2605 if (sdebug_any_injecting_opt) {
2606 struct sdebug_scmd_extra_t *ep = scsi_cmd_priv(scp);
2607
2608 if (ep->inj_short)
2609 num /= 2;
2610 }
2611
2612 /* inline check_device_access_params() */
2613 if (lba + num > sdebug_capacity) {
2614 mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0);
2615 return check_condition_result;
2616 }
2617 /* transfer length excessive (tie in to block limits VPD page) */
2618 if (num > sdebug_store_sectors) {
2619 /* needs work to find which cdb byte 'num' comes from */
2620 mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0);
2621 return check_condition_result;
2622 }
FUJITA Tomonori19789102008-03-30 00:59:56 +09002623
Linus Torvalds1da177e2005-04-16 15:20:36 -07002624 if ((SCSI_DEBUG_OPT_MEDIUM_ERR & scsi_debug_opts) &&
Douglas Gilbert32f7ef72011-03-11 10:43:35 -05002625 (lba <= (OPT_MEDIUM_ERR_ADDR + OPT_MEDIUM_ERR_NUM - 1)) &&
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002626 ((lba + num) > OPT_MEDIUM_ERR_ADDR)) {
2627 /* claim unrecoverable read error */
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002628 mk_sense_buffer(scp, MEDIUM_ERROR, UNRECOVERED_READ_ERR, 0);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002629 /* set info field and valid bit for fixed descriptor */
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002630 if (0x70 == (scp->sense_buffer[0] & 0x7f)) {
2631 scp->sense_buffer[0] |= 0x80; /* Valid bit */
Douglas Gilbert32f7ef72011-03-11 10:43:35 -05002632 ret = (lba < OPT_MEDIUM_ERR_ADDR)
2633 ? OPT_MEDIUM_ERR_ADDR : (int)lba;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002634 put_unaligned_be32(ret, scp->sense_buffer + 3);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002635 }
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002636 scsi_set_resid(scp, scsi_bufflen(scp));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002637 return check_condition_result;
2638 }
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002639
Akinobu Mita6c78cc02014-02-26 22:57:03 +09002640 read_lock_irqsave(&atomic_rw, iflags);
2641
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002642 /* DIX + T10 DIF */
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002643 if (scsi_debug_dix && scsi_prot_sg_count(scp)) {
2644 int prot_ret = prot_verify_read(scp, lba, num, ei_lba);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002645
2646 if (prot_ret) {
Akinobu Mita6c78cc02014-02-26 22:57:03 +09002647 read_unlock_irqrestore(&atomic_rw, iflags);
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002648 mk_sense_buffer(scp, ABORTED_COMMAND, 0x10, prot_ret);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002649 return illegal_condition_result;
2650 }
2651 }
2652
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002653 ret = do_device_access(scp, lba, num, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002654 read_unlock_irqrestore(&atomic_rw, iflags);
Akinobu Mitaa4517512013-07-08 16:01:57 -07002655 if (ret == -1)
2656 return DID_ERROR << 16;
2657
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002658 scsi_in(scp)->resid = scsi_bufflen(scp) - ret;
Akinobu Mitaa4517512013-07-08 16:01:57 -07002659
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002660 if (sdebug_any_injecting_opt) {
2661 struct sdebug_scmd_extra_t *ep = scsi_cmd_priv(scp);
2662
2663 if (ep->inj_recovered) {
2664 mk_sense_buffer(scp, RECOVERED_ERROR,
2665 THRESHOLD_EXCEEDED, 0);
2666 return check_condition_result;
2667 } else if (ep->inj_transport) {
2668 mk_sense_buffer(scp, ABORTED_COMMAND,
2669 TRANSPORT_PROBLEM, ACK_NAK_TO);
2670 return check_condition_result;
2671 } else if (ep->inj_dif) {
2672 /* Logical block guard check failed */
2673 mk_sense_buffer(scp, ABORTED_COMMAND, 0x10, 1);
2674 return illegal_condition_result;
2675 } else if (ep->inj_dix) {
2676 mk_sense_buffer(scp, ILLEGAL_REQUEST, 0x10, 1);
2677 return illegal_condition_result;
2678 }
2679 }
Akinobu Mitaa4517512013-07-08 16:01:57 -07002680 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002681}
2682
Tomas Winkler58a86352015-07-28 16:54:23 +03002683static void dump_sector(unsigned char *buf, int len)
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002684{
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002685 int i, j, n;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002686
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002687 pr_err(">>> Sector Dump <<<\n");
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002688 for (i = 0 ; i < len ; i += 16) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002689 char b[128];
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002690
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002691 for (j = 0, n = 0; j < 16; j++) {
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002692 unsigned char c = buf[i+j];
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002693
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002694 if (c >= 0x20 && c < 0x7e)
2695 n += scnprintf(b + n, sizeof(b) - n,
2696 " %c ", buf[i+j]);
2697 else
2698 n += scnprintf(b + n, sizeof(b) - n,
2699 "%02x ", buf[i+j]);
2700 }
2701 pr_err("%04d: %s\n", i, b);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002702 }
2703}
2704
2705static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec,
Martin K. Petersen395cef02009-09-18 17:33:03 -04002706 unsigned int sectors, u32 ei_lba)
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002707{
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002708 int ret;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002709 struct sd_dif_tuple *sdt;
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002710 void *daddr;
Akinobu Mita65f72f2a2013-09-18 21:27:26 +09002711 sector_t sector = start_sec;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002712 int ppage_offset;
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002713 int dpage_offset;
2714 struct sg_mapping_iter diter;
2715 struct sg_mapping_iter piter;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002716
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002717 BUG_ON(scsi_sg_count(SCpnt) == 0);
2718 BUG_ON(scsi_prot_sg_count(SCpnt) == 0);
2719
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002720 sg_miter_start(&piter, scsi_prot_sglist(SCpnt),
2721 scsi_prot_sg_count(SCpnt),
2722 SG_MITER_ATOMIC | SG_MITER_FROM_SG);
2723 sg_miter_start(&diter, scsi_sglist(SCpnt), scsi_sg_count(SCpnt),
2724 SG_MITER_ATOMIC | SG_MITER_FROM_SG);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002725
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002726 /* For each protection page */
2727 while (sg_miter_next(&piter)) {
2728 dpage_offset = 0;
2729 if (WARN_ON(!sg_miter_next(&diter))) {
2730 ret = 0x01;
2731 goto out;
2732 }
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002733
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002734 for (ppage_offset = 0; ppage_offset < piter.length;
2735 ppage_offset += sizeof(struct sd_dif_tuple)) {
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002736 /* If we're at the end of the current
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002737 * data page advance to the next one
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002738 */
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002739 if (dpage_offset >= diter.length) {
2740 if (WARN_ON(!sg_miter_next(&diter))) {
2741 ret = 0x01;
2742 goto out;
2743 }
2744 dpage_offset = 0;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002745 }
2746
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002747 sdt = piter.addr + ppage_offset;
2748 daddr = diter.addr + dpage_offset;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002749
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002750 ret = dif_verify(sdt, daddr, sector, ei_lba);
Akinobu Mitabeb40ea2013-06-29 17:59:19 +09002751 if (ret) {
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002752 dump_sector(daddr, scsi_debug_sector_size);
Martin K. Petersen395cef02009-09-18 17:33:03 -04002753 goto out;
2754 }
2755
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002756 sector++;
Martin K. Petersen395cef02009-09-18 17:33:03 -04002757 ei_lba++;
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002758 dpage_offset += scsi_debug_sector_size;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002759 }
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002760 diter.consumed = dpage_offset;
2761 sg_miter_stop(&diter);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002762 }
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002763 sg_miter_stop(&piter);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002764
Akinobu Mita65f72f2a2013-09-18 21:27:26 +09002765 dif_copy_prot(SCpnt, start_sec, sectors, false);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002766 dix_writes++;
2767
2768 return 0;
2769
2770out:
2771 dif_errors++;
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002772 sg_miter_stop(&diter);
2773 sg_miter_stop(&piter);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002774 return ret;
2775}
2776
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002777static unsigned long lba_to_map_index(sector_t lba)
2778{
2779 if (scsi_debug_unmap_alignment) {
2780 lba += scsi_debug_unmap_granularity -
2781 scsi_debug_unmap_alignment;
2782 }
2783 do_div(lba, scsi_debug_unmap_granularity);
2784
2785 return lba;
2786}
2787
2788static sector_t map_index_to_lba(unsigned long index)
2789{
Akinobu Mitaa027b5b2013-08-26 22:08:41 +09002790 sector_t lba = index * scsi_debug_unmap_granularity;
2791
2792 if (scsi_debug_unmap_alignment) {
2793 lba -= scsi_debug_unmap_granularity -
2794 scsi_debug_unmap_alignment;
2795 }
2796
2797 return lba;
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002798}
2799
Martin K. Petersen44d92692009-10-15 14:45:27 -04002800static unsigned int map_state(sector_t lba, unsigned int *num)
2801{
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002802 sector_t end;
2803 unsigned int mapped;
2804 unsigned long index;
2805 unsigned long next;
Martin K. Petersen44d92692009-10-15 14:45:27 -04002806
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002807 index = lba_to_map_index(lba);
2808 mapped = test_bit(index, map_storep);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002809
2810 if (mapped)
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002811 next = find_next_zero_bit(map_storep, map_size, index);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002812 else
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002813 next = find_next_bit(map_storep, map_size, index);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002814
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002815 end = min_t(sector_t, sdebug_store_sectors, map_index_to_lba(next));
Martin K. Petersen44d92692009-10-15 14:45:27 -04002816 *num = end - lba;
2817
2818 return mapped;
2819}
2820
2821static void map_region(sector_t lba, unsigned int len)
2822{
Martin K. Petersen44d92692009-10-15 14:45:27 -04002823 sector_t end = lba + len;
2824
Martin K. Petersen44d92692009-10-15 14:45:27 -04002825 while (lba < end) {
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002826 unsigned long index = lba_to_map_index(lba);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002827
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002828 if (index < map_size)
2829 set_bit(index, map_storep);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002830
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002831 lba = map_index_to_lba(index + 1);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002832 }
2833}
2834
2835static void unmap_region(sector_t lba, unsigned int len)
2836{
Martin K. Petersen44d92692009-10-15 14:45:27 -04002837 sector_t end = lba + len;
2838
Martin K. Petersen44d92692009-10-15 14:45:27 -04002839 while (lba < end) {
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002840 unsigned long index = lba_to_map_index(lba);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002841
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002842 if (lba == map_index_to_lba(index) &&
2843 lba + scsi_debug_unmap_granularity <= end &&
2844 index < map_size) {
2845 clear_bit(index, map_storep);
2846 if (scsi_debug_lbprz) {
Eric Sandeenbe1dd782012-03-08 00:03:59 -06002847 memset(fake_storep +
Akinobu Mitacc34a8e2013-04-16 22:11:57 +09002848 lba * scsi_debug_sector_size, 0,
2849 scsi_debug_sector_size *
2850 scsi_debug_unmap_granularity);
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002851 }
Akinobu Mitae9926b42013-06-29 17:59:17 +09002852 if (dif_storep) {
2853 memset(dif_storep + lba, 0xff,
2854 sizeof(*dif_storep) *
2855 scsi_debug_unmap_granularity);
2856 }
Eric Sandeenbe1dd782012-03-08 00:03:59 -06002857 }
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002858 lba = map_index_to_lba(index + 1);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002859 }
2860}
2861
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002862static int
2863resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002864{
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002865 u8 *cmd = scp->cmnd;
2866 u64 lba;
2867 u32 num;
2868 u32 ei_lba;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002869 unsigned long iflags;
FUJITA Tomonori19789102008-03-30 00:59:56 +09002870 int ret;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002871 bool check_prot;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002872
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002873 switch (cmd[0]) {
2874 case WRITE_16:
2875 ei_lba = 0;
2876 lba = get_unaligned_be64(cmd + 2);
2877 num = get_unaligned_be32(cmd + 10);
2878 check_prot = true;
2879 break;
2880 case WRITE_10:
2881 ei_lba = 0;
2882 lba = get_unaligned_be32(cmd + 2);
2883 num = get_unaligned_be16(cmd + 7);
2884 check_prot = true;
2885 break;
2886 case WRITE_6:
2887 ei_lba = 0;
2888 lba = (u32)cmd[3] | (u32)cmd[2] << 8 |
2889 (u32)(cmd[1] & 0x1f) << 16;
2890 num = (0 == cmd[4]) ? 256 : cmd[4];
2891 check_prot = true;
2892 break;
2893 case WRITE_12:
2894 ei_lba = 0;
2895 lba = get_unaligned_be32(cmd + 2);
2896 num = get_unaligned_be32(cmd + 6);
2897 check_prot = true;
2898 break;
2899 case 0x53: /* XDWRITEREAD(10) */
2900 ei_lba = 0;
2901 lba = get_unaligned_be32(cmd + 2);
2902 num = get_unaligned_be16(cmd + 7);
2903 check_prot = false;
2904 break;
2905 default: /* assume WRITE(32) */
2906 lba = get_unaligned_be64(cmd + 12);
2907 ei_lba = get_unaligned_be32(cmd + 20);
2908 num = get_unaligned_be32(cmd + 28);
2909 check_prot = false;
2910 break;
2911 }
2912 if (check_prot) {
2913 if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
2914 (cmd[1] & 0xe0)) {
2915 mk_sense_invalid_opcode(scp);
2916 return check_condition_result;
2917 }
2918 if ((scsi_debug_dif == SD_DIF_TYPE1_PROTECTION ||
2919 scsi_debug_dif == SD_DIF_TYPE3_PROTECTION) &&
2920 (cmd[1] & 0xe0) == 0)
2921 sdev_printk(KERN_ERR, scp->device, "Unprotected WR "
2922 "to DIF device\n");
2923 }
2924
2925 /* inline check_device_access_params() */
2926 if (lba + num > sdebug_capacity) {
2927 mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0);
2928 return check_condition_result;
2929 }
2930 /* transfer length excessive (tie in to block limits VPD page) */
2931 if (num > sdebug_store_sectors) {
2932 /* needs work to find which cdb byte 'num' comes from */
2933 mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0);
2934 return check_condition_result;
2935 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002936
Akinobu Mita6c78cc02014-02-26 22:57:03 +09002937 write_lock_irqsave(&atomic_rw, iflags);
2938
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002939 /* DIX + T10 DIF */
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002940 if (scsi_debug_dix && scsi_prot_sg_count(scp)) {
2941 int prot_ret = prot_verify_write(scp, lba, num, ei_lba);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002942
2943 if (prot_ret) {
Akinobu Mita6c78cc02014-02-26 22:57:03 +09002944 write_unlock_irqrestore(&atomic_rw, iflags);
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002945 mk_sense_buffer(scp, ILLEGAL_REQUEST, 0x10, prot_ret);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002946 return illegal_condition_result;
2947 }
2948 }
2949
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002950 ret = do_device_access(scp, lba, num, true);
Akinobu Mita9ed8d3d2013-04-16 22:11:55 +09002951 if (scsi_debug_lbp())
Martin K. Petersen44d92692009-10-15 14:45:27 -04002952 map_region(lba, num);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002953 write_unlock_irqrestore(&atomic_rw, iflags);
FUJITA Tomonori19789102008-03-30 00:59:56 +09002954 if (-1 == ret)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002955 return (DID_ERROR << 16);
Martin K. Petersen597136a2008-06-05 00:12:59 -04002956 else if ((ret < (num * scsi_debug_sector_size)) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07002957 (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002958 sdev_printk(KERN_INFO, scp->device,
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002959 "%s: write: cdb indicated=%u, IO sent=%d bytes\n",
2960 my_name, num * scsi_debug_sector_size, ret);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002961
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002962 if (sdebug_any_injecting_opt) {
2963 struct sdebug_scmd_extra_t *ep = scsi_cmd_priv(scp);
2964
2965 if (ep->inj_recovered) {
2966 mk_sense_buffer(scp, RECOVERED_ERROR,
2967 THRESHOLD_EXCEEDED, 0);
2968 return check_condition_result;
2969 } else if (ep->inj_dif) {
2970 /* Logical block guard check failed */
2971 mk_sense_buffer(scp, ABORTED_COMMAND, 0x10, 1);
2972 return illegal_condition_result;
2973 } else if (ep->inj_dix) {
2974 mk_sense_buffer(scp, ILLEGAL_REQUEST, 0x10, 1);
2975 return illegal_condition_result;
2976 }
2977 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002978 return 0;
2979}
2980
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002981static int
2982resp_write_same(struct scsi_cmnd *scp, u64 lba, u32 num, u32 ei_lba,
2983 bool unmap, bool ndob)
Martin K. Petersen44d92692009-10-15 14:45:27 -04002984{
2985 unsigned long iflags;
2986 unsigned long long i;
2987 int ret;
2988
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002989 ret = check_device_access_params(scp, lba, num);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002990 if (ret)
2991 return ret;
2992
2993 write_lock_irqsave(&atomic_rw, iflags);
2994
Akinobu Mita9ed8d3d2013-04-16 22:11:55 +09002995 if (unmap && scsi_debug_lbp()) {
Martin K. Petersen44d92692009-10-15 14:45:27 -04002996 unmap_region(lba, num);
2997 goto out;
2998 }
2999
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003000 /* if ndob then zero 1 logical block, else fetch 1 logical block */
3001 if (ndob) {
3002 memset(fake_storep + (lba * scsi_debug_sector_size), 0,
3003 scsi_debug_sector_size);
3004 ret = 0;
3005 } else
3006 ret = fetch_to_dev_buffer(scp, fake_storep +
3007 (lba * scsi_debug_sector_size),
3008 scsi_debug_sector_size);
Martin K. Petersen44d92692009-10-15 14:45:27 -04003009
3010 if (-1 == ret) {
3011 write_unlock_irqrestore(&atomic_rw, iflags);
3012 return (DID_ERROR << 16);
3013 } else if ((ret < (num * scsi_debug_sector_size)) &&
3014 (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003015 sdev_printk(KERN_INFO, scp->device,
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003016 "%s: %s: cdb indicated=%u, IO sent=%d bytes\n",
3017 my_name, "write same",
3018 num * scsi_debug_sector_size, ret);
Martin K. Petersen44d92692009-10-15 14:45:27 -04003019
3020 /* Copy first sector to remaining blocks */
3021 for (i = 1 ; i < num ; i++)
3022 memcpy(fake_storep + ((lba + i) * scsi_debug_sector_size),
3023 fake_storep + (lba * scsi_debug_sector_size),
3024 scsi_debug_sector_size);
3025
Akinobu Mita9ed8d3d2013-04-16 22:11:55 +09003026 if (scsi_debug_lbp())
Martin K. Petersen44d92692009-10-15 14:45:27 -04003027 map_region(lba, num);
3028out:
3029 write_unlock_irqrestore(&atomic_rw, iflags);
3030
3031 return 0;
3032}
3033
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003034static int
3035resp_write_same_10(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
3036{
3037 u8 *cmd = scp->cmnd;
3038 u32 lba;
3039 u16 num;
3040 u32 ei_lba = 0;
3041 bool unmap = false;
3042
3043 if (cmd[1] & 0x8) {
3044 if (scsi_debug_lbpws10 == 0) {
3045 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 1, 3);
3046 return check_condition_result;
3047 } else
3048 unmap = true;
3049 }
3050 lba = get_unaligned_be32(cmd + 2);
3051 num = get_unaligned_be16(cmd + 7);
3052 if (num > scsi_debug_write_same_length) {
3053 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 7, -1);
3054 return check_condition_result;
3055 }
3056 return resp_write_same(scp, lba, num, ei_lba, unmap, false);
3057}
3058
3059static int
3060resp_write_same_16(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
3061{
3062 u8 *cmd = scp->cmnd;
3063 u64 lba;
3064 u32 num;
3065 u32 ei_lba = 0;
3066 bool unmap = false;
3067 bool ndob = false;
3068
3069 if (cmd[1] & 0x8) { /* UNMAP */
3070 if (scsi_debug_lbpws == 0) {
3071 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 1, 3);
3072 return check_condition_result;
3073 } else
3074 unmap = true;
3075 }
3076 if (cmd[1] & 0x1) /* NDOB (no data-out buffer, assumes zeroes) */
3077 ndob = true;
3078 lba = get_unaligned_be64(cmd + 2);
3079 num = get_unaligned_be32(cmd + 10);
3080 if (num > scsi_debug_write_same_length) {
3081 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 10, -1);
3082 return check_condition_result;
3083 }
3084 return resp_write_same(scp, lba, num, ei_lba, unmap, ndob);
3085}
3086
Ewan D. Milneacafd0b2014-12-04 11:49:28 -05003087/* Note the mode field is in the same position as the (lower) service action
3088 * field. For the Report supported operation codes command, SPC-4 suggests
3089 * each mode of this command should be reported separately; for future. */
3090static int
3091resp_write_buffer(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
3092{
3093 u8 *cmd = scp->cmnd;
3094 struct scsi_device *sdp = scp->device;
3095 struct sdebug_dev_info *dp;
3096 u8 mode;
3097
3098 mode = cmd[1] & 0x1f;
3099 switch (mode) {
3100 case 0x4: /* download microcode (MC) and activate (ACT) */
3101 /* set UAs on this device only */
3102 set_bit(SDEBUG_UA_BUS_RESET, devip->uas_bm);
3103 set_bit(SDEBUG_UA_MICROCODE_CHANGED, devip->uas_bm);
3104 break;
3105 case 0x5: /* download MC, save and ACT */
3106 set_bit(SDEBUG_UA_MICROCODE_CHANGED_WO_RESET, devip->uas_bm);
3107 break;
3108 case 0x6: /* download MC with offsets and ACT */
3109 /* set UAs on most devices (LUs) in this target */
3110 list_for_each_entry(dp,
3111 &devip->sdbg_host->dev_info_list,
3112 dev_list)
3113 if (dp->target == sdp->id) {
3114 set_bit(SDEBUG_UA_BUS_RESET, dp->uas_bm);
3115 if (devip != dp)
3116 set_bit(SDEBUG_UA_MICROCODE_CHANGED,
3117 dp->uas_bm);
3118 }
3119 break;
3120 case 0x7: /* download MC with offsets, save, and ACT */
3121 /* set UA on all devices (LUs) in this target */
3122 list_for_each_entry(dp,
3123 &devip->sdbg_host->dev_info_list,
3124 dev_list)
3125 if (dp->target == sdp->id)
3126 set_bit(SDEBUG_UA_MICROCODE_CHANGED_WO_RESET,
3127 dp->uas_bm);
3128 break;
3129 default:
3130 /* do nothing for this command for other mode values */
3131 break;
3132 }
3133 return 0;
3134}
3135
Douglas Gilbert38d5c832014-11-24 21:27:12 -05003136static int
3137resp_comp_write(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
3138{
3139 u8 *cmd = scp->cmnd;
3140 u8 *arr;
3141 u8 *fake_storep_hold;
3142 u64 lba;
3143 u32 dnum;
3144 u32 lb_size = scsi_debug_sector_size;
3145 u8 num;
3146 unsigned long iflags;
3147 int ret;
Douglas Gilbertd467d312014-11-26 12:33:48 -05003148 int retval = 0;
Douglas Gilbert38d5c832014-11-24 21:27:12 -05003149
Douglas Gilbertd467d312014-11-26 12:33:48 -05003150 lba = get_unaligned_be64(cmd + 2);
Douglas Gilbert38d5c832014-11-24 21:27:12 -05003151 num = cmd[13]; /* 1 to a maximum of 255 logical blocks */
3152 if (0 == num)
3153 return 0; /* degenerate case, not an error */
Douglas Gilbert38d5c832014-11-24 21:27:12 -05003154 if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
3155 (cmd[1] & 0xe0)) {
3156 mk_sense_invalid_opcode(scp);
3157 return check_condition_result;
3158 }
3159 if ((scsi_debug_dif == SD_DIF_TYPE1_PROTECTION ||
3160 scsi_debug_dif == SD_DIF_TYPE3_PROTECTION) &&
3161 (cmd[1] & 0xe0) == 0)
3162 sdev_printk(KERN_ERR, scp->device, "Unprotected WR "
3163 "to DIF device\n");
3164
3165 /* inline check_device_access_params() */
3166 if (lba + num > sdebug_capacity) {
3167 mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0);
3168 return check_condition_result;
3169 }
3170 /* transfer length excessive (tie in to block limits VPD page) */
3171 if (num > sdebug_store_sectors) {
3172 /* needs work to find which cdb byte 'num' comes from */
3173 mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0);
3174 return check_condition_result;
3175 }
Douglas Gilbertd467d312014-11-26 12:33:48 -05003176 dnum = 2 * num;
3177 arr = kzalloc(dnum * lb_size, GFP_ATOMIC);
3178 if (NULL == arr) {
3179 mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC,
3180 INSUFF_RES_ASCQ);
3181 return check_condition_result;
3182 }
Douglas Gilbert38d5c832014-11-24 21:27:12 -05003183
3184 write_lock_irqsave(&atomic_rw, iflags);
3185
3186 /* trick do_device_access() to fetch both compare and write buffers
3187 * from data-in into arr. Safe (atomic) since write_lock held. */
3188 fake_storep_hold = fake_storep;
3189 fake_storep = arr;
3190 ret = do_device_access(scp, 0, dnum, true);
3191 fake_storep = fake_storep_hold;
3192 if (ret == -1) {
Douglas Gilbertd467d312014-11-26 12:33:48 -05003193 retval = DID_ERROR << 16;
3194 goto cleanup;
Douglas Gilbert38d5c832014-11-24 21:27:12 -05003195 } else if ((ret < (dnum * lb_size)) &&
3196 (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
3197 sdev_printk(KERN_INFO, scp->device, "%s: compare_write: cdb "
3198 "indicated=%u, IO sent=%d bytes\n", my_name,
3199 dnum * lb_size, ret);
3200 if (!comp_write_worker(lba, num, arr)) {
Douglas Gilbert38d5c832014-11-24 21:27:12 -05003201 mk_sense_buffer(scp, MISCOMPARE, MISCOMPARE_VERIFY_ASC, 0);
Douglas Gilbertd467d312014-11-26 12:33:48 -05003202 retval = check_condition_result;
3203 goto cleanup;
Douglas Gilbert38d5c832014-11-24 21:27:12 -05003204 }
3205 if (scsi_debug_lbp())
3206 map_region(lba, num);
Douglas Gilbertd467d312014-11-26 12:33:48 -05003207cleanup:
Douglas Gilbert38d5c832014-11-24 21:27:12 -05003208 write_unlock_irqrestore(&atomic_rw, iflags);
Douglas Gilbertd467d312014-11-26 12:33:48 -05003209 kfree(arr);
3210 return retval;
Douglas Gilbert38d5c832014-11-24 21:27:12 -05003211}
3212
Martin K. Petersen44d92692009-10-15 14:45:27 -04003213struct unmap_block_desc {
3214 __be64 lba;
3215 __be32 blocks;
3216 __be32 __reserved;
3217};
3218
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003219static int
3220resp_unmap(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
Martin K. Petersen44d92692009-10-15 14:45:27 -04003221{
3222 unsigned char *buf;
3223 struct unmap_block_desc *desc;
3224 unsigned int i, payload_len, descriptors;
3225 int ret;
Akinobu Mita6c78cc02014-02-26 22:57:03 +09003226 unsigned long iflags;
Martin K. Petersen44d92692009-10-15 14:45:27 -04003227
Martin K. Petersen44d92692009-10-15 14:45:27 -04003228
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003229 if (!scsi_debug_lbp())
3230 return 0; /* fib and say its done */
3231 payload_len = get_unaligned_be16(scp->cmnd + 7);
3232 BUG_ON(scsi_bufflen(scp) != payload_len);
Martin K. Petersen44d92692009-10-15 14:45:27 -04003233
3234 descriptors = (payload_len - 8) / 16;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003235 if (descriptors > scsi_debug_unmap_max_desc) {
3236 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 7, -1);
Martin K. Petersen44d92692009-10-15 14:45:27 -04003237 return check_condition_result;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003238 }
Martin K. Petersen44d92692009-10-15 14:45:27 -04003239
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003240 buf = kmalloc(scsi_bufflen(scp), GFP_ATOMIC);
3241 if (!buf) {
3242 mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC,
3243 INSUFF_RES_ASCQ);
3244 return check_condition_result;
3245 }
3246
3247 scsi_sg_copy_to_buffer(scp, buf, scsi_bufflen(scp));
Martin K. Petersen44d92692009-10-15 14:45:27 -04003248
3249 BUG_ON(get_unaligned_be16(&buf[0]) != payload_len - 2);
3250 BUG_ON(get_unaligned_be16(&buf[2]) != descriptors * 16);
3251
3252 desc = (void *)&buf[8];
3253
Akinobu Mita6c78cc02014-02-26 22:57:03 +09003254 write_lock_irqsave(&atomic_rw, iflags);
3255
Martin K. Petersen44d92692009-10-15 14:45:27 -04003256 for (i = 0 ; i < descriptors ; i++) {
3257 unsigned long long lba = get_unaligned_be64(&desc[i].lba);
3258 unsigned int num = get_unaligned_be32(&desc[i].blocks);
3259
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003260 ret = check_device_access_params(scp, lba, num);
Martin K. Petersen44d92692009-10-15 14:45:27 -04003261 if (ret)
3262 goto out;
3263
3264 unmap_region(lba, num);
3265 }
3266
3267 ret = 0;
3268
3269out:
Akinobu Mita6c78cc02014-02-26 22:57:03 +09003270 write_unlock_irqrestore(&atomic_rw, iflags);
Martin K. Petersen44d92692009-10-15 14:45:27 -04003271 kfree(buf);
3272
3273 return ret;
3274}
3275
3276#define SDEBUG_GET_LBA_STATUS_LEN 32
3277
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003278static int
3279resp_get_lba_status(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
Martin K. Petersen44d92692009-10-15 14:45:27 -04003280{
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003281 u8 *cmd = scp->cmnd;
3282 u64 lba;
3283 u32 alloc_len, mapped, num;
3284 u8 arr[SDEBUG_GET_LBA_STATUS_LEN];
Martin K. Petersen44d92692009-10-15 14:45:27 -04003285 int ret;
3286
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003287 lba = get_unaligned_be64(cmd + 2);
3288 alloc_len = get_unaligned_be32(cmd + 10);
Martin K. Petersen44d92692009-10-15 14:45:27 -04003289
3290 if (alloc_len < 24)
3291 return 0;
3292
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003293 ret = check_device_access_params(scp, lba, 1);
Martin K. Petersen44d92692009-10-15 14:45:27 -04003294 if (ret)
3295 return ret;
3296
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003297 if (scsi_debug_lbp())
3298 mapped = map_state(lba, &num);
3299 else {
3300 mapped = 1;
3301 /* following just in case virtual_gb changed */
3302 sdebug_capacity = get_sdebug_capacity();
3303 if (sdebug_capacity - lba <= 0xffffffff)
3304 num = sdebug_capacity - lba;
3305 else
3306 num = 0xffffffff;
3307 }
Martin K. Petersen44d92692009-10-15 14:45:27 -04003308
3309 memset(arr, 0, SDEBUG_GET_LBA_STATUS_LEN);
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003310 put_unaligned_be32(20, arr); /* Parameter Data Length */
3311 put_unaligned_be64(lba, arr + 8); /* LBA */
3312 put_unaligned_be32(num, arr + 16); /* Number of blocks */
3313 arr[20] = !mapped; /* prov_stat=0: mapped; 1: dealloc */
Martin K. Petersen44d92692009-10-15 14:45:27 -04003314
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003315 return fill_from_dev_buffer(scp, arr, SDEBUG_GET_LBA_STATUS_LEN);
Martin K. Petersen44d92692009-10-15 14:45:27 -04003316}
3317
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003318#define SDEBUG_RLUN_ARR_SZ 256
Linus Torvalds1da177e2005-04-16 15:20:36 -07003319
3320static int resp_report_luns(struct scsi_cmnd * scp,
3321 struct sdebug_dev_info * devip)
3322{
3323 unsigned int alloc_len;
Douglas Gilbert22017ed2014-11-24 23:04:47 -05003324 int lun_cnt, i, upper, num, n, want_wlun, shortish;
3325 u64 lun;
Douglas Gilbert01123ef2014-08-05 12:20:02 +02003326 unsigned char *cmd = scp->cmnd;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003327 int select_report = (int)cmd[2];
3328 struct scsi_lun *one_lun;
3329 unsigned char arr[SDEBUG_RLUN_ARR_SZ];
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003330 unsigned char * max_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003331
Ewan D. Milne19c8ead2014-12-04 11:49:27 -05003332 clear_luns_changed_on_target(devip);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003333 alloc_len = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24);
Douglas Gilbert22017ed2014-11-24 23:04:47 -05003334 shortish = (alloc_len < 4);
3335 if (shortish || (select_report > 2)) {
3336 mk_sense_invalid_fld(scp, SDEB_IN_CDB, shortish ? 6 : 2, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003337 return check_condition_result;
3338 }
3339 /* can produce response with up to 16k luns (lun 0 to lun 16383) */
3340 memset(arr, 0, SDEBUG_RLUN_ARR_SZ);
3341 lun_cnt = scsi_debug_max_luns;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003342 if (1 == select_report)
3343 lun_cnt = 0;
3344 else if (scsi_debug_no_lun_0 && (lun_cnt > 0))
3345 --lun_cnt;
Douglas Gilbert22017ed2014-11-24 23:04:47 -05003346 want_wlun = (select_report > 0) ? 1 : 0;
3347 num = lun_cnt + want_wlun;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003348 arr[2] = ((sizeof(struct scsi_lun) * num) >> 8) & 0xff;
3349 arr[3] = (sizeof(struct scsi_lun) * num) & 0xff;
3350 n = min((int)((SDEBUG_RLUN_ARR_SZ - 8) /
3351 sizeof(struct scsi_lun)), num);
3352 if (n < num) {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05003353 want_wlun = 0;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003354 lun_cnt = n;
3355 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003356 one_lun = (struct scsi_lun *) &arr[8];
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003357 max_addr = arr + SDEBUG_RLUN_ARR_SZ;
3358 for (i = 0, lun = (scsi_debug_no_lun_0 ? 1 : 0);
3359 ((i < lun_cnt) && ((unsigned char *)(one_lun + i) < max_addr));
3360 i++, lun++) {
3361 upper = (lun >> 8) & 0x3f;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003362 if (upper)
3363 one_lun[i].scsi_lun[0] =
3364 (upper | (SAM2_LUN_ADDRESS_METHOD << 6));
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003365 one_lun[i].scsi_lun[1] = lun & 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003366 }
Douglas Gilbert22017ed2014-11-24 23:04:47 -05003367 if (want_wlun) {
Tomas Winkler34d55432015-07-28 16:54:21 +03003368 one_lun[i].scsi_lun[0] = (SCSI_W_LUN_REPORT_LUNS >> 8) & 0xff;
3369 one_lun[i].scsi_lun[1] = SCSI_W_LUN_REPORT_LUNS & 0xff;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003370 i++;
3371 }
3372 alloc_len = (unsigned char *)(one_lun + i) - arr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003373 return fill_from_dev_buffer(scp, arr,
3374 min((int)alloc_len, SDEBUG_RLUN_ARR_SZ));
3375}
3376
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003377static int resp_xdwriteread(struct scsi_cmnd *scp, unsigned long long lba,
3378 unsigned int num, struct sdebug_dev_info *devip)
3379{
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09003380 int j;
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003381 unsigned char *kaddr, *buf;
3382 unsigned int offset;
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003383 struct scsi_data_buffer *sdb = scsi_in(scp);
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09003384 struct sg_mapping_iter miter;
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003385
3386 /* better not to use temporary buffer. */
3387 buf = kmalloc(scsi_bufflen(scp), GFP_ATOMIC);
Akinobu Mitac5af0db2014-02-26 22:57:01 +09003388 if (!buf) {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05003389 mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC,
3390 INSUFF_RES_ASCQ);
Akinobu Mitac5af0db2014-02-26 22:57:01 +09003391 return check_condition_result;
3392 }
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003393
FUJITA Tomonori21a61822008-03-09 13:44:30 +09003394 scsi_sg_copy_to_buffer(scp, buf, scsi_bufflen(scp));
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003395
3396 offset = 0;
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09003397 sg_miter_start(&miter, sdb->table.sgl, sdb->table.nents,
3398 SG_MITER_ATOMIC | SG_MITER_TO_SG);
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003399
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09003400 while (sg_miter_next(&miter)) {
3401 kaddr = miter.addr;
3402 for (j = 0; j < miter.length; j++)
3403 *(kaddr + j) ^= *(buf + offset + j);
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003404
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09003405 offset += miter.length;
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003406 }
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09003407 sg_miter_stop(&miter);
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003408 kfree(buf);
3409
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09003410 return 0;
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003411}
3412
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003413static int
3414resp_xdwriteread_10(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
3415{
3416 u8 *cmd = scp->cmnd;
3417 u64 lba;
3418 u32 num;
3419 int errsts;
3420
3421 if (!scsi_bidi_cmnd(scp)) {
3422 mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC,
3423 INSUFF_RES_ASCQ);
3424 return check_condition_result;
3425 }
3426 errsts = resp_read_dt0(scp, devip);
3427 if (errsts)
3428 return errsts;
3429 if (!(cmd[1] & 0x4)) { /* DISABLE_WRITE is not set */
3430 errsts = resp_write_dt0(scp, devip);
3431 if (errsts)
3432 return errsts;
3433 }
3434 lba = get_unaligned_be32(cmd + 2);
3435 num = get_unaligned_be16(cmd + 7);
3436 return resp_xdwriteread(scp, lba, num, devip);
3437}
3438
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003439/* When timer or tasklet goes off this function is called. */
3440static void sdebug_q_cmd_complete(unsigned long indx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003441{
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003442 int qa_indx;
3443 int retiring = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003444 unsigned long iflags;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003445 struct sdebug_queued_cmd *sqcp;
3446 struct scsi_cmnd *scp;
3447 struct sdebug_dev_info *devip;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003448
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003449 atomic_inc(&sdebug_completions);
3450 qa_indx = indx;
3451 if ((qa_indx < 0) || (qa_indx >= SCSI_DEBUG_CANQUEUE)) {
Tomas Winklerc12879702015-07-28 16:54:20 +03003452 pr_err("wild qa_indx=%d\n", qa_indx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003453 return;
3454 }
3455 spin_lock_irqsave(&queued_arr_lock, iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003456 sqcp = &queued_arr[qa_indx];
3457 scp = sqcp->a_cmnd;
3458 if (NULL == scp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003459 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Tomas Winklerc12879702015-07-28 16:54:20 +03003460 pr_err("scp is NULL\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003461 return;
3462 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003463 devip = (struct sdebug_dev_info *)scp->device->hostdata;
3464 if (devip)
3465 atomic_dec(&devip->num_in_q);
3466 else
Tomas Winklerc12879702015-07-28 16:54:20 +03003467 pr_err("devip=NULL\n");
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003468 if (atomic_read(&retired_max_queue) > 0)
3469 retiring = 1;
3470
3471 sqcp->a_cmnd = NULL;
3472 if (!test_and_clear_bit(qa_indx, queued_in_use_bm)) {
3473 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Tomas Winklerc12879702015-07-28 16:54:20 +03003474 pr_err("Unexpected completion\n");
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003475 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003476 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003477
3478 if (unlikely(retiring)) { /* user has reduced max_queue */
3479 int k, retval;
3480
3481 retval = atomic_read(&retired_max_queue);
3482 if (qa_indx >= retval) {
3483 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Tomas Winklerc12879702015-07-28 16:54:20 +03003484 pr_err("index %d too large\n", retval);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003485 return;
3486 }
3487 k = find_last_bit(queued_in_use_bm, retval);
3488 if ((k < scsi_debug_max_queue) || (k == retval))
3489 atomic_set(&retired_max_queue, 0);
3490 else
3491 atomic_set(&retired_max_queue, k + 1);
3492 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003493 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003494 scp->scsi_done(scp); /* callback to mid level */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003495}
3496
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003497/* When high resolution timer goes off this function is called. */
3498static enum hrtimer_restart
3499sdebug_q_cmd_hrt_complete(struct hrtimer *timer)
3500{
3501 int qa_indx;
3502 int retiring = 0;
3503 unsigned long iflags;
3504 struct sdebug_hrtimer *sd_hrtp = (struct sdebug_hrtimer *)timer;
3505 struct sdebug_queued_cmd *sqcp;
3506 struct scsi_cmnd *scp;
3507 struct sdebug_dev_info *devip;
3508
3509 atomic_inc(&sdebug_completions);
3510 qa_indx = sd_hrtp->qa_indx;
3511 if ((qa_indx < 0) || (qa_indx >= SCSI_DEBUG_CANQUEUE)) {
Tomas Winklerc12879702015-07-28 16:54:20 +03003512 pr_err("wild qa_indx=%d\n", qa_indx);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003513 goto the_end;
3514 }
3515 spin_lock_irqsave(&queued_arr_lock, iflags);
3516 sqcp = &queued_arr[qa_indx];
3517 scp = sqcp->a_cmnd;
3518 if (NULL == scp) {
3519 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Tomas Winklerc12879702015-07-28 16:54:20 +03003520 pr_err("scp is NULL\n");
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003521 goto the_end;
3522 }
3523 devip = (struct sdebug_dev_info *)scp->device->hostdata;
3524 if (devip)
3525 atomic_dec(&devip->num_in_q);
3526 else
Tomas Winklerc12879702015-07-28 16:54:20 +03003527 pr_err("devip=NULL\n");
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003528 if (atomic_read(&retired_max_queue) > 0)
3529 retiring = 1;
3530
3531 sqcp->a_cmnd = NULL;
3532 if (!test_and_clear_bit(qa_indx, queued_in_use_bm)) {
3533 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Tomas Winklerc12879702015-07-28 16:54:20 +03003534 pr_err("Unexpected completion\n");
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003535 goto the_end;
3536 }
3537
3538 if (unlikely(retiring)) { /* user has reduced max_queue */
3539 int k, retval;
3540
3541 retval = atomic_read(&retired_max_queue);
3542 if (qa_indx >= retval) {
3543 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Tomas Winklerc12879702015-07-28 16:54:20 +03003544 pr_err("index %d too large\n", retval);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003545 goto the_end;
3546 }
3547 k = find_last_bit(queued_in_use_bm, retval);
3548 if ((k < scsi_debug_max_queue) || (k == retval))
3549 atomic_set(&retired_max_queue, 0);
3550 else
3551 atomic_set(&retired_max_queue, k + 1);
3552 }
3553 spin_unlock_irqrestore(&queued_arr_lock, iflags);
3554 scp->scsi_done(scp); /* callback to mid level */
3555the_end:
3556 return HRTIMER_NORESTART;
3557}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003558
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003559static struct sdebug_dev_info *
3560sdebug_device_create(struct sdebug_host_info *sdbg_host, gfp_t flags)
FUJITA Tomonori5cb2fc02008-03-20 11:09:16 +09003561{
3562 struct sdebug_dev_info *devip;
3563
3564 devip = kzalloc(sizeof(*devip), flags);
3565 if (devip) {
3566 devip->sdbg_host = sdbg_host;
3567 list_add_tail(&devip->dev_list, &sdbg_host->dev_info_list);
3568 }
3569 return devip;
3570}
3571
Linus Torvalds1da177e2005-04-16 15:20:36 -07003572static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev)
3573{
3574 struct sdebug_host_info * sdbg_host;
3575 struct sdebug_dev_info * open_devip = NULL;
3576 struct sdebug_dev_info * devip =
3577 (struct sdebug_dev_info *)sdev->hostdata;
3578
3579 if (devip)
3580 return devip;
FUJITA Tomonorid1e4c9c2008-03-02 18:30:18 +09003581 sdbg_host = *(struct sdebug_host_info **)shost_priv(sdev->host);
3582 if (!sdbg_host) {
Tomas Winklerc12879702015-07-28 16:54:20 +03003583 pr_err("Host info NULL\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003584 return NULL;
3585 }
3586 list_for_each_entry(devip, &sdbg_host->dev_info_list, dev_list) {
3587 if ((devip->used) && (devip->channel == sdev->channel) &&
3588 (devip->target == sdev->id) &&
3589 (devip->lun == sdev->lun))
3590 return devip;
3591 else {
3592 if ((!devip->used) && (!open_devip))
3593 open_devip = devip;
3594 }
3595 }
FUJITA Tomonori5cb2fc02008-03-20 11:09:16 +09003596 if (!open_devip) { /* try and make a new one */
3597 open_devip = sdebug_device_create(sdbg_host, GFP_ATOMIC);
3598 if (!open_devip) {
Tomas Winklerc12879702015-07-28 16:54:20 +03003599 pr_err("out of memory at line %d\n", __LINE__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003600 return NULL;
3601 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003602 }
FUJITA Tomonoria75869d2008-03-20 11:09:17 +09003603
3604 open_devip->channel = sdev->channel;
3605 open_devip->target = sdev->id;
3606 open_devip->lun = sdev->lun;
3607 open_devip->sdbg_host = sdbg_host;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003608 atomic_set(&open_devip->num_in_q, 0);
3609 set_bit(SDEBUG_UA_POR, open_devip->uas_bm);
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003610 open_devip->used = true;
FUJITA Tomonoria75869d2008-03-20 11:09:17 +09003611 return open_devip;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003612}
3613
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003614static int scsi_debug_slave_alloc(struct scsi_device *sdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003615{
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003616 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
Tomas Winklerc12879702015-07-28 16:54:20 +03003617 pr_info("slave_alloc <%u %u %u %llu>\n",
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003618 sdp->host->host_no, sdp->channel, sdp->id, sdp->lun);
Nick Piggin75ad23b2008-04-29 14:48:33 +02003619 queue_flag_set_unlocked(QUEUE_FLAG_BIDI, sdp->request_queue);
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003620 return 0;
3621}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003622
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003623static int scsi_debug_slave_configure(struct scsi_device *sdp)
3624{
3625 struct sdebug_dev_info *devip;
FUJITA Tomonoria34c4e92008-03-25 09:26:50 +09003626
Linus Torvalds1da177e2005-04-16 15:20:36 -07003627 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
Tomas Winklerc12879702015-07-28 16:54:20 +03003628 pr_info("slave_configure <%u %u %u %llu>\n",
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003629 sdp->host->host_no, sdp->channel, sdp->id, sdp->lun);
3630 if (sdp->host->max_cmd_len != SCSI_DEBUG_MAX_CMD_LEN)
3631 sdp->host->max_cmd_len = SCSI_DEBUG_MAX_CMD_LEN;
3632 devip = devInfoReg(sdp);
3633 if (NULL == devip)
3634 return 1; /* no resources, will be marked offline */
Christoph Hellwigc8b09f62014-11-03 20:15:14 +01003635 sdp->hostdata = devip;
Akinobu Mita6bb5e6e2014-06-02 22:56:49 +09003636 blk_queue_max_segment_size(sdp->request_queue, -1U);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04003637 if (scsi_debug_no_uld)
3638 sdp->no_uld_attach = 1;
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003639 return 0;
3640}
3641
3642static void scsi_debug_slave_destroy(struct scsi_device *sdp)
3643{
3644 struct sdebug_dev_info *devip =
3645 (struct sdebug_dev_info *)sdp->hostdata;
3646
3647 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
Tomas Winklerc12879702015-07-28 16:54:20 +03003648 pr_info("slave_destroy <%u %u %u %llu>\n",
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003649 sdp->host->host_no, sdp->channel, sdp->id, sdp->lun);
3650 if (devip) {
Lucas De Marchi25985ed2011-03-30 22:57:33 -03003651 /* make this slot available for re-use */
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003652 devip->used = false;
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003653 sdp->hostdata = NULL;
3654 }
3655}
3656
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003657/* Returns 1 if cmnd found (deletes its timer or tasklet), else returns 0 */
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003658static int stop_queued_cmnd(struct scsi_cmnd *cmnd)
3659{
3660 unsigned long iflags;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003661 int k, qmax, r_qmax;
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003662 struct sdebug_queued_cmd *sqcp;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003663 struct sdebug_dev_info *devip;
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003664
3665 spin_lock_irqsave(&queued_arr_lock, iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003666 qmax = scsi_debug_max_queue;
3667 r_qmax = atomic_read(&retired_max_queue);
3668 if (r_qmax > qmax)
3669 qmax = r_qmax;
3670 for (k = 0; k < qmax; ++k) {
3671 if (test_bit(k, queued_in_use_bm)) {
3672 sqcp = &queued_arr[k];
3673 if (cmnd == sqcp->a_cmnd) {
Douglas Gilbertdb525fc2014-08-31 19:09:59 -04003674 devip = (struct sdebug_dev_info *)
3675 cmnd->device->hostdata;
3676 if (devip)
3677 atomic_dec(&devip->num_in_q);
3678 sqcp->a_cmnd = NULL;
3679 spin_unlock_irqrestore(&queued_arr_lock,
3680 iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003681 if (scsi_debug_ndelay > 0) {
3682 if (sqcp->sd_hrtp)
3683 hrtimer_cancel(
3684 &sqcp->sd_hrtp->hrt);
3685 } else if (scsi_debug_delay > 0) {
3686 if (sqcp->cmnd_timerp)
3687 del_timer_sync(
3688 sqcp->cmnd_timerp);
3689 } else if (scsi_debug_delay < 0) {
3690 if (sqcp->tletp)
3691 tasklet_kill(sqcp->tletp);
3692 }
Douglas Gilbertdb525fc2014-08-31 19:09:59 -04003693 clear_bit(k, queued_in_use_bm);
3694 return 1;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003695 }
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003696 }
3697 }
3698 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Douglas Gilbertdb525fc2014-08-31 19:09:59 -04003699 return 0;
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003700}
3701
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003702/* Deletes (stops) timers or tasklets of all queued commands */
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003703static void stop_all_queued(void)
3704{
3705 unsigned long iflags;
3706 int k;
3707 struct sdebug_queued_cmd *sqcp;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003708 struct sdebug_dev_info *devip;
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003709
3710 spin_lock_irqsave(&queued_arr_lock, iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003711 for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) {
3712 if (test_bit(k, queued_in_use_bm)) {
3713 sqcp = &queued_arr[k];
3714 if (sqcp->a_cmnd) {
Douglas Gilbertdb525fc2014-08-31 19:09:59 -04003715 devip = (struct sdebug_dev_info *)
3716 sqcp->a_cmnd->device->hostdata;
3717 if (devip)
3718 atomic_dec(&devip->num_in_q);
3719 sqcp->a_cmnd = NULL;
3720 spin_unlock_irqrestore(&queued_arr_lock,
3721 iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003722 if (scsi_debug_ndelay > 0) {
3723 if (sqcp->sd_hrtp)
3724 hrtimer_cancel(
3725 &sqcp->sd_hrtp->hrt);
3726 } else if (scsi_debug_delay > 0) {
3727 if (sqcp->cmnd_timerp)
3728 del_timer_sync(
3729 sqcp->cmnd_timerp);
3730 } else if (scsi_debug_delay < 0) {
3731 if (sqcp->tletp)
3732 tasklet_kill(sqcp->tletp);
3733 }
Douglas Gilbertdb525fc2014-08-31 19:09:59 -04003734 clear_bit(k, queued_in_use_bm);
3735 spin_lock_irqsave(&queued_arr_lock, iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003736 }
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003737 }
3738 }
3739 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003740}
3741
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003742/* Free queued command memory on heap */
3743static void free_all_queued(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003744{
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003745 unsigned long iflags;
3746 int k;
3747 struct sdebug_queued_cmd *sqcp;
3748
3749 spin_lock_irqsave(&queued_arr_lock, iflags);
3750 for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) {
3751 sqcp = &queued_arr[k];
3752 kfree(sqcp->cmnd_timerp);
3753 sqcp->cmnd_timerp = NULL;
3754 kfree(sqcp->tletp);
3755 sqcp->tletp = NULL;
3756 kfree(sqcp->sd_hrtp);
3757 sqcp->sd_hrtp = NULL;
3758 }
3759 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003760}
3761
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003762static int scsi_debug_abort(struct scsi_cmnd *SCpnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003763{
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003764 ++num_aborts;
3765 if (SCpnt) {
3766 if (SCpnt->device &&
3767 (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts))
3768 sdev_printk(KERN_INFO, SCpnt->device, "%s\n",
3769 __func__);
3770 stop_queued_cmnd(SCpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003771 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003772 return SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003773}
3774
3775static int scsi_debug_device_reset(struct scsi_cmnd * SCpnt)
3776{
3777 struct sdebug_dev_info * devip;
3778
Linus Torvalds1da177e2005-04-16 15:20:36 -07003779 ++num_dev_resets;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003780 if (SCpnt && SCpnt->device) {
3781 struct scsi_device *sdp = SCpnt->device;
3782
3783 if (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts)
3784 sdev_printk(KERN_INFO, sdp, "%s\n", __func__);
3785 devip = devInfoReg(sdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003786 if (devip)
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003787 set_bit(SDEBUG_UA_POR, devip->uas_bm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003788 }
3789 return SUCCESS;
3790}
3791
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003792static int scsi_debug_target_reset(struct scsi_cmnd *SCpnt)
3793{
3794 struct sdebug_host_info *sdbg_host;
3795 struct sdebug_dev_info *devip;
3796 struct scsi_device *sdp;
3797 struct Scsi_Host *hp;
3798 int k = 0;
3799
3800 ++num_target_resets;
3801 if (!SCpnt)
3802 goto lie;
3803 sdp = SCpnt->device;
3804 if (!sdp)
3805 goto lie;
3806 if (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts)
3807 sdev_printk(KERN_INFO, sdp, "%s\n", __func__);
3808 hp = sdp->host;
3809 if (!hp)
3810 goto lie;
3811 sdbg_host = *(struct sdebug_host_info **)shost_priv(hp);
3812 if (sdbg_host) {
3813 list_for_each_entry(devip,
3814 &sdbg_host->dev_info_list,
3815 dev_list)
3816 if (devip->target == sdp->id) {
3817 set_bit(SDEBUG_UA_BUS_RESET, devip->uas_bm);
3818 ++k;
3819 }
3820 }
3821 if (SCSI_DEBUG_OPT_RESET_NOISE & scsi_debug_opts)
3822 sdev_printk(KERN_INFO, sdp,
3823 "%s: %d device(s) found in target\n", __func__, k);
3824lie:
3825 return SUCCESS;
3826}
3827
Linus Torvalds1da177e2005-04-16 15:20:36 -07003828static int scsi_debug_bus_reset(struct scsi_cmnd * SCpnt)
3829{
3830 struct sdebug_host_info *sdbg_host;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003831 struct sdebug_dev_info *devip;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003832 struct scsi_device * sdp;
3833 struct Scsi_Host * hp;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003834 int k = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003835
Linus Torvalds1da177e2005-04-16 15:20:36 -07003836 ++num_bus_resets;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003837 if (!(SCpnt && SCpnt->device))
3838 goto lie;
3839 sdp = SCpnt->device;
3840 if (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts)
3841 sdev_printk(KERN_INFO, sdp, "%s\n", __func__);
3842 hp = sdp->host;
3843 if (hp) {
FUJITA Tomonorid1e4c9c2008-03-02 18:30:18 +09003844 sdbg_host = *(struct sdebug_host_info **)shost_priv(hp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003845 if (sdbg_host) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003846 list_for_each_entry(devip,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003847 &sdbg_host->dev_info_list,
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003848 dev_list) {
3849 set_bit(SDEBUG_UA_BUS_RESET, devip->uas_bm);
3850 ++k;
3851 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003852 }
3853 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003854 if (SCSI_DEBUG_OPT_RESET_NOISE & scsi_debug_opts)
3855 sdev_printk(KERN_INFO, sdp,
3856 "%s: %d device(s) found in host\n", __func__, k);
3857lie:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003858 return SUCCESS;
3859}
3860
3861static int scsi_debug_host_reset(struct scsi_cmnd * SCpnt)
3862{
3863 struct sdebug_host_info * sdbg_host;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003864 struct sdebug_dev_info *devip;
3865 int k = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003866
Linus Torvalds1da177e2005-04-16 15:20:36 -07003867 ++num_host_resets;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003868 if ((SCpnt->device) && (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts))
3869 sdev_printk(KERN_INFO, SCpnt->device, "%s\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003870 spin_lock(&sdebug_host_list_lock);
3871 list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003872 list_for_each_entry(devip, &sdbg_host->dev_info_list,
3873 dev_list) {
3874 set_bit(SDEBUG_UA_BUS_RESET, devip->uas_bm);
3875 ++k;
3876 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003877 }
3878 spin_unlock(&sdebug_host_list_lock);
3879 stop_all_queued();
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003880 if (SCSI_DEBUG_OPT_RESET_NOISE & scsi_debug_opts)
3881 sdev_printk(KERN_INFO, SCpnt->device,
3882 "%s: %d device(s) found\n", __func__, k);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003883 return SUCCESS;
3884}
3885
FUJITA Tomonorif58b0ef2008-03-30 00:59:54 +09003886static void __init sdebug_build_parts(unsigned char *ramp,
FUJITA Tomonori5f2578e2008-03-30 00:59:57 +09003887 unsigned long store_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003888{
3889 struct partition * pp;
3890 int starts[SDEBUG_MAX_PARTS + 2];
3891 int sectors_per_part, num_sectors, k;
3892 int heads_by_sects, start_sec, end_sec;
3893
3894 /* assume partition table already zeroed */
FUJITA Tomonorif58b0ef2008-03-30 00:59:54 +09003895 if ((scsi_debug_num_parts < 1) || (store_size < 1048576))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003896 return;
3897 if (scsi_debug_num_parts > SDEBUG_MAX_PARTS) {
3898 scsi_debug_num_parts = SDEBUG_MAX_PARTS;
Tomas Winklerc12879702015-07-28 16:54:20 +03003899 pr_warn("reducing partitions to %d\n", SDEBUG_MAX_PARTS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003900 }
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003901 num_sectors = (int)sdebug_store_sectors;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003902 sectors_per_part = (num_sectors - sdebug_sectors_per)
3903 / scsi_debug_num_parts;
3904 heads_by_sects = sdebug_heads * sdebug_sectors_per;
3905 starts[0] = sdebug_sectors_per;
3906 for (k = 1; k < scsi_debug_num_parts; ++k)
3907 starts[k] = ((k * sectors_per_part) / heads_by_sects)
3908 * heads_by_sects;
3909 starts[scsi_debug_num_parts] = num_sectors;
3910 starts[scsi_debug_num_parts + 1] = 0;
3911
3912 ramp[510] = 0x55; /* magic partition markings */
3913 ramp[511] = 0xAA;
3914 pp = (struct partition *)(ramp + 0x1be);
3915 for (k = 0; starts[k + 1]; ++k, ++pp) {
3916 start_sec = starts[k];
3917 end_sec = starts[k + 1] - 1;
3918 pp->boot_ind = 0;
3919
3920 pp->cyl = start_sec / heads_by_sects;
3921 pp->head = (start_sec - (pp->cyl * heads_by_sects))
3922 / sdebug_sectors_per;
3923 pp->sector = (start_sec % sdebug_sectors_per) + 1;
3924
3925 pp->end_cyl = end_sec / heads_by_sects;
3926 pp->end_head = (end_sec - (pp->end_cyl * heads_by_sects))
3927 / sdebug_sectors_per;
3928 pp->end_sector = (end_sec % sdebug_sectors_per) + 1;
3929
Akinobu Mita150c3542013-08-26 22:08:40 +09003930 pp->start_sect = cpu_to_le32(start_sec);
3931 pp->nr_sects = cpu_to_le32(end_sec - start_sec + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003932 pp->sys_ind = 0x83; /* plain Linux partition */
3933 }
3934}
3935
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003936static int
3937schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip,
3938 int scsi_result, int delta_jiff)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003939{
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003940 unsigned long iflags;
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003941 int k, num_in_q, qdepth, inject;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003942 struct sdebug_queued_cmd *sqcp = NULL;
Tomas Winkler299b6c02015-07-28 16:54:24 +03003943 struct scsi_device *sdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003944
Tomas Winkler299b6c02015-07-28 16:54:24 +03003945 /* this should never happen */
3946 if (WARN_ON(!cmnd))
3947 return SCSI_MLQUEUE_HOST_BUSY;
3948
3949 if (NULL == devip) {
3950 pr_warn("called devip == NULL\n");
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003951 /* no particularly good error to report back */
3952 return SCSI_MLQUEUE_HOST_BUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003953 }
Tomas Winkler299b6c02015-07-28 16:54:24 +03003954
3955 sdp = cmnd->device;
3956
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003957 if ((scsi_result) && (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
3958 sdev_printk(KERN_INFO, sdp, "%s: non-zero result=0x%x\n",
3959 __func__, scsi_result);
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003960 if (delta_jiff == 0)
3961 goto respond_in_thread;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003962
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003963 /* schedule the response at a later time if resources permit */
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003964 spin_lock_irqsave(&queued_arr_lock, iflags);
3965 num_in_q = atomic_read(&devip->num_in_q);
3966 qdepth = cmnd->device->queue_depth;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003967 inject = 0;
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003968 if ((qdepth > 0) && (num_in_q >= qdepth)) {
3969 if (scsi_result) {
3970 spin_unlock_irqrestore(&queued_arr_lock, iflags);
3971 goto respond_in_thread;
3972 } else
3973 scsi_result = device_qfull_result;
3974 } else if ((scsi_debug_every_nth != 0) &&
3975 (SCSI_DEBUG_OPT_RARE_TSF & scsi_debug_opts) &&
3976 (scsi_result == 0)) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003977 if ((num_in_q == (qdepth - 1)) &&
3978 (atomic_inc_return(&sdebug_a_tsf) >=
3979 abs(scsi_debug_every_nth))) {
3980 atomic_set(&sdebug_a_tsf, 0);
3981 inject = 1;
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003982 scsi_result = device_qfull_result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003983 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003984 }
3985
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003986 k = find_first_zero_bit(queued_in_use_bm, scsi_debug_max_queue);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003987 if (k >= scsi_debug_max_queue) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003988 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003989 if (scsi_result)
3990 goto respond_in_thread;
3991 else if (SCSI_DEBUG_OPT_ALL_TSF & scsi_debug_opts)
3992 scsi_result = device_qfull_result;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003993 if (SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts)
3994 sdev_printk(KERN_INFO, sdp,
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003995 "%s: max_queue=%d exceeded, %s\n",
3996 __func__, scsi_debug_max_queue,
3997 (scsi_result ? "status: TASK SET FULL" :
3998 "report: host busy"));
3999 if (scsi_result)
4000 goto respond_in_thread;
4001 else
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004002 return SCSI_MLQUEUE_HOST_BUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004003 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004004 __set_bit(k, queued_in_use_bm);
4005 atomic_inc(&devip->num_in_q);
4006 sqcp = &queued_arr[k];
4007 sqcp->a_cmnd = cmnd;
4008 cmnd->result = scsi_result;
4009 spin_unlock_irqrestore(&queued_arr_lock, iflags);
4010 if (delta_jiff > 0) {
4011 if (NULL == sqcp->cmnd_timerp) {
4012 sqcp->cmnd_timerp = kmalloc(sizeof(struct timer_list),
4013 GFP_ATOMIC);
4014 if (NULL == sqcp->cmnd_timerp)
4015 return SCSI_MLQUEUE_HOST_BUSY;
4016 init_timer(sqcp->cmnd_timerp);
4017 }
4018 sqcp->cmnd_timerp->function = sdebug_q_cmd_complete;
4019 sqcp->cmnd_timerp->data = k;
4020 sqcp->cmnd_timerp->expires = get_jiffies_64() + delta_jiff;
4021 add_timer(sqcp->cmnd_timerp);
4022 } else if (scsi_debug_ndelay > 0) {
4023 ktime_t kt = ktime_set(0, scsi_debug_ndelay);
4024 struct sdebug_hrtimer *sd_hp = sqcp->sd_hrtp;
4025
4026 if (NULL == sd_hp) {
4027 sd_hp = kmalloc(sizeof(*sd_hp), GFP_ATOMIC);
4028 if (NULL == sd_hp)
4029 return SCSI_MLQUEUE_HOST_BUSY;
4030 sqcp->sd_hrtp = sd_hp;
4031 hrtimer_init(&sd_hp->hrt, CLOCK_MONOTONIC,
4032 HRTIMER_MODE_REL);
4033 sd_hp->hrt.function = sdebug_q_cmd_hrt_complete;
4034 sd_hp->qa_indx = k;
4035 }
4036 hrtimer_start(&sd_hp->hrt, kt, HRTIMER_MODE_REL);
4037 } else { /* delay < 0 */
4038 if (NULL == sqcp->tletp) {
4039 sqcp->tletp = kmalloc(sizeof(*sqcp->tletp),
4040 GFP_ATOMIC);
4041 if (NULL == sqcp->tletp)
4042 return SCSI_MLQUEUE_HOST_BUSY;
4043 tasklet_init(sqcp->tletp,
4044 sdebug_q_cmd_complete, k);
4045 }
4046 if (-1 == delta_jiff)
4047 tasklet_hi_schedule(sqcp->tletp);
4048 else
4049 tasklet_schedule(sqcp->tletp);
4050 }
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02004051 if ((SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts) &&
4052 (scsi_result == device_qfull_result))
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004053 sdev_printk(KERN_INFO, sdp,
4054 "%s: num_in_q=%d +1, %s%s\n", __func__,
4055 num_in_q, (inject ? "<inject> " : ""),
4056 "status: TASK SET FULL");
4057 return 0;
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02004058
4059respond_in_thread: /* call back to mid-layer using invocation thread */
4060 cmnd->result = scsi_result;
4061 cmnd->scsi_done(cmnd);
4062 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004063}
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004064
Douglas Gilbert23183912006-09-16 20:30:47 -04004065/* Note: The following macros create attribute files in the
4066 /sys/module/scsi_debug/parameters directory. Unfortunately this
4067 driver is unaware of a change and cannot trigger auxiliary actions
4068 as it can when the corresponding attribute in the
4069 /sys/bus/pseudo/drivers/scsi_debug directory is changed.
4070 */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004071module_param_named(add_host, scsi_debug_add_host, int, S_IRUGO | S_IWUSR);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004072module_param_named(ato, scsi_debug_ato, int, S_IRUGO);
Akinobu Mita0759c662014-02-26 22:57:04 +09004073module_param_named(clustering, scsi_debug_clustering, bool, S_IRUGO | S_IWUSR);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004074module_param_named(delay, scsi_debug_delay, int, S_IRUGO | S_IWUSR);
4075module_param_named(dev_size_mb, scsi_debug_dev_size_mb, int, S_IRUGO);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004076module_param_named(dif, scsi_debug_dif, int, S_IRUGO);
4077module_param_named(dix, scsi_debug_dix, int, S_IRUGO);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004078module_param_named(dsense, scsi_debug_dsense, int, S_IRUGO | S_IWUSR);
4079module_param_named(every_nth, scsi_debug_every_nth, int, S_IRUGO | S_IWUSR);
Douglas Gilbert23183912006-09-16 20:30:47 -04004080module_param_named(fake_rw, scsi_debug_fake_rw, int, S_IRUGO | S_IWUSR);
Akinobu Mita68aee7b2013-09-18 21:27:27 +09004081module_param_named(guard, scsi_debug_guard, uint, S_IRUGO);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004082module_param_named(host_lock, scsi_debug_host_lock, bool, S_IRUGO | S_IWUSR);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004083module_param_named(lbpu, scsi_debug_lbpu, int, S_IRUGO);
4084module_param_named(lbpws, scsi_debug_lbpws, int, S_IRUGO);
4085module_param_named(lbpws10, scsi_debug_lbpws10, int, S_IRUGO);
Eric Sandeenbe1dd782012-03-08 00:03:59 -06004086module_param_named(lbprz, scsi_debug_lbprz, int, S_IRUGO);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004087module_param_named(lowest_aligned, scsi_debug_lowest_aligned, int, S_IRUGO);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004088module_param_named(max_luns, scsi_debug_max_luns, int, S_IRUGO | S_IWUSR);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004089module_param_named(max_queue, scsi_debug_max_queue, int, S_IRUGO | S_IWUSR);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004090module_param_named(ndelay, scsi_debug_ndelay, int, S_IRUGO | S_IWUSR);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004091module_param_named(no_lun_0, scsi_debug_no_lun_0, int, S_IRUGO | S_IWUSR);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004092module_param_named(no_uld, scsi_debug_no_uld, int, S_IRUGO);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004093module_param_named(num_parts, scsi_debug_num_parts, int, S_IRUGO);
4094module_param_named(num_tgts, scsi_debug_num_tgts, int, S_IRUGO | S_IWUSR);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004095module_param_named(opt_blks, scsi_debug_opt_blks, int, S_IRUGO);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004096module_param_named(opts, scsi_debug_opts, int, S_IRUGO | S_IWUSR);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004097module_param_named(physblk_exp, scsi_debug_physblk_exp, int, S_IRUGO);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004098module_param_named(ptype, scsi_debug_ptype, int, S_IRUGO | S_IWUSR);
Martin Pittd9867882012-09-06 12:04:33 +02004099module_param_named(removable, scsi_debug_removable, bool, S_IRUGO | S_IWUSR);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004100module_param_named(scsi_level, scsi_debug_scsi_level, int, S_IRUGO);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004101module_param_named(sector_size, scsi_debug_sector_size, int, S_IRUGO);
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05004102module_param_named(strict, scsi_debug_strict, bool, S_IRUGO | S_IWUSR);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004103module_param_named(unmap_alignment, scsi_debug_unmap_alignment, int, S_IRUGO);
4104module_param_named(unmap_granularity, scsi_debug_unmap_granularity, int, S_IRUGO);
4105module_param_named(unmap_max_blocks, scsi_debug_unmap_max_blocks, int, S_IRUGO);
4106module_param_named(unmap_max_desc, scsi_debug_unmap_max_desc, int, S_IRUGO);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004107module_param_named(virtual_gb, scsi_debug_virtual_gb, int, S_IRUGO | S_IWUSR);
Douglas Gilbert23183912006-09-16 20:30:47 -04004108module_param_named(vpd_use_hostno, scsi_debug_vpd_use_hostno, int,
4109 S_IRUGO | S_IWUSR);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004110module_param_named(write_same_length, scsi_debug_write_same_length, int,
4111 S_IRUGO | S_IWUSR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004112
4113MODULE_AUTHOR("Eric Youngdale + Douglas Gilbert");
4114MODULE_DESCRIPTION("SCSI debug adapter driver");
4115MODULE_LICENSE("GPL");
4116MODULE_VERSION(SCSI_DEBUG_VERSION);
4117
4118MODULE_PARM_DESC(add_host, "0..127 hosts allowed(def=1)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004119MODULE_PARM_DESC(ato, "application tag ownership: 0=disk 1=host (def=1)");
Akinobu Mita0759c662014-02-26 22:57:04 +09004120MODULE_PARM_DESC(clustering, "when set enables larger transfers (def=0)");
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004121MODULE_PARM_DESC(delay, "response delay (def=1 jiffy); 0:imm, -1,-2:tiny");
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05004122MODULE_PARM_DESC(dev_size_mb, "size in MiB of ram shared by devs(def=8)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004123MODULE_PARM_DESC(dif, "data integrity field type: 0-3 (def=0)");
4124MODULE_PARM_DESC(dix, "data integrity extensions mask (def=0)");
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004125MODULE_PARM_DESC(dsense, "use descriptor sense format(def=0 -> fixed)");
Randy Dunlapbeb87c32007-06-11 11:36:40 -07004126MODULE_PARM_DESC(every_nth, "timeout every nth command(def=0)");
Douglas Gilbert23183912006-09-16 20:30:47 -04004127MODULE_PARM_DESC(fake_rw, "fake reads/writes instead of copying (def=0)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004128MODULE_PARM_DESC(guard, "protection checksum: 0=crc, 1=ip (def=0)");
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004129MODULE_PARM_DESC(host_lock, "use host_lock around all commands (def=0)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004130MODULE_PARM_DESC(lbpu, "enable LBP, support UNMAP command (def=0)");
4131MODULE_PARM_DESC(lbpws, "enable LBP, support WRITE SAME(16) with UNMAP bit (def=0)");
4132MODULE_PARM_DESC(lbpws10, "enable LBP, support WRITE SAME(10) with UNMAP bit (def=0)");
Eric Sandeenbe1dd782012-03-08 00:03:59 -06004133MODULE_PARM_DESC(lbprz, "unmapped blocks return 0 on read (def=1)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004134MODULE_PARM_DESC(lowest_aligned, "lowest aligned lba (def=0)");
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004135MODULE_PARM_DESC(max_luns, "number of LUNs per target to simulate(def=1)");
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004136MODULE_PARM_DESC(max_queue, "max number of queued commands (1 to max(def))");
4137MODULE_PARM_DESC(ndelay, "response delay in nanoseconds (def=0 -> ignore)");
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004138MODULE_PARM_DESC(no_lun_0, "no LU number 0 (def=0 -> have lun 0)");
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004139MODULE_PARM_DESC(no_uld, "stop ULD (e.g. sd driver) attaching (def=0))");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004140MODULE_PARM_DESC(num_parts, "number of partitions(def=0)");
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004141MODULE_PARM_DESC(num_tgts, "number of targets per host to simulate(def=1)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004142MODULE_PARM_DESC(opt_blks, "optimal transfer length in block (def=64)");
Douglas Gilbert6f3cbf52007-01-05 00:05:25 -05004143MODULE_PARM_DESC(opts, "1->noise, 2->medium_err, 4->timeout, 8->recovered_err... (def=0)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004144MODULE_PARM_DESC(physblk_exp, "physical block exponent (def=0)");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004145MODULE_PARM_DESC(ptype, "SCSI peripheral type(def=0[disk])");
Martin Pittd9867882012-09-06 12:04:33 +02004146MODULE_PARM_DESC(removable, "claim to have removable media (def=0)");
Douglas Gilberte46b0342014-08-05 12:21:53 +02004147MODULE_PARM_DESC(scsi_level, "SCSI level to simulate(def=6[SPC-4])");
Martin K. Petersenea61fca2009-05-15 00:40:33 -04004148MODULE_PARM_DESC(sector_size, "logical block size in bytes (def=512)");
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05004149MODULE_PARM_DESC(strict, "stricter checks: reserved field in cdb (def=0)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004150MODULE_PARM_DESC(unmap_alignment, "lowest aligned thin provisioning lba (def=0)");
4151MODULE_PARM_DESC(unmap_granularity, "thin provisioning granularity in blocks (def=1)");
Martin K. Petersen60147592010-08-19 11:49:00 -04004152MODULE_PARM_DESC(unmap_max_blocks, "max # of blocks can be unmapped in one cmd (def=0xffffffff)");
4153MODULE_PARM_DESC(unmap_max_desc, "max # of ranges that can be unmapped in one cmd (def=256)");
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05004154MODULE_PARM_DESC(virtual_gb, "virtual gigabyte (GiB) size (def=0 -> use dev_size_mb)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004155MODULE_PARM_DESC(vpd_use_hostno, "0 -> dev ids ignore hostno (def=1 -> unique dev ids)");
4156MODULE_PARM_DESC(write_same_length, "Maximum blocks per WRITE SAME cmd (def=0xffff)");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004157
4158static char sdebug_info[256];
4159
4160static const char * scsi_debug_info(struct Scsi_Host * shp)
4161{
4162 sprintf(sdebug_info, "scsi_debug, version %s [%s], "
4163 "dev_size_mb=%d, opts=0x%x", SCSI_DEBUG_VERSION,
4164 scsi_debug_version_date, scsi_debug_dev_size_mb,
4165 scsi_debug_opts);
4166 return sdebug_info;
4167}
4168
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004169/* 'echo <val> > /proc/scsi/scsi_debug/<host_id>' writes to opts */
Al Viroc8ed5552013-03-31 01:46:06 -04004170static int scsi_debug_write_info(struct Scsi_Host *host, char *buffer, int length)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004171{
Al Viroc8ed5552013-03-31 01:46:06 -04004172 char arr[16];
4173 int opts;
4174 int minLen = length > 15 ? 15 : length;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004175
Al Viroc8ed5552013-03-31 01:46:06 -04004176 if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
4177 return -EACCES;
4178 memcpy(arr, buffer, minLen);
4179 arr[minLen] = '\0';
4180 if (1 != sscanf(arr, "%d", &opts))
4181 return -EINVAL;
4182 scsi_debug_opts = opts;
4183 if (scsi_debug_every_nth != 0)
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004184 atomic_set(&sdebug_cmnd_count, 0);
Al Viroc8ed5552013-03-31 01:46:06 -04004185 return length;
4186}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004187
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004188/* Output seen with 'cat /proc/scsi/scsi_debug/<host_id>'. It will be the
4189 * same for each scsi_debug host (if more than one). Some of the counters
4190 * output are not atomics so might be inaccurate in a busy system. */
Al Viroc8ed5552013-03-31 01:46:06 -04004191static int scsi_debug_show_info(struct seq_file *m, struct Scsi_Host *host)
4192{
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004193 int f, l;
4194 char b[32];
4195
4196 if (scsi_debug_every_nth > 0)
4197 snprintf(b, sizeof(b), " (curr:%d)",
4198 ((SCSI_DEBUG_OPT_RARE_TSF & scsi_debug_opts) ?
4199 atomic_read(&sdebug_a_tsf) :
4200 atomic_read(&sdebug_cmnd_count)));
4201 else
4202 b[0] = '\0';
4203
4204 seq_printf(m, "scsi_debug adapter driver, version %s [%s]\n"
4205 "num_tgts=%d, shared (ram) size=%d MB, opts=0x%x, "
4206 "every_nth=%d%s\n"
4207 "delay=%d, ndelay=%d, max_luns=%d, q_completions=%d\n"
4208 "sector_size=%d bytes, cylinders=%d, heads=%d, sectors=%d\n"
4209 "command aborts=%d; RESETs: device=%d, target=%d, bus=%d, "
4210 "host=%d\ndix_reads=%d dix_writes=%d dif_errors=%d "
4211 "usec_in_jiffy=%lu\n",
4212 SCSI_DEBUG_VERSION, scsi_debug_version_date,
4213 scsi_debug_num_tgts, scsi_debug_dev_size_mb, scsi_debug_opts,
4214 scsi_debug_every_nth, b, scsi_debug_delay, scsi_debug_ndelay,
4215 scsi_debug_max_luns, atomic_read(&sdebug_completions),
4216 scsi_debug_sector_size, sdebug_cylinders_per, sdebug_heads,
4217 sdebug_sectors_per, num_aborts, num_dev_resets,
4218 num_target_resets, num_bus_resets, num_host_resets,
4219 dix_reads, dix_writes, dif_errors, TICK_NSEC / 1000);
4220
4221 f = find_first_bit(queued_in_use_bm, scsi_debug_max_queue);
4222 if (f != scsi_debug_max_queue) {
4223 l = find_last_bit(queued_in_use_bm, scsi_debug_max_queue);
4224 seq_printf(m, " %s BUSY: first,last bits set: %d,%d\n",
4225 "queued_in_use_bm", f, l);
4226 }
Al Viroc8ed5552013-03-31 01:46:06 -04004227 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004228}
4229
Akinobu Mita82069372013-10-14 22:48:04 +09004230static ssize_t delay_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004231{
4232 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_delay);
4233}
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004234/* Returns -EBUSY if delay is being changed and commands are queued */
Akinobu Mita82069372013-10-14 22:48:04 +09004235static ssize_t delay_store(struct device_driver *ddp, const char *buf,
4236 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004237{
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004238 int delay, res;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004239
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004240 if ((count > 0) && (1 == sscanf(buf, "%d", &delay))) {
4241 res = count;
4242 if (scsi_debug_delay != delay) {
4243 unsigned long iflags;
4244 int k;
4245
4246 spin_lock_irqsave(&queued_arr_lock, iflags);
4247 k = find_first_bit(queued_in_use_bm,
4248 scsi_debug_max_queue);
4249 if (k != scsi_debug_max_queue)
4250 res = -EBUSY; /* have queued commands */
4251 else {
4252 scsi_debug_delay = delay;
4253 scsi_debug_ndelay = 0;
4254 }
4255 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004256 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004257 return res;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004258 }
4259 return -EINVAL;
4260}
Akinobu Mita82069372013-10-14 22:48:04 +09004261static DRIVER_ATTR_RW(delay);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004262
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004263static ssize_t ndelay_show(struct device_driver *ddp, char *buf)
4264{
4265 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_ndelay);
4266}
4267/* Returns -EBUSY if ndelay is being changed and commands are queued */
4268/* If > 0 and accepted then scsi_debug_delay is set to DELAY_OVERRIDDEN */
4269static ssize_t ndelay_store(struct device_driver *ddp, const char *buf,
4270 size_t count)
4271{
4272 unsigned long iflags;
4273 int ndelay, res, k;
4274
4275 if ((count > 0) && (1 == sscanf(buf, "%d", &ndelay)) &&
4276 (ndelay >= 0) && (ndelay < 1000000000)) {
4277 res = count;
4278 if (scsi_debug_ndelay != ndelay) {
4279 spin_lock_irqsave(&queued_arr_lock, iflags);
4280 k = find_first_bit(queued_in_use_bm,
4281 scsi_debug_max_queue);
4282 if (k != scsi_debug_max_queue)
4283 res = -EBUSY; /* have queued commands */
4284 else {
4285 scsi_debug_ndelay = ndelay;
4286 scsi_debug_delay = ndelay ? DELAY_OVERRIDDEN
4287 : DEF_DELAY;
4288 }
4289 spin_unlock_irqrestore(&queued_arr_lock, iflags);
4290 }
4291 return res;
4292 }
4293 return -EINVAL;
4294}
4295static DRIVER_ATTR_RW(ndelay);
4296
Akinobu Mita82069372013-10-14 22:48:04 +09004297static ssize_t opts_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004298{
4299 return scnprintf(buf, PAGE_SIZE, "0x%x\n", scsi_debug_opts);
4300}
4301
Akinobu Mita82069372013-10-14 22:48:04 +09004302static ssize_t opts_store(struct device_driver *ddp, const char *buf,
4303 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004304{
4305 int opts;
4306 char work[20];
4307
4308 if (1 == sscanf(buf, "%10s", work)) {
Rasmus Villemoes48a96872014-10-13 15:54:44 -07004309 if (0 == strncasecmp(work,"0x", 2)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004310 if (1 == sscanf(&work[2], "%x", &opts))
4311 goto opts_done;
4312 } else {
4313 if (1 == sscanf(work, "%d", &opts))
4314 goto opts_done;
4315 }
4316 }
4317 return -EINVAL;
4318opts_done:
4319 scsi_debug_opts = opts;
Douglas Gilbert817fd662014-11-24 20:18:02 -05004320 if (SCSI_DEBUG_OPT_RECOVERED_ERR & opts)
4321 sdebug_any_injecting_opt = true;
4322 else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & opts)
4323 sdebug_any_injecting_opt = true;
4324 else if (SCSI_DEBUG_OPT_DIF_ERR & opts)
4325 sdebug_any_injecting_opt = true;
4326 else if (SCSI_DEBUG_OPT_DIX_ERR & opts)
4327 sdebug_any_injecting_opt = true;
4328 else if (SCSI_DEBUG_OPT_SHORT_TRANSFER & opts)
4329 sdebug_any_injecting_opt = true;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004330 atomic_set(&sdebug_cmnd_count, 0);
4331 atomic_set(&sdebug_a_tsf, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004332 return count;
4333}
Akinobu Mita82069372013-10-14 22:48:04 +09004334static DRIVER_ATTR_RW(opts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004335
Akinobu Mita82069372013-10-14 22:48:04 +09004336static ssize_t ptype_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004337{
4338 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_ptype);
4339}
Akinobu Mita82069372013-10-14 22:48:04 +09004340static ssize_t ptype_store(struct device_driver *ddp, const char *buf,
4341 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004342{
4343 int n;
4344
4345 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
4346 scsi_debug_ptype = n;
4347 return count;
4348 }
4349 return -EINVAL;
4350}
Akinobu Mita82069372013-10-14 22:48:04 +09004351static DRIVER_ATTR_RW(ptype);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004352
Akinobu Mita82069372013-10-14 22:48:04 +09004353static ssize_t dsense_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004354{
4355 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dsense);
4356}
Akinobu Mita82069372013-10-14 22:48:04 +09004357static ssize_t dsense_store(struct device_driver *ddp, const char *buf,
4358 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004359{
4360 int n;
4361
4362 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
4363 scsi_debug_dsense = n;
4364 return count;
4365 }
4366 return -EINVAL;
4367}
Akinobu Mita82069372013-10-14 22:48:04 +09004368static DRIVER_ATTR_RW(dsense);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004369
Akinobu Mita82069372013-10-14 22:48:04 +09004370static ssize_t fake_rw_show(struct device_driver *ddp, char *buf)
Douglas Gilbert23183912006-09-16 20:30:47 -04004371{
4372 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_fake_rw);
4373}
Akinobu Mita82069372013-10-14 22:48:04 +09004374static ssize_t fake_rw_store(struct device_driver *ddp, const char *buf,
4375 size_t count)
Douglas Gilbert23183912006-09-16 20:30:47 -04004376{
4377 int n;
4378
4379 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004380 n = (n > 0);
4381 scsi_debug_fake_rw = (scsi_debug_fake_rw > 0);
4382 if (scsi_debug_fake_rw != n) {
4383 if ((0 == n) && (NULL == fake_storep)) {
4384 unsigned long sz =
4385 (unsigned long)scsi_debug_dev_size_mb *
4386 1048576;
4387
4388 fake_storep = vmalloc(sz);
4389 if (NULL == fake_storep) {
Tomas Winklerc12879702015-07-28 16:54:20 +03004390 pr_err("out of memory, 9\n");
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004391 return -ENOMEM;
4392 }
4393 memset(fake_storep, 0, sz);
4394 }
4395 scsi_debug_fake_rw = n;
4396 }
Douglas Gilbert23183912006-09-16 20:30:47 -04004397 return count;
4398 }
4399 return -EINVAL;
4400}
Akinobu Mita82069372013-10-14 22:48:04 +09004401static DRIVER_ATTR_RW(fake_rw);
Douglas Gilbert23183912006-09-16 20:30:47 -04004402
Akinobu Mita82069372013-10-14 22:48:04 +09004403static ssize_t no_lun_0_show(struct device_driver *ddp, char *buf)
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004404{
4405 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_no_lun_0);
4406}
Akinobu Mita82069372013-10-14 22:48:04 +09004407static ssize_t no_lun_0_store(struct device_driver *ddp, const char *buf,
4408 size_t count)
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004409{
4410 int n;
4411
4412 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
4413 scsi_debug_no_lun_0 = n;
4414 return count;
4415 }
4416 return -EINVAL;
4417}
Akinobu Mita82069372013-10-14 22:48:04 +09004418static DRIVER_ATTR_RW(no_lun_0);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004419
Akinobu Mita82069372013-10-14 22:48:04 +09004420static ssize_t num_tgts_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004421{
4422 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_num_tgts);
4423}
Akinobu Mita82069372013-10-14 22:48:04 +09004424static ssize_t num_tgts_store(struct device_driver *ddp, const char *buf,
4425 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004426{
4427 int n;
4428
4429 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
4430 scsi_debug_num_tgts = n;
4431 sdebug_max_tgts_luns();
4432 return count;
4433 }
4434 return -EINVAL;
4435}
Akinobu Mita82069372013-10-14 22:48:04 +09004436static DRIVER_ATTR_RW(num_tgts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004437
Akinobu Mita82069372013-10-14 22:48:04 +09004438static ssize_t dev_size_mb_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004439{
4440 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dev_size_mb);
4441}
Akinobu Mita82069372013-10-14 22:48:04 +09004442static DRIVER_ATTR_RO(dev_size_mb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004443
Akinobu Mita82069372013-10-14 22:48:04 +09004444static ssize_t num_parts_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004445{
4446 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_num_parts);
4447}
Akinobu Mita82069372013-10-14 22:48:04 +09004448static DRIVER_ATTR_RO(num_parts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004449
Akinobu Mita82069372013-10-14 22:48:04 +09004450static ssize_t every_nth_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004451{
4452 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_every_nth);
4453}
Akinobu Mita82069372013-10-14 22:48:04 +09004454static ssize_t every_nth_store(struct device_driver *ddp, const char *buf,
4455 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004456{
4457 int nth;
4458
4459 if ((count > 0) && (1 == sscanf(buf, "%d", &nth))) {
4460 scsi_debug_every_nth = nth;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004461 atomic_set(&sdebug_cmnd_count, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004462 return count;
4463 }
4464 return -EINVAL;
4465}
Akinobu Mita82069372013-10-14 22:48:04 +09004466static DRIVER_ATTR_RW(every_nth);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004467
Akinobu Mita82069372013-10-14 22:48:04 +09004468static ssize_t max_luns_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004469{
4470 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_max_luns);
4471}
Akinobu Mita82069372013-10-14 22:48:04 +09004472static ssize_t max_luns_store(struct device_driver *ddp, const char *buf,
4473 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004474{
4475 int n;
Ewan D. Milne19c8ead2014-12-04 11:49:27 -05004476 bool changed;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004477
4478 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
Ewan D. Milne19c8ead2014-12-04 11:49:27 -05004479 changed = (scsi_debug_max_luns != n);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004480 scsi_debug_max_luns = n;
4481 sdebug_max_tgts_luns();
Ewan D. Milne19c8ead2014-12-04 11:49:27 -05004482 if (changed && (scsi_debug_scsi_level >= 5)) { /* >= SPC-3 */
4483 struct sdebug_host_info *sdhp;
4484 struct sdebug_dev_info *dp;
4485
4486 spin_lock(&sdebug_host_list_lock);
4487 list_for_each_entry(sdhp, &sdebug_host_list,
4488 host_list) {
4489 list_for_each_entry(dp, &sdhp->dev_info_list,
4490 dev_list) {
4491 set_bit(SDEBUG_UA_LUNS_CHANGED,
4492 dp->uas_bm);
4493 }
4494 }
4495 spin_unlock(&sdebug_host_list_lock);
4496 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004497 return count;
4498 }
4499 return -EINVAL;
4500}
Akinobu Mita82069372013-10-14 22:48:04 +09004501static DRIVER_ATTR_RW(max_luns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004502
Akinobu Mita82069372013-10-14 22:48:04 +09004503static ssize_t max_queue_show(struct device_driver *ddp, char *buf)
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004504{
4505 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_max_queue);
4506}
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004507/* N.B. max_queue can be changed while there are queued commands. In flight
4508 * commands beyond the new max_queue will be completed. */
Akinobu Mita82069372013-10-14 22:48:04 +09004509static ssize_t max_queue_store(struct device_driver *ddp, const char *buf,
4510 size_t count)
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004511{
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004512 unsigned long iflags;
4513 int n, k;
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004514
4515 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n > 0) &&
4516 (n <= SCSI_DEBUG_CANQUEUE)) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004517 spin_lock_irqsave(&queued_arr_lock, iflags);
4518 k = find_last_bit(queued_in_use_bm, SCSI_DEBUG_CANQUEUE);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004519 scsi_debug_max_queue = n;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004520 if (SCSI_DEBUG_CANQUEUE == k)
4521 atomic_set(&retired_max_queue, 0);
4522 else if (k >= n)
4523 atomic_set(&retired_max_queue, k + 1);
4524 else
4525 atomic_set(&retired_max_queue, 0);
4526 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004527 return count;
4528 }
4529 return -EINVAL;
4530}
Akinobu Mita82069372013-10-14 22:48:04 +09004531static DRIVER_ATTR_RW(max_queue);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004532
Akinobu Mita82069372013-10-14 22:48:04 +09004533static ssize_t no_uld_show(struct device_driver *ddp, char *buf)
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004534{
4535 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_no_uld);
4536}
Akinobu Mita82069372013-10-14 22:48:04 +09004537static DRIVER_ATTR_RO(no_uld);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004538
Akinobu Mita82069372013-10-14 22:48:04 +09004539static ssize_t scsi_level_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004540{
4541 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_scsi_level);
4542}
Akinobu Mita82069372013-10-14 22:48:04 +09004543static DRIVER_ATTR_RO(scsi_level);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004544
Akinobu Mita82069372013-10-14 22:48:04 +09004545static ssize_t virtual_gb_show(struct device_driver *ddp, char *buf)
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004546{
4547 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_virtual_gb);
4548}
Akinobu Mita82069372013-10-14 22:48:04 +09004549static ssize_t virtual_gb_store(struct device_driver *ddp, const char *buf,
4550 size_t count)
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004551{
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05004552 int n;
Douglas Gilbert0d01c5d2014-11-24 20:27:51 -05004553 bool changed;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004554
4555 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
Douglas Gilbert0d01c5d2014-11-24 20:27:51 -05004556 changed = (scsi_debug_virtual_gb != n);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004557 scsi_debug_virtual_gb = n;
FUJITA Tomonori28898872008-03-30 00:59:55 +09004558 sdebug_capacity = get_sdebug_capacity();
Douglas Gilbert0d01c5d2014-11-24 20:27:51 -05004559 if (changed) {
4560 struct sdebug_host_info *sdhp;
4561 struct sdebug_dev_info *dp;
FUJITA Tomonori28898872008-03-30 00:59:55 +09004562
Ewan D. Milne4bc6b632014-12-04 11:49:26 -05004563 spin_lock(&sdebug_host_list_lock);
Douglas Gilbert0d01c5d2014-11-24 20:27:51 -05004564 list_for_each_entry(sdhp, &sdebug_host_list,
4565 host_list) {
4566 list_for_each_entry(dp, &sdhp->dev_info_list,
4567 dev_list) {
4568 set_bit(SDEBUG_UA_CAPACITY_CHANGED,
4569 dp->uas_bm);
4570 }
4571 }
Ewan D. Milne4bc6b632014-12-04 11:49:26 -05004572 spin_unlock(&sdebug_host_list_lock);
Douglas Gilbert0d01c5d2014-11-24 20:27:51 -05004573 }
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004574 return count;
4575 }
4576 return -EINVAL;
4577}
Akinobu Mita82069372013-10-14 22:48:04 +09004578static DRIVER_ATTR_RW(virtual_gb);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004579
Akinobu Mita82069372013-10-14 22:48:04 +09004580static ssize_t add_host_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004581{
4582 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_add_host);
4583}
4584
Akinobu Mita82069372013-10-14 22:48:04 +09004585static ssize_t add_host_store(struct device_driver *ddp, const char *buf,
4586 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004587{
FUJITA Tomonorif3df41c2008-03-20 11:09:15 +09004588 int delta_hosts;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004589
FUJITA Tomonorif3df41c2008-03-20 11:09:15 +09004590 if (sscanf(buf, "%d", &delta_hosts) != 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004591 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004592 if (delta_hosts > 0) {
4593 do {
4594 sdebug_add_adapter();
4595 } while (--delta_hosts);
4596 } else if (delta_hosts < 0) {
4597 do {
4598 sdebug_remove_adapter();
4599 } while (++delta_hosts);
4600 }
4601 return count;
4602}
Akinobu Mita82069372013-10-14 22:48:04 +09004603static DRIVER_ATTR_RW(add_host);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004604
Akinobu Mita82069372013-10-14 22:48:04 +09004605static ssize_t vpd_use_hostno_show(struct device_driver *ddp, char *buf)
Douglas Gilbert23183912006-09-16 20:30:47 -04004606{
4607 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_vpd_use_hostno);
4608}
Akinobu Mita82069372013-10-14 22:48:04 +09004609static ssize_t vpd_use_hostno_store(struct device_driver *ddp, const char *buf,
4610 size_t count)
Douglas Gilbert23183912006-09-16 20:30:47 -04004611{
4612 int n;
4613
4614 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
4615 scsi_debug_vpd_use_hostno = n;
4616 return count;
4617 }
4618 return -EINVAL;
4619}
Akinobu Mita82069372013-10-14 22:48:04 +09004620static DRIVER_ATTR_RW(vpd_use_hostno);
Douglas Gilbert23183912006-09-16 20:30:47 -04004621
Akinobu Mita82069372013-10-14 22:48:04 +09004622static ssize_t sector_size_show(struct device_driver *ddp, char *buf)
Martin K. Petersen597136a2008-06-05 00:12:59 -04004623{
4624 return scnprintf(buf, PAGE_SIZE, "%u\n", scsi_debug_sector_size);
4625}
Akinobu Mita82069372013-10-14 22:48:04 +09004626static DRIVER_ATTR_RO(sector_size);
Martin K. Petersen597136a2008-06-05 00:12:59 -04004627
Akinobu Mita82069372013-10-14 22:48:04 +09004628static ssize_t dix_show(struct device_driver *ddp, char *buf)
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004629{
4630 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dix);
4631}
Akinobu Mita82069372013-10-14 22:48:04 +09004632static DRIVER_ATTR_RO(dix);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004633
Akinobu Mita82069372013-10-14 22:48:04 +09004634static ssize_t dif_show(struct device_driver *ddp, char *buf)
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004635{
4636 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dif);
4637}
Akinobu Mita82069372013-10-14 22:48:04 +09004638static DRIVER_ATTR_RO(dif);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004639
Akinobu Mita82069372013-10-14 22:48:04 +09004640static ssize_t guard_show(struct device_driver *ddp, char *buf)
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004641{
Akinobu Mita68aee7b2013-09-18 21:27:27 +09004642 return scnprintf(buf, PAGE_SIZE, "%u\n", scsi_debug_guard);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004643}
Akinobu Mita82069372013-10-14 22:48:04 +09004644static DRIVER_ATTR_RO(guard);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004645
Akinobu Mita82069372013-10-14 22:48:04 +09004646static ssize_t ato_show(struct device_driver *ddp, char *buf)
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004647{
4648 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_ato);
4649}
Akinobu Mita82069372013-10-14 22:48:04 +09004650static DRIVER_ATTR_RO(ato);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004651
Akinobu Mita82069372013-10-14 22:48:04 +09004652static ssize_t map_show(struct device_driver *ddp, char *buf)
Martin K. Petersen44d92692009-10-15 14:45:27 -04004653{
4654 ssize_t count;
4655
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004656 if (!scsi_debug_lbp())
Martin K. Petersen44d92692009-10-15 14:45:27 -04004657 return scnprintf(buf, PAGE_SIZE, "0-%u\n",
4658 sdebug_store_sectors);
4659
Tejun Heoc7badc92015-02-13 14:37:51 -08004660 count = scnprintf(buf, PAGE_SIZE - 1, "%*pbl",
4661 (int)map_size, map_storep);
Martin K. Petersen44d92692009-10-15 14:45:27 -04004662 buf[count++] = '\n';
Tejun Heoc7badc92015-02-13 14:37:51 -08004663 buf[count] = '\0';
Martin K. Petersen44d92692009-10-15 14:45:27 -04004664
4665 return count;
4666}
Akinobu Mita82069372013-10-14 22:48:04 +09004667static DRIVER_ATTR_RO(map);
Martin K. Petersen44d92692009-10-15 14:45:27 -04004668
Akinobu Mita82069372013-10-14 22:48:04 +09004669static ssize_t removable_show(struct device_driver *ddp, char *buf)
Martin Pittd9867882012-09-06 12:04:33 +02004670{
4671 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_removable ? 1 : 0);
4672}
Akinobu Mita82069372013-10-14 22:48:04 +09004673static ssize_t removable_store(struct device_driver *ddp, const char *buf,
4674 size_t count)
Martin Pittd9867882012-09-06 12:04:33 +02004675{
4676 int n;
4677
4678 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
4679 scsi_debug_removable = (n > 0);
4680 return count;
4681 }
4682 return -EINVAL;
4683}
Akinobu Mita82069372013-10-14 22:48:04 +09004684static DRIVER_ATTR_RW(removable);
Martin Pittd9867882012-09-06 12:04:33 +02004685
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004686static ssize_t host_lock_show(struct device_driver *ddp, char *buf)
4687{
4688 return scnprintf(buf, PAGE_SIZE, "%d\n", !!scsi_debug_host_lock);
4689}
4690/* Returns -EBUSY if host_lock is being changed and commands are queued */
4691static ssize_t host_lock_store(struct device_driver *ddp, const char *buf,
4692 size_t count)
4693{
4694 int n, res;
4695
4696 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
4697 bool new_host_lock = (n > 0);
4698
4699 res = count;
4700 if (new_host_lock != scsi_debug_host_lock) {
4701 unsigned long iflags;
4702 int k;
4703
4704 spin_lock_irqsave(&queued_arr_lock, iflags);
4705 k = find_first_bit(queued_in_use_bm,
4706 scsi_debug_max_queue);
4707 if (k != scsi_debug_max_queue)
4708 res = -EBUSY; /* have queued commands */
4709 else
4710 scsi_debug_host_lock = new_host_lock;
4711 spin_unlock_irqrestore(&queued_arr_lock, iflags);
4712 }
4713 return res;
4714 }
4715 return -EINVAL;
4716}
4717static DRIVER_ATTR_RW(host_lock);
4718
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05004719static ssize_t strict_show(struct device_driver *ddp, char *buf)
4720{
4721 return scnprintf(buf, PAGE_SIZE, "%d\n", !!scsi_debug_strict);
4722}
4723static ssize_t strict_store(struct device_driver *ddp, const char *buf,
4724 size_t count)
4725{
4726 int n;
4727
4728 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
4729 scsi_debug_strict = (n > 0);
4730 return count;
4731 }
4732 return -EINVAL;
4733}
4734static DRIVER_ATTR_RW(strict);
4735
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004736
Akinobu Mita82069372013-10-14 22:48:04 +09004737/* Note: The following array creates attribute files in the
Douglas Gilbert23183912006-09-16 20:30:47 -04004738 /sys/bus/pseudo/drivers/scsi_debug directory. The advantage of these
4739 files (over those found in the /sys/module/scsi_debug/parameters
4740 directory) is that auxiliary actions can be triggered when an attribute
4741 is changed. For example see: sdebug_add_host_store() above.
4742 */
Randy Dunlap6ecaff72006-07-11 20:53:22 -07004743
Akinobu Mita82069372013-10-14 22:48:04 +09004744static struct attribute *sdebug_drv_attrs[] = {
4745 &driver_attr_delay.attr,
4746 &driver_attr_opts.attr,
4747 &driver_attr_ptype.attr,
4748 &driver_attr_dsense.attr,
4749 &driver_attr_fake_rw.attr,
4750 &driver_attr_no_lun_0.attr,
4751 &driver_attr_num_tgts.attr,
4752 &driver_attr_dev_size_mb.attr,
4753 &driver_attr_num_parts.attr,
4754 &driver_attr_every_nth.attr,
4755 &driver_attr_max_luns.attr,
4756 &driver_attr_max_queue.attr,
4757 &driver_attr_no_uld.attr,
4758 &driver_attr_scsi_level.attr,
4759 &driver_attr_virtual_gb.attr,
4760 &driver_attr_add_host.attr,
4761 &driver_attr_vpd_use_hostno.attr,
4762 &driver_attr_sector_size.attr,
4763 &driver_attr_dix.attr,
4764 &driver_attr_dif.attr,
4765 &driver_attr_guard.attr,
4766 &driver_attr_ato.attr,
4767 &driver_attr_map.attr,
4768 &driver_attr_removable.attr,
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004769 &driver_attr_host_lock.attr,
4770 &driver_attr_ndelay.attr,
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05004771 &driver_attr_strict.attr,
Akinobu Mita82069372013-10-14 22:48:04 +09004772 NULL,
4773};
4774ATTRIBUTE_GROUPS(sdebug_drv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004775
Akinobu Mita11ddcec2014-02-26 22:56:59 +09004776static struct device *pseudo_primary;
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09004777
Linus Torvalds1da177e2005-04-16 15:20:36 -07004778static int __init scsi_debug_init(void)
4779{
FUJITA Tomonori5f2578e2008-03-30 00:59:57 +09004780 unsigned long sz;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004781 int host_to_add;
4782 int k;
Randy Dunlap6ecaff72006-07-11 20:53:22 -07004783 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004784
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004785 atomic_set(&sdebug_cmnd_count, 0);
4786 atomic_set(&sdebug_completions, 0);
4787 atomic_set(&retired_max_queue, 0);
4788
4789 if (scsi_debug_ndelay >= 1000000000) {
Tomas Winklerc12879702015-07-28 16:54:20 +03004790 pr_warn("ndelay must be less than 1 second, ignored\n");
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004791 scsi_debug_ndelay = 0;
4792 } else if (scsi_debug_ndelay > 0)
4793 scsi_debug_delay = DELAY_OVERRIDDEN;
4794
Martin K. Petersen597136a2008-06-05 00:12:59 -04004795 switch (scsi_debug_sector_size) {
4796 case 512:
4797 case 1024:
4798 case 2048:
4799 case 4096:
4800 break;
4801 default:
Tomas Winklerc12879702015-07-28 16:54:20 +03004802 pr_err("invalid sector_size %d\n", scsi_debug_sector_size);
Martin K. Petersen597136a2008-06-05 00:12:59 -04004803 return -EINVAL;
4804 }
4805
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004806 switch (scsi_debug_dif) {
4807
4808 case SD_DIF_TYPE0_PROTECTION:
4809 case SD_DIF_TYPE1_PROTECTION:
Martin K. Petersen395cef02009-09-18 17:33:03 -04004810 case SD_DIF_TYPE2_PROTECTION:
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004811 case SD_DIF_TYPE3_PROTECTION:
4812 break;
4813
4814 default:
Tomas Winklerc12879702015-07-28 16:54:20 +03004815 pr_err("dif must be 0, 1, 2 or 3\n");
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004816 return -EINVAL;
4817 }
4818
4819 if (scsi_debug_guard > 1) {
Tomas Winklerc12879702015-07-28 16:54:20 +03004820 pr_err("guard must be 0 or 1\n");
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004821 return -EINVAL;
4822 }
4823
4824 if (scsi_debug_ato > 1) {
Tomas Winklerc12879702015-07-28 16:54:20 +03004825 pr_err("ato must be 0 or 1\n");
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004826 return -EINVAL;
4827 }
4828
Martin K. Petersenea61fca2009-05-15 00:40:33 -04004829 if (scsi_debug_physblk_exp > 15) {
Tomas Winklerc12879702015-07-28 16:54:20 +03004830 pr_err("invalid physblk_exp %u\n", scsi_debug_physblk_exp);
Martin K. Petersenea61fca2009-05-15 00:40:33 -04004831 return -EINVAL;
4832 }
4833
4834 if (scsi_debug_lowest_aligned > 0x3fff) {
Tomas Winklerc12879702015-07-28 16:54:20 +03004835 pr_err("lowest_aligned too big: %u\n",
4836 scsi_debug_lowest_aligned);
Martin K. Petersenea61fca2009-05-15 00:40:33 -04004837 return -EINVAL;
4838 }
4839
Linus Torvalds1da177e2005-04-16 15:20:36 -07004840 if (scsi_debug_dev_size_mb < 1)
4841 scsi_debug_dev_size_mb = 1; /* force minimum 1 MB ramdisk */
FUJITA Tomonori5f2578e2008-03-30 00:59:57 +09004842 sz = (unsigned long)scsi_debug_dev_size_mb * 1048576;
Martin K. Petersen597136a2008-06-05 00:12:59 -04004843 sdebug_store_sectors = sz / scsi_debug_sector_size;
FUJITA Tomonori28898872008-03-30 00:59:55 +09004844 sdebug_capacity = get_sdebug_capacity();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004845
4846 /* play around with geometry, don't waste too much on track 0 */
4847 sdebug_heads = 8;
4848 sdebug_sectors_per = 32;
4849 if (scsi_debug_dev_size_mb >= 16)
4850 sdebug_heads = 32;
4851 else if (scsi_debug_dev_size_mb >= 256)
4852 sdebug_heads = 64;
4853 sdebug_cylinders_per = (unsigned long)sdebug_capacity /
4854 (sdebug_sectors_per * sdebug_heads);
4855 if (sdebug_cylinders_per >= 1024) {
4856 /* other LLDs do this; implies >= 1GB ram disk ... */
4857 sdebug_heads = 255;
4858 sdebug_sectors_per = 63;
4859 sdebug_cylinders_per = (unsigned long)sdebug_capacity /
4860 (sdebug_sectors_per * sdebug_heads);
4861 }
4862
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004863 if (0 == scsi_debug_fake_rw) {
4864 fake_storep = vmalloc(sz);
4865 if (NULL == fake_storep) {
Tomas Winklerc12879702015-07-28 16:54:20 +03004866 pr_err("out of memory, 1\n");
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004867 return -ENOMEM;
4868 }
4869 memset(fake_storep, 0, sz);
4870 if (scsi_debug_num_parts > 0)
4871 sdebug_build_parts(fake_storep, sz);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004872 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004873
Akinobu Mita7cb69d02013-06-29 17:59:16 +09004874 if (scsi_debug_dix) {
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004875 int dif_size;
4876
4877 dif_size = sdebug_store_sectors * sizeof(struct sd_dif_tuple);
4878 dif_storep = vmalloc(dif_size);
4879
Tomas Winklerc12879702015-07-28 16:54:20 +03004880 pr_err("dif_storep %u bytes @ %p\n", dif_size, dif_storep);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004881
4882 if (dif_storep == NULL) {
Tomas Winklerc12879702015-07-28 16:54:20 +03004883 pr_err("out of mem. (DIX)\n");
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004884 ret = -ENOMEM;
4885 goto free_vm;
4886 }
4887
4888 memset(dif_storep, 0xff, dif_size);
4889 }
4890
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004891 /* Logical Block Provisioning */
4892 if (scsi_debug_lbp()) {
Martin K. Petersen60147592010-08-19 11:49:00 -04004893 scsi_debug_unmap_max_blocks =
4894 clamp(scsi_debug_unmap_max_blocks, 0U, 0xffffffffU);
4895
4896 scsi_debug_unmap_max_desc =
4897 clamp(scsi_debug_unmap_max_desc, 0U, 256U);
4898
4899 scsi_debug_unmap_granularity =
4900 clamp(scsi_debug_unmap_granularity, 1U, 0xffffffffU);
4901
4902 if (scsi_debug_unmap_alignment &&
Akinobu Mitaac170782013-04-16 22:11:56 +09004903 scsi_debug_unmap_granularity <=
4904 scsi_debug_unmap_alignment) {
Tomas Winklerc12879702015-07-28 16:54:20 +03004905 pr_err("ERR: unmap_granularity <= unmap_alignment\n");
Martin K. Petersen44d92692009-10-15 14:45:27 -04004906 return -EINVAL;
4907 }
4908
Akinobu Mitab90ebc32013-04-16 22:11:58 +09004909 map_size = lba_to_map_index(sdebug_store_sectors - 1) + 1;
4910 map_storep = vmalloc(BITS_TO_LONGS(map_size) * sizeof(long));
Martin K. Petersen44d92692009-10-15 14:45:27 -04004911
Tomas Winklerc12879702015-07-28 16:54:20 +03004912 pr_info("%lu provisioning blocks\n", map_size);
Martin K. Petersen44d92692009-10-15 14:45:27 -04004913
4914 if (map_storep == NULL) {
Tomas Winklerc12879702015-07-28 16:54:20 +03004915 pr_err("out of mem. (MAP)\n");
Martin K. Petersen44d92692009-10-15 14:45:27 -04004916 ret = -ENOMEM;
4917 goto free_vm;
4918 }
4919
Akinobu Mitab90ebc32013-04-16 22:11:58 +09004920 bitmap_zero(map_storep, map_size);
Martin K. Petersen44d92692009-10-15 14:45:27 -04004921
4922 /* Map first 1KB for partition table */
4923 if (scsi_debug_num_parts)
4924 map_region(0, 2);
4925 }
4926
Nicholas Bellinger9b906772010-09-06 17:24:28 -07004927 pseudo_primary = root_device_register("pseudo_0");
4928 if (IS_ERR(pseudo_primary)) {
Tomas Winklerc12879702015-07-28 16:54:20 +03004929 pr_warn("root_device_register() error\n");
Nicholas Bellinger9b906772010-09-06 17:24:28 -07004930 ret = PTR_ERR(pseudo_primary);
Randy Dunlap6ecaff72006-07-11 20:53:22 -07004931 goto free_vm;
4932 }
4933 ret = bus_register(&pseudo_lld_bus);
4934 if (ret < 0) {
Tomas Winklerc12879702015-07-28 16:54:20 +03004935 pr_warn("bus_register error: %d\n", ret);
Randy Dunlap6ecaff72006-07-11 20:53:22 -07004936 goto dev_unreg;
4937 }
4938 ret = driver_register(&sdebug_driverfs_driver);
4939 if (ret < 0) {
Tomas Winklerc12879702015-07-28 16:54:20 +03004940 pr_warn("driver_register error: %d\n", ret);
Randy Dunlap6ecaff72006-07-11 20:53:22 -07004941 goto bus_unreg;
4942 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004943
Linus Torvalds1da177e2005-04-16 15:20:36 -07004944 host_to_add = scsi_debug_add_host;
4945 scsi_debug_add_host = 0;
4946
4947 for (k = 0; k < host_to_add; k++) {
4948 if (sdebug_add_adapter()) {
Tomas Winklerc12879702015-07-28 16:54:20 +03004949 pr_err("sdebug_add_adapter failed k=%d\n", k);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004950 break;
4951 }
4952 }
4953
Tomas Winklerc12879702015-07-28 16:54:20 +03004954 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
4955 pr_info("built %d host(s)\n", scsi_debug_add_host);
4956
Linus Torvalds1da177e2005-04-16 15:20:36 -07004957 return 0;
Randy Dunlap6ecaff72006-07-11 20:53:22 -07004958
Randy Dunlap6ecaff72006-07-11 20:53:22 -07004959bus_unreg:
4960 bus_unregister(&pseudo_lld_bus);
4961dev_unreg:
Nicholas Bellinger9b906772010-09-06 17:24:28 -07004962 root_device_unregister(pseudo_primary);
Randy Dunlap6ecaff72006-07-11 20:53:22 -07004963free_vm:
Tomas Winklerde232af2015-07-28 16:54:22 +03004964 vfree(map_storep);
4965 vfree(dif_storep);
Randy Dunlap6ecaff72006-07-11 20:53:22 -07004966 vfree(fake_storep);
4967
4968 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004969}
4970
4971static void __exit scsi_debug_exit(void)
4972{
4973 int k = scsi_debug_add_host;
4974
4975 stop_all_queued();
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004976 free_all_queued();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004977 for (; k; k--)
4978 sdebug_remove_adapter();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004979 driver_unregister(&sdebug_driverfs_driver);
4980 bus_unregister(&pseudo_lld_bus);
Nicholas Bellinger9b906772010-09-06 17:24:28 -07004981 root_device_unregister(pseudo_primary);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004982
Tomas Winklerde232af2015-07-28 16:54:22 +03004983 vfree(dif_storep);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004984 vfree(fake_storep);
4985}
4986
4987device_initcall(scsi_debug_init);
4988module_exit(scsi_debug_exit);
4989
Linus Torvalds1da177e2005-04-16 15:20:36 -07004990static void sdebug_release_adapter(struct device * dev)
4991{
4992 struct sdebug_host_info *sdbg_host;
4993
4994 sdbg_host = to_sdebug_host(dev);
4995 kfree(sdbg_host);
4996}
4997
4998static int sdebug_add_adapter(void)
4999{
5000 int k, devs_per_host;
5001 int error = 0;
5002 struct sdebug_host_info *sdbg_host;
FUJITA Tomonori8b40228f2008-03-20 11:09:18 +09005003 struct sdebug_dev_info *sdbg_devinfo, *tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005004
Douglas Gilbertc65b1442006-06-06 00:11:24 -04005005 sdbg_host = kzalloc(sizeof(*sdbg_host),GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005006 if (NULL == sdbg_host) {
Tomas Winklerc12879702015-07-28 16:54:20 +03005007 pr_err("out of memory at line %d\n", __LINE__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005008 return -ENOMEM;
5009 }
5010
Linus Torvalds1da177e2005-04-16 15:20:36 -07005011 INIT_LIST_HEAD(&sdbg_host->dev_info_list);
5012
5013 devs_per_host = scsi_debug_num_tgts * scsi_debug_max_luns;
5014 for (k = 0; k < devs_per_host; k++) {
FUJITA Tomonori5cb2fc02008-03-20 11:09:16 +09005015 sdbg_devinfo = sdebug_device_create(sdbg_host, GFP_KERNEL);
5016 if (!sdbg_devinfo) {
Tomas Winklerc12879702015-07-28 16:54:20 +03005017 pr_err("out of memory at line %d\n", __LINE__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005018 error = -ENOMEM;
5019 goto clean;
5020 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005021 }
5022
5023 spin_lock(&sdebug_host_list_lock);
5024 list_add_tail(&sdbg_host->host_list, &sdebug_host_list);
5025 spin_unlock(&sdebug_host_list_lock);
5026
5027 sdbg_host->dev.bus = &pseudo_lld_bus;
Nicholas Bellinger9b906772010-09-06 17:24:28 -07005028 sdbg_host->dev.parent = pseudo_primary;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005029 sdbg_host->dev.release = &sdebug_release_adapter;
Kay Sievers71610f52008-12-03 22:41:36 +01005030 dev_set_name(&sdbg_host->dev, "adapter%d", scsi_debug_add_host);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005031
5032 error = device_register(&sdbg_host->dev);
5033
5034 if (error)
5035 goto clean;
5036
5037 ++scsi_debug_add_host;
5038 return error;
5039
5040clean:
FUJITA Tomonori8b40228f2008-03-20 11:09:18 +09005041 list_for_each_entry_safe(sdbg_devinfo, tmp, &sdbg_host->dev_info_list,
5042 dev_list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005043 list_del(&sdbg_devinfo->dev_list);
5044 kfree(sdbg_devinfo);
5045 }
5046
5047 kfree(sdbg_host);
5048 return error;
5049}
5050
5051static void sdebug_remove_adapter(void)
5052{
5053 struct sdebug_host_info * sdbg_host = NULL;
5054
5055 spin_lock(&sdebug_host_list_lock);
5056 if (!list_empty(&sdebug_host_list)) {
5057 sdbg_host = list_entry(sdebug_host_list.prev,
5058 struct sdebug_host_info, host_list);
5059 list_del(&sdbg_host->host_list);
5060 }
5061 spin_unlock(&sdebug_host_list_lock);
5062
5063 if (!sdbg_host)
5064 return;
5065
5066 device_unregister(&sdbg_host->dev);
5067 --scsi_debug_add_host;
5068}
5069
Douglas Gilbertcbf67842014-07-26 11:55:35 -04005070static int
Christoph Hellwigdb5ed4d2014-11-13 15:08:42 +01005071sdebug_change_qdepth(struct scsi_device *sdev, int qdepth)
Douglas Gilbertcbf67842014-07-26 11:55:35 -04005072{
5073 int num_in_q = 0;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04005074 unsigned long iflags;
5075 struct sdebug_dev_info *devip;
5076
5077 spin_lock_irqsave(&queued_arr_lock, iflags);
5078 devip = (struct sdebug_dev_info *)sdev->hostdata;
5079 if (NULL == devip) {
5080 spin_unlock_irqrestore(&queued_arr_lock, iflags);
5081 return -ENODEV;
5082 }
5083 num_in_q = atomic_read(&devip->num_in_q);
5084 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04005085
Christoph Hellwigc40ecc12014-11-13 14:25:11 +01005086 if (qdepth < 1)
5087 qdepth = 1;
5088 /* allow to exceed max host queued_arr elements for testing */
5089 if (qdepth > SCSI_DEBUG_CANQUEUE + 10)
5090 qdepth = SCSI_DEBUG_CANQUEUE + 10;
Christoph Hellwigdb5ed4d2014-11-13 15:08:42 +01005091 scsi_change_queue_depth(sdev, qdepth);
Christoph Hellwigc40ecc12014-11-13 14:25:11 +01005092
5093 if (SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts) {
5094 sdev_printk(KERN_INFO, sdev,
5095 "%s: qdepth=%d, num_in_q=%d\n",
5096 __func__, qdepth, num_in_q);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04005097 }
5098 return sdev->queue_depth;
5099}
5100
5101static int
Douglas Gilbert817fd662014-11-24 20:18:02 -05005102check_inject(struct scsi_cmnd *scp)
5103{
5104 struct sdebug_scmd_extra_t *ep = scsi_cmd_priv(scp);
5105
5106 memset(ep, 0, sizeof(struct sdebug_scmd_extra_t));
5107
5108 if (atomic_inc_return(&sdebug_cmnd_count) >=
5109 abs(scsi_debug_every_nth)) {
5110 atomic_set(&sdebug_cmnd_count, 0);
5111 if (scsi_debug_every_nth < -1)
5112 scsi_debug_every_nth = -1;
5113 if (SCSI_DEBUG_OPT_TIMEOUT & scsi_debug_opts)
5114 return 1; /* ignore command causing timeout */
5115 else if (SCSI_DEBUG_OPT_MAC_TIMEOUT & scsi_debug_opts &&
5116 scsi_medium_access_command(scp))
5117 return 1; /* time out reads and writes */
5118 if (sdebug_any_injecting_opt) {
5119 int opts = scsi_debug_opts;
5120
5121 if (SCSI_DEBUG_OPT_RECOVERED_ERR & opts)
5122 ep->inj_recovered = true;
5123 else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & opts)
5124 ep->inj_transport = true;
5125 else if (SCSI_DEBUG_OPT_DIF_ERR & opts)
5126 ep->inj_dif = true;
5127 else if (SCSI_DEBUG_OPT_DIX_ERR & opts)
5128 ep->inj_dix = true;
5129 else if (SCSI_DEBUG_OPT_SHORT_TRANSFER & opts)
5130 ep->inj_short = true;
5131 }
5132 }
5133 return 0;
5134}
5135
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05005136static int
5137scsi_debug_queuecommand(struct scsi_cmnd *scp)
5138{
5139 u8 sdeb_i;
5140 struct scsi_device *sdp = scp->device;
5141 const struct opcode_info_t *oip;
5142 const struct opcode_info_t *r_oip;
5143 struct sdebug_dev_info *devip;
5144 u8 *cmd = scp->cmnd;
5145 int (*r_pfp)(struct scsi_cmnd *, struct sdebug_dev_info *);
5146 int k, na;
5147 int errsts = 0;
5148 int errsts_no_connect = DID_NO_CONNECT << 16;
5149 u32 flags;
5150 u16 sa;
5151 u8 opcode = cmd[0];
5152 bool has_wlun_rl;
5153 bool debug = !!(SCSI_DEBUG_OPT_NOISE & scsi_debug_opts);
5154
5155 scsi_set_resid(scp, 0);
5156 if (debug && !(SCSI_DEBUG_OPT_NO_CDB_NOISE & scsi_debug_opts)) {
5157 char b[120];
5158 int n, len, sb;
5159
5160 len = scp->cmd_len;
5161 sb = (int)sizeof(b);
5162 if (len > 32)
5163 strcpy(b, "too long, over 32 bytes");
5164 else {
5165 for (k = 0, n = 0; k < len && n < sb; ++k)
5166 n += scnprintf(b + n, sb - n, "%02x ",
5167 (u32)cmd[k]);
5168 }
5169 sdev_printk(KERN_INFO, sdp, "%s: cmd %s\n", my_name, b);
5170 }
Tomas Winkler34d55432015-07-28 16:54:21 +03005171 has_wlun_rl = (sdp->lun == SCSI_W_LUN_REPORT_LUNS);
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05005172 if ((sdp->lun >= scsi_debug_max_luns) && !has_wlun_rl)
5173 return schedule_resp(scp, NULL, errsts_no_connect, 0);
5174
5175 sdeb_i = opcode_ind_arr[opcode]; /* fully mapped */
5176 oip = &opcode_info_arr[sdeb_i]; /* safe if table consistent */
5177 devip = (struct sdebug_dev_info *)sdp->hostdata;
5178 if (!devip) {
5179 devip = devInfoReg(sdp);
5180 if (NULL == devip)
5181 return schedule_resp(scp, NULL, errsts_no_connect, 0);
5182 }
5183 na = oip->num_attached;
5184 r_pfp = oip->pfp;
5185 if (na) { /* multiple commands with this opcode */
5186 r_oip = oip;
5187 if (FF_SA & r_oip->flags) {
5188 if (F_SA_LOW & oip->flags)
5189 sa = 0x1f & cmd[1];
5190 else
5191 sa = get_unaligned_be16(cmd + 8);
5192 for (k = 0; k <= na; oip = r_oip->arrp + k++) {
5193 if (opcode == oip->opcode && sa == oip->sa)
5194 break;
5195 }
5196 } else { /* since no service action only check opcode */
5197 for (k = 0; k <= na; oip = r_oip->arrp + k++) {
5198 if (opcode == oip->opcode)
5199 break;
5200 }
5201 }
5202 if (k > na) {
5203 if (F_SA_LOW & r_oip->flags)
5204 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 1, 4);
5205 else if (F_SA_HIGH & r_oip->flags)
5206 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 8, 7);
5207 else
5208 mk_sense_invalid_opcode(scp);
5209 goto check_cond;
5210 }
5211 } /* else (when na==0) we assume the oip is a match */
5212 flags = oip->flags;
5213 if (F_INV_OP & flags) {
5214 mk_sense_invalid_opcode(scp);
5215 goto check_cond;
5216 }
5217 if (has_wlun_rl && !(F_RL_WLUN_OK & flags)) {
5218 if (debug)
5219 sdev_printk(KERN_INFO, sdp, "scsi_debug: Opcode: "
5220 "0x%x not supported for wlun\n", opcode);
5221 mk_sense_invalid_opcode(scp);
5222 goto check_cond;
5223 }
5224 if (scsi_debug_strict) { /* check cdb against mask */
5225 u8 rem;
5226 int j;
5227
5228 for (k = 1; k < oip->len_mask[0] && k < 16; ++k) {
5229 rem = ~oip->len_mask[k] & cmd[k];
5230 if (rem) {
5231 for (j = 7; j >= 0; --j, rem <<= 1) {
5232 if (0x80 & rem)
5233 break;
5234 }
5235 mk_sense_invalid_fld(scp, SDEB_IN_CDB, k, j);
5236 goto check_cond;
5237 }
5238 }
5239 }
5240 if (!(F_SKIP_UA & flags) &&
5241 SDEBUG_NUM_UAS != find_first_bit(devip->uas_bm, SDEBUG_NUM_UAS)) {
5242 errsts = check_readiness(scp, UAS_ONLY, devip);
5243 if (errsts)
5244 goto check_cond;
5245 }
5246 if ((F_M_ACCESS & flags) && devip->stopped) {
5247 mk_sense_buffer(scp, NOT_READY, LOGICAL_UNIT_NOT_READY, 0x2);
5248 if (debug)
5249 sdev_printk(KERN_INFO, sdp, "%s reports: Not ready: "
5250 "%s\n", my_name, "initializing command "
5251 "required");
5252 errsts = check_condition_result;
5253 goto fini;
5254 }
5255 if (scsi_debug_fake_rw && (F_FAKE_RW & flags))
5256 goto fini;
5257 if (scsi_debug_every_nth) {
5258 if (check_inject(scp))
5259 return 0; /* ignore command: make trouble */
5260 }
5261 if (oip->pfp) /* if this command has a resp_* function, call it */
5262 errsts = oip->pfp(scp, devip);
5263 else if (r_pfp) /* if leaf function ptr NULL, try the root's */
5264 errsts = r_pfp(scp, devip);
5265
5266fini:
5267 return schedule_resp(scp, devip, errsts,
5268 ((F_DELAY_OVERR & flags) ? 0 : scsi_debug_delay));
5269check_cond:
5270 return schedule_resp(scp, devip, check_condition_result, 0);
5271}
5272
Douglas Gilbert38d5c832014-11-24 21:27:12 -05005273static int
5274sdebug_queuecommand_lock_or_not(struct Scsi_Host *shost, struct scsi_cmnd *cmd)
5275{
5276 if (scsi_debug_host_lock) {
5277 unsigned long iflags;
5278 int rc;
5279
5280 spin_lock_irqsave(shost->host_lock, iflags);
5281 rc = scsi_debug_queuecommand(cmd);
5282 spin_unlock_irqrestore(shost->host_lock, iflags);
5283 return rc;
5284 } else
5285 return scsi_debug_queuecommand(cmd);
5286}
5287
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +09005288static struct scsi_host_template sdebug_driver_template = {
Al Viroc8ed5552013-03-31 01:46:06 -04005289 .show_info = scsi_debug_show_info,
5290 .write_info = scsi_debug_write_info,
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +09005291 .proc_name = sdebug_proc_name,
5292 .name = "SCSI DEBUG",
5293 .info = scsi_debug_info,
5294 .slave_alloc = scsi_debug_slave_alloc,
5295 .slave_configure = scsi_debug_slave_configure,
5296 .slave_destroy = scsi_debug_slave_destroy,
5297 .ioctl = scsi_debug_ioctl,
Douglas Gilbertcbf67842014-07-26 11:55:35 -04005298 .queuecommand = sdebug_queuecommand_lock_or_not,
5299 .change_queue_depth = sdebug_change_qdepth,
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +09005300 .eh_abort_handler = scsi_debug_abort,
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +09005301 .eh_device_reset_handler = scsi_debug_device_reset,
Douglas Gilbertcbf67842014-07-26 11:55:35 -04005302 .eh_target_reset_handler = scsi_debug_target_reset,
5303 .eh_bus_reset_handler = scsi_debug_bus_reset,
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +09005304 .eh_host_reset_handler = scsi_debug_host_reset,
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +09005305 .can_queue = SCSI_DEBUG_CANQUEUE,
5306 .this_id = 7,
Akinobu Mita6bb5e6e2014-06-02 22:56:49 +09005307 .sg_tablesize = SCSI_MAX_SG_CHAIN_SEGMENTS,
Douglas Gilbertcbf67842014-07-26 11:55:35 -04005308 .cmd_per_lun = DEF_CMD_PER_LUN,
Akinobu Mita6bb5e6e2014-06-02 22:56:49 +09005309 .max_sectors = -1U,
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +09005310 .use_clustering = DISABLE_CLUSTERING,
5311 .module = THIS_MODULE,
Christoph Hellwigc40ecc12014-11-13 14:25:11 +01005312 .track_queue_depth = 1,
Douglas Gilbert817fd662014-11-24 20:18:02 -05005313 .cmd_size = sizeof(struct sdebug_scmd_extra_t),
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +09005314};
5315
Linus Torvalds1da177e2005-04-16 15:20:36 -07005316static int sdebug_driver_probe(struct device * dev)
5317{
Douglas Gilbert22017ed2014-11-24 23:04:47 -05005318 int error = 0;
Douglas Gilbert817fd662014-11-24 20:18:02 -05005319 int opts;
Douglas Gilbert22017ed2014-11-24 23:04:47 -05005320 struct sdebug_host_info *sdbg_host;
5321 struct Scsi_Host *hpnt;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05005322 int host_prot;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005323
5324 sdbg_host = to_sdebug_host(dev);
5325
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04005326 sdebug_driver_template.can_queue = scsi_debug_max_queue;
Akinobu Mita0759c662014-02-26 22:57:04 +09005327 if (scsi_debug_clustering)
5328 sdebug_driver_template.use_clustering = ENABLE_CLUSTERING;
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04005329 hpnt = scsi_host_alloc(&sdebug_driver_template, sizeof(sdbg_host));
5330 if (NULL == hpnt) {
Tomas Winklerc12879702015-07-28 16:54:20 +03005331 pr_err("scsi_host_alloc failed\n");
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04005332 error = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005333 return error;
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04005334 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005335
5336 sdbg_host->shost = hpnt;
5337 *((struct sdebug_host_info **)hpnt->hostdata) = sdbg_host;
5338 if ((hpnt->this_id >= 0) && (scsi_debug_num_tgts > hpnt->this_id))
5339 hpnt->max_id = scsi_debug_num_tgts + 1;
5340 else
5341 hpnt->max_id = scsi_debug_num_tgts;
Tomas Winklerf2d3fd22015-07-28 16:54:25 +03005342 /* = scsi_debug_max_luns; */
5343 hpnt->max_lun = SCSI_W_LUN_REPORT_LUNS + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005344
Martin K. Petersenc6a44282009-01-04 03:08:19 -05005345 host_prot = 0;
5346
5347 switch (scsi_debug_dif) {
5348
5349 case SD_DIF_TYPE1_PROTECTION:
5350 host_prot = SHOST_DIF_TYPE1_PROTECTION;
5351 if (scsi_debug_dix)
5352 host_prot |= SHOST_DIX_TYPE1_PROTECTION;
5353 break;
5354
5355 case SD_DIF_TYPE2_PROTECTION:
5356 host_prot = SHOST_DIF_TYPE2_PROTECTION;
5357 if (scsi_debug_dix)
5358 host_prot |= SHOST_DIX_TYPE2_PROTECTION;
5359 break;
5360
5361 case SD_DIF_TYPE3_PROTECTION:
5362 host_prot = SHOST_DIF_TYPE3_PROTECTION;
5363 if (scsi_debug_dix)
5364 host_prot |= SHOST_DIX_TYPE3_PROTECTION;
5365 break;
5366
5367 default:
5368 if (scsi_debug_dix)
5369 host_prot |= SHOST_DIX_TYPE0_PROTECTION;
5370 break;
5371 }
5372
5373 scsi_host_set_prot(hpnt, host_prot);
5374
Tomas Winklerc12879702015-07-28 16:54:20 +03005375 pr_info("host protection%s%s%s%s%s%s%s\n",
Martin K. Petersenc6a44282009-01-04 03:08:19 -05005376 (host_prot & SHOST_DIF_TYPE1_PROTECTION) ? " DIF1" : "",
5377 (host_prot & SHOST_DIF_TYPE2_PROTECTION) ? " DIF2" : "",
5378 (host_prot & SHOST_DIF_TYPE3_PROTECTION) ? " DIF3" : "",
5379 (host_prot & SHOST_DIX_TYPE0_PROTECTION) ? " DIX0" : "",
5380 (host_prot & SHOST_DIX_TYPE1_PROTECTION) ? " DIX1" : "",
5381 (host_prot & SHOST_DIX_TYPE2_PROTECTION) ? " DIX2" : "",
5382 (host_prot & SHOST_DIX_TYPE3_PROTECTION) ? " DIX3" : "");
5383
5384 if (scsi_debug_guard == 1)
5385 scsi_host_set_guard(hpnt, SHOST_DIX_GUARD_IP);
5386 else
5387 scsi_host_set_guard(hpnt, SHOST_DIX_GUARD_CRC);
5388
Douglas Gilbert817fd662014-11-24 20:18:02 -05005389 opts = scsi_debug_opts;
5390 if (SCSI_DEBUG_OPT_RECOVERED_ERR & opts)
5391 sdebug_any_injecting_opt = true;
5392 else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & opts)
5393 sdebug_any_injecting_opt = true;
5394 else if (SCSI_DEBUG_OPT_DIF_ERR & opts)
5395 sdebug_any_injecting_opt = true;
5396 else if (SCSI_DEBUG_OPT_DIX_ERR & opts)
5397 sdebug_any_injecting_opt = true;
5398 else if (SCSI_DEBUG_OPT_SHORT_TRANSFER & opts)
5399 sdebug_any_injecting_opt = true;
5400
Linus Torvalds1da177e2005-04-16 15:20:36 -07005401 error = scsi_add_host(hpnt, &sdbg_host->dev);
5402 if (error) {
Tomas Winklerc12879702015-07-28 16:54:20 +03005403 pr_err("scsi_add_host failed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005404 error = -ENODEV;
5405 scsi_host_put(hpnt);
5406 } else
5407 scsi_scan_host(hpnt);
5408
Douglas Gilbertcbf67842014-07-26 11:55:35 -04005409 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005410}
5411
5412static int sdebug_driver_remove(struct device * dev)
5413{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005414 struct sdebug_host_info *sdbg_host;
FUJITA Tomonori8b40228f2008-03-20 11:09:18 +09005415 struct sdebug_dev_info *sdbg_devinfo, *tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005416
5417 sdbg_host = to_sdebug_host(dev);
5418
5419 if (!sdbg_host) {
Tomas Winklerc12879702015-07-28 16:54:20 +03005420 pr_err("Unable to locate host info\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005421 return -ENODEV;
5422 }
5423
5424 scsi_remove_host(sdbg_host->shost);
5425
FUJITA Tomonori8b40228f2008-03-20 11:09:18 +09005426 list_for_each_entry_safe(sdbg_devinfo, tmp, &sdbg_host->dev_info_list,
5427 dev_list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005428 list_del(&sdbg_devinfo->dev_list);
5429 kfree(sdbg_devinfo);
5430 }
5431
5432 scsi_host_put(sdbg_host->shost);
5433 return 0;
5434}
5435
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09005436static int pseudo_lld_bus_match(struct device *dev,
5437 struct device_driver *dev_driver)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005438{
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09005439 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005440}
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09005441
5442static struct bus_type pseudo_lld_bus = {
5443 .name = "pseudo",
5444 .match = pseudo_lld_bus_match,
5445 .probe = sdebug_driver_probe,
5446 .remove = sdebug_driver_remove,
Akinobu Mita82069372013-10-14 22:48:04 +09005447 .drv_groups = sdebug_drv_groups,
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09005448};