blob: 0d0e0593e3c517b3c42ee41cebd8d7726dc4579f [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 * vvvvvvvvvvvvvvvvvvvvvvv Original vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
3 * Copyright (C) 1992 Eric Youngdale
4 * Simulate a host adapter with 2 disks attached. Do a lot of checking
5 * to make sure that we are not getting blocks mixed up, and PANIC if
6 * anything out of the ordinary is seen.
7 * ^^^^^^^^^^^^^^^^^^^^^^^ Original ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
8 *
9 * This version is more generic, simulating a variable number of disk
Douglas Gilbert23183912006-09-16 20:30:47 -040010 * (or disk like devices) sharing a common amount of RAM. To be more
11 * realistic, the simulated devices have the transport attributes of
12 * SAS disks.
Linus Torvalds1da177e2005-04-16 15:20:36 -070013 *
14 *
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -040015 * For documentation see http://sg.danny.cz/sg/sdebug26.html
Linus Torvalds1da177e2005-04-16 15:20:36 -070016 *
17 * D. Gilbert (dpg) work for Magneto-Optical device test [20010421]
18 * dpg: work for devfs large number of disks [20010809]
19 * forked for lk 2.5 series [20011216, 20020101]
20 * use vmalloc() more inquiry+mode_sense [20020302]
21 * add timers for delayed responses [20020721]
22 * Patrick Mansfield <patmans@us.ibm.com> max_luns+scsi_level [20021031]
23 * Mike Anderson <andmike@us.ibm.com> sysfs work [20021118]
24 * dpg: change style of boot options to "scsi_debug.num_tgts=2" and
25 * module options to "modprobe scsi_debug num_tgts=2" [20021221]
26 */
27
Linus Torvalds1da177e2005-04-16 15:20:36 -070028#include <linux/module.h>
29
30#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070031#include <linux/errno.h>
32#include <linux/timer.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090033#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070034#include <linux/types.h>
35#include <linux/string.h>
36#include <linux/genhd.h>
37#include <linux/fs.h>
38#include <linux/init.h>
39#include <linux/proc_fs.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070040#include <linux/vmalloc.h>
41#include <linux/moduleparam.h>
Jens Axboe852e0342007-07-16 10:19:24 +020042#include <linux/scatterlist.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#include <linux/blkdev.h>
Martin K. Petersenc6a44282009-01-04 03:08:19 -050044#include <linux/crc-t10dif.h>
Douglas Gilbertcbf67842014-07-26 11:55:35 -040045#include <linux/spinlock.h>
46#include <linux/interrupt.h>
47#include <linux/atomic.h>
48#include <linux/hrtimer.h>
Martin K. Petersenc6a44282009-01-04 03:08:19 -050049
50#include <net/checksum.h>
FUJITA Tomonori9ff26ee2008-03-02 18:30:15 +090051
Martin K. Petersen44d92692009-10-15 14:45:27 -040052#include <asm/unaligned.h>
53
FUJITA Tomonori9ff26ee2008-03-02 18:30:15 +090054#include <scsi/scsi.h>
55#include <scsi/scsi_cmnd.h>
56#include <scsi/scsi_device.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070057#include <scsi/scsi_host.h>
58#include <scsi/scsicam.h>
FUJITA Tomonoria34c4e92008-03-25 09:26:50 +090059#include <scsi/scsi_eh.h>
Douglas Gilbertcbf67842014-07-26 11:55:35 -040060#include <scsi/scsi_tcq.h>
Martin K. Petersen395cef02009-09-18 17:33:03 -040061#include <scsi/scsi_dbg.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070062
Martin K. Petersenc6a44282009-01-04 03:08:19 -050063#include "sd.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070064#include "scsi_logging.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070065
Douglas Gilbert22017ed2014-11-24 23:04:47 -050066#define SCSI_DEBUG_VERSION "1.85"
67static const char *scsi_debug_version_date = "20141022";
Douglas Gilbertcbf67842014-07-26 11:55:35 -040068
69#define MY_NAME "scsi_debug"
Linus Torvalds1da177e2005-04-16 15:20:36 -070070
Douglas Gilbert6f3cbf52007-01-05 00:05:25 -050071/* Additional Sense Code (ASC) */
Douglas Gilbertc65b1442006-06-06 00:11:24 -040072#define NO_ADDITIONAL_SENSE 0x0
73#define LOGICAL_UNIT_NOT_READY 0x4
Douglas Gilbertc2248fc2014-11-24 20:46:29 -050074#define LOGICAL_UNIT_COMMUNICATION_FAILURE 0x8
Linus Torvalds1da177e2005-04-16 15:20:36 -070075#define UNRECOVERED_READ_ERR 0x11
Douglas Gilbertc65b1442006-06-06 00:11:24 -040076#define PARAMETER_LIST_LENGTH_ERR 0x1a
Linus Torvalds1da177e2005-04-16 15:20:36 -070077#define INVALID_OPCODE 0x20
Douglas Gilbert22017ed2014-11-24 23:04:47 -050078#define LBA_OUT_OF_RANGE 0x21
Linus Torvalds1da177e2005-04-16 15:20:36 -070079#define INVALID_FIELD_IN_CDB 0x24
Douglas Gilbertc65b1442006-06-06 00:11:24 -040080#define INVALID_FIELD_IN_PARAM_LIST 0x26
Douglas Gilbertcbf67842014-07-26 11:55:35 -040081#define UA_RESET_ASC 0x29
82#define UA_CHANGED_ASC 0x2a
Douglas Gilbert22017ed2014-11-24 23:04:47 -050083#define INSUFF_RES_ASC 0x55
84#define INSUFF_RES_ASCQ 0x3
Douglas Gilbertcbf67842014-07-26 11:55:35 -040085#define POWER_ON_RESET_ASCQ 0x0
86#define BUS_RESET_ASCQ 0x2 /* scsi bus reset occurred */
87#define MODE_CHANGED_ASCQ 0x1 /* mode parameters changed */
Douglas Gilbert22017ed2014-11-24 23:04:47 -050088#define CAPACITY_CHANGED_ASCQ 0x9
Linus Torvalds1da177e2005-04-16 15:20:36 -070089#define SAVING_PARAMS_UNSUP 0x39
Douglas Gilbert6f3cbf52007-01-05 00:05:25 -050090#define TRANSPORT_PROBLEM 0x4b
Douglas Gilbertc65b1442006-06-06 00:11:24 -040091#define THRESHOLD_EXCEEDED 0x5d
92#define LOW_POWER_COND_ON 0x5e
Douglas Gilbert22017ed2014-11-24 23:04:47 -050093#define MISCOMPARE_VERIFY_ASC 0x1d
Linus Torvalds1da177e2005-04-16 15:20:36 -070094
Douglas Gilbert6f3cbf52007-01-05 00:05:25 -050095/* Additional Sense Code Qualifier (ASCQ) */
96#define ACK_NAK_TO 0x3
97
Linus Torvalds1da177e2005-04-16 15:20:36 -070098
99/* Default values for driver parameters */
100#define DEF_NUM_HOST 1
101#define DEF_NUM_TGTS 1
102#define DEF_MAX_LUNS 1
103/* With these defaults, this driver will make 1 host with 1 target
104 * (id 0) containing 1 logical unit (lun 0). That is 1 device.
105 */
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500106#define DEF_ATO 1
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400107#define DEF_DELAY 1 /* if > 0 unit is a jiffy */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108#define DEF_DEV_SIZE_MB 8
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500109#define DEF_DIF 0
110#define DEF_DIX 0
111#define DEF_D_SENSE 0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112#define DEF_EVERY_NTH 0
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500113#define DEF_FAKE_RW 0
114#define DEF_GUARD 0
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400115#define DEF_HOST_LOCK 0
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500116#define DEF_LBPU 0
117#define DEF_LBPWS 0
118#define DEF_LBPWS10 0
Eric Sandeenbe1dd782012-03-08 00:03:59 -0600119#define DEF_LBPRZ 1
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500120#define DEF_LOWEST_ALIGNED 0
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400121#define DEF_NDELAY 0 /* if > 0 unit is a nanosecond */
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500122#define DEF_NO_LUN_0 0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123#define DEF_NUM_PARTS 0
124#define DEF_OPTS 0
Martin K. Petersene308b3d2010-03-23 01:12:27 -0400125#define DEF_OPT_BLKS 64
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500126#define DEF_PHYSBLK_EXP 0
127#define DEF_PTYPE 0
Martin Pittd9867882012-09-06 12:04:33 +0200128#define DEF_REMOVABLE false
Douglas Gilberte46b0342014-08-05 12:21:53 +0200129#define DEF_SCSI_LEVEL 6 /* INQUIRY, byte2 [6->SPC-4] */
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500130#define DEF_SECTOR_SIZE 512
131#define DEF_UNMAP_ALIGNMENT 0
132#define DEF_UNMAP_GRANULARITY 1
Martin K. Petersen60147592010-08-19 11:49:00 -0400133#define DEF_UNMAP_MAX_BLOCKS 0xFFFFFFFF
134#define DEF_UNMAP_MAX_DESC 256
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500135#define DEF_VIRTUAL_GB 0
136#define DEF_VPD_USE_HOSTNO 1
137#define DEF_WRITESAME_LENGTH 0xFFFF
Douglas Gilbertc2248fc2014-11-24 20:46:29 -0500138#define DEF_STRICT 0
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400139#define DELAY_OVERRIDDEN -9999
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140
141/* bit mask values for scsi_debug_opts */
142#define SCSI_DEBUG_OPT_NOISE 1
143#define SCSI_DEBUG_OPT_MEDIUM_ERR 2
144#define SCSI_DEBUG_OPT_TIMEOUT 4
145#define SCSI_DEBUG_OPT_RECOVERED_ERR 8
Douglas Gilbert6f3cbf52007-01-05 00:05:25 -0500146#define SCSI_DEBUG_OPT_TRANSPORT_ERR 16
Martin K. Petersenc6a44282009-01-04 03:08:19 -0500147#define SCSI_DEBUG_OPT_DIF_ERR 32
148#define SCSI_DEBUG_OPT_DIX_ERR 64
Martin K. Petersen18a4d0a2012-02-09 13:48:53 -0500149#define SCSI_DEBUG_OPT_MAC_TIMEOUT 128
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400150#define SCSI_DEBUG_OPT_SHORT_TRANSFER 0x100
151#define SCSI_DEBUG_OPT_Q_NOISE 0x200
152#define SCSI_DEBUG_OPT_ALL_TSF 0x400
153#define SCSI_DEBUG_OPT_RARE_TSF 0x800
154#define SCSI_DEBUG_OPT_N_WCE 0x1000
155#define SCSI_DEBUG_OPT_RESET_NOISE 0x2000
156#define SCSI_DEBUG_OPT_NO_CDB_NOISE 0x4000
157#define SCSI_DEBUG_OPT_ALL_NOISE (0x1 | 0x200 | 0x2000)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158/* When "every_nth" > 0 then modulo "every_nth" commands:
159 * - a no response is simulated if SCSI_DEBUG_OPT_TIMEOUT is set
160 * - a RECOVERED_ERROR is simulated on successful read and write
161 * commands if SCSI_DEBUG_OPT_RECOVERED_ERR is set.
Douglas Gilbert6f3cbf52007-01-05 00:05:25 -0500162 * - a TRANSPORT_ERROR is simulated on successful read and write
163 * commands if SCSI_DEBUG_OPT_TRANSPORT_ERR is set.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700164 *
165 * When "every_nth" < 0 then after "- 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 * This will continue until some other action occurs (e.g. the user
172 * writing a new value (other than -1 or 1) to every_nth via sysfs).
173 */
174
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400175/* As indicated in SAM-5 and SPC-4 Unit Attentions (UAs)are returned in
176 * priority order. In the subset implemented here lower numbers have higher
177 * priority. The UA numbers should be a sequence starting from 0 with
178 * SDEBUG_NUM_UAS being 1 higher than the highest numbered UA. */
179#define SDEBUG_UA_POR 0 /* Power on, reset, or bus device reset */
180#define SDEBUG_UA_BUS_RESET 1
181#define SDEBUG_UA_MODE_CHANGED 2
Douglas Gilbert0d01c5d2014-11-24 20:27:51 -0500182#define SDEBUG_UA_CAPACITY_CHANGED 3
183#define SDEBUG_NUM_UAS 4
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400184
185/* for check_readiness() */
Douglas Gilbertc2248fc2014-11-24 20:46:29 -0500186#define UAS_ONLY 1 /* check for UAs only */
187#define UAS_TUR 0 /* if no UAs then check if media access possible */
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400188
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189/* when 1==SCSI_DEBUG_OPT_MEDIUM_ERR, a medium error is simulated at this
190 * sector on read commands: */
191#define OPT_MEDIUM_ERR_ADDR 0x1234 /* that's sector 4660 in decimal */
Douglas Gilbert32f7ef72011-03-11 10:43:35 -0500192#define OPT_MEDIUM_ERR_NUM 10 /* number of consecutive medium errs */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193
194/* If REPORT LUNS has luns >= 256 it can choose "flat space" (value 1)
195 * or "peripheral device" addressing (value 0) */
196#define SAM2_LUN_ADDRESS_METHOD 0
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400197#define SAM2_WLUN_REPORT_LUNS 0xc101
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400199/* SCSI_DEBUG_CANQUEUE is the maximum number of commands that can be queued
200 * (for response) at one time. Can be reduced by max_queue option. Command
201 * responses are not queued when delay=0 and ndelay=0. The per-device
202 * DEF_CMD_PER_LUN can be changed via sysfs:
203 * /sys/class/scsi_device/<h:c:t:l>/device/queue_depth but cannot exceed
204 * SCSI_DEBUG_CANQUEUE. */
205#define SCSI_DEBUG_CANQUEUE_WORDS 9 /* a WORD is bits in a long */
206#define SCSI_DEBUG_CANQUEUE (SCSI_DEBUG_CANQUEUE_WORDS * BITS_PER_LONG)
207#define DEF_CMD_PER_LUN 255
208
209#if DEF_CMD_PER_LUN > SCSI_DEBUG_CANQUEUE
210#warning "Expect DEF_CMD_PER_LUN <= SCSI_DEBUG_CANQUEUE"
211#endif
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -0400212
Douglas Gilbertc2248fc2014-11-24 20:46:29 -0500213/* SCSI opcodes (first byte of cdb) mapped onto these indexes */
214enum sdeb_opcode_index {
215 SDEB_I_INVALID_OPCODE = 0,
216 SDEB_I_INQUIRY = 1,
217 SDEB_I_REPORT_LUNS = 2,
218 SDEB_I_REQUEST_SENSE = 3,
219 SDEB_I_TEST_UNIT_READY = 4,
220 SDEB_I_MODE_SENSE = 5, /* 6, 10 */
221 SDEB_I_MODE_SELECT = 6, /* 6, 10 */
222 SDEB_I_LOG_SENSE = 7,
223 SDEB_I_READ_CAPACITY = 8, /* 10; 16 is in SA_IN(16) */
224 SDEB_I_READ = 9, /* 6, 10, 12, 16 */
225 SDEB_I_WRITE = 10, /* 6, 10, 12, 16 */
226 SDEB_I_START_STOP = 11,
227 SDEB_I_SERV_ACT_IN = 12, /* 12, 16 */
228 SDEB_I_SERV_ACT_OUT = 13, /* 12, 16 */
229 SDEB_I_MAINT_IN = 14,
230 SDEB_I_MAINT_OUT = 15,
231 SDEB_I_VERIFY = 16, /* 10 only */
232 SDEB_I_VARIABLE_LEN = 17,
233 SDEB_I_RESERVE = 18, /* 6, 10 */
234 SDEB_I_RELEASE = 19, /* 6, 10 */
235 SDEB_I_ALLOW_REMOVAL = 20, /* PREVENT ALLOW MEDIUM REMOVAL */
236 SDEB_I_REZERO_UNIT = 21, /* REWIND in SSC */
237 SDEB_I_ATA_PT = 22, /* 12, 16 */
238 SDEB_I_SEND_DIAG = 23,
239 SDEB_I_UNMAP = 24,
240 SDEB_I_XDWRITEREAD = 25, /* 10 only */
241 SDEB_I_WRITE_BUFFER = 26,
242 SDEB_I_WRITE_SAME = 27, /* 10, 16 */
243 SDEB_I_SYNC_CACHE = 28, /* 10 only */
244 SDEB_I_COMP_WRITE = 29,
245 SDEB_I_LAST_ELEMENT = 30, /* keep this last */
246};
247
248static const unsigned char opcode_ind_arr[256] = {
249/* 0x0; 0x0->0x1f: 6 byte cdbs */
250 SDEB_I_TEST_UNIT_READY, SDEB_I_REZERO_UNIT, 0, SDEB_I_REQUEST_SENSE,
251 0, 0, 0, 0,
252 SDEB_I_READ, 0, SDEB_I_WRITE, 0, 0, 0, 0, 0,
253 0, 0, SDEB_I_INQUIRY, 0, 0, SDEB_I_MODE_SELECT, SDEB_I_RESERVE,
254 SDEB_I_RELEASE,
255 0, 0, SDEB_I_MODE_SENSE, SDEB_I_START_STOP, 0, SDEB_I_SEND_DIAG,
256 SDEB_I_ALLOW_REMOVAL, 0,
257/* 0x20; 0x20->0x3f: 10 byte cdbs */
258 0, 0, 0, 0, 0, SDEB_I_READ_CAPACITY, 0, 0,
259 SDEB_I_READ, 0, SDEB_I_WRITE, 0, 0, 0, 0, SDEB_I_VERIFY,
260 0, 0, 0, 0, 0, SDEB_I_SYNC_CACHE, 0, 0,
261 0, 0, 0, SDEB_I_WRITE_BUFFER, 0, 0, 0, 0,
262/* 0x40; 0x40->0x5f: 10 byte cdbs */
263 0, SDEB_I_WRITE_SAME, SDEB_I_UNMAP, 0, 0, 0, 0, 0,
264 0, 0, 0, 0, 0, SDEB_I_LOG_SENSE, 0, 0,
265 0, 0, 0, SDEB_I_XDWRITEREAD, 0, SDEB_I_MODE_SELECT, SDEB_I_RESERVE,
266 SDEB_I_RELEASE,
267 0, 0, SDEB_I_MODE_SENSE, 0, 0, 0, 0, 0,
268/* 0x60; 0x60->0x7d are reserved */
269 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
270 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
271 0, SDEB_I_VARIABLE_LEN,
272/* 0x80; 0x80->0x9f: 16 byte cdbs */
273 0, 0, 0, 0, 0, SDEB_I_ATA_PT, 0, 0,
274 SDEB_I_READ, SDEB_I_COMP_WRITE, SDEB_I_WRITE, 0, 0, 0, 0, 0,
275 0, 0, 0, SDEB_I_WRITE_SAME, 0, 0, 0, 0,
276 0, 0, 0, 0, 0, 0, SDEB_I_SERV_ACT_IN, SDEB_I_SERV_ACT_OUT,
277/* 0xa0; 0xa0->0xbf: 12 byte cdbs */
278 SDEB_I_REPORT_LUNS, SDEB_I_ATA_PT, 0, SDEB_I_MAINT_IN,
279 SDEB_I_MAINT_OUT, 0, 0, 0,
280 SDEB_I_READ, SDEB_I_SERV_ACT_OUT, SDEB_I_WRITE, SDEB_I_SERV_ACT_IN,
281 0, 0, 0, 0,
282 0, 0, 0, 0, 0, 0, 0, 0,
283 0, 0, 0, 0, 0, 0, 0, 0,
284/* 0xc0; 0xc0->0xff: vendor specific */
285 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
286 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
287 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
288 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
289};
290
291#define F_D_IN 1
292#define F_D_OUT 2
293#define F_D_OUT_MAYBE 4 /* WRITE SAME, NDOB bit */
294#define F_D_UNKN 8
295#define F_RL_WLUN_OK 0x10
296#define F_SKIP_UA 0x20
297#define F_DELAY_OVERR 0x40
298#define F_SA_LOW 0x80 /* cdb byte 1, bits 4 to 0 */
299#define F_SA_HIGH 0x100 /* as used by variable length cdbs */
300#define F_INV_OP 0x200
301#define F_FAKE_RW 0x400
302#define F_M_ACCESS 0x800 /* media access */
303
304#define FF_RESPOND (F_RL_WLUN_OK | F_SKIP_UA | F_DELAY_OVERR)
305#define FF_DIRECT_IO (F_M_ACCESS | F_FAKE_RW)
306#define FF_SA (F_SA_HIGH | F_SA_LOW)
307
308struct sdebug_dev_info;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -0500309static int resp_inquiry(struct scsi_cmnd *, struct sdebug_dev_info *);
310static int resp_report_luns(struct scsi_cmnd *, struct sdebug_dev_info *);
311static int resp_requests(struct scsi_cmnd *, struct sdebug_dev_info *);
312static int resp_mode_sense(struct scsi_cmnd *, struct sdebug_dev_info *);
313static int resp_mode_select(struct scsi_cmnd *, struct sdebug_dev_info *);
314static int resp_log_sense(struct scsi_cmnd *, struct sdebug_dev_info *);
315static int resp_readcap(struct scsi_cmnd *, struct sdebug_dev_info *);
316static int resp_read_dt0(struct scsi_cmnd *, struct sdebug_dev_info *);
317static int resp_write_dt0(struct scsi_cmnd *, struct sdebug_dev_info *);
318static int resp_start_stop(struct scsi_cmnd *, struct sdebug_dev_info *);
319static int resp_readcap16(struct scsi_cmnd *, struct sdebug_dev_info *);
320static int resp_get_lba_status(struct scsi_cmnd *, struct sdebug_dev_info *);
321static int resp_report_tgtpgs(struct scsi_cmnd *, struct sdebug_dev_info *);
322static int resp_unmap(struct scsi_cmnd *, struct sdebug_dev_info *);
Douglas Gilbert38d5c832014-11-24 21:27:12 -0500323static int resp_rsup_opcodes(struct scsi_cmnd *, struct sdebug_dev_info *);
324static int resp_rsup_tmfs(struct scsi_cmnd *, struct sdebug_dev_info *);
Douglas Gilbertc2248fc2014-11-24 20:46:29 -0500325static int resp_write_same_10(struct scsi_cmnd *, struct sdebug_dev_info *);
326static int resp_write_same_16(struct scsi_cmnd *, struct sdebug_dev_info *);
327static int resp_xdwriteread_10(struct scsi_cmnd *, struct sdebug_dev_info *);
Douglas Gilbert38d5c832014-11-24 21:27:12 -0500328static int resp_comp_write(struct scsi_cmnd *, struct sdebug_dev_info *);
Douglas Gilbertc2248fc2014-11-24 20:46:29 -0500329
330struct opcode_info_t {
331 u8 num_attached; /* 0 if this is it (i.e. a leaf); use 0xff
332 * for terminating element */
333 u8 opcode; /* if num_attached > 0, preferred */
334 u16 sa; /* service action */
335 u32 flags; /* OR-ed set of SDEB_F_* */
336 int (*pfp)(struct scsi_cmnd *, struct sdebug_dev_info *);
337 const struct opcode_info_t *arrp; /* num_attached elements or NULL */
338 u8 len_mask[16]; /* len=len_mask[0], then mask for cdb[1]... */
339 /* ignore cdb bytes after position 15 */
340};
341
342static const struct opcode_info_t msense_iarr[1] = {
343 {0, 0x1a, 0, F_D_IN, NULL, NULL,
344 {6, 0xe8, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
345};
346
347static const struct opcode_info_t mselect_iarr[1] = {
348 {0, 0x15, 0, F_D_OUT, NULL, NULL,
349 {6, 0xf1, 0, 0, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
350};
351
352static const struct opcode_info_t read_iarr[3] = {
353 {0, 0x28, 0, F_D_IN | FF_DIRECT_IO, resp_read_dt0, NULL,/* READ(10) */
354 {10, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xc7, 0, 0,
355 0, 0, 0, 0} },
356 {0, 0x8, 0, F_D_IN | FF_DIRECT_IO, resp_read_dt0, NULL, /* READ(6) */
357 {6, 0xff, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
358 {0, 0xa8, 0, F_D_IN | FF_DIRECT_IO, resp_read_dt0, NULL,/* READ(12) */
359 {12, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f,
360 0xc7, 0, 0, 0, 0} },
361};
362
363static const struct opcode_info_t write_iarr[3] = {
364 {0, 0x2a, 0, F_D_OUT | FF_DIRECT_IO, resp_write_dt0, NULL, /* 10 */
365 {10, 0xfb, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xc7, 0, 0,
366 0, 0, 0, 0} },
367 {0, 0xa, 0, F_D_OUT | FF_DIRECT_IO, resp_write_dt0, NULL, /* 6 */
368 {6, 0xff, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
369 {0, 0xaa, 0, F_D_OUT | FF_DIRECT_IO, resp_write_dt0, NULL, /* 12 */
370 {12, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f,
371 0xc7, 0, 0, 0, 0} },
372};
373
374static const struct opcode_info_t sa_in_iarr[1] = {
375 {0, 0x9e, 0x12, F_SA_LOW | F_D_IN, resp_get_lba_status, NULL,
376 {16, 0x12, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
377 0xff, 0xff, 0xff, 0, 0xc7} },
378};
379
380static const struct opcode_info_t vl_iarr[1] = { /* VARIABLE LENGTH */
381 {0, 0x7f, 0xb, F_SA_HIGH | F_D_OUT | FF_DIRECT_IO, resp_write_dt0,
382 NULL, {32, 0xc7, 0, 0, 0, 0, 0x1f, 0x18, 0x0, 0xb, 0xfa,
383 0, 0xff, 0xff, 0xff, 0xff} }, /* WRITE(32) */
384};
385
386static const struct opcode_info_t maint_in_iarr[2] = {
Douglas Gilbert38d5c832014-11-24 21:27:12 -0500387 {0, 0xa3, 0xc, F_SA_LOW | F_D_IN, resp_rsup_opcodes, NULL,
Douglas Gilbertc2248fc2014-11-24 20:46:29 -0500388 {12, 0xc, 0x87, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0,
389 0xc7, 0, 0, 0, 0} },
Douglas Gilbert38d5c832014-11-24 21:27:12 -0500390 {0, 0xa3, 0xd, F_SA_LOW | F_D_IN, resp_rsup_tmfs, NULL,
Douglas Gilbertc2248fc2014-11-24 20:46:29 -0500391 {12, 0xd, 0x80, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0, 0xc7, 0, 0,
392 0, 0} },
393};
394
395static const struct opcode_info_t write_same_iarr[1] = {
396 {0, 0x93, 0, F_D_OUT_MAYBE | FF_DIRECT_IO, resp_write_same_16, NULL,
397 {16, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
398 0xff, 0xff, 0xff, 0x1f, 0xc7} },
399};
400
401static const struct opcode_info_t reserve_iarr[1] = {
402 {0, 0x16, 0, F_D_OUT, NULL, NULL, /* RESERVE(6) */
403 {6, 0x1f, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
404};
405
406static const struct opcode_info_t release_iarr[1] = {
407 {0, 0x17, 0, F_D_OUT, NULL, NULL, /* RELEASE(6) */
408 {6, 0x1f, 0xff, 0, 0, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
409};
410
411
412/* This array is accessed via SDEB_I_* values. Make sure all are mapped,
413 * plus the terminating elements for logic that scans this table such as
414 * REPORT SUPPORTED OPERATION CODES. */
415static const struct opcode_info_t opcode_info_arr[SDEB_I_LAST_ELEMENT + 1] = {
416/* 0 */
417 {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL,
418 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
419 {0, 0x12, 0, FF_RESPOND | F_D_IN, resp_inquiry, NULL,
420 {6, 0xe3, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
421 {0, 0xa0, 0, FF_RESPOND | F_D_IN, resp_report_luns, NULL,
422 {12, 0xe3, 0xff, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0, 0xc7, 0, 0,
423 0, 0} },
424 {0, 0x3, 0, FF_RESPOND | F_D_IN, resp_requests, NULL,
425 {6, 0xe1, 0, 0, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
426 {0, 0x0, 0, F_M_ACCESS | F_RL_WLUN_OK, NULL, NULL,/* TEST UNIT READY */
427 {6, 0, 0, 0, 0, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
428 {1, 0x5a, 0, F_D_IN, resp_mode_sense, msense_iarr,
429 {10, 0xf8, 0xff, 0xff, 0, 0, 0, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0,
430 0} },
431 {1, 0x55, 0, F_D_OUT, resp_mode_select, mselect_iarr,
432 {10, 0xf1, 0, 0, 0, 0, 0, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0} },
433 {0, 0x4d, 0, F_D_IN, resp_log_sense, NULL,
434 {10, 0xe3, 0xff, 0xff, 0, 0xff, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0,
435 0, 0, 0} },
436 {0, 0x25, 0, F_D_IN, resp_readcap, NULL,
437 {10, 0xe1, 0xff, 0xff, 0xff, 0xff, 0, 0, 0x1, 0xc7, 0, 0, 0, 0,
438 0, 0} },
439 {3, 0x88, 0, F_D_IN | FF_DIRECT_IO, resp_read_dt0, read_iarr,
440 {16, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
441 0xff, 0xff, 0xff, 0x9f, 0xc7} }, /* READ(16) */
442/* 10 */
443 {3, 0x8a, 0, F_D_OUT | FF_DIRECT_IO, resp_write_dt0, write_iarr,
444 {16, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
445 0xff, 0xff, 0xff, 0x9f, 0xc7} }, /* WRITE(16) */
446 {0, 0x1b, 0, 0, resp_start_stop, NULL, /* START STOP UNIT */
447 {6, 0x1, 0, 0xf, 0xf7, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
448 {1, 0x9e, 0x10, F_SA_LOW | F_D_IN, resp_readcap16, sa_in_iarr,
449 {16, 0x10, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
450 0xff, 0xff, 0xff, 0x1, 0xc7} }, /* READ CAPACITY(16) */
451 {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, /* SA OUT */
452 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
453 {2, 0xa3, 0xa, F_SA_LOW | F_D_IN, resp_report_tgtpgs, maint_in_iarr,
454 {12, 0xea, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0, 0xc7, 0, 0, 0,
455 0} },
456 {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, /* MAINT OUT */
457 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
458 {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, /* VERIFY */
459 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
460 {1, 0x7f, 0x9, F_SA_HIGH | F_D_IN | FF_DIRECT_IO, resp_read_dt0,
461 vl_iarr, {32, 0xc7, 0, 0, 0, 0, 0x1f, 0x18, 0x0, 0x9, 0xfe, 0,
462 0xff, 0xff, 0xff, 0xff} },/* VARIABLE LENGTH, READ(32) */
463 {1, 0x56, 0, F_D_OUT, NULL, reserve_iarr, /* RESERVE(10) */
464 {10, 0xff, 0xff, 0xff, 0, 0, 0, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0,
465 0} },
466 {1, 0x57, 0, F_D_OUT, NULL, release_iarr, /* RELEASE(10) */
467 {10, 0x13, 0xff, 0xff, 0, 0, 0, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0,
468 0} },
469/* 20 */
470 {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, /* ALLOW REMOVAL */
471 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
472 {0, 0x1, 0, 0, resp_start_stop, NULL, /* REWIND ?? */
473 {6, 0x1, 0, 0, 0, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
474 {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, /* ATA_PT */
475 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
476 {0, 0x1d, F_D_OUT, 0, NULL, NULL, /* SEND DIAGNOSTIC */
477 {6, 0xf7, 0, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
478 {0, 0x42, 0, F_D_OUT | FF_DIRECT_IO, resp_unmap, NULL, /* UNMAP */
479 {10, 0x1, 0, 0, 0, 0, 0x1f, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0} },
480 {0, 0x53, 0, F_D_IN | F_D_OUT | FF_DIRECT_IO, resp_xdwriteread_10,
481 NULL, {10, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xc7,
482 0, 0, 0, 0, 0, 0} },
483 {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, /* WRITE_BUFFER */
484 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
485 {1, 0x41, 0, F_D_OUT_MAYBE | FF_DIRECT_IO, resp_write_same_10,
486 write_same_iarr, {10, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff,
487 0xff, 0xc7, 0, 0, 0, 0, 0, 0} },
488 {0, 0x35, 0, F_DELAY_OVERR | FF_DIRECT_IO, NULL, NULL, /* SYNC_CACHE */
489 {10, 0x7, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xc7, 0, 0,
490 0, 0, 0, 0} },
Douglas Gilbert38d5c832014-11-24 21:27:12 -0500491 {0, 0x89, 0, F_D_OUT | FF_DIRECT_IO, resp_comp_write, NULL,
Douglas Gilbertc2248fc2014-11-24 20:46:29 -0500492 {16, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0,
493 0, 0xff, 0x1f, 0xc7} }, /* COMPARE AND WRITE */
494
495/* 30 */
496 {0xff, 0, 0, 0, NULL, NULL, /* terminating element */
497 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
498};
499
Douglas Gilbert817fd662014-11-24 20:18:02 -0500500struct sdebug_scmd_extra_t {
501 bool inj_recovered;
502 bool inj_transport;
503 bool inj_dif;
504 bool inj_dix;
505 bool inj_short;
506};
507
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508static int scsi_debug_add_host = DEF_NUM_HOST;
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500509static int scsi_debug_ato = DEF_ATO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510static int scsi_debug_delay = DEF_DELAY;
511static int scsi_debug_dev_size_mb = DEF_DEV_SIZE_MB;
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500512static int scsi_debug_dif = DEF_DIF;
513static int scsi_debug_dix = DEF_DIX;
514static int scsi_debug_dsense = DEF_D_SENSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515static int scsi_debug_every_nth = DEF_EVERY_NTH;
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500516static int scsi_debug_fake_rw = DEF_FAKE_RW;
Akinobu Mita68aee7b2013-09-18 21:27:27 +0900517static unsigned int scsi_debug_guard = DEF_GUARD;
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500518static int scsi_debug_lowest_aligned = DEF_LOWEST_ALIGNED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519static int scsi_debug_max_luns = DEF_MAX_LUNS;
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -0400520static int scsi_debug_max_queue = SCSI_DEBUG_CANQUEUE;
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400521static atomic_t retired_max_queue; /* if > 0 then was prior max_queue */
522static int scsi_debug_ndelay = DEF_NDELAY;
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400523static int scsi_debug_no_lun_0 = DEF_NO_LUN_0;
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500524static int scsi_debug_no_uld = 0;
525static int scsi_debug_num_parts = DEF_NUM_PARTS;
526static int scsi_debug_num_tgts = DEF_NUM_TGTS; /* targets per host */
Martin K. Petersene308b3d2010-03-23 01:12:27 -0400527static int scsi_debug_opt_blks = DEF_OPT_BLKS;
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500528static int scsi_debug_opts = DEF_OPTS;
529static int scsi_debug_physblk_exp = DEF_PHYSBLK_EXP;
530static int scsi_debug_ptype = DEF_PTYPE; /* SCSI peripheral type (0==disk) */
531static int scsi_debug_scsi_level = DEF_SCSI_LEVEL;
532static int scsi_debug_sector_size = DEF_SECTOR_SIZE;
533static int scsi_debug_virtual_gb = DEF_VIRTUAL_GB;
534static int scsi_debug_vpd_use_hostno = DEF_VPD_USE_HOSTNO;
535static unsigned int scsi_debug_lbpu = DEF_LBPU;
536static unsigned int scsi_debug_lbpws = DEF_LBPWS;
537static unsigned int scsi_debug_lbpws10 = DEF_LBPWS10;
Eric Sandeenbe1dd782012-03-08 00:03:59 -0600538static unsigned int scsi_debug_lbprz = DEF_LBPRZ;
Martin K. Petersen60147592010-08-19 11:49:00 -0400539static unsigned int scsi_debug_unmap_alignment = DEF_UNMAP_ALIGNMENT;
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500540static unsigned int scsi_debug_unmap_granularity = DEF_UNMAP_GRANULARITY;
541static unsigned int scsi_debug_unmap_max_blocks = DEF_UNMAP_MAX_BLOCKS;
542static unsigned int scsi_debug_unmap_max_desc = DEF_UNMAP_MAX_DESC;
543static unsigned int scsi_debug_write_same_length = DEF_WRITESAME_LENGTH;
Martin Pittd9867882012-09-06 12:04:33 +0200544static bool scsi_debug_removable = DEF_REMOVABLE;
Akinobu Mita0759c662014-02-26 22:57:04 +0900545static bool scsi_debug_clustering;
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400546static bool scsi_debug_host_lock = DEF_HOST_LOCK;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -0500547static bool scsi_debug_strict = DEF_STRICT;
Douglas Gilbert817fd662014-11-24 20:18:02 -0500548static bool sdebug_any_injecting_opt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400550static atomic_t sdebug_cmnd_count;
551static atomic_t sdebug_completions;
552static atomic_t sdebug_a_tsf; /* counter of 'almost' TSFs */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553
554#define DEV_READONLY(TGT) (0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400556static unsigned int sdebug_store_sectors;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557static sector_t sdebug_capacity; /* in sectors */
558
559/* old BIOS stuff, kernel may get rid of them but some mode sense pages
560 may still need them */
561static int sdebug_heads; /* heads per disk */
562static int sdebug_cylinders_per; /* cylinders per surface */
563static int sdebug_sectors_per; /* sectors per cylinder */
564
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565#define SDEBUG_MAX_PARTS 4
566
Martin K. Petersen395cef02009-09-18 17:33:03 -0400567#define SCSI_DEBUG_MAX_CMD_LEN 32
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +0900568
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500569static unsigned int scsi_debug_lbp(void)
570{
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400571 return ((0 == scsi_debug_fake_rw) &&
572 (scsi_debug_lbpu | scsi_debug_lbpws | scsi_debug_lbpws10));
Martin K. Petersen5b94e232011-03-08 02:08:11 -0500573}
574
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575struct sdebug_dev_info {
576 struct list_head dev_list;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577 unsigned int channel;
578 unsigned int target;
Hannes Reinecke9cb78c12014-06-25 15:27:36 +0200579 u64 lun;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580 struct sdebug_host_info *sdbg_host;
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400581 unsigned long uas_bm[1];
582 atomic_t num_in_q;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -0500583 char stopped; /* TODO: should be atomic */
584 bool used;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585};
586
587struct sdebug_host_info {
588 struct list_head host_list;
589 struct Scsi_Host *shost;
590 struct device dev;
591 struct list_head dev_info_list;
592};
593
594#define to_sdebug_host(d) \
595 container_of(d, struct sdebug_host_info, dev)
596
597static LIST_HEAD(sdebug_host_list);
598static DEFINE_SPINLOCK(sdebug_host_list_lock);
599
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400600
601struct sdebug_hrtimer { /* ... is derived from hrtimer */
602 struct hrtimer hrt; /* must be first element */
603 int qa_indx;
604};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605
606struct sdebug_queued_cmd {
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400607 /* in_use flagged by a bit in queued_in_use_bm[] */
608 struct timer_list *cmnd_timerp;
609 struct tasklet_struct *tletp;
610 struct sdebug_hrtimer *sd_hrtp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611 struct scsi_cmnd * a_cmnd;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612};
613static struct sdebug_queued_cmd queued_arr[SCSI_DEBUG_CANQUEUE];
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400614static unsigned long queued_in_use_bm[SCSI_DEBUG_CANQUEUE_WORDS];
615
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617static unsigned char * fake_storep; /* ramdisk storage */
Akinobu Mitae18d8be2013-06-29 17:59:18 +0900618static struct sd_dif_tuple *dif_storep; /* protection info */
Martin K. Petersen44d92692009-10-15 14:45:27 -0400619static void *map_storep; /* provisioning map */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620
Martin K. Petersen44d92692009-10-15 14:45:27 -0400621static unsigned long map_size;
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400622static int num_aborts;
623static int num_dev_resets;
624static int num_target_resets;
625static int num_bus_resets;
626static int num_host_resets;
Martin K. Petersenc6a44282009-01-04 03:08:19 -0500627static int dix_writes;
628static int dix_reads;
629static int dif_errors;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630
631static DEFINE_SPINLOCK(queued_arr_lock);
632static DEFINE_RWLOCK(atomic_rw);
633
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400634static char sdebug_proc_name[] = MY_NAME;
635static const char *my_name = MY_NAME;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637static struct bus_type pseudo_lld_bus;
638
639static struct device_driver sdebug_driverfs_driver = {
640 .name = sdebug_proc_name,
641 .bus = &pseudo_lld_bus,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642};
643
644static const int check_condition_result =
645 (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
646
Martin K. Petersenc6a44282009-01-04 03:08:19 -0500647static const int illegal_condition_result =
648 (DRIVER_SENSE << 24) | (DID_ABORT << 16) | SAM_STAT_CHECK_CONDITION;
649
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400650static const int device_qfull_result =
651 (DID_OK << 16) | (COMMAND_COMPLETE << 8) | SAM_STAT_TASK_SET_FULL;
652
653static unsigned char caching_pg[] = {0x8, 18, 0x14, 0, 0xff, 0xff, 0, 0,
654 0xff, 0xff, 0xff, 0xff, 0x80, 0x14, 0, 0,
655 0, 0, 0, 0};
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400656static unsigned char ctrl_m_pg[] = {0xa, 10, 2, 0, 0, 0, 0, 0,
657 0, 0, 0x2, 0x4b};
658static unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0,
659 0, 0, 0x0, 0x0};
660
Akinobu Mita14faa942013-09-18 21:27:24 +0900661static void *fake_store(unsigned long long lba)
662{
663 lba = do_div(lba, sdebug_store_sectors);
664
665 return fake_storep + lba * scsi_debug_sector_size;
666}
667
668static struct sd_dif_tuple *dif_store(sector_t sector)
669{
670 sector = do_div(sector, sdebug_store_sectors);
671
672 return dif_storep + sector;
673}
674
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675static int sdebug_add_adapter(void);
676static void sdebug_remove_adapter(void);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +0900678static void sdebug_max_tgts_luns(void)
679{
680 struct sdebug_host_info *sdbg_host;
681 struct Scsi_Host *hpnt;
682
683 spin_lock(&sdebug_host_list_lock);
684 list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) {
685 hpnt = sdbg_host->shost;
686 if ((hpnt->this_id >= 0) &&
687 (scsi_debug_num_tgts > hpnt->this_id))
688 hpnt->max_id = scsi_debug_num_tgts + 1;
689 else
690 hpnt->max_id = scsi_debug_num_tgts;
691 /* scsi_debug_max_luns; */
692 hpnt->max_lun = SAM2_WLUN_REPORT_LUNS;
693 }
694 spin_unlock(&sdebug_host_list_lock);
695}
696
Douglas Gilbert22017ed2014-11-24 23:04:47 -0500697enum sdeb_cmd_data {SDEB_IN_DATA = 0, SDEB_IN_CDB = 1};
698
699/* Set in_bit to -1 to indicate no bit position of invalid field */
700static void
701mk_sense_invalid_fld(struct scsi_cmnd *scp, enum sdeb_cmd_data c_d,
702 int in_byte, int in_bit)
703{
704 unsigned char *sbuff;
705 u8 sks[4];
706 int sl, asc;
707
708 sbuff = scp->sense_buffer;
709 if (!sbuff) {
710 sdev_printk(KERN_ERR, scp->device,
711 "%s: sense_buffer is NULL\n", __func__);
712 return;
713 }
714 asc = c_d ? INVALID_FIELD_IN_CDB : INVALID_FIELD_IN_PARAM_LIST;
715 memset(sbuff, 0, SCSI_SENSE_BUFFERSIZE);
716 scsi_build_sense_buffer(scsi_debug_dsense, sbuff, ILLEGAL_REQUEST,
717 asc, 0);
718 memset(sks, 0, sizeof(sks));
719 sks[0] = 0x80;
720 if (c_d)
721 sks[0] |= 0x40;
722 if (in_bit >= 0) {
723 sks[0] |= 0x8;
724 sks[0] |= 0x7 & in_bit;
725 }
726 put_unaligned_be16(in_byte, sks + 1);
727 if (scsi_debug_dsense) {
728 sl = sbuff[7] + 8;
729 sbuff[7] = sl;
730 sbuff[sl] = 0x2;
731 sbuff[sl + 1] = 0x6;
732 memcpy(sbuff + sl + 4, sks, 3);
733 } else
734 memcpy(sbuff + 15, sks, 3);
735 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
736 sdev_printk(KERN_INFO, scp->device, "%s: [sense_key,asc,ascq"
737 "]: [0x5,0x%x,0x0] %c byte=%d, bit=%d\n",
738 my_name, asc, c_d ? 'C' : 'D', in_byte, in_bit);
739}
740
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400741static void mk_sense_buffer(struct scsi_cmnd *scp, int key, int asc, int asq)
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +0900742{
743 unsigned char *sbuff;
744
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400745 sbuff = scp->sense_buffer;
746 if (!sbuff) {
747 sdev_printk(KERN_ERR, scp->device,
748 "%s: sense_buffer is NULL\n", __func__);
749 return;
750 }
751 memset(sbuff, 0, SCSI_SENSE_BUFFERSIZE);
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +0900752
753 scsi_build_sense_buffer(scsi_debug_dsense, sbuff, key, asc, asq);
754
755 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400756 sdev_printk(KERN_INFO, scp->device,
757 "%s: [sense_key,asc,ascq]: [0x%x,0x%x,0x%x]\n",
758 my_name, key, asc, asq);
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +0900759}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760
Douglas Gilbert22017ed2014-11-24 23:04:47 -0500761static void
762mk_sense_invalid_opcode(struct scsi_cmnd *scp)
763{
764 mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_OPCODE, 0);
765}
766
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767static int scsi_debug_ioctl(struct scsi_device *dev, int cmd, void __user *arg)
768{
769 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400770 if (0x1261 == cmd)
771 sdev_printk(KERN_INFO, dev,
772 "%s: BLKFLSBUF [0x1261]\n", __func__);
773 else if (0x5331 == cmd)
774 sdev_printk(KERN_INFO, dev,
775 "%s: CDROM_GET_CAPABILITY [0x5331]\n",
776 __func__);
777 else
778 sdev_printk(KERN_INFO, dev, "%s: cmd=0x%x\n",
779 __func__, cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780 }
781 return -EINVAL;
782 /* return -ENOTTY; // correct return but upsets fdisk */
783}
784
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400785static int check_readiness(struct scsi_cmnd *SCpnt, int uas_only,
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400786 struct sdebug_dev_info * devip)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787{
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400788 int k;
789 bool debug = !!(SCSI_DEBUG_OPT_NOISE & scsi_debug_opts);
790
791 k = find_first_bit(devip->uas_bm, SDEBUG_NUM_UAS);
792 if (k != SDEBUG_NUM_UAS) {
793 const char *cp = NULL;
794
795 switch (k) {
796 case SDEBUG_UA_POR:
797 mk_sense_buffer(SCpnt, UNIT_ATTENTION,
798 UA_RESET_ASC, POWER_ON_RESET_ASCQ);
799 if (debug)
800 cp = "power on reset";
801 break;
802 case SDEBUG_UA_BUS_RESET:
803 mk_sense_buffer(SCpnt, UNIT_ATTENTION,
804 UA_RESET_ASC, BUS_RESET_ASCQ);
805 if (debug)
806 cp = "bus reset";
807 break;
808 case SDEBUG_UA_MODE_CHANGED:
809 mk_sense_buffer(SCpnt, UNIT_ATTENTION,
810 UA_CHANGED_ASC, MODE_CHANGED_ASCQ);
811 if (debug)
812 cp = "mode parameters changed";
813 break;
Douglas Gilbert0d01c5d2014-11-24 20:27:51 -0500814 case SDEBUG_UA_CAPACITY_CHANGED:
815 mk_sense_buffer(SCpnt, UNIT_ATTENTION,
816 UA_CHANGED_ASC, CAPACITY_CHANGED_ASCQ);
817 if (debug)
818 cp = "capacity data changed";
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400819 default:
820 pr_warn("%s: unexpected unit attention code=%d\n",
821 __func__, k);
822 if (debug)
823 cp = "unknown";
824 break;
825 }
826 clear_bit(k, devip->uas_bm);
827 if (debug)
828 sdev_printk(KERN_INFO, SCpnt->device,
829 "%s reports: Unit attention: %s\n",
830 my_name, cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831 return check_condition_result;
832 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400833 if ((UAS_TUR == uas_only) && devip->stopped) {
834 mk_sense_buffer(SCpnt, NOT_READY, LOGICAL_UNIT_NOT_READY,
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400835 0x2);
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400836 if (debug)
837 sdev_printk(KERN_INFO, SCpnt->device,
838 "%s reports: Not ready: %s\n", my_name,
839 "initializing command required");
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400840 return check_condition_result;
841 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842 return 0;
843}
844
845/* Returns 0 if ok else (DID_ERROR << 16). Sets scp->resid . */
FUJITA Tomonori21a61822008-03-09 13:44:30 +0900846static int fill_from_dev_buffer(struct scsi_cmnd *scp, unsigned char *arr,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847 int arr_len)
848{
FUJITA Tomonori21a61822008-03-09 13:44:30 +0900849 int act_len;
FUJITA Tomonori072d0bb2008-01-23 01:32:00 +0900850 struct scsi_data_buffer *sdb = scsi_in(scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851
FUJITA Tomonori072d0bb2008-01-23 01:32:00 +0900852 if (!sdb->length)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853 return 0;
FUJITA Tomonori072d0bb2008-01-23 01:32:00 +0900854 if (!(scsi_bidi_cmnd(scp) || scp->sc_data_direction == DMA_FROM_DEVICE))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855 return (DID_ERROR << 16);
FUJITA Tomonori21a61822008-03-09 13:44:30 +0900856
857 act_len = sg_copy_from_buffer(sdb->table.sgl, sdb->table.nents,
858 arr, arr_len);
Akinobu Mitaa4517512013-07-08 16:01:57 -0700859 sdb->resid = scsi_bufflen(scp) - act_len;
FUJITA Tomonori21a61822008-03-09 13:44:30 +0900860
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861 return 0;
862}
863
864/* Returns number of bytes fetched into 'arr' or -1 if error. */
FUJITA Tomonori21a61822008-03-09 13:44:30 +0900865static int fetch_to_dev_buffer(struct scsi_cmnd *scp, unsigned char *arr,
866 int arr_len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867{
FUJITA Tomonori21a61822008-03-09 13:44:30 +0900868 if (!scsi_bufflen(scp))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869 return 0;
FUJITA Tomonori072d0bb2008-01-23 01:32:00 +0900870 if (!(scsi_bidi_cmnd(scp) || scp->sc_data_direction == DMA_TO_DEVICE))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871 return -1;
FUJITA Tomonori21a61822008-03-09 13:44:30 +0900872
873 return scsi_sg_copy_to_buffer(scp, arr, arr_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874}
875
876
877static const char * inq_vendor_id = "Linux ";
878static const char * inq_product_id = "scsi_debug ";
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400879static const char *inq_product_rev = "0184"; /* version less '.' */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400881/* Device identification VPD page. Returns number of bytes placed in arr */
Hannes Reinecke5a09e392006-10-20 09:58:47 +0200882static int inquiry_evpd_83(unsigned char * arr, int port_group_id,
883 int target_dev_id, int dev_id_num,
884 const char * dev_id_str,
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400885 int dev_id_str_len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886{
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400887 int num, port_a;
888 char b[32];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400890 port_a = target_dev_id + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891 /* T10 vendor identifier field format (faked) */
892 arr[0] = 0x2; /* ASCII */
893 arr[1] = 0x1;
894 arr[2] = 0x0;
895 memcpy(&arr[4], inq_vendor_id, 8);
896 memcpy(&arr[12], inq_product_id, 16);
897 memcpy(&arr[28], dev_id_str, dev_id_str_len);
898 num = 8 + 16 + dev_id_str_len;
899 arr[3] = num;
900 num += 4;
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400901 if (dev_id_num >= 0) {
902 /* NAA-5, Logical unit identifier (binary) */
903 arr[num++] = 0x1; /* binary (not necessarily sas) */
904 arr[num++] = 0x3; /* PIV=0, lu, naa */
905 arr[num++] = 0x0;
906 arr[num++] = 0x8;
907 arr[num++] = 0x53; /* naa-5 ieee company id=0x333333 (fake) */
908 arr[num++] = 0x33;
909 arr[num++] = 0x33;
910 arr[num++] = 0x30;
911 arr[num++] = (dev_id_num >> 24);
912 arr[num++] = (dev_id_num >> 16) & 0xff;
913 arr[num++] = (dev_id_num >> 8) & 0xff;
914 arr[num++] = dev_id_num & 0xff;
915 /* Target relative port number */
916 arr[num++] = 0x61; /* proto=sas, binary */
917 arr[num++] = 0x94; /* PIV=1, target port, rel port */
918 arr[num++] = 0x0; /* reserved */
919 arr[num++] = 0x4; /* length */
920 arr[num++] = 0x0; /* reserved */
921 arr[num++] = 0x0; /* reserved */
922 arr[num++] = 0x0;
923 arr[num++] = 0x1; /* relative port A */
924 }
925 /* NAA-5, Target port identifier */
926 arr[num++] = 0x61; /* proto=sas, binary */
927 arr[num++] = 0x93; /* piv=1, target port, naa */
928 arr[num++] = 0x0;
929 arr[num++] = 0x8;
930 arr[num++] = 0x52; /* naa-5, company id=0x222222 (fake) */
931 arr[num++] = 0x22;
932 arr[num++] = 0x22;
933 arr[num++] = 0x20;
934 arr[num++] = (port_a >> 24);
935 arr[num++] = (port_a >> 16) & 0xff;
936 arr[num++] = (port_a >> 8) & 0xff;
937 arr[num++] = port_a & 0xff;
Hannes Reinecke5a09e392006-10-20 09:58:47 +0200938 /* NAA-5, Target port group identifier */
939 arr[num++] = 0x61; /* proto=sas, binary */
940 arr[num++] = 0x95; /* piv=1, target port group id */
941 arr[num++] = 0x0;
942 arr[num++] = 0x4;
943 arr[num++] = 0;
944 arr[num++] = 0;
945 arr[num++] = (port_group_id >> 8) & 0xff;
946 arr[num++] = port_group_id & 0xff;
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400947 /* NAA-5, Target device identifier */
948 arr[num++] = 0x61; /* proto=sas, binary */
949 arr[num++] = 0xa3; /* piv=1, target device, naa */
950 arr[num++] = 0x0;
951 arr[num++] = 0x8;
952 arr[num++] = 0x52; /* naa-5, company id=0x222222 (fake) */
953 arr[num++] = 0x22;
954 arr[num++] = 0x22;
955 arr[num++] = 0x20;
956 arr[num++] = (target_dev_id >> 24);
957 arr[num++] = (target_dev_id >> 16) & 0xff;
958 arr[num++] = (target_dev_id >> 8) & 0xff;
959 arr[num++] = target_dev_id & 0xff;
960 /* SCSI name string: Target device identifier */
961 arr[num++] = 0x63; /* proto=sas, UTF-8 */
962 arr[num++] = 0xa8; /* piv=1, target device, SCSI name string */
963 arr[num++] = 0x0;
964 arr[num++] = 24;
965 memcpy(arr + num, "naa.52222220", 12);
966 num += 12;
967 snprintf(b, sizeof(b), "%08X", target_dev_id);
968 memcpy(arr + num, b, 8);
969 num += 8;
970 memset(arr + num, 0, 4);
971 num += 4;
972 return num;
973}
974
975
976static unsigned char vpd84_data[] = {
977/* from 4th byte */ 0x22,0x22,0x22,0x0,0xbb,0x0,
978 0x22,0x22,0x22,0x0,0xbb,0x1,
979 0x22,0x22,0x22,0x0,0xbb,0x2,
980};
981
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400982/* Software interface identification VPD page */
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400983static int inquiry_evpd_84(unsigned char * arr)
984{
985 memcpy(arr, vpd84_data, sizeof(vpd84_data));
986 return sizeof(vpd84_data);
987}
988
Douglas Gilbertcbf67842014-07-26 11:55:35 -0400989/* Management network addresses VPD page */
Douglas Gilbertc65b1442006-06-06 00:11:24 -0400990static int inquiry_evpd_85(unsigned char * arr)
991{
992 int num = 0;
993 const char * na1 = "https://www.kernel.org/config";
994 const char * na2 = "http://www.kernel.org/log";
995 int plen, olen;
996
997 arr[num++] = 0x1; /* lu, storage config */
998 arr[num++] = 0x0; /* reserved */
999 arr[num++] = 0x0;
1000 olen = strlen(na1);
1001 plen = olen + 1;
1002 if (plen % 4)
1003 plen = ((plen / 4) + 1) * 4;
1004 arr[num++] = plen; /* length, null termianted, padded */
1005 memcpy(arr + num, na1, olen);
1006 memset(arr + num + olen, 0, plen - olen);
1007 num += plen;
1008
1009 arr[num++] = 0x4; /* lu, logging */
1010 arr[num++] = 0x0; /* reserved */
1011 arr[num++] = 0x0;
1012 olen = strlen(na2);
1013 plen = olen + 1;
1014 if (plen % 4)
1015 plen = ((plen / 4) + 1) * 4;
1016 arr[num++] = plen; /* length, null terminated, padded */
1017 memcpy(arr + num, na2, olen);
1018 memset(arr + num + olen, 0, plen - olen);
1019 num += plen;
1020
1021 return num;
1022}
1023
1024/* SCSI ports VPD page */
1025static int inquiry_evpd_88(unsigned char * arr, int target_dev_id)
1026{
1027 int num = 0;
1028 int port_a, port_b;
1029
1030 port_a = target_dev_id + 1;
1031 port_b = port_a + 1;
1032 arr[num++] = 0x0; /* reserved */
1033 arr[num++] = 0x0; /* reserved */
1034 arr[num++] = 0x0;
1035 arr[num++] = 0x1; /* relative port 1 (primary) */
1036 memset(arr + num, 0, 6);
1037 num += 6;
1038 arr[num++] = 0x0;
1039 arr[num++] = 12; /* length tp descriptor */
1040 /* naa-5 target port identifier (A) */
1041 arr[num++] = 0x61; /* proto=sas, binary */
1042 arr[num++] = 0x93; /* PIV=1, target port, NAA */
1043 arr[num++] = 0x0; /* reserved */
1044 arr[num++] = 0x8; /* length */
1045 arr[num++] = 0x52; /* NAA-5, company_id=0x222222 (fake) */
1046 arr[num++] = 0x22;
1047 arr[num++] = 0x22;
1048 arr[num++] = 0x20;
1049 arr[num++] = (port_a >> 24);
1050 arr[num++] = (port_a >> 16) & 0xff;
1051 arr[num++] = (port_a >> 8) & 0xff;
1052 arr[num++] = port_a & 0xff;
1053
1054 arr[num++] = 0x0; /* reserved */
1055 arr[num++] = 0x0; /* reserved */
1056 arr[num++] = 0x0;
1057 arr[num++] = 0x2; /* relative port 2 (secondary) */
1058 memset(arr + num, 0, 6);
1059 num += 6;
1060 arr[num++] = 0x0;
1061 arr[num++] = 12; /* length tp descriptor */
1062 /* naa-5 target port identifier (B) */
1063 arr[num++] = 0x61; /* proto=sas, binary */
1064 arr[num++] = 0x93; /* PIV=1, target port, NAA */
1065 arr[num++] = 0x0; /* reserved */
1066 arr[num++] = 0x8; /* length */
1067 arr[num++] = 0x52; /* NAA-5, company_id=0x222222 (fake) */
1068 arr[num++] = 0x22;
1069 arr[num++] = 0x22;
1070 arr[num++] = 0x20;
1071 arr[num++] = (port_b >> 24);
1072 arr[num++] = (port_b >> 16) & 0xff;
1073 arr[num++] = (port_b >> 8) & 0xff;
1074 arr[num++] = port_b & 0xff;
1075
1076 return num;
1077}
1078
1079
1080static unsigned char vpd89_data[] = {
1081/* from 4th byte */ 0,0,0,0,
1082'l','i','n','u','x',' ',' ',' ',
1083'S','A','T',' ','s','c','s','i','_','d','e','b','u','g',' ',' ',
1084'1','2','3','4',
10850x34,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,
10860xec,0,0,0,
10870x5a,0xc,0xff,0x3f,0x37,0xc8,0x10,0,0,0,0,0,0x3f,0,0,0,
10880,0,0,0,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x20,0x20,0x20,0x20,
10890x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0,0,0,0x40,0x4,0,0x2e,0x33,
10900x38,0x31,0x20,0x20,0x20,0x20,0x54,0x53,0x38,0x33,0x30,0x30,0x33,0x31,
10910x53,0x41,
10920x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
10930x20,0x20,
10940x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
10950x10,0x80,
10960,0,0,0x2f,0,0,0,0x2,0,0x2,0x7,0,0xff,0xff,0x1,0,
10970x3f,0,0xc1,0xff,0x3e,0,0x10,0x1,0xb0,0xf8,0x50,0x9,0,0,0x7,0,
10980x3,0,0x78,0,0x78,0,0xf0,0,0x78,0,0,0,0,0,0,0,
10990,0,0,0,0,0,0,0,0x2,0,0,0,0,0,0,0,
11000x7e,0,0x1b,0,0x6b,0x34,0x1,0x7d,0x3,0x40,0x69,0x34,0x1,0x3c,0x3,0x40,
11010x7f,0x40,0,0,0,0,0xfe,0xfe,0,0,0,0,0,0xfe,0,0,
11020,0,0,0,0,0,0,0,0xb0,0xf8,0x50,0x9,0,0,0,0,
11030,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
11040,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
11050,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
11060x1,0,0xb0,0xf8,0x50,0x9,0xb0,0xf8,0x50,0x9,0x20,0x20,0x2,0,0xb6,0x42,
11070,0x80,0x8a,0,0x6,0x3c,0xa,0x3c,0xff,0xff,0xc6,0x7,0,0x1,0,0x8,
11080xf0,0xf,0,0x10,0x2,0,0x30,0,0,0,0,0,0,0,0x6,0xfe,
11090,0,0x2,0,0x50,0,0x8a,0,0x4f,0x95,0,0,0x21,0,0xb,0,
11100,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
11110,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
11120,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
11130,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
11140,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
11150,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
11160,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
11170,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
11180,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
11190,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
11200,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
11210,0,0,0,0,0,0,0,0,0,0,0,0,0,0xa5,0x51,
1122};
1123
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001124/* ATA Information VPD page */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001125static int inquiry_evpd_89(unsigned char * arr)
1126{
1127 memcpy(arr, vpd89_data, sizeof(vpd89_data));
1128 return sizeof(vpd89_data);
1129}
1130
1131
1132static unsigned char vpdb0_data[] = {
Douglas Gilbert1e49f782009-10-29 01:48:31 -04001133 /* from 4th byte */ 0,0,0,4, 0,0,0x4,0, 0,0,0,64,
1134 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1135 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1136 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001137};
1138
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001139/* Block limits VPD page (SBC-3) */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001140static int inquiry_evpd_b0(unsigned char * arr)
1141{
Martin K. Petersenea61fca2009-05-15 00:40:33 -04001142 unsigned int gran;
1143
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001144 memcpy(arr, vpdb0_data, sizeof(vpdb0_data));
Martin K. Petersene308b3d2010-03-23 01:12:27 -04001145
1146 /* Optimal transfer length granularity */
Martin K. Petersenea61fca2009-05-15 00:40:33 -04001147 gran = 1 << scsi_debug_physblk_exp;
1148 arr[2] = (gran >> 8) & 0xff;
1149 arr[3] = gran & 0xff;
Martin K. Petersene308b3d2010-03-23 01:12:27 -04001150
1151 /* Maximum Transfer Length */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001152 if (sdebug_store_sectors > 0x400) {
1153 arr[4] = (sdebug_store_sectors >> 24) & 0xff;
1154 arr[5] = (sdebug_store_sectors >> 16) & 0xff;
1155 arr[6] = (sdebug_store_sectors >> 8) & 0xff;
1156 arr[7] = sdebug_store_sectors & 0xff;
1157 }
Martin K. Petersen44d92692009-10-15 14:45:27 -04001158
Martin K. Petersene308b3d2010-03-23 01:12:27 -04001159 /* Optimal Transfer Length */
1160 put_unaligned_be32(scsi_debug_opt_blks, &arr[8]);
1161
Martin K. Petersen5b94e232011-03-08 02:08:11 -05001162 if (scsi_debug_lbpu) {
Martin K. Petersene308b3d2010-03-23 01:12:27 -04001163 /* Maximum Unmap LBA Count */
Martin K. Petersen60147592010-08-19 11:49:00 -04001164 put_unaligned_be32(scsi_debug_unmap_max_blocks, &arr[16]);
Martin K. Petersene308b3d2010-03-23 01:12:27 -04001165
1166 /* Maximum Unmap Block Descriptor Count */
Martin K. Petersen44d92692009-10-15 14:45:27 -04001167 put_unaligned_be32(scsi_debug_unmap_max_desc, &arr[20]);
1168 }
1169
Martin K. Petersene308b3d2010-03-23 01:12:27 -04001170 /* Unmap Granularity Alignment */
Martin K. Petersen44d92692009-10-15 14:45:27 -04001171 if (scsi_debug_unmap_alignment) {
1172 put_unaligned_be32(scsi_debug_unmap_alignment, &arr[28]);
1173 arr[28] |= 0x80; /* UGAVALID */
1174 }
1175
Martin K. Petersene308b3d2010-03-23 01:12:27 -04001176 /* Optimal Unmap Granularity */
Martin K. Petersen60147592010-08-19 11:49:00 -04001177 put_unaligned_be32(scsi_debug_unmap_granularity, &arr[24]);
1178
Martin K. Petersen5b94e232011-03-08 02:08:11 -05001179 /* Maximum WRITE SAME Length */
1180 put_unaligned_be64(scsi_debug_write_same_length, &arr[32]);
1181
1182 return 0x3c; /* Mandatory page length for Logical Block Provisioning */
Martin K. Petersen44d92692009-10-15 14:45:27 -04001183
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001184 return sizeof(vpdb0_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001185}
1186
Douglas Gilbert1e49f782009-10-29 01:48:31 -04001187/* Block device characteristics VPD page (SBC-3) */
Matthew Wilcoxeac6e8e42008-06-19 10:02:58 -06001188static int inquiry_evpd_b1(unsigned char *arr)
1189{
1190 memset(arr, 0, 0x3c);
1191 arr[0] = 0;
Douglas Gilbert1e49f782009-10-29 01:48:31 -04001192 arr[1] = 1; /* non rotating medium (e.g. solid state) */
1193 arr[2] = 0;
1194 arr[3] = 5; /* less than 1.8" */
Matthew Wilcoxeac6e8e42008-06-19 10:02:58 -06001195
1196 return 0x3c;
1197}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198
Eric Sandeenbe1dd782012-03-08 00:03:59 -06001199/* Logical block provisioning VPD page (SBC-3) */
Martin K. Petersen60147592010-08-19 11:49:00 -04001200static int inquiry_evpd_b2(unsigned char *arr)
1201{
Martin K. Petersen3f0bc3b2012-03-08 10:48:29 -05001202 memset(arr, 0, 0x4);
Martin K. Petersen60147592010-08-19 11:49:00 -04001203 arr[0] = 0; /* threshold exponent */
1204
Martin K. Petersen5b94e232011-03-08 02:08:11 -05001205 if (scsi_debug_lbpu)
Martin K. Petersen60147592010-08-19 11:49:00 -04001206 arr[1] = 1 << 7;
1207
Martin K. Petersen5b94e232011-03-08 02:08:11 -05001208 if (scsi_debug_lbpws)
Martin K. Petersen60147592010-08-19 11:49:00 -04001209 arr[1] |= 1 << 6;
1210
Martin K. Petersen5b94e232011-03-08 02:08:11 -05001211 if (scsi_debug_lbpws10)
1212 arr[1] |= 1 << 5;
1213
Eric Sandeenbe1dd782012-03-08 00:03:59 -06001214 if (scsi_debug_lbprz)
1215 arr[1] |= 1 << 2;
1216
Martin K. Petersen3f0bc3b2012-03-08 10:48:29 -05001217 return 0x4;
Martin K. Petersen60147592010-08-19 11:49:00 -04001218}
1219
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220#define SDEBUG_LONG_INQ_SZ 96
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001221#define SDEBUG_MAX_INQ_ARR_SZ 584
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001223static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224{
1225 unsigned char pq_pdt;
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001226 unsigned char * arr;
Douglas Gilbert01123ef2014-08-05 12:20:02 +02001227 unsigned char *cmd = scp->cmnd;
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001228 int alloc_len, n, ret;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001229 bool have_wlun;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230
1231 alloc_len = (cmd[3] << 8) + cmd[4];
Douglas Gilbert6f3cbf52007-01-05 00:05:25 -05001232 arr = kzalloc(SDEBUG_MAX_INQ_ARR_SZ, GFP_ATOMIC);
1233 if (! arr)
1234 return DID_REQUEUE << 16;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001235 have_wlun = (scp->device->lun == SAM2_WLUN_REPORT_LUNS);
1236 if (have_wlun)
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001237 pq_pdt = 0x1e; /* present, wlun */
1238 else if (scsi_debug_no_lun_0 && (0 == devip->lun))
1239 pq_pdt = 0x7f; /* not present, no device type */
1240 else
1241 pq_pdt = (scsi_debug_ptype & 0x1f);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242 arr[0] = pq_pdt;
1243 if (0x2 & cmd[1]) { /* CMDDT bit set */
Douglas Gilbert22017ed2014-11-24 23:04:47 -05001244 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 1, 1);
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001245 kfree(arr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001246 return check_condition_result;
1247 } else if (0x1 & cmd[1]) { /* EVPD bit set */
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001248 int lu_id_num, port_group_id, target_dev_id, len;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001249 char lu_id_str[6];
1250 int host_no = devip->sdbg_host->shost->host_no;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001252 port_group_id = (((host_no + 1) & 0x7f) << 8) +
1253 (devip->channel & 0x7f);
Douglas Gilbert23183912006-09-16 20:30:47 -04001254 if (0 == scsi_debug_vpd_use_hostno)
1255 host_no = 0;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001256 lu_id_num = have_wlun ? -1 : (((host_no + 1) * 2000) +
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001257 (devip->target * 1000) + devip->lun);
1258 target_dev_id = ((host_no + 1) * 2000) +
1259 (devip->target * 1000) - 3;
1260 len = scnprintf(lu_id_str, 6, "%d", lu_id_num);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261 if (0 == cmd[2]) { /* supported vital product data pages */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001262 arr[1] = cmd[2]; /*sanity */
1263 n = 4;
1264 arr[n++] = 0x0; /* this page */
1265 arr[n++] = 0x80; /* unit serial number */
1266 arr[n++] = 0x83; /* device identification */
1267 arr[n++] = 0x84; /* software interface ident. */
1268 arr[n++] = 0x85; /* management network addresses */
1269 arr[n++] = 0x86; /* extended inquiry */
1270 arr[n++] = 0x87; /* mode page policy */
1271 arr[n++] = 0x88; /* SCSI ports */
1272 arr[n++] = 0x89; /* ATA information */
1273 arr[n++] = 0xb0; /* Block limits (SBC) */
Matthew Wilcoxeac6e8e42008-06-19 10:02:58 -06001274 arr[n++] = 0xb1; /* Block characteristics (SBC) */
Martin K. Petersen5b94e232011-03-08 02:08:11 -05001275 if (scsi_debug_lbp()) /* Logical Block Prov. (SBC) */
1276 arr[n++] = 0xb2;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001277 arr[3] = n - 4; /* number of supported VPD pages */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278 } else if (0x80 == cmd[2]) { /* unit serial number */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001279 arr[1] = cmd[2]; /*sanity */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280 arr[3] = len;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001281 memcpy(&arr[4], lu_id_str, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282 } else if (0x83 == cmd[2]) { /* device identification */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001283 arr[1] = cmd[2]; /*sanity */
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001284 arr[3] = inquiry_evpd_83(&arr[4], port_group_id,
1285 target_dev_id, lu_id_num,
1286 lu_id_str, len);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001287 } else if (0x84 == cmd[2]) { /* Software interface ident. */
1288 arr[1] = cmd[2]; /*sanity */
1289 arr[3] = inquiry_evpd_84(&arr[4]);
1290 } else if (0x85 == cmd[2]) { /* Management network addresses */
1291 arr[1] = cmd[2]; /*sanity */
1292 arr[3] = inquiry_evpd_85(&arr[4]);
1293 } else if (0x86 == cmd[2]) { /* extended inquiry */
1294 arr[1] = cmd[2]; /*sanity */
1295 arr[3] = 0x3c; /* number of following entries */
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001296 if (scsi_debug_dif == SD_DIF_TYPE3_PROTECTION)
1297 arr[4] = 0x4; /* SPT: GRD_CHK:1 */
1298 else if (scsi_debug_dif)
1299 arr[4] = 0x5; /* SPT: GRD_CHK:1, REF_CHK:1 */
1300 else
1301 arr[4] = 0x0; /* no protection stuff */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001302 arr[5] = 0x7; /* head of q, ordered + simple q's */
1303 } else if (0x87 == cmd[2]) { /* mode page policy */
1304 arr[1] = cmd[2]; /*sanity */
1305 arr[3] = 0x8; /* number of following entries */
1306 arr[4] = 0x2; /* disconnect-reconnect mp */
1307 arr[6] = 0x80; /* mlus, shared */
1308 arr[8] = 0x18; /* protocol specific lu */
1309 arr[10] = 0x82; /* mlus, per initiator port */
1310 } else if (0x88 == cmd[2]) { /* SCSI Ports */
1311 arr[1] = cmd[2]; /*sanity */
1312 arr[3] = inquiry_evpd_88(&arr[4], target_dev_id);
1313 } else if (0x89 == cmd[2]) { /* ATA information */
1314 arr[1] = cmd[2]; /*sanity */
1315 n = inquiry_evpd_89(&arr[4]);
1316 arr[2] = (n >> 8);
1317 arr[3] = (n & 0xff);
1318 } else if (0xb0 == cmd[2]) { /* Block limits (SBC) */
1319 arr[1] = cmd[2]; /*sanity */
1320 arr[3] = inquiry_evpd_b0(&arr[4]);
Matthew Wilcoxeac6e8e42008-06-19 10:02:58 -06001321 } else if (0xb1 == cmd[2]) { /* Block characteristics (SBC) */
1322 arr[1] = cmd[2]; /*sanity */
1323 arr[3] = inquiry_evpd_b1(&arr[4]);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05001324 } else if (0xb2 == cmd[2]) { /* Logical Block Prov. (SBC) */
Martin K. Petersen60147592010-08-19 11:49:00 -04001325 arr[1] = cmd[2]; /*sanity */
1326 arr[3] = inquiry_evpd_b2(&arr[4]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327 } else {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05001328 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, -1);
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001329 kfree(arr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330 return check_condition_result;
1331 }
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001332 len = min(((arr[2] << 8) + arr[3]) + 4, alloc_len);
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001333 ret = fill_from_dev_buffer(scp, arr,
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001334 min(len, SDEBUG_MAX_INQ_ARR_SZ));
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001335 kfree(arr);
1336 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001337 }
1338 /* drops through here for a standard inquiry */
Martin Pittd9867882012-09-06 12:04:33 +02001339 arr[1] = scsi_debug_removable ? 0x80 : 0; /* Removable disk */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340 arr[2] = scsi_debug_scsi_level;
1341 arr[3] = 2; /* response_data_format==2 */
1342 arr[4] = SDEBUG_LONG_INQ_SZ - 5;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001343 arr[5] = scsi_debug_dif ? 1 : 0; /* PROTECT bit */
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001344 if (0 == scsi_debug_vpd_use_hostno)
1345 arr[5] = 0x10; /* claim: implicit TGPS */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001346 arr[6] = 0x10; /* claim: MultiP */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347 /* arr[6] |= 0x40; ... claim: EncServ (enclosure services) */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001348 arr[7] = 0xa; /* claim: LINKED + CMDQUE */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349 memcpy(&arr[8], inq_vendor_id, 8);
1350 memcpy(&arr[16], inq_product_id, 16);
1351 memcpy(&arr[32], inq_product_rev, 4);
1352 /* version descriptors (2 bytes each) follow */
Douglas Gilberte46b0342014-08-05 12:21:53 +02001353 arr[58] = 0x0; arr[59] = 0xa2; /* SAM-5 rev 4 */
1354 arr[60] = 0x4; arr[61] = 0x68; /* SPC-4 rev 37 */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001355 n = 62;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356 if (scsi_debug_ptype == 0) {
Douglas Gilberte46b0342014-08-05 12:21:53 +02001357 arr[n++] = 0x4; arr[n++] = 0xc5; /* SBC-4 rev 36 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358 } else if (scsi_debug_ptype == 1) {
Douglas Gilberte46b0342014-08-05 12:21:53 +02001359 arr[n++] = 0x5; arr[n++] = 0x25; /* SSC-4 rev 3 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360 }
Douglas Gilberte46b0342014-08-05 12:21:53 +02001361 arr[n++] = 0x20; arr[n++] = 0xe6; /* SPL-3 rev 7 */
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001362 ret = fill_from_dev_buffer(scp, arr,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363 min(alloc_len, SDEBUG_LONG_INQ_SZ));
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001364 kfree(arr);
1365 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366}
1367
1368static int resp_requests(struct scsi_cmnd * scp,
1369 struct sdebug_dev_info * devip)
1370{
1371 unsigned char * sbuff;
Douglas Gilbert01123ef2014-08-05 12:20:02 +02001372 unsigned char *cmd = scp->cmnd;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001373 unsigned char arr[SCSI_SENSE_BUFFERSIZE];
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001374 bool dsense, want_dsense;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375 int len = 18;
1376
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001377 memset(arr, 0, sizeof(arr));
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001378 dsense = !!(cmd[1] & 1);
1379 want_dsense = dsense || scsi_debug_dsense;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001380 sbuff = scp->sense_buffer;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001381 if ((iec_m_pg[2] & 0x4) && (6 == (iec_m_pg[3] & 0xf))) {
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001382 if (dsense) {
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001383 arr[0] = 0x72;
1384 arr[1] = 0x0; /* NO_SENSE in sense_key */
1385 arr[2] = THRESHOLD_EXCEEDED;
1386 arr[3] = 0xff; /* TEST set and MRIE==6 */
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001387 len = 8;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001388 } else {
1389 arr[0] = 0x70;
1390 arr[2] = 0x0; /* NO_SENSE in sense_key */
1391 arr[7] = 0xa; /* 18 byte sense buffer */
1392 arr[12] = THRESHOLD_EXCEEDED;
1393 arr[13] = 0xff; /* TEST set and MRIE==6 */
1394 }
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001395 } else {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001396 memcpy(arr, sbuff, SCSI_SENSE_BUFFERSIZE);
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001397 if (arr[0] >= 0x70 && dsense == scsi_debug_dsense)
1398 ; /* have sense and formats match */
1399 else if (arr[0] <= 0x70) {
1400 if (dsense) {
1401 memset(arr, 0, 8);
1402 arr[0] = 0x72;
1403 len = 8;
1404 } else {
1405 memset(arr, 0, 18);
1406 arr[0] = 0x70;
1407 arr[7] = 0xa;
1408 }
1409 } else if (dsense) {
1410 memset(arr, 0, 8);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001411 arr[0] = 0x72;
1412 arr[1] = sbuff[2]; /* sense key */
1413 arr[2] = sbuff[12]; /* asc */
1414 arr[3] = sbuff[13]; /* ascq */
1415 len = 8;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001416 } else {
1417 memset(arr, 0, 18);
1418 arr[0] = 0x70;
1419 arr[2] = sbuff[1];
1420 arr[7] = 0xa;
1421 arr[12] = sbuff[1];
1422 arr[13] = sbuff[3];
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001423 }
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001424
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001425 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001426 mk_sense_buffer(scp, 0, NO_ADDITIONAL_SENSE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001427 return fill_from_dev_buffer(scp, arr, len);
1428}
1429
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001430static int resp_start_stop(struct scsi_cmnd * scp,
1431 struct sdebug_dev_info * devip)
1432{
Douglas Gilbert01123ef2014-08-05 12:20:02 +02001433 unsigned char *cmd = scp->cmnd;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001434 int power_cond, start;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001435
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001436 power_cond = (cmd[4] & 0xf0) >> 4;
1437 if (power_cond) {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05001438 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 4, 7);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001439 return check_condition_result;
1440 }
1441 start = cmd[4] & 1;
1442 if (start == devip->stopped)
1443 devip->stopped = !start;
1444 return 0;
1445}
1446
FUJITA Tomonori28898872008-03-30 00:59:55 +09001447static sector_t get_sdebug_capacity(void)
1448{
1449 if (scsi_debug_virtual_gb > 0)
Douglas Gilbert5447ed62010-04-25 12:30:23 +02001450 return (sector_t)scsi_debug_virtual_gb *
1451 (1073741824 / scsi_debug_sector_size);
FUJITA Tomonori28898872008-03-30 00:59:55 +09001452 else
1453 return sdebug_store_sectors;
1454}
1455
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456#define SDEBUG_READCAP_ARR_SZ 8
1457static int resp_readcap(struct scsi_cmnd * scp,
1458 struct sdebug_dev_info * devip)
1459{
1460 unsigned char arr[SDEBUG_READCAP_ARR_SZ];
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001461 unsigned int capac;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001462
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001463 /* following just in case virtual_gb changed */
FUJITA Tomonori28898872008-03-30 00:59:55 +09001464 sdebug_capacity = get_sdebug_capacity();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465 memset(arr, 0, SDEBUG_READCAP_ARR_SZ);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001466 if (sdebug_capacity < 0xffffffff) {
1467 capac = (unsigned int)sdebug_capacity - 1;
1468 arr[0] = (capac >> 24);
1469 arr[1] = (capac >> 16) & 0xff;
1470 arr[2] = (capac >> 8) & 0xff;
1471 arr[3] = capac & 0xff;
1472 } else {
1473 arr[0] = 0xff;
1474 arr[1] = 0xff;
1475 arr[2] = 0xff;
1476 arr[3] = 0xff;
1477 }
Martin K. Petersen597136a2008-06-05 00:12:59 -04001478 arr[6] = (scsi_debug_sector_size >> 8) & 0xff;
1479 arr[7] = scsi_debug_sector_size & 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001480 return fill_from_dev_buffer(scp, arr, SDEBUG_READCAP_ARR_SZ);
1481}
1482
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001483#define SDEBUG_READCAP16_ARR_SZ 32
1484static int resp_readcap16(struct scsi_cmnd * scp,
1485 struct sdebug_dev_info * devip)
1486{
Douglas Gilbert01123ef2014-08-05 12:20:02 +02001487 unsigned char *cmd = scp->cmnd;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001488 unsigned char arr[SDEBUG_READCAP16_ARR_SZ];
1489 unsigned long long capac;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001490 int k, alloc_len;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001491
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001492 alloc_len = ((cmd[10] << 24) + (cmd[11] << 16) + (cmd[12] << 8)
1493 + cmd[13]);
1494 /* following just in case virtual_gb changed */
FUJITA Tomonori28898872008-03-30 00:59:55 +09001495 sdebug_capacity = get_sdebug_capacity();
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001496 memset(arr, 0, SDEBUG_READCAP16_ARR_SZ);
1497 capac = sdebug_capacity - 1;
1498 for (k = 0; k < 8; ++k, capac >>= 8)
1499 arr[7 - k] = capac & 0xff;
Martin K. Petersen597136a2008-06-05 00:12:59 -04001500 arr[8] = (scsi_debug_sector_size >> 24) & 0xff;
1501 arr[9] = (scsi_debug_sector_size >> 16) & 0xff;
1502 arr[10] = (scsi_debug_sector_size >> 8) & 0xff;
1503 arr[11] = scsi_debug_sector_size & 0xff;
Martin K. Petersenea61fca2009-05-15 00:40:33 -04001504 arr[13] = scsi_debug_physblk_exp & 0xf;
1505 arr[14] = (scsi_debug_lowest_aligned >> 8) & 0x3f;
Martin K. Petersen44d92692009-10-15 14:45:27 -04001506
Eric Sandeenbe1dd782012-03-08 00:03:59 -06001507 if (scsi_debug_lbp()) {
Martin K. Petersen5b94e232011-03-08 02:08:11 -05001508 arr[14] |= 0x80; /* LBPME */
Eric Sandeenbe1dd782012-03-08 00:03:59 -06001509 if (scsi_debug_lbprz)
1510 arr[14] |= 0x40; /* LBPRZ */
1511 }
Martin K. Petersen44d92692009-10-15 14:45:27 -04001512
Martin K. Petersenea61fca2009-05-15 00:40:33 -04001513 arr[15] = scsi_debug_lowest_aligned & 0xff;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001514
1515 if (scsi_debug_dif) {
1516 arr[12] = (scsi_debug_dif - 1) << 1; /* P_TYPE */
1517 arr[12] |= 1; /* PROT_EN */
1518 }
1519
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001520 return fill_from_dev_buffer(scp, arr,
1521 min(alloc_len, SDEBUG_READCAP16_ARR_SZ));
1522}
1523
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001524#define SDEBUG_MAX_TGTPGS_ARR_SZ 1412
1525
1526static int resp_report_tgtpgs(struct scsi_cmnd * scp,
1527 struct sdebug_dev_info * devip)
1528{
Douglas Gilbert01123ef2014-08-05 12:20:02 +02001529 unsigned char *cmd = scp->cmnd;
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001530 unsigned char * arr;
1531 int host_no = devip->sdbg_host->shost->host_no;
1532 int n, ret, alen, rlen;
1533 int port_group_a, port_group_b, port_a, port_b;
1534
1535 alen = ((cmd[6] << 24) + (cmd[7] << 16) + (cmd[8] << 8)
1536 + cmd[9]);
1537
Douglas Gilbert6f3cbf52007-01-05 00:05:25 -05001538 arr = kzalloc(SDEBUG_MAX_TGTPGS_ARR_SZ, GFP_ATOMIC);
1539 if (! arr)
1540 return DID_REQUEUE << 16;
Hannes Reinecke5a09e392006-10-20 09:58:47 +02001541 /*
1542 * EVPD page 0x88 states we have two ports, one
1543 * real and a fake port with no device connected.
1544 * So we create two port groups with one port each
1545 * and set the group with port B to unavailable.
1546 */
1547 port_a = 0x1; /* relative port A */
1548 port_b = 0x2; /* relative port B */
1549 port_group_a = (((host_no + 1) & 0x7f) << 8) +
1550 (devip->channel & 0x7f);
1551 port_group_b = (((host_no + 1) & 0x7f) << 8) +
1552 (devip->channel & 0x7f) + 0x80;
1553
1554 /*
1555 * The asymmetric access state is cycled according to the host_id.
1556 */
1557 n = 4;
1558 if (0 == scsi_debug_vpd_use_hostno) {
1559 arr[n++] = host_no % 3; /* Asymm access state */
1560 arr[n++] = 0x0F; /* claim: all states are supported */
1561 } else {
1562 arr[n++] = 0x0; /* Active/Optimized path */
1563 arr[n++] = 0x01; /* claim: only support active/optimized paths */
1564 }
1565 arr[n++] = (port_group_a >> 8) & 0xff;
1566 arr[n++] = port_group_a & 0xff;
1567 arr[n++] = 0; /* Reserved */
1568 arr[n++] = 0; /* Status code */
1569 arr[n++] = 0; /* Vendor unique */
1570 arr[n++] = 0x1; /* One port per group */
1571 arr[n++] = 0; /* Reserved */
1572 arr[n++] = 0; /* Reserved */
1573 arr[n++] = (port_a >> 8) & 0xff;
1574 arr[n++] = port_a & 0xff;
1575 arr[n++] = 3; /* Port unavailable */
1576 arr[n++] = 0x08; /* claim: only unavailalbe paths are supported */
1577 arr[n++] = (port_group_b >> 8) & 0xff;
1578 arr[n++] = port_group_b & 0xff;
1579 arr[n++] = 0; /* Reserved */
1580 arr[n++] = 0; /* Status code */
1581 arr[n++] = 0; /* Vendor unique */
1582 arr[n++] = 0x1; /* One port per group */
1583 arr[n++] = 0; /* Reserved */
1584 arr[n++] = 0; /* Reserved */
1585 arr[n++] = (port_b >> 8) & 0xff;
1586 arr[n++] = port_b & 0xff;
1587
1588 rlen = n - 4;
1589 arr[0] = (rlen >> 24) & 0xff;
1590 arr[1] = (rlen >> 16) & 0xff;
1591 arr[2] = (rlen >> 8) & 0xff;
1592 arr[3] = rlen & 0xff;
1593
1594 /*
1595 * Return the smallest value of either
1596 * - The allocated length
1597 * - The constructed command length
1598 * - The maximum array size
1599 */
1600 rlen = min(alen,n);
1601 ret = fill_from_dev_buffer(scp, arr,
1602 min(rlen, SDEBUG_MAX_TGTPGS_ARR_SZ));
1603 kfree(arr);
1604 return ret;
1605}
1606
Douglas Gilbert38d5c832014-11-24 21:27:12 -05001607static int
1608resp_rsup_opcodes(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
1609{
1610 bool rctd;
1611 u8 reporting_opts, req_opcode, sdeb_i, supp;
1612 u16 req_sa, u;
1613 u32 alloc_len, a_len;
1614 int k, offset, len, errsts, count, bump, na;
1615 const struct opcode_info_t *oip;
1616 const struct opcode_info_t *r_oip;
1617 u8 *arr;
1618 u8 *cmd = scp->cmnd;
1619
1620 rctd = !!(cmd[2] & 0x80);
1621 reporting_opts = cmd[2] & 0x7;
1622 req_opcode = cmd[3];
1623 req_sa = get_unaligned_be16(cmd + 4);
1624 alloc_len = get_unaligned_be32(cmd + 6);
1625 if (alloc_len < 4 && alloc_len > 0xffff) {
1626 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 6, -1);
1627 return check_condition_result;
1628 }
1629 if (alloc_len > 8192)
1630 a_len = 8192;
1631 else
1632 a_len = alloc_len;
1633 arr = kzalloc((a_len < 256) ? 320 : a_len + 64, GFP_KERNEL);
1634 if (NULL == arr) {
1635 mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC,
1636 INSUFF_RES_ASCQ);
1637 return check_condition_result;
1638 }
1639 switch (reporting_opts) {
1640 case 0: /* all commands */
1641 /* count number of commands */
1642 for (count = 0, oip = opcode_info_arr;
1643 oip->num_attached != 0xff; ++oip) {
1644 if (F_INV_OP & oip->flags)
1645 continue;
1646 count += (oip->num_attached + 1);
1647 }
1648 bump = rctd ? 20 : 8;
1649 put_unaligned_be32(count * bump, arr);
1650 for (offset = 4, oip = opcode_info_arr;
1651 oip->num_attached != 0xff && offset < a_len; ++oip) {
1652 if (F_INV_OP & oip->flags)
1653 continue;
1654 na = oip->num_attached;
1655 arr[offset] = oip->opcode;
1656 put_unaligned_be16(oip->sa, arr + offset + 2);
1657 if (rctd)
1658 arr[offset + 5] |= 0x2;
1659 if (FF_SA & oip->flags)
1660 arr[offset + 5] |= 0x1;
1661 put_unaligned_be16(oip->len_mask[0], arr + offset + 6);
1662 if (rctd)
1663 put_unaligned_be16(0xa, arr + offset + 8);
1664 r_oip = oip;
1665 for (k = 0, oip = oip->arrp; k < na; ++k, ++oip) {
1666 if (F_INV_OP & oip->flags)
1667 continue;
1668 offset += bump;
1669 arr[offset] = oip->opcode;
1670 put_unaligned_be16(oip->sa, arr + offset + 2);
1671 if (rctd)
1672 arr[offset + 5] |= 0x2;
1673 if (FF_SA & oip->flags)
1674 arr[offset + 5] |= 0x1;
1675 put_unaligned_be16(oip->len_mask[0],
1676 arr + offset + 6);
1677 if (rctd)
1678 put_unaligned_be16(0xa,
1679 arr + offset + 8);
1680 }
1681 oip = r_oip;
1682 offset += bump;
1683 }
1684 break;
1685 case 1: /* one command: opcode only */
1686 case 2: /* one command: opcode plus service action */
1687 case 3: /* one command: if sa==0 then opcode only else opcode+sa */
1688 sdeb_i = opcode_ind_arr[req_opcode];
1689 oip = &opcode_info_arr[sdeb_i];
1690 if (F_INV_OP & oip->flags) {
1691 supp = 1;
1692 offset = 4;
1693 } else {
1694 if (1 == reporting_opts) {
1695 if (FF_SA & oip->flags) {
1696 mk_sense_invalid_fld(scp, SDEB_IN_CDB,
1697 2, 2);
1698 kfree(arr);
1699 return check_condition_result;
1700 }
1701 req_sa = 0;
1702 } else if (2 == reporting_opts &&
1703 0 == (FF_SA & oip->flags)) {
1704 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 4, -1);
1705 kfree(arr); /* point at requested sa */
1706 return check_condition_result;
1707 }
1708 if (0 == (FF_SA & oip->flags) &&
1709 req_opcode == oip->opcode)
1710 supp = 3;
1711 else if (0 == (FF_SA & oip->flags)) {
1712 na = oip->num_attached;
1713 for (k = 0, oip = oip->arrp; k < na;
1714 ++k, ++oip) {
1715 if (req_opcode == oip->opcode)
1716 break;
1717 }
1718 supp = (k >= na) ? 1 : 3;
1719 } else if (req_sa != oip->sa) {
1720 na = oip->num_attached;
1721 for (k = 0, oip = oip->arrp; k < na;
1722 ++k, ++oip) {
1723 if (req_sa == oip->sa)
1724 break;
1725 }
1726 supp = (k >= na) ? 1 : 3;
1727 } else
1728 supp = 3;
1729 if (3 == supp) {
1730 u = oip->len_mask[0];
1731 put_unaligned_be16(u, arr + 2);
1732 arr[4] = oip->opcode;
1733 for (k = 1; k < u; ++k)
1734 arr[4 + k] = (k < 16) ?
1735 oip->len_mask[k] : 0xff;
1736 offset = 4 + u;
1737 } else
1738 offset = 4;
1739 }
1740 arr[1] = (rctd ? 0x80 : 0) | supp;
1741 if (rctd) {
1742 put_unaligned_be16(0xa, arr + offset);
1743 offset += 12;
1744 }
1745 break;
1746 default:
1747 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, 2);
1748 kfree(arr);
1749 return check_condition_result;
1750 }
1751 offset = (offset < a_len) ? offset : a_len;
1752 len = (offset < alloc_len) ? offset : alloc_len;
1753 errsts = fill_from_dev_buffer(scp, arr, len);
1754 kfree(arr);
1755 return errsts;
1756}
1757
1758static int
1759resp_rsup_tmfs(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
1760{
1761 bool repd;
1762 u32 alloc_len, len;
1763 u8 arr[16];
1764 u8 *cmd = scp->cmnd;
1765
1766 memset(arr, 0, sizeof(arr));
1767 repd = !!(cmd[2] & 0x80);
1768 alloc_len = get_unaligned_be32(cmd + 6);
1769 if (alloc_len < 4) {
1770 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 6, -1);
1771 return check_condition_result;
1772 }
1773 arr[0] = 0xc8; /* ATS | ATSS | LURS */
1774 arr[1] = 0x1; /* ITNRS */
1775 if (repd) {
1776 arr[3] = 0xc;
1777 len = 16;
1778 } else
1779 len = 4;
1780
1781 len = (len < alloc_len) ? len : alloc_len;
1782 return fill_from_dev_buffer(scp, arr, len);
1783}
1784
Linus Torvalds1da177e2005-04-16 15:20:36 -07001785/* <<Following mode page info copied from ST318451LW>> */
1786
1787static int resp_err_recov_pg(unsigned char * p, int pcontrol, int target)
1788{ /* Read-Write Error Recovery page for mode_sense */
1789 unsigned char err_recov_pg[] = {0x1, 0xa, 0xc0, 11, 240, 0, 0, 0,
1790 5, 0, 0xff, 0xff};
1791
1792 memcpy(p, err_recov_pg, sizeof(err_recov_pg));
1793 if (1 == pcontrol)
1794 memset(p + 2, 0, sizeof(err_recov_pg) - 2);
1795 return sizeof(err_recov_pg);
1796}
1797
1798static int resp_disconnect_pg(unsigned char * p, int pcontrol, int target)
1799{ /* Disconnect-Reconnect page for mode_sense */
1800 unsigned char disconnect_pg[] = {0x2, 0xe, 128, 128, 0, 10, 0, 0,
1801 0, 0, 0, 0, 0, 0, 0, 0};
1802
1803 memcpy(p, disconnect_pg, sizeof(disconnect_pg));
1804 if (1 == pcontrol)
1805 memset(p + 2, 0, sizeof(disconnect_pg) - 2);
1806 return sizeof(disconnect_pg);
1807}
1808
1809static int resp_format_pg(unsigned char * p, int pcontrol, int target)
1810{ /* Format device page for mode_sense */
Martin K. Petersen597136a2008-06-05 00:12:59 -04001811 unsigned char format_pg[] = {0x3, 0x16, 0, 0, 0, 0, 0, 0,
1812 0, 0, 0, 0, 0, 0, 0, 0,
1813 0, 0, 0, 0, 0x40, 0, 0, 0};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001814
Martin K. Petersen597136a2008-06-05 00:12:59 -04001815 memcpy(p, format_pg, sizeof(format_pg));
1816 p[10] = (sdebug_sectors_per >> 8) & 0xff;
1817 p[11] = sdebug_sectors_per & 0xff;
1818 p[12] = (scsi_debug_sector_size >> 8) & 0xff;
1819 p[13] = scsi_debug_sector_size & 0xff;
Martin Pittd9867882012-09-06 12:04:33 +02001820 if (scsi_debug_removable)
Martin K. Petersen597136a2008-06-05 00:12:59 -04001821 p[20] |= 0x20; /* should agree with INQUIRY */
1822 if (1 == pcontrol)
1823 memset(p + 2, 0, sizeof(format_pg) - 2);
1824 return sizeof(format_pg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001825}
1826
1827static int resp_caching_pg(unsigned char * p, int pcontrol, int target)
1828{ /* Caching page for mode_sense */
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001829 unsigned char ch_caching_pg[] = {/* 0x8, 18, */ 0x4, 0, 0, 0, 0, 0,
1830 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
1831 unsigned char d_caching_pg[] = {0x8, 18, 0x14, 0, 0xff, 0xff, 0, 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001832 0xff, 0xff, 0xff, 0xff, 0x80, 0x14, 0, 0, 0, 0, 0, 0};
1833
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001834 if (SCSI_DEBUG_OPT_N_WCE & scsi_debug_opts)
1835 caching_pg[2] &= ~0x4; /* set WCE=0 (default WCE=1) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836 memcpy(p, caching_pg, sizeof(caching_pg));
1837 if (1 == pcontrol)
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001838 memcpy(p + 2, ch_caching_pg, sizeof(ch_caching_pg));
1839 else if (2 == pcontrol)
1840 memcpy(p, d_caching_pg, sizeof(d_caching_pg));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001841 return sizeof(caching_pg);
1842}
1843
1844static int resp_ctrl_m_pg(unsigned char * p, int pcontrol, int target)
1845{ /* Control mode page for mode_sense */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001846 unsigned char ch_ctrl_m_pg[] = {/* 0xa, 10, */ 0x6, 0, 0, 0, 0, 0,
1847 0, 0, 0, 0};
1848 unsigned char d_ctrl_m_pg[] = {0xa, 10, 2, 0, 0, 0, 0, 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001849 0, 0, 0x2, 0x4b};
1850
1851 if (scsi_debug_dsense)
1852 ctrl_m_pg[2] |= 0x4;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001853 else
1854 ctrl_m_pg[2] &= ~0x4;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05001855
1856 if (scsi_debug_ato)
1857 ctrl_m_pg[5] |= 0x80; /* ATO=1 */
1858
Linus Torvalds1da177e2005-04-16 15:20:36 -07001859 memcpy(p, ctrl_m_pg, sizeof(ctrl_m_pg));
1860 if (1 == pcontrol)
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001861 memcpy(p + 2, ch_ctrl_m_pg, sizeof(ch_ctrl_m_pg));
1862 else if (2 == pcontrol)
1863 memcpy(p, d_ctrl_m_pg, sizeof(d_ctrl_m_pg));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864 return sizeof(ctrl_m_pg);
1865}
1866
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001867
Linus Torvalds1da177e2005-04-16 15:20:36 -07001868static int resp_iec_m_pg(unsigned char * p, int pcontrol, int target)
1869{ /* Informational Exceptions control mode page for mode_sense */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001870 unsigned char ch_iec_m_pg[] = {/* 0x1c, 0xa, */ 0x4, 0xf, 0, 0, 0, 0,
1871 0, 0, 0x0, 0x0};
1872 unsigned char d_iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0,
1873 0, 0, 0x0, 0x0};
1874
Linus Torvalds1da177e2005-04-16 15:20:36 -07001875 memcpy(p, iec_m_pg, sizeof(iec_m_pg));
1876 if (1 == pcontrol)
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001877 memcpy(p + 2, ch_iec_m_pg, sizeof(ch_iec_m_pg));
1878 else if (2 == pcontrol)
1879 memcpy(p, d_iec_m_pg, sizeof(d_iec_m_pg));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001880 return sizeof(iec_m_pg);
1881}
1882
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001883static int resp_sas_sf_m_pg(unsigned char * p, int pcontrol, int target)
1884{ /* SAS SSP mode page - short format for mode_sense */
1885 unsigned char sas_sf_m_pg[] = {0x19, 0x6,
1886 0x6, 0x0, 0x7, 0xd0, 0x0, 0x0};
1887
1888 memcpy(p, sas_sf_m_pg, sizeof(sas_sf_m_pg));
1889 if (1 == pcontrol)
1890 memset(p + 2, 0, sizeof(sas_sf_m_pg) - 2);
1891 return sizeof(sas_sf_m_pg);
1892}
1893
1894
1895static int resp_sas_pcd_m_spg(unsigned char * p, int pcontrol, int target,
1896 int target_dev_id)
1897{ /* SAS phy control and discover mode page for mode_sense */
1898 unsigned char sas_pcd_m_pg[] = {0x59, 0x1, 0, 0x64, 0, 0x6, 0, 2,
1899 0, 0, 0, 0, 0x10, 0x9, 0x8, 0x0,
1900 0x52, 0x22, 0x22, 0x20, 0x0, 0x0, 0x0, 0x0,
1901 0x51, 0x11, 0x11, 0x10, 0x0, 0x0, 0x0, 0x1,
1902 0x2, 0, 0, 0, 0, 0, 0, 0,
1903 0x88, 0x99, 0, 0, 0, 0, 0, 0,
1904 0, 0, 0, 0, 0, 0, 0, 0,
1905 0, 1, 0, 0, 0x10, 0x9, 0x8, 0x0,
1906 0x52, 0x22, 0x22, 0x20, 0x0, 0x0, 0x0, 0x0,
1907 0x51, 0x11, 0x11, 0x10, 0x0, 0x0, 0x0, 0x1,
1908 0x3, 0, 0, 0, 0, 0, 0, 0,
1909 0x88, 0x99, 0, 0, 0, 0, 0, 0,
1910 0, 0, 0, 0, 0, 0, 0, 0,
1911 };
1912 int port_a, port_b;
1913
1914 port_a = target_dev_id + 1;
1915 port_b = port_a + 1;
1916 memcpy(p, sas_pcd_m_pg, sizeof(sas_pcd_m_pg));
1917 p[20] = (port_a >> 24);
1918 p[21] = (port_a >> 16) & 0xff;
1919 p[22] = (port_a >> 8) & 0xff;
1920 p[23] = port_a & 0xff;
1921 p[48 + 20] = (port_b >> 24);
1922 p[48 + 21] = (port_b >> 16) & 0xff;
1923 p[48 + 22] = (port_b >> 8) & 0xff;
1924 p[48 + 23] = port_b & 0xff;
1925 if (1 == pcontrol)
1926 memset(p + 4, 0, sizeof(sas_pcd_m_pg) - 4);
1927 return sizeof(sas_pcd_m_pg);
1928}
1929
1930static int resp_sas_sha_m_spg(unsigned char * p, int pcontrol)
1931{ /* SAS SSP shared protocol specific port mode subpage */
1932 unsigned char sas_sha_m_pg[] = {0x59, 0x2, 0, 0xc, 0, 0x6, 0x10, 0,
1933 0, 0, 0, 0, 0, 0, 0, 0,
1934 };
1935
1936 memcpy(p, sas_sha_m_pg, sizeof(sas_sha_m_pg));
1937 if (1 == pcontrol)
1938 memset(p + 4, 0, sizeof(sas_sha_m_pg) - 4);
1939 return sizeof(sas_sha_m_pg);
1940}
1941
Linus Torvalds1da177e2005-04-16 15:20:36 -07001942#define SDEBUG_MAX_MSENSE_SZ 256
1943
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001944static int
1945resp_mode_sense(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001946{
Douglas Gilbert23183912006-09-16 20:30:47 -04001947 unsigned char dbd, llbaa;
1948 int pcontrol, pcode, subpcode, bd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001949 unsigned char dev_spec;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05001950 int k, alloc_len, msense_6, offset, len, target_dev_id;
1951 int target = scp->device->id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001952 unsigned char * ap;
1953 unsigned char arr[SDEBUG_MAX_MSENSE_SZ];
Douglas Gilbert01123ef2014-08-05 12:20:02 +02001954 unsigned char *cmd = scp->cmnd;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001955
Douglas Gilbert23183912006-09-16 20:30:47 -04001956 dbd = !!(cmd[1] & 0x8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001957 pcontrol = (cmd[2] & 0xc0) >> 6;
1958 pcode = cmd[2] & 0x3f;
1959 subpcode = cmd[3];
1960 msense_6 = (MODE_SENSE == cmd[0]);
Douglas Gilbert23183912006-09-16 20:30:47 -04001961 llbaa = msense_6 ? 0 : !!(cmd[1] & 0x10);
1962 if ((0 == scsi_debug_ptype) && (0 == dbd))
1963 bd_len = llbaa ? 16 : 8;
1964 else
1965 bd_len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001966 alloc_len = msense_6 ? cmd[4] : ((cmd[7] << 8) | cmd[8]);
1967 memset(arr, 0, SDEBUG_MAX_MSENSE_SZ);
1968 if (0x3 == pcontrol) { /* Saving values not supported */
Douglas Gilbertcbf67842014-07-26 11:55:35 -04001969 mk_sense_buffer(scp, ILLEGAL_REQUEST, SAVING_PARAMS_UNSUP, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001970 return check_condition_result;
1971 }
Douglas Gilbertc65b1442006-06-06 00:11:24 -04001972 target_dev_id = ((devip->sdbg_host->shost->host_no + 1) * 2000) +
1973 (devip->target * 1000) - 3;
Douglas Gilbert23183912006-09-16 20:30:47 -04001974 /* set DPOFUA bit for disks */
1975 if (0 == scsi_debug_ptype)
1976 dev_spec = (DEV_READONLY(target) ? 0x80 : 0x0) | 0x10;
1977 else
1978 dev_spec = 0x0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001979 if (msense_6) {
1980 arr[2] = dev_spec;
Douglas Gilbert23183912006-09-16 20:30:47 -04001981 arr[3] = bd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001982 offset = 4;
1983 } else {
1984 arr[3] = dev_spec;
Douglas Gilbert23183912006-09-16 20:30:47 -04001985 if (16 == bd_len)
1986 arr[4] = 0x1; /* set LONGLBA bit */
1987 arr[7] = bd_len; /* assume 255 or less */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001988 offset = 8;
1989 }
1990 ap = arr + offset;
FUJITA Tomonori28898872008-03-30 00:59:55 +09001991 if ((bd_len > 0) && (!sdebug_capacity))
1992 sdebug_capacity = get_sdebug_capacity();
1993
Douglas Gilbert23183912006-09-16 20:30:47 -04001994 if (8 == bd_len) {
1995 if (sdebug_capacity > 0xfffffffe) {
1996 ap[0] = 0xff;
1997 ap[1] = 0xff;
1998 ap[2] = 0xff;
1999 ap[3] = 0xff;
2000 } else {
2001 ap[0] = (sdebug_capacity >> 24) & 0xff;
2002 ap[1] = (sdebug_capacity >> 16) & 0xff;
2003 ap[2] = (sdebug_capacity >> 8) & 0xff;
2004 ap[3] = sdebug_capacity & 0xff;
2005 }
Martin K. Petersen597136a2008-06-05 00:12:59 -04002006 ap[6] = (scsi_debug_sector_size >> 8) & 0xff;
2007 ap[7] = scsi_debug_sector_size & 0xff;
Douglas Gilbert23183912006-09-16 20:30:47 -04002008 offset += bd_len;
2009 ap = arr + offset;
2010 } else if (16 == bd_len) {
2011 unsigned long long capac = sdebug_capacity;
2012
2013 for (k = 0; k < 8; ++k, capac >>= 8)
2014 ap[7 - k] = capac & 0xff;
Martin K. Petersen597136a2008-06-05 00:12:59 -04002015 ap[12] = (scsi_debug_sector_size >> 24) & 0xff;
2016 ap[13] = (scsi_debug_sector_size >> 16) & 0xff;
2017 ap[14] = (scsi_debug_sector_size >> 8) & 0xff;
2018 ap[15] = scsi_debug_sector_size & 0xff;
Douglas Gilbert23183912006-09-16 20:30:47 -04002019 offset += bd_len;
2020 ap = arr + offset;
2021 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002022
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002023 if ((subpcode > 0x0) && (subpcode < 0xff) && (0x19 != pcode)) {
2024 /* TODO: Control Extension page */
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002025 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 3, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002026 return check_condition_result;
2027 }
2028 switch (pcode) {
2029 case 0x1: /* Read-Write error recovery page, direct access */
2030 len = resp_err_recov_pg(ap, pcontrol, target);
2031 offset += len;
2032 break;
2033 case 0x2: /* Disconnect-Reconnect page, all devices */
2034 len = resp_disconnect_pg(ap, pcontrol, target);
2035 offset += len;
2036 break;
2037 case 0x3: /* Format device page, direct access */
2038 len = resp_format_pg(ap, pcontrol, target);
2039 offset += len;
2040 break;
2041 case 0x8: /* Caching page, direct access */
2042 len = resp_caching_pg(ap, pcontrol, target);
2043 offset += len;
2044 break;
2045 case 0xa: /* Control Mode page, all devices */
2046 len = resp_ctrl_m_pg(ap, pcontrol, target);
2047 offset += len;
2048 break;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002049 case 0x19: /* if spc==1 then sas phy, control+discover */
2050 if ((subpcode > 0x2) && (subpcode < 0xff)) {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002051 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 3, -1);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002052 return check_condition_result;
2053 }
2054 len = 0;
2055 if ((0x0 == subpcode) || (0xff == subpcode))
2056 len += resp_sas_sf_m_pg(ap + len, pcontrol, target);
2057 if ((0x1 == subpcode) || (0xff == subpcode))
2058 len += resp_sas_pcd_m_spg(ap + len, pcontrol, target,
2059 target_dev_id);
2060 if ((0x2 == subpcode) || (0xff == subpcode))
2061 len += resp_sas_sha_m_spg(ap + len, pcontrol);
2062 offset += len;
2063 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002064 case 0x1c: /* Informational Exceptions Mode page, all devices */
2065 len = resp_iec_m_pg(ap, pcontrol, target);
2066 offset += len;
2067 break;
2068 case 0x3f: /* Read all Mode pages */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002069 if ((0 == subpcode) || (0xff == subpcode)) {
2070 len = resp_err_recov_pg(ap, pcontrol, target);
2071 len += resp_disconnect_pg(ap + len, pcontrol, target);
2072 len += resp_format_pg(ap + len, pcontrol, target);
2073 len += resp_caching_pg(ap + len, pcontrol, target);
2074 len += resp_ctrl_m_pg(ap + len, pcontrol, target);
2075 len += resp_sas_sf_m_pg(ap + len, pcontrol, target);
2076 if (0xff == subpcode) {
2077 len += resp_sas_pcd_m_spg(ap + len, pcontrol,
2078 target, target_dev_id);
2079 len += resp_sas_sha_m_spg(ap + len, pcontrol);
2080 }
2081 len += resp_iec_m_pg(ap + len, pcontrol, target);
2082 } else {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002083 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 3, -1);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002084 return check_condition_result;
2085 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002086 offset += len;
2087 break;
2088 default:
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002089 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, 5);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002090 return check_condition_result;
2091 }
2092 if (msense_6)
2093 arr[0] = offset - 1;
2094 else {
2095 arr[0] = ((offset - 2) >> 8) & 0xff;
2096 arr[1] = (offset - 2) & 0xff;
2097 }
2098 return fill_from_dev_buffer(scp, arr, min(alloc_len, offset));
2099}
2100
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002101#define SDEBUG_MAX_MSELECT_SZ 512
2102
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002103static int
2104resp_mode_select(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002105{
2106 int pf, sp, ps, md_len, bd_len, off, spf, pg_len;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002107 int param_len, res, mpage;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002108 unsigned char arr[SDEBUG_MAX_MSELECT_SZ];
Douglas Gilbert01123ef2014-08-05 12:20:02 +02002109 unsigned char *cmd = scp->cmnd;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002110 int mselect6 = (MODE_SELECT == cmd[0]);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002111
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002112 memset(arr, 0, sizeof(arr));
2113 pf = cmd[1] & 0x10;
2114 sp = cmd[1] & 0x1;
2115 param_len = mselect6 ? cmd[4] : ((cmd[7] << 8) + cmd[8]);
2116 if ((0 == pf) || sp || (param_len > SDEBUG_MAX_MSELECT_SZ)) {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002117 mk_sense_invalid_fld(scp, SDEB_IN_CDB, mselect6 ? 4 : 7, -1);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002118 return check_condition_result;
2119 }
2120 res = fetch_to_dev_buffer(scp, arr, param_len);
2121 if (-1 == res)
2122 return (DID_ERROR << 16);
2123 else if ((res < param_len) &&
2124 (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002125 sdev_printk(KERN_INFO, scp->device,
2126 "%s: cdb indicated=%d, IO sent=%d bytes\n",
2127 __func__, param_len, res);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002128 md_len = mselect6 ? (arr[0] + 1) : ((arr[0] << 8) + arr[1] + 2);
2129 bd_len = mselect6 ? arr[3] : ((arr[6] << 8) + arr[7]);
Douglas Gilbert23183912006-09-16 20:30:47 -04002130 if (md_len > 2) {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002131 mk_sense_invalid_fld(scp, SDEB_IN_DATA, 0, -1);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002132 return check_condition_result;
2133 }
2134 off = bd_len + (mselect6 ? 4 : 8);
2135 mpage = arr[off] & 0x3f;
2136 ps = !!(arr[off] & 0x80);
2137 if (ps) {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002138 mk_sense_invalid_fld(scp, SDEB_IN_DATA, off, 7);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002139 return check_condition_result;
2140 }
2141 spf = !!(arr[off] & 0x40);
2142 pg_len = spf ? ((arr[off + 2] << 8) + arr[off + 3] + 4) :
2143 (arr[off + 1] + 2);
2144 if ((pg_len + off) > param_len) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002145 mk_sense_buffer(scp, ILLEGAL_REQUEST,
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002146 PARAMETER_LIST_LENGTH_ERR, 0);
2147 return check_condition_result;
2148 }
2149 switch (mpage) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002150 case 0x8: /* Caching Mode page */
2151 if (caching_pg[1] == arr[off + 1]) {
2152 memcpy(caching_pg + 2, arr + off + 2,
2153 sizeof(caching_pg) - 2);
2154 goto set_mode_changed_ua;
2155 }
2156 break;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002157 case 0xa: /* Control Mode page */
2158 if (ctrl_m_pg[1] == arr[off + 1]) {
2159 memcpy(ctrl_m_pg + 2, arr + off + 2,
2160 sizeof(ctrl_m_pg) - 2);
2161 scsi_debug_dsense = !!(ctrl_m_pg[2] & 0x4);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002162 goto set_mode_changed_ua;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002163 }
2164 break;
2165 case 0x1c: /* Informational Exceptions Mode page */
2166 if (iec_m_pg[1] == arr[off + 1]) {
2167 memcpy(iec_m_pg + 2, arr + off + 2,
2168 sizeof(iec_m_pg) - 2);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002169 goto set_mode_changed_ua;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002170 }
2171 break;
2172 default:
2173 break;
2174 }
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002175 mk_sense_invalid_fld(scp, SDEB_IN_DATA, off, 5);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002176 return check_condition_result;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002177set_mode_changed_ua:
2178 set_bit(SDEBUG_UA_MODE_CHANGED, devip->uas_bm);
2179 return 0;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002180}
2181
2182static int resp_temp_l_pg(unsigned char * arr)
2183{
2184 unsigned char temp_l_pg[] = {0x0, 0x0, 0x3, 0x2, 0x0, 38,
2185 0x0, 0x1, 0x3, 0x2, 0x0, 65,
2186 };
2187
2188 memcpy(arr, temp_l_pg, sizeof(temp_l_pg));
2189 return sizeof(temp_l_pg);
2190}
2191
2192static int resp_ie_l_pg(unsigned char * arr)
2193{
2194 unsigned char ie_l_pg[] = {0x0, 0x0, 0x3, 0x3, 0x0, 0x0, 38,
2195 };
2196
2197 memcpy(arr, ie_l_pg, sizeof(ie_l_pg));
2198 if (iec_m_pg[2] & 0x4) { /* TEST bit set */
2199 arr[4] = THRESHOLD_EXCEEDED;
2200 arr[5] = 0xff;
2201 }
2202 return sizeof(ie_l_pg);
2203}
2204
2205#define SDEBUG_MAX_LSENSE_SZ 512
2206
2207static int resp_log_sense(struct scsi_cmnd * scp,
2208 struct sdebug_dev_info * devip)
2209{
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002210 int ppc, sp, pcontrol, pcode, subpcode, alloc_len, len, n;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002211 unsigned char arr[SDEBUG_MAX_LSENSE_SZ];
Douglas Gilbert01123ef2014-08-05 12:20:02 +02002212 unsigned char *cmd = scp->cmnd;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002213
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002214 memset(arr, 0, sizeof(arr));
2215 ppc = cmd[1] & 0x2;
2216 sp = cmd[1] & 0x1;
2217 if (ppc || sp) {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002218 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 1, ppc ? 1 : 0);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002219 return check_condition_result;
2220 }
2221 pcontrol = (cmd[2] & 0xc0) >> 6;
2222 pcode = cmd[2] & 0x3f;
Douglas Gilbert23183912006-09-16 20:30:47 -04002223 subpcode = cmd[3] & 0xff;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002224 alloc_len = (cmd[7] << 8) + cmd[8];
2225 arr[0] = pcode;
Douglas Gilbert23183912006-09-16 20:30:47 -04002226 if (0 == subpcode) {
2227 switch (pcode) {
2228 case 0x0: /* Supported log pages log page */
2229 n = 4;
2230 arr[n++] = 0x0; /* this page */
2231 arr[n++] = 0xd; /* Temperature */
2232 arr[n++] = 0x2f; /* Informational exceptions */
2233 arr[3] = n - 4;
2234 break;
2235 case 0xd: /* Temperature log page */
2236 arr[3] = resp_temp_l_pg(arr + 4);
2237 break;
2238 case 0x2f: /* Informational exceptions log page */
2239 arr[3] = resp_ie_l_pg(arr + 4);
2240 break;
2241 default:
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002242 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, 5);
Douglas Gilbert23183912006-09-16 20:30:47 -04002243 return check_condition_result;
2244 }
2245 } else if (0xff == subpcode) {
2246 arr[0] |= 0x40;
2247 arr[1] = subpcode;
2248 switch (pcode) {
2249 case 0x0: /* Supported log pages and subpages log page */
2250 n = 4;
2251 arr[n++] = 0x0;
2252 arr[n++] = 0x0; /* 0,0 page */
2253 arr[n++] = 0x0;
2254 arr[n++] = 0xff; /* this page */
2255 arr[n++] = 0xd;
2256 arr[n++] = 0x0; /* Temperature */
2257 arr[n++] = 0x2f;
2258 arr[n++] = 0x0; /* Informational exceptions */
2259 arr[3] = n - 4;
2260 break;
2261 case 0xd: /* Temperature subpages */
2262 n = 4;
2263 arr[n++] = 0xd;
2264 arr[n++] = 0x0; /* Temperature */
2265 arr[3] = n - 4;
2266 break;
2267 case 0x2f: /* Informational exceptions subpages */
2268 n = 4;
2269 arr[n++] = 0x2f;
2270 arr[n++] = 0x0; /* Informational exceptions */
2271 arr[3] = n - 4;
2272 break;
2273 default:
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002274 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, 5);
Douglas Gilbert23183912006-09-16 20:30:47 -04002275 return check_condition_result;
2276 }
2277 } else {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002278 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 3, -1);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002279 return check_condition_result;
2280 }
2281 len = min(((arr[2] << 8) + arr[3]) + 4, alloc_len);
2282 return fill_from_dev_buffer(scp, arr,
2283 min(len, SDEBUG_MAX_INQ_ARR_SZ));
2284}
2285
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002286static int check_device_access_params(struct scsi_cmnd *scp,
FUJITA Tomonori19789102008-03-30 00:59:56 +09002287 unsigned long long lba, unsigned int num)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002288{
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002289 if (lba + num > sdebug_capacity) {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002290 mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002291 return check_condition_result;
2292 }
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002293 /* transfer length excessive (tie in to block limits VPD page) */
2294 if (num > sdebug_store_sectors) {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05002295 /* needs work to find which cdb byte 'num' comes from */
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002296 mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002297 return check_condition_result;
2298 }
FUJITA Tomonori19789102008-03-30 00:59:56 +09002299 return 0;
2300}
2301
Akinobu Mitaa4517512013-07-08 16:01:57 -07002302/* Returns number of bytes copied or -1 if error. */
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002303static int
2304do_device_access(struct scsi_cmnd *scmd, u64 lba, u32 num, bool do_write)
FUJITA Tomonori19789102008-03-30 00:59:56 +09002305{
2306 int ret;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002307 u64 block, rest = 0;
Akinobu Mitaa4517512013-07-08 16:01:57 -07002308 struct scsi_data_buffer *sdb;
2309 enum dma_data_direction dir;
2310 size_t (*func)(struct scatterlist *, unsigned int, void *, size_t,
2311 off_t);
FUJITA Tomonori19789102008-03-30 00:59:56 +09002312
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002313 if (do_write) {
Akinobu Mitaa4517512013-07-08 16:01:57 -07002314 sdb = scsi_out(scmd);
2315 dir = DMA_TO_DEVICE;
2316 func = sg_pcopy_to_buffer;
2317 } else {
2318 sdb = scsi_in(scmd);
2319 dir = DMA_FROM_DEVICE;
2320 func = sg_pcopy_from_buffer;
2321 }
2322
2323 if (!sdb->length)
2324 return 0;
2325 if (!(scsi_bidi_cmnd(scmd) || scmd->sc_data_direction == dir))
2326 return -1;
FUJITA Tomonori19789102008-03-30 00:59:56 +09002327
2328 block = do_div(lba, sdebug_store_sectors);
2329 if (block + num > sdebug_store_sectors)
2330 rest = block + num - sdebug_store_sectors;
2331
Akinobu Mitaa4517512013-07-08 16:01:57 -07002332 ret = func(sdb->table.sgl, sdb->table.nents,
2333 fake_storep + (block * scsi_debug_sector_size),
2334 (num - rest) * scsi_debug_sector_size, 0);
2335 if (ret != (num - rest) * scsi_debug_sector_size)
2336 return ret;
2337
2338 if (rest) {
2339 ret += func(sdb->table.sgl, sdb->table.nents,
2340 fake_storep, rest * scsi_debug_sector_size,
2341 (num - rest) * scsi_debug_sector_size);
2342 }
FUJITA Tomonori19789102008-03-30 00:59:56 +09002343
2344 return ret;
2345}
2346
Douglas Gilbert38d5c832014-11-24 21:27:12 -05002347/* If fake_store(lba,num) compares equal to arr(num), then copy top half of
2348 * arr into fake_store(lba,num) and return true. If comparison fails then
2349 * return false. */
2350static bool
2351comp_write_worker(u64 lba, u32 num, const u8 *arr)
2352{
2353 bool res;
2354 u64 block, rest = 0;
2355 u32 store_blks = sdebug_store_sectors;
2356 u32 lb_size = scsi_debug_sector_size;
2357
2358 block = do_div(lba, store_blks);
2359 if (block + num > store_blks)
2360 rest = block + num - store_blks;
2361
2362 res = !memcmp(fake_storep + (block * lb_size), arr,
2363 (num - rest) * lb_size);
2364 if (!res)
2365 return res;
2366 if (rest)
2367 res = memcmp(fake_storep, arr + ((num - rest) * lb_size),
2368 rest * lb_size);
2369 if (!res)
2370 return res;
2371 arr += num * lb_size;
2372 memcpy(fake_storep + (block * lb_size), arr, (num - rest) * lb_size);
2373 if (rest)
2374 memcpy(fake_storep, arr + ((num - rest) * lb_size),
2375 rest * lb_size);
2376 return res;
2377}
2378
Akinobu Mita51d648a2013-09-18 21:27:28 +09002379static __be16 dif_compute_csum(const void *buf, int len)
Akinobu Mitabeb40ea2013-06-29 17:59:19 +09002380{
Akinobu Mita51d648a2013-09-18 21:27:28 +09002381 __be16 csum;
Akinobu Mitabeb40ea2013-06-29 17:59:19 +09002382
Akinobu Mita51d648a2013-09-18 21:27:28 +09002383 if (scsi_debug_guard)
2384 csum = (__force __be16)ip_compute_csum(buf, len);
2385 else
Akinobu Mitabeb40ea2013-06-29 17:59:19 +09002386 csum = cpu_to_be16(crc_t10dif(buf, len));
Akinobu Mita51d648a2013-09-18 21:27:28 +09002387
Akinobu Mitabeb40ea2013-06-29 17:59:19 +09002388 return csum;
2389}
2390
2391static int dif_verify(struct sd_dif_tuple *sdt, const void *data,
2392 sector_t sector, u32 ei_lba)
2393{
Akinobu Mita51d648a2013-09-18 21:27:28 +09002394 __be16 csum = dif_compute_csum(data, scsi_debug_sector_size);
Akinobu Mitabeb40ea2013-06-29 17:59:19 +09002395
2396 if (sdt->guard_tag != csum) {
2397 pr_err("%s: GUARD check failed on sector %lu rcvd 0x%04x, data 0x%04x\n",
2398 __func__,
2399 (unsigned long)sector,
2400 be16_to_cpu(sdt->guard_tag),
2401 be16_to_cpu(csum));
2402 return 0x01;
2403 }
2404 if (scsi_debug_dif == SD_DIF_TYPE1_PROTECTION &&
2405 be32_to_cpu(sdt->ref_tag) != (sector & 0xffffffff)) {
2406 pr_err("%s: REF check failed on sector %lu\n",
2407 __func__, (unsigned long)sector);
2408 return 0x03;
2409 }
2410 if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
2411 be32_to_cpu(sdt->ref_tag) != ei_lba) {
2412 pr_err("%s: REF check failed on sector %lu\n",
2413 __func__, (unsigned long)sector);
Akinobu Mitabeb40ea2013-06-29 17:59:19 +09002414 return 0x03;
2415 }
2416 return 0;
2417}
2418
Akinobu Mitabb8c0632013-09-18 21:27:25 +09002419static void dif_copy_prot(struct scsi_cmnd *SCpnt, sector_t sector,
Akinobu Mita65f72f2a2013-09-18 21:27:26 +09002420 unsigned int sectors, bool read)
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002421{
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002422 size_t resid;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002423 void *paddr;
Akinobu Mita14faa942013-09-18 21:27:24 +09002424 const void *dif_store_end = dif_storep + sdebug_store_sectors;
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002425 struct sg_mapping_iter miter;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002426
Akinobu Mitae18d8be2013-06-29 17:59:18 +09002427 /* Bytes of protection data to copy into sgl */
2428 resid = sectors * sizeof(*dif_storep);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002429
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002430 sg_miter_start(&miter, scsi_prot_sglist(SCpnt),
2431 scsi_prot_sg_count(SCpnt), SG_MITER_ATOMIC |
2432 (read ? SG_MITER_TO_SG : SG_MITER_FROM_SG));
2433
2434 while (sg_miter_next(&miter) && resid > 0) {
2435 size_t len = min(miter.length, resid);
Akinobu Mita14faa942013-09-18 21:27:24 +09002436 void *start = dif_store(sector);
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002437 size_t rest = 0;
Akinobu Mita14faa942013-09-18 21:27:24 +09002438
2439 if (dif_store_end < start + len)
2440 rest = start + len - dif_store_end;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002441
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002442 paddr = miter.addr;
Akinobu Mita14faa942013-09-18 21:27:24 +09002443
Akinobu Mita65f72f2a2013-09-18 21:27:26 +09002444 if (read)
2445 memcpy(paddr, start, len - rest);
2446 else
2447 memcpy(start, paddr, len - rest);
2448
2449 if (rest) {
2450 if (read)
2451 memcpy(paddr + len - rest, dif_storep, rest);
2452 else
2453 memcpy(dif_storep, paddr + len - rest, rest);
2454 }
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002455
Akinobu Mitae18d8be2013-06-29 17:59:18 +09002456 sector += len / sizeof(*dif_storep);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002457 resid -= len;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002458 }
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002459 sg_miter_stop(&miter);
Akinobu Mitabb8c0632013-09-18 21:27:25 +09002460}
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002461
Akinobu Mitabb8c0632013-09-18 21:27:25 +09002462static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec,
2463 unsigned int sectors, u32 ei_lba)
2464{
2465 unsigned int i;
2466 struct sd_dif_tuple *sdt;
2467 sector_t sector;
2468
Akinobu Mitac45eabec2014-02-26 22:56:58 +09002469 for (i = 0; i < sectors; i++, ei_lba++) {
Akinobu Mitabb8c0632013-09-18 21:27:25 +09002470 int ret;
2471
2472 sector = start_sec + i;
2473 sdt = dif_store(sector);
2474
Akinobu Mita51d648a2013-09-18 21:27:28 +09002475 if (sdt->app_tag == cpu_to_be16(0xffff))
Akinobu Mitabb8c0632013-09-18 21:27:25 +09002476 continue;
2477
2478 ret = dif_verify(sdt, fake_store(sector), sector, ei_lba);
2479 if (ret) {
2480 dif_errors++;
2481 return ret;
2482 }
Akinobu Mitabb8c0632013-09-18 21:27:25 +09002483 }
2484
Akinobu Mita65f72f2a2013-09-18 21:27:26 +09002485 dif_copy_prot(SCpnt, start_sec, sectors, true);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002486 dix_reads++;
2487
2488 return 0;
2489}
2490
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002491static int
2492resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
FUJITA Tomonori19789102008-03-30 00:59:56 +09002493{
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002494 u8 *cmd = scp->cmnd;
2495 u64 lba;
2496 u32 num;
2497 u32 ei_lba;
FUJITA Tomonori19789102008-03-30 00:59:56 +09002498 unsigned long iflags;
2499 int ret;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002500 bool check_prot;
FUJITA Tomonori19789102008-03-30 00:59:56 +09002501
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002502 switch (cmd[0]) {
2503 case READ_16:
2504 ei_lba = 0;
2505 lba = get_unaligned_be64(cmd + 2);
2506 num = get_unaligned_be32(cmd + 10);
2507 check_prot = true;
2508 break;
2509 case READ_10:
2510 ei_lba = 0;
2511 lba = get_unaligned_be32(cmd + 2);
2512 num = get_unaligned_be16(cmd + 7);
2513 check_prot = true;
2514 break;
2515 case READ_6:
2516 ei_lba = 0;
2517 lba = (u32)cmd[3] | (u32)cmd[2] << 8 |
2518 (u32)(cmd[1] & 0x1f) << 16;
2519 num = (0 == cmd[4]) ? 256 : cmd[4];
2520 check_prot = true;
2521 break;
2522 case READ_12:
2523 ei_lba = 0;
2524 lba = get_unaligned_be32(cmd + 2);
2525 num = get_unaligned_be32(cmd + 6);
2526 check_prot = true;
2527 break;
2528 case XDWRITEREAD_10:
2529 ei_lba = 0;
2530 lba = get_unaligned_be32(cmd + 2);
2531 num = get_unaligned_be16(cmd + 7);
2532 check_prot = false;
2533 break;
2534 default: /* assume READ(32) */
2535 lba = get_unaligned_be64(cmd + 12);
2536 ei_lba = get_unaligned_be32(cmd + 20);
2537 num = get_unaligned_be32(cmd + 28);
2538 check_prot = false;
2539 break;
2540 }
2541 if (check_prot) {
2542 if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
2543 (cmd[1] & 0xe0)) {
2544 mk_sense_invalid_opcode(scp);
2545 return check_condition_result;
2546 }
2547 if ((scsi_debug_dif == SD_DIF_TYPE1_PROTECTION ||
2548 scsi_debug_dif == SD_DIF_TYPE3_PROTECTION) &&
2549 (cmd[1] & 0xe0) == 0)
2550 sdev_printk(KERN_ERR, scp->device, "Unprotected RD "
2551 "to DIF device\n");
2552 }
2553 if (sdebug_any_injecting_opt) {
2554 struct sdebug_scmd_extra_t *ep = scsi_cmd_priv(scp);
2555
2556 if (ep->inj_short)
2557 num /= 2;
2558 }
2559
2560 /* inline check_device_access_params() */
2561 if (lba + num > sdebug_capacity) {
2562 mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0);
2563 return check_condition_result;
2564 }
2565 /* transfer length excessive (tie in to block limits VPD page) */
2566 if (num > sdebug_store_sectors) {
2567 /* needs work to find which cdb byte 'num' comes from */
2568 mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0);
2569 return check_condition_result;
2570 }
FUJITA Tomonori19789102008-03-30 00:59:56 +09002571
Linus Torvalds1da177e2005-04-16 15:20:36 -07002572 if ((SCSI_DEBUG_OPT_MEDIUM_ERR & scsi_debug_opts) &&
Douglas Gilbert32f7ef72011-03-11 10:43:35 -05002573 (lba <= (OPT_MEDIUM_ERR_ADDR + OPT_MEDIUM_ERR_NUM - 1)) &&
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002574 ((lba + num) > OPT_MEDIUM_ERR_ADDR)) {
2575 /* claim unrecoverable read error */
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002576 mk_sense_buffer(scp, MEDIUM_ERROR, UNRECOVERED_READ_ERR, 0);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002577 /* set info field and valid bit for fixed descriptor */
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002578 if (0x70 == (scp->sense_buffer[0] & 0x7f)) {
2579 scp->sense_buffer[0] |= 0x80; /* Valid bit */
Douglas Gilbert32f7ef72011-03-11 10:43:35 -05002580 ret = (lba < OPT_MEDIUM_ERR_ADDR)
2581 ? OPT_MEDIUM_ERR_ADDR : (int)lba;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002582 put_unaligned_be32(ret, scp->sense_buffer + 3);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04002583 }
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002584 scsi_set_resid(scp, scsi_bufflen(scp));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002585 return check_condition_result;
2586 }
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002587
Akinobu Mita6c78cc02014-02-26 22:57:03 +09002588 read_lock_irqsave(&atomic_rw, iflags);
2589
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002590 /* DIX + T10 DIF */
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002591 if (scsi_debug_dix && scsi_prot_sg_count(scp)) {
2592 int prot_ret = prot_verify_read(scp, lba, num, ei_lba);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002593
2594 if (prot_ret) {
Akinobu Mita6c78cc02014-02-26 22:57:03 +09002595 read_unlock_irqrestore(&atomic_rw, iflags);
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002596 mk_sense_buffer(scp, ABORTED_COMMAND, 0x10, prot_ret);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002597 return illegal_condition_result;
2598 }
2599 }
2600
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002601 ret = do_device_access(scp, lba, num, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002602 read_unlock_irqrestore(&atomic_rw, iflags);
Akinobu Mitaa4517512013-07-08 16:01:57 -07002603 if (ret == -1)
2604 return DID_ERROR << 16;
2605
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002606 scsi_in(scp)->resid = scsi_bufflen(scp) - ret;
Akinobu Mitaa4517512013-07-08 16:01:57 -07002607
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002608 if (sdebug_any_injecting_opt) {
2609 struct sdebug_scmd_extra_t *ep = scsi_cmd_priv(scp);
2610
2611 if (ep->inj_recovered) {
2612 mk_sense_buffer(scp, RECOVERED_ERROR,
2613 THRESHOLD_EXCEEDED, 0);
2614 return check_condition_result;
2615 } else if (ep->inj_transport) {
2616 mk_sense_buffer(scp, ABORTED_COMMAND,
2617 TRANSPORT_PROBLEM, ACK_NAK_TO);
2618 return check_condition_result;
2619 } else if (ep->inj_dif) {
2620 /* Logical block guard check failed */
2621 mk_sense_buffer(scp, ABORTED_COMMAND, 0x10, 1);
2622 return illegal_condition_result;
2623 } else if (ep->inj_dix) {
2624 mk_sense_buffer(scp, ILLEGAL_REQUEST, 0x10, 1);
2625 return illegal_condition_result;
2626 }
2627 }
Akinobu Mitaa4517512013-07-08 16:01:57 -07002628 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002629}
2630
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002631void dump_sector(unsigned char *buf, int len)
2632{
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002633 int i, j, n;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002634
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002635 pr_err(">>> Sector Dump <<<\n");
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002636 for (i = 0 ; i < len ; i += 16) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002637 char b[128];
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002638
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002639 for (j = 0, n = 0; j < 16; j++) {
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002640 unsigned char c = buf[i+j];
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002641
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002642 if (c >= 0x20 && c < 0x7e)
2643 n += scnprintf(b + n, sizeof(b) - n,
2644 " %c ", buf[i+j]);
2645 else
2646 n += scnprintf(b + n, sizeof(b) - n,
2647 "%02x ", buf[i+j]);
2648 }
2649 pr_err("%04d: %s\n", i, b);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002650 }
2651}
2652
2653static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec,
Martin K. Petersen395cef02009-09-18 17:33:03 -04002654 unsigned int sectors, u32 ei_lba)
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002655{
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002656 int ret;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002657 struct sd_dif_tuple *sdt;
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002658 void *daddr;
Akinobu Mita65f72f2a2013-09-18 21:27:26 +09002659 sector_t sector = start_sec;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002660 int ppage_offset;
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002661 int dpage_offset;
2662 struct sg_mapping_iter diter;
2663 struct sg_mapping_iter piter;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002664
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002665 BUG_ON(scsi_sg_count(SCpnt) == 0);
2666 BUG_ON(scsi_prot_sg_count(SCpnt) == 0);
2667
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002668 sg_miter_start(&piter, scsi_prot_sglist(SCpnt),
2669 scsi_prot_sg_count(SCpnt),
2670 SG_MITER_ATOMIC | SG_MITER_FROM_SG);
2671 sg_miter_start(&diter, scsi_sglist(SCpnt), scsi_sg_count(SCpnt),
2672 SG_MITER_ATOMIC | SG_MITER_FROM_SG);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002673
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002674 /* For each protection page */
2675 while (sg_miter_next(&piter)) {
2676 dpage_offset = 0;
2677 if (WARN_ON(!sg_miter_next(&diter))) {
2678 ret = 0x01;
2679 goto out;
2680 }
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002681
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002682 for (ppage_offset = 0; ppage_offset < piter.length;
2683 ppage_offset += sizeof(struct sd_dif_tuple)) {
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002684 /* If we're at the end of the current
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002685 * data page advance to the next one
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002686 */
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002687 if (dpage_offset >= diter.length) {
2688 if (WARN_ON(!sg_miter_next(&diter))) {
2689 ret = 0x01;
2690 goto out;
2691 }
2692 dpage_offset = 0;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002693 }
2694
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002695 sdt = piter.addr + ppage_offset;
2696 daddr = diter.addr + dpage_offset;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002697
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002698 ret = dif_verify(sdt, daddr, sector, ei_lba);
Akinobu Mitabeb40ea2013-06-29 17:59:19 +09002699 if (ret) {
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002700 dump_sector(daddr, scsi_debug_sector_size);
Martin K. Petersen395cef02009-09-18 17:33:03 -04002701 goto out;
2702 }
2703
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002704 sector++;
Martin K. Petersen395cef02009-09-18 17:33:03 -04002705 ei_lba++;
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002706 dpage_offset += scsi_debug_sector_size;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002707 }
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002708 diter.consumed = dpage_offset;
2709 sg_miter_stop(&diter);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002710 }
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002711 sg_miter_stop(&piter);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002712
Akinobu Mita65f72f2a2013-09-18 21:27:26 +09002713 dif_copy_prot(SCpnt, start_sec, sectors, false);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002714 dix_writes++;
2715
2716 return 0;
2717
2718out:
2719 dif_errors++;
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09002720 sg_miter_stop(&diter);
2721 sg_miter_stop(&piter);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002722 return ret;
2723}
2724
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002725static unsigned long lba_to_map_index(sector_t lba)
2726{
2727 if (scsi_debug_unmap_alignment) {
2728 lba += scsi_debug_unmap_granularity -
2729 scsi_debug_unmap_alignment;
2730 }
2731 do_div(lba, scsi_debug_unmap_granularity);
2732
2733 return lba;
2734}
2735
2736static sector_t map_index_to_lba(unsigned long index)
2737{
Akinobu Mitaa027b5b2013-08-26 22:08:41 +09002738 sector_t lba = index * scsi_debug_unmap_granularity;
2739
2740 if (scsi_debug_unmap_alignment) {
2741 lba -= scsi_debug_unmap_granularity -
2742 scsi_debug_unmap_alignment;
2743 }
2744
2745 return lba;
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002746}
2747
Martin K. Petersen44d92692009-10-15 14:45:27 -04002748static unsigned int map_state(sector_t lba, unsigned int *num)
2749{
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002750 sector_t end;
2751 unsigned int mapped;
2752 unsigned long index;
2753 unsigned long next;
Martin K. Petersen44d92692009-10-15 14:45:27 -04002754
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002755 index = lba_to_map_index(lba);
2756 mapped = test_bit(index, map_storep);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002757
2758 if (mapped)
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002759 next = find_next_zero_bit(map_storep, map_size, index);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002760 else
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002761 next = find_next_bit(map_storep, map_size, index);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002762
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002763 end = min_t(sector_t, sdebug_store_sectors, map_index_to_lba(next));
Martin K. Petersen44d92692009-10-15 14:45:27 -04002764 *num = end - lba;
2765
2766 return mapped;
2767}
2768
2769static void map_region(sector_t lba, unsigned int len)
2770{
Martin K. Petersen44d92692009-10-15 14:45:27 -04002771 sector_t end = lba + len;
2772
Martin K. Petersen44d92692009-10-15 14:45:27 -04002773 while (lba < end) {
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002774 unsigned long index = lba_to_map_index(lba);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002775
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002776 if (index < map_size)
2777 set_bit(index, map_storep);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002778
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002779 lba = map_index_to_lba(index + 1);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002780 }
2781}
2782
2783static void unmap_region(sector_t lba, unsigned int len)
2784{
Martin K. Petersen44d92692009-10-15 14:45:27 -04002785 sector_t end = lba + len;
2786
Martin K. Petersen44d92692009-10-15 14:45:27 -04002787 while (lba < end) {
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002788 unsigned long index = lba_to_map_index(lba);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002789
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002790 if (lba == map_index_to_lba(index) &&
2791 lba + scsi_debug_unmap_granularity <= end &&
2792 index < map_size) {
2793 clear_bit(index, map_storep);
2794 if (scsi_debug_lbprz) {
Eric Sandeenbe1dd782012-03-08 00:03:59 -06002795 memset(fake_storep +
Akinobu Mitacc34a8e2013-04-16 22:11:57 +09002796 lba * scsi_debug_sector_size, 0,
2797 scsi_debug_sector_size *
2798 scsi_debug_unmap_granularity);
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002799 }
Akinobu Mitae9926b42013-06-29 17:59:17 +09002800 if (dif_storep) {
2801 memset(dif_storep + lba, 0xff,
2802 sizeof(*dif_storep) *
2803 scsi_debug_unmap_granularity);
2804 }
Eric Sandeenbe1dd782012-03-08 00:03:59 -06002805 }
Akinobu Mitab90ebc32013-04-16 22:11:58 +09002806 lba = map_index_to_lba(index + 1);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002807 }
2808}
2809
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002810static int
2811resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002812{
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002813 u8 *cmd = scp->cmnd;
2814 u64 lba;
2815 u32 num;
2816 u32 ei_lba;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002817 unsigned long iflags;
FUJITA Tomonori19789102008-03-30 00:59:56 +09002818 int ret;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002819 bool check_prot;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002820
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002821 switch (cmd[0]) {
2822 case WRITE_16:
2823 ei_lba = 0;
2824 lba = get_unaligned_be64(cmd + 2);
2825 num = get_unaligned_be32(cmd + 10);
2826 check_prot = true;
2827 break;
2828 case WRITE_10:
2829 ei_lba = 0;
2830 lba = get_unaligned_be32(cmd + 2);
2831 num = get_unaligned_be16(cmd + 7);
2832 check_prot = true;
2833 break;
2834 case WRITE_6:
2835 ei_lba = 0;
2836 lba = (u32)cmd[3] | (u32)cmd[2] << 8 |
2837 (u32)(cmd[1] & 0x1f) << 16;
2838 num = (0 == cmd[4]) ? 256 : cmd[4];
2839 check_prot = true;
2840 break;
2841 case WRITE_12:
2842 ei_lba = 0;
2843 lba = get_unaligned_be32(cmd + 2);
2844 num = get_unaligned_be32(cmd + 6);
2845 check_prot = true;
2846 break;
2847 case 0x53: /* XDWRITEREAD(10) */
2848 ei_lba = 0;
2849 lba = get_unaligned_be32(cmd + 2);
2850 num = get_unaligned_be16(cmd + 7);
2851 check_prot = false;
2852 break;
2853 default: /* assume WRITE(32) */
2854 lba = get_unaligned_be64(cmd + 12);
2855 ei_lba = get_unaligned_be32(cmd + 20);
2856 num = get_unaligned_be32(cmd + 28);
2857 check_prot = false;
2858 break;
2859 }
2860 if (check_prot) {
2861 if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
2862 (cmd[1] & 0xe0)) {
2863 mk_sense_invalid_opcode(scp);
2864 return check_condition_result;
2865 }
2866 if ((scsi_debug_dif == SD_DIF_TYPE1_PROTECTION ||
2867 scsi_debug_dif == SD_DIF_TYPE3_PROTECTION) &&
2868 (cmd[1] & 0xe0) == 0)
2869 sdev_printk(KERN_ERR, scp->device, "Unprotected WR "
2870 "to DIF device\n");
2871 }
2872
2873 /* inline check_device_access_params() */
2874 if (lba + num > sdebug_capacity) {
2875 mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0);
2876 return check_condition_result;
2877 }
2878 /* transfer length excessive (tie in to block limits VPD page) */
2879 if (num > sdebug_store_sectors) {
2880 /* needs work to find which cdb byte 'num' comes from */
2881 mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0);
2882 return check_condition_result;
2883 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002884
Akinobu Mita6c78cc02014-02-26 22:57:03 +09002885 write_lock_irqsave(&atomic_rw, iflags);
2886
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002887 /* DIX + T10 DIF */
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002888 if (scsi_debug_dix && scsi_prot_sg_count(scp)) {
2889 int prot_ret = prot_verify_write(scp, lba, num, ei_lba);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002890
2891 if (prot_ret) {
Akinobu Mita6c78cc02014-02-26 22:57:03 +09002892 write_unlock_irqrestore(&atomic_rw, iflags);
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002893 mk_sense_buffer(scp, ILLEGAL_REQUEST, 0x10, prot_ret);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05002894 return illegal_condition_result;
2895 }
2896 }
2897
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002898 ret = do_device_access(scp, lba, num, true);
Akinobu Mita9ed8d3d2013-04-16 22:11:55 +09002899 if (scsi_debug_lbp())
Martin K. Petersen44d92692009-10-15 14:45:27 -04002900 map_region(lba, num);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002901 write_unlock_irqrestore(&atomic_rw, iflags);
FUJITA Tomonori19789102008-03-30 00:59:56 +09002902 if (-1 == ret)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002903 return (DID_ERROR << 16);
Martin K. Petersen597136a2008-06-05 00:12:59 -04002904 else if ((ret < (num * scsi_debug_sector_size)) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07002905 (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002906 sdev_printk(KERN_INFO, scp->device,
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002907 "%s: write: cdb indicated=%u, IO sent=%d bytes\n",
2908 my_name, num * scsi_debug_sector_size, ret);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002909
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002910 if (sdebug_any_injecting_opt) {
2911 struct sdebug_scmd_extra_t *ep = scsi_cmd_priv(scp);
2912
2913 if (ep->inj_recovered) {
2914 mk_sense_buffer(scp, RECOVERED_ERROR,
2915 THRESHOLD_EXCEEDED, 0);
2916 return check_condition_result;
2917 } else if (ep->inj_dif) {
2918 /* Logical block guard check failed */
2919 mk_sense_buffer(scp, ABORTED_COMMAND, 0x10, 1);
2920 return illegal_condition_result;
2921 } else if (ep->inj_dix) {
2922 mk_sense_buffer(scp, ILLEGAL_REQUEST, 0x10, 1);
2923 return illegal_condition_result;
2924 }
2925 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002926 return 0;
2927}
2928
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002929static int
2930resp_write_same(struct scsi_cmnd *scp, u64 lba, u32 num, u32 ei_lba,
2931 bool unmap, bool ndob)
Martin K. Petersen44d92692009-10-15 14:45:27 -04002932{
2933 unsigned long iflags;
2934 unsigned long long i;
2935 int ret;
2936
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002937 ret = check_device_access_params(scp, lba, num);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002938 if (ret)
2939 return ret;
2940
2941 write_lock_irqsave(&atomic_rw, iflags);
2942
Akinobu Mita9ed8d3d2013-04-16 22:11:55 +09002943 if (unmap && scsi_debug_lbp()) {
Martin K. Petersen44d92692009-10-15 14:45:27 -04002944 unmap_region(lba, num);
2945 goto out;
2946 }
2947
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002948 /* if ndob then zero 1 logical block, else fetch 1 logical block */
2949 if (ndob) {
2950 memset(fake_storep + (lba * scsi_debug_sector_size), 0,
2951 scsi_debug_sector_size);
2952 ret = 0;
2953 } else
2954 ret = fetch_to_dev_buffer(scp, fake_storep +
2955 (lba * scsi_debug_sector_size),
2956 scsi_debug_sector_size);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002957
2958 if (-1 == ret) {
2959 write_unlock_irqrestore(&atomic_rw, iflags);
2960 return (DID_ERROR << 16);
2961 } else if ((ret < (num * scsi_debug_sector_size)) &&
2962 (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002963 sdev_printk(KERN_INFO, scp->device,
Douglas Gilbertcbf67842014-07-26 11:55:35 -04002964 "%s: %s: cdb indicated=%u, IO sent=%d bytes\n",
2965 my_name, "write same",
2966 num * scsi_debug_sector_size, ret);
Martin K. Petersen44d92692009-10-15 14:45:27 -04002967
2968 /* Copy first sector to remaining blocks */
2969 for (i = 1 ; i < num ; i++)
2970 memcpy(fake_storep + ((lba + i) * scsi_debug_sector_size),
2971 fake_storep + (lba * scsi_debug_sector_size),
2972 scsi_debug_sector_size);
2973
Akinobu Mita9ed8d3d2013-04-16 22:11:55 +09002974 if (scsi_debug_lbp())
Martin K. Petersen44d92692009-10-15 14:45:27 -04002975 map_region(lba, num);
2976out:
2977 write_unlock_irqrestore(&atomic_rw, iflags);
2978
2979 return 0;
2980}
2981
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05002982static int
2983resp_write_same_10(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
2984{
2985 u8 *cmd = scp->cmnd;
2986 u32 lba;
2987 u16 num;
2988 u32 ei_lba = 0;
2989 bool unmap = false;
2990
2991 if (cmd[1] & 0x8) {
2992 if (scsi_debug_lbpws10 == 0) {
2993 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 1, 3);
2994 return check_condition_result;
2995 } else
2996 unmap = true;
2997 }
2998 lba = get_unaligned_be32(cmd + 2);
2999 num = get_unaligned_be16(cmd + 7);
3000 if (num > scsi_debug_write_same_length) {
3001 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 7, -1);
3002 return check_condition_result;
3003 }
3004 return resp_write_same(scp, lba, num, ei_lba, unmap, false);
3005}
3006
3007static int
3008resp_write_same_16(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
3009{
3010 u8 *cmd = scp->cmnd;
3011 u64 lba;
3012 u32 num;
3013 u32 ei_lba = 0;
3014 bool unmap = false;
3015 bool ndob = false;
3016
3017 if (cmd[1] & 0x8) { /* UNMAP */
3018 if (scsi_debug_lbpws == 0) {
3019 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 1, 3);
3020 return check_condition_result;
3021 } else
3022 unmap = true;
3023 }
3024 if (cmd[1] & 0x1) /* NDOB (no data-out buffer, assumes zeroes) */
3025 ndob = true;
3026 lba = get_unaligned_be64(cmd + 2);
3027 num = get_unaligned_be32(cmd + 10);
3028 if (num > scsi_debug_write_same_length) {
3029 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 10, -1);
3030 return check_condition_result;
3031 }
3032 return resp_write_same(scp, lba, num, ei_lba, unmap, ndob);
3033}
3034
Douglas Gilbert38d5c832014-11-24 21:27:12 -05003035static int
3036resp_comp_write(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
3037{
3038 u8 *cmd = scp->cmnd;
3039 u8 *arr;
3040 u8 *fake_storep_hold;
3041 u64 lba;
3042 u32 dnum;
3043 u32 lb_size = scsi_debug_sector_size;
3044 u8 num;
3045 unsigned long iflags;
3046 int ret;
Douglas Gilbertd467d312014-11-26 12:33:48 -05003047 int retval = 0;
Douglas Gilbert38d5c832014-11-24 21:27:12 -05003048
Douglas Gilbertd467d312014-11-26 12:33:48 -05003049 lba = get_unaligned_be64(cmd + 2);
Douglas Gilbert38d5c832014-11-24 21:27:12 -05003050 num = cmd[13]; /* 1 to a maximum of 255 logical blocks */
3051 if (0 == num)
3052 return 0; /* degenerate case, not an error */
Douglas Gilbert38d5c832014-11-24 21:27:12 -05003053 if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
3054 (cmd[1] & 0xe0)) {
3055 mk_sense_invalid_opcode(scp);
3056 return check_condition_result;
3057 }
3058 if ((scsi_debug_dif == SD_DIF_TYPE1_PROTECTION ||
3059 scsi_debug_dif == SD_DIF_TYPE3_PROTECTION) &&
3060 (cmd[1] & 0xe0) == 0)
3061 sdev_printk(KERN_ERR, scp->device, "Unprotected WR "
3062 "to DIF device\n");
3063
3064 /* inline check_device_access_params() */
3065 if (lba + num > sdebug_capacity) {
3066 mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0);
3067 return check_condition_result;
3068 }
3069 /* transfer length excessive (tie in to block limits VPD page) */
3070 if (num > sdebug_store_sectors) {
3071 /* needs work to find which cdb byte 'num' comes from */
3072 mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0);
3073 return check_condition_result;
3074 }
Douglas Gilbertd467d312014-11-26 12:33:48 -05003075 dnum = 2 * num;
3076 arr = kzalloc(dnum * lb_size, GFP_ATOMIC);
3077 if (NULL == arr) {
3078 mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC,
3079 INSUFF_RES_ASCQ);
3080 return check_condition_result;
3081 }
Douglas Gilbert38d5c832014-11-24 21:27:12 -05003082
3083 write_lock_irqsave(&atomic_rw, iflags);
3084
3085 /* trick do_device_access() to fetch both compare and write buffers
3086 * from data-in into arr. Safe (atomic) since write_lock held. */
3087 fake_storep_hold = fake_storep;
3088 fake_storep = arr;
3089 ret = do_device_access(scp, 0, dnum, true);
3090 fake_storep = fake_storep_hold;
3091 if (ret == -1) {
Douglas Gilbertd467d312014-11-26 12:33:48 -05003092 retval = DID_ERROR << 16;
3093 goto cleanup;
Douglas Gilbert38d5c832014-11-24 21:27:12 -05003094 } else if ((ret < (dnum * lb_size)) &&
3095 (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
3096 sdev_printk(KERN_INFO, scp->device, "%s: compare_write: cdb "
3097 "indicated=%u, IO sent=%d bytes\n", my_name,
3098 dnum * lb_size, ret);
3099 if (!comp_write_worker(lba, num, arr)) {
Douglas Gilbert38d5c832014-11-24 21:27:12 -05003100 mk_sense_buffer(scp, MISCOMPARE, MISCOMPARE_VERIFY_ASC, 0);
Douglas Gilbertd467d312014-11-26 12:33:48 -05003101 retval = check_condition_result;
3102 goto cleanup;
Douglas Gilbert38d5c832014-11-24 21:27:12 -05003103 }
3104 if (scsi_debug_lbp())
3105 map_region(lba, num);
Douglas Gilbertd467d312014-11-26 12:33:48 -05003106cleanup:
Douglas Gilbert38d5c832014-11-24 21:27:12 -05003107 write_unlock_irqrestore(&atomic_rw, iflags);
Douglas Gilbertd467d312014-11-26 12:33:48 -05003108 kfree(arr);
3109 return retval;
Douglas Gilbert38d5c832014-11-24 21:27:12 -05003110}
3111
Martin K. Petersen44d92692009-10-15 14:45:27 -04003112struct unmap_block_desc {
3113 __be64 lba;
3114 __be32 blocks;
3115 __be32 __reserved;
3116};
3117
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003118static int
3119resp_unmap(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
Martin K. Petersen44d92692009-10-15 14:45:27 -04003120{
3121 unsigned char *buf;
3122 struct unmap_block_desc *desc;
3123 unsigned int i, payload_len, descriptors;
3124 int ret;
Akinobu Mita6c78cc02014-02-26 22:57:03 +09003125 unsigned long iflags;
Martin K. Petersen44d92692009-10-15 14:45:27 -04003126
Martin K. Petersen44d92692009-10-15 14:45:27 -04003127
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003128 if (!scsi_debug_lbp())
3129 return 0; /* fib and say its done */
3130 payload_len = get_unaligned_be16(scp->cmnd + 7);
3131 BUG_ON(scsi_bufflen(scp) != payload_len);
Martin K. Petersen44d92692009-10-15 14:45:27 -04003132
3133 descriptors = (payload_len - 8) / 16;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003134 if (descriptors > scsi_debug_unmap_max_desc) {
3135 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 7, -1);
Martin K. Petersen44d92692009-10-15 14:45:27 -04003136 return check_condition_result;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003137 }
Martin K. Petersen44d92692009-10-15 14:45:27 -04003138
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003139 buf = kmalloc(scsi_bufflen(scp), GFP_ATOMIC);
3140 if (!buf) {
3141 mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC,
3142 INSUFF_RES_ASCQ);
3143 return check_condition_result;
3144 }
3145
3146 scsi_sg_copy_to_buffer(scp, buf, scsi_bufflen(scp));
Martin K. Petersen44d92692009-10-15 14:45:27 -04003147
3148 BUG_ON(get_unaligned_be16(&buf[0]) != payload_len - 2);
3149 BUG_ON(get_unaligned_be16(&buf[2]) != descriptors * 16);
3150
3151 desc = (void *)&buf[8];
3152
Akinobu Mita6c78cc02014-02-26 22:57:03 +09003153 write_lock_irqsave(&atomic_rw, iflags);
3154
Martin K. Petersen44d92692009-10-15 14:45:27 -04003155 for (i = 0 ; i < descriptors ; i++) {
3156 unsigned long long lba = get_unaligned_be64(&desc[i].lba);
3157 unsigned int num = get_unaligned_be32(&desc[i].blocks);
3158
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003159 ret = check_device_access_params(scp, lba, num);
Martin K. Petersen44d92692009-10-15 14:45:27 -04003160 if (ret)
3161 goto out;
3162
3163 unmap_region(lba, num);
3164 }
3165
3166 ret = 0;
3167
3168out:
Akinobu Mita6c78cc02014-02-26 22:57:03 +09003169 write_unlock_irqrestore(&atomic_rw, iflags);
Martin K. Petersen44d92692009-10-15 14:45:27 -04003170 kfree(buf);
3171
3172 return ret;
3173}
3174
3175#define SDEBUG_GET_LBA_STATUS_LEN 32
3176
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003177static int
3178resp_get_lba_status(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
Martin K. Petersen44d92692009-10-15 14:45:27 -04003179{
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003180 u8 *cmd = scp->cmnd;
3181 u64 lba;
3182 u32 alloc_len, mapped, num;
3183 u8 arr[SDEBUG_GET_LBA_STATUS_LEN];
Martin K. Petersen44d92692009-10-15 14:45:27 -04003184 int ret;
3185
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003186 lba = get_unaligned_be64(cmd + 2);
3187 alloc_len = get_unaligned_be32(cmd + 10);
Martin K. Petersen44d92692009-10-15 14:45:27 -04003188
3189 if (alloc_len < 24)
3190 return 0;
3191
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003192 ret = check_device_access_params(scp, lba, 1);
Martin K. Petersen44d92692009-10-15 14:45:27 -04003193 if (ret)
3194 return ret;
3195
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003196 if (scsi_debug_lbp())
3197 mapped = map_state(lba, &num);
3198 else {
3199 mapped = 1;
3200 /* following just in case virtual_gb changed */
3201 sdebug_capacity = get_sdebug_capacity();
3202 if (sdebug_capacity - lba <= 0xffffffff)
3203 num = sdebug_capacity - lba;
3204 else
3205 num = 0xffffffff;
3206 }
Martin K. Petersen44d92692009-10-15 14:45:27 -04003207
3208 memset(arr, 0, SDEBUG_GET_LBA_STATUS_LEN);
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003209 put_unaligned_be32(20, arr); /* Parameter Data Length */
3210 put_unaligned_be64(lba, arr + 8); /* LBA */
3211 put_unaligned_be32(num, arr + 16); /* Number of blocks */
3212 arr[20] = !mapped; /* prov_stat=0: mapped; 1: dealloc */
Martin K. Petersen44d92692009-10-15 14:45:27 -04003213
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003214 return fill_from_dev_buffer(scp, arr, SDEBUG_GET_LBA_STATUS_LEN);
Martin K. Petersen44d92692009-10-15 14:45:27 -04003215}
3216
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003217#define SDEBUG_RLUN_ARR_SZ 256
Linus Torvalds1da177e2005-04-16 15:20:36 -07003218
3219static int resp_report_luns(struct scsi_cmnd * scp,
3220 struct sdebug_dev_info * devip)
3221{
3222 unsigned int alloc_len;
Douglas Gilbert22017ed2014-11-24 23:04:47 -05003223 int lun_cnt, i, upper, num, n, want_wlun, shortish;
3224 u64 lun;
Douglas Gilbert01123ef2014-08-05 12:20:02 +02003225 unsigned char *cmd = scp->cmnd;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003226 int select_report = (int)cmd[2];
3227 struct scsi_lun *one_lun;
3228 unsigned char arr[SDEBUG_RLUN_ARR_SZ];
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003229 unsigned char * max_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003230
3231 alloc_len = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24);
Douglas Gilbert22017ed2014-11-24 23:04:47 -05003232 shortish = (alloc_len < 4);
3233 if (shortish || (select_report > 2)) {
3234 mk_sense_invalid_fld(scp, SDEB_IN_CDB, shortish ? 6 : 2, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003235 return check_condition_result;
3236 }
3237 /* can produce response with up to 16k luns (lun 0 to lun 16383) */
3238 memset(arr, 0, SDEBUG_RLUN_ARR_SZ);
3239 lun_cnt = scsi_debug_max_luns;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003240 if (1 == select_report)
3241 lun_cnt = 0;
3242 else if (scsi_debug_no_lun_0 && (lun_cnt > 0))
3243 --lun_cnt;
Douglas Gilbert22017ed2014-11-24 23:04:47 -05003244 want_wlun = (select_report > 0) ? 1 : 0;
3245 num = lun_cnt + want_wlun;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003246 arr[2] = ((sizeof(struct scsi_lun) * num) >> 8) & 0xff;
3247 arr[3] = (sizeof(struct scsi_lun) * num) & 0xff;
3248 n = min((int)((SDEBUG_RLUN_ARR_SZ - 8) /
3249 sizeof(struct scsi_lun)), num);
3250 if (n < num) {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05003251 want_wlun = 0;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003252 lun_cnt = n;
3253 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003254 one_lun = (struct scsi_lun *) &arr[8];
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003255 max_addr = arr + SDEBUG_RLUN_ARR_SZ;
3256 for (i = 0, lun = (scsi_debug_no_lun_0 ? 1 : 0);
3257 ((i < lun_cnt) && ((unsigned char *)(one_lun + i) < max_addr));
3258 i++, lun++) {
3259 upper = (lun >> 8) & 0x3f;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003260 if (upper)
3261 one_lun[i].scsi_lun[0] =
3262 (upper | (SAM2_LUN_ADDRESS_METHOD << 6));
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003263 one_lun[i].scsi_lun[1] = lun & 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003264 }
Douglas Gilbert22017ed2014-11-24 23:04:47 -05003265 if (want_wlun) {
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003266 one_lun[i].scsi_lun[0] = (SAM2_WLUN_REPORT_LUNS >> 8) & 0xff;
3267 one_lun[i].scsi_lun[1] = SAM2_WLUN_REPORT_LUNS & 0xff;
3268 i++;
3269 }
3270 alloc_len = (unsigned char *)(one_lun + i) - arr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003271 return fill_from_dev_buffer(scp, arr,
3272 min((int)alloc_len, SDEBUG_RLUN_ARR_SZ));
3273}
3274
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003275static int resp_xdwriteread(struct scsi_cmnd *scp, unsigned long long lba,
3276 unsigned int num, struct sdebug_dev_info *devip)
3277{
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09003278 int j;
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003279 unsigned char *kaddr, *buf;
3280 unsigned int offset;
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003281 struct scsi_data_buffer *sdb = scsi_in(scp);
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09003282 struct sg_mapping_iter miter;
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003283
3284 /* better not to use temporary buffer. */
3285 buf = kmalloc(scsi_bufflen(scp), GFP_ATOMIC);
Akinobu Mitac5af0db2014-02-26 22:57:01 +09003286 if (!buf) {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05003287 mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC,
3288 INSUFF_RES_ASCQ);
Akinobu Mitac5af0db2014-02-26 22:57:01 +09003289 return check_condition_result;
3290 }
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003291
FUJITA Tomonori21a61822008-03-09 13:44:30 +09003292 scsi_sg_copy_to_buffer(scp, buf, scsi_bufflen(scp));
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003293
3294 offset = 0;
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09003295 sg_miter_start(&miter, sdb->table.sgl, sdb->table.nents,
3296 SG_MITER_ATOMIC | SG_MITER_TO_SG);
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003297
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09003298 while (sg_miter_next(&miter)) {
3299 kaddr = miter.addr;
3300 for (j = 0; j < miter.length; j++)
3301 *(kaddr + j) ^= *(buf + offset + j);
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003302
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09003303 offset += miter.length;
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003304 }
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09003305 sg_miter_stop(&miter);
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003306 kfree(buf);
3307
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09003308 return 0;
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003309}
3310
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003311static int
3312resp_xdwriteread_10(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
3313{
3314 u8 *cmd = scp->cmnd;
3315 u64 lba;
3316 u32 num;
3317 int errsts;
3318
3319 if (!scsi_bidi_cmnd(scp)) {
3320 mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC,
3321 INSUFF_RES_ASCQ);
3322 return check_condition_result;
3323 }
3324 errsts = resp_read_dt0(scp, devip);
3325 if (errsts)
3326 return errsts;
3327 if (!(cmd[1] & 0x4)) { /* DISABLE_WRITE is not set */
3328 errsts = resp_write_dt0(scp, devip);
3329 if (errsts)
3330 return errsts;
3331 }
3332 lba = get_unaligned_be32(cmd + 2);
3333 num = get_unaligned_be16(cmd + 7);
3334 return resp_xdwriteread(scp, lba, num, devip);
3335}
3336
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003337/* When timer or tasklet goes off this function is called. */
3338static void sdebug_q_cmd_complete(unsigned long indx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003339{
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003340 int qa_indx;
3341 int retiring = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003342 unsigned long iflags;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003343 struct sdebug_queued_cmd *sqcp;
3344 struct scsi_cmnd *scp;
3345 struct sdebug_dev_info *devip;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003346
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003347 atomic_inc(&sdebug_completions);
3348 qa_indx = indx;
3349 if ((qa_indx < 0) || (qa_indx >= SCSI_DEBUG_CANQUEUE)) {
3350 pr_err("%s: wild qa_indx=%d\n", __func__, qa_indx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003351 return;
3352 }
3353 spin_lock_irqsave(&queued_arr_lock, iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003354 sqcp = &queued_arr[qa_indx];
3355 scp = sqcp->a_cmnd;
3356 if (NULL == scp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003357 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003358 pr_err("%s: scp is NULL\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003359 return;
3360 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003361 devip = (struct sdebug_dev_info *)scp->device->hostdata;
3362 if (devip)
3363 atomic_dec(&devip->num_in_q);
3364 else
3365 pr_err("%s: devip=NULL\n", __func__);
3366 if (atomic_read(&retired_max_queue) > 0)
3367 retiring = 1;
3368
3369 sqcp->a_cmnd = NULL;
3370 if (!test_and_clear_bit(qa_indx, queued_in_use_bm)) {
3371 spin_unlock_irqrestore(&queued_arr_lock, iflags);
3372 pr_err("%s: Unexpected completion\n", __func__);
3373 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003374 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003375
3376 if (unlikely(retiring)) { /* user has reduced max_queue */
3377 int k, retval;
3378
3379 retval = atomic_read(&retired_max_queue);
3380 if (qa_indx >= retval) {
3381 spin_unlock_irqrestore(&queued_arr_lock, iflags);
3382 pr_err("%s: index %d too large\n", __func__, retval);
3383 return;
3384 }
3385 k = find_last_bit(queued_in_use_bm, retval);
3386 if ((k < scsi_debug_max_queue) || (k == retval))
3387 atomic_set(&retired_max_queue, 0);
3388 else
3389 atomic_set(&retired_max_queue, k + 1);
3390 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003391 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003392 scp->scsi_done(scp); /* callback to mid level */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003393}
3394
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003395/* When high resolution timer goes off this function is called. */
3396static enum hrtimer_restart
3397sdebug_q_cmd_hrt_complete(struct hrtimer *timer)
3398{
3399 int qa_indx;
3400 int retiring = 0;
3401 unsigned long iflags;
3402 struct sdebug_hrtimer *sd_hrtp = (struct sdebug_hrtimer *)timer;
3403 struct sdebug_queued_cmd *sqcp;
3404 struct scsi_cmnd *scp;
3405 struct sdebug_dev_info *devip;
3406
3407 atomic_inc(&sdebug_completions);
3408 qa_indx = sd_hrtp->qa_indx;
3409 if ((qa_indx < 0) || (qa_indx >= SCSI_DEBUG_CANQUEUE)) {
3410 pr_err("%s: wild qa_indx=%d\n", __func__, qa_indx);
3411 goto the_end;
3412 }
3413 spin_lock_irqsave(&queued_arr_lock, iflags);
3414 sqcp = &queued_arr[qa_indx];
3415 scp = sqcp->a_cmnd;
3416 if (NULL == scp) {
3417 spin_unlock_irqrestore(&queued_arr_lock, iflags);
3418 pr_err("%s: scp is NULL\n", __func__);
3419 goto the_end;
3420 }
3421 devip = (struct sdebug_dev_info *)scp->device->hostdata;
3422 if (devip)
3423 atomic_dec(&devip->num_in_q);
3424 else
3425 pr_err("%s: devip=NULL\n", __func__);
3426 if (atomic_read(&retired_max_queue) > 0)
3427 retiring = 1;
3428
3429 sqcp->a_cmnd = NULL;
3430 if (!test_and_clear_bit(qa_indx, queued_in_use_bm)) {
3431 spin_unlock_irqrestore(&queued_arr_lock, iflags);
3432 pr_err("%s: Unexpected completion\n", __func__);
3433 goto the_end;
3434 }
3435
3436 if (unlikely(retiring)) { /* user has reduced max_queue */
3437 int k, retval;
3438
3439 retval = atomic_read(&retired_max_queue);
3440 if (qa_indx >= retval) {
3441 spin_unlock_irqrestore(&queued_arr_lock, iflags);
3442 pr_err("%s: index %d too large\n", __func__, retval);
3443 goto the_end;
3444 }
3445 k = find_last_bit(queued_in_use_bm, retval);
3446 if ((k < scsi_debug_max_queue) || (k == retval))
3447 atomic_set(&retired_max_queue, 0);
3448 else
3449 atomic_set(&retired_max_queue, k + 1);
3450 }
3451 spin_unlock_irqrestore(&queued_arr_lock, iflags);
3452 scp->scsi_done(scp); /* callback to mid level */
3453the_end:
3454 return HRTIMER_NORESTART;
3455}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003456
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003457static struct sdebug_dev_info *
3458sdebug_device_create(struct sdebug_host_info *sdbg_host, gfp_t flags)
FUJITA Tomonori5cb2fc02008-03-20 11:09:16 +09003459{
3460 struct sdebug_dev_info *devip;
3461
3462 devip = kzalloc(sizeof(*devip), flags);
3463 if (devip) {
3464 devip->sdbg_host = sdbg_host;
3465 list_add_tail(&devip->dev_list, &sdbg_host->dev_info_list);
3466 }
3467 return devip;
3468}
3469
Linus Torvalds1da177e2005-04-16 15:20:36 -07003470static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev)
3471{
3472 struct sdebug_host_info * sdbg_host;
3473 struct sdebug_dev_info * open_devip = NULL;
3474 struct sdebug_dev_info * devip =
3475 (struct sdebug_dev_info *)sdev->hostdata;
3476
3477 if (devip)
3478 return devip;
FUJITA Tomonorid1e4c9c2008-03-02 18:30:18 +09003479 sdbg_host = *(struct sdebug_host_info **)shost_priv(sdev->host);
3480 if (!sdbg_host) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003481 pr_err("%s: Host info NULL\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003482 return NULL;
3483 }
3484 list_for_each_entry(devip, &sdbg_host->dev_info_list, dev_list) {
3485 if ((devip->used) && (devip->channel == sdev->channel) &&
3486 (devip->target == sdev->id) &&
3487 (devip->lun == sdev->lun))
3488 return devip;
3489 else {
3490 if ((!devip->used) && (!open_devip))
3491 open_devip = devip;
3492 }
3493 }
FUJITA Tomonori5cb2fc02008-03-20 11:09:16 +09003494 if (!open_devip) { /* try and make a new one */
3495 open_devip = sdebug_device_create(sdbg_host, GFP_ATOMIC);
3496 if (!open_devip) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003497 printk(KERN_ERR "%s: out of memory at line %d\n",
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07003498 __func__, __LINE__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003499 return NULL;
3500 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003501 }
FUJITA Tomonoria75869d2008-03-20 11:09:17 +09003502
3503 open_devip->channel = sdev->channel;
3504 open_devip->target = sdev->id;
3505 open_devip->lun = sdev->lun;
3506 open_devip->sdbg_host = sdbg_host;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003507 atomic_set(&open_devip->num_in_q, 0);
3508 set_bit(SDEBUG_UA_POR, open_devip->uas_bm);
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003509 open_devip->used = true;
FUJITA Tomonoria75869d2008-03-20 11:09:17 +09003510 return open_devip;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003511}
3512
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003513static int scsi_debug_slave_alloc(struct scsi_device *sdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003514{
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003515 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
Hannes Reinecke9cb78c12014-06-25 15:27:36 +02003516 printk(KERN_INFO "scsi_debug: slave_alloc <%u %u %u %llu>\n",
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003517 sdp->host->host_no, sdp->channel, sdp->id, sdp->lun);
Nick Piggin75ad23b2008-04-29 14:48:33 +02003518 queue_flag_set_unlocked(QUEUE_FLAG_BIDI, sdp->request_queue);
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003519 return 0;
3520}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003521
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003522static int scsi_debug_slave_configure(struct scsi_device *sdp)
3523{
3524 struct sdebug_dev_info *devip;
FUJITA Tomonoria34c4e92008-03-25 09:26:50 +09003525
Linus Torvalds1da177e2005-04-16 15:20:36 -07003526 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
Hannes Reinecke9cb78c12014-06-25 15:27:36 +02003527 printk(KERN_INFO "scsi_debug: slave_configure <%u %u %u %llu>\n",
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003528 sdp->host->host_no, sdp->channel, sdp->id, sdp->lun);
3529 if (sdp->host->max_cmd_len != SCSI_DEBUG_MAX_CMD_LEN)
3530 sdp->host->max_cmd_len = SCSI_DEBUG_MAX_CMD_LEN;
3531 devip = devInfoReg(sdp);
3532 if (NULL == devip)
3533 return 1; /* no resources, will be marked offline */
Christoph Hellwigc8b09f62014-11-03 20:15:14 +01003534 sdp->hostdata = devip;
Akinobu Mita6bb5e6e2014-06-02 22:56:49 +09003535 blk_queue_max_segment_size(sdp->request_queue, -1U);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04003536 if (scsi_debug_no_uld)
3537 sdp->no_uld_attach = 1;
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003538 return 0;
3539}
3540
3541static void scsi_debug_slave_destroy(struct scsi_device *sdp)
3542{
3543 struct sdebug_dev_info *devip =
3544 (struct sdebug_dev_info *)sdp->hostdata;
3545
3546 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
Hannes Reinecke9cb78c12014-06-25 15:27:36 +02003547 printk(KERN_INFO "scsi_debug: slave_destroy <%u %u %u %llu>\n",
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003548 sdp->host->host_no, sdp->channel, sdp->id, sdp->lun);
3549 if (devip) {
Lucas De Marchi25985ed2011-03-30 22:57:33 -03003550 /* make this slot available for re-use */
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003551 devip->used = false;
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003552 sdp->hostdata = NULL;
3553 }
3554}
3555
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003556/* Returns 1 if cmnd found (deletes its timer or tasklet), else returns 0 */
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003557static int stop_queued_cmnd(struct scsi_cmnd *cmnd)
3558{
3559 unsigned long iflags;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003560 int k, qmax, r_qmax;
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003561 struct sdebug_queued_cmd *sqcp;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003562 struct sdebug_dev_info *devip;
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003563
3564 spin_lock_irqsave(&queued_arr_lock, iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003565 qmax = scsi_debug_max_queue;
3566 r_qmax = atomic_read(&retired_max_queue);
3567 if (r_qmax > qmax)
3568 qmax = r_qmax;
3569 for (k = 0; k < qmax; ++k) {
3570 if (test_bit(k, queued_in_use_bm)) {
3571 sqcp = &queued_arr[k];
3572 if (cmnd == sqcp->a_cmnd) {
Douglas Gilbertdb525fc2014-08-31 19:09:59 -04003573 devip = (struct sdebug_dev_info *)
3574 cmnd->device->hostdata;
3575 if (devip)
3576 atomic_dec(&devip->num_in_q);
3577 sqcp->a_cmnd = NULL;
3578 spin_unlock_irqrestore(&queued_arr_lock,
3579 iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003580 if (scsi_debug_ndelay > 0) {
3581 if (sqcp->sd_hrtp)
3582 hrtimer_cancel(
3583 &sqcp->sd_hrtp->hrt);
3584 } else if (scsi_debug_delay > 0) {
3585 if (sqcp->cmnd_timerp)
3586 del_timer_sync(
3587 sqcp->cmnd_timerp);
3588 } else if (scsi_debug_delay < 0) {
3589 if (sqcp->tletp)
3590 tasklet_kill(sqcp->tletp);
3591 }
Douglas Gilbertdb525fc2014-08-31 19:09:59 -04003592 clear_bit(k, queued_in_use_bm);
3593 return 1;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003594 }
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003595 }
3596 }
3597 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Douglas Gilbertdb525fc2014-08-31 19:09:59 -04003598 return 0;
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003599}
3600
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003601/* Deletes (stops) timers or tasklets of all queued commands */
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003602static void stop_all_queued(void)
3603{
3604 unsigned long iflags;
3605 int k;
3606 struct sdebug_queued_cmd *sqcp;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003607 struct sdebug_dev_info *devip;
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003608
3609 spin_lock_irqsave(&queued_arr_lock, iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003610 for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) {
3611 if (test_bit(k, queued_in_use_bm)) {
3612 sqcp = &queued_arr[k];
3613 if (sqcp->a_cmnd) {
Douglas Gilbertdb525fc2014-08-31 19:09:59 -04003614 devip = (struct sdebug_dev_info *)
3615 sqcp->a_cmnd->device->hostdata;
3616 if (devip)
3617 atomic_dec(&devip->num_in_q);
3618 sqcp->a_cmnd = NULL;
3619 spin_unlock_irqrestore(&queued_arr_lock,
3620 iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003621 if (scsi_debug_ndelay > 0) {
3622 if (sqcp->sd_hrtp)
3623 hrtimer_cancel(
3624 &sqcp->sd_hrtp->hrt);
3625 } else if (scsi_debug_delay > 0) {
3626 if (sqcp->cmnd_timerp)
3627 del_timer_sync(
3628 sqcp->cmnd_timerp);
3629 } else if (scsi_debug_delay < 0) {
3630 if (sqcp->tletp)
3631 tasklet_kill(sqcp->tletp);
3632 }
Douglas Gilbertdb525fc2014-08-31 19:09:59 -04003633 clear_bit(k, queued_in_use_bm);
3634 spin_lock_irqsave(&queued_arr_lock, iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003635 }
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003636 }
3637 }
3638 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003639}
3640
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003641/* Free queued command memory on heap */
3642static void free_all_queued(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003643{
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003644 unsigned long iflags;
3645 int k;
3646 struct sdebug_queued_cmd *sqcp;
3647
3648 spin_lock_irqsave(&queued_arr_lock, iflags);
3649 for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) {
3650 sqcp = &queued_arr[k];
3651 kfree(sqcp->cmnd_timerp);
3652 sqcp->cmnd_timerp = NULL;
3653 kfree(sqcp->tletp);
3654 sqcp->tletp = NULL;
3655 kfree(sqcp->sd_hrtp);
3656 sqcp->sd_hrtp = NULL;
3657 }
3658 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003659}
3660
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003661static int scsi_debug_abort(struct scsi_cmnd *SCpnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003662{
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003663 ++num_aborts;
3664 if (SCpnt) {
3665 if (SCpnt->device &&
3666 (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts))
3667 sdev_printk(KERN_INFO, SCpnt->device, "%s\n",
3668 __func__);
3669 stop_queued_cmnd(SCpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003670 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003671 return SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003672}
3673
3674static int scsi_debug_device_reset(struct scsi_cmnd * SCpnt)
3675{
3676 struct sdebug_dev_info * devip;
3677
Linus Torvalds1da177e2005-04-16 15:20:36 -07003678 ++num_dev_resets;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003679 if (SCpnt && SCpnt->device) {
3680 struct scsi_device *sdp = SCpnt->device;
3681
3682 if (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts)
3683 sdev_printk(KERN_INFO, sdp, "%s\n", __func__);
3684 devip = devInfoReg(sdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003685 if (devip)
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003686 set_bit(SDEBUG_UA_POR, devip->uas_bm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003687 }
3688 return SUCCESS;
3689}
3690
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003691static int scsi_debug_target_reset(struct scsi_cmnd *SCpnt)
3692{
3693 struct sdebug_host_info *sdbg_host;
3694 struct sdebug_dev_info *devip;
3695 struct scsi_device *sdp;
3696 struct Scsi_Host *hp;
3697 int k = 0;
3698
3699 ++num_target_resets;
3700 if (!SCpnt)
3701 goto lie;
3702 sdp = SCpnt->device;
3703 if (!sdp)
3704 goto lie;
3705 if (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts)
3706 sdev_printk(KERN_INFO, sdp, "%s\n", __func__);
3707 hp = sdp->host;
3708 if (!hp)
3709 goto lie;
3710 sdbg_host = *(struct sdebug_host_info **)shost_priv(hp);
3711 if (sdbg_host) {
3712 list_for_each_entry(devip,
3713 &sdbg_host->dev_info_list,
3714 dev_list)
3715 if (devip->target == sdp->id) {
3716 set_bit(SDEBUG_UA_BUS_RESET, devip->uas_bm);
3717 ++k;
3718 }
3719 }
3720 if (SCSI_DEBUG_OPT_RESET_NOISE & scsi_debug_opts)
3721 sdev_printk(KERN_INFO, sdp,
3722 "%s: %d device(s) found in target\n", __func__, k);
3723lie:
3724 return SUCCESS;
3725}
3726
Linus Torvalds1da177e2005-04-16 15:20:36 -07003727static int scsi_debug_bus_reset(struct scsi_cmnd * SCpnt)
3728{
3729 struct sdebug_host_info *sdbg_host;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003730 struct sdebug_dev_info *devip;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003731 struct scsi_device * sdp;
3732 struct Scsi_Host * hp;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003733 int k = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003734
Linus Torvalds1da177e2005-04-16 15:20:36 -07003735 ++num_bus_resets;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003736 if (!(SCpnt && SCpnt->device))
3737 goto lie;
3738 sdp = SCpnt->device;
3739 if (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts)
3740 sdev_printk(KERN_INFO, sdp, "%s\n", __func__);
3741 hp = sdp->host;
3742 if (hp) {
FUJITA Tomonorid1e4c9c2008-03-02 18:30:18 +09003743 sdbg_host = *(struct sdebug_host_info **)shost_priv(hp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003744 if (sdbg_host) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003745 list_for_each_entry(devip,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003746 &sdbg_host->dev_info_list,
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003747 dev_list) {
3748 set_bit(SDEBUG_UA_BUS_RESET, devip->uas_bm);
3749 ++k;
3750 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003751 }
3752 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003753 if (SCSI_DEBUG_OPT_RESET_NOISE & scsi_debug_opts)
3754 sdev_printk(KERN_INFO, sdp,
3755 "%s: %d device(s) found in host\n", __func__, k);
3756lie:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003757 return SUCCESS;
3758}
3759
3760static int scsi_debug_host_reset(struct scsi_cmnd * SCpnt)
3761{
3762 struct sdebug_host_info * sdbg_host;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003763 struct sdebug_dev_info *devip;
3764 int k = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003765
Linus Torvalds1da177e2005-04-16 15:20:36 -07003766 ++num_host_resets;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003767 if ((SCpnt->device) && (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts))
3768 sdev_printk(KERN_INFO, SCpnt->device, "%s\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003769 spin_lock(&sdebug_host_list_lock);
3770 list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003771 list_for_each_entry(devip, &sdbg_host->dev_info_list,
3772 dev_list) {
3773 set_bit(SDEBUG_UA_BUS_RESET, devip->uas_bm);
3774 ++k;
3775 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003776 }
3777 spin_unlock(&sdebug_host_list_lock);
3778 stop_all_queued();
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003779 if (SCSI_DEBUG_OPT_RESET_NOISE & scsi_debug_opts)
3780 sdev_printk(KERN_INFO, SCpnt->device,
3781 "%s: %d device(s) found\n", __func__, k);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003782 return SUCCESS;
3783}
3784
FUJITA Tomonorif58b0ef2008-03-30 00:59:54 +09003785static void __init sdebug_build_parts(unsigned char *ramp,
FUJITA Tomonori5f2578e2008-03-30 00:59:57 +09003786 unsigned long store_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003787{
3788 struct partition * pp;
3789 int starts[SDEBUG_MAX_PARTS + 2];
3790 int sectors_per_part, num_sectors, k;
3791 int heads_by_sects, start_sec, end_sec;
3792
3793 /* assume partition table already zeroed */
FUJITA Tomonorif58b0ef2008-03-30 00:59:54 +09003794 if ((scsi_debug_num_parts < 1) || (store_size < 1048576))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003795 return;
3796 if (scsi_debug_num_parts > SDEBUG_MAX_PARTS) {
3797 scsi_debug_num_parts = SDEBUG_MAX_PARTS;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003798 pr_warn("%s: reducing partitions to %d\n", __func__,
3799 SDEBUG_MAX_PARTS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003800 }
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003801 num_sectors = (int)sdebug_store_sectors;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003802 sectors_per_part = (num_sectors - sdebug_sectors_per)
3803 / scsi_debug_num_parts;
3804 heads_by_sects = sdebug_heads * sdebug_sectors_per;
3805 starts[0] = sdebug_sectors_per;
3806 for (k = 1; k < scsi_debug_num_parts; ++k)
3807 starts[k] = ((k * sectors_per_part) / heads_by_sects)
3808 * heads_by_sects;
3809 starts[scsi_debug_num_parts] = num_sectors;
3810 starts[scsi_debug_num_parts + 1] = 0;
3811
3812 ramp[510] = 0x55; /* magic partition markings */
3813 ramp[511] = 0xAA;
3814 pp = (struct partition *)(ramp + 0x1be);
3815 for (k = 0; starts[k + 1]; ++k, ++pp) {
3816 start_sec = starts[k];
3817 end_sec = starts[k + 1] - 1;
3818 pp->boot_ind = 0;
3819
3820 pp->cyl = start_sec / heads_by_sects;
3821 pp->head = (start_sec - (pp->cyl * heads_by_sects))
3822 / sdebug_sectors_per;
3823 pp->sector = (start_sec % sdebug_sectors_per) + 1;
3824
3825 pp->end_cyl = end_sec / heads_by_sects;
3826 pp->end_head = (end_sec - (pp->end_cyl * heads_by_sects))
3827 / sdebug_sectors_per;
3828 pp->end_sector = (end_sec % sdebug_sectors_per) + 1;
3829
Akinobu Mita150c3542013-08-26 22:08:40 +09003830 pp->start_sect = cpu_to_le32(start_sec);
3831 pp->nr_sects = cpu_to_le32(end_sec - start_sec + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003832 pp->sys_ind = 0x83; /* plain Linux partition */
3833 }
3834}
3835
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003836static int
3837schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip,
3838 int scsi_result, int delta_jiff)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003839{
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003840 unsigned long iflags;
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003841 int k, num_in_q, qdepth, inject;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003842 struct sdebug_queued_cmd *sqcp = NULL;
3843 struct scsi_device *sdp = cmnd->device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003844
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003845 if (NULL == cmnd || NULL == devip) {
3846 pr_warn("%s: called with NULL cmnd or devip pointer\n",
3847 __func__);
3848 /* no particularly good error to report back */
3849 return SCSI_MLQUEUE_HOST_BUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003850 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003851 if ((scsi_result) && (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
3852 sdev_printk(KERN_INFO, sdp, "%s: non-zero result=0x%x\n",
3853 __func__, scsi_result);
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003854 if (delta_jiff == 0)
3855 goto respond_in_thread;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003856
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003857 /* schedule the response at a later time if resources permit */
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003858 spin_lock_irqsave(&queued_arr_lock, iflags);
3859 num_in_q = atomic_read(&devip->num_in_q);
3860 qdepth = cmnd->device->queue_depth;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003861 inject = 0;
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003862 if ((qdepth > 0) && (num_in_q >= qdepth)) {
3863 if (scsi_result) {
3864 spin_unlock_irqrestore(&queued_arr_lock, iflags);
3865 goto respond_in_thread;
3866 } else
3867 scsi_result = device_qfull_result;
3868 } else if ((scsi_debug_every_nth != 0) &&
3869 (SCSI_DEBUG_OPT_RARE_TSF & scsi_debug_opts) &&
3870 (scsi_result == 0)) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003871 if ((num_in_q == (qdepth - 1)) &&
3872 (atomic_inc_return(&sdebug_a_tsf) >=
3873 abs(scsi_debug_every_nth))) {
3874 atomic_set(&sdebug_a_tsf, 0);
3875 inject = 1;
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003876 scsi_result = device_qfull_result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003877 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003878 }
3879
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003880 k = find_first_zero_bit(queued_in_use_bm, scsi_debug_max_queue);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003881 if (k >= scsi_debug_max_queue) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003882 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003883 if (scsi_result)
3884 goto respond_in_thread;
3885 else if (SCSI_DEBUG_OPT_ALL_TSF & scsi_debug_opts)
3886 scsi_result = device_qfull_result;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003887 if (SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts)
3888 sdev_printk(KERN_INFO, sdp,
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003889 "%s: max_queue=%d exceeded, %s\n",
3890 __func__, scsi_debug_max_queue,
3891 (scsi_result ? "status: TASK SET FULL" :
3892 "report: host busy"));
3893 if (scsi_result)
3894 goto respond_in_thread;
3895 else
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003896 return SCSI_MLQUEUE_HOST_BUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003897 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003898 __set_bit(k, queued_in_use_bm);
3899 atomic_inc(&devip->num_in_q);
3900 sqcp = &queued_arr[k];
3901 sqcp->a_cmnd = cmnd;
3902 cmnd->result = scsi_result;
3903 spin_unlock_irqrestore(&queued_arr_lock, iflags);
3904 if (delta_jiff > 0) {
3905 if (NULL == sqcp->cmnd_timerp) {
3906 sqcp->cmnd_timerp = kmalloc(sizeof(struct timer_list),
3907 GFP_ATOMIC);
3908 if (NULL == sqcp->cmnd_timerp)
3909 return SCSI_MLQUEUE_HOST_BUSY;
3910 init_timer(sqcp->cmnd_timerp);
3911 }
3912 sqcp->cmnd_timerp->function = sdebug_q_cmd_complete;
3913 sqcp->cmnd_timerp->data = k;
3914 sqcp->cmnd_timerp->expires = get_jiffies_64() + delta_jiff;
3915 add_timer(sqcp->cmnd_timerp);
3916 } else if (scsi_debug_ndelay > 0) {
3917 ktime_t kt = ktime_set(0, scsi_debug_ndelay);
3918 struct sdebug_hrtimer *sd_hp = sqcp->sd_hrtp;
3919
3920 if (NULL == sd_hp) {
3921 sd_hp = kmalloc(sizeof(*sd_hp), GFP_ATOMIC);
3922 if (NULL == sd_hp)
3923 return SCSI_MLQUEUE_HOST_BUSY;
3924 sqcp->sd_hrtp = sd_hp;
3925 hrtimer_init(&sd_hp->hrt, CLOCK_MONOTONIC,
3926 HRTIMER_MODE_REL);
3927 sd_hp->hrt.function = sdebug_q_cmd_hrt_complete;
3928 sd_hp->qa_indx = k;
3929 }
3930 hrtimer_start(&sd_hp->hrt, kt, HRTIMER_MODE_REL);
3931 } else { /* delay < 0 */
3932 if (NULL == sqcp->tletp) {
3933 sqcp->tletp = kmalloc(sizeof(*sqcp->tletp),
3934 GFP_ATOMIC);
3935 if (NULL == sqcp->tletp)
3936 return SCSI_MLQUEUE_HOST_BUSY;
3937 tasklet_init(sqcp->tletp,
3938 sdebug_q_cmd_complete, k);
3939 }
3940 if (-1 == delta_jiff)
3941 tasklet_hi_schedule(sqcp->tletp);
3942 else
3943 tasklet_schedule(sqcp->tletp);
3944 }
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003945 if ((SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts) &&
3946 (scsi_result == device_qfull_result))
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003947 sdev_printk(KERN_INFO, sdp,
3948 "%s: num_in_q=%d +1, %s%s\n", __func__,
3949 num_in_q, (inject ? "<inject> " : ""),
3950 "status: TASK SET FULL");
3951 return 0;
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003952
3953respond_in_thread: /* call back to mid-layer using invocation thread */
3954 cmnd->result = scsi_result;
3955 cmnd->scsi_done(cmnd);
3956 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003957}
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003958
Douglas Gilbert23183912006-09-16 20:30:47 -04003959/* Note: The following macros create attribute files in the
3960 /sys/module/scsi_debug/parameters directory. Unfortunately this
3961 driver is unaware of a change and cannot trigger auxiliary actions
3962 as it can when the corresponding attribute in the
3963 /sys/bus/pseudo/drivers/scsi_debug directory is changed.
3964 */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003965module_param_named(add_host, scsi_debug_add_host, int, S_IRUGO | S_IWUSR);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05003966module_param_named(ato, scsi_debug_ato, int, S_IRUGO);
Akinobu Mita0759c662014-02-26 22:57:04 +09003967module_param_named(clustering, scsi_debug_clustering, bool, S_IRUGO | S_IWUSR);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003968module_param_named(delay, scsi_debug_delay, int, S_IRUGO | S_IWUSR);
3969module_param_named(dev_size_mb, scsi_debug_dev_size_mb, int, S_IRUGO);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05003970module_param_named(dif, scsi_debug_dif, int, S_IRUGO);
3971module_param_named(dix, scsi_debug_dix, int, S_IRUGO);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003972module_param_named(dsense, scsi_debug_dsense, int, S_IRUGO | S_IWUSR);
3973module_param_named(every_nth, scsi_debug_every_nth, int, S_IRUGO | S_IWUSR);
Douglas Gilbert23183912006-09-16 20:30:47 -04003974module_param_named(fake_rw, scsi_debug_fake_rw, int, S_IRUGO | S_IWUSR);
Akinobu Mita68aee7b2013-09-18 21:27:27 +09003975module_param_named(guard, scsi_debug_guard, uint, S_IRUGO);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003976module_param_named(host_lock, scsi_debug_host_lock, bool, S_IRUGO | S_IWUSR);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05003977module_param_named(lbpu, scsi_debug_lbpu, int, S_IRUGO);
3978module_param_named(lbpws, scsi_debug_lbpws, int, S_IRUGO);
3979module_param_named(lbpws10, scsi_debug_lbpws10, int, S_IRUGO);
Eric Sandeenbe1dd782012-03-08 00:03:59 -06003980module_param_named(lbprz, scsi_debug_lbprz, int, S_IRUGO);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05003981module_param_named(lowest_aligned, scsi_debug_lowest_aligned, int, S_IRUGO);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003982module_param_named(max_luns, scsi_debug_max_luns, int, S_IRUGO | S_IWUSR);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04003983module_param_named(max_queue, scsi_debug_max_queue, int, S_IRUGO | S_IWUSR);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003984module_param_named(ndelay, scsi_debug_ndelay, int, S_IRUGO | S_IWUSR);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003985module_param_named(no_lun_0, scsi_debug_no_lun_0, int, S_IRUGO | S_IWUSR);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04003986module_param_named(no_uld, scsi_debug_no_uld, int, S_IRUGO);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003987module_param_named(num_parts, scsi_debug_num_parts, int, S_IRUGO);
3988module_param_named(num_tgts, scsi_debug_num_tgts, int, S_IRUGO | S_IWUSR);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05003989module_param_named(opt_blks, scsi_debug_opt_blks, int, S_IRUGO);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003990module_param_named(opts, scsi_debug_opts, int, S_IRUGO | S_IWUSR);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05003991module_param_named(physblk_exp, scsi_debug_physblk_exp, int, S_IRUGO);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003992module_param_named(ptype, scsi_debug_ptype, int, S_IRUGO | S_IWUSR);
Martin Pittd9867882012-09-06 12:04:33 +02003993module_param_named(removable, scsi_debug_removable, bool, S_IRUGO | S_IWUSR);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003994module_param_named(scsi_level, scsi_debug_scsi_level, int, S_IRUGO);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05003995module_param_named(sector_size, scsi_debug_sector_size, int, S_IRUGO);
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003996module_param_named(strict, scsi_debug_strict, bool, S_IRUGO | S_IWUSR);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05003997module_param_named(unmap_alignment, scsi_debug_unmap_alignment, int, S_IRUGO);
3998module_param_named(unmap_granularity, scsi_debug_unmap_granularity, int, S_IRUGO);
3999module_param_named(unmap_max_blocks, scsi_debug_unmap_max_blocks, int, S_IRUGO);
4000module_param_named(unmap_max_desc, scsi_debug_unmap_max_desc, int, S_IRUGO);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004001module_param_named(virtual_gb, scsi_debug_virtual_gb, int, S_IRUGO | S_IWUSR);
Douglas Gilbert23183912006-09-16 20:30:47 -04004002module_param_named(vpd_use_hostno, scsi_debug_vpd_use_hostno, int,
4003 S_IRUGO | S_IWUSR);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004004module_param_named(write_same_length, scsi_debug_write_same_length, int,
4005 S_IRUGO | S_IWUSR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004006
4007MODULE_AUTHOR("Eric Youngdale + Douglas Gilbert");
4008MODULE_DESCRIPTION("SCSI debug adapter driver");
4009MODULE_LICENSE("GPL");
4010MODULE_VERSION(SCSI_DEBUG_VERSION);
4011
4012MODULE_PARM_DESC(add_host, "0..127 hosts allowed(def=1)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004013MODULE_PARM_DESC(ato, "application tag ownership: 0=disk 1=host (def=1)");
Akinobu Mita0759c662014-02-26 22:57:04 +09004014MODULE_PARM_DESC(clustering, "when set enables larger transfers (def=0)");
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004015MODULE_PARM_DESC(delay, "response delay (def=1 jiffy); 0:imm, -1,-2:tiny");
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05004016MODULE_PARM_DESC(dev_size_mb, "size in MiB of ram shared by devs(def=8)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004017MODULE_PARM_DESC(dif, "data integrity field type: 0-3 (def=0)");
4018MODULE_PARM_DESC(dix, "data integrity extensions mask (def=0)");
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004019MODULE_PARM_DESC(dsense, "use descriptor sense format(def=0 -> fixed)");
Randy Dunlapbeb87c32007-06-11 11:36:40 -07004020MODULE_PARM_DESC(every_nth, "timeout every nth command(def=0)");
Douglas Gilbert23183912006-09-16 20:30:47 -04004021MODULE_PARM_DESC(fake_rw, "fake reads/writes instead of copying (def=0)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004022MODULE_PARM_DESC(guard, "protection checksum: 0=crc, 1=ip (def=0)");
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004023MODULE_PARM_DESC(host_lock, "use host_lock around all commands (def=0)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004024MODULE_PARM_DESC(lbpu, "enable LBP, support UNMAP command (def=0)");
4025MODULE_PARM_DESC(lbpws, "enable LBP, support WRITE SAME(16) with UNMAP bit (def=0)");
4026MODULE_PARM_DESC(lbpws10, "enable LBP, support WRITE SAME(10) with UNMAP bit (def=0)");
Eric Sandeenbe1dd782012-03-08 00:03:59 -06004027MODULE_PARM_DESC(lbprz, "unmapped blocks return 0 on read (def=1)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004028MODULE_PARM_DESC(lowest_aligned, "lowest aligned lba (def=0)");
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004029MODULE_PARM_DESC(max_luns, "number of LUNs per target to simulate(def=1)");
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004030MODULE_PARM_DESC(max_queue, "max number of queued commands (1 to max(def))");
4031MODULE_PARM_DESC(ndelay, "response delay in nanoseconds (def=0 -> ignore)");
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004032MODULE_PARM_DESC(no_lun_0, "no LU number 0 (def=0 -> have lun 0)");
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004033MODULE_PARM_DESC(no_uld, "stop ULD (e.g. sd driver) attaching (def=0))");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004034MODULE_PARM_DESC(num_parts, "number of partitions(def=0)");
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004035MODULE_PARM_DESC(num_tgts, "number of targets per host to simulate(def=1)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004036MODULE_PARM_DESC(opt_blks, "optimal transfer length in block (def=64)");
Douglas Gilbert6f3cbf52007-01-05 00:05:25 -05004037MODULE_PARM_DESC(opts, "1->noise, 2->medium_err, 4->timeout, 8->recovered_err... (def=0)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004038MODULE_PARM_DESC(physblk_exp, "physical block exponent (def=0)");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004039MODULE_PARM_DESC(ptype, "SCSI peripheral type(def=0[disk])");
Martin Pittd9867882012-09-06 12:04:33 +02004040MODULE_PARM_DESC(removable, "claim to have removable media (def=0)");
Douglas Gilberte46b0342014-08-05 12:21:53 +02004041MODULE_PARM_DESC(scsi_level, "SCSI level to simulate(def=6[SPC-4])");
Martin K. Petersenea61fca2009-05-15 00:40:33 -04004042MODULE_PARM_DESC(sector_size, "logical block size in bytes (def=512)");
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05004043MODULE_PARM_DESC(strict, "stricter checks: reserved field in cdb (def=0)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004044MODULE_PARM_DESC(unmap_alignment, "lowest aligned thin provisioning lba (def=0)");
4045MODULE_PARM_DESC(unmap_granularity, "thin provisioning granularity in blocks (def=1)");
Martin K. Petersen60147592010-08-19 11:49:00 -04004046MODULE_PARM_DESC(unmap_max_blocks, "max # of blocks can be unmapped in one cmd (def=0xffffffff)");
4047MODULE_PARM_DESC(unmap_max_desc, "max # of ranges that can be unmapped in one cmd (def=256)");
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05004048MODULE_PARM_DESC(virtual_gb, "virtual gigabyte (GiB) size (def=0 -> use dev_size_mb)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004049MODULE_PARM_DESC(vpd_use_hostno, "0 -> dev ids ignore hostno (def=1 -> unique dev ids)");
4050MODULE_PARM_DESC(write_same_length, "Maximum blocks per WRITE SAME cmd (def=0xffff)");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004051
4052static char sdebug_info[256];
4053
4054static const char * scsi_debug_info(struct Scsi_Host * shp)
4055{
4056 sprintf(sdebug_info, "scsi_debug, version %s [%s], "
4057 "dev_size_mb=%d, opts=0x%x", SCSI_DEBUG_VERSION,
4058 scsi_debug_version_date, scsi_debug_dev_size_mb,
4059 scsi_debug_opts);
4060 return sdebug_info;
4061}
4062
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004063/* 'echo <val> > /proc/scsi/scsi_debug/<host_id>' writes to opts */
Al Viroc8ed5552013-03-31 01:46:06 -04004064static int scsi_debug_write_info(struct Scsi_Host *host, char *buffer, int length)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004065{
Al Viroc8ed5552013-03-31 01:46:06 -04004066 char arr[16];
4067 int opts;
4068 int minLen = length > 15 ? 15 : length;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004069
Al Viroc8ed5552013-03-31 01:46:06 -04004070 if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
4071 return -EACCES;
4072 memcpy(arr, buffer, minLen);
4073 arr[minLen] = '\0';
4074 if (1 != sscanf(arr, "%d", &opts))
4075 return -EINVAL;
4076 scsi_debug_opts = opts;
4077 if (scsi_debug_every_nth != 0)
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004078 atomic_set(&sdebug_cmnd_count, 0);
Al Viroc8ed5552013-03-31 01:46:06 -04004079 return length;
4080}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004081
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004082/* Output seen with 'cat /proc/scsi/scsi_debug/<host_id>'. It will be the
4083 * same for each scsi_debug host (if more than one). Some of the counters
4084 * output are not atomics so might be inaccurate in a busy system. */
Al Viroc8ed5552013-03-31 01:46:06 -04004085static int scsi_debug_show_info(struct seq_file *m, struct Scsi_Host *host)
4086{
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004087 int f, l;
4088 char b[32];
4089
4090 if (scsi_debug_every_nth > 0)
4091 snprintf(b, sizeof(b), " (curr:%d)",
4092 ((SCSI_DEBUG_OPT_RARE_TSF & scsi_debug_opts) ?
4093 atomic_read(&sdebug_a_tsf) :
4094 atomic_read(&sdebug_cmnd_count)));
4095 else
4096 b[0] = '\0';
4097
4098 seq_printf(m, "scsi_debug adapter driver, version %s [%s]\n"
4099 "num_tgts=%d, shared (ram) size=%d MB, opts=0x%x, "
4100 "every_nth=%d%s\n"
4101 "delay=%d, ndelay=%d, max_luns=%d, q_completions=%d\n"
4102 "sector_size=%d bytes, cylinders=%d, heads=%d, sectors=%d\n"
4103 "command aborts=%d; RESETs: device=%d, target=%d, bus=%d, "
4104 "host=%d\ndix_reads=%d dix_writes=%d dif_errors=%d "
4105 "usec_in_jiffy=%lu\n",
4106 SCSI_DEBUG_VERSION, scsi_debug_version_date,
4107 scsi_debug_num_tgts, scsi_debug_dev_size_mb, scsi_debug_opts,
4108 scsi_debug_every_nth, b, scsi_debug_delay, scsi_debug_ndelay,
4109 scsi_debug_max_luns, atomic_read(&sdebug_completions),
4110 scsi_debug_sector_size, sdebug_cylinders_per, sdebug_heads,
4111 sdebug_sectors_per, num_aborts, num_dev_resets,
4112 num_target_resets, num_bus_resets, num_host_resets,
4113 dix_reads, dix_writes, dif_errors, TICK_NSEC / 1000);
4114
4115 f = find_first_bit(queued_in_use_bm, scsi_debug_max_queue);
4116 if (f != scsi_debug_max_queue) {
4117 l = find_last_bit(queued_in_use_bm, scsi_debug_max_queue);
4118 seq_printf(m, " %s BUSY: first,last bits set: %d,%d\n",
4119 "queued_in_use_bm", f, l);
4120 }
Al Viroc8ed5552013-03-31 01:46:06 -04004121 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004122}
4123
Akinobu Mita82069372013-10-14 22:48:04 +09004124static ssize_t delay_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004125{
4126 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_delay);
4127}
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004128/* Returns -EBUSY if delay is being changed and commands are queued */
Akinobu Mita82069372013-10-14 22:48:04 +09004129static ssize_t delay_store(struct device_driver *ddp, const char *buf,
4130 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004131{
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004132 int delay, res;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004133
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004134 if ((count > 0) && (1 == sscanf(buf, "%d", &delay))) {
4135 res = count;
4136 if (scsi_debug_delay != delay) {
4137 unsigned long iflags;
4138 int k;
4139
4140 spin_lock_irqsave(&queued_arr_lock, iflags);
4141 k = find_first_bit(queued_in_use_bm,
4142 scsi_debug_max_queue);
4143 if (k != scsi_debug_max_queue)
4144 res = -EBUSY; /* have queued commands */
4145 else {
4146 scsi_debug_delay = delay;
4147 scsi_debug_ndelay = 0;
4148 }
4149 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004150 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004151 return res;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004152 }
4153 return -EINVAL;
4154}
Akinobu Mita82069372013-10-14 22:48:04 +09004155static DRIVER_ATTR_RW(delay);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004156
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004157static ssize_t ndelay_show(struct device_driver *ddp, char *buf)
4158{
4159 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_ndelay);
4160}
4161/* Returns -EBUSY if ndelay is being changed and commands are queued */
4162/* If > 0 and accepted then scsi_debug_delay is set to DELAY_OVERRIDDEN */
4163static ssize_t ndelay_store(struct device_driver *ddp, const char *buf,
4164 size_t count)
4165{
4166 unsigned long iflags;
4167 int ndelay, res, k;
4168
4169 if ((count > 0) && (1 == sscanf(buf, "%d", &ndelay)) &&
4170 (ndelay >= 0) && (ndelay < 1000000000)) {
4171 res = count;
4172 if (scsi_debug_ndelay != ndelay) {
4173 spin_lock_irqsave(&queued_arr_lock, iflags);
4174 k = find_first_bit(queued_in_use_bm,
4175 scsi_debug_max_queue);
4176 if (k != scsi_debug_max_queue)
4177 res = -EBUSY; /* have queued commands */
4178 else {
4179 scsi_debug_ndelay = ndelay;
4180 scsi_debug_delay = ndelay ? DELAY_OVERRIDDEN
4181 : DEF_DELAY;
4182 }
4183 spin_unlock_irqrestore(&queued_arr_lock, iflags);
4184 }
4185 return res;
4186 }
4187 return -EINVAL;
4188}
4189static DRIVER_ATTR_RW(ndelay);
4190
Akinobu Mita82069372013-10-14 22:48:04 +09004191static ssize_t opts_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004192{
4193 return scnprintf(buf, PAGE_SIZE, "0x%x\n", scsi_debug_opts);
4194}
4195
Akinobu Mita82069372013-10-14 22:48:04 +09004196static ssize_t opts_store(struct device_driver *ddp, const char *buf,
4197 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004198{
4199 int opts;
4200 char work[20];
4201
4202 if (1 == sscanf(buf, "%10s", work)) {
Rasmus Villemoes48a96872014-10-13 15:54:44 -07004203 if (0 == strncasecmp(work,"0x", 2)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004204 if (1 == sscanf(&work[2], "%x", &opts))
4205 goto opts_done;
4206 } else {
4207 if (1 == sscanf(work, "%d", &opts))
4208 goto opts_done;
4209 }
4210 }
4211 return -EINVAL;
4212opts_done:
4213 scsi_debug_opts = opts;
Douglas Gilbert817fd662014-11-24 20:18:02 -05004214 if (SCSI_DEBUG_OPT_RECOVERED_ERR & opts)
4215 sdebug_any_injecting_opt = true;
4216 else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & opts)
4217 sdebug_any_injecting_opt = true;
4218 else if (SCSI_DEBUG_OPT_DIF_ERR & opts)
4219 sdebug_any_injecting_opt = true;
4220 else if (SCSI_DEBUG_OPT_DIX_ERR & opts)
4221 sdebug_any_injecting_opt = true;
4222 else if (SCSI_DEBUG_OPT_SHORT_TRANSFER & opts)
4223 sdebug_any_injecting_opt = true;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004224 atomic_set(&sdebug_cmnd_count, 0);
4225 atomic_set(&sdebug_a_tsf, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004226 return count;
4227}
Akinobu Mita82069372013-10-14 22:48:04 +09004228static DRIVER_ATTR_RW(opts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004229
Akinobu Mita82069372013-10-14 22:48:04 +09004230static ssize_t ptype_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004231{
4232 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_ptype);
4233}
Akinobu Mita82069372013-10-14 22:48:04 +09004234static ssize_t ptype_store(struct device_driver *ddp, const char *buf,
4235 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004236{
4237 int n;
4238
4239 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
4240 scsi_debug_ptype = n;
4241 return count;
4242 }
4243 return -EINVAL;
4244}
Akinobu Mita82069372013-10-14 22:48:04 +09004245static DRIVER_ATTR_RW(ptype);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004246
Akinobu Mita82069372013-10-14 22:48:04 +09004247static ssize_t dsense_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004248{
4249 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dsense);
4250}
Akinobu Mita82069372013-10-14 22:48:04 +09004251static ssize_t dsense_store(struct device_driver *ddp, const char *buf,
4252 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004253{
4254 int n;
4255
4256 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
4257 scsi_debug_dsense = n;
4258 return count;
4259 }
4260 return -EINVAL;
4261}
Akinobu Mita82069372013-10-14 22:48:04 +09004262static DRIVER_ATTR_RW(dsense);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004263
Akinobu Mita82069372013-10-14 22:48:04 +09004264static ssize_t fake_rw_show(struct device_driver *ddp, char *buf)
Douglas Gilbert23183912006-09-16 20:30:47 -04004265{
4266 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_fake_rw);
4267}
Akinobu Mita82069372013-10-14 22:48:04 +09004268static ssize_t fake_rw_store(struct device_driver *ddp, const char *buf,
4269 size_t count)
Douglas Gilbert23183912006-09-16 20:30:47 -04004270{
4271 int n;
4272
4273 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004274 n = (n > 0);
4275 scsi_debug_fake_rw = (scsi_debug_fake_rw > 0);
4276 if (scsi_debug_fake_rw != n) {
4277 if ((0 == n) && (NULL == fake_storep)) {
4278 unsigned long sz =
4279 (unsigned long)scsi_debug_dev_size_mb *
4280 1048576;
4281
4282 fake_storep = vmalloc(sz);
4283 if (NULL == fake_storep) {
4284 pr_err("%s: out of memory, 9\n",
4285 __func__);
4286 return -ENOMEM;
4287 }
4288 memset(fake_storep, 0, sz);
4289 }
4290 scsi_debug_fake_rw = n;
4291 }
Douglas Gilbert23183912006-09-16 20:30:47 -04004292 return count;
4293 }
4294 return -EINVAL;
4295}
Akinobu Mita82069372013-10-14 22:48:04 +09004296static DRIVER_ATTR_RW(fake_rw);
Douglas Gilbert23183912006-09-16 20:30:47 -04004297
Akinobu Mita82069372013-10-14 22:48:04 +09004298static ssize_t no_lun_0_show(struct device_driver *ddp, char *buf)
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004299{
4300 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_no_lun_0);
4301}
Akinobu Mita82069372013-10-14 22:48:04 +09004302static ssize_t no_lun_0_store(struct device_driver *ddp, const char *buf,
4303 size_t count)
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004304{
4305 int n;
4306
4307 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
4308 scsi_debug_no_lun_0 = n;
4309 return count;
4310 }
4311 return -EINVAL;
4312}
Akinobu Mita82069372013-10-14 22:48:04 +09004313static DRIVER_ATTR_RW(no_lun_0);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004314
Akinobu Mita82069372013-10-14 22:48:04 +09004315static ssize_t num_tgts_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004316{
4317 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_num_tgts);
4318}
Akinobu Mita82069372013-10-14 22:48:04 +09004319static ssize_t num_tgts_store(struct device_driver *ddp, const char *buf,
4320 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004321{
4322 int n;
4323
4324 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
4325 scsi_debug_num_tgts = n;
4326 sdebug_max_tgts_luns();
4327 return count;
4328 }
4329 return -EINVAL;
4330}
Akinobu Mita82069372013-10-14 22:48:04 +09004331static DRIVER_ATTR_RW(num_tgts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004332
Akinobu Mita82069372013-10-14 22:48:04 +09004333static ssize_t dev_size_mb_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004334{
4335 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dev_size_mb);
4336}
Akinobu Mita82069372013-10-14 22:48:04 +09004337static DRIVER_ATTR_RO(dev_size_mb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004338
Akinobu Mita82069372013-10-14 22:48:04 +09004339static ssize_t num_parts_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004340{
4341 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_num_parts);
4342}
Akinobu Mita82069372013-10-14 22:48:04 +09004343static DRIVER_ATTR_RO(num_parts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004344
Akinobu Mita82069372013-10-14 22:48:04 +09004345static ssize_t every_nth_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004346{
4347 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_every_nth);
4348}
Akinobu Mita82069372013-10-14 22:48:04 +09004349static ssize_t every_nth_store(struct device_driver *ddp, const char *buf,
4350 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004351{
4352 int nth;
4353
4354 if ((count > 0) && (1 == sscanf(buf, "%d", &nth))) {
4355 scsi_debug_every_nth = nth;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004356 atomic_set(&sdebug_cmnd_count, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004357 return count;
4358 }
4359 return -EINVAL;
4360}
Akinobu Mita82069372013-10-14 22:48:04 +09004361static DRIVER_ATTR_RW(every_nth);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004362
Akinobu Mita82069372013-10-14 22:48:04 +09004363static ssize_t max_luns_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004364{
4365 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_max_luns);
4366}
Akinobu Mita82069372013-10-14 22:48:04 +09004367static ssize_t max_luns_store(struct device_driver *ddp, const char *buf,
4368 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004369{
4370 int n;
4371
4372 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
4373 scsi_debug_max_luns = n;
4374 sdebug_max_tgts_luns();
4375 return count;
4376 }
4377 return -EINVAL;
4378}
Akinobu Mita82069372013-10-14 22:48:04 +09004379static DRIVER_ATTR_RW(max_luns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004380
Akinobu Mita82069372013-10-14 22:48:04 +09004381static ssize_t max_queue_show(struct device_driver *ddp, char *buf)
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004382{
4383 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_max_queue);
4384}
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004385/* N.B. max_queue can be changed while there are queued commands. In flight
4386 * commands beyond the new max_queue will be completed. */
Akinobu Mita82069372013-10-14 22:48:04 +09004387static ssize_t max_queue_store(struct device_driver *ddp, const char *buf,
4388 size_t count)
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004389{
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004390 unsigned long iflags;
4391 int n, k;
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004392
4393 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n > 0) &&
4394 (n <= SCSI_DEBUG_CANQUEUE)) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004395 spin_lock_irqsave(&queued_arr_lock, iflags);
4396 k = find_last_bit(queued_in_use_bm, SCSI_DEBUG_CANQUEUE);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004397 scsi_debug_max_queue = n;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004398 if (SCSI_DEBUG_CANQUEUE == k)
4399 atomic_set(&retired_max_queue, 0);
4400 else if (k >= n)
4401 atomic_set(&retired_max_queue, k + 1);
4402 else
4403 atomic_set(&retired_max_queue, 0);
4404 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004405 return count;
4406 }
4407 return -EINVAL;
4408}
Akinobu Mita82069372013-10-14 22:48:04 +09004409static DRIVER_ATTR_RW(max_queue);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004410
Akinobu Mita82069372013-10-14 22:48:04 +09004411static ssize_t no_uld_show(struct device_driver *ddp, char *buf)
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004412{
4413 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_no_uld);
4414}
Akinobu Mita82069372013-10-14 22:48:04 +09004415static DRIVER_ATTR_RO(no_uld);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004416
Akinobu Mita82069372013-10-14 22:48:04 +09004417static ssize_t scsi_level_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004418{
4419 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_scsi_level);
4420}
Akinobu Mita82069372013-10-14 22:48:04 +09004421static DRIVER_ATTR_RO(scsi_level);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004422
Akinobu Mita82069372013-10-14 22:48:04 +09004423static ssize_t virtual_gb_show(struct device_driver *ddp, char *buf)
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004424{
4425 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_virtual_gb);
4426}
Akinobu Mita82069372013-10-14 22:48:04 +09004427static ssize_t virtual_gb_store(struct device_driver *ddp, const char *buf,
4428 size_t count)
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004429{
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05004430 int n;
Douglas Gilbert0d01c5d2014-11-24 20:27:51 -05004431 bool changed;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004432
4433 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
Douglas Gilbert0d01c5d2014-11-24 20:27:51 -05004434 changed = (scsi_debug_virtual_gb != n);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004435 scsi_debug_virtual_gb = n;
FUJITA Tomonori28898872008-03-30 00:59:55 +09004436 sdebug_capacity = get_sdebug_capacity();
Douglas Gilbert0d01c5d2014-11-24 20:27:51 -05004437 if (changed) {
4438 struct sdebug_host_info *sdhp;
4439 struct sdebug_dev_info *dp;
FUJITA Tomonori28898872008-03-30 00:59:55 +09004440
Ewan D. Milne4bc6b632014-12-04 11:49:26 -05004441 spin_lock(&sdebug_host_list_lock);
Douglas Gilbert0d01c5d2014-11-24 20:27:51 -05004442 list_for_each_entry(sdhp, &sdebug_host_list,
4443 host_list) {
4444 list_for_each_entry(dp, &sdhp->dev_info_list,
4445 dev_list) {
4446 set_bit(SDEBUG_UA_CAPACITY_CHANGED,
4447 dp->uas_bm);
4448 }
4449 }
Ewan D. Milne4bc6b632014-12-04 11:49:26 -05004450 spin_unlock(&sdebug_host_list_lock);
Douglas Gilbert0d01c5d2014-11-24 20:27:51 -05004451 }
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004452 return count;
4453 }
4454 return -EINVAL;
4455}
Akinobu Mita82069372013-10-14 22:48:04 +09004456static DRIVER_ATTR_RW(virtual_gb);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004457
Akinobu Mita82069372013-10-14 22:48:04 +09004458static ssize_t add_host_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004459{
4460 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_add_host);
4461}
4462
Akinobu Mita82069372013-10-14 22:48:04 +09004463static ssize_t add_host_store(struct device_driver *ddp, const char *buf,
4464 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004465{
FUJITA Tomonorif3df41c2008-03-20 11:09:15 +09004466 int delta_hosts;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004467
FUJITA Tomonorif3df41c2008-03-20 11:09:15 +09004468 if (sscanf(buf, "%d", &delta_hosts) != 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004469 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004470 if (delta_hosts > 0) {
4471 do {
4472 sdebug_add_adapter();
4473 } while (--delta_hosts);
4474 } else if (delta_hosts < 0) {
4475 do {
4476 sdebug_remove_adapter();
4477 } while (++delta_hosts);
4478 }
4479 return count;
4480}
Akinobu Mita82069372013-10-14 22:48:04 +09004481static DRIVER_ATTR_RW(add_host);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004482
Akinobu Mita82069372013-10-14 22:48:04 +09004483static ssize_t vpd_use_hostno_show(struct device_driver *ddp, char *buf)
Douglas Gilbert23183912006-09-16 20:30:47 -04004484{
4485 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_vpd_use_hostno);
4486}
Akinobu Mita82069372013-10-14 22:48:04 +09004487static ssize_t vpd_use_hostno_store(struct device_driver *ddp, const char *buf,
4488 size_t count)
Douglas Gilbert23183912006-09-16 20:30:47 -04004489{
4490 int n;
4491
4492 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
4493 scsi_debug_vpd_use_hostno = n;
4494 return count;
4495 }
4496 return -EINVAL;
4497}
Akinobu Mita82069372013-10-14 22:48:04 +09004498static DRIVER_ATTR_RW(vpd_use_hostno);
Douglas Gilbert23183912006-09-16 20:30:47 -04004499
Akinobu Mita82069372013-10-14 22:48:04 +09004500static ssize_t sector_size_show(struct device_driver *ddp, char *buf)
Martin K. Petersen597136a2008-06-05 00:12:59 -04004501{
4502 return scnprintf(buf, PAGE_SIZE, "%u\n", scsi_debug_sector_size);
4503}
Akinobu Mita82069372013-10-14 22:48:04 +09004504static DRIVER_ATTR_RO(sector_size);
Martin K. Petersen597136a2008-06-05 00:12:59 -04004505
Akinobu Mita82069372013-10-14 22:48:04 +09004506static ssize_t dix_show(struct device_driver *ddp, char *buf)
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004507{
4508 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dix);
4509}
Akinobu Mita82069372013-10-14 22:48:04 +09004510static DRIVER_ATTR_RO(dix);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004511
Akinobu Mita82069372013-10-14 22:48:04 +09004512static ssize_t dif_show(struct device_driver *ddp, char *buf)
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004513{
4514 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dif);
4515}
Akinobu Mita82069372013-10-14 22:48:04 +09004516static DRIVER_ATTR_RO(dif);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004517
Akinobu Mita82069372013-10-14 22:48:04 +09004518static ssize_t guard_show(struct device_driver *ddp, char *buf)
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004519{
Akinobu Mita68aee7b2013-09-18 21:27:27 +09004520 return scnprintf(buf, PAGE_SIZE, "%u\n", scsi_debug_guard);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004521}
Akinobu Mita82069372013-10-14 22:48:04 +09004522static DRIVER_ATTR_RO(guard);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004523
Akinobu Mita82069372013-10-14 22:48:04 +09004524static ssize_t ato_show(struct device_driver *ddp, char *buf)
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004525{
4526 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_ato);
4527}
Akinobu Mita82069372013-10-14 22:48:04 +09004528static DRIVER_ATTR_RO(ato);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004529
Akinobu Mita82069372013-10-14 22:48:04 +09004530static ssize_t map_show(struct device_driver *ddp, char *buf)
Martin K. Petersen44d92692009-10-15 14:45:27 -04004531{
4532 ssize_t count;
4533
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004534 if (!scsi_debug_lbp())
Martin K. Petersen44d92692009-10-15 14:45:27 -04004535 return scnprintf(buf, PAGE_SIZE, "0-%u\n",
4536 sdebug_store_sectors);
4537
4538 count = bitmap_scnlistprintf(buf, PAGE_SIZE, map_storep, map_size);
4539
4540 buf[count++] = '\n';
4541 buf[count++] = 0;
4542
4543 return count;
4544}
Akinobu Mita82069372013-10-14 22:48:04 +09004545static DRIVER_ATTR_RO(map);
Martin K. Petersen44d92692009-10-15 14:45:27 -04004546
Akinobu Mita82069372013-10-14 22:48:04 +09004547static ssize_t removable_show(struct device_driver *ddp, char *buf)
Martin Pittd9867882012-09-06 12:04:33 +02004548{
4549 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_removable ? 1 : 0);
4550}
Akinobu Mita82069372013-10-14 22:48:04 +09004551static ssize_t removable_store(struct device_driver *ddp, const char *buf,
4552 size_t count)
Martin Pittd9867882012-09-06 12:04:33 +02004553{
4554 int n;
4555
4556 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
4557 scsi_debug_removable = (n > 0);
4558 return count;
4559 }
4560 return -EINVAL;
4561}
Akinobu Mita82069372013-10-14 22:48:04 +09004562static DRIVER_ATTR_RW(removable);
Martin Pittd9867882012-09-06 12:04:33 +02004563
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004564static ssize_t host_lock_show(struct device_driver *ddp, char *buf)
4565{
4566 return scnprintf(buf, PAGE_SIZE, "%d\n", !!scsi_debug_host_lock);
4567}
4568/* Returns -EBUSY if host_lock is being changed and commands are queued */
4569static ssize_t host_lock_store(struct device_driver *ddp, const char *buf,
4570 size_t count)
4571{
4572 int n, res;
4573
4574 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
4575 bool new_host_lock = (n > 0);
4576
4577 res = count;
4578 if (new_host_lock != scsi_debug_host_lock) {
4579 unsigned long iflags;
4580 int k;
4581
4582 spin_lock_irqsave(&queued_arr_lock, iflags);
4583 k = find_first_bit(queued_in_use_bm,
4584 scsi_debug_max_queue);
4585 if (k != scsi_debug_max_queue)
4586 res = -EBUSY; /* have queued commands */
4587 else
4588 scsi_debug_host_lock = new_host_lock;
4589 spin_unlock_irqrestore(&queued_arr_lock, iflags);
4590 }
4591 return res;
4592 }
4593 return -EINVAL;
4594}
4595static DRIVER_ATTR_RW(host_lock);
4596
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05004597static ssize_t strict_show(struct device_driver *ddp, char *buf)
4598{
4599 return scnprintf(buf, PAGE_SIZE, "%d\n", !!scsi_debug_strict);
4600}
4601static ssize_t strict_store(struct device_driver *ddp, const char *buf,
4602 size_t count)
4603{
4604 int n;
4605
4606 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
4607 scsi_debug_strict = (n > 0);
4608 return count;
4609 }
4610 return -EINVAL;
4611}
4612static DRIVER_ATTR_RW(strict);
4613
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004614
Akinobu Mita82069372013-10-14 22:48:04 +09004615/* Note: The following array creates attribute files in the
Douglas Gilbert23183912006-09-16 20:30:47 -04004616 /sys/bus/pseudo/drivers/scsi_debug directory. The advantage of these
4617 files (over those found in the /sys/module/scsi_debug/parameters
4618 directory) is that auxiliary actions can be triggered when an attribute
4619 is changed. For example see: sdebug_add_host_store() above.
4620 */
Randy Dunlap6ecaff72006-07-11 20:53:22 -07004621
Akinobu Mita82069372013-10-14 22:48:04 +09004622static struct attribute *sdebug_drv_attrs[] = {
4623 &driver_attr_delay.attr,
4624 &driver_attr_opts.attr,
4625 &driver_attr_ptype.attr,
4626 &driver_attr_dsense.attr,
4627 &driver_attr_fake_rw.attr,
4628 &driver_attr_no_lun_0.attr,
4629 &driver_attr_num_tgts.attr,
4630 &driver_attr_dev_size_mb.attr,
4631 &driver_attr_num_parts.attr,
4632 &driver_attr_every_nth.attr,
4633 &driver_attr_max_luns.attr,
4634 &driver_attr_max_queue.attr,
4635 &driver_attr_no_uld.attr,
4636 &driver_attr_scsi_level.attr,
4637 &driver_attr_virtual_gb.attr,
4638 &driver_attr_add_host.attr,
4639 &driver_attr_vpd_use_hostno.attr,
4640 &driver_attr_sector_size.attr,
4641 &driver_attr_dix.attr,
4642 &driver_attr_dif.attr,
4643 &driver_attr_guard.attr,
4644 &driver_attr_ato.attr,
4645 &driver_attr_map.attr,
4646 &driver_attr_removable.attr,
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004647 &driver_attr_host_lock.attr,
4648 &driver_attr_ndelay.attr,
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05004649 &driver_attr_strict.attr,
Akinobu Mita82069372013-10-14 22:48:04 +09004650 NULL,
4651};
4652ATTRIBUTE_GROUPS(sdebug_drv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004653
Akinobu Mita11ddcec2014-02-26 22:56:59 +09004654static struct device *pseudo_primary;
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09004655
Linus Torvalds1da177e2005-04-16 15:20:36 -07004656static int __init scsi_debug_init(void)
4657{
FUJITA Tomonori5f2578e2008-03-30 00:59:57 +09004658 unsigned long sz;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004659 int host_to_add;
4660 int k;
Randy Dunlap6ecaff72006-07-11 20:53:22 -07004661 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004662
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004663 atomic_set(&sdebug_cmnd_count, 0);
4664 atomic_set(&sdebug_completions, 0);
4665 atomic_set(&retired_max_queue, 0);
4666
4667 if (scsi_debug_ndelay >= 1000000000) {
4668 pr_warn("%s: ndelay must be less than 1 second, ignored\n",
4669 __func__);
4670 scsi_debug_ndelay = 0;
4671 } else if (scsi_debug_ndelay > 0)
4672 scsi_debug_delay = DELAY_OVERRIDDEN;
4673
Martin K. Petersen597136a2008-06-05 00:12:59 -04004674 switch (scsi_debug_sector_size) {
4675 case 512:
4676 case 1024:
4677 case 2048:
4678 case 4096:
4679 break;
4680 default:
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004681 pr_err("%s: invalid sector_size %d\n", __func__,
Martin K. Petersen597136a2008-06-05 00:12:59 -04004682 scsi_debug_sector_size);
4683 return -EINVAL;
4684 }
4685
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004686 switch (scsi_debug_dif) {
4687
4688 case SD_DIF_TYPE0_PROTECTION:
4689 case SD_DIF_TYPE1_PROTECTION:
Martin K. Petersen395cef02009-09-18 17:33:03 -04004690 case SD_DIF_TYPE2_PROTECTION:
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004691 case SD_DIF_TYPE3_PROTECTION:
4692 break;
4693
4694 default:
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004695 pr_err("%s: dif must be 0, 1, 2 or 3\n", __func__);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004696 return -EINVAL;
4697 }
4698
4699 if (scsi_debug_guard > 1) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004700 pr_err("%s: guard must be 0 or 1\n", __func__);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004701 return -EINVAL;
4702 }
4703
4704 if (scsi_debug_ato > 1) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004705 pr_err("%s: ato must be 0 or 1\n", __func__);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004706 return -EINVAL;
4707 }
4708
Martin K. Petersenea61fca2009-05-15 00:40:33 -04004709 if (scsi_debug_physblk_exp > 15) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004710 pr_err("%s: invalid physblk_exp %u\n", __func__,
Martin K. Petersenea61fca2009-05-15 00:40:33 -04004711 scsi_debug_physblk_exp);
4712 return -EINVAL;
4713 }
4714
4715 if (scsi_debug_lowest_aligned > 0x3fff) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004716 pr_err("%s: lowest_aligned too big: %u\n", __func__,
Martin K. Petersenea61fca2009-05-15 00:40:33 -04004717 scsi_debug_lowest_aligned);
4718 return -EINVAL;
4719 }
4720
Linus Torvalds1da177e2005-04-16 15:20:36 -07004721 if (scsi_debug_dev_size_mb < 1)
4722 scsi_debug_dev_size_mb = 1; /* force minimum 1 MB ramdisk */
FUJITA Tomonori5f2578e2008-03-30 00:59:57 +09004723 sz = (unsigned long)scsi_debug_dev_size_mb * 1048576;
Martin K. Petersen597136a2008-06-05 00:12:59 -04004724 sdebug_store_sectors = sz / scsi_debug_sector_size;
FUJITA Tomonori28898872008-03-30 00:59:55 +09004725 sdebug_capacity = get_sdebug_capacity();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004726
4727 /* play around with geometry, don't waste too much on track 0 */
4728 sdebug_heads = 8;
4729 sdebug_sectors_per = 32;
4730 if (scsi_debug_dev_size_mb >= 16)
4731 sdebug_heads = 32;
4732 else if (scsi_debug_dev_size_mb >= 256)
4733 sdebug_heads = 64;
4734 sdebug_cylinders_per = (unsigned long)sdebug_capacity /
4735 (sdebug_sectors_per * sdebug_heads);
4736 if (sdebug_cylinders_per >= 1024) {
4737 /* other LLDs do this; implies >= 1GB ram disk ... */
4738 sdebug_heads = 255;
4739 sdebug_sectors_per = 63;
4740 sdebug_cylinders_per = (unsigned long)sdebug_capacity /
4741 (sdebug_sectors_per * sdebug_heads);
4742 }
4743
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004744 if (0 == scsi_debug_fake_rw) {
4745 fake_storep = vmalloc(sz);
4746 if (NULL == fake_storep) {
4747 pr_err("%s: out of memory, 1\n", __func__);
4748 return -ENOMEM;
4749 }
4750 memset(fake_storep, 0, sz);
4751 if (scsi_debug_num_parts > 0)
4752 sdebug_build_parts(fake_storep, sz);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004753 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004754
Akinobu Mita7cb69d02013-06-29 17:59:16 +09004755 if (scsi_debug_dix) {
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004756 int dif_size;
4757
4758 dif_size = sdebug_store_sectors * sizeof(struct sd_dif_tuple);
4759 dif_storep = vmalloc(dif_size);
4760
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004761 pr_err("%s: dif_storep %u bytes @ %p\n", __func__, dif_size,
4762 dif_storep);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004763
4764 if (dif_storep == NULL) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004765 pr_err("%s: out of mem. (DIX)\n", __func__);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004766 ret = -ENOMEM;
4767 goto free_vm;
4768 }
4769
4770 memset(dif_storep, 0xff, dif_size);
4771 }
4772
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004773 /* Logical Block Provisioning */
4774 if (scsi_debug_lbp()) {
Martin K. Petersen60147592010-08-19 11:49:00 -04004775 scsi_debug_unmap_max_blocks =
4776 clamp(scsi_debug_unmap_max_blocks, 0U, 0xffffffffU);
4777
4778 scsi_debug_unmap_max_desc =
4779 clamp(scsi_debug_unmap_max_desc, 0U, 256U);
4780
4781 scsi_debug_unmap_granularity =
4782 clamp(scsi_debug_unmap_granularity, 1U, 0xffffffffU);
4783
4784 if (scsi_debug_unmap_alignment &&
Akinobu Mitaac170782013-04-16 22:11:56 +09004785 scsi_debug_unmap_granularity <=
4786 scsi_debug_unmap_alignment) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004787 pr_err("%s: ERR: unmap_granularity <= unmap_alignment\n",
Martin K. Petersen44d92692009-10-15 14:45:27 -04004788 __func__);
4789 return -EINVAL;
4790 }
4791
Akinobu Mitab90ebc32013-04-16 22:11:58 +09004792 map_size = lba_to_map_index(sdebug_store_sectors - 1) + 1;
4793 map_storep = vmalloc(BITS_TO_LONGS(map_size) * sizeof(long));
Martin K. Petersen44d92692009-10-15 14:45:27 -04004794
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004795 pr_info("%s: %lu provisioning blocks\n", __func__, map_size);
Martin K. Petersen44d92692009-10-15 14:45:27 -04004796
4797 if (map_storep == NULL) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004798 pr_err("%s: out of mem. (MAP)\n", __func__);
Martin K. Petersen44d92692009-10-15 14:45:27 -04004799 ret = -ENOMEM;
4800 goto free_vm;
4801 }
4802
Akinobu Mitab90ebc32013-04-16 22:11:58 +09004803 bitmap_zero(map_storep, map_size);
Martin K. Petersen44d92692009-10-15 14:45:27 -04004804
4805 /* Map first 1KB for partition table */
4806 if (scsi_debug_num_parts)
4807 map_region(0, 2);
4808 }
4809
Nicholas Bellinger9b906772010-09-06 17:24:28 -07004810 pseudo_primary = root_device_register("pseudo_0");
4811 if (IS_ERR(pseudo_primary)) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004812 pr_warn("%s: root_device_register() error\n", __func__);
Nicholas Bellinger9b906772010-09-06 17:24:28 -07004813 ret = PTR_ERR(pseudo_primary);
Randy Dunlap6ecaff72006-07-11 20:53:22 -07004814 goto free_vm;
4815 }
4816 ret = bus_register(&pseudo_lld_bus);
4817 if (ret < 0) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004818 pr_warn("%s: bus_register error: %d\n", __func__, ret);
Randy Dunlap6ecaff72006-07-11 20:53:22 -07004819 goto dev_unreg;
4820 }
4821 ret = driver_register(&sdebug_driverfs_driver);
4822 if (ret < 0) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004823 pr_warn("%s: driver_register error: %d\n", __func__, ret);
Randy Dunlap6ecaff72006-07-11 20:53:22 -07004824 goto bus_unreg;
4825 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004826
Linus Torvalds1da177e2005-04-16 15:20:36 -07004827 host_to_add = scsi_debug_add_host;
4828 scsi_debug_add_host = 0;
4829
4830 for (k = 0; k < host_to_add; k++) {
4831 if (sdebug_add_adapter()) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004832 pr_err("%s: sdebug_add_adapter failed k=%d\n",
4833 __func__, k);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004834 break;
4835 }
4836 }
4837
4838 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004839 pr_info("%s: built %d host(s)\n", __func__,
4840 scsi_debug_add_host);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004841 }
4842 return 0;
Randy Dunlap6ecaff72006-07-11 20:53:22 -07004843
Randy Dunlap6ecaff72006-07-11 20:53:22 -07004844bus_unreg:
4845 bus_unregister(&pseudo_lld_bus);
4846dev_unreg:
Nicholas Bellinger9b906772010-09-06 17:24:28 -07004847 root_device_unregister(pseudo_primary);
Randy Dunlap6ecaff72006-07-11 20:53:22 -07004848free_vm:
Martin K. Petersen44d92692009-10-15 14:45:27 -04004849 if (map_storep)
4850 vfree(map_storep);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004851 if (dif_storep)
4852 vfree(dif_storep);
Randy Dunlap6ecaff72006-07-11 20:53:22 -07004853 vfree(fake_storep);
4854
4855 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004856}
4857
4858static void __exit scsi_debug_exit(void)
4859{
4860 int k = scsi_debug_add_host;
4861
4862 stop_all_queued();
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004863 free_all_queued();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004864 for (; k; k--)
4865 sdebug_remove_adapter();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004866 driver_unregister(&sdebug_driverfs_driver);
4867 bus_unregister(&pseudo_lld_bus);
Nicholas Bellinger9b906772010-09-06 17:24:28 -07004868 root_device_unregister(pseudo_primary);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004869
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004870 if (dif_storep)
4871 vfree(dif_storep);
4872
Linus Torvalds1da177e2005-04-16 15:20:36 -07004873 vfree(fake_storep);
4874}
4875
4876device_initcall(scsi_debug_init);
4877module_exit(scsi_debug_exit);
4878
Linus Torvalds1da177e2005-04-16 15:20:36 -07004879static void sdebug_release_adapter(struct device * dev)
4880{
4881 struct sdebug_host_info *sdbg_host;
4882
4883 sdbg_host = to_sdebug_host(dev);
4884 kfree(sdbg_host);
4885}
4886
4887static int sdebug_add_adapter(void)
4888{
4889 int k, devs_per_host;
4890 int error = 0;
4891 struct sdebug_host_info *sdbg_host;
FUJITA Tomonori8b40228f2008-03-20 11:09:18 +09004892 struct sdebug_dev_info *sdbg_devinfo, *tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004893
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004894 sdbg_host = kzalloc(sizeof(*sdbg_host),GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004895 if (NULL == sdbg_host) {
4896 printk(KERN_ERR "%s: out of memory at line %d\n",
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07004897 __func__, __LINE__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004898 return -ENOMEM;
4899 }
4900
Linus Torvalds1da177e2005-04-16 15:20:36 -07004901 INIT_LIST_HEAD(&sdbg_host->dev_info_list);
4902
4903 devs_per_host = scsi_debug_num_tgts * scsi_debug_max_luns;
4904 for (k = 0; k < devs_per_host; k++) {
FUJITA Tomonori5cb2fc02008-03-20 11:09:16 +09004905 sdbg_devinfo = sdebug_device_create(sdbg_host, GFP_KERNEL);
4906 if (!sdbg_devinfo) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004907 printk(KERN_ERR "%s: out of memory at line %d\n",
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07004908 __func__, __LINE__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004909 error = -ENOMEM;
4910 goto clean;
4911 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004912 }
4913
4914 spin_lock(&sdebug_host_list_lock);
4915 list_add_tail(&sdbg_host->host_list, &sdebug_host_list);
4916 spin_unlock(&sdebug_host_list_lock);
4917
4918 sdbg_host->dev.bus = &pseudo_lld_bus;
Nicholas Bellinger9b906772010-09-06 17:24:28 -07004919 sdbg_host->dev.parent = pseudo_primary;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004920 sdbg_host->dev.release = &sdebug_release_adapter;
Kay Sievers71610f52008-12-03 22:41:36 +01004921 dev_set_name(&sdbg_host->dev, "adapter%d", scsi_debug_add_host);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004922
4923 error = device_register(&sdbg_host->dev);
4924
4925 if (error)
4926 goto clean;
4927
4928 ++scsi_debug_add_host;
4929 return error;
4930
4931clean:
FUJITA Tomonori8b40228f2008-03-20 11:09:18 +09004932 list_for_each_entry_safe(sdbg_devinfo, tmp, &sdbg_host->dev_info_list,
4933 dev_list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004934 list_del(&sdbg_devinfo->dev_list);
4935 kfree(sdbg_devinfo);
4936 }
4937
4938 kfree(sdbg_host);
4939 return error;
4940}
4941
4942static void sdebug_remove_adapter(void)
4943{
4944 struct sdebug_host_info * sdbg_host = NULL;
4945
4946 spin_lock(&sdebug_host_list_lock);
4947 if (!list_empty(&sdebug_host_list)) {
4948 sdbg_host = list_entry(sdebug_host_list.prev,
4949 struct sdebug_host_info, host_list);
4950 list_del(&sdbg_host->host_list);
4951 }
4952 spin_unlock(&sdebug_host_list_lock);
4953
4954 if (!sdbg_host)
4955 return;
4956
4957 device_unregister(&sdbg_host->dev);
4958 --scsi_debug_add_host;
4959}
4960
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004961static int
Christoph Hellwigdb5ed4d2014-11-13 15:08:42 +01004962sdebug_change_qdepth(struct scsi_device *sdev, int qdepth)
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004963{
4964 int num_in_q = 0;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004965 unsigned long iflags;
4966 struct sdebug_dev_info *devip;
4967
4968 spin_lock_irqsave(&queued_arr_lock, iflags);
4969 devip = (struct sdebug_dev_info *)sdev->hostdata;
4970 if (NULL == devip) {
4971 spin_unlock_irqrestore(&queued_arr_lock, iflags);
4972 return -ENODEV;
4973 }
4974 num_in_q = atomic_read(&devip->num_in_q);
4975 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004976
Christoph Hellwigc40ecc12014-11-13 14:25:11 +01004977 if (qdepth < 1)
4978 qdepth = 1;
4979 /* allow to exceed max host queued_arr elements for testing */
4980 if (qdepth > SCSI_DEBUG_CANQUEUE + 10)
4981 qdepth = SCSI_DEBUG_CANQUEUE + 10;
Christoph Hellwigdb5ed4d2014-11-13 15:08:42 +01004982 scsi_change_queue_depth(sdev, qdepth);
Christoph Hellwigc40ecc12014-11-13 14:25:11 +01004983
4984 if (SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts) {
4985 sdev_printk(KERN_INFO, sdev,
4986 "%s: qdepth=%d, num_in_q=%d\n",
4987 __func__, qdepth, num_in_q);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004988 }
4989 return sdev->queue_depth;
4990}
4991
4992static int
Douglas Gilbert817fd662014-11-24 20:18:02 -05004993check_inject(struct scsi_cmnd *scp)
4994{
4995 struct sdebug_scmd_extra_t *ep = scsi_cmd_priv(scp);
4996
4997 memset(ep, 0, sizeof(struct sdebug_scmd_extra_t));
4998
4999 if (atomic_inc_return(&sdebug_cmnd_count) >=
5000 abs(scsi_debug_every_nth)) {
5001 atomic_set(&sdebug_cmnd_count, 0);
5002 if (scsi_debug_every_nth < -1)
5003 scsi_debug_every_nth = -1;
5004 if (SCSI_DEBUG_OPT_TIMEOUT & scsi_debug_opts)
5005 return 1; /* ignore command causing timeout */
5006 else if (SCSI_DEBUG_OPT_MAC_TIMEOUT & scsi_debug_opts &&
5007 scsi_medium_access_command(scp))
5008 return 1; /* time out reads and writes */
5009 if (sdebug_any_injecting_opt) {
5010 int opts = scsi_debug_opts;
5011
5012 if (SCSI_DEBUG_OPT_RECOVERED_ERR & opts)
5013 ep->inj_recovered = true;
5014 else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & opts)
5015 ep->inj_transport = true;
5016 else if (SCSI_DEBUG_OPT_DIF_ERR & opts)
5017 ep->inj_dif = true;
5018 else if (SCSI_DEBUG_OPT_DIX_ERR & opts)
5019 ep->inj_dix = true;
5020 else if (SCSI_DEBUG_OPT_SHORT_TRANSFER & opts)
5021 ep->inj_short = true;
5022 }
5023 }
5024 return 0;
5025}
5026
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05005027static int
5028scsi_debug_queuecommand(struct scsi_cmnd *scp)
5029{
5030 u8 sdeb_i;
5031 struct scsi_device *sdp = scp->device;
5032 const struct opcode_info_t *oip;
5033 const struct opcode_info_t *r_oip;
5034 struct sdebug_dev_info *devip;
5035 u8 *cmd = scp->cmnd;
5036 int (*r_pfp)(struct scsi_cmnd *, struct sdebug_dev_info *);
5037 int k, na;
5038 int errsts = 0;
5039 int errsts_no_connect = DID_NO_CONNECT << 16;
5040 u32 flags;
5041 u16 sa;
5042 u8 opcode = cmd[0];
5043 bool has_wlun_rl;
5044 bool debug = !!(SCSI_DEBUG_OPT_NOISE & scsi_debug_opts);
5045
5046 scsi_set_resid(scp, 0);
5047 if (debug && !(SCSI_DEBUG_OPT_NO_CDB_NOISE & scsi_debug_opts)) {
5048 char b[120];
5049 int n, len, sb;
5050
5051 len = scp->cmd_len;
5052 sb = (int)sizeof(b);
5053 if (len > 32)
5054 strcpy(b, "too long, over 32 bytes");
5055 else {
5056 for (k = 0, n = 0; k < len && n < sb; ++k)
5057 n += scnprintf(b + n, sb - n, "%02x ",
5058 (u32)cmd[k]);
5059 }
5060 sdev_printk(KERN_INFO, sdp, "%s: cmd %s\n", my_name, b);
5061 }
5062 has_wlun_rl = (sdp->lun == SAM2_WLUN_REPORT_LUNS);
5063 if ((sdp->lun >= scsi_debug_max_luns) && !has_wlun_rl)
5064 return schedule_resp(scp, NULL, errsts_no_connect, 0);
5065
5066 sdeb_i = opcode_ind_arr[opcode]; /* fully mapped */
5067 oip = &opcode_info_arr[sdeb_i]; /* safe if table consistent */
5068 devip = (struct sdebug_dev_info *)sdp->hostdata;
5069 if (!devip) {
5070 devip = devInfoReg(sdp);
5071 if (NULL == devip)
5072 return schedule_resp(scp, NULL, errsts_no_connect, 0);
5073 }
5074 na = oip->num_attached;
5075 r_pfp = oip->pfp;
5076 if (na) { /* multiple commands with this opcode */
5077 r_oip = oip;
5078 if (FF_SA & r_oip->flags) {
5079 if (F_SA_LOW & oip->flags)
5080 sa = 0x1f & cmd[1];
5081 else
5082 sa = get_unaligned_be16(cmd + 8);
5083 for (k = 0; k <= na; oip = r_oip->arrp + k++) {
5084 if (opcode == oip->opcode && sa == oip->sa)
5085 break;
5086 }
5087 } else { /* since no service action only check opcode */
5088 for (k = 0; k <= na; oip = r_oip->arrp + k++) {
5089 if (opcode == oip->opcode)
5090 break;
5091 }
5092 }
5093 if (k > na) {
5094 if (F_SA_LOW & r_oip->flags)
5095 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 1, 4);
5096 else if (F_SA_HIGH & r_oip->flags)
5097 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 8, 7);
5098 else
5099 mk_sense_invalid_opcode(scp);
5100 goto check_cond;
5101 }
5102 } /* else (when na==0) we assume the oip is a match */
5103 flags = oip->flags;
5104 if (F_INV_OP & flags) {
5105 mk_sense_invalid_opcode(scp);
5106 goto check_cond;
5107 }
5108 if (has_wlun_rl && !(F_RL_WLUN_OK & flags)) {
5109 if (debug)
5110 sdev_printk(KERN_INFO, sdp, "scsi_debug: Opcode: "
5111 "0x%x not supported for wlun\n", opcode);
5112 mk_sense_invalid_opcode(scp);
5113 goto check_cond;
5114 }
5115 if (scsi_debug_strict) { /* check cdb against mask */
5116 u8 rem;
5117 int j;
5118
5119 for (k = 1; k < oip->len_mask[0] && k < 16; ++k) {
5120 rem = ~oip->len_mask[k] & cmd[k];
5121 if (rem) {
5122 for (j = 7; j >= 0; --j, rem <<= 1) {
5123 if (0x80 & rem)
5124 break;
5125 }
5126 mk_sense_invalid_fld(scp, SDEB_IN_CDB, k, j);
5127 goto check_cond;
5128 }
5129 }
5130 }
5131 if (!(F_SKIP_UA & flags) &&
5132 SDEBUG_NUM_UAS != find_first_bit(devip->uas_bm, SDEBUG_NUM_UAS)) {
5133 errsts = check_readiness(scp, UAS_ONLY, devip);
5134 if (errsts)
5135 goto check_cond;
5136 }
5137 if ((F_M_ACCESS & flags) && devip->stopped) {
5138 mk_sense_buffer(scp, NOT_READY, LOGICAL_UNIT_NOT_READY, 0x2);
5139 if (debug)
5140 sdev_printk(KERN_INFO, sdp, "%s reports: Not ready: "
5141 "%s\n", my_name, "initializing command "
5142 "required");
5143 errsts = check_condition_result;
5144 goto fini;
5145 }
5146 if (scsi_debug_fake_rw && (F_FAKE_RW & flags))
5147 goto fini;
5148 if (scsi_debug_every_nth) {
5149 if (check_inject(scp))
5150 return 0; /* ignore command: make trouble */
5151 }
5152 if (oip->pfp) /* if this command has a resp_* function, call it */
5153 errsts = oip->pfp(scp, devip);
5154 else if (r_pfp) /* if leaf function ptr NULL, try the root's */
5155 errsts = r_pfp(scp, devip);
5156
5157fini:
5158 return schedule_resp(scp, devip, errsts,
5159 ((F_DELAY_OVERR & flags) ? 0 : scsi_debug_delay));
5160check_cond:
5161 return schedule_resp(scp, devip, check_condition_result, 0);
5162}
5163
Douglas Gilbert38d5c832014-11-24 21:27:12 -05005164static int
5165sdebug_queuecommand_lock_or_not(struct Scsi_Host *shost, struct scsi_cmnd *cmd)
5166{
5167 if (scsi_debug_host_lock) {
5168 unsigned long iflags;
5169 int rc;
5170
5171 spin_lock_irqsave(shost->host_lock, iflags);
5172 rc = scsi_debug_queuecommand(cmd);
5173 spin_unlock_irqrestore(shost->host_lock, iflags);
5174 return rc;
5175 } else
5176 return scsi_debug_queuecommand(cmd);
5177}
5178
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +09005179static struct scsi_host_template sdebug_driver_template = {
Al Viroc8ed5552013-03-31 01:46:06 -04005180 .show_info = scsi_debug_show_info,
5181 .write_info = scsi_debug_write_info,
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +09005182 .proc_name = sdebug_proc_name,
5183 .name = "SCSI DEBUG",
5184 .info = scsi_debug_info,
5185 .slave_alloc = scsi_debug_slave_alloc,
5186 .slave_configure = scsi_debug_slave_configure,
5187 .slave_destroy = scsi_debug_slave_destroy,
5188 .ioctl = scsi_debug_ioctl,
Douglas Gilbertcbf67842014-07-26 11:55:35 -04005189 .queuecommand = sdebug_queuecommand_lock_or_not,
5190 .change_queue_depth = sdebug_change_qdepth,
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +09005191 .eh_abort_handler = scsi_debug_abort,
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +09005192 .eh_device_reset_handler = scsi_debug_device_reset,
Douglas Gilbertcbf67842014-07-26 11:55:35 -04005193 .eh_target_reset_handler = scsi_debug_target_reset,
5194 .eh_bus_reset_handler = scsi_debug_bus_reset,
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +09005195 .eh_host_reset_handler = scsi_debug_host_reset,
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +09005196 .can_queue = SCSI_DEBUG_CANQUEUE,
5197 .this_id = 7,
Akinobu Mita6bb5e6e2014-06-02 22:56:49 +09005198 .sg_tablesize = SCSI_MAX_SG_CHAIN_SEGMENTS,
Douglas Gilbertcbf67842014-07-26 11:55:35 -04005199 .cmd_per_lun = DEF_CMD_PER_LUN,
Akinobu Mita6bb5e6e2014-06-02 22:56:49 +09005200 .max_sectors = -1U,
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +09005201 .use_clustering = DISABLE_CLUSTERING,
5202 .module = THIS_MODULE,
Christoph Hellwigc40ecc12014-11-13 14:25:11 +01005203 .track_queue_depth = 1,
Douglas Gilbert817fd662014-11-24 20:18:02 -05005204 .cmd_size = sizeof(struct sdebug_scmd_extra_t),
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +09005205};
5206
Linus Torvalds1da177e2005-04-16 15:20:36 -07005207static int sdebug_driver_probe(struct device * dev)
5208{
Douglas Gilbert22017ed2014-11-24 23:04:47 -05005209 int error = 0;
Douglas Gilbert817fd662014-11-24 20:18:02 -05005210 int opts;
Douglas Gilbert22017ed2014-11-24 23:04:47 -05005211 struct sdebug_host_info *sdbg_host;
5212 struct Scsi_Host *hpnt;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05005213 int host_prot;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005214
5215 sdbg_host = to_sdebug_host(dev);
5216
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04005217 sdebug_driver_template.can_queue = scsi_debug_max_queue;
Akinobu Mita0759c662014-02-26 22:57:04 +09005218 if (scsi_debug_clustering)
5219 sdebug_driver_template.use_clustering = ENABLE_CLUSTERING;
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04005220 hpnt = scsi_host_alloc(&sdebug_driver_template, sizeof(sdbg_host));
5221 if (NULL == hpnt) {
Finn Thain17c9ff52014-10-03 11:43:31 +10005222 pr_err("%s: scsi_host_alloc failed\n", __func__);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04005223 error = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005224 return error;
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04005225 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005226
5227 sdbg_host->shost = hpnt;
5228 *((struct sdebug_host_info **)hpnt->hostdata) = sdbg_host;
5229 if ((hpnt->this_id >= 0) && (scsi_debug_num_tgts > hpnt->this_id))
5230 hpnt->max_id = scsi_debug_num_tgts + 1;
5231 else
5232 hpnt->max_id = scsi_debug_num_tgts;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04005233 hpnt->max_lun = SAM2_WLUN_REPORT_LUNS; /* = scsi_debug_max_luns; */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005234
Martin K. Petersenc6a44282009-01-04 03:08:19 -05005235 host_prot = 0;
5236
5237 switch (scsi_debug_dif) {
5238
5239 case SD_DIF_TYPE1_PROTECTION:
5240 host_prot = SHOST_DIF_TYPE1_PROTECTION;
5241 if (scsi_debug_dix)
5242 host_prot |= SHOST_DIX_TYPE1_PROTECTION;
5243 break;
5244
5245 case SD_DIF_TYPE2_PROTECTION:
5246 host_prot = SHOST_DIF_TYPE2_PROTECTION;
5247 if (scsi_debug_dix)
5248 host_prot |= SHOST_DIX_TYPE2_PROTECTION;
5249 break;
5250
5251 case SD_DIF_TYPE3_PROTECTION:
5252 host_prot = SHOST_DIF_TYPE3_PROTECTION;
5253 if (scsi_debug_dix)
5254 host_prot |= SHOST_DIX_TYPE3_PROTECTION;
5255 break;
5256
5257 default:
5258 if (scsi_debug_dix)
5259 host_prot |= SHOST_DIX_TYPE0_PROTECTION;
5260 break;
5261 }
5262
5263 scsi_host_set_prot(hpnt, host_prot);
5264
5265 printk(KERN_INFO "scsi_debug: host protection%s%s%s%s%s%s%s\n",
5266 (host_prot & SHOST_DIF_TYPE1_PROTECTION) ? " DIF1" : "",
5267 (host_prot & SHOST_DIF_TYPE2_PROTECTION) ? " DIF2" : "",
5268 (host_prot & SHOST_DIF_TYPE3_PROTECTION) ? " DIF3" : "",
5269 (host_prot & SHOST_DIX_TYPE0_PROTECTION) ? " DIX0" : "",
5270 (host_prot & SHOST_DIX_TYPE1_PROTECTION) ? " DIX1" : "",
5271 (host_prot & SHOST_DIX_TYPE2_PROTECTION) ? " DIX2" : "",
5272 (host_prot & SHOST_DIX_TYPE3_PROTECTION) ? " DIX3" : "");
5273
5274 if (scsi_debug_guard == 1)
5275 scsi_host_set_guard(hpnt, SHOST_DIX_GUARD_IP);
5276 else
5277 scsi_host_set_guard(hpnt, SHOST_DIX_GUARD_CRC);
5278
Douglas Gilbert817fd662014-11-24 20:18:02 -05005279 opts = scsi_debug_opts;
5280 if (SCSI_DEBUG_OPT_RECOVERED_ERR & opts)
5281 sdebug_any_injecting_opt = true;
5282 else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & opts)
5283 sdebug_any_injecting_opt = true;
5284 else if (SCSI_DEBUG_OPT_DIF_ERR & opts)
5285 sdebug_any_injecting_opt = true;
5286 else if (SCSI_DEBUG_OPT_DIX_ERR & opts)
5287 sdebug_any_injecting_opt = true;
5288 else if (SCSI_DEBUG_OPT_SHORT_TRANSFER & opts)
5289 sdebug_any_injecting_opt = true;
5290
Linus Torvalds1da177e2005-04-16 15:20:36 -07005291 error = scsi_add_host(hpnt, &sdbg_host->dev);
5292 if (error) {
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07005293 printk(KERN_ERR "%s: scsi_add_host failed\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005294 error = -ENODEV;
5295 scsi_host_put(hpnt);
5296 } else
5297 scsi_scan_host(hpnt);
5298
Douglas Gilbertcbf67842014-07-26 11:55:35 -04005299 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005300}
5301
5302static int sdebug_driver_remove(struct device * dev)
5303{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005304 struct sdebug_host_info *sdbg_host;
FUJITA Tomonori8b40228f2008-03-20 11:09:18 +09005305 struct sdebug_dev_info *sdbg_devinfo, *tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005306
5307 sdbg_host = to_sdebug_host(dev);
5308
5309 if (!sdbg_host) {
5310 printk(KERN_ERR "%s: Unable to locate host info\n",
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07005311 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005312 return -ENODEV;
5313 }
5314
5315 scsi_remove_host(sdbg_host->shost);
5316
FUJITA Tomonori8b40228f2008-03-20 11:09:18 +09005317 list_for_each_entry_safe(sdbg_devinfo, tmp, &sdbg_host->dev_info_list,
5318 dev_list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005319 list_del(&sdbg_devinfo->dev_list);
5320 kfree(sdbg_devinfo);
5321 }
5322
5323 scsi_host_put(sdbg_host->shost);
5324 return 0;
5325}
5326
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09005327static int pseudo_lld_bus_match(struct device *dev,
5328 struct device_driver *dev_driver)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005329{
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09005330 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005331}
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09005332
5333static struct bus_type pseudo_lld_bus = {
5334 .name = "pseudo",
5335 .match = pseudo_lld_bus_match,
5336 .probe = sdebug_driver_probe,
5337 .remove = sdebug_driver_remove,
Akinobu Mita82069372013-10-14 22:48:04 +09005338 .drv_groups = sdebug_drv_groups,
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09005339};