blob: 6e6bf0f03cf7ae508694a2da886da28aba4c72d5 [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
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400207#define SAM2_WLUN_REPORT_LUNS 0xc101
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400209/* SCSI_DEBUG_CANQUEUE is the maximum number of commands that can be queued
210 * (for response) at one time. Can be reduced by max_queue option. Command
211 * responses are not queued when delay=0 and ndelay=0. The per-device
212 * DEF_CMD_PER_LUN can be changed via sysfs:
213 * /sys/class/scsi_device/<h:c:t:l>/device/queue_depth but cannot exceed
214 * SCSI_DEBUG_CANQUEUE. */
215#define SCSI_DEBUG_CANQUEUE_WORDS 9 /* a WORD is bits in a long */
216#define SCSI_DEBUG_CANQUEUE (SCSI_DEBUG_CANQUEUE_WORDS * BITS_PER_LONG)
217#define DEF_CMD_PER_LUN 255
218
219#if DEF_CMD_PER_LUN > SCSI_DEBUG_CANQUEUE
220#warning "Expect DEF_CMD_PER_LUN <= SCSI_DEBUG_CANQUEUE"
221#endif
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -0400222
Douglas Gilbertc2248fc2014-11-24 20:46:29 -0500223/* SCSI opcodes (first byte of cdb) mapped onto these indexes */
224enum sdeb_opcode_index {
225 SDEB_I_INVALID_OPCODE = 0,
226 SDEB_I_INQUIRY = 1,
227 SDEB_I_REPORT_LUNS = 2,
228 SDEB_I_REQUEST_SENSE = 3,
229 SDEB_I_TEST_UNIT_READY = 4,
230 SDEB_I_MODE_SENSE = 5, /* 6, 10 */
231 SDEB_I_MODE_SELECT = 6, /* 6, 10 */
232 SDEB_I_LOG_SENSE = 7,
233 SDEB_I_READ_CAPACITY = 8, /* 10; 16 is in SA_IN(16) */
234 SDEB_I_READ = 9, /* 6, 10, 12, 16 */
235 SDEB_I_WRITE = 10, /* 6, 10, 12, 16 */
236 SDEB_I_START_STOP = 11,
237 SDEB_I_SERV_ACT_IN = 12, /* 12, 16 */
238 SDEB_I_SERV_ACT_OUT = 13, /* 12, 16 */
239 SDEB_I_MAINT_IN = 14,
240 SDEB_I_MAINT_OUT = 15,
241 SDEB_I_VERIFY = 16, /* 10 only */
242 SDEB_I_VARIABLE_LEN = 17,
243 SDEB_I_RESERVE = 18, /* 6, 10 */
244 SDEB_I_RELEASE = 19, /* 6, 10 */
245 SDEB_I_ALLOW_REMOVAL = 20, /* PREVENT ALLOW MEDIUM REMOVAL */
246 SDEB_I_REZERO_UNIT = 21, /* REWIND in SSC */
247 SDEB_I_ATA_PT = 22, /* 12, 16 */
248 SDEB_I_SEND_DIAG = 23,
249 SDEB_I_UNMAP = 24,
250 SDEB_I_XDWRITEREAD = 25, /* 10 only */
251 SDEB_I_WRITE_BUFFER = 26,
252 SDEB_I_WRITE_SAME = 27, /* 10, 16 */
253 SDEB_I_SYNC_CACHE = 28, /* 10 only */
254 SDEB_I_COMP_WRITE = 29,
255 SDEB_I_LAST_ELEMENT = 30, /* keep this last */
256};
257
258static const unsigned char opcode_ind_arr[256] = {
259/* 0x0; 0x0->0x1f: 6 byte cdbs */
260 SDEB_I_TEST_UNIT_READY, SDEB_I_REZERO_UNIT, 0, SDEB_I_REQUEST_SENSE,
261 0, 0, 0, 0,
262 SDEB_I_READ, 0, SDEB_I_WRITE, 0, 0, 0, 0, 0,
263 0, 0, SDEB_I_INQUIRY, 0, 0, SDEB_I_MODE_SELECT, SDEB_I_RESERVE,
264 SDEB_I_RELEASE,
265 0, 0, SDEB_I_MODE_SENSE, SDEB_I_START_STOP, 0, SDEB_I_SEND_DIAG,
266 SDEB_I_ALLOW_REMOVAL, 0,
267/* 0x20; 0x20->0x3f: 10 byte cdbs */
268 0, 0, 0, 0, 0, SDEB_I_READ_CAPACITY, 0, 0,
269 SDEB_I_READ, 0, SDEB_I_WRITE, 0, 0, 0, 0, SDEB_I_VERIFY,
270 0, 0, 0, 0, 0, SDEB_I_SYNC_CACHE, 0, 0,
271 0, 0, 0, SDEB_I_WRITE_BUFFER, 0, 0, 0, 0,
272/* 0x40; 0x40->0x5f: 10 byte cdbs */
273 0, SDEB_I_WRITE_SAME, SDEB_I_UNMAP, 0, 0, 0, 0, 0,
274 0, 0, 0, 0, 0, SDEB_I_LOG_SENSE, 0, 0,
275 0, 0, 0, SDEB_I_XDWRITEREAD, 0, SDEB_I_MODE_SELECT, SDEB_I_RESERVE,
276 SDEB_I_RELEASE,
277 0, 0, SDEB_I_MODE_SENSE, 0, 0, 0, 0, 0,
278/* 0x60; 0x60->0x7d are reserved */
279 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
280 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
281 0, SDEB_I_VARIABLE_LEN,
282/* 0x80; 0x80->0x9f: 16 byte cdbs */
283 0, 0, 0, 0, 0, SDEB_I_ATA_PT, 0, 0,
284 SDEB_I_READ, SDEB_I_COMP_WRITE, SDEB_I_WRITE, 0, 0, 0, 0, 0,
285 0, 0, 0, SDEB_I_WRITE_SAME, 0, 0, 0, 0,
286 0, 0, 0, 0, 0, 0, SDEB_I_SERV_ACT_IN, SDEB_I_SERV_ACT_OUT,
287/* 0xa0; 0xa0->0xbf: 12 byte cdbs */
288 SDEB_I_REPORT_LUNS, SDEB_I_ATA_PT, 0, SDEB_I_MAINT_IN,
289 SDEB_I_MAINT_OUT, 0, 0, 0,
290 SDEB_I_READ, SDEB_I_SERV_ACT_OUT, SDEB_I_WRITE, SDEB_I_SERV_ACT_IN,
291 0, 0, 0, 0,
292 0, 0, 0, 0, 0, 0, 0, 0,
293 0, 0, 0, 0, 0, 0, 0, 0,
294/* 0xc0; 0xc0->0xff: vendor specific */
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 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
299};
300
301#define F_D_IN 1
302#define F_D_OUT 2
303#define F_D_OUT_MAYBE 4 /* WRITE SAME, NDOB bit */
304#define F_D_UNKN 8
305#define F_RL_WLUN_OK 0x10
306#define F_SKIP_UA 0x20
307#define F_DELAY_OVERR 0x40
308#define F_SA_LOW 0x80 /* cdb byte 1, bits 4 to 0 */
309#define F_SA_HIGH 0x100 /* as used by variable length cdbs */
310#define F_INV_OP 0x200
311#define F_FAKE_RW 0x400
312#define F_M_ACCESS 0x800 /* media access */
313
314#define FF_RESPOND (F_RL_WLUN_OK | F_SKIP_UA | F_DELAY_OVERR)
315#define FF_DIRECT_IO (F_M_ACCESS | F_FAKE_RW)
316#define FF_SA (F_SA_HIGH | F_SA_LOW)
317
318struct sdebug_dev_info;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -0500319static int resp_inquiry(struct scsi_cmnd *, struct sdebug_dev_info *);
320static int resp_report_luns(struct scsi_cmnd *, struct sdebug_dev_info *);
321static int resp_requests(struct scsi_cmnd *, struct sdebug_dev_info *);
322static int resp_mode_sense(struct scsi_cmnd *, struct sdebug_dev_info *);
323static int resp_mode_select(struct scsi_cmnd *, struct sdebug_dev_info *);
324static int resp_log_sense(struct scsi_cmnd *, struct sdebug_dev_info *);
325static int resp_readcap(struct scsi_cmnd *, struct sdebug_dev_info *);
326static int resp_read_dt0(struct scsi_cmnd *, struct sdebug_dev_info *);
327static int resp_write_dt0(struct scsi_cmnd *, struct sdebug_dev_info *);
328static int resp_start_stop(struct scsi_cmnd *, struct sdebug_dev_info *);
329static int resp_readcap16(struct scsi_cmnd *, struct sdebug_dev_info *);
330static int resp_get_lba_status(struct scsi_cmnd *, struct sdebug_dev_info *);
331static int resp_report_tgtpgs(struct scsi_cmnd *, struct sdebug_dev_info *);
332static int resp_unmap(struct scsi_cmnd *, struct sdebug_dev_info *);
Douglas Gilbert38d5c832014-11-24 21:27:12 -0500333static int resp_rsup_opcodes(struct scsi_cmnd *, struct sdebug_dev_info *);
334static int resp_rsup_tmfs(struct scsi_cmnd *, struct sdebug_dev_info *);
Douglas Gilbertc2248fc2014-11-24 20:46:29 -0500335static int resp_write_same_10(struct scsi_cmnd *, struct sdebug_dev_info *);
336static int resp_write_same_16(struct scsi_cmnd *, struct sdebug_dev_info *);
337static int resp_xdwriteread_10(struct scsi_cmnd *, struct sdebug_dev_info *);
Douglas Gilbert38d5c832014-11-24 21:27:12 -0500338static int resp_comp_write(struct scsi_cmnd *, struct sdebug_dev_info *);
Ewan D. Milneacafd0b2014-12-04 11:49:28 -0500339static int resp_write_buffer(struct scsi_cmnd *, struct sdebug_dev_info *);
Douglas Gilbertc2248fc2014-11-24 20:46:29 -0500340
341struct opcode_info_t {
342 u8 num_attached; /* 0 if this is it (i.e. a leaf); use 0xff
343 * for terminating element */
344 u8 opcode; /* if num_attached > 0, preferred */
345 u16 sa; /* service action */
346 u32 flags; /* OR-ed set of SDEB_F_* */
347 int (*pfp)(struct scsi_cmnd *, struct sdebug_dev_info *);
348 const struct opcode_info_t *arrp; /* num_attached elements or NULL */
349 u8 len_mask[16]; /* len=len_mask[0], then mask for cdb[1]... */
350 /* ignore cdb bytes after position 15 */
351};
352
353static const struct opcode_info_t msense_iarr[1] = {
354 {0, 0x1a, 0, F_D_IN, NULL, NULL,
355 {6, 0xe8, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
356};
357
358static const struct opcode_info_t mselect_iarr[1] = {
359 {0, 0x15, 0, F_D_OUT, NULL, NULL,
360 {6, 0xf1, 0, 0, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
361};
362
363static const struct opcode_info_t read_iarr[3] = {
364 {0, 0x28, 0, F_D_IN | FF_DIRECT_IO, resp_read_dt0, NULL,/* READ(10) */
365 {10, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xc7, 0, 0,
366 0, 0, 0, 0} },
367 {0, 0x8, 0, F_D_IN | FF_DIRECT_IO, resp_read_dt0, NULL, /* READ(6) */
368 {6, 0xff, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
369 {0, 0xa8, 0, F_D_IN | FF_DIRECT_IO, resp_read_dt0, NULL,/* READ(12) */
370 {12, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f,
371 0xc7, 0, 0, 0, 0} },
372};
373
374static const struct opcode_info_t write_iarr[3] = {
375 {0, 0x2a, 0, F_D_OUT | FF_DIRECT_IO, resp_write_dt0, NULL, /* 10 */
376 {10, 0xfb, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xc7, 0, 0,
377 0, 0, 0, 0} },
378 {0, 0xa, 0, F_D_OUT | FF_DIRECT_IO, resp_write_dt0, NULL, /* 6 */
379 {6, 0xff, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
380 {0, 0xaa, 0, F_D_OUT | FF_DIRECT_IO, resp_write_dt0, NULL, /* 12 */
381 {12, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f,
382 0xc7, 0, 0, 0, 0} },
383};
384
385static const struct opcode_info_t sa_in_iarr[1] = {
386 {0, 0x9e, 0x12, F_SA_LOW | F_D_IN, resp_get_lba_status, NULL,
387 {16, 0x12, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
388 0xff, 0xff, 0xff, 0, 0xc7} },
389};
390
391static const struct opcode_info_t vl_iarr[1] = { /* VARIABLE LENGTH */
392 {0, 0x7f, 0xb, F_SA_HIGH | F_D_OUT | FF_DIRECT_IO, resp_write_dt0,
393 NULL, {32, 0xc7, 0, 0, 0, 0, 0x1f, 0x18, 0x0, 0xb, 0xfa,
394 0, 0xff, 0xff, 0xff, 0xff} }, /* WRITE(32) */
395};
396
397static const struct opcode_info_t maint_in_iarr[2] = {
Douglas Gilbert38d5c832014-11-24 21:27:12 -0500398 {0, 0xa3, 0xc, F_SA_LOW | F_D_IN, resp_rsup_opcodes, NULL,
Douglas Gilbertc2248fc2014-11-24 20:46:29 -0500399 {12, 0xc, 0x87, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0,
400 0xc7, 0, 0, 0, 0} },
Douglas Gilbert38d5c832014-11-24 21:27:12 -0500401 {0, 0xa3, 0xd, F_SA_LOW | F_D_IN, resp_rsup_tmfs, NULL,
Douglas Gilbertc2248fc2014-11-24 20:46:29 -0500402 {12, 0xd, 0x80, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0, 0xc7, 0, 0,
403 0, 0} },
404};
405
406static const struct opcode_info_t write_same_iarr[1] = {
407 {0, 0x93, 0, F_D_OUT_MAYBE | FF_DIRECT_IO, resp_write_same_16, NULL,
408 {16, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
409 0xff, 0xff, 0xff, 0x1f, 0xc7} },
410};
411
412static const struct opcode_info_t reserve_iarr[1] = {
413 {0, 0x16, 0, F_D_OUT, NULL, NULL, /* RESERVE(6) */
414 {6, 0x1f, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
415};
416
417static const struct opcode_info_t release_iarr[1] = {
418 {0, 0x17, 0, F_D_OUT, NULL, NULL, /* RELEASE(6) */
419 {6, 0x1f, 0xff, 0, 0, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
420};
421
422
423/* This array is accessed via SDEB_I_* values. Make sure all are mapped,
424 * plus the terminating elements for logic that scans this table such as
425 * REPORT SUPPORTED OPERATION CODES. */
426static const struct opcode_info_t opcode_info_arr[SDEB_I_LAST_ELEMENT + 1] = {
427/* 0 */
428 {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL,
429 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
430 {0, 0x12, 0, FF_RESPOND | F_D_IN, resp_inquiry, NULL,
431 {6, 0xe3, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
432 {0, 0xa0, 0, FF_RESPOND | F_D_IN, resp_report_luns, NULL,
433 {12, 0xe3, 0xff, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0, 0xc7, 0, 0,
434 0, 0} },
435 {0, 0x3, 0, FF_RESPOND | F_D_IN, resp_requests, NULL,
436 {6, 0xe1, 0, 0, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
437 {0, 0x0, 0, F_M_ACCESS | F_RL_WLUN_OK, NULL, NULL,/* TEST UNIT READY */
438 {6, 0, 0, 0, 0, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
439 {1, 0x5a, 0, F_D_IN, resp_mode_sense, msense_iarr,
440 {10, 0xf8, 0xff, 0xff, 0, 0, 0, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0,
441 0} },
442 {1, 0x55, 0, F_D_OUT, resp_mode_select, mselect_iarr,
443 {10, 0xf1, 0, 0, 0, 0, 0, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0} },
444 {0, 0x4d, 0, F_D_IN, resp_log_sense, NULL,
445 {10, 0xe3, 0xff, 0xff, 0, 0xff, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0,
446 0, 0, 0} },
447 {0, 0x25, 0, F_D_IN, resp_readcap, NULL,
448 {10, 0xe1, 0xff, 0xff, 0xff, 0xff, 0, 0, 0x1, 0xc7, 0, 0, 0, 0,
449 0, 0} },
450 {3, 0x88, 0, F_D_IN | FF_DIRECT_IO, resp_read_dt0, read_iarr,
451 {16, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
452 0xff, 0xff, 0xff, 0x9f, 0xc7} }, /* READ(16) */
453/* 10 */
454 {3, 0x8a, 0, F_D_OUT | FF_DIRECT_IO, resp_write_dt0, write_iarr,
455 {16, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
456 0xff, 0xff, 0xff, 0x9f, 0xc7} }, /* WRITE(16) */
457 {0, 0x1b, 0, 0, resp_start_stop, NULL, /* START STOP UNIT */
458 {6, 0x1, 0, 0xf, 0xf7, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
459 {1, 0x9e, 0x10, F_SA_LOW | F_D_IN, resp_readcap16, sa_in_iarr,
460 {16, 0x10, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
461 0xff, 0xff, 0xff, 0x1, 0xc7} }, /* READ CAPACITY(16) */
462 {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, /* SA OUT */
463 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
464 {2, 0xa3, 0xa, F_SA_LOW | F_D_IN, resp_report_tgtpgs, maint_in_iarr,
465 {12, 0xea, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0, 0xc7, 0, 0, 0,
466 0} },
467 {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, /* MAINT OUT */
468 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
469 {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, /* VERIFY */
470 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
471 {1, 0x7f, 0x9, F_SA_HIGH | F_D_IN | FF_DIRECT_IO, resp_read_dt0,
472 vl_iarr, {32, 0xc7, 0, 0, 0, 0, 0x1f, 0x18, 0x0, 0x9, 0xfe, 0,
473 0xff, 0xff, 0xff, 0xff} },/* VARIABLE LENGTH, READ(32) */
474 {1, 0x56, 0, F_D_OUT, NULL, reserve_iarr, /* RESERVE(10) */
475 {10, 0xff, 0xff, 0xff, 0, 0, 0, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0,
476 0} },
477 {1, 0x57, 0, F_D_OUT, NULL, release_iarr, /* RELEASE(10) */
478 {10, 0x13, 0xff, 0xff, 0, 0, 0, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0,
479 0} },
480/* 20 */
481 {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, /* ALLOW REMOVAL */
482 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
483 {0, 0x1, 0, 0, resp_start_stop, NULL, /* REWIND ?? */
484 {6, 0x1, 0, 0, 0, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
485 {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, /* ATA_PT */
486 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
487 {0, 0x1d, F_D_OUT, 0, NULL, NULL, /* SEND DIAGNOSTIC */
488 {6, 0xf7, 0, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
489 {0, 0x42, 0, F_D_OUT | FF_DIRECT_IO, resp_unmap, NULL, /* UNMAP */
490 {10, 0x1, 0, 0, 0, 0, 0x1f, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0} },
491 {0, 0x53, 0, F_D_IN | F_D_OUT | FF_DIRECT_IO, resp_xdwriteread_10,
492 NULL, {10, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xc7,
493 0, 0, 0, 0, 0, 0} },
Ewan D. Milneacafd0b2014-12-04 11:49:28 -0500494 {0, 0x3b, 0, F_D_OUT_MAYBE, resp_write_buffer, NULL,
495 {10, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7, 0, 0,
496 0, 0, 0, 0} }, /* WRITE_BUFFER */
Douglas Gilbertc2248fc2014-11-24 20:46:29 -0500497 {1, 0x41, 0, F_D_OUT_MAYBE | FF_DIRECT_IO, resp_write_same_10,
498 write_same_iarr, {10, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff,
499 0xff, 0xc7, 0, 0, 0, 0, 0, 0} },
500 {0, 0x35, 0, F_DELAY_OVERR | FF_DIRECT_IO, NULL, NULL, /* SYNC_CACHE */
501 {10, 0x7, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xc7, 0, 0,
502 0, 0, 0, 0} },
Douglas Gilbert38d5c832014-11-24 21:27:12 -0500503 {0, 0x89, 0, F_D_OUT | FF_DIRECT_IO, resp_comp_write, NULL,
Douglas Gilbertc2248fc2014-11-24 20:46:29 -0500504 {16, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0,
505 0, 0xff, 0x1f, 0xc7} }, /* COMPARE AND WRITE */
506
507/* 30 */
508 {0xff, 0, 0, 0, NULL, NULL, /* terminating element */
509 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
510};
511
Douglas Gilbert817fd662014-11-24 20:18:02 -0500512struct sdebug_scmd_extra_t {
513 bool inj_recovered;
514 bool inj_transport;
515 bool inj_dif;
516 bool inj_dix;
517 bool inj_short;
518};
519
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520static int scsi_debug_add_host = DEF_NUM_HOST;
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500521static int scsi_debug_ato = DEF_ATO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522static int scsi_debug_delay = DEF_DELAY;
523static int scsi_debug_dev_size_mb = DEF_DEV_SIZE_MB;
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500524static int scsi_debug_dif = DEF_DIF;
525static int scsi_debug_dix = DEF_DIX;
526static int scsi_debug_dsense = DEF_D_SENSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527static int scsi_debug_every_nth = DEF_EVERY_NTH;
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500528static int scsi_debug_fake_rw = DEF_FAKE_RW;
Akinobu Mita68aee7b2013-09-18 21:27:27 +0900529static unsigned int scsi_debug_guard = DEF_GUARD;
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500530static int scsi_debug_lowest_aligned = DEF_LOWEST_ALIGNED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531static int scsi_debug_max_luns = DEF_MAX_LUNS;
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -0400532static int scsi_debug_max_queue = SCSI_DEBUG_CANQUEUE;
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400533static atomic_t retired_max_queue; /* if > 0 then was prior max_queue */
534static int scsi_debug_ndelay = DEF_NDELAY;
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400535static int scsi_debug_no_lun_0 = DEF_NO_LUN_0;
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500536static int scsi_debug_no_uld = 0;
537static int scsi_debug_num_parts = DEF_NUM_PARTS;
538static int scsi_debug_num_tgts = DEF_NUM_TGTS; /* targets per host */
Martin K. Petersene308b3d2010-03-23 01:12:27 -0400539static int scsi_debug_opt_blks = DEF_OPT_BLKS;
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500540static int scsi_debug_opts = DEF_OPTS;
541static int scsi_debug_physblk_exp = DEF_PHYSBLK_EXP;
542static int scsi_debug_ptype = DEF_PTYPE; /* SCSI peripheral type (0==disk) */
543static int scsi_debug_scsi_level = DEF_SCSI_LEVEL;
544static int scsi_debug_sector_size = DEF_SECTOR_SIZE;
545static int scsi_debug_virtual_gb = DEF_VIRTUAL_GB;
546static int scsi_debug_vpd_use_hostno = DEF_VPD_USE_HOSTNO;
547static unsigned int scsi_debug_lbpu = DEF_LBPU;
548static unsigned int scsi_debug_lbpws = DEF_LBPWS;
549static unsigned int scsi_debug_lbpws10 = DEF_LBPWS10;
Eric Sandeenbe1dd782012-03-08 00:03:59 -0600550static unsigned int scsi_debug_lbprz = DEF_LBPRZ;
Martin K. Petersen60147592010-08-19 11:49:00 -0400551static unsigned int scsi_debug_unmap_alignment = DEF_UNMAP_ALIGNMENT;
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500552static unsigned int scsi_debug_unmap_granularity = DEF_UNMAP_GRANULARITY;
553static unsigned int scsi_debug_unmap_max_blocks = DEF_UNMAP_MAX_BLOCKS;
554static unsigned int scsi_debug_unmap_max_desc = DEF_UNMAP_MAX_DESC;
555static unsigned int scsi_debug_write_same_length = DEF_WRITESAME_LENGTH;
Martin Pittd9867882012-09-06 12:04:33 +0200556static bool scsi_debug_removable = DEF_REMOVABLE;
Akinobu Mita0759c662014-02-26 22:57:04 +0900557static bool scsi_debug_clustering;
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400558static bool scsi_debug_host_lock = DEF_HOST_LOCK;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -0500559static bool scsi_debug_strict = DEF_STRICT;
Douglas Gilbert817fd662014-11-24 20:18:02 -0500560static bool sdebug_any_injecting_opt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400562static atomic_t sdebug_cmnd_count;
563static atomic_t sdebug_completions;
564static atomic_t sdebug_a_tsf; /* counter of 'almost' TSFs */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565
566#define DEV_READONLY(TGT) (0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400568static unsigned int sdebug_store_sectors;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569static sector_t sdebug_capacity; /* in sectors */
570
571/* old BIOS stuff, kernel may get rid of them but some mode sense pages
572 may still need them */
573static int sdebug_heads; /* heads per disk */
574static int sdebug_cylinders_per; /* cylinders per surface */
575static int sdebug_sectors_per; /* sectors per cylinder */
576
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577#define SDEBUG_MAX_PARTS 4
578
Martin K. Petersen395cef02009-09-18 17:33:03 -0400579#define SCSI_DEBUG_MAX_CMD_LEN 32
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +0900580
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500581static unsigned int scsi_debug_lbp(void)
582{
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400583 return ((0 == scsi_debug_fake_rw) &&
584 (scsi_debug_lbpu | scsi_debug_lbpws | scsi_debug_lbpws10));
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500585}
586
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587struct sdebug_dev_info {
588 struct list_head dev_list;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589 unsigned int channel;
590 unsigned int target;
Hannes Reinecke9cb78c12014-06-25 15:27:36 +0200591 u64 lun;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592 struct sdebug_host_info *sdbg_host;
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400593 unsigned long uas_bm[1];
594 atomic_t num_in_q;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -0500595 char stopped; /* TODO: should be atomic */
596 bool used;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597};
598
599struct sdebug_host_info {
600 struct list_head host_list;
601 struct Scsi_Host *shost;
602 struct device dev;
603 struct list_head dev_info_list;
604};
605
606#define to_sdebug_host(d) \
607 container_of(d, struct sdebug_host_info, dev)
608
609static LIST_HEAD(sdebug_host_list);
610static DEFINE_SPINLOCK(sdebug_host_list_lock);
611
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400612
613struct sdebug_hrtimer { /* ... is derived from hrtimer */
614 struct hrtimer hrt; /* must be first element */
615 int qa_indx;
616};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617
618struct sdebug_queued_cmd {
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400619 /* in_use flagged by a bit in queued_in_use_bm[] */
620 struct timer_list *cmnd_timerp;
621 struct tasklet_struct *tletp;
622 struct sdebug_hrtimer *sd_hrtp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623 struct scsi_cmnd * a_cmnd;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624};
625static struct sdebug_queued_cmd queued_arr[SCSI_DEBUG_CANQUEUE];
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400626static unsigned long queued_in_use_bm[SCSI_DEBUG_CANQUEUE_WORDS];
627
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629static unsigned char * fake_storep; /* ramdisk storage */
Akinobu Mitae18d8be2013-06-29 17:59:18 +0900630static struct sd_dif_tuple *dif_storep; /* protection info */
Martin K. Petersen44d92692009-10-15 14:45:27 -0400631static void *map_storep; /* provisioning map */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632
Martin K. Petersen44d92692009-10-15 14:45:27 -0400633static unsigned long map_size;
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400634static int num_aborts;
635static int num_dev_resets;
636static int num_target_resets;
637static int num_bus_resets;
638static int num_host_resets;
Martin K. Petersenc6a44282009-01-04 03:08:19 -0500639static int dix_writes;
640static int dix_reads;
641static int dif_errors;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642
643static DEFINE_SPINLOCK(queued_arr_lock);
644static DEFINE_RWLOCK(atomic_rw);
645
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400646static char sdebug_proc_name[] = MY_NAME;
647static const char *my_name = MY_NAME;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648
Linus Torvalds1da177e2005-04-16 15:20:36 -0700649static struct bus_type pseudo_lld_bus;
650
651static struct device_driver sdebug_driverfs_driver = {
652 .name = sdebug_proc_name,
653 .bus = &pseudo_lld_bus,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654};
655
656static const int check_condition_result =
657 (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
658
Martin K. Petersenc6a44282009-01-04 03:08:19 -0500659static const int illegal_condition_result =
660 (DRIVER_SENSE << 24) | (DID_ABORT << 16) | SAM_STAT_CHECK_CONDITION;
661
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400662static const int device_qfull_result =
663 (DID_OK << 16) | (COMMAND_COMPLETE << 8) | SAM_STAT_TASK_SET_FULL;
664
665static unsigned char caching_pg[] = {0x8, 18, 0x14, 0, 0xff, 0xff, 0, 0,
666 0xff, 0xff, 0xff, 0xff, 0x80, 0x14, 0, 0,
667 0, 0, 0, 0};
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400668static unsigned char ctrl_m_pg[] = {0xa, 10, 2, 0, 0, 0, 0, 0,
669 0, 0, 0x2, 0x4b};
670static unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0,
671 0, 0, 0x0, 0x0};
672
Akinobu Mita14faa942013-09-18 21:27:24 +0900673static void *fake_store(unsigned long long lba)
674{
675 lba = do_div(lba, sdebug_store_sectors);
676
677 return fake_storep + lba * scsi_debug_sector_size;
678}
679
680static struct sd_dif_tuple *dif_store(sector_t sector)
681{
682 sector = do_div(sector, sdebug_store_sectors);
683
684 return dif_storep + sector;
685}
686
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687static int sdebug_add_adapter(void);
688static void sdebug_remove_adapter(void);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +0900690static void sdebug_max_tgts_luns(void)
691{
692 struct sdebug_host_info *sdbg_host;
693 struct Scsi_Host *hpnt;
694
695 spin_lock(&sdebug_host_list_lock);
696 list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) {
697 hpnt = sdbg_host->shost;
698 if ((hpnt->this_id >= 0) &&
699 (scsi_debug_num_tgts > hpnt->this_id))
700 hpnt->max_id = scsi_debug_num_tgts + 1;
701 else
702 hpnt->max_id = scsi_debug_num_tgts;
703 /* scsi_debug_max_luns; */
704 hpnt->max_lun = SAM2_WLUN_REPORT_LUNS;
705 }
706 spin_unlock(&sdebug_host_list_lock);
707}
708
Douglas Gilbert22017ed2014-11-24 23:04:47 -0500709enum sdeb_cmd_data {SDEB_IN_DATA = 0, SDEB_IN_CDB = 1};
710
711/* Set in_bit to -1 to indicate no bit position of invalid field */
712static void
713mk_sense_invalid_fld(struct scsi_cmnd *scp, enum sdeb_cmd_data c_d,
714 int in_byte, int in_bit)
715{
716 unsigned char *sbuff;
717 u8 sks[4];
718 int sl, asc;
719
720 sbuff = scp->sense_buffer;
721 if (!sbuff) {
722 sdev_printk(KERN_ERR, scp->device,
723 "%s: sense_buffer is NULL\n", __func__);
724 return;
725 }
726 asc = c_d ? INVALID_FIELD_IN_CDB : INVALID_FIELD_IN_PARAM_LIST;
727 memset(sbuff, 0, SCSI_SENSE_BUFFERSIZE);
728 scsi_build_sense_buffer(scsi_debug_dsense, sbuff, ILLEGAL_REQUEST,
729 asc, 0);
730 memset(sks, 0, sizeof(sks));
731 sks[0] = 0x80;
732 if (c_d)
733 sks[0] |= 0x40;
734 if (in_bit >= 0) {
735 sks[0] |= 0x8;
736 sks[0] |= 0x7 & in_bit;
737 }
738 put_unaligned_be16(in_byte, sks + 1);
739 if (scsi_debug_dsense) {
740 sl = sbuff[7] + 8;
741 sbuff[7] = sl;
742 sbuff[sl] = 0x2;
743 sbuff[sl + 1] = 0x6;
744 memcpy(sbuff + sl + 4, sks, 3);
745 } else
746 memcpy(sbuff + 15, sks, 3);
747 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
748 sdev_printk(KERN_INFO, scp->device, "%s: [sense_key,asc,ascq"
749 "]: [0x5,0x%x,0x0] %c byte=%d, bit=%d\n",
750 my_name, asc, c_d ? 'C' : 'D', in_byte, in_bit);
751}
752
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400753static void mk_sense_buffer(struct scsi_cmnd *scp, int key, int asc, int asq)
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +0900754{
755 unsigned char *sbuff;
756
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400757 sbuff = scp->sense_buffer;
758 if (!sbuff) {
759 sdev_printk(KERN_ERR, scp->device,
760 "%s: sense_buffer is NULL\n", __func__);
761 return;
762 }
763 memset(sbuff, 0, SCSI_SENSE_BUFFERSIZE);
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +0900764
765 scsi_build_sense_buffer(scsi_debug_dsense, sbuff, key, asc, asq);
766
767 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400768 sdev_printk(KERN_INFO, scp->device,
769 "%s: [sense_key,asc,ascq]: [0x%x,0x%x,0x%x]\n",
770 my_name, key, asc, asq);
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +0900771}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772
Douglas Gilbert22017ed2014-11-24 23:04:47 -0500773static void
774mk_sense_invalid_opcode(struct scsi_cmnd *scp)
775{
776 mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_OPCODE, 0);
777}
778
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779static int scsi_debug_ioctl(struct scsi_device *dev, int cmd, void __user *arg)
780{
781 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400782 if (0x1261 == cmd)
783 sdev_printk(KERN_INFO, dev,
784 "%s: BLKFLSBUF [0x1261]\n", __func__);
785 else if (0x5331 == cmd)
786 sdev_printk(KERN_INFO, dev,
787 "%s: CDROM_GET_CAPABILITY [0x5331]\n",
788 __func__);
789 else
790 sdev_printk(KERN_INFO, dev, "%s: cmd=0x%x\n",
791 __func__, cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792 }
793 return -EINVAL;
794 /* return -ENOTTY; // correct return but upsets fdisk */
795}
796
Ewan D. Milne19c8ead2014-12-04 11:49:27 -0500797static void clear_luns_changed_on_target(struct sdebug_dev_info *devip)
798{
799 struct sdebug_host_info *sdhp;
800 struct sdebug_dev_info *dp;
801
802 spin_lock(&sdebug_host_list_lock);
803 list_for_each_entry(sdhp, &sdebug_host_list, host_list) {
804 list_for_each_entry(dp, &sdhp->dev_info_list, dev_list) {
805 if ((devip->sdbg_host == dp->sdbg_host) &&
806 (devip->target == dp->target))
807 clear_bit(SDEBUG_UA_LUNS_CHANGED, dp->uas_bm);
808 }
809 }
810 spin_unlock(&sdebug_host_list_lock);
811}
812
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400813static int check_readiness(struct scsi_cmnd *SCpnt, int uas_only,
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400814 struct sdebug_dev_info * devip)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700815{
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400816 int k;
817 bool debug = !!(SCSI_DEBUG_OPT_NOISE & scsi_debug_opts);
818
819 k = find_first_bit(devip->uas_bm, SDEBUG_NUM_UAS);
820 if (k != SDEBUG_NUM_UAS) {
821 const char *cp = NULL;
822
823 switch (k) {
824 case SDEBUG_UA_POR:
825 mk_sense_buffer(SCpnt, UNIT_ATTENTION,
826 UA_RESET_ASC, POWER_ON_RESET_ASCQ);
827 if (debug)
828 cp = "power on reset";
829 break;
830 case SDEBUG_UA_BUS_RESET:
831 mk_sense_buffer(SCpnt, UNIT_ATTENTION,
832 UA_RESET_ASC, BUS_RESET_ASCQ);
833 if (debug)
834 cp = "bus reset";
835 break;
836 case SDEBUG_UA_MODE_CHANGED:
837 mk_sense_buffer(SCpnt, UNIT_ATTENTION,
838 UA_CHANGED_ASC, MODE_CHANGED_ASCQ);
839 if (debug)
840 cp = "mode parameters changed";
841 break;
Douglas Gilbert0d01c5d2014-11-24 20:27:51 -0500842 case SDEBUG_UA_CAPACITY_CHANGED:
843 mk_sense_buffer(SCpnt, UNIT_ATTENTION,
844 UA_CHANGED_ASC, CAPACITY_CHANGED_ASCQ);
845 if (debug)
846 cp = "capacity data changed";
Ewan D. Milnef49accf2014-12-04 11:49:25 -0500847 break;
Ewan D. Milneacafd0b2014-12-04 11:49:28 -0500848 case SDEBUG_UA_MICROCODE_CHANGED:
849 mk_sense_buffer(SCpnt, UNIT_ATTENTION,
850 TARGET_CHANGED_ASC, MICROCODE_CHANGED_ASCQ);
851 if (debug)
852 cp = "microcode has been changed";
853 break;
854 case SDEBUG_UA_MICROCODE_CHANGED_WO_RESET:
855 mk_sense_buffer(SCpnt, UNIT_ATTENTION,
856 TARGET_CHANGED_ASC,
857 MICROCODE_CHANGED_WO_RESET_ASCQ);
858 if (debug)
859 cp = "microcode has been changed without reset";
860 break;
Ewan D. Milne19c8ead2014-12-04 11:49:27 -0500861 case SDEBUG_UA_LUNS_CHANGED:
862 /*
863 * SPC-3 behavior is to report a UNIT ATTENTION with
864 * ASC/ASCQ REPORTED LUNS DATA HAS CHANGED on every LUN
865 * on the target, until a REPORT LUNS command is
866 * received. SPC-4 behavior is to report it only once.
867 * NOTE: scsi_debug_scsi_level does not use the same
868 * values as struct scsi_device->scsi_level.
869 */
870 if (scsi_debug_scsi_level >= 6) /* SPC-4 and above */
871 clear_luns_changed_on_target(devip);
872 mk_sense_buffer(SCpnt, UNIT_ATTENTION,
873 TARGET_CHANGED_ASC,
874 LUNS_CHANGED_ASCQ);
875 if (debug)
876 cp = "reported luns data has changed";
877 break;
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400878 default:
879 pr_warn("%s: unexpected unit attention code=%d\n",
880 __func__, k);
881 if (debug)
882 cp = "unknown";
883 break;
884 }
885 clear_bit(k, devip->uas_bm);
886 if (debug)
887 sdev_printk(KERN_INFO, SCpnt->device,
888 "%s reports: Unit attention: %s\n",
889 my_name, cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890 return check_condition_result;
891 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400892 if ((UAS_TUR == uas_only) && devip->stopped) {
893 mk_sense_buffer(SCpnt, NOT_READY, LOGICAL_UNIT_NOT_READY,
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400894 0x2);
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400895 if (debug)
896 sdev_printk(KERN_INFO, SCpnt->device,
897 "%s reports: Not ready: %s\n", my_name,
898 "initializing command required");
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400899 return check_condition_result;
900 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901 return 0;
902}
903
904/* Returns 0 if ok else (DID_ERROR << 16). Sets scp->resid . */
FUJITA Tomonori21a61822008-03-09 13:44:30 +0900905static int fill_from_dev_buffer(struct scsi_cmnd *scp, unsigned char *arr,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906 int arr_len)
907{
FUJITA Tomonori21a61822008-03-09 13:44:30 +0900908 int act_len;
FUJITA Tomonori072d0bb2008-01-23 01:32:00 +0900909 struct scsi_data_buffer *sdb = scsi_in(scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910
FUJITA Tomonori072d0bb2008-01-23 01:32:00 +0900911 if (!sdb->length)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912 return 0;
FUJITA Tomonori072d0bb2008-01-23 01:32:00 +0900913 if (!(scsi_bidi_cmnd(scp) || scp->sc_data_direction == DMA_FROM_DEVICE))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914 return (DID_ERROR << 16);
FUJITA Tomonori21a61822008-03-09 13:44:30 +0900915
916 act_len = sg_copy_from_buffer(sdb->table.sgl, sdb->table.nents,
917 arr, arr_len);
Akinobu Mitaa4517512013-07-08 16:01:57 -0700918 sdb->resid = scsi_bufflen(scp) - act_len;
FUJITA Tomonori21a61822008-03-09 13:44:30 +0900919
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920 return 0;
921}
922
923/* Returns number of bytes fetched into 'arr' or -1 if error. */
FUJITA Tomonori21a61822008-03-09 13:44:30 +0900924static int fetch_to_dev_buffer(struct scsi_cmnd *scp, unsigned char *arr,
925 int arr_len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926{
FUJITA Tomonori21a61822008-03-09 13:44:30 +0900927 if (!scsi_bufflen(scp))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928 return 0;
FUJITA Tomonori072d0bb2008-01-23 01:32:00 +0900929 if (!(scsi_bidi_cmnd(scp) || scp->sc_data_direction == DMA_TO_DEVICE))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930 return -1;
FUJITA Tomonori21a61822008-03-09 13:44:30 +0900931
932 return scsi_sg_copy_to_buffer(scp, arr, arr_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933}
934
935
936static const char * inq_vendor_id = "Linux ";
937static const char * inq_product_id = "scsi_debug ";
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400938static const char *inq_product_rev = "0184"; /* version less '.' */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400940/* Device identification VPD page. Returns number of bytes placed in arr */
Hannes Reinecke5a09e392006-10-20 09:58:47 +0200941static int inquiry_evpd_83(unsigned char * arr, int port_group_id,
942 int target_dev_id, int dev_id_num,
943 const char * dev_id_str,
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400944 int dev_id_str_len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945{
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400946 int num, port_a;
947 char b[32];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400949 port_a = target_dev_id + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950 /* T10 vendor identifier field format (faked) */
951 arr[0] = 0x2; /* ASCII */
952 arr[1] = 0x1;
953 arr[2] = 0x0;
954 memcpy(&arr[4], inq_vendor_id, 8);
955 memcpy(&arr[12], inq_product_id, 16);
956 memcpy(&arr[28], dev_id_str, dev_id_str_len);
957 num = 8 + 16 + dev_id_str_len;
958 arr[3] = num;
959 num += 4;
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400960 if (dev_id_num >= 0) {
961 /* NAA-5, Logical unit identifier (binary) */
962 arr[num++] = 0x1; /* binary (not necessarily sas) */
963 arr[num++] = 0x3; /* PIV=0, lu, naa */
964 arr[num++] = 0x0;
965 arr[num++] = 0x8;
966 arr[num++] = 0x53; /* naa-5 ieee company id=0x333333 (fake) */
967 arr[num++] = 0x33;
968 arr[num++] = 0x33;
969 arr[num++] = 0x30;
970 arr[num++] = (dev_id_num >> 24);
971 arr[num++] = (dev_id_num >> 16) & 0xff;
972 arr[num++] = (dev_id_num >> 8) & 0xff;
973 arr[num++] = dev_id_num & 0xff;
974 /* Target relative port number */
975 arr[num++] = 0x61; /* proto=sas, binary */
976 arr[num++] = 0x94; /* PIV=1, target port, rel port */
977 arr[num++] = 0x0; /* reserved */
978 arr[num++] = 0x4; /* length */
979 arr[num++] = 0x0; /* reserved */
980 arr[num++] = 0x0; /* reserved */
981 arr[num++] = 0x0;
982 arr[num++] = 0x1; /* relative port A */
983 }
984 /* NAA-5, Target port identifier */
985 arr[num++] = 0x61; /* proto=sas, binary */
986 arr[num++] = 0x93; /* piv=1, target port, naa */
987 arr[num++] = 0x0;
988 arr[num++] = 0x8;
989 arr[num++] = 0x52; /* naa-5, company id=0x222222 (fake) */
990 arr[num++] = 0x22;
991 arr[num++] = 0x22;
992 arr[num++] = 0x20;
993 arr[num++] = (port_a >> 24);
994 arr[num++] = (port_a >> 16) & 0xff;
995 arr[num++] = (port_a >> 8) & 0xff;
996 arr[num++] = port_a & 0xff;
Hannes Reinecke5a09e392006-10-20 09:58:47 +0200997 /* NAA-5, Target port group identifier */
998 arr[num++] = 0x61; /* proto=sas, binary */
999 arr[num++] = 0x95; /* piv=1, target port group id */
1000 arr[num++] = 0x0;
1001 arr[num++] = 0x4;
1002 arr[num++] = 0;
1003 arr[num++] = 0;
1004 arr[num++] = (port_group_id >> 8) & 0xff;
1005 arr[num++] = port_group_id & 0xff;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001006 /* NAA-5, Target device identifier */
1007 arr[num++] = 0x61; /* proto=sas, binary */
1008 arr[num++] = 0xa3; /* piv=1, target device, naa */
1009 arr[num++] = 0x0;
1010 arr[num++] = 0x8;
1011 arr[num++] = 0x52; /* naa-5, company id=0x222222 (fake) */
1012 arr[num++] = 0x22;
1013 arr[num++] = 0x22;
1014 arr[num++] = 0x20;
1015 arr[num++] = (target_dev_id >> 24);
1016 arr[num++] = (target_dev_id >> 16) & 0xff;
1017 arr[num++] = (target_dev_id >> 8) & 0xff;
1018 arr[num++] = target_dev_id & 0xff;
1019 /* SCSI name string: Target device identifier */
1020 arr[num++] = 0x63; /* proto=sas, UTF-8 */
1021 arr[num++] = 0xa8; /* piv=1, target device, SCSI name string */
1022 arr[num++] = 0x0;
1023 arr[num++] = 24;
1024 memcpy(arr + num, "naa.52222220", 12);
1025 num += 12;
1026 snprintf(b, sizeof(b), "%08X", target_dev_id);
1027 memcpy(arr + num, b, 8);
1028 num += 8;
1029 memset(arr + num, 0, 4);
1030 num += 4;
1031 return num;
1032}
1033
1034
1035static unsigned char vpd84_data[] = {
1036/* from 4th byte */ 0x22,0x22,0x22,0x0,0xbb,0x0,
1037 0x22,0x22,0x22,0x0,0xbb,0x1,
1038 0x22,0x22,0x22,0x0,0xbb,0x2,
1039};
1040
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001041/* Software interface identification VPD page */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001042static int inquiry_evpd_84(unsigned char * arr)
1043{
1044 memcpy(arr, vpd84_data, sizeof(vpd84_data));
1045 return sizeof(vpd84_data);
1046}
1047
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001048/* Management network addresses VPD page */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001049static int inquiry_evpd_85(unsigned char * arr)
1050{
1051 int num = 0;
1052 const char * na1 = "https://www.kernel.org/config";
1053 const char * na2 = "http://www.kernel.org/log";
1054 int plen, olen;
1055
1056 arr[num++] = 0x1; /* lu, storage config */
1057 arr[num++] = 0x0; /* reserved */
1058 arr[num++] = 0x0;
1059 olen = strlen(na1);
1060 plen = olen + 1;
1061 if (plen % 4)
1062 plen = ((plen / 4) + 1) * 4;
1063 arr[num++] = plen; /* length, null termianted, padded */
1064 memcpy(arr + num, na1, olen);
1065 memset(arr + num + olen, 0, plen - olen);
1066 num += plen;
1067
1068 arr[num++] = 0x4; /* lu, logging */
1069 arr[num++] = 0x0; /* reserved */
1070 arr[num++] = 0x0;
1071 olen = strlen(na2);
1072 plen = olen + 1;
1073 if (plen % 4)
1074 plen = ((plen / 4) + 1) * 4;
1075 arr[num++] = plen; /* length, null terminated, padded */
1076 memcpy(arr + num, na2, olen);
1077 memset(arr + num + olen, 0, plen - olen);
1078 num += plen;
1079
1080 return num;
1081}
1082
1083/* SCSI ports VPD page */
1084static int inquiry_evpd_88(unsigned char * arr, int target_dev_id)
1085{
1086 int num = 0;
1087 int port_a, port_b;
1088
1089 port_a = target_dev_id + 1;
1090 port_b = port_a + 1;
1091 arr[num++] = 0x0; /* reserved */
1092 arr[num++] = 0x0; /* reserved */
1093 arr[num++] = 0x0;
1094 arr[num++] = 0x1; /* relative port 1 (primary) */
1095 memset(arr + num, 0, 6);
1096 num += 6;
1097 arr[num++] = 0x0;
1098 arr[num++] = 12; /* length tp descriptor */
1099 /* naa-5 target port identifier (A) */
1100 arr[num++] = 0x61; /* proto=sas, binary */
1101 arr[num++] = 0x93; /* PIV=1, target port, NAA */
1102 arr[num++] = 0x0; /* reserved */
1103 arr[num++] = 0x8; /* length */
1104 arr[num++] = 0x52; /* NAA-5, company_id=0x222222 (fake) */
1105 arr[num++] = 0x22;
1106 arr[num++] = 0x22;
1107 arr[num++] = 0x20;
1108 arr[num++] = (port_a >> 24);
1109 arr[num++] = (port_a >> 16) & 0xff;
1110 arr[num++] = (port_a >> 8) & 0xff;
1111 arr[num++] = port_a & 0xff;
1112
1113 arr[num++] = 0x0; /* reserved */
1114 arr[num++] = 0x0; /* reserved */
1115 arr[num++] = 0x0;
1116 arr[num++] = 0x2; /* relative port 2 (secondary) */
1117 memset(arr + num, 0, 6);
1118 num += 6;
1119 arr[num++] = 0x0;
1120 arr[num++] = 12; /* length tp descriptor */
1121 /* naa-5 target port identifier (B) */
1122 arr[num++] = 0x61; /* proto=sas, binary */
1123 arr[num++] = 0x93; /* PIV=1, target port, NAA */
1124 arr[num++] = 0x0; /* reserved */
1125 arr[num++] = 0x8; /* length */
1126 arr[num++] = 0x52; /* NAA-5, company_id=0x222222 (fake) */
1127 arr[num++] = 0x22;
1128 arr[num++] = 0x22;
1129 arr[num++] = 0x20;
1130 arr[num++] = (port_b >> 24);
1131 arr[num++] = (port_b >> 16) & 0xff;
1132 arr[num++] = (port_b >> 8) & 0xff;
1133 arr[num++] = port_b & 0xff;
1134
1135 return num;
1136}
1137
1138
1139static unsigned char vpd89_data[] = {
1140/* from 4th byte */ 0,0,0,0,
1141'l','i','n','u','x',' ',' ',' ',
1142'S','A','T',' ','s','c','s','i','_','d','e','b','u','g',' ',' ',
1143'1','2','3','4',
11440x34,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,
11450xec,0,0,0,
11460x5a,0xc,0xff,0x3f,0x37,0xc8,0x10,0,0,0,0,0,0x3f,0,0,0,
11470,0,0,0,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x20,0x20,0x20,0x20,
11480x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0,0,0,0x40,0x4,0,0x2e,0x33,
11490x38,0x31,0x20,0x20,0x20,0x20,0x54,0x53,0x38,0x33,0x30,0x30,0x33,0x31,
11500x53,0x41,
11510x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
11520x20,0x20,
11530x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
11540x10,0x80,
11550,0,0,0x2f,0,0,0,0x2,0,0x2,0x7,0,0xff,0xff,0x1,0,
11560x3f,0,0xc1,0xff,0x3e,0,0x10,0x1,0xb0,0xf8,0x50,0x9,0,0,0x7,0,
11570x3,0,0x78,0,0x78,0,0xf0,0,0x78,0,0,0,0,0,0,0,
11580,0,0,0,0,0,0,0,0x2,0,0,0,0,0,0,0,
11590x7e,0,0x1b,0,0x6b,0x34,0x1,0x7d,0x3,0x40,0x69,0x34,0x1,0x3c,0x3,0x40,
11600x7f,0x40,0,0,0,0,0xfe,0xfe,0,0,0,0,0,0xfe,0,0,
11610,0,0,0,0,0,0,0,0xb0,0xf8,0x50,0x9,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,
11640,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
11650x1,0,0xb0,0xf8,0x50,0x9,0xb0,0xf8,0x50,0x9,0x20,0x20,0x2,0,0xb6,0x42,
11660,0x80,0x8a,0,0x6,0x3c,0xa,0x3c,0xff,0xff,0xc6,0x7,0,0x1,0,0x8,
11670xf0,0xf,0,0x10,0x2,0,0x30,0,0,0,0,0,0,0,0x6,0xfe,
11680,0,0x2,0,0x50,0,0x8a,0,0x4f,0x95,0,0,0x21,0,0xb,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,0,0,
11800,0,0,0,0,0,0,0,0,0,0,0,0,0,0xa5,0x51,
1181};
1182
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001183/* ATA Information VPD page */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001184static int inquiry_evpd_89(unsigned char * arr)
1185{
1186 memcpy(arr, vpd89_data, sizeof(vpd89_data));
1187 return sizeof(vpd89_data);
1188}
1189
1190
1191static unsigned char vpdb0_data[] = {
Douglas Gilbert1e49f782009-10-29 01:48:31 -04001192 /* from 4th byte */ 0,0,0,4, 0,0,0x4,0, 0,0,0,64,
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,
1195 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001196};
1197
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001198/* Block limits VPD page (SBC-3) */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001199static int inquiry_evpd_b0(unsigned char * arr)
1200{
Martin K. Petersenea61fca2009-05-15 00:40:33 -04001201 unsigned int gran;
1202
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001203 memcpy(arr, vpdb0_data, sizeof(vpdb0_data));
Martin K. Petersene308b3d2010-03-23 01:12:27 -04001204
1205 /* Optimal transfer length granularity */
Martin K. Petersenea61fca2009-05-15 00:40:33 -04001206 gran = 1 << scsi_debug_physblk_exp;
1207 arr[2] = (gran >> 8) & 0xff;
1208 arr[3] = gran & 0xff;
Martin K. Petersene308b3d2010-03-23 01:12:27 -04001209
1210 /* Maximum Transfer Length */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001211 if (sdebug_store_sectors > 0x400) {
1212 arr[4] = (sdebug_store_sectors >> 24) & 0xff;
1213 arr[5] = (sdebug_store_sectors >> 16) & 0xff;
1214 arr[6] = (sdebug_store_sectors >> 8) & 0xff;
1215 arr[7] = sdebug_store_sectors & 0xff;
1216 }
Martin K. Petersen44d92692009-10-15 14:45:27 -04001217
Martin K. Petersene308b3d2010-03-23 01:12:27 -04001218 /* Optimal Transfer Length */
1219 put_unaligned_be32(scsi_debug_opt_blks, &arr[8]);
1220
Martin K. Petersen5b94e232011-03-08 02:08:11 -05001221 if (scsi_debug_lbpu) {
Martin K. Petersene308b3d2010-03-23 01:12:27 -04001222 /* Maximum Unmap LBA Count */
Martin K. Petersen60147592010-08-19 11:49:00 -04001223 put_unaligned_be32(scsi_debug_unmap_max_blocks, &arr[16]);
Martin K. Petersene308b3d2010-03-23 01:12:27 -04001224
1225 /* Maximum Unmap Block Descriptor Count */
Martin K. Petersen44d92692009-10-15 14:45:27 -04001226 put_unaligned_be32(scsi_debug_unmap_max_desc, &arr[20]);
1227 }
1228
Martin K. Petersene308b3d2010-03-23 01:12:27 -04001229 /* Unmap Granularity Alignment */
Martin K. Petersen44d92692009-10-15 14:45:27 -04001230 if (scsi_debug_unmap_alignment) {
1231 put_unaligned_be32(scsi_debug_unmap_alignment, &arr[28]);
1232 arr[28] |= 0x80; /* UGAVALID */
1233 }
1234
Martin K. Petersene308b3d2010-03-23 01:12:27 -04001235 /* Optimal Unmap Granularity */
Martin K. Petersen60147592010-08-19 11:49:00 -04001236 put_unaligned_be32(scsi_debug_unmap_granularity, &arr[24]);
1237
Martin K. Petersen5b94e232011-03-08 02:08:11 -05001238 /* Maximum WRITE SAME Length */
1239 put_unaligned_be64(scsi_debug_write_same_length, &arr[32]);
1240
1241 return 0x3c; /* Mandatory page length for Logical Block Provisioning */
Martin K. Petersen44d92692009-10-15 14:45:27 -04001242
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001243 return sizeof(vpdb0_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244}
1245
Douglas Gilbert1e49f782009-10-29 01:48:31 -04001246/* Block device characteristics VPD page (SBC-3) */
Matthew Wilcoxeac6e8e42008-06-19 10:02:58 -06001247static int inquiry_evpd_b1(unsigned char *arr)
1248{
1249 memset(arr, 0, 0x3c);
1250 arr[0] = 0;
Douglas Gilbert1e49f782009-10-29 01:48:31 -04001251 arr[1] = 1; /* non rotating medium (e.g. solid state) */
1252 arr[2] = 0;
1253 arr[3] = 5; /* less than 1.8" */
Matthew Wilcoxeac6e8e42008-06-19 10:02:58 -06001254
1255 return 0x3c;
1256}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257
Eric Sandeenbe1dd782012-03-08 00:03:59 -06001258/* Logical block provisioning VPD page (SBC-3) */
Martin K. Petersen60147592010-08-19 11:49:00 -04001259static int inquiry_evpd_b2(unsigned char *arr)
1260{
Martin K. Petersen3f0bc3b2012-03-08 10:48:29 -05001261 memset(arr, 0, 0x4);
Martin K. Petersen60147592010-08-19 11:49:00 -04001262 arr[0] = 0; /* threshold exponent */
1263
Martin K. Petersen5b94e232011-03-08 02:08:11 -05001264 if (scsi_debug_lbpu)
Martin K. Petersen60147592010-08-19 11:49:00 -04001265 arr[1] = 1 << 7;
1266
Martin K. Petersen5b94e232011-03-08 02:08:11 -05001267 if (scsi_debug_lbpws)
Martin K. Petersen60147592010-08-19 11:49:00 -04001268 arr[1] |= 1 << 6;
1269
Martin K. Petersen5b94e232011-03-08 02:08:11 -05001270 if (scsi_debug_lbpws10)
1271 arr[1] |= 1 << 5;
1272
Eric Sandeenbe1dd782012-03-08 00:03:59 -06001273 if (scsi_debug_lbprz)
1274 arr[1] |= 1 << 2;
1275
Martin K. Petersen3f0bc3b2012-03-08 10:48:29 -05001276 return 0x4;
Martin K. Petersen60147592010-08-19 11:49:00 -04001277}
1278
Linus Torvalds1da177e2005-04-16 15:20:36 -07001279#define SDEBUG_LONG_INQ_SZ 96
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001280#define SDEBUG_MAX_INQ_ARR_SZ 584
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001282static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001283{
1284 unsigned char pq_pdt;
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001285 unsigned char * arr;
Douglas Gilbert01123ef2014-08-05 12:20:02 +02001286 unsigned char *cmd = scp->cmnd;
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001287 int alloc_len, n, ret;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001288 bool have_wlun;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001289
1290 alloc_len = (cmd[3] << 8) + cmd[4];
Douglas Gilbert6f3cbf52007-01-05 00:05:25 -05001291 arr = kzalloc(SDEBUG_MAX_INQ_ARR_SZ, GFP_ATOMIC);
1292 if (! arr)
1293 return DID_REQUEUE << 16;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001294 have_wlun = (scp->device->lun == SAM2_WLUN_REPORT_LUNS);
1295 if (have_wlun)
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001296 pq_pdt = 0x1e; /* present, wlun */
1297 else if (scsi_debug_no_lun_0 && (0 == devip->lun))
1298 pq_pdt = 0x7f; /* not present, no device type */
1299 else
1300 pq_pdt = (scsi_debug_ptype & 0x1f);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301 arr[0] = pq_pdt;
1302 if (0x2 & cmd[1]) { /* CMDDT bit set */
Douglas Gilbert22017ed2014-11-24 23:04:47 -05001303 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 1, 1);
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001304 kfree(arr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001305 return check_condition_result;
1306 } else if (0x1 & cmd[1]) { /* EVPD bit set */
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001307 int lu_id_num, port_group_id, target_dev_id, len;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001308 char lu_id_str[6];
1309 int host_no = devip->sdbg_host->shost->host_no;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001311 port_group_id = (((host_no + 1) & 0x7f) << 8) +
1312 (devip->channel & 0x7f);
Douglas Gilbert23183912006-09-16 20:30:47 -04001313 if (0 == scsi_debug_vpd_use_hostno)
1314 host_no = 0;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001315 lu_id_num = have_wlun ? -1 : (((host_no + 1) * 2000) +
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001316 (devip->target * 1000) + devip->lun);
1317 target_dev_id = ((host_no + 1) * 2000) +
1318 (devip->target * 1000) - 3;
1319 len = scnprintf(lu_id_str, 6, "%d", lu_id_num);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320 if (0 == cmd[2]) { /* supported vital product data pages */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001321 arr[1] = cmd[2]; /*sanity */
1322 n = 4;
1323 arr[n++] = 0x0; /* this page */
1324 arr[n++] = 0x80; /* unit serial number */
1325 arr[n++] = 0x83; /* device identification */
1326 arr[n++] = 0x84; /* software interface ident. */
1327 arr[n++] = 0x85; /* management network addresses */
1328 arr[n++] = 0x86; /* extended inquiry */
1329 arr[n++] = 0x87; /* mode page policy */
1330 arr[n++] = 0x88; /* SCSI ports */
1331 arr[n++] = 0x89; /* ATA information */
1332 arr[n++] = 0xb0; /* Block limits (SBC) */
Matthew Wilcoxeac6e8e42008-06-19 10:02:58 -06001333 arr[n++] = 0xb1; /* Block characteristics (SBC) */
Martin K. Petersen5b94e232011-03-08 02:08:11 -05001334 if (scsi_debug_lbp()) /* Logical Block Prov. (SBC) */
1335 arr[n++] = 0xb2;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001336 arr[3] = n - 4; /* number of supported VPD pages */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001337 } else if (0x80 == cmd[2]) { /* unit serial number */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001338 arr[1] = cmd[2]; /*sanity */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339 arr[3] = len;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001340 memcpy(&arr[4], lu_id_str, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341 } else if (0x83 == cmd[2]) { /* device identification */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001342 arr[1] = cmd[2]; /*sanity */
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001343 arr[3] = inquiry_evpd_83(&arr[4], port_group_id,
1344 target_dev_id, lu_id_num,
1345 lu_id_str, len);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001346 } else if (0x84 == cmd[2]) { /* Software interface ident. */
1347 arr[1] = cmd[2]; /*sanity */
1348 arr[3] = inquiry_evpd_84(&arr[4]);
1349 } else if (0x85 == cmd[2]) { /* Management network addresses */
1350 arr[1] = cmd[2]; /*sanity */
1351 arr[3] = inquiry_evpd_85(&arr[4]);
1352 } else if (0x86 == cmd[2]) { /* extended inquiry */
1353 arr[1] = cmd[2]; /*sanity */
1354 arr[3] = 0x3c; /* number of following entries */
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001355 if (scsi_debug_dif == SD_DIF_TYPE3_PROTECTION)
1356 arr[4] = 0x4; /* SPT: GRD_CHK:1 */
1357 else if (scsi_debug_dif)
1358 arr[4] = 0x5; /* SPT: GRD_CHK:1, REF_CHK:1 */
1359 else
1360 arr[4] = 0x0; /* no protection stuff */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001361 arr[5] = 0x7; /* head of q, ordered + simple q's */
1362 } else if (0x87 == cmd[2]) { /* mode page policy */
1363 arr[1] = cmd[2]; /*sanity */
1364 arr[3] = 0x8; /* number of following entries */
1365 arr[4] = 0x2; /* disconnect-reconnect mp */
1366 arr[6] = 0x80; /* mlus, shared */
1367 arr[8] = 0x18; /* protocol specific lu */
1368 arr[10] = 0x82; /* mlus, per initiator port */
1369 } else if (0x88 == cmd[2]) { /* SCSI Ports */
1370 arr[1] = cmd[2]; /*sanity */
1371 arr[3] = inquiry_evpd_88(&arr[4], target_dev_id);
1372 } else if (0x89 == cmd[2]) { /* ATA information */
1373 arr[1] = cmd[2]; /*sanity */
1374 n = inquiry_evpd_89(&arr[4]);
1375 arr[2] = (n >> 8);
1376 arr[3] = (n & 0xff);
1377 } else if (0xb0 == cmd[2]) { /* Block limits (SBC) */
1378 arr[1] = cmd[2]; /*sanity */
1379 arr[3] = inquiry_evpd_b0(&arr[4]);
Matthew Wilcoxeac6e8e42008-06-19 10:02:58 -06001380 } else if (0xb1 == cmd[2]) { /* Block characteristics (SBC) */
1381 arr[1] = cmd[2]; /*sanity */
1382 arr[3] = inquiry_evpd_b1(&arr[4]);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05001383 } else if (0xb2 == cmd[2]) { /* Logical Block Prov. (SBC) */
Martin K. Petersen60147592010-08-19 11:49:00 -04001384 arr[1] = cmd[2]; /*sanity */
1385 arr[3] = inquiry_evpd_b2(&arr[4]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386 } else {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05001387 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, -1);
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001388 kfree(arr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389 return check_condition_result;
1390 }
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001391 len = min(((arr[2] << 8) + arr[3]) + 4, alloc_len);
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001392 ret = fill_from_dev_buffer(scp, arr,
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001393 min(len, SDEBUG_MAX_INQ_ARR_SZ));
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001394 kfree(arr);
1395 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396 }
1397 /* drops through here for a standard inquiry */
Martin Pittd9867882012-09-06 12:04:33 +02001398 arr[1] = scsi_debug_removable ? 0x80 : 0; /* Removable disk */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001399 arr[2] = scsi_debug_scsi_level;
1400 arr[3] = 2; /* response_data_format==2 */
1401 arr[4] = SDEBUG_LONG_INQ_SZ - 5;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001402 arr[5] = scsi_debug_dif ? 1 : 0; /* PROTECT bit */
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001403 if (0 == scsi_debug_vpd_use_hostno)
1404 arr[5] = 0x10; /* claim: implicit TGPS */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001405 arr[6] = 0x10; /* claim: MultiP */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406 /* arr[6] |= 0x40; ... claim: EncServ (enclosure services) */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001407 arr[7] = 0xa; /* claim: LINKED + CMDQUE */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408 memcpy(&arr[8], inq_vendor_id, 8);
1409 memcpy(&arr[16], inq_product_id, 16);
1410 memcpy(&arr[32], inq_product_rev, 4);
1411 /* version descriptors (2 bytes each) follow */
Douglas Gilberte46b0342014-08-05 12:21:53 +02001412 arr[58] = 0x0; arr[59] = 0xa2; /* SAM-5 rev 4 */
1413 arr[60] = 0x4; arr[61] = 0x68; /* SPC-4 rev 37 */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001414 n = 62;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415 if (scsi_debug_ptype == 0) {
Douglas Gilberte46b0342014-08-05 12:21:53 +02001416 arr[n++] = 0x4; arr[n++] = 0xc5; /* SBC-4 rev 36 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417 } else if (scsi_debug_ptype == 1) {
Douglas Gilberte46b0342014-08-05 12:21:53 +02001418 arr[n++] = 0x5; arr[n++] = 0x25; /* SSC-4 rev 3 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001419 }
Douglas Gilberte46b0342014-08-05 12:21:53 +02001420 arr[n++] = 0x20; arr[n++] = 0xe6; /* SPL-3 rev 7 */
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001421 ret = fill_from_dev_buffer(scp, arr,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001422 min(alloc_len, SDEBUG_LONG_INQ_SZ));
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001423 kfree(arr);
1424 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001425}
1426
1427static int resp_requests(struct scsi_cmnd * scp,
1428 struct sdebug_dev_info * devip)
1429{
1430 unsigned char * sbuff;
Douglas Gilbert01123ef2014-08-05 12:20:02 +02001431 unsigned char *cmd = scp->cmnd;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001432 unsigned char arr[SCSI_SENSE_BUFFERSIZE];
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001433 bool dsense, want_dsense;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001434 int len = 18;
1435
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001436 memset(arr, 0, sizeof(arr));
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001437 dsense = !!(cmd[1] & 1);
1438 want_dsense = dsense || scsi_debug_dsense;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001439 sbuff = scp->sense_buffer;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001440 if ((iec_m_pg[2] & 0x4) && (6 == (iec_m_pg[3] & 0xf))) {
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001441 if (dsense) {
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001442 arr[0] = 0x72;
1443 arr[1] = 0x0; /* NO_SENSE in sense_key */
1444 arr[2] = THRESHOLD_EXCEEDED;
1445 arr[3] = 0xff; /* TEST set and MRIE==6 */
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001446 len = 8;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001447 } else {
1448 arr[0] = 0x70;
1449 arr[2] = 0x0; /* NO_SENSE in sense_key */
1450 arr[7] = 0xa; /* 18 byte sense buffer */
1451 arr[12] = THRESHOLD_EXCEEDED;
1452 arr[13] = 0xff; /* TEST set and MRIE==6 */
1453 }
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001454 } else {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001455 memcpy(arr, sbuff, SCSI_SENSE_BUFFERSIZE);
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001456 if (arr[0] >= 0x70 && dsense == scsi_debug_dsense)
1457 ; /* have sense and formats match */
1458 else if (arr[0] <= 0x70) {
1459 if (dsense) {
1460 memset(arr, 0, 8);
1461 arr[0] = 0x72;
1462 len = 8;
1463 } else {
1464 memset(arr, 0, 18);
1465 arr[0] = 0x70;
1466 arr[7] = 0xa;
1467 }
1468 } else if (dsense) {
1469 memset(arr, 0, 8);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001470 arr[0] = 0x72;
1471 arr[1] = sbuff[2]; /* sense key */
1472 arr[2] = sbuff[12]; /* asc */
1473 arr[3] = sbuff[13]; /* ascq */
1474 len = 8;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001475 } else {
1476 memset(arr, 0, 18);
1477 arr[0] = 0x70;
1478 arr[2] = sbuff[1];
1479 arr[7] = 0xa;
1480 arr[12] = sbuff[1];
1481 arr[13] = sbuff[3];
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001482 }
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001483
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001484 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001485 mk_sense_buffer(scp, 0, NO_ADDITIONAL_SENSE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001486 return fill_from_dev_buffer(scp, arr, len);
1487}
1488
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001489static int resp_start_stop(struct scsi_cmnd * scp,
1490 struct sdebug_dev_info * devip)
1491{
Douglas Gilbert01123ef2014-08-05 12:20:02 +02001492 unsigned char *cmd = scp->cmnd;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001493 int power_cond, start;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001494
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001495 power_cond = (cmd[4] & 0xf0) >> 4;
1496 if (power_cond) {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05001497 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 4, 7);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001498 return check_condition_result;
1499 }
1500 start = cmd[4] & 1;
1501 if (start == devip->stopped)
1502 devip->stopped = !start;
1503 return 0;
1504}
1505
FUJITA Tomonori28898872008-03-30 00:59:55 +09001506static sector_t get_sdebug_capacity(void)
1507{
1508 if (scsi_debug_virtual_gb > 0)
Douglas Gilbert5447ed62010-04-25 12:30:23 +02001509 return (sector_t)scsi_debug_virtual_gb *
1510 (1073741824 / scsi_debug_sector_size);
FUJITA Tomonori28898872008-03-30 00:59:55 +09001511 else
1512 return sdebug_store_sectors;
1513}
1514
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515#define SDEBUG_READCAP_ARR_SZ 8
1516static int resp_readcap(struct scsi_cmnd * scp,
1517 struct sdebug_dev_info * devip)
1518{
1519 unsigned char arr[SDEBUG_READCAP_ARR_SZ];
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001520 unsigned int capac;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001522 /* following just in case virtual_gb changed */
FUJITA Tomonori28898872008-03-30 00:59:55 +09001523 sdebug_capacity = get_sdebug_capacity();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524 memset(arr, 0, SDEBUG_READCAP_ARR_SZ);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001525 if (sdebug_capacity < 0xffffffff) {
1526 capac = (unsigned int)sdebug_capacity - 1;
1527 arr[0] = (capac >> 24);
1528 arr[1] = (capac >> 16) & 0xff;
1529 arr[2] = (capac >> 8) & 0xff;
1530 arr[3] = capac & 0xff;
1531 } else {
1532 arr[0] = 0xff;
1533 arr[1] = 0xff;
1534 arr[2] = 0xff;
1535 arr[3] = 0xff;
1536 }
Martin K. Petersen597136a2008-06-05 00:12:59 -04001537 arr[6] = (scsi_debug_sector_size >> 8) & 0xff;
1538 arr[7] = scsi_debug_sector_size & 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001539 return fill_from_dev_buffer(scp, arr, SDEBUG_READCAP_ARR_SZ);
1540}
1541
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001542#define SDEBUG_READCAP16_ARR_SZ 32
1543static int resp_readcap16(struct scsi_cmnd * scp,
1544 struct sdebug_dev_info * devip)
1545{
Douglas Gilbert01123ef2014-08-05 12:20:02 +02001546 unsigned char *cmd = scp->cmnd;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001547 unsigned char arr[SDEBUG_READCAP16_ARR_SZ];
1548 unsigned long long capac;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001549 int k, alloc_len;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001550
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001551 alloc_len = ((cmd[10] << 24) + (cmd[11] << 16) + (cmd[12] << 8)
1552 + cmd[13]);
1553 /* following just in case virtual_gb changed */
FUJITA Tomonori28898872008-03-30 00:59:55 +09001554 sdebug_capacity = get_sdebug_capacity();
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001555 memset(arr, 0, SDEBUG_READCAP16_ARR_SZ);
1556 capac = sdebug_capacity - 1;
1557 for (k = 0; k < 8; ++k, capac >>= 8)
1558 arr[7 - k] = capac & 0xff;
Martin K. Petersen597136a2008-06-05 00:12:59 -04001559 arr[8] = (scsi_debug_sector_size >> 24) & 0xff;
1560 arr[9] = (scsi_debug_sector_size >> 16) & 0xff;
1561 arr[10] = (scsi_debug_sector_size >> 8) & 0xff;
1562 arr[11] = scsi_debug_sector_size & 0xff;
Martin K. Petersenea61fca2009-05-15 00:40:33 -04001563 arr[13] = scsi_debug_physblk_exp & 0xf;
1564 arr[14] = (scsi_debug_lowest_aligned >> 8) & 0x3f;
Martin K. Petersen44d92692009-10-15 14:45:27 -04001565
Eric Sandeenbe1dd782012-03-08 00:03:59 -06001566 if (scsi_debug_lbp()) {
Martin K. Petersen5b94e232011-03-08 02:08:11 -05001567 arr[14] |= 0x80; /* LBPME */
Eric Sandeenbe1dd782012-03-08 00:03:59 -06001568 if (scsi_debug_lbprz)
1569 arr[14] |= 0x40; /* LBPRZ */
1570 }
Martin K. Petersen44d92692009-10-15 14:45:27 -04001571
Martin K. Petersenea61fca2009-05-15 00:40:33 -04001572 arr[15] = scsi_debug_lowest_aligned & 0xff;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001573
1574 if (scsi_debug_dif) {
1575 arr[12] = (scsi_debug_dif - 1) << 1; /* P_TYPE */
1576 arr[12] |= 1; /* PROT_EN */
1577 }
1578
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001579 return fill_from_dev_buffer(scp, arr,
1580 min(alloc_len, SDEBUG_READCAP16_ARR_SZ));
1581}
1582
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001583#define SDEBUG_MAX_TGTPGS_ARR_SZ 1412
1584
1585static int resp_report_tgtpgs(struct scsi_cmnd * scp,
1586 struct sdebug_dev_info * devip)
1587{
Douglas Gilbert01123ef2014-08-05 12:20:02 +02001588 unsigned char *cmd = scp->cmnd;
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001589 unsigned char * arr;
1590 int host_no = devip->sdbg_host->shost->host_no;
1591 int n, ret, alen, rlen;
1592 int port_group_a, port_group_b, port_a, port_b;
1593
1594 alen = ((cmd[6] << 24) + (cmd[7] << 16) + (cmd[8] << 8)
1595 + cmd[9]);
1596
Douglas Gilbert6f3cbf52007-01-05 00:05:25 -05001597 arr = kzalloc(SDEBUG_MAX_TGTPGS_ARR_SZ, GFP_ATOMIC);
1598 if (! arr)
1599 return DID_REQUEUE << 16;
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001600 /*
1601 * EVPD page 0x88 states we have two ports, one
1602 * real and a fake port with no device connected.
1603 * So we create two port groups with one port each
1604 * and set the group with port B to unavailable.
1605 */
1606 port_a = 0x1; /* relative port A */
1607 port_b = 0x2; /* relative port B */
1608 port_group_a = (((host_no + 1) & 0x7f) << 8) +
1609 (devip->channel & 0x7f);
1610 port_group_b = (((host_no + 1) & 0x7f) << 8) +
1611 (devip->channel & 0x7f) + 0x80;
1612
1613 /*
1614 * The asymmetric access state is cycled according to the host_id.
1615 */
1616 n = 4;
1617 if (0 == scsi_debug_vpd_use_hostno) {
1618 arr[n++] = host_no % 3; /* Asymm access state */
1619 arr[n++] = 0x0F; /* claim: all states are supported */
1620 } else {
1621 arr[n++] = 0x0; /* Active/Optimized path */
1622 arr[n++] = 0x01; /* claim: only support active/optimized paths */
1623 }
1624 arr[n++] = (port_group_a >> 8) & 0xff;
1625 arr[n++] = port_group_a & 0xff;
1626 arr[n++] = 0; /* Reserved */
1627 arr[n++] = 0; /* Status code */
1628 arr[n++] = 0; /* Vendor unique */
1629 arr[n++] = 0x1; /* One port per group */
1630 arr[n++] = 0; /* Reserved */
1631 arr[n++] = 0; /* Reserved */
1632 arr[n++] = (port_a >> 8) & 0xff;
1633 arr[n++] = port_a & 0xff;
1634 arr[n++] = 3; /* Port unavailable */
1635 arr[n++] = 0x08; /* claim: only unavailalbe paths are supported */
1636 arr[n++] = (port_group_b >> 8) & 0xff;
1637 arr[n++] = port_group_b & 0xff;
1638 arr[n++] = 0; /* Reserved */
1639 arr[n++] = 0; /* Status code */
1640 arr[n++] = 0; /* Vendor unique */
1641 arr[n++] = 0x1; /* One port per group */
1642 arr[n++] = 0; /* Reserved */
1643 arr[n++] = 0; /* Reserved */
1644 arr[n++] = (port_b >> 8) & 0xff;
1645 arr[n++] = port_b & 0xff;
1646
1647 rlen = n - 4;
1648 arr[0] = (rlen >> 24) & 0xff;
1649 arr[1] = (rlen >> 16) & 0xff;
1650 arr[2] = (rlen >> 8) & 0xff;
1651 arr[3] = rlen & 0xff;
1652
1653 /*
1654 * Return the smallest value of either
1655 * - The allocated length
1656 * - The constructed command length
1657 * - The maximum array size
1658 */
1659 rlen = min(alen,n);
1660 ret = fill_from_dev_buffer(scp, arr,
1661 min(rlen, SDEBUG_MAX_TGTPGS_ARR_SZ));
1662 kfree(arr);
1663 return ret;
1664}
1665
Douglas Gilbert38d5c832014-11-24 21:27:12 -05001666static int
1667resp_rsup_opcodes(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
1668{
1669 bool rctd;
1670 u8 reporting_opts, req_opcode, sdeb_i, supp;
1671 u16 req_sa, u;
1672 u32 alloc_len, a_len;
1673 int k, offset, len, errsts, count, bump, na;
1674 const struct opcode_info_t *oip;
1675 const struct opcode_info_t *r_oip;
1676 u8 *arr;
1677 u8 *cmd = scp->cmnd;
1678
1679 rctd = !!(cmd[2] & 0x80);
1680 reporting_opts = cmd[2] & 0x7;
1681 req_opcode = cmd[3];
1682 req_sa = get_unaligned_be16(cmd + 4);
1683 alloc_len = get_unaligned_be32(cmd + 6);
Colin Ian King6d310df2015-01-22 11:20:40 +00001684 if (alloc_len < 4 || alloc_len > 0xffff) {
Douglas Gilbert38d5c832014-11-24 21:27:12 -05001685 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 6, -1);
1686 return check_condition_result;
1687 }
1688 if (alloc_len > 8192)
1689 a_len = 8192;
1690 else
1691 a_len = alloc_len;
Sasha Levin99531e62015-01-17 17:47:37 -05001692 arr = kzalloc((a_len < 256) ? 320 : a_len + 64, GFP_ATOMIC);
Douglas Gilbert38d5c832014-11-24 21:27:12 -05001693 if (NULL == arr) {
1694 mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC,
1695 INSUFF_RES_ASCQ);
1696 return check_condition_result;
1697 }
1698 switch (reporting_opts) {
1699 case 0: /* all commands */
1700 /* count number of commands */
1701 for (count = 0, oip = opcode_info_arr;
1702 oip->num_attached != 0xff; ++oip) {
1703 if (F_INV_OP & oip->flags)
1704 continue;
1705 count += (oip->num_attached + 1);
1706 }
1707 bump = rctd ? 20 : 8;
1708 put_unaligned_be32(count * bump, arr);
1709 for (offset = 4, oip = opcode_info_arr;
1710 oip->num_attached != 0xff && offset < a_len; ++oip) {
1711 if (F_INV_OP & oip->flags)
1712 continue;
1713 na = oip->num_attached;
1714 arr[offset] = oip->opcode;
1715 put_unaligned_be16(oip->sa, arr + offset + 2);
1716 if (rctd)
1717 arr[offset + 5] |= 0x2;
1718 if (FF_SA & oip->flags)
1719 arr[offset + 5] |= 0x1;
1720 put_unaligned_be16(oip->len_mask[0], arr + offset + 6);
1721 if (rctd)
1722 put_unaligned_be16(0xa, arr + offset + 8);
1723 r_oip = oip;
1724 for (k = 0, oip = oip->arrp; k < na; ++k, ++oip) {
1725 if (F_INV_OP & oip->flags)
1726 continue;
1727 offset += bump;
1728 arr[offset] = oip->opcode;
1729 put_unaligned_be16(oip->sa, arr + offset + 2);
1730 if (rctd)
1731 arr[offset + 5] |= 0x2;
1732 if (FF_SA & oip->flags)
1733 arr[offset + 5] |= 0x1;
1734 put_unaligned_be16(oip->len_mask[0],
1735 arr + offset + 6);
1736 if (rctd)
1737 put_unaligned_be16(0xa,
1738 arr + offset + 8);
1739 }
1740 oip = r_oip;
1741 offset += bump;
1742 }
1743 break;
1744 case 1: /* one command: opcode only */
1745 case 2: /* one command: opcode plus service action */
1746 case 3: /* one command: if sa==0 then opcode only else opcode+sa */
1747 sdeb_i = opcode_ind_arr[req_opcode];
1748 oip = &opcode_info_arr[sdeb_i];
1749 if (F_INV_OP & oip->flags) {
1750 supp = 1;
1751 offset = 4;
1752 } else {
1753 if (1 == reporting_opts) {
1754 if (FF_SA & oip->flags) {
1755 mk_sense_invalid_fld(scp, SDEB_IN_CDB,
1756 2, 2);
1757 kfree(arr);
1758 return check_condition_result;
1759 }
1760 req_sa = 0;
1761 } else if (2 == reporting_opts &&
1762 0 == (FF_SA & oip->flags)) {
1763 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 4, -1);
1764 kfree(arr); /* point at requested sa */
1765 return check_condition_result;
1766 }
1767 if (0 == (FF_SA & oip->flags) &&
1768 req_opcode == oip->opcode)
1769 supp = 3;
1770 else if (0 == (FF_SA & oip->flags)) {
1771 na = oip->num_attached;
1772 for (k = 0, oip = oip->arrp; k < na;
1773 ++k, ++oip) {
1774 if (req_opcode == oip->opcode)
1775 break;
1776 }
1777 supp = (k >= na) ? 1 : 3;
1778 } else if (req_sa != oip->sa) {
1779 na = oip->num_attached;
1780 for (k = 0, oip = oip->arrp; k < na;
1781 ++k, ++oip) {
1782 if (req_sa == oip->sa)
1783 break;
1784 }
1785 supp = (k >= na) ? 1 : 3;
1786 } else
1787 supp = 3;
1788 if (3 == supp) {
1789 u = oip->len_mask[0];
1790 put_unaligned_be16(u, arr + 2);
1791 arr[4] = oip->opcode;
1792 for (k = 1; k < u; ++k)
1793 arr[4 + k] = (k < 16) ?
1794 oip->len_mask[k] : 0xff;
1795 offset = 4 + u;
1796 } else
1797 offset = 4;
1798 }
1799 arr[1] = (rctd ? 0x80 : 0) | supp;
1800 if (rctd) {
1801 put_unaligned_be16(0xa, arr + offset);
1802 offset += 12;
1803 }
1804 break;
1805 default:
1806 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, 2);
1807 kfree(arr);
1808 return check_condition_result;
1809 }
1810 offset = (offset < a_len) ? offset : a_len;
1811 len = (offset < alloc_len) ? offset : alloc_len;
1812 errsts = fill_from_dev_buffer(scp, arr, len);
1813 kfree(arr);
1814 return errsts;
1815}
1816
1817static int
1818resp_rsup_tmfs(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
1819{
1820 bool repd;
1821 u32 alloc_len, len;
1822 u8 arr[16];
1823 u8 *cmd = scp->cmnd;
1824
1825 memset(arr, 0, sizeof(arr));
1826 repd = !!(cmd[2] & 0x80);
1827 alloc_len = get_unaligned_be32(cmd + 6);
1828 if (alloc_len < 4) {
1829 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 6, -1);
1830 return check_condition_result;
1831 }
1832 arr[0] = 0xc8; /* ATS | ATSS | LURS */
1833 arr[1] = 0x1; /* ITNRS */
1834 if (repd) {
1835 arr[3] = 0xc;
1836 len = 16;
1837 } else
1838 len = 4;
1839
1840 len = (len < alloc_len) ? len : alloc_len;
1841 return fill_from_dev_buffer(scp, arr, len);
1842}
1843
Linus Torvalds1da177e2005-04-16 15:20:36 -07001844/* <<Following mode page info copied from ST318451LW>> */
1845
1846static int resp_err_recov_pg(unsigned char * p, int pcontrol, int target)
1847{ /* Read-Write Error Recovery page for mode_sense */
1848 unsigned char err_recov_pg[] = {0x1, 0xa, 0xc0, 11, 240, 0, 0, 0,
1849 5, 0, 0xff, 0xff};
1850
1851 memcpy(p, err_recov_pg, sizeof(err_recov_pg));
1852 if (1 == pcontrol)
1853 memset(p + 2, 0, sizeof(err_recov_pg) - 2);
1854 return sizeof(err_recov_pg);
1855}
1856
1857static int resp_disconnect_pg(unsigned char * p, int pcontrol, int target)
1858{ /* Disconnect-Reconnect page for mode_sense */
1859 unsigned char disconnect_pg[] = {0x2, 0xe, 128, 128, 0, 10, 0, 0,
1860 0, 0, 0, 0, 0, 0, 0, 0};
1861
1862 memcpy(p, disconnect_pg, sizeof(disconnect_pg));
1863 if (1 == pcontrol)
1864 memset(p + 2, 0, sizeof(disconnect_pg) - 2);
1865 return sizeof(disconnect_pg);
1866}
1867
1868static int resp_format_pg(unsigned char * p, int pcontrol, int target)
1869{ /* Format device page for mode_sense */
Martin K. Petersen597136a2008-06-05 00:12:59 -04001870 unsigned char format_pg[] = {0x3, 0x16, 0, 0, 0, 0, 0, 0,
1871 0, 0, 0, 0, 0, 0, 0, 0,
1872 0, 0, 0, 0, 0x40, 0, 0, 0};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001873
Martin K. Petersen597136a2008-06-05 00:12:59 -04001874 memcpy(p, format_pg, sizeof(format_pg));
1875 p[10] = (sdebug_sectors_per >> 8) & 0xff;
1876 p[11] = sdebug_sectors_per & 0xff;
1877 p[12] = (scsi_debug_sector_size >> 8) & 0xff;
1878 p[13] = scsi_debug_sector_size & 0xff;
Martin Pittd9867882012-09-06 12:04:33 +02001879 if (scsi_debug_removable)
Martin K. Petersen597136a2008-06-05 00:12:59 -04001880 p[20] |= 0x20; /* should agree with INQUIRY */
1881 if (1 == pcontrol)
1882 memset(p + 2, 0, sizeof(format_pg) - 2);
1883 return sizeof(format_pg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001884}
1885
1886static int resp_caching_pg(unsigned char * p, int pcontrol, int target)
1887{ /* Caching page for mode_sense */
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001888 unsigned char ch_caching_pg[] = {/* 0x8, 18, */ 0x4, 0, 0, 0, 0, 0,
1889 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
1890 unsigned char d_caching_pg[] = {0x8, 18, 0x14, 0, 0xff, 0xff, 0, 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001891 0xff, 0xff, 0xff, 0xff, 0x80, 0x14, 0, 0, 0, 0, 0, 0};
1892
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001893 if (SCSI_DEBUG_OPT_N_WCE & scsi_debug_opts)
1894 caching_pg[2] &= ~0x4; /* set WCE=0 (default WCE=1) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001895 memcpy(p, caching_pg, sizeof(caching_pg));
1896 if (1 == pcontrol)
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001897 memcpy(p + 2, ch_caching_pg, sizeof(ch_caching_pg));
1898 else if (2 == pcontrol)
1899 memcpy(p, d_caching_pg, sizeof(d_caching_pg));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001900 return sizeof(caching_pg);
1901}
1902
1903static int resp_ctrl_m_pg(unsigned char * p, int pcontrol, int target)
1904{ /* Control mode page for mode_sense */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001905 unsigned char ch_ctrl_m_pg[] = {/* 0xa, 10, */ 0x6, 0, 0, 0, 0, 0,
1906 0, 0, 0, 0};
1907 unsigned char d_ctrl_m_pg[] = {0xa, 10, 2, 0, 0, 0, 0, 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001908 0, 0, 0x2, 0x4b};
1909
1910 if (scsi_debug_dsense)
1911 ctrl_m_pg[2] |= 0x4;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001912 else
1913 ctrl_m_pg[2] &= ~0x4;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001914
1915 if (scsi_debug_ato)
1916 ctrl_m_pg[5] |= 0x80; /* ATO=1 */
1917
Linus Torvalds1da177e2005-04-16 15:20:36 -07001918 memcpy(p, ctrl_m_pg, sizeof(ctrl_m_pg));
1919 if (1 == pcontrol)
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001920 memcpy(p + 2, ch_ctrl_m_pg, sizeof(ch_ctrl_m_pg));
1921 else if (2 == pcontrol)
1922 memcpy(p, d_ctrl_m_pg, sizeof(d_ctrl_m_pg));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001923 return sizeof(ctrl_m_pg);
1924}
1925
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001926
Linus Torvalds1da177e2005-04-16 15:20:36 -07001927static int resp_iec_m_pg(unsigned char * p, int pcontrol, int target)
1928{ /* Informational Exceptions control mode page for mode_sense */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001929 unsigned char ch_iec_m_pg[] = {/* 0x1c, 0xa, */ 0x4, 0xf, 0, 0, 0, 0,
1930 0, 0, 0x0, 0x0};
1931 unsigned char d_iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0,
1932 0, 0, 0x0, 0x0};
1933
Linus Torvalds1da177e2005-04-16 15:20:36 -07001934 memcpy(p, iec_m_pg, sizeof(iec_m_pg));
1935 if (1 == pcontrol)
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001936 memcpy(p + 2, ch_iec_m_pg, sizeof(ch_iec_m_pg));
1937 else if (2 == pcontrol)
1938 memcpy(p, d_iec_m_pg, sizeof(d_iec_m_pg));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001939 return sizeof(iec_m_pg);
1940}
1941
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001942static int resp_sas_sf_m_pg(unsigned char * p, int pcontrol, int target)
1943{ /* SAS SSP mode page - short format for mode_sense */
1944 unsigned char sas_sf_m_pg[] = {0x19, 0x6,
1945 0x6, 0x0, 0x7, 0xd0, 0x0, 0x0};
1946
1947 memcpy(p, sas_sf_m_pg, sizeof(sas_sf_m_pg));
1948 if (1 == pcontrol)
1949 memset(p + 2, 0, sizeof(sas_sf_m_pg) - 2);
1950 return sizeof(sas_sf_m_pg);
1951}
1952
1953
1954static int resp_sas_pcd_m_spg(unsigned char * p, int pcontrol, int target,
1955 int target_dev_id)
1956{ /* SAS phy control and discover mode page for mode_sense */
1957 unsigned char sas_pcd_m_pg[] = {0x59, 0x1, 0, 0x64, 0, 0x6, 0, 2,
1958 0, 0, 0, 0, 0x10, 0x9, 0x8, 0x0,
1959 0x52, 0x22, 0x22, 0x20, 0x0, 0x0, 0x0, 0x0,
1960 0x51, 0x11, 0x11, 0x10, 0x0, 0x0, 0x0, 0x1,
1961 0x2, 0, 0, 0, 0, 0, 0, 0,
1962 0x88, 0x99, 0, 0, 0, 0, 0, 0,
1963 0, 0, 0, 0, 0, 0, 0, 0,
1964 0, 1, 0, 0, 0x10, 0x9, 0x8, 0x0,
1965 0x52, 0x22, 0x22, 0x20, 0x0, 0x0, 0x0, 0x0,
1966 0x51, 0x11, 0x11, 0x10, 0x0, 0x0, 0x0, 0x1,
1967 0x3, 0, 0, 0, 0, 0, 0, 0,
1968 0x88, 0x99, 0, 0, 0, 0, 0, 0,
1969 0, 0, 0, 0, 0, 0, 0, 0,
1970 };
1971 int port_a, port_b;
1972
1973 port_a = target_dev_id + 1;
1974 port_b = port_a + 1;
1975 memcpy(p, sas_pcd_m_pg, sizeof(sas_pcd_m_pg));
1976 p[20] = (port_a >> 24);
1977 p[21] = (port_a >> 16) & 0xff;
1978 p[22] = (port_a >> 8) & 0xff;
1979 p[23] = port_a & 0xff;
1980 p[48 + 20] = (port_b >> 24);
1981 p[48 + 21] = (port_b >> 16) & 0xff;
1982 p[48 + 22] = (port_b >> 8) & 0xff;
1983 p[48 + 23] = port_b & 0xff;
1984 if (1 == pcontrol)
1985 memset(p + 4, 0, sizeof(sas_pcd_m_pg) - 4);
1986 return sizeof(sas_pcd_m_pg);
1987}
1988
1989static int resp_sas_sha_m_spg(unsigned char * p, int pcontrol)
1990{ /* SAS SSP shared protocol specific port mode subpage */
1991 unsigned char sas_sha_m_pg[] = {0x59, 0x2, 0, 0xc, 0, 0x6, 0x10, 0,
1992 0, 0, 0, 0, 0, 0, 0, 0,
1993 };
1994
1995 memcpy(p, sas_sha_m_pg, sizeof(sas_sha_m_pg));
1996 if (1 == pcontrol)
1997 memset(p + 4, 0, sizeof(sas_sha_m_pg) - 4);
1998 return sizeof(sas_sha_m_pg);
1999}
2000
Linus Torvalds1da177e2005-04-16 15:20:36 -07002001#define SDEBUG_MAX_MSENSE_SZ 256
2002
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002003static int
2004resp_mode_sense(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002005{
Douglas Gilbert23183912006-09-16 20:30:47 -04002006 unsigned char dbd, llbaa;
2007 int pcontrol, pcode, subpcode, bd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002008 unsigned char dev_spec;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002009 int k, alloc_len, msense_6, offset, len, target_dev_id;
2010 int target = scp->device->id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002011 unsigned char * ap;
2012 unsigned char arr[SDEBUG_MAX_MSENSE_SZ];
Douglas Gilbert01123ef2014-08-05 12:20:02 +02002013 unsigned char *cmd = scp->cmnd;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014
Douglas Gilbert23183912006-09-16 20:30:47 -04002015 dbd = !!(cmd[1] & 0x8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002016 pcontrol = (cmd[2] & 0xc0) >> 6;
2017 pcode = cmd[2] & 0x3f;
2018 subpcode = cmd[3];
2019 msense_6 = (MODE_SENSE == cmd[0]);
Douglas Gilbert23183912006-09-16 20:30:47 -04002020 llbaa = msense_6 ? 0 : !!(cmd[1] & 0x10);
2021 if ((0 == scsi_debug_ptype) && (0 == dbd))
2022 bd_len = llbaa ? 16 : 8;
2023 else
2024 bd_len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002025 alloc_len = msense_6 ? cmd[4] : ((cmd[7] << 8) | cmd[8]);
2026 memset(arr, 0, SDEBUG_MAX_MSENSE_SZ);
2027 if (0x3 == pcontrol) { /* Saving values not supported */
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002028 mk_sense_buffer(scp, ILLEGAL_REQUEST, SAVING_PARAMS_UNSUP, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002029 return check_condition_result;
2030 }
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002031 target_dev_id = ((devip->sdbg_host->shost->host_no + 1) * 2000) +
2032 (devip->target * 1000) - 3;
Douglas Gilbert23183912006-09-16 20:30:47 -04002033 /* set DPOFUA bit for disks */
2034 if (0 == scsi_debug_ptype)
2035 dev_spec = (DEV_READONLY(target) ? 0x80 : 0x0) | 0x10;
2036 else
2037 dev_spec = 0x0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002038 if (msense_6) {
2039 arr[2] = dev_spec;
Douglas Gilbert23183912006-09-16 20:30:47 -04002040 arr[3] = bd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002041 offset = 4;
2042 } else {
2043 arr[3] = dev_spec;
Douglas Gilbert23183912006-09-16 20:30:47 -04002044 if (16 == bd_len)
2045 arr[4] = 0x1; /* set LONGLBA bit */
2046 arr[7] = bd_len; /* assume 255 or less */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002047 offset = 8;
2048 }
2049 ap = arr + offset;
FUJITA Tomonori28898872008-03-30 00:59:55 +09002050 if ((bd_len > 0) && (!sdebug_capacity))
2051 sdebug_capacity = get_sdebug_capacity();
2052
Douglas Gilbert23183912006-09-16 20:30:47 -04002053 if (8 == bd_len) {
2054 if (sdebug_capacity > 0xfffffffe) {
2055 ap[0] = 0xff;
2056 ap[1] = 0xff;
2057 ap[2] = 0xff;
2058 ap[3] = 0xff;
2059 } else {
2060 ap[0] = (sdebug_capacity >> 24) & 0xff;
2061 ap[1] = (sdebug_capacity >> 16) & 0xff;
2062 ap[2] = (sdebug_capacity >> 8) & 0xff;
2063 ap[3] = sdebug_capacity & 0xff;
2064 }
Martin K. Petersen597136a2008-06-05 00:12:59 -04002065 ap[6] = (scsi_debug_sector_size >> 8) & 0xff;
2066 ap[7] = scsi_debug_sector_size & 0xff;
Douglas Gilbert23183912006-09-16 20:30:47 -04002067 offset += bd_len;
2068 ap = arr + offset;
2069 } else if (16 == bd_len) {
2070 unsigned long long capac = sdebug_capacity;
2071
2072 for (k = 0; k < 8; ++k, capac >>= 8)
2073 ap[7 - k] = capac & 0xff;
Martin K. Petersen597136a2008-06-05 00:12:59 -04002074 ap[12] = (scsi_debug_sector_size >> 24) & 0xff;
2075 ap[13] = (scsi_debug_sector_size >> 16) & 0xff;
2076 ap[14] = (scsi_debug_sector_size >> 8) & 0xff;
2077 ap[15] = scsi_debug_sector_size & 0xff;
Douglas Gilbert23183912006-09-16 20:30:47 -04002078 offset += bd_len;
2079 ap = arr + offset;
2080 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002081
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002082 if ((subpcode > 0x0) && (subpcode < 0xff) && (0x19 != pcode)) {
2083 /* TODO: Control Extension page */
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002084 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 3, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002085 return check_condition_result;
2086 }
2087 switch (pcode) {
2088 case 0x1: /* Read-Write error recovery page, direct access */
2089 len = resp_err_recov_pg(ap, pcontrol, target);
2090 offset += len;
2091 break;
2092 case 0x2: /* Disconnect-Reconnect page, all devices */
2093 len = resp_disconnect_pg(ap, pcontrol, target);
2094 offset += len;
2095 break;
2096 case 0x3: /* Format device page, direct access */
2097 len = resp_format_pg(ap, pcontrol, target);
2098 offset += len;
2099 break;
2100 case 0x8: /* Caching page, direct access */
2101 len = resp_caching_pg(ap, pcontrol, target);
2102 offset += len;
2103 break;
2104 case 0xa: /* Control Mode page, all devices */
2105 len = resp_ctrl_m_pg(ap, pcontrol, target);
2106 offset += len;
2107 break;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002108 case 0x19: /* if spc==1 then sas phy, control+discover */
2109 if ((subpcode > 0x2) && (subpcode < 0xff)) {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002110 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 3, -1);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002111 return check_condition_result;
2112 }
2113 len = 0;
2114 if ((0x0 == subpcode) || (0xff == subpcode))
2115 len += resp_sas_sf_m_pg(ap + len, pcontrol, target);
2116 if ((0x1 == subpcode) || (0xff == subpcode))
2117 len += resp_sas_pcd_m_spg(ap + len, pcontrol, target,
2118 target_dev_id);
2119 if ((0x2 == subpcode) || (0xff == subpcode))
2120 len += resp_sas_sha_m_spg(ap + len, pcontrol);
2121 offset += len;
2122 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002123 case 0x1c: /* Informational Exceptions Mode page, all devices */
2124 len = resp_iec_m_pg(ap, pcontrol, target);
2125 offset += len;
2126 break;
2127 case 0x3f: /* Read all Mode pages */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002128 if ((0 == subpcode) || (0xff == subpcode)) {
2129 len = resp_err_recov_pg(ap, pcontrol, target);
2130 len += resp_disconnect_pg(ap + len, pcontrol, target);
2131 len += resp_format_pg(ap + len, pcontrol, target);
2132 len += resp_caching_pg(ap + len, pcontrol, target);
2133 len += resp_ctrl_m_pg(ap + len, pcontrol, target);
2134 len += resp_sas_sf_m_pg(ap + len, pcontrol, target);
2135 if (0xff == subpcode) {
2136 len += resp_sas_pcd_m_spg(ap + len, pcontrol,
2137 target, target_dev_id);
2138 len += resp_sas_sha_m_spg(ap + len, pcontrol);
2139 }
2140 len += resp_iec_m_pg(ap + len, pcontrol, target);
2141 } else {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002142 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 3, -1);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002143 return check_condition_result;
2144 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002145 offset += len;
2146 break;
2147 default:
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002148 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, 5);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002149 return check_condition_result;
2150 }
2151 if (msense_6)
2152 arr[0] = offset - 1;
2153 else {
2154 arr[0] = ((offset - 2) >> 8) & 0xff;
2155 arr[1] = (offset - 2) & 0xff;
2156 }
2157 return fill_from_dev_buffer(scp, arr, min(alloc_len, offset));
2158}
2159
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002160#define SDEBUG_MAX_MSELECT_SZ 512
2161
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002162static int
2163resp_mode_select(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002164{
2165 int pf, sp, ps, md_len, bd_len, off, spf, pg_len;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002166 int param_len, res, mpage;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002167 unsigned char arr[SDEBUG_MAX_MSELECT_SZ];
Douglas Gilbert01123ef2014-08-05 12:20:02 +02002168 unsigned char *cmd = scp->cmnd;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002169 int mselect6 = (MODE_SELECT == cmd[0]);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002170
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002171 memset(arr, 0, sizeof(arr));
2172 pf = cmd[1] & 0x10;
2173 sp = cmd[1] & 0x1;
2174 param_len = mselect6 ? cmd[4] : ((cmd[7] << 8) + cmd[8]);
2175 if ((0 == pf) || sp || (param_len > SDEBUG_MAX_MSELECT_SZ)) {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002176 mk_sense_invalid_fld(scp, SDEB_IN_CDB, mselect6 ? 4 : 7, -1);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002177 return check_condition_result;
2178 }
2179 res = fetch_to_dev_buffer(scp, arr, param_len);
2180 if (-1 == res)
2181 return (DID_ERROR << 16);
2182 else if ((res < param_len) &&
2183 (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002184 sdev_printk(KERN_INFO, scp->device,
2185 "%s: cdb indicated=%d, IO sent=%d bytes\n",
2186 __func__, param_len, res);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002187 md_len = mselect6 ? (arr[0] + 1) : ((arr[0] << 8) + arr[1] + 2);
2188 bd_len = mselect6 ? arr[3] : ((arr[6] << 8) + arr[7]);
Douglas Gilbert23183912006-09-16 20:30:47 -04002189 if (md_len > 2) {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002190 mk_sense_invalid_fld(scp, SDEB_IN_DATA, 0, -1);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002191 return check_condition_result;
2192 }
2193 off = bd_len + (mselect6 ? 4 : 8);
2194 mpage = arr[off] & 0x3f;
2195 ps = !!(arr[off] & 0x80);
2196 if (ps) {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002197 mk_sense_invalid_fld(scp, SDEB_IN_DATA, off, 7);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002198 return check_condition_result;
2199 }
2200 spf = !!(arr[off] & 0x40);
2201 pg_len = spf ? ((arr[off + 2] << 8) + arr[off + 3] + 4) :
2202 (arr[off + 1] + 2);
2203 if ((pg_len + off) > param_len) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002204 mk_sense_buffer(scp, ILLEGAL_REQUEST,
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002205 PARAMETER_LIST_LENGTH_ERR, 0);
2206 return check_condition_result;
2207 }
2208 switch (mpage) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002209 case 0x8: /* Caching Mode page */
2210 if (caching_pg[1] == arr[off + 1]) {
2211 memcpy(caching_pg + 2, arr + off + 2,
2212 sizeof(caching_pg) - 2);
2213 goto set_mode_changed_ua;
2214 }
2215 break;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002216 case 0xa: /* Control Mode page */
2217 if (ctrl_m_pg[1] == arr[off + 1]) {
2218 memcpy(ctrl_m_pg + 2, arr + off + 2,
2219 sizeof(ctrl_m_pg) - 2);
2220 scsi_debug_dsense = !!(ctrl_m_pg[2] & 0x4);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002221 goto set_mode_changed_ua;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002222 }
2223 break;
2224 case 0x1c: /* Informational Exceptions Mode page */
2225 if (iec_m_pg[1] == arr[off + 1]) {
2226 memcpy(iec_m_pg + 2, arr + off + 2,
2227 sizeof(iec_m_pg) - 2);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002228 goto set_mode_changed_ua;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002229 }
2230 break;
2231 default:
2232 break;
2233 }
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002234 mk_sense_invalid_fld(scp, SDEB_IN_DATA, off, 5);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002235 return check_condition_result;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002236set_mode_changed_ua:
2237 set_bit(SDEBUG_UA_MODE_CHANGED, devip->uas_bm);
2238 return 0;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002239}
2240
2241static int resp_temp_l_pg(unsigned char * arr)
2242{
2243 unsigned char temp_l_pg[] = {0x0, 0x0, 0x3, 0x2, 0x0, 38,
2244 0x0, 0x1, 0x3, 0x2, 0x0, 65,
2245 };
2246
2247 memcpy(arr, temp_l_pg, sizeof(temp_l_pg));
2248 return sizeof(temp_l_pg);
2249}
2250
2251static int resp_ie_l_pg(unsigned char * arr)
2252{
2253 unsigned char ie_l_pg[] = {0x0, 0x0, 0x3, 0x3, 0x0, 0x0, 38,
2254 };
2255
2256 memcpy(arr, ie_l_pg, sizeof(ie_l_pg));
2257 if (iec_m_pg[2] & 0x4) { /* TEST bit set */
2258 arr[4] = THRESHOLD_EXCEEDED;
2259 arr[5] = 0xff;
2260 }
2261 return sizeof(ie_l_pg);
2262}
2263
2264#define SDEBUG_MAX_LSENSE_SZ 512
2265
2266static int resp_log_sense(struct scsi_cmnd * scp,
2267 struct sdebug_dev_info * devip)
2268{
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002269 int ppc, sp, pcontrol, pcode, subpcode, alloc_len, len, n;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002270 unsigned char arr[SDEBUG_MAX_LSENSE_SZ];
Douglas Gilbert01123ef2014-08-05 12:20:02 +02002271 unsigned char *cmd = scp->cmnd;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002272
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002273 memset(arr, 0, sizeof(arr));
2274 ppc = cmd[1] & 0x2;
2275 sp = cmd[1] & 0x1;
2276 if (ppc || sp) {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002277 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 1, ppc ? 1 : 0);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002278 return check_condition_result;
2279 }
2280 pcontrol = (cmd[2] & 0xc0) >> 6;
2281 pcode = cmd[2] & 0x3f;
Douglas Gilbert23183912006-09-16 20:30:47 -04002282 subpcode = cmd[3] & 0xff;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002283 alloc_len = (cmd[7] << 8) + cmd[8];
2284 arr[0] = pcode;
Douglas Gilbert23183912006-09-16 20:30:47 -04002285 if (0 == subpcode) {
2286 switch (pcode) {
2287 case 0x0: /* Supported log pages log page */
2288 n = 4;
2289 arr[n++] = 0x0; /* this page */
2290 arr[n++] = 0xd; /* Temperature */
2291 arr[n++] = 0x2f; /* Informational exceptions */
2292 arr[3] = n - 4;
2293 break;
2294 case 0xd: /* Temperature log page */
2295 arr[3] = resp_temp_l_pg(arr + 4);
2296 break;
2297 case 0x2f: /* Informational exceptions log page */
2298 arr[3] = resp_ie_l_pg(arr + 4);
2299 break;
2300 default:
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002301 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, 5);
Douglas Gilbert23183912006-09-16 20:30:47 -04002302 return check_condition_result;
2303 }
2304 } else if (0xff == subpcode) {
2305 arr[0] |= 0x40;
2306 arr[1] = subpcode;
2307 switch (pcode) {
2308 case 0x0: /* Supported log pages and subpages log page */
2309 n = 4;
2310 arr[n++] = 0x0;
2311 arr[n++] = 0x0; /* 0,0 page */
2312 arr[n++] = 0x0;
2313 arr[n++] = 0xff; /* this page */
2314 arr[n++] = 0xd;
2315 arr[n++] = 0x0; /* Temperature */
2316 arr[n++] = 0x2f;
2317 arr[n++] = 0x0; /* Informational exceptions */
2318 arr[3] = n - 4;
2319 break;
2320 case 0xd: /* Temperature subpages */
2321 n = 4;
2322 arr[n++] = 0xd;
2323 arr[n++] = 0x0; /* Temperature */
2324 arr[3] = n - 4;
2325 break;
2326 case 0x2f: /* Informational exceptions subpages */
2327 n = 4;
2328 arr[n++] = 0x2f;
2329 arr[n++] = 0x0; /* Informational exceptions */
2330 arr[3] = n - 4;
2331 break;
2332 default:
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002333 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, 5);
Douglas Gilbert23183912006-09-16 20:30:47 -04002334 return check_condition_result;
2335 }
2336 } else {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002337 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 3, -1);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002338 return check_condition_result;
2339 }
2340 len = min(((arr[2] << 8) + arr[3]) + 4, alloc_len);
2341 return fill_from_dev_buffer(scp, arr,
2342 min(len, SDEBUG_MAX_INQ_ARR_SZ));
2343}
2344
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002345static int check_device_access_params(struct scsi_cmnd *scp,
FUJITA Tomonori19789102008-03-30 00:59:56 +09002346 unsigned long long lba, unsigned int num)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002347{
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002348 if (lba + num > sdebug_capacity) {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002349 mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002350 return check_condition_result;
2351 }
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002352 /* transfer length excessive (tie in to block limits VPD page) */
2353 if (num > sdebug_store_sectors) {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002354 /* needs work to find which cdb byte 'num' comes from */
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002355 mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002356 return check_condition_result;
2357 }
FUJITA Tomonori19789102008-03-30 00:59:56 +09002358 return 0;
2359}
2360
Akinobu Mitaa4517512013-07-08 16:01:57 -07002361/* Returns number of bytes copied or -1 if error. */
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002362static int
2363do_device_access(struct scsi_cmnd *scmd, u64 lba, u32 num, bool do_write)
FUJITA Tomonori19789102008-03-30 00:59:56 +09002364{
2365 int ret;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002366 u64 block, rest = 0;
Akinobu Mitaa4517512013-07-08 16:01:57 -07002367 struct scsi_data_buffer *sdb;
2368 enum dma_data_direction dir;
FUJITA Tomonori19789102008-03-30 00:59:56 +09002369
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002370 if (do_write) {
Akinobu Mitaa4517512013-07-08 16:01:57 -07002371 sdb = scsi_out(scmd);
2372 dir = DMA_TO_DEVICE;
Akinobu Mitaa4517512013-07-08 16:01:57 -07002373 } else {
2374 sdb = scsi_in(scmd);
2375 dir = DMA_FROM_DEVICE;
Akinobu Mitaa4517512013-07-08 16:01:57 -07002376 }
2377
2378 if (!sdb->length)
2379 return 0;
2380 if (!(scsi_bidi_cmnd(scmd) || scmd->sc_data_direction == dir))
2381 return -1;
FUJITA Tomonori19789102008-03-30 00:59:56 +09002382
2383 block = do_div(lba, sdebug_store_sectors);
2384 if (block + num > sdebug_store_sectors)
2385 rest = block + num - sdebug_store_sectors;
2386
Dave Gordon386ecb12015-06-30 14:58:57 -07002387 ret = sg_copy_buffer(sdb->table.sgl, sdb->table.nents,
Akinobu Mitaa4517512013-07-08 16:01:57 -07002388 fake_storep + (block * scsi_debug_sector_size),
Dave Gordon386ecb12015-06-30 14:58:57 -07002389 (num - rest) * scsi_debug_sector_size, 0, do_write);
Akinobu Mitaa4517512013-07-08 16:01:57 -07002390 if (ret != (num - rest) * scsi_debug_sector_size)
2391 return ret;
2392
2393 if (rest) {
Dave Gordon386ecb12015-06-30 14:58:57 -07002394 ret += sg_copy_buffer(sdb->table.sgl, sdb->table.nents,
Akinobu Mitaa4517512013-07-08 16:01:57 -07002395 fake_storep, rest * scsi_debug_sector_size,
Dave Gordon386ecb12015-06-30 14:58:57 -07002396 (num - rest) * scsi_debug_sector_size, do_write);
Akinobu Mitaa4517512013-07-08 16:01:57 -07002397 }
FUJITA Tomonori19789102008-03-30 00:59:56 +09002398
2399 return ret;
2400}
2401
Douglas Gilbert38d5c832014-11-24 21:27:12 -05002402/* If fake_store(lba,num) compares equal to arr(num), then copy top half of
2403 * arr into fake_store(lba,num) and return true. If comparison fails then
2404 * return false. */
2405static bool
2406comp_write_worker(u64 lba, u32 num, const u8 *arr)
2407{
2408 bool res;
2409 u64 block, rest = 0;
2410 u32 store_blks = sdebug_store_sectors;
2411 u32 lb_size = scsi_debug_sector_size;
2412
2413 block = do_div(lba, store_blks);
2414 if (block + num > store_blks)
2415 rest = block + num - store_blks;
2416
2417 res = !memcmp(fake_storep + (block * lb_size), arr,
2418 (num - rest) * lb_size);
2419 if (!res)
2420 return res;
2421 if (rest)
2422 res = memcmp(fake_storep, arr + ((num - rest) * lb_size),
2423 rest * lb_size);
2424 if (!res)
2425 return res;
2426 arr += num * lb_size;
2427 memcpy(fake_storep + (block * lb_size), arr, (num - rest) * lb_size);
2428 if (rest)
2429 memcpy(fake_storep, arr + ((num - rest) * lb_size),
2430 rest * lb_size);
2431 return res;
2432}
2433
Akinobu Mita51d648a2013-09-18 21:27:28 +09002434static __be16 dif_compute_csum(const void *buf, int len)
Akinobu Mitabeb40ea2013-06-29 17:59:19 +09002435{
Akinobu Mita51d648a2013-09-18 21:27:28 +09002436 __be16 csum;
Akinobu Mitabeb40ea2013-06-29 17:59:19 +09002437
Akinobu Mita51d648a2013-09-18 21:27:28 +09002438 if (scsi_debug_guard)
2439 csum = (__force __be16)ip_compute_csum(buf, len);
2440 else
Akinobu Mitabeb40ea2013-06-29 17:59:19 +09002441 csum = cpu_to_be16(crc_t10dif(buf, len));
Akinobu Mita51d648a2013-09-18 21:27:28 +09002442
Akinobu Mitabeb40ea2013-06-29 17:59:19 +09002443 return csum;
2444}
2445
2446static int dif_verify(struct sd_dif_tuple *sdt, const void *data,
2447 sector_t sector, u32 ei_lba)
2448{
Akinobu Mita51d648a2013-09-18 21:27:28 +09002449 __be16 csum = dif_compute_csum(data, scsi_debug_sector_size);
Akinobu Mitabeb40ea2013-06-29 17:59:19 +09002450
2451 if (sdt->guard_tag != csum) {
Tomas Winklerc12879702015-07-28 16:54:20 +03002452 pr_err("GUARD check failed on sector %lu rcvd 0x%04x, data 0x%04x\n",
Akinobu Mitabeb40ea2013-06-29 17:59:19 +09002453 (unsigned long)sector,
2454 be16_to_cpu(sdt->guard_tag),
2455 be16_to_cpu(csum));
2456 return 0x01;
2457 }
2458 if (scsi_debug_dif == SD_DIF_TYPE1_PROTECTION &&
2459 be32_to_cpu(sdt->ref_tag) != (sector & 0xffffffff)) {
Tomas Winklerc12879702015-07-28 16:54:20 +03002460 pr_err("REF check failed on sector %lu\n",
2461 (unsigned long)sector);
Akinobu Mitabeb40ea2013-06-29 17:59:19 +09002462 return 0x03;
2463 }
2464 if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
2465 be32_to_cpu(sdt->ref_tag) != ei_lba) {
Tomas Winklerc12879702015-07-28 16:54:20 +03002466 pr_err("REF check failed on sector %lu\n",
2467 (unsigned long)sector);
Akinobu Mitabeb40ea2013-06-29 17:59:19 +09002468 return 0x03;
2469 }
2470 return 0;
2471}
2472
Akinobu Mitabb8c0632013-09-18 21:27:25 +09002473static void dif_copy_prot(struct scsi_cmnd *SCpnt, sector_t sector,
Akinobu Mita65f72f2a2013-09-18 21:27:26 +09002474 unsigned int sectors, bool read)
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002475{
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002476 size_t resid;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002477 void *paddr;
Akinobu Mita14faa942013-09-18 21:27:24 +09002478 const void *dif_store_end = dif_storep + sdebug_store_sectors;
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002479 struct sg_mapping_iter miter;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002480
Akinobu Mitae18d8be2013-06-29 17:59:18 +09002481 /* Bytes of protection data to copy into sgl */
2482 resid = sectors * sizeof(*dif_storep);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002483
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002484 sg_miter_start(&miter, scsi_prot_sglist(SCpnt),
2485 scsi_prot_sg_count(SCpnt), SG_MITER_ATOMIC |
2486 (read ? SG_MITER_TO_SG : SG_MITER_FROM_SG));
2487
2488 while (sg_miter_next(&miter) && resid > 0) {
2489 size_t len = min(miter.length, resid);
Akinobu Mita14faa942013-09-18 21:27:24 +09002490 void *start = dif_store(sector);
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002491 size_t rest = 0;
Akinobu Mita14faa942013-09-18 21:27:24 +09002492
2493 if (dif_store_end < start + len)
2494 rest = start + len - dif_store_end;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002495
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002496 paddr = miter.addr;
Akinobu Mita14faa942013-09-18 21:27:24 +09002497
Akinobu Mita65f72f2a2013-09-18 21:27:26 +09002498 if (read)
2499 memcpy(paddr, start, len - rest);
2500 else
2501 memcpy(start, paddr, len - rest);
2502
2503 if (rest) {
2504 if (read)
2505 memcpy(paddr + len - rest, dif_storep, rest);
2506 else
2507 memcpy(dif_storep, paddr + len - rest, rest);
2508 }
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002509
Akinobu Mitae18d8be2013-06-29 17:59:18 +09002510 sector += len / sizeof(*dif_storep);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002511 resid -= len;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002512 }
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002513 sg_miter_stop(&miter);
Akinobu Mitabb8c0632013-09-18 21:27:25 +09002514}
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002515
Akinobu Mitabb8c0632013-09-18 21:27:25 +09002516static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec,
2517 unsigned int sectors, u32 ei_lba)
2518{
2519 unsigned int i;
2520 struct sd_dif_tuple *sdt;
2521 sector_t sector;
2522
Akinobu Mitac45eabec2014-02-26 22:56:58 +09002523 for (i = 0; i < sectors; i++, ei_lba++) {
Akinobu Mitabb8c0632013-09-18 21:27:25 +09002524 int ret;
2525
2526 sector = start_sec + i;
2527 sdt = dif_store(sector);
2528
Akinobu Mita51d648a2013-09-18 21:27:28 +09002529 if (sdt->app_tag == cpu_to_be16(0xffff))
Akinobu Mitabb8c0632013-09-18 21:27:25 +09002530 continue;
2531
2532 ret = dif_verify(sdt, fake_store(sector), sector, ei_lba);
2533 if (ret) {
2534 dif_errors++;
2535 return ret;
2536 }
Akinobu Mitabb8c0632013-09-18 21:27:25 +09002537 }
2538
Akinobu Mita65f72f2a2013-09-18 21:27:26 +09002539 dif_copy_prot(SCpnt, start_sec, sectors, true);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002540 dix_reads++;
2541
2542 return 0;
2543}
2544
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002545static int
2546resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
FUJITA Tomonori19789102008-03-30 00:59:56 +09002547{
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002548 u8 *cmd = scp->cmnd;
2549 u64 lba;
2550 u32 num;
2551 u32 ei_lba;
FUJITA Tomonori19789102008-03-30 00:59:56 +09002552 unsigned long iflags;
2553 int ret;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002554 bool check_prot;
FUJITA Tomonori19789102008-03-30 00:59:56 +09002555
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002556 switch (cmd[0]) {
2557 case READ_16:
2558 ei_lba = 0;
2559 lba = get_unaligned_be64(cmd + 2);
2560 num = get_unaligned_be32(cmd + 10);
2561 check_prot = true;
2562 break;
2563 case READ_10:
2564 ei_lba = 0;
2565 lba = get_unaligned_be32(cmd + 2);
2566 num = get_unaligned_be16(cmd + 7);
2567 check_prot = true;
2568 break;
2569 case READ_6:
2570 ei_lba = 0;
2571 lba = (u32)cmd[3] | (u32)cmd[2] << 8 |
2572 (u32)(cmd[1] & 0x1f) << 16;
2573 num = (0 == cmd[4]) ? 256 : cmd[4];
2574 check_prot = true;
2575 break;
2576 case READ_12:
2577 ei_lba = 0;
2578 lba = get_unaligned_be32(cmd + 2);
2579 num = get_unaligned_be32(cmd + 6);
2580 check_prot = true;
2581 break;
2582 case XDWRITEREAD_10:
2583 ei_lba = 0;
2584 lba = get_unaligned_be32(cmd + 2);
2585 num = get_unaligned_be16(cmd + 7);
2586 check_prot = false;
2587 break;
2588 default: /* assume READ(32) */
2589 lba = get_unaligned_be64(cmd + 12);
2590 ei_lba = get_unaligned_be32(cmd + 20);
2591 num = get_unaligned_be32(cmd + 28);
2592 check_prot = false;
2593 break;
2594 }
2595 if (check_prot) {
2596 if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
2597 (cmd[1] & 0xe0)) {
2598 mk_sense_invalid_opcode(scp);
2599 return check_condition_result;
2600 }
2601 if ((scsi_debug_dif == SD_DIF_TYPE1_PROTECTION ||
2602 scsi_debug_dif == SD_DIF_TYPE3_PROTECTION) &&
2603 (cmd[1] & 0xe0) == 0)
2604 sdev_printk(KERN_ERR, scp->device, "Unprotected RD "
2605 "to DIF device\n");
2606 }
2607 if (sdebug_any_injecting_opt) {
2608 struct sdebug_scmd_extra_t *ep = scsi_cmd_priv(scp);
2609
2610 if (ep->inj_short)
2611 num /= 2;
2612 }
2613
2614 /* inline check_device_access_params() */
2615 if (lba + num > sdebug_capacity) {
2616 mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0);
2617 return check_condition_result;
2618 }
2619 /* transfer length excessive (tie in to block limits VPD page) */
2620 if (num > sdebug_store_sectors) {
2621 /* needs work to find which cdb byte 'num' comes from */
2622 mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0);
2623 return check_condition_result;
2624 }
FUJITA Tomonori19789102008-03-30 00:59:56 +09002625
Linus Torvalds1da177e2005-04-16 15:20:36 -07002626 if ((SCSI_DEBUG_OPT_MEDIUM_ERR & scsi_debug_opts) &&
Douglas Gilbert32f7ef72011-03-11 10:43:35 -05002627 (lba <= (OPT_MEDIUM_ERR_ADDR + OPT_MEDIUM_ERR_NUM - 1)) &&
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002628 ((lba + num) > OPT_MEDIUM_ERR_ADDR)) {
2629 /* claim unrecoverable read error */
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002630 mk_sense_buffer(scp, MEDIUM_ERROR, UNRECOVERED_READ_ERR, 0);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002631 /* set info field and valid bit for fixed descriptor */
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002632 if (0x70 == (scp->sense_buffer[0] & 0x7f)) {
2633 scp->sense_buffer[0] |= 0x80; /* Valid bit */
Douglas Gilbert32f7ef72011-03-11 10:43:35 -05002634 ret = (lba < OPT_MEDIUM_ERR_ADDR)
2635 ? OPT_MEDIUM_ERR_ADDR : (int)lba;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002636 put_unaligned_be32(ret, scp->sense_buffer + 3);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002637 }
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002638 scsi_set_resid(scp, scsi_bufflen(scp));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002639 return check_condition_result;
2640 }
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002641
Akinobu Mita6c78cc02014-02-26 22:57:03 +09002642 read_lock_irqsave(&atomic_rw, iflags);
2643
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002644 /* DIX + T10 DIF */
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002645 if (scsi_debug_dix && scsi_prot_sg_count(scp)) {
2646 int prot_ret = prot_verify_read(scp, lba, num, ei_lba);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002647
2648 if (prot_ret) {
Akinobu Mita6c78cc02014-02-26 22:57:03 +09002649 read_unlock_irqrestore(&atomic_rw, iflags);
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002650 mk_sense_buffer(scp, ABORTED_COMMAND, 0x10, prot_ret);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002651 return illegal_condition_result;
2652 }
2653 }
2654
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002655 ret = do_device_access(scp, lba, num, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002656 read_unlock_irqrestore(&atomic_rw, iflags);
Akinobu Mitaa4517512013-07-08 16:01:57 -07002657 if (ret == -1)
2658 return DID_ERROR << 16;
2659
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002660 scsi_in(scp)->resid = scsi_bufflen(scp) - ret;
Akinobu Mitaa4517512013-07-08 16:01:57 -07002661
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002662 if (sdebug_any_injecting_opt) {
2663 struct sdebug_scmd_extra_t *ep = scsi_cmd_priv(scp);
2664
2665 if (ep->inj_recovered) {
2666 mk_sense_buffer(scp, RECOVERED_ERROR,
2667 THRESHOLD_EXCEEDED, 0);
2668 return check_condition_result;
2669 } else if (ep->inj_transport) {
2670 mk_sense_buffer(scp, ABORTED_COMMAND,
2671 TRANSPORT_PROBLEM, ACK_NAK_TO);
2672 return check_condition_result;
2673 } else if (ep->inj_dif) {
2674 /* Logical block guard check failed */
2675 mk_sense_buffer(scp, ABORTED_COMMAND, 0x10, 1);
2676 return illegal_condition_result;
2677 } else if (ep->inj_dix) {
2678 mk_sense_buffer(scp, ILLEGAL_REQUEST, 0x10, 1);
2679 return illegal_condition_result;
2680 }
2681 }
Akinobu Mitaa4517512013-07-08 16:01:57 -07002682 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002683}
2684
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002685void dump_sector(unsigned char *buf, int len)
2686{
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002687 int i, j, n;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002688
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002689 pr_err(">>> Sector Dump <<<\n");
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002690 for (i = 0 ; i < len ; i += 16) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002691 char b[128];
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002692
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002693 for (j = 0, n = 0; j < 16; j++) {
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002694 unsigned char c = buf[i+j];
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002695
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002696 if (c >= 0x20 && c < 0x7e)
2697 n += scnprintf(b + n, sizeof(b) - n,
2698 " %c ", buf[i+j]);
2699 else
2700 n += scnprintf(b + n, sizeof(b) - n,
2701 "%02x ", buf[i+j]);
2702 }
2703 pr_err("%04d: %s\n", i, b);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002704 }
2705}
2706
2707static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec,
Martin K. Petersen395cef02009-09-18 17:33:03 -04002708 unsigned int sectors, u32 ei_lba)
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002709{
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002710 int ret;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002711 struct sd_dif_tuple *sdt;
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002712 void *daddr;
Akinobu Mita65f72f2a2013-09-18 21:27:26 +09002713 sector_t sector = start_sec;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002714 int ppage_offset;
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002715 int dpage_offset;
2716 struct sg_mapping_iter diter;
2717 struct sg_mapping_iter piter;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002718
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002719 BUG_ON(scsi_sg_count(SCpnt) == 0);
2720 BUG_ON(scsi_prot_sg_count(SCpnt) == 0);
2721
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002722 sg_miter_start(&piter, scsi_prot_sglist(SCpnt),
2723 scsi_prot_sg_count(SCpnt),
2724 SG_MITER_ATOMIC | SG_MITER_FROM_SG);
2725 sg_miter_start(&diter, scsi_sglist(SCpnt), scsi_sg_count(SCpnt),
2726 SG_MITER_ATOMIC | SG_MITER_FROM_SG);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002727
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002728 /* For each protection page */
2729 while (sg_miter_next(&piter)) {
2730 dpage_offset = 0;
2731 if (WARN_ON(!sg_miter_next(&diter))) {
2732 ret = 0x01;
2733 goto out;
2734 }
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002735
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002736 for (ppage_offset = 0; ppage_offset < piter.length;
2737 ppage_offset += sizeof(struct sd_dif_tuple)) {
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002738 /* If we're at the end of the current
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002739 * data page advance to the next one
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002740 */
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002741 if (dpage_offset >= diter.length) {
2742 if (WARN_ON(!sg_miter_next(&diter))) {
2743 ret = 0x01;
2744 goto out;
2745 }
2746 dpage_offset = 0;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002747 }
2748
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002749 sdt = piter.addr + ppage_offset;
2750 daddr = diter.addr + dpage_offset;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002751
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002752 ret = dif_verify(sdt, daddr, sector, ei_lba);
Akinobu Mitabeb40ea2013-06-29 17:59:19 +09002753 if (ret) {
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002754 dump_sector(daddr, scsi_debug_sector_size);
Martin K. Petersen395cef02009-09-18 17:33:03 -04002755 goto out;
2756 }
2757
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002758 sector++;
Martin K. Petersen395cef02009-09-18 17:33:03 -04002759 ei_lba++;
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002760 dpage_offset += scsi_debug_sector_size;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002761 }
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002762 diter.consumed = dpage_offset;
2763 sg_miter_stop(&diter);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002764 }
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002765 sg_miter_stop(&piter);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002766
Akinobu Mita65f72f2a2013-09-18 21:27:26 +09002767 dif_copy_prot(SCpnt, start_sec, sectors, false);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002768 dix_writes++;
2769
2770 return 0;
2771
2772out:
2773 dif_errors++;
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002774 sg_miter_stop(&diter);
2775 sg_miter_stop(&piter);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002776 return ret;
2777}
2778
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002779static unsigned long lba_to_map_index(sector_t lba)
2780{
2781 if (scsi_debug_unmap_alignment) {
2782 lba += scsi_debug_unmap_granularity -
2783 scsi_debug_unmap_alignment;
2784 }
2785 do_div(lba, scsi_debug_unmap_granularity);
2786
2787 return lba;
2788}
2789
2790static sector_t map_index_to_lba(unsigned long index)
2791{
Akinobu Mitaa027b5b2013-08-26 22:08:41 +09002792 sector_t lba = index * scsi_debug_unmap_granularity;
2793
2794 if (scsi_debug_unmap_alignment) {
2795 lba -= scsi_debug_unmap_granularity -
2796 scsi_debug_unmap_alignment;
2797 }
2798
2799 return lba;
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002800}
2801
Martin K. Petersen44d92692009-10-15 14:45:27 -04002802static unsigned int map_state(sector_t lba, unsigned int *num)
2803{
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002804 sector_t end;
2805 unsigned int mapped;
2806 unsigned long index;
2807 unsigned long next;
Martin K. Petersen44d92692009-10-15 14:45:27 -04002808
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002809 index = lba_to_map_index(lba);
2810 mapped = test_bit(index, map_storep);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002811
2812 if (mapped)
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002813 next = find_next_zero_bit(map_storep, map_size, index);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002814 else
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002815 next = find_next_bit(map_storep, map_size, index);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002816
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002817 end = min_t(sector_t, sdebug_store_sectors, map_index_to_lba(next));
Martin K. Petersen44d92692009-10-15 14:45:27 -04002818 *num = end - lba;
2819
2820 return mapped;
2821}
2822
2823static void map_region(sector_t lba, unsigned int len)
2824{
Martin K. Petersen44d92692009-10-15 14:45:27 -04002825 sector_t end = lba + len;
2826
Martin K. Petersen44d92692009-10-15 14:45:27 -04002827 while (lba < end) {
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002828 unsigned long index = lba_to_map_index(lba);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002829
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002830 if (index < map_size)
2831 set_bit(index, map_storep);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002832
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002833 lba = map_index_to_lba(index + 1);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002834 }
2835}
2836
2837static void unmap_region(sector_t lba, unsigned int len)
2838{
Martin K. Petersen44d92692009-10-15 14:45:27 -04002839 sector_t end = lba + len;
2840
Martin K. Petersen44d92692009-10-15 14:45:27 -04002841 while (lba < end) {
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002842 unsigned long index = lba_to_map_index(lba);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002843
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002844 if (lba == map_index_to_lba(index) &&
2845 lba + scsi_debug_unmap_granularity <= end &&
2846 index < map_size) {
2847 clear_bit(index, map_storep);
2848 if (scsi_debug_lbprz) {
Eric Sandeenbe1dd782012-03-08 00:03:59 -06002849 memset(fake_storep +
Akinobu Mitacc34a8e2013-04-16 22:11:57 +09002850 lba * scsi_debug_sector_size, 0,
2851 scsi_debug_sector_size *
2852 scsi_debug_unmap_granularity);
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002853 }
Akinobu Mitae9926b42013-06-29 17:59:17 +09002854 if (dif_storep) {
2855 memset(dif_storep + lba, 0xff,
2856 sizeof(*dif_storep) *
2857 scsi_debug_unmap_granularity);
2858 }
Eric Sandeenbe1dd782012-03-08 00:03:59 -06002859 }
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002860 lba = map_index_to_lba(index + 1);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002861 }
2862}
2863
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002864static int
2865resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002866{
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002867 u8 *cmd = scp->cmnd;
2868 u64 lba;
2869 u32 num;
2870 u32 ei_lba;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002871 unsigned long iflags;
FUJITA Tomonori19789102008-03-30 00:59:56 +09002872 int ret;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002873 bool check_prot;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002874
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002875 switch (cmd[0]) {
2876 case WRITE_16:
2877 ei_lba = 0;
2878 lba = get_unaligned_be64(cmd + 2);
2879 num = get_unaligned_be32(cmd + 10);
2880 check_prot = true;
2881 break;
2882 case WRITE_10:
2883 ei_lba = 0;
2884 lba = get_unaligned_be32(cmd + 2);
2885 num = get_unaligned_be16(cmd + 7);
2886 check_prot = true;
2887 break;
2888 case WRITE_6:
2889 ei_lba = 0;
2890 lba = (u32)cmd[3] | (u32)cmd[2] << 8 |
2891 (u32)(cmd[1] & 0x1f) << 16;
2892 num = (0 == cmd[4]) ? 256 : cmd[4];
2893 check_prot = true;
2894 break;
2895 case WRITE_12:
2896 ei_lba = 0;
2897 lba = get_unaligned_be32(cmd + 2);
2898 num = get_unaligned_be32(cmd + 6);
2899 check_prot = true;
2900 break;
2901 case 0x53: /* XDWRITEREAD(10) */
2902 ei_lba = 0;
2903 lba = get_unaligned_be32(cmd + 2);
2904 num = get_unaligned_be16(cmd + 7);
2905 check_prot = false;
2906 break;
2907 default: /* assume WRITE(32) */
2908 lba = get_unaligned_be64(cmd + 12);
2909 ei_lba = get_unaligned_be32(cmd + 20);
2910 num = get_unaligned_be32(cmd + 28);
2911 check_prot = false;
2912 break;
2913 }
2914 if (check_prot) {
2915 if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
2916 (cmd[1] & 0xe0)) {
2917 mk_sense_invalid_opcode(scp);
2918 return check_condition_result;
2919 }
2920 if ((scsi_debug_dif == SD_DIF_TYPE1_PROTECTION ||
2921 scsi_debug_dif == SD_DIF_TYPE3_PROTECTION) &&
2922 (cmd[1] & 0xe0) == 0)
2923 sdev_printk(KERN_ERR, scp->device, "Unprotected WR "
2924 "to DIF device\n");
2925 }
2926
2927 /* inline check_device_access_params() */
2928 if (lba + num > sdebug_capacity) {
2929 mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0);
2930 return check_condition_result;
2931 }
2932 /* transfer length excessive (tie in to block limits VPD page) */
2933 if (num > sdebug_store_sectors) {
2934 /* needs work to find which cdb byte 'num' comes from */
2935 mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0);
2936 return check_condition_result;
2937 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002938
Akinobu Mita6c78cc02014-02-26 22:57:03 +09002939 write_lock_irqsave(&atomic_rw, iflags);
2940
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002941 /* DIX + T10 DIF */
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002942 if (scsi_debug_dix && scsi_prot_sg_count(scp)) {
2943 int prot_ret = prot_verify_write(scp, lba, num, ei_lba);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002944
2945 if (prot_ret) {
Akinobu Mita6c78cc02014-02-26 22:57:03 +09002946 write_unlock_irqrestore(&atomic_rw, iflags);
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002947 mk_sense_buffer(scp, ILLEGAL_REQUEST, 0x10, prot_ret);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002948 return illegal_condition_result;
2949 }
2950 }
2951
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002952 ret = do_device_access(scp, lba, num, true);
Akinobu Mita9ed8d3d2013-04-16 22:11:55 +09002953 if (scsi_debug_lbp())
Martin K. Petersen44d92692009-10-15 14:45:27 -04002954 map_region(lba, num);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002955 write_unlock_irqrestore(&atomic_rw, iflags);
FUJITA Tomonori19789102008-03-30 00:59:56 +09002956 if (-1 == ret)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002957 return (DID_ERROR << 16);
Martin K. Petersen597136a2008-06-05 00:12:59 -04002958 else if ((ret < (num * scsi_debug_sector_size)) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07002959 (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002960 sdev_printk(KERN_INFO, scp->device,
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002961 "%s: write: cdb indicated=%u, IO sent=%d bytes\n",
2962 my_name, num * scsi_debug_sector_size, ret);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002963
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002964 if (sdebug_any_injecting_opt) {
2965 struct sdebug_scmd_extra_t *ep = scsi_cmd_priv(scp);
2966
2967 if (ep->inj_recovered) {
2968 mk_sense_buffer(scp, RECOVERED_ERROR,
2969 THRESHOLD_EXCEEDED, 0);
2970 return check_condition_result;
2971 } else if (ep->inj_dif) {
2972 /* Logical block guard check failed */
2973 mk_sense_buffer(scp, ABORTED_COMMAND, 0x10, 1);
2974 return illegal_condition_result;
2975 } else if (ep->inj_dix) {
2976 mk_sense_buffer(scp, ILLEGAL_REQUEST, 0x10, 1);
2977 return illegal_condition_result;
2978 }
2979 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002980 return 0;
2981}
2982
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002983static int
2984resp_write_same(struct scsi_cmnd *scp, u64 lba, u32 num, u32 ei_lba,
2985 bool unmap, bool ndob)
Martin K. Petersen44d92692009-10-15 14:45:27 -04002986{
2987 unsigned long iflags;
2988 unsigned long long i;
2989 int ret;
2990
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002991 ret = check_device_access_params(scp, lba, num);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002992 if (ret)
2993 return ret;
2994
2995 write_lock_irqsave(&atomic_rw, iflags);
2996
Akinobu Mita9ed8d3d2013-04-16 22:11:55 +09002997 if (unmap && scsi_debug_lbp()) {
Martin K. Petersen44d92692009-10-15 14:45:27 -04002998 unmap_region(lba, num);
2999 goto out;
3000 }
3001
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003002 /* if ndob then zero 1 logical block, else fetch 1 logical block */
3003 if (ndob) {
3004 memset(fake_storep + (lba * scsi_debug_sector_size), 0,
3005 scsi_debug_sector_size);
3006 ret = 0;
3007 } else
3008 ret = fetch_to_dev_buffer(scp, fake_storep +
3009 (lba * scsi_debug_sector_size),
3010 scsi_debug_sector_size);
Martin K. Petersen44d92692009-10-15 14:45:27 -04003011
3012 if (-1 == ret) {
3013 write_unlock_irqrestore(&atomic_rw, iflags);
3014 return (DID_ERROR << 16);
3015 } else if ((ret < (num * scsi_debug_sector_size)) &&
3016 (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003017 sdev_printk(KERN_INFO, scp->device,
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003018 "%s: %s: cdb indicated=%u, IO sent=%d bytes\n",
3019 my_name, "write same",
3020 num * scsi_debug_sector_size, ret);
Martin K. Petersen44d92692009-10-15 14:45:27 -04003021
3022 /* Copy first sector to remaining blocks */
3023 for (i = 1 ; i < num ; i++)
3024 memcpy(fake_storep + ((lba + i) * scsi_debug_sector_size),
3025 fake_storep + (lba * scsi_debug_sector_size),
3026 scsi_debug_sector_size);
3027
Akinobu Mita9ed8d3d2013-04-16 22:11:55 +09003028 if (scsi_debug_lbp())
Martin K. Petersen44d92692009-10-15 14:45:27 -04003029 map_region(lba, num);
3030out:
3031 write_unlock_irqrestore(&atomic_rw, iflags);
3032
3033 return 0;
3034}
3035
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003036static int
3037resp_write_same_10(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
3038{
3039 u8 *cmd = scp->cmnd;
3040 u32 lba;
3041 u16 num;
3042 u32 ei_lba = 0;
3043 bool unmap = false;
3044
3045 if (cmd[1] & 0x8) {
3046 if (scsi_debug_lbpws10 == 0) {
3047 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 1, 3);
3048 return check_condition_result;
3049 } else
3050 unmap = true;
3051 }
3052 lba = get_unaligned_be32(cmd + 2);
3053 num = get_unaligned_be16(cmd + 7);
3054 if (num > scsi_debug_write_same_length) {
3055 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 7, -1);
3056 return check_condition_result;
3057 }
3058 return resp_write_same(scp, lba, num, ei_lba, unmap, false);
3059}
3060
3061static int
3062resp_write_same_16(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
3063{
3064 u8 *cmd = scp->cmnd;
3065 u64 lba;
3066 u32 num;
3067 u32 ei_lba = 0;
3068 bool unmap = false;
3069 bool ndob = false;
3070
3071 if (cmd[1] & 0x8) { /* UNMAP */
3072 if (scsi_debug_lbpws == 0) {
3073 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 1, 3);
3074 return check_condition_result;
3075 } else
3076 unmap = true;
3077 }
3078 if (cmd[1] & 0x1) /* NDOB (no data-out buffer, assumes zeroes) */
3079 ndob = true;
3080 lba = get_unaligned_be64(cmd + 2);
3081 num = get_unaligned_be32(cmd + 10);
3082 if (num > scsi_debug_write_same_length) {
3083 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 10, -1);
3084 return check_condition_result;
3085 }
3086 return resp_write_same(scp, lba, num, ei_lba, unmap, ndob);
3087}
3088
Ewan D. Milneacafd0b2014-12-04 11:49:28 -05003089/* Note the mode field is in the same position as the (lower) service action
3090 * field. For the Report supported operation codes command, SPC-4 suggests
3091 * each mode of this command should be reported separately; for future. */
3092static int
3093resp_write_buffer(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
3094{
3095 u8 *cmd = scp->cmnd;
3096 struct scsi_device *sdp = scp->device;
3097 struct sdebug_dev_info *dp;
3098 u8 mode;
3099
3100 mode = cmd[1] & 0x1f;
3101 switch (mode) {
3102 case 0x4: /* download microcode (MC) and activate (ACT) */
3103 /* set UAs on this device only */
3104 set_bit(SDEBUG_UA_BUS_RESET, devip->uas_bm);
3105 set_bit(SDEBUG_UA_MICROCODE_CHANGED, devip->uas_bm);
3106 break;
3107 case 0x5: /* download MC, save and ACT */
3108 set_bit(SDEBUG_UA_MICROCODE_CHANGED_WO_RESET, devip->uas_bm);
3109 break;
3110 case 0x6: /* download MC with offsets and ACT */
3111 /* set UAs on most devices (LUs) in this target */
3112 list_for_each_entry(dp,
3113 &devip->sdbg_host->dev_info_list,
3114 dev_list)
3115 if (dp->target == sdp->id) {
3116 set_bit(SDEBUG_UA_BUS_RESET, dp->uas_bm);
3117 if (devip != dp)
3118 set_bit(SDEBUG_UA_MICROCODE_CHANGED,
3119 dp->uas_bm);
3120 }
3121 break;
3122 case 0x7: /* download MC with offsets, save, and ACT */
3123 /* set UA on all devices (LUs) in this target */
3124 list_for_each_entry(dp,
3125 &devip->sdbg_host->dev_info_list,
3126 dev_list)
3127 if (dp->target == sdp->id)
3128 set_bit(SDEBUG_UA_MICROCODE_CHANGED_WO_RESET,
3129 dp->uas_bm);
3130 break;
3131 default:
3132 /* do nothing for this command for other mode values */
3133 break;
3134 }
3135 return 0;
3136}
3137
Douglas Gilbert38d5c832014-11-24 21:27:12 -05003138static int
3139resp_comp_write(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
3140{
3141 u8 *cmd = scp->cmnd;
3142 u8 *arr;
3143 u8 *fake_storep_hold;
3144 u64 lba;
3145 u32 dnum;
3146 u32 lb_size = scsi_debug_sector_size;
3147 u8 num;
3148 unsigned long iflags;
3149 int ret;
Douglas Gilbertd467d312014-11-26 12:33:48 -05003150 int retval = 0;
Douglas Gilbert38d5c832014-11-24 21:27:12 -05003151
Douglas Gilbertd467d312014-11-26 12:33:48 -05003152 lba = get_unaligned_be64(cmd + 2);
Douglas Gilbert38d5c832014-11-24 21:27:12 -05003153 num = cmd[13]; /* 1 to a maximum of 255 logical blocks */
3154 if (0 == num)
3155 return 0; /* degenerate case, not an error */
Douglas Gilbert38d5c832014-11-24 21:27:12 -05003156 if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
3157 (cmd[1] & 0xe0)) {
3158 mk_sense_invalid_opcode(scp);
3159 return check_condition_result;
3160 }
3161 if ((scsi_debug_dif == SD_DIF_TYPE1_PROTECTION ||
3162 scsi_debug_dif == SD_DIF_TYPE3_PROTECTION) &&
3163 (cmd[1] & 0xe0) == 0)
3164 sdev_printk(KERN_ERR, scp->device, "Unprotected WR "
3165 "to DIF device\n");
3166
3167 /* inline check_device_access_params() */
3168 if (lba + num > sdebug_capacity) {
3169 mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0);
3170 return check_condition_result;
3171 }
3172 /* transfer length excessive (tie in to block limits VPD page) */
3173 if (num > sdebug_store_sectors) {
3174 /* needs work to find which cdb byte 'num' comes from */
3175 mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0);
3176 return check_condition_result;
3177 }
Douglas Gilbertd467d312014-11-26 12:33:48 -05003178 dnum = 2 * num;
3179 arr = kzalloc(dnum * lb_size, GFP_ATOMIC);
3180 if (NULL == arr) {
3181 mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC,
3182 INSUFF_RES_ASCQ);
3183 return check_condition_result;
3184 }
Douglas Gilbert38d5c832014-11-24 21:27:12 -05003185
3186 write_lock_irqsave(&atomic_rw, iflags);
3187
3188 /* trick do_device_access() to fetch both compare and write buffers
3189 * from data-in into arr. Safe (atomic) since write_lock held. */
3190 fake_storep_hold = fake_storep;
3191 fake_storep = arr;
3192 ret = do_device_access(scp, 0, dnum, true);
3193 fake_storep = fake_storep_hold;
3194 if (ret == -1) {
Douglas Gilbertd467d312014-11-26 12:33:48 -05003195 retval = DID_ERROR << 16;
3196 goto cleanup;
Douglas Gilbert38d5c832014-11-24 21:27:12 -05003197 } else if ((ret < (dnum * lb_size)) &&
3198 (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
3199 sdev_printk(KERN_INFO, scp->device, "%s: compare_write: cdb "
3200 "indicated=%u, IO sent=%d bytes\n", my_name,
3201 dnum * lb_size, ret);
3202 if (!comp_write_worker(lba, num, arr)) {
Douglas Gilbert38d5c832014-11-24 21:27:12 -05003203 mk_sense_buffer(scp, MISCOMPARE, MISCOMPARE_VERIFY_ASC, 0);
Douglas Gilbertd467d312014-11-26 12:33:48 -05003204 retval = check_condition_result;
3205 goto cleanup;
Douglas Gilbert38d5c832014-11-24 21:27:12 -05003206 }
3207 if (scsi_debug_lbp())
3208 map_region(lba, num);
Douglas Gilbertd467d312014-11-26 12:33:48 -05003209cleanup:
Douglas Gilbert38d5c832014-11-24 21:27:12 -05003210 write_unlock_irqrestore(&atomic_rw, iflags);
Douglas Gilbertd467d312014-11-26 12:33:48 -05003211 kfree(arr);
3212 return retval;
Douglas Gilbert38d5c832014-11-24 21:27:12 -05003213}
3214
Martin K. Petersen44d92692009-10-15 14:45:27 -04003215struct unmap_block_desc {
3216 __be64 lba;
3217 __be32 blocks;
3218 __be32 __reserved;
3219};
3220
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003221static int
3222resp_unmap(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
Martin K. Petersen44d92692009-10-15 14:45:27 -04003223{
3224 unsigned char *buf;
3225 struct unmap_block_desc *desc;
3226 unsigned int i, payload_len, descriptors;
3227 int ret;
Akinobu Mita6c78cc02014-02-26 22:57:03 +09003228 unsigned long iflags;
Martin K. Petersen44d92692009-10-15 14:45:27 -04003229
Martin K. Petersen44d92692009-10-15 14:45:27 -04003230
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003231 if (!scsi_debug_lbp())
3232 return 0; /* fib and say its done */
3233 payload_len = get_unaligned_be16(scp->cmnd + 7);
3234 BUG_ON(scsi_bufflen(scp) != payload_len);
Martin K. Petersen44d92692009-10-15 14:45:27 -04003235
3236 descriptors = (payload_len - 8) / 16;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003237 if (descriptors > scsi_debug_unmap_max_desc) {
3238 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 7, -1);
Martin K. Petersen44d92692009-10-15 14:45:27 -04003239 return check_condition_result;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003240 }
Martin K. Petersen44d92692009-10-15 14:45:27 -04003241
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003242 buf = kmalloc(scsi_bufflen(scp), GFP_ATOMIC);
3243 if (!buf) {
3244 mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC,
3245 INSUFF_RES_ASCQ);
3246 return check_condition_result;
3247 }
3248
3249 scsi_sg_copy_to_buffer(scp, buf, scsi_bufflen(scp));
Martin K. Petersen44d92692009-10-15 14:45:27 -04003250
3251 BUG_ON(get_unaligned_be16(&buf[0]) != payload_len - 2);
3252 BUG_ON(get_unaligned_be16(&buf[2]) != descriptors * 16);
3253
3254 desc = (void *)&buf[8];
3255
Akinobu Mita6c78cc02014-02-26 22:57:03 +09003256 write_lock_irqsave(&atomic_rw, iflags);
3257
Martin K. Petersen44d92692009-10-15 14:45:27 -04003258 for (i = 0 ; i < descriptors ; i++) {
3259 unsigned long long lba = get_unaligned_be64(&desc[i].lba);
3260 unsigned int num = get_unaligned_be32(&desc[i].blocks);
3261
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003262 ret = check_device_access_params(scp, lba, num);
Martin K. Petersen44d92692009-10-15 14:45:27 -04003263 if (ret)
3264 goto out;
3265
3266 unmap_region(lba, num);
3267 }
3268
3269 ret = 0;
3270
3271out:
Akinobu Mita6c78cc02014-02-26 22:57:03 +09003272 write_unlock_irqrestore(&atomic_rw, iflags);
Martin K. Petersen44d92692009-10-15 14:45:27 -04003273 kfree(buf);
3274
3275 return ret;
3276}
3277
3278#define SDEBUG_GET_LBA_STATUS_LEN 32
3279
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003280static int
3281resp_get_lba_status(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
Martin K. Petersen44d92692009-10-15 14:45:27 -04003282{
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003283 u8 *cmd = scp->cmnd;
3284 u64 lba;
3285 u32 alloc_len, mapped, num;
3286 u8 arr[SDEBUG_GET_LBA_STATUS_LEN];
Martin K. Petersen44d92692009-10-15 14:45:27 -04003287 int ret;
3288
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003289 lba = get_unaligned_be64(cmd + 2);
3290 alloc_len = get_unaligned_be32(cmd + 10);
Martin K. Petersen44d92692009-10-15 14:45:27 -04003291
3292 if (alloc_len < 24)
3293 return 0;
3294
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003295 ret = check_device_access_params(scp, lba, 1);
Martin K. Petersen44d92692009-10-15 14:45:27 -04003296 if (ret)
3297 return ret;
3298
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003299 if (scsi_debug_lbp())
3300 mapped = map_state(lba, &num);
3301 else {
3302 mapped = 1;
3303 /* following just in case virtual_gb changed */
3304 sdebug_capacity = get_sdebug_capacity();
3305 if (sdebug_capacity - lba <= 0xffffffff)
3306 num = sdebug_capacity - lba;
3307 else
3308 num = 0xffffffff;
3309 }
Martin K. Petersen44d92692009-10-15 14:45:27 -04003310
3311 memset(arr, 0, SDEBUG_GET_LBA_STATUS_LEN);
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003312 put_unaligned_be32(20, arr); /* Parameter Data Length */
3313 put_unaligned_be64(lba, arr + 8); /* LBA */
3314 put_unaligned_be32(num, arr + 16); /* Number of blocks */
3315 arr[20] = !mapped; /* prov_stat=0: mapped; 1: dealloc */
Martin K. Petersen44d92692009-10-15 14:45:27 -04003316
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003317 return fill_from_dev_buffer(scp, arr, SDEBUG_GET_LBA_STATUS_LEN);
Martin K. Petersen44d92692009-10-15 14:45:27 -04003318}
3319
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003320#define SDEBUG_RLUN_ARR_SZ 256
Linus Torvalds1da177e2005-04-16 15:20:36 -07003321
3322static int resp_report_luns(struct scsi_cmnd * scp,
3323 struct sdebug_dev_info * devip)
3324{
3325 unsigned int alloc_len;
Douglas Gilbert22017ed2014-11-24 23:04:47 -05003326 int lun_cnt, i, upper, num, n, want_wlun, shortish;
3327 u64 lun;
Douglas Gilbert01123ef2014-08-05 12:20:02 +02003328 unsigned char *cmd = scp->cmnd;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003329 int select_report = (int)cmd[2];
3330 struct scsi_lun *one_lun;
3331 unsigned char arr[SDEBUG_RLUN_ARR_SZ];
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003332 unsigned char * max_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003333
Ewan D. Milne19c8ead2014-12-04 11:49:27 -05003334 clear_luns_changed_on_target(devip);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003335 alloc_len = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24);
Douglas Gilbert22017ed2014-11-24 23:04:47 -05003336 shortish = (alloc_len < 4);
3337 if (shortish || (select_report > 2)) {
3338 mk_sense_invalid_fld(scp, SDEB_IN_CDB, shortish ? 6 : 2, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003339 return check_condition_result;
3340 }
3341 /* can produce response with up to 16k luns (lun 0 to lun 16383) */
3342 memset(arr, 0, SDEBUG_RLUN_ARR_SZ);
3343 lun_cnt = scsi_debug_max_luns;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003344 if (1 == select_report)
3345 lun_cnt = 0;
3346 else if (scsi_debug_no_lun_0 && (lun_cnt > 0))
3347 --lun_cnt;
Douglas Gilbert22017ed2014-11-24 23:04:47 -05003348 want_wlun = (select_report > 0) ? 1 : 0;
3349 num = lun_cnt + want_wlun;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003350 arr[2] = ((sizeof(struct scsi_lun) * num) >> 8) & 0xff;
3351 arr[3] = (sizeof(struct scsi_lun) * num) & 0xff;
3352 n = min((int)((SDEBUG_RLUN_ARR_SZ - 8) /
3353 sizeof(struct scsi_lun)), num);
3354 if (n < num) {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05003355 want_wlun = 0;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003356 lun_cnt = n;
3357 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003358 one_lun = (struct scsi_lun *) &arr[8];
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003359 max_addr = arr + SDEBUG_RLUN_ARR_SZ;
3360 for (i = 0, lun = (scsi_debug_no_lun_0 ? 1 : 0);
3361 ((i < lun_cnt) && ((unsigned char *)(one_lun + i) < max_addr));
3362 i++, lun++) {
3363 upper = (lun >> 8) & 0x3f;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003364 if (upper)
3365 one_lun[i].scsi_lun[0] =
3366 (upper | (SAM2_LUN_ADDRESS_METHOD << 6));
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003367 one_lun[i].scsi_lun[1] = lun & 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003368 }
Douglas Gilbert22017ed2014-11-24 23:04:47 -05003369 if (want_wlun) {
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003370 one_lun[i].scsi_lun[0] = (SAM2_WLUN_REPORT_LUNS >> 8) & 0xff;
3371 one_lun[i].scsi_lun[1] = SAM2_WLUN_REPORT_LUNS & 0xff;
3372 i++;
3373 }
3374 alloc_len = (unsigned char *)(one_lun + i) - arr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003375 return fill_from_dev_buffer(scp, arr,
3376 min((int)alloc_len, SDEBUG_RLUN_ARR_SZ));
3377}
3378
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003379static int resp_xdwriteread(struct scsi_cmnd *scp, unsigned long long lba,
3380 unsigned int num, struct sdebug_dev_info *devip)
3381{
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09003382 int j;
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003383 unsigned char *kaddr, *buf;
3384 unsigned int offset;
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003385 struct scsi_data_buffer *sdb = scsi_in(scp);
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09003386 struct sg_mapping_iter miter;
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003387
3388 /* better not to use temporary buffer. */
3389 buf = kmalloc(scsi_bufflen(scp), GFP_ATOMIC);
Akinobu Mitac5af0db2014-02-26 22:57:01 +09003390 if (!buf) {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05003391 mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC,
3392 INSUFF_RES_ASCQ);
Akinobu Mitac5af0db2014-02-26 22:57:01 +09003393 return check_condition_result;
3394 }
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003395
FUJITA Tomonori21a61822008-03-09 13:44:30 +09003396 scsi_sg_copy_to_buffer(scp, buf, scsi_bufflen(scp));
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003397
3398 offset = 0;
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09003399 sg_miter_start(&miter, sdb->table.sgl, sdb->table.nents,
3400 SG_MITER_ATOMIC | SG_MITER_TO_SG);
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003401
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09003402 while (sg_miter_next(&miter)) {
3403 kaddr = miter.addr;
3404 for (j = 0; j < miter.length; j++)
3405 *(kaddr + j) ^= *(buf + offset + j);
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003406
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09003407 offset += miter.length;
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003408 }
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09003409 sg_miter_stop(&miter);
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003410 kfree(buf);
3411
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09003412 return 0;
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003413}
3414
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003415static int
3416resp_xdwriteread_10(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
3417{
3418 u8 *cmd = scp->cmnd;
3419 u64 lba;
3420 u32 num;
3421 int errsts;
3422
3423 if (!scsi_bidi_cmnd(scp)) {
3424 mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC,
3425 INSUFF_RES_ASCQ);
3426 return check_condition_result;
3427 }
3428 errsts = resp_read_dt0(scp, devip);
3429 if (errsts)
3430 return errsts;
3431 if (!(cmd[1] & 0x4)) { /* DISABLE_WRITE is not set */
3432 errsts = resp_write_dt0(scp, devip);
3433 if (errsts)
3434 return errsts;
3435 }
3436 lba = get_unaligned_be32(cmd + 2);
3437 num = get_unaligned_be16(cmd + 7);
3438 return resp_xdwriteread(scp, lba, num, devip);
3439}
3440
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003441/* When timer or tasklet goes off this function is called. */
3442static void sdebug_q_cmd_complete(unsigned long indx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003443{
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003444 int qa_indx;
3445 int retiring = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003446 unsigned long iflags;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003447 struct sdebug_queued_cmd *sqcp;
3448 struct scsi_cmnd *scp;
3449 struct sdebug_dev_info *devip;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003450
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003451 atomic_inc(&sdebug_completions);
3452 qa_indx = indx;
3453 if ((qa_indx < 0) || (qa_indx >= SCSI_DEBUG_CANQUEUE)) {
Tomas Winklerc12879702015-07-28 16:54:20 +03003454 pr_err("wild qa_indx=%d\n", qa_indx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003455 return;
3456 }
3457 spin_lock_irqsave(&queued_arr_lock, iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003458 sqcp = &queued_arr[qa_indx];
3459 scp = sqcp->a_cmnd;
3460 if (NULL == scp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003461 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Tomas Winklerc12879702015-07-28 16:54:20 +03003462 pr_err("scp is NULL\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003463 return;
3464 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003465 devip = (struct sdebug_dev_info *)scp->device->hostdata;
3466 if (devip)
3467 atomic_dec(&devip->num_in_q);
3468 else
Tomas Winklerc12879702015-07-28 16:54:20 +03003469 pr_err("devip=NULL\n");
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003470 if (atomic_read(&retired_max_queue) > 0)
3471 retiring = 1;
3472
3473 sqcp->a_cmnd = NULL;
3474 if (!test_and_clear_bit(qa_indx, queued_in_use_bm)) {
3475 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Tomas Winklerc12879702015-07-28 16:54:20 +03003476 pr_err("Unexpected completion\n");
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003477 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003478 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003479
3480 if (unlikely(retiring)) { /* user has reduced max_queue */
3481 int k, retval;
3482
3483 retval = atomic_read(&retired_max_queue);
3484 if (qa_indx >= retval) {
3485 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Tomas Winklerc12879702015-07-28 16:54:20 +03003486 pr_err("index %d too large\n", retval);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003487 return;
3488 }
3489 k = find_last_bit(queued_in_use_bm, retval);
3490 if ((k < scsi_debug_max_queue) || (k == retval))
3491 atomic_set(&retired_max_queue, 0);
3492 else
3493 atomic_set(&retired_max_queue, k + 1);
3494 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003495 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003496 scp->scsi_done(scp); /* callback to mid level */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003497}
3498
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003499/* When high resolution timer goes off this function is called. */
3500static enum hrtimer_restart
3501sdebug_q_cmd_hrt_complete(struct hrtimer *timer)
3502{
3503 int qa_indx;
3504 int retiring = 0;
3505 unsigned long iflags;
3506 struct sdebug_hrtimer *sd_hrtp = (struct sdebug_hrtimer *)timer;
3507 struct sdebug_queued_cmd *sqcp;
3508 struct scsi_cmnd *scp;
3509 struct sdebug_dev_info *devip;
3510
3511 atomic_inc(&sdebug_completions);
3512 qa_indx = sd_hrtp->qa_indx;
3513 if ((qa_indx < 0) || (qa_indx >= SCSI_DEBUG_CANQUEUE)) {
Tomas Winklerc12879702015-07-28 16:54:20 +03003514 pr_err("wild qa_indx=%d\n", qa_indx);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003515 goto the_end;
3516 }
3517 spin_lock_irqsave(&queued_arr_lock, iflags);
3518 sqcp = &queued_arr[qa_indx];
3519 scp = sqcp->a_cmnd;
3520 if (NULL == scp) {
3521 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Tomas Winklerc12879702015-07-28 16:54:20 +03003522 pr_err("scp is NULL\n");
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003523 goto the_end;
3524 }
3525 devip = (struct sdebug_dev_info *)scp->device->hostdata;
3526 if (devip)
3527 atomic_dec(&devip->num_in_q);
3528 else
Tomas Winklerc12879702015-07-28 16:54:20 +03003529 pr_err("devip=NULL\n");
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003530 if (atomic_read(&retired_max_queue) > 0)
3531 retiring = 1;
3532
3533 sqcp->a_cmnd = NULL;
3534 if (!test_and_clear_bit(qa_indx, queued_in_use_bm)) {
3535 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Tomas Winklerc12879702015-07-28 16:54:20 +03003536 pr_err("Unexpected completion\n");
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003537 goto the_end;
3538 }
3539
3540 if (unlikely(retiring)) { /* user has reduced max_queue */
3541 int k, retval;
3542
3543 retval = atomic_read(&retired_max_queue);
3544 if (qa_indx >= retval) {
3545 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Tomas Winklerc12879702015-07-28 16:54:20 +03003546 pr_err("index %d too large\n", retval);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003547 goto the_end;
3548 }
3549 k = find_last_bit(queued_in_use_bm, retval);
3550 if ((k < scsi_debug_max_queue) || (k == retval))
3551 atomic_set(&retired_max_queue, 0);
3552 else
3553 atomic_set(&retired_max_queue, k + 1);
3554 }
3555 spin_unlock_irqrestore(&queued_arr_lock, iflags);
3556 scp->scsi_done(scp); /* callback to mid level */
3557the_end:
3558 return HRTIMER_NORESTART;
3559}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003560
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003561static struct sdebug_dev_info *
3562sdebug_device_create(struct sdebug_host_info *sdbg_host, gfp_t flags)
FUJITA Tomonori5cb2fc02008-03-20 11:09:16 +09003563{
3564 struct sdebug_dev_info *devip;
3565
3566 devip = kzalloc(sizeof(*devip), flags);
3567 if (devip) {
3568 devip->sdbg_host = sdbg_host;
3569 list_add_tail(&devip->dev_list, &sdbg_host->dev_info_list);
3570 }
3571 return devip;
3572}
3573
Linus Torvalds1da177e2005-04-16 15:20:36 -07003574static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev)
3575{
3576 struct sdebug_host_info * sdbg_host;
3577 struct sdebug_dev_info * open_devip = NULL;
3578 struct sdebug_dev_info * devip =
3579 (struct sdebug_dev_info *)sdev->hostdata;
3580
3581 if (devip)
3582 return devip;
FUJITA Tomonorid1e4c9c2008-03-02 18:30:18 +09003583 sdbg_host = *(struct sdebug_host_info **)shost_priv(sdev->host);
3584 if (!sdbg_host) {
Tomas Winklerc12879702015-07-28 16:54:20 +03003585 pr_err("Host info NULL\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003586 return NULL;
3587 }
3588 list_for_each_entry(devip, &sdbg_host->dev_info_list, dev_list) {
3589 if ((devip->used) && (devip->channel == sdev->channel) &&
3590 (devip->target == sdev->id) &&
3591 (devip->lun == sdev->lun))
3592 return devip;
3593 else {
3594 if ((!devip->used) && (!open_devip))
3595 open_devip = devip;
3596 }
3597 }
FUJITA Tomonori5cb2fc02008-03-20 11:09:16 +09003598 if (!open_devip) { /* try and make a new one */
3599 open_devip = sdebug_device_create(sdbg_host, GFP_ATOMIC);
3600 if (!open_devip) {
Tomas Winklerc12879702015-07-28 16:54:20 +03003601 pr_err("out of memory at line %d\n", __LINE__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003602 return NULL;
3603 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003604 }
FUJITA Tomonoria75869d2008-03-20 11:09:17 +09003605
3606 open_devip->channel = sdev->channel;
3607 open_devip->target = sdev->id;
3608 open_devip->lun = sdev->lun;
3609 open_devip->sdbg_host = sdbg_host;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003610 atomic_set(&open_devip->num_in_q, 0);
3611 set_bit(SDEBUG_UA_POR, open_devip->uas_bm);
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003612 open_devip->used = true;
FUJITA Tomonoria75869d2008-03-20 11:09:17 +09003613 return open_devip;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003614}
3615
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003616static int scsi_debug_slave_alloc(struct scsi_device *sdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003617{
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003618 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
Tomas Winklerc12879702015-07-28 16:54:20 +03003619 pr_info("slave_alloc <%u %u %u %llu>\n",
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003620 sdp->host->host_no, sdp->channel, sdp->id, sdp->lun);
Nick Piggin75ad23b2008-04-29 14:48:33 +02003621 queue_flag_set_unlocked(QUEUE_FLAG_BIDI, sdp->request_queue);
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003622 return 0;
3623}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003624
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003625static int scsi_debug_slave_configure(struct scsi_device *sdp)
3626{
3627 struct sdebug_dev_info *devip;
FUJITA Tomonoria34c4e92008-03-25 09:26:50 +09003628
Linus Torvalds1da177e2005-04-16 15:20:36 -07003629 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
Tomas Winklerc12879702015-07-28 16:54:20 +03003630 pr_info("slave_configure <%u %u %u %llu>\n",
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003631 sdp->host->host_no, sdp->channel, sdp->id, sdp->lun);
3632 if (sdp->host->max_cmd_len != SCSI_DEBUG_MAX_CMD_LEN)
3633 sdp->host->max_cmd_len = SCSI_DEBUG_MAX_CMD_LEN;
3634 devip = devInfoReg(sdp);
3635 if (NULL == devip)
3636 return 1; /* no resources, will be marked offline */
Christoph Hellwigc8b09f62014-11-03 20:15:14 +01003637 sdp->hostdata = devip;
Akinobu Mita6bb5e6e2014-06-02 22:56:49 +09003638 blk_queue_max_segment_size(sdp->request_queue, -1U);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04003639 if (scsi_debug_no_uld)
3640 sdp->no_uld_attach = 1;
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003641 return 0;
3642}
3643
3644static void scsi_debug_slave_destroy(struct scsi_device *sdp)
3645{
3646 struct sdebug_dev_info *devip =
3647 (struct sdebug_dev_info *)sdp->hostdata;
3648
3649 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
Tomas Winklerc12879702015-07-28 16:54:20 +03003650 pr_info("slave_destroy <%u %u %u %llu>\n",
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003651 sdp->host->host_no, sdp->channel, sdp->id, sdp->lun);
3652 if (devip) {
Lucas De Marchi25985ed2011-03-30 22:57:33 -03003653 /* make this slot available for re-use */
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003654 devip->used = false;
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003655 sdp->hostdata = NULL;
3656 }
3657}
3658
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003659/* Returns 1 if cmnd found (deletes its timer or tasklet), else returns 0 */
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003660static int stop_queued_cmnd(struct scsi_cmnd *cmnd)
3661{
3662 unsigned long iflags;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003663 int k, qmax, r_qmax;
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003664 struct sdebug_queued_cmd *sqcp;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003665 struct sdebug_dev_info *devip;
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003666
3667 spin_lock_irqsave(&queued_arr_lock, iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003668 qmax = scsi_debug_max_queue;
3669 r_qmax = atomic_read(&retired_max_queue);
3670 if (r_qmax > qmax)
3671 qmax = r_qmax;
3672 for (k = 0; k < qmax; ++k) {
3673 if (test_bit(k, queued_in_use_bm)) {
3674 sqcp = &queued_arr[k];
3675 if (cmnd == sqcp->a_cmnd) {
Douglas Gilbertdb525fc2014-08-31 19:09:59 -04003676 devip = (struct sdebug_dev_info *)
3677 cmnd->device->hostdata;
3678 if (devip)
3679 atomic_dec(&devip->num_in_q);
3680 sqcp->a_cmnd = NULL;
3681 spin_unlock_irqrestore(&queued_arr_lock,
3682 iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003683 if (scsi_debug_ndelay > 0) {
3684 if (sqcp->sd_hrtp)
3685 hrtimer_cancel(
3686 &sqcp->sd_hrtp->hrt);
3687 } else if (scsi_debug_delay > 0) {
3688 if (sqcp->cmnd_timerp)
3689 del_timer_sync(
3690 sqcp->cmnd_timerp);
3691 } else if (scsi_debug_delay < 0) {
3692 if (sqcp->tletp)
3693 tasklet_kill(sqcp->tletp);
3694 }
Douglas Gilbertdb525fc2014-08-31 19:09:59 -04003695 clear_bit(k, queued_in_use_bm);
3696 return 1;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003697 }
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003698 }
3699 }
3700 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Douglas Gilbertdb525fc2014-08-31 19:09:59 -04003701 return 0;
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003702}
3703
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003704/* Deletes (stops) timers or tasklets of all queued commands */
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003705static void stop_all_queued(void)
3706{
3707 unsigned long iflags;
3708 int k;
3709 struct sdebug_queued_cmd *sqcp;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003710 struct sdebug_dev_info *devip;
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003711
3712 spin_lock_irqsave(&queued_arr_lock, iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003713 for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) {
3714 if (test_bit(k, queued_in_use_bm)) {
3715 sqcp = &queued_arr[k];
3716 if (sqcp->a_cmnd) {
Douglas Gilbertdb525fc2014-08-31 19:09:59 -04003717 devip = (struct sdebug_dev_info *)
3718 sqcp->a_cmnd->device->hostdata;
3719 if (devip)
3720 atomic_dec(&devip->num_in_q);
3721 sqcp->a_cmnd = NULL;
3722 spin_unlock_irqrestore(&queued_arr_lock,
3723 iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003724 if (scsi_debug_ndelay > 0) {
3725 if (sqcp->sd_hrtp)
3726 hrtimer_cancel(
3727 &sqcp->sd_hrtp->hrt);
3728 } else if (scsi_debug_delay > 0) {
3729 if (sqcp->cmnd_timerp)
3730 del_timer_sync(
3731 sqcp->cmnd_timerp);
3732 } else if (scsi_debug_delay < 0) {
3733 if (sqcp->tletp)
3734 tasklet_kill(sqcp->tletp);
3735 }
Douglas Gilbertdb525fc2014-08-31 19:09:59 -04003736 clear_bit(k, queued_in_use_bm);
3737 spin_lock_irqsave(&queued_arr_lock, iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003738 }
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003739 }
3740 }
3741 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003742}
3743
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003744/* Free queued command memory on heap */
3745static void free_all_queued(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003746{
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003747 unsigned long iflags;
3748 int k;
3749 struct sdebug_queued_cmd *sqcp;
3750
3751 spin_lock_irqsave(&queued_arr_lock, iflags);
3752 for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) {
3753 sqcp = &queued_arr[k];
3754 kfree(sqcp->cmnd_timerp);
3755 sqcp->cmnd_timerp = NULL;
3756 kfree(sqcp->tletp);
3757 sqcp->tletp = NULL;
3758 kfree(sqcp->sd_hrtp);
3759 sqcp->sd_hrtp = NULL;
3760 }
3761 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003762}
3763
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003764static int scsi_debug_abort(struct scsi_cmnd *SCpnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003765{
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003766 ++num_aborts;
3767 if (SCpnt) {
3768 if (SCpnt->device &&
3769 (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts))
3770 sdev_printk(KERN_INFO, SCpnt->device, "%s\n",
3771 __func__);
3772 stop_queued_cmnd(SCpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003773 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003774 return SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003775}
3776
3777static int scsi_debug_device_reset(struct scsi_cmnd * SCpnt)
3778{
3779 struct sdebug_dev_info * devip;
3780
Linus Torvalds1da177e2005-04-16 15:20:36 -07003781 ++num_dev_resets;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003782 if (SCpnt && SCpnt->device) {
3783 struct scsi_device *sdp = SCpnt->device;
3784
3785 if (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts)
3786 sdev_printk(KERN_INFO, sdp, "%s\n", __func__);
3787 devip = devInfoReg(sdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003788 if (devip)
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003789 set_bit(SDEBUG_UA_POR, devip->uas_bm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003790 }
3791 return SUCCESS;
3792}
3793
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003794static int scsi_debug_target_reset(struct scsi_cmnd *SCpnt)
3795{
3796 struct sdebug_host_info *sdbg_host;
3797 struct sdebug_dev_info *devip;
3798 struct scsi_device *sdp;
3799 struct Scsi_Host *hp;
3800 int k = 0;
3801
3802 ++num_target_resets;
3803 if (!SCpnt)
3804 goto lie;
3805 sdp = SCpnt->device;
3806 if (!sdp)
3807 goto lie;
3808 if (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts)
3809 sdev_printk(KERN_INFO, sdp, "%s\n", __func__);
3810 hp = sdp->host;
3811 if (!hp)
3812 goto lie;
3813 sdbg_host = *(struct sdebug_host_info **)shost_priv(hp);
3814 if (sdbg_host) {
3815 list_for_each_entry(devip,
3816 &sdbg_host->dev_info_list,
3817 dev_list)
3818 if (devip->target == sdp->id) {
3819 set_bit(SDEBUG_UA_BUS_RESET, devip->uas_bm);
3820 ++k;
3821 }
3822 }
3823 if (SCSI_DEBUG_OPT_RESET_NOISE & scsi_debug_opts)
3824 sdev_printk(KERN_INFO, sdp,
3825 "%s: %d device(s) found in target\n", __func__, k);
3826lie:
3827 return SUCCESS;
3828}
3829
Linus Torvalds1da177e2005-04-16 15:20:36 -07003830static int scsi_debug_bus_reset(struct scsi_cmnd * SCpnt)
3831{
3832 struct sdebug_host_info *sdbg_host;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003833 struct sdebug_dev_info *devip;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003834 struct scsi_device * sdp;
3835 struct Scsi_Host * hp;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003836 int k = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003837
Linus Torvalds1da177e2005-04-16 15:20:36 -07003838 ++num_bus_resets;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003839 if (!(SCpnt && SCpnt->device))
3840 goto lie;
3841 sdp = SCpnt->device;
3842 if (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts)
3843 sdev_printk(KERN_INFO, sdp, "%s\n", __func__);
3844 hp = sdp->host;
3845 if (hp) {
FUJITA Tomonorid1e4c9c2008-03-02 18:30:18 +09003846 sdbg_host = *(struct sdebug_host_info **)shost_priv(hp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003847 if (sdbg_host) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003848 list_for_each_entry(devip,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003849 &sdbg_host->dev_info_list,
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003850 dev_list) {
3851 set_bit(SDEBUG_UA_BUS_RESET, devip->uas_bm);
3852 ++k;
3853 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003854 }
3855 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003856 if (SCSI_DEBUG_OPT_RESET_NOISE & scsi_debug_opts)
3857 sdev_printk(KERN_INFO, sdp,
3858 "%s: %d device(s) found in host\n", __func__, k);
3859lie:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003860 return SUCCESS;
3861}
3862
3863static int scsi_debug_host_reset(struct scsi_cmnd * SCpnt)
3864{
3865 struct sdebug_host_info * sdbg_host;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003866 struct sdebug_dev_info *devip;
3867 int k = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003868
Linus Torvalds1da177e2005-04-16 15:20:36 -07003869 ++num_host_resets;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003870 if ((SCpnt->device) && (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts))
3871 sdev_printk(KERN_INFO, SCpnt->device, "%s\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003872 spin_lock(&sdebug_host_list_lock);
3873 list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003874 list_for_each_entry(devip, &sdbg_host->dev_info_list,
3875 dev_list) {
3876 set_bit(SDEBUG_UA_BUS_RESET, devip->uas_bm);
3877 ++k;
3878 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003879 }
3880 spin_unlock(&sdebug_host_list_lock);
3881 stop_all_queued();
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003882 if (SCSI_DEBUG_OPT_RESET_NOISE & scsi_debug_opts)
3883 sdev_printk(KERN_INFO, SCpnt->device,
3884 "%s: %d device(s) found\n", __func__, k);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003885 return SUCCESS;
3886}
3887
FUJITA Tomonorif58b0ef2008-03-30 00:59:54 +09003888static void __init sdebug_build_parts(unsigned char *ramp,
FUJITA Tomonori5f2578e2008-03-30 00:59:57 +09003889 unsigned long store_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003890{
3891 struct partition * pp;
3892 int starts[SDEBUG_MAX_PARTS + 2];
3893 int sectors_per_part, num_sectors, k;
3894 int heads_by_sects, start_sec, end_sec;
3895
3896 /* assume partition table already zeroed */
FUJITA Tomonorif58b0ef2008-03-30 00:59:54 +09003897 if ((scsi_debug_num_parts < 1) || (store_size < 1048576))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003898 return;
3899 if (scsi_debug_num_parts > SDEBUG_MAX_PARTS) {
3900 scsi_debug_num_parts = SDEBUG_MAX_PARTS;
Tomas Winklerc12879702015-07-28 16:54:20 +03003901 pr_warn("reducing partitions to %d\n", SDEBUG_MAX_PARTS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003902 }
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003903 num_sectors = (int)sdebug_store_sectors;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003904 sectors_per_part = (num_sectors - sdebug_sectors_per)
3905 / scsi_debug_num_parts;
3906 heads_by_sects = sdebug_heads * sdebug_sectors_per;
3907 starts[0] = sdebug_sectors_per;
3908 for (k = 1; k < scsi_debug_num_parts; ++k)
3909 starts[k] = ((k * sectors_per_part) / heads_by_sects)
3910 * heads_by_sects;
3911 starts[scsi_debug_num_parts] = num_sectors;
3912 starts[scsi_debug_num_parts + 1] = 0;
3913
3914 ramp[510] = 0x55; /* magic partition markings */
3915 ramp[511] = 0xAA;
3916 pp = (struct partition *)(ramp + 0x1be);
3917 for (k = 0; starts[k + 1]; ++k, ++pp) {
3918 start_sec = starts[k];
3919 end_sec = starts[k + 1] - 1;
3920 pp->boot_ind = 0;
3921
3922 pp->cyl = start_sec / heads_by_sects;
3923 pp->head = (start_sec - (pp->cyl * heads_by_sects))
3924 / sdebug_sectors_per;
3925 pp->sector = (start_sec % sdebug_sectors_per) + 1;
3926
3927 pp->end_cyl = end_sec / heads_by_sects;
3928 pp->end_head = (end_sec - (pp->end_cyl * heads_by_sects))
3929 / sdebug_sectors_per;
3930 pp->end_sector = (end_sec % sdebug_sectors_per) + 1;
3931
Akinobu Mita150c3542013-08-26 22:08:40 +09003932 pp->start_sect = cpu_to_le32(start_sec);
3933 pp->nr_sects = cpu_to_le32(end_sec - start_sec + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003934 pp->sys_ind = 0x83; /* plain Linux partition */
3935 }
3936}
3937
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003938static int
3939schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip,
3940 int scsi_result, int delta_jiff)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003941{
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003942 unsigned long iflags;
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003943 int k, num_in_q, qdepth, inject;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003944 struct sdebug_queued_cmd *sqcp = NULL;
3945 struct scsi_device *sdp = cmnd->device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003946
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003947 if (NULL == cmnd || NULL == devip) {
Tomas Winklerc12879702015-07-28 16:54:20 +03003948 pr_warn("called with NULL cmnd or devip pointer\n");
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003949 /* no particularly good error to report back */
3950 return SCSI_MLQUEUE_HOST_BUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003951 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003952 if ((scsi_result) && (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
3953 sdev_printk(KERN_INFO, sdp, "%s: non-zero result=0x%x\n",
3954 __func__, scsi_result);
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003955 if (delta_jiff == 0)
3956 goto respond_in_thread;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003957
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003958 /* schedule the response at a later time if resources permit */
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003959 spin_lock_irqsave(&queued_arr_lock, iflags);
3960 num_in_q = atomic_read(&devip->num_in_q);
3961 qdepth = cmnd->device->queue_depth;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003962 inject = 0;
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003963 if ((qdepth > 0) && (num_in_q >= qdepth)) {
3964 if (scsi_result) {
3965 spin_unlock_irqrestore(&queued_arr_lock, iflags);
3966 goto respond_in_thread;
3967 } else
3968 scsi_result = device_qfull_result;
3969 } else if ((scsi_debug_every_nth != 0) &&
3970 (SCSI_DEBUG_OPT_RARE_TSF & scsi_debug_opts) &&
3971 (scsi_result == 0)) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003972 if ((num_in_q == (qdepth - 1)) &&
3973 (atomic_inc_return(&sdebug_a_tsf) >=
3974 abs(scsi_debug_every_nth))) {
3975 atomic_set(&sdebug_a_tsf, 0);
3976 inject = 1;
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003977 scsi_result = device_qfull_result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003978 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003979 }
3980
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003981 k = find_first_zero_bit(queued_in_use_bm, scsi_debug_max_queue);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003982 if (k >= scsi_debug_max_queue) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003983 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003984 if (scsi_result)
3985 goto respond_in_thread;
3986 else if (SCSI_DEBUG_OPT_ALL_TSF & scsi_debug_opts)
3987 scsi_result = device_qfull_result;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003988 if (SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts)
3989 sdev_printk(KERN_INFO, sdp,
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003990 "%s: max_queue=%d exceeded, %s\n",
3991 __func__, scsi_debug_max_queue,
3992 (scsi_result ? "status: TASK SET FULL" :
3993 "report: host busy"));
3994 if (scsi_result)
3995 goto respond_in_thread;
3996 else
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003997 return SCSI_MLQUEUE_HOST_BUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003998 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003999 __set_bit(k, queued_in_use_bm);
4000 atomic_inc(&devip->num_in_q);
4001 sqcp = &queued_arr[k];
4002 sqcp->a_cmnd = cmnd;
4003 cmnd->result = scsi_result;
4004 spin_unlock_irqrestore(&queued_arr_lock, iflags);
4005 if (delta_jiff > 0) {
4006 if (NULL == sqcp->cmnd_timerp) {
4007 sqcp->cmnd_timerp = kmalloc(sizeof(struct timer_list),
4008 GFP_ATOMIC);
4009 if (NULL == sqcp->cmnd_timerp)
4010 return SCSI_MLQUEUE_HOST_BUSY;
4011 init_timer(sqcp->cmnd_timerp);
4012 }
4013 sqcp->cmnd_timerp->function = sdebug_q_cmd_complete;
4014 sqcp->cmnd_timerp->data = k;
4015 sqcp->cmnd_timerp->expires = get_jiffies_64() + delta_jiff;
4016 add_timer(sqcp->cmnd_timerp);
4017 } else if (scsi_debug_ndelay > 0) {
4018 ktime_t kt = ktime_set(0, scsi_debug_ndelay);
4019 struct sdebug_hrtimer *sd_hp = sqcp->sd_hrtp;
4020
4021 if (NULL == sd_hp) {
4022 sd_hp = kmalloc(sizeof(*sd_hp), GFP_ATOMIC);
4023 if (NULL == sd_hp)
4024 return SCSI_MLQUEUE_HOST_BUSY;
4025 sqcp->sd_hrtp = sd_hp;
4026 hrtimer_init(&sd_hp->hrt, CLOCK_MONOTONIC,
4027 HRTIMER_MODE_REL);
4028 sd_hp->hrt.function = sdebug_q_cmd_hrt_complete;
4029 sd_hp->qa_indx = k;
4030 }
4031 hrtimer_start(&sd_hp->hrt, kt, HRTIMER_MODE_REL);
4032 } else { /* delay < 0 */
4033 if (NULL == sqcp->tletp) {
4034 sqcp->tletp = kmalloc(sizeof(*sqcp->tletp),
4035 GFP_ATOMIC);
4036 if (NULL == sqcp->tletp)
4037 return SCSI_MLQUEUE_HOST_BUSY;
4038 tasklet_init(sqcp->tletp,
4039 sdebug_q_cmd_complete, k);
4040 }
4041 if (-1 == delta_jiff)
4042 tasklet_hi_schedule(sqcp->tletp);
4043 else
4044 tasklet_schedule(sqcp->tletp);
4045 }
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02004046 if ((SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts) &&
4047 (scsi_result == device_qfull_result))
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004048 sdev_printk(KERN_INFO, sdp,
4049 "%s: num_in_q=%d +1, %s%s\n", __func__,
4050 num_in_q, (inject ? "<inject> " : ""),
4051 "status: TASK SET FULL");
4052 return 0;
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02004053
4054respond_in_thread: /* call back to mid-layer using invocation thread */
4055 cmnd->result = scsi_result;
4056 cmnd->scsi_done(cmnd);
4057 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004058}
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004059
Douglas Gilbert23183912006-09-16 20:30:47 -04004060/* Note: The following macros create attribute files in the
4061 /sys/module/scsi_debug/parameters directory. Unfortunately this
4062 driver is unaware of a change and cannot trigger auxiliary actions
4063 as it can when the corresponding attribute in the
4064 /sys/bus/pseudo/drivers/scsi_debug directory is changed.
4065 */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004066module_param_named(add_host, scsi_debug_add_host, int, S_IRUGO | S_IWUSR);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004067module_param_named(ato, scsi_debug_ato, int, S_IRUGO);
Akinobu Mita0759c662014-02-26 22:57:04 +09004068module_param_named(clustering, scsi_debug_clustering, bool, S_IRUGO | S_IWUSR);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004069module_param_named(delay, scsi_debug_delay, int, S_IRUGO | S_IWUSR);
4070module_param_named(dev_size_mb, scsi_debug_dev_size_mb, int, S_IRUGO);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004071module_param_named(dif, scsi_debug_dif, int, S_IRUGO);
4072module_param_named(dix, scsi_debug_dix, int, S_IRUGO);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004073module_param_named(dsense, scsi_debug_dsense, int, S_IRUGO | S_IWUSR);
4074module_param_named(every_nth, scsi_debug_every_nth, int, S_IRUGO | S_IWUSR);
Douglas Gilbert23183912006-09-16 20:30:47 -04004075module_param_named(fake_rw, scsi_debug_fake_rw, int, S_IRUGO | S_IWUSR);
Akinobu Mita68aee7b2013-09-18 21:27:27 +09004076module_param_named(guard, scsi_debug_guard, uint, S_IRUGO);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004077module_param_named(host_lock, scsi_debug_host_lock, bool, S_IRUGO | S_IWUSR);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004078module_param_named(lbpu, scsi_debug_lbpu, int, S_IRUGO);
4079module_param_named(lbpws, scsi_debug_lbpws, int, S_IRUGO);
4080module_param_named(lbpws10, scsi_debug_lbpws10, int, S_IRUGO);
Eric Sandeenbe1dd782012-03-08 00:03:59 -06004081module_param_named(lbprz, scsi_debug_lbprz, int, S_IRUGO);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004082module_param_named(lowest_aligned, scsi_debug_lowest_aligned, int, S_IRUGO);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004083module_param_named(max_luns, scsi_debug_max_luns, int, S_IRUGO | S_IWUSR);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004084module_param_named(max_queue, scsi_debug_max_queue, int, S_IRUGO | S_IWUSR);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004085module_param_named(ndelay, scsi_debug_ndelay, int, S_IRUGO | S_IWUSR);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004086module_param_named(no_lun_0, scsi_debug_no_lun_0, int, S_IRUGO | S_IWUSR);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004087module_param_named(no_uld, scsi_debug_no_uld, int, S_IRUGO);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004088module_param_named(num_parts, scsi_debug_num_parts, int, S_IRUGO);
4089module_param_named(num_tgts, scsi_debug_num_tgts, int, S_IRUGO | S_IWUSR);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004090module_param_named(opt_blks, scsi_debug_opt_blks, int, S_IRUGO);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004091module_param_named(opts, scsi_debug_opts, int, S_IRUGO | S_IWUSR);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004092module_param_named(physblk_exp, scsi_debug_physblk_exp, int, S_IRUGO);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004093module_param_named(ptype, scsi_debug_ptype, int, S_IRUGO | S_IWUSR);
Martin Pittd9867882012-09-06 12:04:33 +02004094module_param_named(removable, scsi_debug_removable, bool, S_IRUGO | S_IWUSR);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004095module_param_named(scsi_level, scsi_debug_scsi_level, int, S_IRUGO);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004096module_param_named(sector_size, scsi_debug_sector_size, int, S_IRUGO);
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05004097module_param_named(strict, scsi_debug_strict, bool, S_IRUGO | S_IWUSR);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004098module_param_named(unmap_alignment, scsi_debug_unmap_alignment, int, S_IRUGO);
4099module_param_named(unmap_granularity, scsi_debug_unmap_granularity, int, S_IRUGO);
4100module_param_named(unmap_max_blocks, scsi_debug_unmap_max_blocks, int, S_IRUGO);
4101module_param_named(unmap_max_desc, scsi_debug_unmap_max_desc, int, S_IRUGO);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004102module_param_named(virtual_gb, scsi_debug_virtual_gb, int, S_IRUGO | S_IWUSR);
Douglas Gilbert23183912006-09-16 20:30:47 -04004103module_param_named(vpd_use_hostno, scsi_debug_vpd_use_hostno, int,
4104 S_IRUGO | S_IWUSR);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004105module_param_named(write_same_length, scsi_debug_write_same_length, int,
4106 S_IRUGO | S_IWUSR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004107
4108MODULE_AUTHOR("Eric Youngdale + Douglas Gilbert");
4109MODULE_DESCRIPTION("SCSI debug adapter driver");
4110MODULE_LICENSE("GPL");
4111MODULE_VERSION(SCSI_DEBUG_VERSION);
4112
4113MODULE_PARM_DESC(add_host, "0..127 hosts allowed(def=1)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004114MODULE_PARM_DESC(ato, "application tag ownership: 0=disk 1=host (def=1)");
Akinobu Mita0759c662014-02-26 22:57:04 +09004115MODULE_PARM_DESC(clustering, "when set enables larger transfers (def=0)");
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004116MODULE_PARM_DESC(delay, "response delay (def=1 jiffy); 0:imm, -1,-2:tiny");
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05004117MODULE_PARM_DESC(dev_size_mb, "size in MiB of ram shared by devs(def=8)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004118MODULE_PARM_DESC(dif, "data integrity field type: 0-3 (def=0)");
4119MODULE_PARM_DESC(dix, "data integrity extensions mask (def=0)");
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004120MODULE_PARM_DESC(dsense, "use descriptor sense format(def=0 -> fixed)");
Randy Dunlapbeb87c32007-06-11 11:36:40 -07004121MODULE_PARM_DESC(every_nth, "timeout every nth command(def=0)");
Douglas Gilbert23183912006-09-16 20:30:47 -04004122MODULE_PARM_DESC(fake_rw, "fake reads/writes instead of copying (def=0)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004123MODULE_PARM_DESC(guard, "protection checksum: 0=crc, 1=ip (def=0)");
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004124MODULE_PARM_DESC(host_lock, "use host_lock around all commands (def=0)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004125MODULE_PARM_DESC(lbpu, "enable LBP, support UNMAP command (def=0)");
4126MODULE_PARM_DESC(lbpws, "enable LBP, support WRITE SAME(16) with UNMAP bit (def=0)");
4127MODULE_PARM_DESC(lbpws10, "enable LBP, support WRITE SAME(10) with UNMAP bit (def=0)");
Eric Sandeenbe1dd782012-03-08 00:03:59 -06004128MODULE_PARM_DESC(lbprz, "unmapped blocks return 0 on read (def=1)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004129MODULE_PARM_DESC(lowest_aligned, "lowest aligned lba (def=0)");
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004130MODULE_PARM_DESC(max_luns, "number of LUNs per target to simulate(def=1)");
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004131MODULE_PARM_DESC(max_queue, "max number of queued commands (1 to max(def))");
4132MODULE_PARM_DESC(ndelay, "response delay in nanoseconds (def=0 -> ignore)");
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004133MODULE_PARM_DESC(no_lun_0, "no LU number 0 (def=0 -> have lun 0)");
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004134MODULE_PARM_DESC(no_uld, "stop ULD (e.g. sd driver) attaching (def=0))");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004135MODULE_PARM_DESC(num_parts, "number of partitions(def=0)");
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004136MODULE_PARM_DESC(num_tgts, "number of targets per host to simulate(def=1)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004137MODULE_PARM_DESC(opt_blks, "optimal transfer length in block (def=64)");
Douglas Gilbert6f3cbf52007-01-05 00:05:25 -05004138MODULE_PARM_DESC(opts, "1->noise, 2->medium_err, 4->timeout, 8->recovered_err... (def=0)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004139MODULE_PARM_DESC(physblk_exp, "physical block exponent (def=0)");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004140MODULE_PARM_DESC(ptype, "SCSI peripheral type(def=0[disk])");
Martin Pittd9867882012-09-06 12:04:33 +02004141MODULE_PARM_DESC(removable, "claim to have removable media (def=0)");
Douglas Gilberte46b0342014-08-05 12:21:53 +02004142MODULE_PARM_DESC(scsi_level, "SCSI level to simulate(def=6[SPC-4])");
Martin K. Petersenea61fca2009-05-15 00:40:33 -04004143MODULE_PARM_DESC(sector_size, "logical block size in bytes (def=512)");
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05004144MODULE_PARM_DESC(strict, "stricter checks: reserved field in cdb (def=0)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004145MODULE_PARM_DESC(unmap_alignment, "lowest aligned thin provisioning lba (def=0)");
4146MODULE_PARM_DESC(unmap_granularity, "thin provisioning granularity in blocks (def=1)");
Martin K. Petersen60147592010-08-19 11:49:00 -04004147MODULE_PARM_DESC(unmap_max_blocks, "max # of blocks can be unmapped in one cmd (def=0xffffffff)");
4148MODULE_PARM_DESC(unmap_max_desc, "max # of ranges that can be unmapped in one cmd (def=256)");
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05004149MODULE_PARM_DESC(virtual_gb, "virtual gigabyte (GiB) size (def=0 -> use dev_size_mb)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004150MODULE_PARM_DESC(vpd_use_hostno, "0 -> dev ids ignore hostno (def=1 -> unique dev ids)");
4151MODULE_PARM_DESC(write_same_length, "Maximum blocks per WRITE SAME cmd (def=0xffff)");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004152
4153static char sdebug_info[256];
4154
4155static const char * scsi_debug_info(struct Scsi_Host * shp)
4156{
4157 sprintf(sdebug_info, "scsi_debug, version %s [%s], "
4158 "dev_size_mb=%d, opts=0x%x", SCSI_DEBUG_VERSION,
4159 scsi_debug_version_date, scsi_debug_dev_size_mb,
4160 scsi_debug_opts);
4161 return sdebug_info;
4162}
4163
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004164/* 'echo <val> > /proc/scsi/scsi_debug/<host_id>' writes to opts */
Al Viroc8ed5552013-03-31 01:46:06 -04004165static int scsi_debug_write_info(struct Scsi_Host *host, char *buffer, int length)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004166{
Al Viroc8ed5552013-03-31 01:46:06 -04004167 char arr[16];
4168 int opts;
4169 int minLen = length > 15 ? 15 : length;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004170
Al Viroc8ed5552013-03-31 01:46:06 -04004171 if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
4172 return -EACCES;
4173 memcpy(arr, buffer, minLen);
4174 arr[minLen] = '\0';
4175 if (1 != sscanf(arr, "%d", &opts))
4176 return -EINVAL;
4177 scsi_debug_opts = opts;
4178 if (scsi_debug_every_nth != 0)
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004179 atomic_set(&sdebug_cmnd_count, 0);
Al Viroc8ed5552013-03-31 01:46:06 -04004180 return length;
4181}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004182
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004183/* Output seen with 'cat /proc/scsi/scsi_debug/<host_id>'. It will be the
4184 * same for each scsi_debug host (if more than one). Some of the counters
4185 * output are not atomics so might be inaccurate in a busy system. */
Al Viroc8ed5552013-03-31 01:46:06 -04004186static int scsi_debug_show_info(struct seq_file *m, struct Scsi_Host *host)
4187{
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004188 int f, l;
4189 char b[32];
4190
4191 if (scsi_debug_every_nth > 0)
4192 snprintf(b, sizeof(b), " (curr:%d)",
4193 ((SCSI_DEBUG_OPT_RARE_TSF & scsi_debug_opts) ?
4194 atomic_read(&sdebug_a_tsf) :
4195 atomic_read(&sdebug_cmnd_count)));
4196 else
4197 b[0] = '\0';
4198
4199 seq_printf(m, "scsi_debug adapter driver, version %s [%s]\n"
4200 "num_tgts=%d, shared (ram) size=%d MB, opts=0x%x, "
4201 "every_nth=%d%s\n"
4202 "delay=%d, ndelay=%d, max_luns=%d, q_completions=%d\n"
4203 "sector_size=%d bytes, cylinders=%d, heads=%d, sectors=%d\n"
4204 "command aborts=%d; RESETs: device=%d, target=%d, bus=%d, "
4205 "host=%d\ndix_reads=%d dix_writes=%d dif_errors=%d "
4206 "usec_in_jiffy=%lu\n",
4207 SCSI_DEBUG_VERSION, scsi_debug_version_date,
4208 scsi_debug_num_tgts, scsi_debug_dev_size_mb, scsi_debug_opts,
4209 scsi_debug_every_nth, b, scsi_debug_delay, scsi_debug_ndelay,
4210 scsi_debug_max_luns, atomic_read(&sdebug_completions),
4211 scsi_debug_sector_size, sdebug_cylinders_per, sdebug_heads,
4212 sdebug_sectors_per, num_aborts, num_dev_resets,
4213 num_target_resets, num_bus_resets, num_host_resets,
4214 dix_reads, dix_writes, dif_errors, TICK_NSEC / 1000);
4215
4216 f = find_first_bit(queued_in_use_bm, scsi_debug_max_queue);
4217 if (f != scsi_debug_max_queue) {
4218 l = find_last_bit(queued_in_use_bm, scsi_debug_max_queue);
4219 seq_printf(m, " %s BUSY: first,last bits set: %d,%d\n",
4220 "queued_in_use_bm", f, l);
4221 }
Al Viroc8ed5552013-03-31 01:46:06 -04004222 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004223}
4224
Akinobu Mita82069372013-10-14 22:48:04 +09004225static ssize_t delay_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004226{
4227 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_delay);
4228}
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004229/* Returns -EBUSY if delay is being changed and commands are queued */
Akinobu Mita82069372013-10-14 22:48:04 +09004230static ssize_t delay_store(struct device_driver *ddp, const char *buf,
4231 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004232{
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004233 int delay, res;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004234
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004235 if ((count > 0) && (1 == sscanf(buf, "%d", &delay))) {
4236 res = count;
4237 if (scsi_debug_delay != delay) {
4238 unsigned long iflags;
4239 int k;
4240
4241 spin_lock_irqsave(&queued_arr_lock, iflags);
4242 k = find_first_bit(queued_in_use_bm,
4243 scsi_debug_max_queue);
4244 if (k != scsi_debug_max_queue)
4245 res = -EBUSY; /* have queued commands */
4246 else {
4247 scsi_debug_delay = delay;
4248 scsi_debug_ndelay = 0;
4249 }
4250 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004251 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004252 return res;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004253 }
4254 return -EINVAL;
4255}
Akinobu Mita82069372013-10-14 22:48:04 +09004256static DRIVER_ATTR_RW(delay);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004257
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004258static ssize_t ndelay_show(struct device_driver *ddp, char *buf)
4259{
4260 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_ndelay);
4261}
4262/* Returns -EBUSY if ndelay is being changed and commands are queued */
4263/* If > 0 and accepted then scsi_debug_delay is set to DELAY_OVERRIDDEN */
4264static ssize_t ndelay_store(struct device_driver *ddp, const char *buf,
4265 size_t count)
4266{
4267 unsigned long iflags;
4268 int ndelay, res, k;
4269
4270 if ((count > 0) && (1 == sscanf(buf, "%d", &ndelay)) &&
4271 (ndelay >= 0) && (ndelay < 1000000000)) {
4272 res = count;
4273 if (scsi_debug_ndelay != ndelay) {
4274 spin_lock_irqsave(&queued_arr_lock, iflags);
4275 k = find_first_bit(queued_in_use_bm,
4276 scsi_debug_max_queue);
4277 if (k != scsi_debug_max_queue)
4278 res = -EBUSY; /* have queued commands */
4279 else {
4280 scsi_debug_ndelay = ndelay;
4281 scsi_debug_delay = ndelay ? DELAY_OVERRIDDEN
4282 : DEF_DELAY;
4283 }
4284 spin_unlock_irqrestore(&queued_arr_lock, iflags);
4285 }
4286 return res;
4287 }
4288 return -EINVAL;
4289}
4290static DRIVER_ATTR_RW(ndelay);
4291
Akinobu Mita82069372013-10-14 22:48:04 +09004292static ssize_t opts_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004293{
4294 return scnprintf(buf, PAGE_SIZE, "0x%x\n", scsi_debug_opts);
4295}
4296
Akinobu Mita82069372013-10-14 22:48:04 +09004297static ssize_t opts_store(struct device_driver *ddp, const char *buf,
4298 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004299{
4300 int opts;
4301 char work[20];
4302
4303 if (1 == sscanf(buf, "%10s", work)) {
Rasmus Villemoes48a96872014-10-13 15:54:44 -07004304 if (0 == strncasecmp(work,"0x", 2)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004305 if (1 == sscanf(&work[2], "%x", &opts))
4306 goto opts_done;
4307 } else {
4308 if (1 == sscanf(work, "%d", &opts))
4309 goto opts_done;
4310 }
4311 }
4312 return -EINVAL;
4313opts_done:
4314 scsi_debug_opts = opts;
Douglas Gilbert817fd662014-11-24 20:18:02 -05004315 if (SCSI_DEBUG_OPT_RECOVERED_ERR & opts)
4316 sdebug_any_injecting_opt = true;
4317 else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & opts)
4318 sdebug_any_injecting_opt = true;
4319 else if (SCSI_DEBUG_OPT_DIF_ERR & opts)
4320 sdebug_any_injecting_opt = true;
4321 else if (SCSI_DEBUG_OPT_DIX_ERR & opts)
4322 sdebug_any_injecting_opt = true;
4323 else if (SCSI_DEBUG_OPT_SHORT_TRANSFER & opts)
4324 sdebug_any_injecting_opt = true;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004325 atomic_set(&sdebug_cmnd_count, 0);
4326 atomic_set(&sdebug_a_tsf, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004327 return count;
4328}
Akinobu Mita82069372013-10-14 22:48:04 +09004329static DRIVER_ATTR_RW(opts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004330
Akinobu Mita82069372013-10-14 22:48:04 +09004331static ssize_t ptype_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004332{
4333 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_ptype);
4334}
Akinobu Mita82069372013-10-14 22:48:04 +09004335static ssize_t ptype_store(struct device_driver *ddp, const char *buf,
4336 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004337{
4338 int n;
4339
4340 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
4341 scsi_debug_ptype = n;
4342 return count;
4343 }
4344 return -EINVAL;
4345}
Akinobu Mita82069372013-10-14 22:48:04 +09004346static DRIVER_ATTR_RW(ptype);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004347
Akinobu Mita82069372013-10-14 22:48:04 +09004348static ssize_t dsense_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004349{
4350 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dsense);
4351}
Akinobu Mita82069372013-10-14 22:48:04 +09004352static ssize_t dsense_store(struct device_driver *ddp, const char *buf,
4353 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004354{
4355 int n;
4356
4357 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
4358 scsi_debug_dsense = n;
4359 return count;
4360 }
4361 return -EINVAL;
4362}
Akinobu Mita82069372013-10-14 22:48:04 +09004363static DRIVER_ATTR_RW(dsense);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004364
Akinobu Mita82069372013-10-14 22:48:04 +09004365static ssize_t fake_rw_show(struct device_driver *ddp, char *buf)
Douglas Gilbert23183912006-09-16 20:30:47 -04004366{
4367 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_fake_rw);
4368}
Akinobu Mita82069372013-10-14 22:48:04 +09004369static ssize_t fake_rw_store(struct device_driver *ddp, const char *buf,
4370 size_t count)
Douglas Gilbert23183912006-09-16 20:30:47 -04004371{
4372 int n;
4373
4374 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004375 n = (n > 0);
4376 scsi_debug_fake_rw = (scsi_debug_fake_rw > 0);
4377 if (scsi_debug_fake_rw != n) {
4378 if ((0 == n) && (NULL == fake_storep)) {
4379 unsigned long sz =
4380 (unsigned long)scsi_debug_dev_size_mb *
4381 1048576;
4382
4383 fake_storep = vmalloc(sz);
4384 if (NULL == fake_storep) {
Tomas Winklerc12879702015-07-28 16:54:20 +03004385 pr_err("out of memory, 9\n");
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004386 return -ENOMEM;
4387 }
4388 memset(fake_storep, 0, sz);
4389 }
4390 scsi_debug_fake_rw = n;
4391 }
Douglas Gilbert23183912006-09-16 20:30:47 -04004392 return count;
4393 }
4394 return -EINVAL;
4395}
Akinobu Mita82069372013-10-14 22:48:04 +09004396static DRIVER_ATTR_RW(fake_rw);
Douglas Gilbert23183912006-09-16 20:30:47 -04004397
Akinobu Mita82069372013-10-14 22:48:04 +09004398static ssize_t no_lun_0_show(struct device_driver *ddp, char *buf)
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004399{
4400 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_no_lun_0);
4401}
Akinobu Mita82069372013-10-14 22:48:04 +09004402static ssize_t no_lun_0_store(struct device_driver *ddp, const char *buf,
4403 size_t count)
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004404{
4405 int n;
4406
4407 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
4408 scsi_debug_no_lun_0 = n;
4409 return count;
4410 }
4411 return -EINVAL;
4412}
Akinobu Mita82069372013-10-14 22:48:04 +09004413static DRIVER_ATTR_RW(no_lun_0);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004414
Akinobu Mita82069372013-10-14 22:48:04 +09004415static ssize_t num_tgts_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004416{
4417 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_num_tgts);
4418}
Akinobu Mita82069372013-10-14 22:48:04 +09004419static ssize_t num_tgts_store(struct device_driver *ddp, const char *buf,
4420 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004421{
4422 int n;
4423
4424 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
4425 scsi_debug_num_tgts = n;
4426 sdebug_max_tgts_luns();
4427 return count;
4428 }
4429 return -EINVAL;
4430}
Akinobu Mita82069372013-10-14 22:48:04 +09004431static DRIVER_ATTR_RW(num_tgts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004432
Akinobu Mita82069372013-10-14 22:48:04 +09004433static ssize_t dev_size_mb_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004434{
4435 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dev_size_mb);
4436}
Akinobu Mita82069372013-10-14 22:48:04 +09004437static DRIVER_ATTR_RO(dev_size_mb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004438
Akinobu Mita82069372013-10-14 22:48:04 +09004439static ssize_t num_parts_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004440{
4441 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_num_parts);
4442}
Akinobu Mita82069372013-10-14 22:48:04 +09004443static DRIVER_ATTR_RO(num_parts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004444
Akinobu Mita82069372013-10-14 22:48:04 +09004445static ssize_t every_nth_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004446{
4447 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_every_nth);
4448}
Akinobu Mita82069372013-10-14 22:48:04 +09004449static ssize_t every_nth_store(struct device_driver *ddp, const char *buf,
4450 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004451{
4452 int nth;
4453
4454 if ((count > 0) && (1 == sscanf(buf, "%d", &nth))) {
4455 scsi_debug_every_nth = nth;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004456 atomic_set(&sdebug_cmnd_count, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004457 return count;
4458 }
4459 return -EINVAL;
4460}
Akinobu Mita82069372013-10-14 22:48:04 +09004461static DRIVER_ATTR_RW(every_nth);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004462
Akinobu Mita82069372013-10-14 22:48:04 +09004463static ssize_t max_luns_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004464{
4465 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_max_luns);
4466}
Akinobu Mita82069372013-10-14 22:48:04 +09004467static ssize_t max_luns_store(struct device_driver *ddp, const char *buf,
4468 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004469{
4470 int n;
Ewan D. Milne19c8ead2014-12-04 11:49:27 -05004471 bool changed;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004472
4473 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
Ewan D. Milne19c8ead2014-12-04 11:49:27 -05004474 changed = (scsi_debug_max_luns != n);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004475 scsi_debug_max_luns = n;
4476 sdebug_max_tgts_luns();
Ewan D. Milne19c8ead2014-12-04 11:49:27 -05004477 if (changed && (scsi_debug_scsi_level >= 5)) { /* >= SPC-3 */
4478 struct sdebug_host_info *sdhp;
4479 struct sdebug_dev_info *dp;
4480
4481 spin_lock(&sdebug_host_list_lock);
4482 list_for_each_entry(sdhp, &sdebug_host_list,
4483 host_list) {
4484 list_for_each_entry(dp, &sdhp->dev_info_list,
4485 dev_list) {
4486 set_bit(SDEBUG_UA_LUNS_CHANGED,
4487 dp->uas_bm);
4488 }
4489 }
4490 spin_unlock(&sdebug_host_list_lock);
4491 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004492 return count;
4493 }
4494 return -EINVAL;
4495}
Akinobu Mita82069372013-10-14 22:48:04 +09004496static DRIVER_ATTR_RW(max_luns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004497
Akinobu Mita82069372013-10-14 22:48:04 +09004498static ssize_t max_queue_show(struct device_driver *ddp, char *buf)
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004499{
4500 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_max_queue);
4501}
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004502/* N.B. max_queue can be changed while there are queued commands. In flight
4503 * commands beyond the new max_queue will be completed. */
Akinobu Mita82069372013-10-14 22:48:04 +09004504static ssize_t max_queue_store(struct device_driver *ddp, const char *buf,
4505 size_t count)
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004506{
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004507 unsigned long iflags;
4508 int n, k;
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004509
4510 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n > 0) &&
4511 (n <= SCSI_DEBUG_CANQUEUE)) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004512 spin_lock_irqsave(&queued_arr_lock, iflags);
4513 k = find_last_bit(queued_in_use_bm, SCSI_DEBUG_CANQUEUE);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004514 scsi_debug_max_queue = n;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004515 if (SCSI_DEBUG_CANQUEUE == k)
4516 atomic_set(&retired_max_queue, 0);
4517 else if (k >= n)
4518 atomic_set(&retired_max_queue, k + 1);
4519 else
4520 atomic_set(&retired_max_queue, 0);
4521 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004522 return count;
4523 }
4524 return -EINVAL;
4525}
Akinobu Mita82069372013-10-14 22:48:04 +09004526static DRIVER_ATTR_RW(max_queue);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004527
Akinobu Mita82069372013-10-14 22:48:04 +09004528static ssize_t no_uld_show(struct device_driver *ddp, char *buf)
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004529{
4530 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_no_uld);
4531}
Akinobu Mita82069372013-10-14 22:48:04 +09004532static DRIVER_ATTR_RO(no_uld);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004533
Akinobu Mita82069372013-10-14 22:48:04 +09004534static ssize_t scsi_level_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004535{
4536 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_scsi_level);
4537}
Akinobu Mita82069372013-10-14 22:48:04 +09004538static DRIVER_ATTR_RO(scsi_level);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004539
Akinobu Mita82069372013-10-14 22:48:04 +09004540static ssize_t virtual_gb_show(struct device_driver *ddp, char *buf)
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004541{
4542 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_virtual_gb);
4543}
Akinobu Mita82069372013-10-14 22:48:04 +09004544static ssize_t virtual_gb_store(struct device_driver *ddp, const char *buf,
4545 size_t count)
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004546{
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05004547 int n;
Douglas Gilbert0d01c5d2014-11-24 20:27:51 -05004548 bool changed;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004549
4550 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
Douglas Gilbert0d01c5d2014-11-24 20:27:51 -05004551 changed = (scsi_debug_virtual_gb != n);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004552 scsi_debug_virtual_gb = n;
FUJITA Tomonori28898872008-03-30 00:59:55 +09004553 sdebug_capacity = get_sdebug_capacity();
Douglas Gilbert0d01c5d2014-11-24 20:27:51 -05004554 if (changed) {
4555 struct sdebug_host_info *sdhp;
4556 struct sdebug_dev_info *dp;
FUJITA Tomonori28898872008-03-30 00:59:55 +09004557
Ewan D. Milne4bc6b632014-12-04 11:49:26 -05004558 spin_lock(&sdebug_host_list_lock);
Douglas Gilbert0d01c5d2014-11-24 20:27:51 -05004559 list_for_each_entry(sdhp, &sdebug_host_list,
4560 host_list) {
4561 list_for_each_entry(dp, &sdhp->dev_info_list,
4562 dev_list) {
4563 set_bit(SDEBUG_UA_CAPACITY_CHANGED,
4564 dp->uas_bm);
4565 }
4566 }
Ewan D. Milne4bc6b632014-12-04 11:49:26 -05004567 spin_unlock(&sdebug_host_list_lock);
Douglas Gilbert0d01c5d2014-11-24 20:27:51 -05004568 }
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004569 return count;
4570 }
4571 return -EINVAL;
4572}
Akinobu Mita82069372013-10-14 22:48:04 +09004573static DRIVER_ATTR_RW(virtual_gb);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004574
Akinobu Mita82069372013-10-14 22:48:04 +09004575static ssize_t add_host_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004576{
4577 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_add_host);
4578}
4579
Akinobu Mita82069372013-10-14 22:48:04 +09004580static ssize_t add_host_store(struct device_driver *ddp, const char *buf,
4581 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004582{
FUJITA Tomonorif3df41c2008-03-20 11:09:15 +09004583 int delta_hosts;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004584
FUJITA Tomonorif3df41c2008-03-20 11:09:15 +09004585 if (sscanf(buf, "%d", &delta_hosts) != 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004586 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004587 if (delta_hosts > 0) {
4588 do {
4589 sdebug_add_adapter();
4590 } while (--delta_hosts);
4591 } else if (delta_hosts < 0) {
4592 do {
4593 sdebug_remove_adapter();
4594 } while (++delta_hosts);
4595 }
4596 return count;
4597}
Akinobu Mita82069372013-10-14 22:48:04 +09004598static DRIVER_ATTR_RW(add_host);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004599
Akinobu Mita82069372013-10-14 22:48:04 +09004600static ssize_t vpd_use_hostno_show(struct device_driver *ddp, char *buf)
Douglas Gilbert23183912006-09-16 20:30:47 -04004601{
4602 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_vpd_use_hostno);
4603}
Akinobu Mita82069372013-10-14 22:48:04 +09004604static ssize_t vpd_use_hostno_store(struct device_driver *ddp, const char *buf,
4605 size_t count)
Douglas Gilbert23183912006-09-16 20:30:47 -04004606{
4607 int n;
4608
4609 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
4610 scsi_debug_vpd_use_hostno = n;
4611 return count;
4612 }
4613 return -EINVAL;
4614}
Akinobu Mita82069372013-10-14 22:48:04 +09004615static DRIVER_ATTR_RW(vpd_use_hostno);
Douglas Gilbert23183912006-09-16 20:30:47 -04004616
Akinobu Mita82069372013-10-14 22:48:04 +09004617static ssize_t sector_size_show(struct device_driver *ddp, char *buf)
Martin K. Petersen597136a2008-06-05 00:12:59 -04004618{
4619 return scnprintf(buf, PAGE_SIZE, "%u\n", scsi_debug_sector_size);
4620}
Akinobu Mita82069372013-10-14 22:48:04 +09004621static DRIVER_ATTR_RO(sector_size);
Martin K. Petersen597136a2008-06-05 00:12:59 -04004622
Akinobu Mita82069372013-10-14 22:48:04 +09004623static ssize_t dix_show(struct device_driver *ddp, char *buf)
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004624{
4625 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dix);
4626}
Akinobu Mita82069372013-10-14 22:48:04 +09004627static DRIVER_ATTR_RO(dix);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004628
Akinobu Mita82069372013-10-14 22:48:04 +09004629static ssize_t dif_show(struct device_driver *ddp, char *buf)
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004630{
4631 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dif);
4632}
Akinobu Mita82069372013-10-14 22:48:04 +09004633static DRIVER_ATTR_RO(dif);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004634
Akinobu Mita82069372013-10-14 22:48:04 +09004635static ssize_t guard_show(struct device_driver *ddp, char *buf)
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004636{
Akinobu Mita68aee7b2013-09-18 21:27:27 +09004637 return scnprintf(buf, PAGE_SIZE, "%u\n", scsi_debug_guard);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004638}
Akinobu Mita82069372013-10-14 22:48:04 +09004639static DRIVER_ATTR_RO(guard);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004640
Akinobu Mita82069372013-10-14 22:48:04 +09004641static ssize_t ato_show(struct device_driver *ddp, char *buf)
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004642{
4643 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_ato);
4644}
Akinobu Mita82069372013-10-14 22:48:04 +09004645static DRIVER_ATTR_RO(ato);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004646
Akinobu Mita82069372013-10-14 22:48:04 +09004647static ssize_t map_show(struct device_driver *ddp, char *buf)
Martin K. Petersen44d92692009-10-15 14:45:27 -04004648{
4649 ssize_t count;
4650
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004651 if (!scsi_debug_lbp())
Martin K. Petersen44d92692009-10-15 14:45:27 -04004652 return scnprintf(buf, PAGE_SIZE, "0-%u\n",
4653 sdebug_store_sectors);
4654
Tejun Heoc7badc92015-02-13 14:37:51 -08004655 count = scnprintf(buf, PAGE_SIZE - 1, "%*pbl",
4656 (int)map_size, map_storep);
Martin K. Petersen44d92692009-10-15 14:45:27 -04004657 buf[count++] = '\n';
Tejun Heoc7badc92015-02-13 14:37:51 -08004658 buf[count] = '\0';
Martin K. Petersen44d92692009-10-15 14:45:27 -04004659
4660 return count;
4661}
Akinobu Mita82069372013-10-14 22:48:04 +09004662static DRIVER_ATTR_RO(map);
Martin K. Petersen44d92692009-10-15 14:45:27 -04004663
Akinobu Mita82069372013-10-14 22:48:04 +09004664static ssize_t removable_show(struct device_driver *ddp, char *buf)
Martin Pittd9867882012-09-06 12:04:33 +02004665{
4666 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_removable ? 1 : 0);
4667}
Akinobu Mita82069372013-10-14 22:48:04 +09004668static ssize_t removable_store(struct device_driver *ddp, const char *buf,
4669 size_t count)
Martin Pittd9867882012-09-06 12:04:33 +02004670{
4671 int n;
4672
4673 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
4674 scsi_debug_removable = (n > 0);
4675 return count;
4676 }
4677 return -EINVAL;
4678}
Akinobu Mita82069372013-10-14 22:48:04 +09004679static DRIVER_ATTR_RW(removable);
Martin Pittd9867882012-09-06 12:04:33 +02004680
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004681static ssize_t host_lock_show(struct device_driver *ddp, char *buf)
4682{
4683 return scnprintf(buf, PAGE_SIZE, "%d\n", !!scsi_debug_host_lock);
4684}
4685/* Returns -EBUSY if host_lock is being changed and commands are queued */
4686static ssize_t host_lock_store(struct device_driver *ddp, const char *buf,
4687 size_t count)
4688{
4689 int n, res;
4690
4691 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
4692 bool new_host_lock = (n > 0);
4693
4694 res = count;
4695 if (new_host_lock != scsi_debug_host_lock) {
4696 unsigned long iflags;
4697 int k;
4698
4699 spin_lock_irqsave(&queued_arr_lock, iflags);
4700 k = find_first_bit(queued_in_use_bm,
4701 scsi_debug_max_queue);
4702 if (k != scsi_debug_max_queue)
4703 res = -EBUSY; /* have queued commands */
4704 else
4705 scsi_debug_host_lock = new_host_lock;
4706 spin_unlock_irqrestore(&queued_arr_lock, iflags);
4707 }
4708 return res;
4709 }
4710 return -EINVAL;
4711}
4712static DRIVER_ATTR_RW(host_lock);
4713
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05004714static ssize_t strict_show(struct device_driver *ddp, char *buf)
4715{
4716 return scnprintf(buf, PAGE_SIZE, "%d\n", !!scsi_debug_strict);
4717}
4718static ssize_t strict_store(struct device_driver *ddp, const char *buf,
4719 size_t count)
4720{
4721 int n;
4722
4723 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
4724 scsi_debug_strict = (n > 0);
4725 return count;
4726 }
4727 return -EINVAL;
4728}
4729static DRIVER_ATTR_RW(strict);
4730
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004731
Akinobu Mita82069372013-10-14 22:48:04 +09004732/* Note: The following array creates attribute files in the
Douglas Gilbert23183912006-09-16 20:30:47 -04004733 /sys/bus/pseudo/drivers/scsi_debug directory. The advantage of these
4734 files (over those found in the /sys/module/scsi_debug/parameters
4735 directory) is that auxiliary actions can be triggered when an attribute
4736 is changed. For example see: sdebug_add_host_store() above.
4737 */
Randy Dunlap6ecaff72006-07-11 20:53:22 -07004738
Akinobu Mita82069372013-10-14 22:48:04 +09004739static struct attribute *sdebug_drv_attrs[] = {
4740 &driver_attr_delay.attr,
4741 &driver_attr_opts.attr,
4742 &driver_attr_ptype.attr,
4743 &driver_attr_dsense.attr,
4744 &driver_attr_fake_rw.attr,
4745 &driver_attr_no_lun_0.attr,
4746 &driver_attr_num_tgts.attr,
4747 &driver_attr_dev_size_mb.attr,
4748 &driver_attr_num_parts.attr,
4749 &driver_attr_every_nth.attr,
4750 &driver_attr_max_luns.attr,
4751 &driver_attr_max_queue.attr,
4752 &driver_attr_no_uld.attr,
4753 &driver_attr_scsi_level.attr,
4754 &driver_attr_virtual_gb.attr,
4755 &driver_attr_add_host.attr,
4756 &driver_attr_vpd_use_hostno.attr,
4757 &driver_attr_sector_size.attr,
4758 &driver_attr_dix.attr,
4759 &driver_attr_dif.attr,
4760 &driver_attr_guard.attr,
4761 &driver_attr_ato.attr,
4762 &driver_attr_map.attr,
4763 &driver_attr_removable.attr,
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004764 &driver_attr_host_lock.attr,
4765 &driver_attr_ndelay.attr,
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05004766 &driver_attr_strict.attr,
Akinobu Mita82069372013-10-14 22:48:04 +09004767 NULL,
4768};
4769ATTRIBUTE_GROUPS(sdebug_drv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004770
Akinobu Mita11ddcec2014-02-26 22:56:59 +09004771static struct device *pseudo_primary;
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09004772
Linus Torvalds1da177e2005-04-16 15:20:36 -07004773static int __init scsi_debug_init(void)
4774{
FUJITA Tomonori5f2578e2008-03-30 00:59:57 +09004775 unsigned long sz;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004776 int host_to_add;
4777 int k;
Randy Dunlap6ecaff72006-07-11 20:53:22 -07004778 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004779
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004780 atomic_set(&sdebug_cmnd_count, 0);
4781 atomic_set(&sdebug_completions, 0);
4782 atomic_set(&retired_max_queue, 0);
4783
4784 if (scsi_debug_ndelay >= 1000000000) {
Tomas Winklerc12879702015-07-28 16:54:20 +03004785 pr_warn("ndelay must be less than 1 second, ignored\n");
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004786 scsi_debug_ndelay = 0;
4787 } else if (scsi_debug_ndelay > 0)
4788 scsi_debug_delay = DELAY_OVERRIDDEN;
4789
Martin K. Petersen597136a2008-06-05 00:12:59 -04004790 switch (scsi_debug_sector_size) {
4791 case 512:
4792 case 1024:
4793 case 2048:
4794 case 4096:
4795 break;
4796 default:
Tomas Winklerc12879702015-07-28 16:54:20 +03004797 pr_err("invalid sector_size %d\n", scsi_debug_sector_size);
Martin K. Petersen597136a2008-06-05 00:12:59 -04004798 return -EINVAL;
4799 }
4800
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004801 switch (scsi_debug_dif) {
4802
4803 case SD_DIF_TYPE0_PROTECTION:
4804 case SD_DIF_TYPE1_PROTECTION:
Martin K. Petersen395cef02009-09-18 17:33:03 -04004805 case SD_DIF_TYPE2_PROTECTION:
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004806 case SD_DIF_TYPE3_PROTECTION:
4807 break;
4808
4809 default:
Tomas Winklerc12879702015-07-28 16:54:20 +03004810 pr_err("dif must be 0, 1, 2 or 3\n");
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004811 return -EINVAL;
4812 }
4813
4814 if (scsi_debug_guard > 1) {
Tomas Winklerc12879702015-07-28 16:54:20 +03004815 pr_err("guard must be 0 or 1\n");
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004816 return -EINVAL;
4817 }
4818
4819 if (scsi_debug_ato > 1) {
Tomas Winklerc12879702015-07-28 16:54:20 +03004820 pr_err("ato must be 0 or 1\n");
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004821 return -EINVAL;
4822 }
4823
Martin K. Petersenea61fca2009-05-15 00:40:33 -04004824 if (scsi_debug_physblk_exp > 15) {
Tomas Winklerc12879702015-07-28 16:54:20 +03004825 pr_err("invalid physblk_exp %u\n", scsi_debug_physblk_exp);
Martin K. Petersenea61fca2009-05-15 00:40:33 -04004826 return -EINVAL;
4827 }
4828
4829 if (scsi_debug_lowest_aligned > 0x3fff) {
Tomas Winklerc12879702015-07-28 16:54:20 +03004830 pr_err("lowest_aligned too big: %u\n",
4831 scsi_debug_lowest_aligned);
Martin K. Petersenea61fca2009-05-15 00:40:33 -04004832 return -EINVAL;
4833 }
4834
Linus Torvalds1da177e2005-04-16 15:20:36 -07004835 if (scsi_debug_dev_size_mb < 1)
4836 scsi_debug_dev_size_mb = 1; /* force minimum 1 MB ramdisk */
FUJITA Tomonori5f2578e2008-03-30 00:59:57 +09004837 sz = (unsigned long)scsi_debug_dev_size_mb * 1048576;
Martin K. Petersen597136a2008-06-05 00:12:59 -04004838 sdebug_store_sectors = sz / scsi_debug_sector_size;
FUJITA Tomonori28898872008-03-30 00:59:55 +09004839 sdebug_capacity = get_sdebug_capacity();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004840
4841 /* play around with geometry, don't waste too much on track 0 */
4842 sdebug_heads = 8;
4843 sdebug_sectors_per = 32;
4844 if (scsi_debug_dev_size_mb >= 16)
4845 sdebug_heads = 32;
4846 else if (scsi_debug_dev_size_mb >= 256)
4847 sdebug_heads = 64;
4848 sdebug_cylinders_per = (unsigned long)sdebug_capacity /
4849 (sdebug_sectors_per * sdebug_heads);
4850 if (sdebug_cylinders_per >= 1024) {
4851 /* other LLDs do this; implies >= 1GB ram disk ... */
4852 sdebug_heads = 255;
4853 sdebug_sectors_per = 63;
4854 sdebug_cylinders_per = (unsigned long)sdebug_capacity /
4855 (sdebug_sectors_per * sdebug_heads);
4856 }
4857
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004858 if (0 == scsi_debug_fake_rw) {
4859 fake_storep = vmalloc(sz);
4860 if (NULL == fake_storep) {
Tomas Winklerc12879702015-07-28 16:54:20 +03004861 pr_err("out of memory, 1\n");
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004862 return -ENOMEM;
4863 }
4864 memset(fake_storep, 0, sz);
4865 if (scsi_debug_num_parts > 0)
4866 sdebug_build_parts(fake_storep, sz);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004867 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004868
Akinobu Mita7cb69d02013-06-29 17:59:16 +09004869 if (scsi_debug_dix) {
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004870 int dif_size;
4871
4872 dif_size = sdebug_store_sectors * sizeof(struct sd_dif_tuple);
4873 dif_storep = vmalloc(dif_size);
4874
Tomas Winklerc12879702015-07-28 16:54:20 +03004875 pr_err("dif_storep %u bytes @ %p\n", dif_size, dif_storep);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004876
4877 if (dif_storep == NULL) {
Tomas Winklerc12879702015-07-28 16:54:20 +03004878 pr_err("out of mem. (DIX)\n");
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004879 ret = -ENOMEM;
4880 goto free_vm;
4881 }
4882
4883 memset(dif_storep, 0xff, dif_size);
4884 }
4885
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004886 /* Logical Block Provisioning */
4887 if (scsi_debug_lbp()) {
Martin K. Petersen60147592010-08-19 11:49:00 -04004888 scsi_debug_unmap_max_blocks =
4889 clamp(scsi_debug_unmap_max_blocks, 0U, 0xffffffffU);
4890
4891 scsi_debug_unmap_max_desc =
4892 clamp(scsi_debug_unmap_max_desc, 0U, 256U);
4893
4894 scsi_debug_unmap_granularity =
4895 clamp(scsi_debug_unmap_granularity, 1U, 0xffffffffU);
4896
4897 if (scsi_debug_unmap_alignment &&
Akinobu Mitaac170782013-04-16 22:11:56 +09004898 scsi_debug_unmap_granularity <=
4899 scsi_debug_unmap_alignment) {
Tomas Winklerc12879702015-07-28 16:54:20 +03004900 pr_err("ERR: unmap_granularity <= unmap_alignment\n");
Martin K. Petersen44d92692009-10-15 14:45:27 -04004901 return -EINVAL;
4902 }
4903
Akinobu Mitab90ebc32013-04-16 22:11:58 +09004904 map_size = lba_to_map_index(sdebug_store_sectors - 1) + 1;
4905 map_storep = vmalloc(BITS_TO_LONGS(map_size) * sizeof(long));
Martin K. Petersen44d92692009-10-15 14:45:27 -04004906
Tomas Winklerc12879702015-07-28 16:54:20 +03004907 pr_info("%lu provisioning blocks\n", map_size);
Martin K. Petersen44d92692009-10-15 14:45:27 -04004908
4909 if (map_storep == NULL) {
Tomas Winklerc12879702015-07-28 16:54:20 +03004910 pr_err("out of mem. (MAP)\n");
Martin K. Petersen44d92692009-10-15 14:45:27 -04004911 ret = -ENOMEM;
4912 goto free_vm;
4913 }
4914
Akinobu Mitab90ebc32013-04-16 22:11:58 +09004915 bitmap_zero(map_storep, map_size);
Martin K. Petersen44d92692009-10-15 14:45:27 -04004916
4917 /* Map first 1KB for partition table */
4918 if (scsi_debug_num_parts)
4919 map_region(0, 2);
4920 }
4921
Nicholas Bellinger9b906772010-09-06 17:24:28 -07004922 pseudo_primary = root_device_register("pseudo_0");
4923 if (IS_ERR(pseudo_primary)) {
Tomas Winklerc12879702015-07-28 16:54:20 +03004924 pr_warn("root_device_register() error\n");
Nicholas Bellinger9b906772010-09-06 17:24:28 -07004925 ret = PTR_ERR(pseudo_primary);
Randy Dunlap6ecaff72006-07-11 20:53:22 -07004926 goto free_vm;
4927 }
4928 ret = bus_register(&pseudo_lld_bus);
4929 if (ret < 0) {
Tomas Winklerc12879702015-07-28 16:54:20 +03004930 pr_warn("bus_register error: %d\n", ret);
Randy Dunlap6ecaff72006-07-11 20:53:22 -07004931 goto dev_unreg;
4932 }
4933 ret = driver_register(&sdebug_driverfs_driver);
4934 if (ret < 0) {
Tomas Winklerc12879702015-07-28 16:54:20 +03004935 pr_warn("driver_register error: %d\n", ret);
Randy Dunlap6ecaff72006-07-11 20:53:22 -07004936 goto bus_unreg;
4937 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004938
Linus Torvalds1da177e2005-04-16 15:20:36 -07004939 host_to_add = scsi_debug_add_host;
4940 scsi_debug_add_host = 0;
4941
4942 for (k = 0; k < host_to_add; k++) {
4943 if (sdebug_add_adapter()) {
Tomas Winklerc12879702015-07-28 16:54:20 +03004944 pr_err("sdebug_add_adapter failed k=%d\n", k);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004945 break;
4946 }
4947 }
4948
Tomas Winklerc12879702015-07-28 16:54:20 +03004949 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
4950 pr_info("built %d host(s)\n", scsi_debug_add_host);
4951
Linus Torvalds1da177e2005-04-16 15:20:36 -07004952 return 0;
Randy Dunlap6ecaff72006-07-11 20:53:22 -07004953
Randy Dunlap6ecaff72006-07-11 20:53:22 -07004954bus_unreg:
4955 bus_unregister(&pseudo_lld_bus);
4956dev_unreg:
Nicholas Bellinger9b906772010-09-06 17:24:28 -07004957 root_device_unregister(pseudo_primary);
Randy Dunlap6ecaff72006-07-11 20:53:22 -07004958free_vm:
Martin K. Petersen44d92692009-10-15 14:45:27 -04004959 if (map_storep)
4960 vfree(map_storep);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004961 if (dif_storep)
4962 vfree(dif_storep);
Randy Dunlap6ecaff72006-07-11 20:53:22 -07004963 vfree(fake_storep);
4964
4965 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004966}
4967
4968static void __exit scsi_debug_exit(void)
4969{
4970 int k = scsi_debug_add_host;
4971
4972 stop_all_queued();
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004973 free_all_queued();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004974 for (; k; k--)
4975 sdebug_remove_adapter();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004976 driver_unregister(&sdebug_driverfs_driver);
4977 bus_unregister(&pseudo_lld_bus);
Nicholas Bellinger9b906772010-09-06 17:24:28 -07004978 root_device_unregister(pseudo_primary);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004979
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004980 if (dif_storep)
4981 vfree(dif_storep);
4982
Linus Torvalds1da177e2005-04-16 15:20:36 -07004983 vfree(fake_storep);
4984}
4985
4986device_initcall(scsi_debug_init);
4987module_exit(scsi_debug_exit);
4988
Linus Torvalds1da177e2005-04-16 15:20:36 -07004989static void sdebug_release_adapter(struct device * dev)
4990{
4991 struct sdebug_host_info *sdbg_host;
4992
4993 sdbg_host = to_sdebug_host(dev);
4994 kfree(sdbg_host);
4995}
4996
4997static int sdebug_add_adapter(void)
4998{
4999 int k, devs_per_host;
5000 int error = 0;
5001 struct sdebug_host_info *sdbg_host;
FUJITA Tomonori8b40228f2008-03-20 11:09:18 +09005002 struct sdebug_dev_info *sdbg_devinfo, *tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005003
Douglas Gilbertc65b1442006-06-06 00:11:24 -04005004 sdbg_host = kzalloc(sizeof(*sdbg_host),GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005005 if (NULL == sdbg_host) {
Tomas Winklerc12879702015-07-28 16:54:20 +03005006 pr_err("out of memory at line %d\n", __LINE__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005007 return -ENOMEM;
5008 }
5009
Linus Torvalds1da177e2005-04-16 15:20:36 -07005010 INIT_LIST_HEAD(&sdbg_host->dev_info_list);
5011
5012 devs_per_host = scsi_debug_num_tgts * scsi_debug_max_luns;
5013 for (k = 0; k < devs_per_host; k++) {
FUJITA Tomonori5cb2fc02008-03-20 11:09:16 +09005014 sdbg_devinfo = sdebug_device_create(sdbg_host, GFP_KERNEL);
5015 if (!sdbg_devinfo) {
Tomas Winklerc12879702015-07-28 16:54:20 +03005016 pr_err("out of memory at line %d\n", __LINE__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005017 error = -ENOMEM;
5018 goto clean;
5019 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005020 }
5021
5022 spin_lock(&sdebug_host_list_lock);
5023 list_add_tail(&sdbg_host->host_list, &sdebug_host_list);
5024 spin_unlock(&sdebug_host_list_lock);
5025
5026 sdbg_host->dev.bus = &pseudo_lld_bus;
Nicholas Bellinger9b906772010-09-06 17:24:28 -07005027 sdbg_host->dev.parent = pseudo_primary;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005028 sdbg_host->dev.release = &sdebug_release_adapter;
Kay Sievers71610f52008-12-03 22:41:36 +01005029 dev_set_name(&sdbg_host->dev, "adapter%d", scsi_debug_add_host);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005030
5031 error = device_register(&sdbg_host->dev);
5032
5033 if (error)
5034 goto clean;
5035
5036 ++scsi_debug_add_host;
5037 return error;
5038
5039clean:
FUJITA Tomonori8b40228f2008-03-20 11:09:18 +09005040 list_for_each_entry_safe(sdbg_devinfo, tmp, &sdbg_host->dev_info_list,
5041 dev_list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005042 list_del(&sdbg_devinfo->dev_list);
5043 kfree(sdbg_devinfo);
5044 }
5045
5046 kfree(sdbg_host);
5047 return error;
5048}
5049
5050static void sdebug_remove_adapter(void)
5051{
5052 struct sdebug_host_info * sdbg_host = NULL;
5053
5054 spin_lock(&sdebug_host_list_lock);
5055 if (!list_empty(&sdebug_host_list)) {
5056 sdbg_host = list_entry(sdebug_host_list.prev,
5057 struct sdebug_host_info, host_list);
5058 list_del(&sdbg_host->host_list);
5059 }
5060 spin_unlock(&sdebug_host_list_lock);
5061
5062 if (!sdbg_host)
5063 return;
5064
5065 device_unregister(&sdbg_host->dev);
5066 --scsi_debug_add_host;
5067}
5068
Douglas Gilbertcbf67842014-07-26 11:55:35 -04005069static int
Christoph Hellwigdb5ed4d2014-11-13 15:08:42 +01005070sdebug_change_qdepth(struct scsi_device *sdev, int qdepth)
Douglas Gilbertcbf67842014-07-26 11:55:35 -04005071{
5072 int num_in_q = 0;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04005073 unsigned long iflags;
5074 struct sdebug_dev_info *devip;
5075
5076 spin_lock_irqsave(&queued_arr_lock, iflags);
5077 devip = (struct sdebug_dev_info *)sdev->hostdata;
5078 if (NULL == devip) {
5079 spin_unlock_irqrestore(&queued_arr_lock, iflags);
5080 return -ENODEV;
5081 }
5082 num_in_q = atomic_read(&devip->num_in_q);
5083 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04005084
Christoph Hellwigc40ecc12014-11-13 14:25:11 +01005085 if (qdepth < 1)
5086 qdepth = 1;
5087 /* allow to exceed max host queued_arr elements for testing */
5088 if (qdepth > SCSI_DEBUG_CANQUEUE + 10)
5089 qdepth = SCSI_DEBUG_CANQUEUE + 10;
Christoph Hellwigdb5ed4d2014-11-13 15:08:42 +01005090 scsi_change_queue_depth(sdev, qdepth);
Christoph Hellwigc40ecc12014-11-13 14:25:11 +01005091
5092 if (SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts) {
5093 sdev_printk(KERN_INFO, sdev,
5094 "%s: qdepth=%d, num_in_q=%d\n",
5095 __func__, qdepth, num_in_q);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04005096 }
5097 return sdev->queue_depth;
5098}
5099
5100static int
Douglas Gilbert817fd662014-11-24 20:18:02 -05005101check_inject(struct scsi_cmnd *scp)
5102{
5103 struct sdebug_scmd_extra_t *ep = scsi_cmd_priv(scp);
5104
5105 memset(ep, 0, sizeof(struct sdebug_scmd_extra_t));
5106
5107 if (atomic_inc_return(&sdebug_cmnd_count) >=
5108 abs(scsi_debug_every_nth)) {
5109 atomic_set(&sdebug_cmnd_count, 0);
5110 if (scsi_debug_every_nth < -1)
5111 scsi_debug_every_nth = -1;
5112 if (SCSI_DEBUG_OPT_TIMEOUT & scsi_debug_opts)
5113 return 1; /* ignore command causing timeout */
5114 else if (SCSI_DEBUG_OPT_MAC_TIMEOUT & scsi_debug_opts &&
5115 scsi_medium_access_command(scp))
5116 return 1; /* time out reads and writes */
5117 if (sdebug_any_injecting_opt) {
5118 int opts = scsi_debug_opts;
5119
5120 if (SCSI_DEBUG_OPT_RECOVERED_ERR & opts)
5121 ep->inj_recovered = true;
5122 else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & opts)
5123 ep->inj_transport = true;
5124 else if (SCSI_DEBUG_OPT_DIF_ERR & opts)
5125 ep->inj_dif = true;
5126 else if (SCSI_DEBUG_OPT_DIX_ERR & opts)
5127 ep->inj_dix = true;
5128 else if (SCSI_DEBUG_OPT_SHORT_TRANSFER & opts)
5129 ep->inj_short = true;
5130 }
5131 }
5132 return 0;
5133}
5134
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05005135static int
5136scsi_debug_queuecommand(struct scsi_cmnd *scp)
5137{
5138 u8 sdeb_i;
5139 struct scsi_device *sdp = scp->device;
5140 const struct opcode_info_t *oip;
5141 const struct opcode_info_t *r_oip;
5142 struct sdebug_dev_info *devip;
5143 u8 *cmd = scp->cmnd;
5144 int (*r_pfp)(struct scsi_cmnd *, struct sdebug_dev_info *);
5145 int k, na;
5146 int errsts = 0;
5147 int errsts_no_connect = DID_NO_CONNECT << 16;
5148 u32 flags;
5149 u16 sa;
5150 u8 opcode = cmd[0];
5151 bool has_wlun_rl;
5152 bool debug = !!(SCSI_DEBUG_OPT_NOISE & scsi_debug_opts);
5153
5154 scsi_set_resid(scp, 0);
5155 if (debug && !(SCSI_DEBUG_OPT_NO_CDB_NOISE & scsi_debug_opts)) {
5156 char b[120];
5157 int n, len, sb;
5158
5159 len = scp->cmd_len;
5160 sb = (int)sizeof(b);
5161 if (len > 32)
5162 strcpy(b, "too long, over 32 bytes");
5163 else {
5164 for (k = 0, n = 0; k < len && n < sb; ++k)
5165 n += scnprintf(b + n, sb - n, "%02x ",
5166 (u32)cmd[k]);
5167 }
5168 sdev_printk(KERN_INFO, sdp, "%s: cmd %s\n", my_name, b);
5169 }
5170 has_wlun_rl = (sdp->lun == SAM2_WLUN_REPORT_LUNS);
5171 if ((sdp->lun >= scsi_debug_max_luns) && !has_wlun_rl)
5172 return schedule_resp(scp, NULL, errsts_no_connect, 0);
5173
5174 sdeb_i = opcode_ind_arr[opcode]; /* fully mapped */
5175 oip = &opcode_info_arr[sdeb_i]; /* safe if table consistent */
5176 devip = (struct sdebug_dev_info *)sdp->hostdata;
5177 if (!devip) {
5178 devip = devInfoReg(sdp);
5179 if (NULL == devip)
5180 return schedule_resp(scp, NULL, errsts_no_connect, 0);
5181 }
5182 na = oip->num_attached;
5183 r_pfp = oip->pfp;
5184 if (na) { /* multiple commands with this opcode */
5185 r_oip = oip;
5186 if (FF_SA & r_oip->flags) {
5187 if (F_SA_LOW & oip->flags)
5188 sa = 0x1f & cmd[1];
5189 else
5190 sa = get_unaligned_be16(cmd + 8);
5191 for (k = 0; k <= na; oip = r_oip->arrp + k++) {
5192 if (opcode == oip->opcode && sa == oip->sa)
5193 break;
5194 }
5195 } else { /* since no service action only check opcode */
5196 for (k = 0; k <= na; oip = r_oip->arrp + k++) {
5197 if (opcode == oip->opcode)
5198 break;
5199 }
5200 }
5201 if (k > na) {
5202 if (F_SA_LOW & r_oip->flags)
5203 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 1, 4);
5204 else if (F_SA_HIGH & r_oip->flags)
5205 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 8, 7);
5206 else
5207 mk_sense_invalid_opcode(scp);
5208 goto check_cond;
5209 }
5210 } /* else (when na==0) we assume the oip is a match */
5211 flags = oip->flags;
5212 if (F_INV_OP & flags) {
5213 mk_sense_invalid_opcode(scp);
5214 goto check_cond;
5215 }
5216 if (has_wlun_rl && !(F_RL_WLUN_OK & flags)) {
5217 if (debug)
5218 sdev_printk(KERN_INFO, sdp, "scsi_debug: Opcode: "
5219 "0x%x not supported for wlun\n", opcode);
5220 mk_sense_invalid_opcode(scp);
5221 goto check_cond;
5222 }
5223 if (scsi_debug_strict) { /* check cdb against mask */
5224 u8 rem;
5225 int j;
5226
5227 for (k = 1; k < oip->len_mask[0] && k < 16; ++k) {
5228 rem = ~oip->len_mask[k] & cmd[k];
5229 if (rem) {
5230 for (j = 7; j >= 0; --j, rem <<= 1) {
5231 if (0x80 & rem)
5232 break;
5233 }
5234 mk_sense_invalid_fld(scp, SDEB_IN_CDB, k, j);
5235 goto check_cond;
5236 }
5237 }
5238 }
5239 if (!(F_SKIP_UA & flags) &&
5240 SDEBUG_NUM_UAS != find_first_bit(devip->uas_bm, SDEBUG_NUM_UAS)) {
5241 errsts = check_readiness(scp, UAS_ONLY, devip);
5242 if (errsts)
5243 goto check_cond;
5244 }
5245 if ((F_M_ACCESS & flags) && devip->stopped) {
5246 mk_sense_buffer(scp, NOT_READY, LOGICAL_UNIT_NOT_READY, 0x2);
5247 if (debug)
5248 sdev_printk(KERN_INFO, sdp, "%s reports: Not ready: "
5249 "%s\n", my_name, "initializing command "
5250 "required");
5251 errsts = check_condition_result;
5252 goto fini;
5253 }
5254 if (scsi_debug_fake_rw && (F_FAKE_RW & flags))
5255 goto fini;
5256 if (scsi_debug_every_nth) {
5257 if (check_inject(scp))
5258 return 0; /* ignore command: make trouble */
5259 }
5260 if (oip->pfp) /* if this command has a resp_* function, call it */
5261 errsts = oip->pfp(scp, devip);
5262 else if (r_pfp) /* if leaf function ptr NULL, try the root's */
5263 errsts = r_pfp(scp, devip);
5264
5265fini:
5266 return schedule_resp(scp, devip, errsts,
5267 ((F_DELAY_OVERR & flags) ? 0 : scsi_debug_delay));
5268check_cond:
5269 return schedule_resp(scp, devip, check_condition_result, 0);
5270}
5271
Douglas Gilbert38d5c832014-11-24 21:27:12 -05005272static int
5273sdebug_queuecommand_lock_or_not(struct Scsi_Host *shost, struct scsi_cmnd *cmd)
5274{
5275 if (scsi_debug_host_lock) {
5276 unsigned long iflags;
5277 int rc;
5278
5279 spin_lock_irqsave(shost->host_lock, iflags);
5280 rc = scsi_debug_queuecommand(cmd);
5281 spin_unlock_irqrestore(shost->host_lock, iflags);
5282 return rc;
5283 } else
5284 return scsi_debug_queuecommand(cmd);
5285}
5286
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +09005287static struct scsi_host_template sdebug_driver_template = {
Al Viroc8ed5552013-03-31 01:46:06 -04005288 .show_info = scsi_debug_show_info,
5289 .write_info = scsi_debug_write_info,
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +09005290 .proc_name = sdebug_proc_name,
5291 .name = "SCSI DEBUG",
5292 .info = scsi_debug_info,
5293 .slave_alloc = scsi_debug_slave_alloc,
5294 .slave_configure = scsi_debug_slave_configure,
5295 .slave_destroy = scsi_debug_slave_destroy,
5296 .ioctl = scsi_debug_ioctl,
Douglas Gilbertcbf67842014-07-26 11:55:35 -04005297 .queuecommand = sdebug_queuecommand_lock_or_not,
5298 .change_queue_depth = sdebug_change_qdepth,
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +09005299 .eh_abort_handler = scsi_debug_abort,
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +09005300 .eh_device_reset_handler = scsi_debug_device_reset,
Douglas Gilbertcbf67842014-07-26 11:55:35 -04005301 .eh_target_reset_handler = scsi_debug_target_reset,
5302 .eh_bus_reset_handler = scsi_debug_bus_reset,
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +09005303 .eh_host_reset_handler = scsi_debug_host_reset,
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +09005304 .can_queue = SCSI_DEBUG_CANQUEUE,
5305 .this_id = 7,
Akinobu Mita6bb5e6e2014-06-02 22:56:49 +09005306 .sg_tablesize = SCSI_MAX_SG_CHAIN_SEGMENTS,
Douglas Gilbertcbf67842014-07-26 11:55:35 -04005307 .cmd_per_lun = DEF_CMD_PER_LUN,
Akinobu Mita6bb5e6e2014-06-02 22:56:49 +09005308 .max_sectors = -1U,
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +09005309 .use_clustering = DISABLE_CLUSTERING,
5310 .module = THIS_MODULE,
Christoph Hellwigc40ecc12014-11-13 14:25:11 +01005311 .track_queue_depth = 1,
Douglas Gilbert817fd662014-11-24 20:18:02 -05005312 .cmd_size = sizeof(struct sdebug_scmd_extra_t),
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +09005313};
5314
Linus Torvalds1da177e2005-04-16 15:20:36 -07005315static int sdebug_driver_probe(struct device * dev)
5316{
Douglas Gilbert22017ed2014-11-24 23:04:47 -05005317 int error = 0;
Douglas Gilbert817fd662014-11-24 20:18:02 -05005318 int opts;
Douglas Gilbert22017ed2014-11-24 23:04:47 -05005319 struct sdebug_host_info *sdbg_host;
5320 struct Scsi_Host *hpnt;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05005321 int host_prot;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005322
5323 sdbg_host = to_sdebug_host(dev);
5324
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04005325 sdebug_driver_template.can_queue = scsi_debug_max_queue;
Akinobu Mita0759c662014-02-26 22:57:04 +09005326 if (scsi_debug_clustering)
5327 sdebug_driver_template.use_clustering = ENABLE_CLUSTERING;
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04005328 hpnt = scsi_host_alloc(&sdebug_driver_template, sizeof(sdbg_host));
5329 if (NULL == hpnt) {
Tomas Winklerc12879702015-07-28 16:54:20 +03005330 pr_err("scsi_host_alloc failed\n");
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04005331 error = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005332 return error;
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04005333 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005334
5335 sdbg_host->shost = hpnt;
5336 *((struct sdebug_host_info **)hpnt->hostdata) = sdbg_host;
5337 if ((hpnt->this_id >= 0) && (scsi_debug_num_tgts > hpnt->this_id))
5338 hpnt->max_id = scsi_debug_num_tgts + 1;
5339 else
5340 hpnt->max_id = scsi_debug_num_tgts;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04005341 hpnt->max_lun = SAM2_WLUN_REPORT_LUNS; /* = scsi_debug_max_luns; */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005342
Martin K. Petersenc6a44282009-01-04 03:08:19 -05005343 host_prot = 0;
5344
5345 switch (scsi_debug_dif) {
5346
5347 case SD_DIF_TYPE1_PROTECTION:
5348 host_prot = SHOST_DIF_TYPE1_PROTECTION;
5349 if (scsi_debug_dix)
5350 host_prot |= SHOST_DIX_TYPE1_PROTECTION;
5351 break;
5352
5353 case SD_DIF_TYPE2_PROTECTION:
5354 host_prot = SHOST_DIF_TYPE2_PROTECTION;
5355 if (scsi_debug_dix)
5356 host_prot |= SHOST_DIX_TYPE2_PROTECTION;
5357 break;
5358
5359 case SD_DIF_TYPE3_PROTECTION:
5360 host_prot = SHOST_DIF_TYPE3_PROTECTION;
5361 if (scsi_debug_dix)
5362 host_prot |= SHOST_DIX_TYPE3_PROTECTION;
5363 break;
5364
5365 default:
5366 if (scsi_debug_dix)
5367 host_prot |= SHOST_DIX_TYPE0_PROTECTION;
5368 break;
5369 }
5370
5371 scsi_host_set_prot(hpnt, host_prot);
5372
Tomas Winklerc12879702015-07-28 16:54:20 +03005373 pr_info("host protection%s%s%s%s%s%s%s\n",
Martin K. Petersenc6a44282009-01-04 03:08:19 -05005374 (host_prot & SHOST_DIF_TYPE1_PROTECTION) ? " DIF1" : "",
5375 (host_prot & SHOST_DIF_TYPE2_PROTECTION) ? " DIF2" : "",
5376 (host_prot & SHOST_DIF_TYPE3_PROTECTION) ? " DIF3" : "",
5377 (host_prot & SHOST_DIX_TYPE0_PROTECTION) ? " DIX0" : "",
5378 (host_prot & SHOST_DIX_TYPE1_PROTECTION) ? " DIX1" : "",
5379 (host_prot & SHOST_DIX_TYPE2_PROTECTION) ? " DIX2" : "",
5380 (host_prot & SHOST_DIX_TYPE3_PROTECTION) ? " DIX3" : "");
5381
5382 if (scsi_debug_guard == 1)
5383 scsi_host_set_guard(hpnt, SHOST_DIX_GUARD_IP);
5384 else
5385 scsi_host_set_guard(hpnt, SHOST_DIX_GUARD_CRC);
5386
Douglas Gilbert817fd662014-11-24 20:18:02 -05005387 opts = scsi_debug_opts;
5388 if (SCSI_DEBUG_OPT_RECOVERED_ERR & opts)
5389 sdebug_any_injecting_opt = true;
5390 else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & opts)
5391 sdebug_any_injecting_opt = true;
5392 else if (SCSI_DEBUG_OPT_DIF_ERR & opts)
5393 sdebug_any_injecting_opt = true;
5394 else if (SCSI_DEBUG_OPT_DIX_ERR & opts)
5395 sdebug_any_injecting_opt = true;
5396 else if (SCSI_DEBUG_OPT_SHORT_TRANSFER & opts)
5397 sdebug_any_injecting_opt = true;
5398
Linus Torvalds1da177e2005-04-16 15:20:36 -07005399 error = scsi_add_host(hpnt, &sdbg_host->dev);
5400 if (error) {
Tomas Winklerc12879702015-07-28 16:54:20 +03005401 pr_err("scsi_add_host failed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005402 error = -ENODEV;
5403 scsi_host_put(hpnt);
5404 } else
5405 scsi_scan_host(hpnt);
5406
Douglas Gilbertcbf67842014-07-26 11:55:35 -04005407 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005408}
5409
5410static int sdebug_driver_remove(struct device * dev)
5411{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005412 struct sdebug_host_info *sdbg_host;
FUJITA Tomonori8b40228f2008-03-20 11:09:18 +09005413 struct sdebug_dev_info *sdbg_devinfo, *tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005414
5415 sdbg_host = to_sdebug_host(dev);
5416
5417 if (!sdbg_host) {
Tomas Winklerc12879702015-07-28 16:54:20 +03005418 pr_err("Unable to locate host info\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005419 return -ENODEV;
5420 }
5421
5422 scsi_remove_host(sdbg_host->shost);
5423
FUJITA Tomonori8b40228f2008-03-20 11:09:18 +09005424 list_for_each_entry_safe(sdbg_devinfo, tmp, &sdbg_host->dev_info_list,
5425 dev_list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005426 list_del(&sdbg_devinfo->dev_list);
5427 kfree(sdbg_devinfo);
5428 }
5429
5430 scsi_host_put(sdbg_host->shost);
5431 return 0;
5432}
5433
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09005434static int pseudo_lld_bus_match(struct device *dev,
5435 struct device_driver *dev_driver)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005436{
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09005437 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005438}
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09005439
5440static struct bus_type pseudo_lld_bus = {
5441 .name = "pseudo",
5442 .match = pseudo_lld_bus_match,
5443 .probe = sdebug_driver_probe,
5444 .remove = sdebug_driver_remove,
Akinobu Mita82069372013-10-14 22:48:04 +09005445 .drv_groups = sdebug_drv_groups,
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09005446};