blob: d81158b71326f61912f6615af3b8b0802904f08f [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;
3047
3048 lba = get_unaligned_be32(cmd + 2);
3049 num = cmd[13]; /* 1 to a maximum of 255 logical blocks */
3050 if (0 == num)
3051 return 0; /* degenerate case, not an error */
3052 dnum = 2 * num;
3053 arr = kzalloc(dnum * lb_size, GFP_ATOMIC);
3054 if (NULL == arr) {
3055 mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC,
3056 INSUFF_RES_ASCQ);
3057 return check_condition_result;
3058 }
3059 if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
3060 (cmd[1] & 0xe0)) {
3061 mk_sense_invalid_opcode(scp);
3062 return check_condition_result;
3063 }
3064 if ((scsi_debug_dif == SD_DIF_TYPE1_PROTECTION ||
3065 scsi_debug_dif == SD_DIF_TYPE3_PROTECTION) &&
3066 (cmd[1] & 0xe0) == 0)
3067 sdev_printk(KERN_ERR, scp->device, "Unprotected WR "
3068 "to DIF device\n");
3069
3070 /* inline check_device_access_params() */
3071 if (lba + num > sdebug_capacity) {
3072 mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0);
3073 return check_condition_result;
3074 }
3075 /* transfer length excessive (tie in to block limits VPD page) */
3076 if (num > sdebug_store_sectors) {
3077 /* needs work to find which cdb byte 'num' comes from */
3078 mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0);
3079 return check_condition_result;
3080 }
3081
3082 write_lock_irqsave(&atomic_rw, iflags);
3083
3084 /* trick do_device_access() to fetch both compare and write buffers
3085 * from data-in into arr. Safe (atomic) since write_lock held. */
3086 fake_storep_hold = fake_storep;
3087 fake_storep = arr;
3088 ret = do_device_access(scp, 0, dnum, true);
3089 fake_storep = fake_storep_hold;
3090 if (ret == -1) {
3091 write_unlock_irqrestore(&atomic_rw, iflags);
3092 kfree(arr);
3093 return DID_ERROR << 16;
3094 } 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)) {
3100 write_unlock_irqrestore(&atomic_rw, iflags);
3101 kfree(arr);
3102 mk_sense_buffer(scp, MISCOMPARE, MISCOMPARE_VERIFY_ASC, 0);
3103 return check_condition_result;
3104 }
3105 if (scsi_debug_lbp())
3106 map_region(lba, num);
3107 write_unlock_irqrestore(&atomic_rw, iflags);
3108 return 0;
3109}
3110
Martin K. Petersen44d92692009-10-15 14:45:27 -04003111struct unmap_block_desc {
3112 __be64 lba;
3113 __be32 blocks;
3114 __be32 __reserved;
3115};
3116
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003117static int
3118resp_unmap(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
Martin K. Petersen44d92692009-10-15 14:45:27 -04003119{
3120 unsigned char *buf;
3121 struct unmap_block_desc *desc;
3122 unsigned int i, payload_len, descriptors;
3123 int ret;
Akinobu Mita6c78cc02014-02-26 22:57:03 +09003124 unsigned long iflags;
Martin K. Petersen44d92692009-10-15 14:45:27 -04003125
Martin K. Petersen44d92692009-10-15 14:45:27 -04003126
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003127 if (!scsi_debug_lbp())
3128 return 0; /* fib and say its done */
3129 payload_len = get_unaligned_be16(scp->cmnd + 7);
3130 BUG_ON(scsi_bufflen(scp) != payload_len);
Martin K. Petersen44d92692009-10-15 14:45:27 -04003131
3132 descriptors = (payload_len - 8) / 16;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003133 if (descriptors > scsi_debug_unmap_max_desc) {
3134 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 7, -1);
Martin K. Petersen44d92692009-10-15 14:45:27 -04003135 return check_condition_result;
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003136 }
Martin K. Petersen44d92692009-10-15 14:45:27 -04003137
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003138 buf = kmalloc(scsi_bufflen(scp), GFP_ATOMIC);
3139 if (!buf) {
3140 mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC,
3141 INSUFF_RES_ASCQ);
3142 return check_condition_result;
3143 }
3144
3145 scsi_sg_copy_to_buffer(scp, buf, scsi_bufflen(scp));
Martin K. Petersen44d92692009-10-15 14:45:27 -04003146
3147 BUG_ON(get_unaligned_be16(&buf[0]) != payload_len - 2);
3148 BUG_ON(get_unaligned_be16(&buf[2]) != descriptors * 16);
3149
3150 desc = (void *)&buf[8];
3151
Akinobu Mita6c78cc02014-02-26 22:57:03 +09003152 write_lock_irqsave(&atomic_rw, iflags);
3153
Martin K. Petersen44d92692009-10-15 14:45:27 -04003154 for (i = 0 ; i < descriptors ; i++) {
3155 unsigned long long lba = get_unaligned_be64(&desc[i].lba);
3156 unsigned int num = get_unaligned_be32(&desc[i].blocks);
3157
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003158 ret = check_device_access_params(scp, lba, num);
Martin K. Petersen44d92692009-10-15 14:45:27 -04003159 if (ret)
3160 goto out;
3161
3162 unmap_region(lba, num);
3163 }
3164
3165 ret = 0;
3166
3167out:
Akinobu Mita6c78cc02014-02-26 22:57:03 +09003168 write_unlock_irqrestore(&atomic_rw, iflags);
Martin K. Petersen44d92692009-10-15 14:45:27 -04003169 kfree(buf);
3170
3171 return ret;
3172}
3173
3174#define SDEBUG_GET_LBA_STATUS_LEN 32
3175
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003176static int
3177resp_get_lba_status(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
Martin K. Petersen44d92692009-10-15 14:45:27 -04003178{
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003179 u8 *cmd = scp->cmnd;
3180 u64 lba;
3181 u32 alloc_len, mapped, num;
3182 u8 arr[SDEBUG_GET_LBA_STATUS_LEN];
Martin K. Petersen44d92692009-10-15 14:45:27 -04003183 int ret;
3184
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003185 lba = get_unaligned_be64(cmd + 2);
3186 alloc_len = get_unaligned_be32(cmd + 10);
Martin K. Petersen44d92692009-10-15 14:45:27 -04003187
3188 if (alloc_len < 24)
3189 return 0;
3190
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003191 ret = check_device_access_params(scp, lba, 1);
Martin K. Petersen44d92692009-10-15 14:45:27 -04003192 if (ret)
3193 return ret;
3194
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003195 if (scsi_debug_lbp())
3196 mapped = map_state(lba, &num);
3197 else {
3198 mapped = 1;
3199 /* following just in case virtual_gb changed */
3200 sdebug_capacity = get_sdebug_capacity();
3201 if (sdebug_capacity - lba <= 0xffffffff)
3202 num = sdebug_capacity - lba;
3203 else
3204 num = 0xffffffff;
3205 }
Martin K. Petersen44d92692009-10-15 14:45:27 -04003206
3207 memset(arr, 0, SDEBUG_GET_LBA_STATUS_LEN);
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003208 put_unaligned_be32(20, arr); /* Parameter Data Length */
3209 put_unaligned_be64(lba, arr + 8); /* LBA */
3210 put_unaligned_be32(num, arr + 16); /* Number of blocks */
3211 arr[20] = !mapped; /* prov_stat=0: mapped; 1: dealloc */
Martin K. Petersen44d92692009-10-15 14:45:27 -04003212
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003213 return fill_from_dev_buffer(scp, arr, SDEBUG_GET_LBA_STATUS_LEN);
Martin K. Petersen44d92692009-10-15 14:45:27 -04003214}
3215
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003216#define SDEBUG_RLUN_ARR_SZ 256
Linus Torvalds1da177e2005-04-16 15:20:36 -07003217
3218static int resp_report_luns(struct scsi_cmnd * scp,
3219 struct sdebug_dev_info * devip)
3220{
3221 unsigned int alloc_len;
Douglas Gilbert22017ed2014-11-24 23:04:47 -05003222 int lun_cnt, i, upper, num, n, want_wlun, shortish;
3223 u64 lun;
Douglas Gilbert01123ef2014-08-05 12:20:02 +02003224 unsigned char *cmd = scp->cmnd;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003225 int select_report = (int)cmd[2];
3226 struct scsi_lun *one_lun;
3227 unsigned char arr[SDEBUG_RLUN_ARR_SZ];
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003228 unsigned char * max_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003229
3230 alloc_len = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24);
Douglas Gilbert22017ed2014-11-24 23:04:47 -05003231 shortish = (alloc_len < 4);
3232 if (shortish || (select_report > 2)) {
3233 mk_sense_invalid_fld(scp, SDEB_IN_CDB, shortish ? 6 : 2, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003234 return check_condition_result;
3235 }
3236 /* can produce response with up to 16k luns (lun 0 to lun 16383) */
3237 memset(arr, 0, SDEBUG_RLUN_ARR_SZ);
3238 lun_cnt = scsi_debug_max_luns;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003239 if (1 == select_report)
3240 lun_cnt = 0;
3241 else if (scsi_debug_no_lun_0 && (lun_cnt > 0))
3242 --lun_cnt;
Douglas Gilbert22017ed2014-11-24 23:04:47 -05003243 want_wlun = (select_report > 0) ? 1 : 0;
3244 num = lun_cnt + want_wlun;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003245 arr[2] = ((sizeof(struct scsi_lun) * num) >> 8) & 0xff;
3246 arr[3] = (sizeof(struct scsi_lun) * num) & 0xff;
3247 n = min((int)((SDEBUG_RLUN_ARR_SZ - 8) /
3248 sizeof(struct scsi_lun)), num);
3249 if (n < num) {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05003250 want_wlun = 0;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003251 lun_cnt = n;
3252 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003253 one_lun = (struct scsi_lun *) &arr[8];
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003254 max_addr = arr + SDEBUG_RLUN_ARR_SZ;
3255 for (i = 0, lun = (scsi_debug_no_lun_0 ? 1 : 0);
3256 ((i < lun_cnt) && ((unsigned char *)(one_lun + i) < max_addr));
3257 i++, lun++) {
3258 upper = (lun >> 8) & 0x3f;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003259 if (upper)
3260 one_lun[i].scsi_lun[0] =
3261 (upper | (SAM2_LUN_ADDRESS_METHOD << 6));
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003262 one_lun[i].scsi_lun[1] = lun & 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003263 }
Douglas Gilbert22017ed2014-11-24 23:04:47 -05003264 if (want_wlun) {
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003265 one_lun[i].scsi_lun[0] = (SAM2_WLUN_REPORT_LUNS >> 8) & 0xff;
3266 one_lun[i].scsi_lun[1] = SAM2_WLUN_REPORT_LUNS & 0xff;
3267 i++;
3268 }
3269 alloc_len = (unsigned char *)(one_lun + i) - arr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003270 return fill_from_dev_buffer(scp, arr,
3271 min((int)alloc_len, SDEBUG_RLUN_ARR_SZ));
3272}
3273
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003274static int resp_xdwriteread(struct scsi_cmnd *scp, unsigned long long lba,
3275 unsigned int num, struct sdebug_dev_info *devip)
3276{
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09003277 int j;
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003278 unsigned char *kaddr, *buf;
3279 unsigned int offset;
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003280 struct scsi_data_buffer *sdb = scsi_in(scp);
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09003281 struct sg_mapping_iter miter;
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003282
3283 /* better not to use temporary buffer. */
3284 buf = kmalloc(scsi_bufflen(scp), GFP_ATOMIC);
Akinobu Mitac5af0db2014-02-26 22:57:01 +09003285 if (!buf) {
Douglas Gilbert22017ed2014-11-24 23:04:47 -05003286 mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC,
3287 INSUFF_RES_ASCQ);
Akinobu Mitac5af0db2014-02-26 22:57:01 +09003288 return check_condition_result;
3289 }
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003290
FUJITA Tomonori21a61822008-03-09 13:44:30 +09003291 scsi_sg_copy_to_buffer(scp, buf, scsi_bufflen(scp));
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003292
3293 offset = 0;
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09003294 sg_miter_start(&miter, sdb->table.sgl, sdb->table.nents,
3295 SG_MITER_ATOMIC | SG_MITER_TO_SG);
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003296
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09003297 while (sg_miter_next(&miter)) {
3298 kaddr = miter.addr;
3299 for (j = 0; j < miter.length; j++)
3300 *(kaddr + j) ^= *(buf + offset + j);
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003301
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09003302 offset += miter.length;
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003303 }
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09003304 sg_miter_stop(&miter);
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003305 kfree(buf);
3306
Akinobu Mitabe4e11b2014-02-26 22:57:02 +09003307 return 0;
FUJITA Tomonoric639d142008-01-23 01:32:01 +09003308}
3309
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003310static int
3311resp_xdwriteread_10(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
3312{
3313 u8 *cmd = scp->cmnd;
3314 u64 lba;
3315 u32 num;
3316 int errsts;
3317
3318 if (!scsi_bidi_cmnd(scp)) {
3319 mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC,
3320 INSUFF_RES_ASCQ);
3321 return check_condition_result;
3322 }
3323 errsts = resp_read_dt0(scp, devip);
3324 if (errsts)
3325 return errsts;
3326 if (!(cmd[1] & 0x4)) { /* DISABLE_WRITE is not set */
3327 errsts = resp_write_dt0(scp, devip);
3328 if (errsts)
3329 return errsts;
3330 }
3331 lba = get_unaligned_be32(cmd + 2);
3332 num = get_unaligned_be16(cmd + 7);
3333 return resp_xdwriteread(scp, lba, num, devip);
3334}
3335
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003336/* When timer or tasklet goes off this function is called. */
3337static void sdebug_q_cmd_complete(unsigned long indx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003338{
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003339 int qa_indx;
3340 int retiring = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003341 unsigned long iflags;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003342 struct sdebug_queued_cmd *sqcp;
3343 struct scsi_cmnd *scp;
3344 struct sdebug_dev_info *devip;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003345
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003346 atomic_inc(&sdebug_completions);
3347 qa_indx = indx;
3348 if ((qa_indx < 0) || (qa_indx >= SCSI_DEBUG_CANQUEUE)) {
3349 pr_err("%s: wild qa_indx=%d\n", __func__, qa_indx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003350 return;
3351 }
3352 spin_lock_irqsave(&queued_arr_lock, iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003353 sqcp = &queued_arr[qa_indx];
3354 scp = sqcp->a_cmnd;
3355 if (NULL == scp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003356 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003357 pr_err("%s: scp is NULL\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003358 return;
3359 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003360 devip = (struct sdebug_dev_info *)scp->device->hostdata;
3361 if (devip)
3362 atomic_dec(&devip->num_in_q);
3363 else
3364 pr_err("%s: devip=NULL\n", __func__);
3365 if (atomic_read(&retired_max_queue) > 0)
3366 retiring = 1;
3367
3368 sqcp->a_cmnd = NULL;
3369 if (!test_and_clear_bit(qa_indx, queued_in_use_bm)) {
3370 spin_unlock_irqrestore(&queued_arr_lock, iflags);
3371 pr_err("%s: Unexpected completion\n", __func__);
3372 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003373 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003374
3375 if (unlikely(retiring)) { /* user has reduced max_queue */
3376 int k, retval;
3377
3378 retval = atomic_read(&retired_max_queue);
3379 if (qa_indx >= retval) {
3380 spin_unlock_irqrestore(&queued_arr_lock, iflags);
3381 pr_err("%s: index %d too large\n", __func__, retval);
3382 return;
3383 }
3384 k = find_last_bit(queued_in_use_bm, retval);
3385 if ((k < scsi_debug_max_queue) || (k == retval))
3386 atomic_set(&retired_max_queue, 0);
3387 else
3388 atomic_set(&retired_max_queue, k + 1);
3389 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003390 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003391 scp->scsi_done(scp); /* callback to mid level */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003392}
3393
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003394/* When high resolution timer goes off this function is called. */
3395static enum hrtimer_restart
3396sdebug_q_cmd_hrt_complete(struct hrtimer *timer)
3397{
3398 int qa_indx;
3399 int retiring = 0;
3400 unsigned long iflags;
3401 struct sdebug_hrtimer *sd_hrtp = (struct sdebug_hrtimer *)timer;
3402 struct sdebug_queued_cmd *sqcp;
3403 struct scsi_cmnd *scp;
3404 struct sdebug_dev_info *devip;
3405
3406 atomic_inc(&sdebug_completions);
3407 qa_indx = sd_hrtp->qa_indx;
3408 if ((qa_indx < 0) || (qa_indx >= SCSI_DEBUG_CANQUEUE)) {
3409 pr_err("%s: wild qa_indx=%d\n", __func__, qa_indx);
3410 goto the_end;
3411 }
3412 spin_lock_irqsave(&queued_arr_lock, iflags);
3413 sqcp = &queued_arr[qa_indx];
3414 scp = sqcp->a_cmnd;
3415 if (NULL == scp) {
3416 spin_unlock_irqrestore(&queued_arr_lock, iflags);
3417 pr_err("%s: scp is NULL\n", __func__);
3418 goto the_end;
3419 }
3420 devip = (struct sdebug_dev_info *)scp->device->hostdata;
3421 if (devip)
3422 atomic_dec(&devip->num_in_q);
3423 else
3424 pr_err("%s: devip=NULL\n", __func__);
3425 if (atomic_read(&retired_max_queue) > 0)
3426 retiring = 1;
3427
3428 sqcp->a_cmnd = NULL;
3429 if (!test_and_clear_bit(qa_indx, queued_in_use_bm)) {
3430 spin_unlock_irqrestore(&queued_arr_lock, iflags);
3431 pr_err("%s: Unexpected completion\n", __func__);
3432 goto the_end;
3433 }
3434
3435 if (unlikely(retiring)) { /* user has reduced max_queue */
3436 int k, retval;
3437
3438 retval = atomic_read(&retired_max_queue);
3439 if (qa_indx >= retval) {
3440 spin_unlock_irqrestore(&queued_arr_lock, iflags);
3441 pr_err("%s: index %d too large\n", __func__, retval);
3442 goto the_end;
3443 }
3444 k = find_last_bit(queued_in_use_bm, retval);
3445 if ((k < scsi_debug_max_queue) || (k == retval))
3446 atomic_set(&retired_max_queue, 0);
3447 else
3448 atomic_set(&retired_max_queue, k + 1);
3449 }
3450 spin_unlock_irqrestore(&queued_arr_lock, iflags);
3451 scp->scsi_done(scp); /* callback to mid level */
3452the_end:
3453 return HRTIMER_NORESTART;
3454}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003455
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003456static struct sdebug_dev_info *
3457sdebug_device_create(struct sdebug_host_info *sdbg_host, gfp_t flags)
FUJITA Tomonori5cb2fc02008-03-20 11:09:16 +09003458{
3459 struct sdebug_dev_info *devip;
3460
3461 devip = kzalloc(sizeof(*devip), flags);
3462 if (devip) {
3463 devip->sdbg_host = sdbg_host;
3464 list_add_tail(&devip->dev_list, &sdbg_host->dev_info_list);
3465 }
3466 return devip;
3467}
3468
Linus Torvalds1da177e2005-04-16 15:20:36 -07003469static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev)
3470{
3471 struct sdebug_host_info * sdbg_host;
3472 struct sdebug_dev_info * open_devip = NULL;
3473 struct sdebug_dev_info * devip =
3474 (struct sdebug_dev_info *)sdev->hostdata;
3475
3476 if (devip)
3477 return devip;
FUJITA Tomonorid1e4c9c2008-03-02 18:30:18 +09003478 sdbg_host = *(struct sdebug_host_info **)shost_priv(sdev->host);
3479 if (!sdbg_host) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003480 pr_err("%s: Host info NULL\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003481 return NULL;
3482 }
3483 list_for_each_entry(devip, &sdbg_host->dev_info_list, dev_list) {
3484 if ((devip->used) && (devip->channel == sdev->channel) &&
3485 (devip->target == sdev->id) &&
3486 (devip->lun == sdev->lun))
3487 return devip;
3488 else {
3489 if ((!devip->used) && (!open_devip))
3490 open_devip = devip;
3491 }
3492 }
FUJITA Tomonori5cb2fc02008-03-20 11:09:16 +09003493 if (!open_devip) { /* try and make a new one */
3494 open_devip = sdebug_device_create(sdbg_host, GFP_ATOMIC);
3495 if (!open_devip) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003496 printk(KERN_ERR "%s: out of memory at line %d\n",
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07003497 __func__, __LINE__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003498 return NULL;
3499 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003500 }
FUJITA Tomonoria75869d2008-03-20 11:09:17 +09003501
3502 open_devip->channel = sdev->channel;
3503 open_devip->target = sdev->id;
3504 open_devip->lun = sdev->lun;
3505 open_devip->sdbg_host = sdbg_host;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003506 atomic_set(&open_devip->num_in_q, 0);
3507 set_bit(SDEBUG_UA_POR, open_devip->uas_bm);
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003508 open_devip->used = true;
FUJITA Tomonoria75869d2008-03-20 11:09:17 +09003509 return open_devip;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003510}
3511
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003512static int scsi_debug_slave_alloc(struct scsi_device *sdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003513{
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003514 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
Hannes Reinecke9cb78c12014-06-25 15:27:36 +02003515 printk(KERN_INFO "scsi_debug: slave_alloc <%u %u %u %llu>\n",
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003516 sdp->host->host_no, sdp->channel, sdp->id, sdp->lun);
Nick Piggin75ad23b2008-04-29 14:48:33 +02003517 queue_flag_set_unlocked(QUEUE_FLAG_BIDI, sdp->request_queue);
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003518 return 0;
3519}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003520
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003521static int scsi_debug_slave_configure(struct scsi_device *sdp)
3522{
3523 struct sdebug_dev_info *devip;
FUJITA Tomonoria34c4e92008-03-25 09:26:50 +09003524
Linus Torvalds1da177e2005-04-16 15:20:36 -07003525 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
Hannes Reinecke9cb78c12014-06-25 15:27:36 +02003526 printk(KERN_INFO "scsi_debug: slave_configure <%u %u %u %llu>\n",
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003527 sdp->host->host_no, sdp->channel, sdp->id, sdp->lun);
3528 if (sdp->host->max_cmd_len != SCSI_DEBUG_MAX_CMD_LEN)
3529 sdp->host->max_cmd_len = SCSI_DEBUG_MAX_CMD_LEN;
3530 devip = devInfoReg(sdp);
3531 if (NULL == devip)
3532 return 1; /* no resources, will be marked offline */
Christoph Hellwigc8b09f62014-11-03 20:15:14 +01003533 sdp->hostdata = devip;
Akinobu Mita6bb5e6e2014-06-02 22:56:49 +09003534 blk_queue_max_segment_size(sdp->request_queue, -1U);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04003535 if (scsi_debug_no_uld)
3536 sdp->no_uld_attach = 1;
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003537 return 0;
3538}
3539
3540static void scsi_debug_slave_destroy(struct scsi_device *sdp)
3541{
3542 struct sdebug_dev_info *devip =
3543 (struct sdebug_dev_info *)sdp->hostdata;
3544
3545 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
Hannes Reinecke9cb78c12014-06-25 15:27:36 +02003546 printk(KERN_INFO "scsi_debug: slave_destroy <%u %u %u %llu>\n",
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003547 sdp->host->host_no, sdp->channel, sdp->id, sdp->lun);
3548 if (devip) {
Lucas De Marchi25985ed2011-03-30 22:57:33 -03003549 /* make this slot available for re-use */
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003550 devip->used = false;
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003551 sdp->hostdata = NULL;
3552 }
3553}
3554
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003555/* Returns 1 if cmnd found (deletes its timer or tasklet), else returns 0 */
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003556static int stop_queued_cmnd(struct scsi_cmnd *cmnd)
3557{
3558 unsigned long iflags;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003559 int k, qmax, r_qmax;
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003560 struct sdebug_queued_cmd *sqcp;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003561 struct sdebug_dev_info *devip;
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003562
3563 spin_lock_irqsave(&queued_arr_lock, iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003564 qmax = scsi_debug_max_queue;
3565 r_qmax = atomic_read(&retired_max_queue);
3566 if (r_qmax > qmax)
3567 qmax = r_qmax;
3568 for (k = 0; k < qmax; ++k) {
3569 if (test_bit(k, queued_in_use_bm)) {
3570 sqcp = &queued_arr[k];
3571 if (cmnd == sqcp->a_cmnd) {
Douglas Gilbertdb525fc2014-08-31 19:09:59 -04003572 devip = (struct sdebug_dev_info *)
3573 cmnd->device->hostdata;
3574 if (devip)
3575 atomic_dec(&devip->num_in_q);
3576 sqcp->a_cmnd = NULL;
3577 spin_unlock_irqrestore(&queued_arr_lock,
3578 iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003579 if (scsi_debug_ndelay > 0) {
3580 if (sqcp->sd_hrtp)
3581 hrtimer_cancel(
3582 &sqcp->sd_hrtp->hrt);
3583 } else if (scsi_debug_delay > 0) {
3584 if (sqcp->cmnd_timerp)
3585 del_timer_sync(
3586 sqcp->cmnd_timerp);
3587 } else if (scsi_debug_delay < 0) {
3588 if (sqcp->tletp)
3589 tasklet_kill(sqcp->tletp);
3590 }
Douglas Gilbertdb525fc2014-08-31 19:09:59 -04003591 clear_bit(k, queued_in_use_bm);
3592 return 1;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003593 }
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003594 }
3595 }
3596 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Douglas Gilbertdb525fc2014-08-31 19:09:59 -04003597 return 0;
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003598}
3599
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003600/* Deletes (stops) timers or tasklets of all queued commands */
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003601static void stop_all_queued(void)
3602{
3603 unsigned long iflags;
3604 int k;
3605 struct sdebug_queued_cmd *sqcp;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003606 struct sdebug_dev_info *devip;
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003607
3608 spin_lock_irqsave(&queued_arr_lock, iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003609 for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) {
3610 if (test_bit(k, queued_in_use_bm)) {
3611 sqcp = &queued_arr[k];
3612 if (sqcp->a_cmnd) {
Douglas Gilbertdb525fc2014-08-31 19:09:59 -04003613 devip = (struct sdebug_dev_info *)
3614 sqcp->a_cmnd->device->hostdata;
3615 if (devip)
3616 atomic_dec(&devip->num_in_q);
3617 sqcp->a_cmnd = NULL;
3618 spin_unlock_irqrestore(&queued_arr_lock,
3619 iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003620 if (scsi_debug_ndelay > 0) {
3621 if (sqcp->sd_hrtp)
3622 hrtimer_cancel(
3623 &sqcp->sd_hrtp->hrt);
3624 } else if (scsi_debug_delay > 0) {
3625 if (sqcp->cmnd_timerp)
3626 del_timer_sync(
3627 sqcp->cmnd_timerp);
3628 } else if (scsi_debug_delay < 0) {
3629 if (sqcp->tletp)
3630 tasklet_kill(sqcp->tletp);
3631 }
Douglas Gilbertdb525fc2014-08-31 19:09:59 -04003632 clear_bit(k, queued_in_use_bm);
3633 spin_lock_irqsave(&queued_arr_lock, iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003634 }
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09003635 }
3636 }
3637 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003638}
3639
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003640/* Free queued command memory on heap */
3641static void free_all_queued(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003642{
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003643 unsigned long iflags;
3644 int k;
3645 struct sdebug_queued_cmd *sqcp;
3646
3647 spin_lock_irqsave(&queued_arr_lock, iflags);
3648 for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) {
3649 sqcp = &queued_arr[k];
3650 kfree(sqcp->cmnd_timerp);
3651 sqcp->cmnd_timerp = NULL;
3652 kfree(sqcp->tletp);
3653 sqcp->tletp = NULL;
3654 kfree(sqcp->sd_hrtp);
3655 sqcp->sd_hrtp = NULL;
3656 }
3657 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003658}
3659
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003660static int scsi_debug_abort(struct scsi_cmnd *SCpnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003661{
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003662 ++num_aborts;
3663 if (SCpnt) {
3664 if (SCpnt->device &&
3665 (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts))
3666 sdev_printk(KERN_INFO, SCpnt->device, "%s\n",
3667 __func__);
3668 stop_queued_cmnd(SCpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003669 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003670 return SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003671}
3672
3673static int scsi_debug_device_reset(struct scsi_cmnd * SCpnt)
3674{
3675 struct sdebug_dev_info * devip;
3676
Linus Torvalds1da177e2005-04-16 15:20:36 -07003677 ++num_dev_resets;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003678 if (SCpnt && SCpnt->device) {
3679 struct scsi_device *sdp = SCpnt->device;
3680
3681 if (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts)
3682 sdev_printk(KERN_INFO, sdp, "%s\n", __func__);
3683 devip = devInfoReg(sdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003684 if (devip)
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003685 set_bit(SDEBUG_UA_POR, devip->uas_bm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003686 }
3687 return SUCCESS;
3688}
3689
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003690static int scsi_debug_target_reset(struct scsi_cmnd *SCpnt)
3691{
3692 struct sdebug_host_info *sdbg_host;
3693 struct sdebug_dev_info *devip;
3694 struct scsi_device *sdp;
3695 struct Scsi_Host *hp;
3696 int k = 0;
3697
3698 ++num_target_resets;
3699 if (!SCpnt)
3700 goto lie;
3701 sdp = SCpnt->device;
3702 if (!sdp)
3703 goto lie;
3704 if (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts)
3705 sdev_printk(KERN_INFO, sdp, "%s\n", __func__);
3706 hp = sdp->host;
3707 if (!hp)
3708 goto lie;
3709 sdbg_host = *(struct sdebug_host_info **)shost_priv(hp);
3710 if (sdbg_host) {
3711 list_for_each_entry(devip,
3712 &sdbg_host->dev_info_list,
3713 dev_list)
3714 if (devip->target == sdp->id) {
3715 set_bit(SDEBUG_UA_BUS_RESET, devip->uas_bm);
3716 ++k;
3717 }
3718 }
3719 if (SCSI_DEBUG_OPT_RESET_NOISE & scsi_debug_opts)
3720 sdev_printk(KERN_INFO, sdp,
3721 "%s: %d device(s) found in target\n", __func__, k);
3722lie:
3723 return SUCCESS;
3724}
3725
Linus Torvalds1da177e2005-04-16 15:20:36 -07003726static int scsi_debug_bus_reset(struct scsi_cmnd * SCpnt)
3727{
3728 struct sdebug_host_info *sdbg_host;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003729 struct sdebug_dev_info *devip;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003730 struct scsi_device * sdp;
3731 struct Scsi_Host * hp;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003732 int k = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003733
Linus Torvalds1da177e2005-04-16 15:20:36 -07003734 ++num_bus_resets;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003735 if (!(SCpnt && SCpnt->device))
3736 goto lie;
3737 sdp = SCpnt->device;
3738 if (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts)
3739 sdev_printk(KERN_INFO, sdp, "%s\n", __func__);
3740 hp = sdp->host;
3741 if (hp) {
FUJITA Tomonorid1e4c9c2008-03-02 18:30:18 +09003742 sdbg_host = *(struct sdebug_host_info **)shost_priv(hp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003743 if (sdbg_host) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003744 list_for_each_entry(devip,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003745 &sdbg_host->dev_info_list,
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003746 dev_list) {
3747 set_bit(SDEBUG_UA_BUS_RESET, devip->uas_bm);
3748 ++k;
3749 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003750 }
3751 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003752 if (SCSI_DEBUG_OPT_RESET_NOISE & scsi_debug_opts)
3753 sdev_printk(KERN_INFO, sdp,
3754 "%s: %d device(s) found in host\n", __func__, k);
3755lie:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003756 return SUCCESS;
3757}
3758
3759static int scsi_debug_host_reset(struct scsi_cmnd * SCpnt)
3760{
3761 struct sdebug_host_info * sdbg_host;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003762 struct sdebug_dev_info *devip;
3763 int k = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003764
Linus Torvalds1da177e2005-04-16 15:20:36 -07003765 ++num_host_resets;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003766 if ((SCpnt->device) && (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts))
3767 sdev_printk(KERN_INFO, SCpnt->device, "%s\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003768 spin_lock(&sdebug_host_list_lock);
3769 list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003770 list_for_each_entry(devip, &sdbg_host->dev_info_list,
3771 dev_list) {
3772 set_bit(SDEBUG_UA_BUS_RESET, devip->uas_bm);
3773 ++k;
3774 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003775 }
3776 spin_unlock(&sdebug_host_list_lock);
3777 stop_all_queued();
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003778 if (SCSI_DEBUG_OPT_RESET_NOISE & scsi_debug_opts)
3779 sdev_printk(KERN_INFO, SCpnt->device,
3780 "%s: %d device(s) found\n", __func__, k);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003781 return SUCCESS;
3782}
3783
FUJITA Tomonorif58b0ef2008-03-30 00:59:54 +09003784static void __init sdebug_build_parts(unsigned char *ramp,
FUJITA Tomonori5f2578e2008-03-30 00:59:57 +09003785 unsigned long store_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003786{
3787 struct partition * pp;
3788 int starts[SDEBUG_MAX_PARTS + 2];
3789 int sectors_per_part, num_sectors, k;
3790 int heads_by_sects, start_sec, end_sec;
3791
3792 /* assume partition table already zeroed */
FUJITA Tomonorif58b0ef2008-03-30 00:59:54 +09003793 if ((scsi_debug_num_parts < 1) || (store_size < 1048576))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003794 return;
3795 if (scsi_debug_num_parts > SDEBUG_MAX_PARTS) {
3796 scsi_debug_num_parts = SDEBUG_MAX_PARTS;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003797 pr_warn("%s: reducing partitions to %d\n", __func__,
3798 SDEBUG_MAX_PARTS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003799 }
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003800 num_sectors = (int)sdebug_store_sectors;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003801 sectors_per_part = (num_sectors - sdebug_sectors_per)
3802 / scsi_debug_num_parts;
3803 heads_by_sects = sdebug_heads * sdebug_sectors_per;
3804 starts[0] = sdebug_sectors_per;
3805 for (k = 1; k < scsi_debug_num_parts; ++k)
3806 starts[k] = ((k * sectors_per_part) / heads_by_sects)
3807 * heads_by_sects;
3808 starts[scsi_debug_num_parts] = num_sectors;
3809 starts[scsi_debug_num_parts + 1] = 0;
3810
3811 ramp[510] = 0x55; /* magic partition markings */
3812 ramp[511] = 0xAA;
3813 pp = (struct partition *)(ramp + 0x1be);
3814 for (k = 0; starts[k + 1]; ++k, ++pp) {
3815 start_sec = starts[k];
3816 end_sec = starts[k + 1] - 1;
3817 pp->boot_ind = 0;
3818
3819 pp->cyl = start_sec / heads_by_sects;
3820 pp->head = (start_sec - (pp->cyl * heads_by_sects))
3821 / sdebug_sectors_per;
3822 pp->sector = (start_sec % sdebug_sectors_per) + 1;
3823
3824 pp->end_cyl = end_sec / heads_by_sects;
3825 pp->end_head = (end_sec - (pp->end_cyl * heads_by_sects))
3826 / sdebug_sectors_per;
3827 pp->end_sector = (end_sec % sdebug_sectors_per) + 1;
3828
Akinobu Mita150c3542013-08-26 22:08:40 +09003829 pp->start_sect = cpu_to_le32(start_sec);
3830 pp->nr_sects = cpu_to_le32(end_sec - start_sec + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003831 pp->sys_ind = 0x83; /* plain Linux partition */
3832 }
3833}
3834
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003835static int
3836schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip,
3837 int scsi_result, int delta_jiff)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003838{
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003839 unsigned long iflags;
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003840 int k, num_in_q, qdepth, inject;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003841 struct sdebug_queued_cmd *sqcp = NULL;
3842 struct scsi_device *sdp = cmnd->device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003843
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003844 if (NULL == cmnd || NULL == devip) {
3845 pr_warn("%s: called with NULL cmnd or devip pointer\n",
3846 __func__);
3847 /* no particularly good error to report back */
3848 return SCSI_MLQUEUE_HOST_BUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003849 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003850 if ((scsi_result) && (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
3851 sdev_printk(KERN_INFO, sdp, "%s: non-zero result=0x%x\n",
3852 __func__, scsi_result);
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003853 if (delta_jiff == 0)
3854 goto respond_in_thread;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003855
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003856 /* schedule the response at a later time if resources permit */
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003857 spin_lock_irqsave(&queued_arr_lock, iflags);
3858 num_in_q = atomic_read(&devip->num_in_q);
3859 qdepth = cmnd->device->queue_depth;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003860 inject = 0;
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003861 if ((qdepth > 0) && (num_in_q >= qdepth)) {
3862 if (scsi_result) {
3863 spin_unlock_irqrestore(&queued_arr_lock, iflags);
3864 goto respond_in_thread;
3865 } else
3866 scsi_result = device_qfull_result;
3867 } else if ((scsi_debug_every_nth != 0) &&
3868 (SCSI_DEBUG_OPT_RARE_TSF & scsi_debug_opts) &&
3869 (scsi_result == 0)) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003870 if ((num_in_q == (qdepth - 1)) &&
3871 (atomic_inc_return(&sdebug_a_tsf) >=
3872 abs(scsi_debug_every_nth))) {
3873 atomic_set(&sdebug_a_tsf, 0);
3874 inject = 1;
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003875 scsi_result = device_qfull_result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003876 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003877 }
3878
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003879 k = find_first_zero_bit(queued_in_use_bm, scsi_debug_max_queue);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003880 if (k >= scsi_debug_max_queue) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003881 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003882 if (scsi_result)
3883 goto respond_in_thread;
3884 else if (SCSI_DEBUG_OPT_ALL_TSF & scsi_debug_opts)
3885 scsi_result = device_qfull_result;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003886 if (SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts)
3887 sdev_printk(KERN_INFO, sdp,
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003888 "%s: max_queue=%d exceeded, %s\n",
3889 __func__, scsi_debug_max_queue,
3890 (scsi_result ? "status: TASK SET FULL" :
3891 "report: host busy"));
3892 if (scsi_result)
3893 goto respond_in_thread;
3894 else
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003895 return SCSI_MLQUEUE_HOST_BUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003896 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003897 __set_bit(k, queued_in_use_bm);
3898 atomic_inc(&devip->num_in_q);
3899 sqcp = &queued_arr[k];
3900 sqcp->a_cmnd = cmnd;
3901 cmnd->result = scsi_result;
3902 spin_unlock_irqrestore(&queued_arr_lock, iflags);
3903 if (delta_jiff > 0) {
3904 if (NULL == sqcp->cmnd_timerp) {
3905 sqcp->cmnd_timerp = kmalloc(sizeof(struct timer_list),
3906 GFP_ATOMIC);
3907 if (NULL == sqcp->cmnd_timerp)
3908 return SCSI_MLQUEUE_HOST_BUSY;
3909 init_timer(sqcp->cmnd_timerp);
3910 }
3911 sqcp->cmnd_timerp->function = sdebug_q_cmd_complete;
3912 sqcp->cmnd_timerp->data = k;
3913 sqcp->cmnd_timerp->expires = get_jiffies_64() + delta_jiff;
3914 add_timer(sqcp->cmnd_timerp);
3915 } else if (scsi_debug_ndelay > 0) {
3916 ktime_t kt = ktime_set(0, scsi_debug_ndelay);
3917 struct sdebug_hrtimer *sd_hp = sqcp->sd_hrtp;
3918
3919 if (NULL == sd_hp) {
3920 sd_hp = kmalloc(sizeof(*sd_hp), GFP_ATOMIC);
3921 if (NULL == sd_hp)
3922 return SCSI_MLQUEUE_HOST_BUSY;
3923 sqcp->sd_hrtp = sd_hp;
3924 hrtimer_init(&sd_hp->hrt, CLOCK_MONOTONIC,
3925 HRTIMER_MODE_REL);
3926 sd_hp->hrt.function = sdebug_q_cmd_hrt_complete;
3927 sd_hp->qa_indx = k;
3928 }
3929 hrtimer_start(&sd_hp->hrt, kt, HRTIMER_MODE_REL);
3930 } else { /* delay < 0 */
3931 if (NULL == sqcp->tletp) {
3932 sqcp->tletp = kmalloc(sizeof(*sqcp->tletp),
3933 GFP_ATOMIC);
3934 if (NULL == sqcp->tletp)
3935 return SCSI_MLQUEUE_HOST_BUSY;
3936 tasklet_init(sqcp->tletp,
3937 sdebug_q_cmd_complete, k);
3938 }
3939 if (-1 == delta_jiff)
3940 tasklet_hi_schedule(sqcp->tletp);
3941 else
3942 tasklet_schedule(sqcp->tletp);
3943 }
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003944 if ((SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts) &&
3945 (scsi_result == device_qfull_result))
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003946 sdev_printk(KERN_INFO, sdp,
3947 "%s: num_in_q=%d +1, %s%s\n", __func__,
3948 num_in_q, (inject ? "<inject> " : ""),
3949 "status: TASK SET FULL");
3950 return 0;
Douglas Gilbertcd62b7d2014-08-05 12:20:46 +02003951
3952respond_in_thread: /* call back to mid-layer using invocation thread */
3953 cmnd->result = scsi_result;
3954 cmnd->scsi_done(cmnd);
3955 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003956}
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003957
Douglas Gilbert23183912006-09-16 20:30:47 -04003958/* Note: The following macros create attribute files in the
3959 /sys/module/scsi_debug/parameters directory. Unfortunately this
3960 driver is unaware of a change and cannot trigger auxiliary actions
3961 as it can when the corresponding attribute in the
3962 /sys/bus/pseudo/drivers/scsi_debug directory is changed.
3963 */
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003964module_param_named(add_host, scsi_debug_add_host, int, S_IRUGO | S_IWUSR);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05003965module_param_named(ato, scsi_debug_ato, int, S_IRUGO);
Akinobu Mita0759c662014-02-26 22:57:04 +09003966module_param_named(clustering, scsi_debug_clustering, bool, S_IRUGO | S_IWUSR);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003967module_param_named(delay, scsi_debug_delay, int, S_IRUGO | S_IWUSR);
3968module_param_named(dev_size_mb, scsi_debug_dev_size_mb, int, S_IRUGO);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05003969module_param_named(dif, scsi_debug_dif, int, S_IRUGO);
3970module_param_named(dix, scsi_debug_dix, int, S_IRUGO);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003971module_param_named(dsense, scsi_debug_dsense, int, S_IRUGO | S_IWUSR);
3972module_param_named(every_nth, scsi_debug_every_nth, int, S_IRUGO | S_IWUSR);
Douglas Gilbert23183912006-09-16 20:30:47 -04003973module_param_named(fake_rw, scsi_debug_fake_rw, int, S_IRUGO | S_IWUSR);
Akinobu Mita68aee7b2013-09-18 21:27:27 +09003974module_param_named(guard, scsi_debug_guard, uint, S_IRUGO);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003975module_param_named(host_lock, scsi_debug_host_lock, bool, S_IRUGO | S_IWUSR);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05003976module_param_named(lbpu, scsi_debug_lbpu, int, S_IRUGO);
3977module_param_named(lbpws, scsi_debug_lbpws, int, S_IRUGO);
3978module_param_named(lbpws10, scsi_debug_lbpws10, int, S_IRUGO);
Eric Sandeenbe1dd782012-03-08 00:03:59 -06003979module_param_named(lbprz, scsi_debug_lbprz, int, S_IRUGO);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05003980module_param_named(lowest_aligned, scsi_debug_lowest_aligned, int, S_IRUGO);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003981module_param_named(max_luns, scsi_debug_max_luns, int, S_IRUGO | S_IWUSR);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04003982module_param_named(max_queue, scsi_debug_max_queue, int, S_IRUGO | S_IWUSR);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04003983module_param_named(ndelay, scsi_debug_ndelay, int, S_IRUGO | S_IWUSR);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003984module_param_named(no_lun_0, scsi_debug_no_lun_0, int, S_IRUGO | S_IWUSR);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04003985module_param_named(no_uld, scsi_debug_no_uld, int, S_IRUGO);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003986module_param_named(num_parts, scsi_debug_num_parts, int, S_IRUGO);
3987module_param_named(num_tgts, scsi_debug_num_tgts, int, S_IRUGO | S_IWUSR);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05003988module_param_named(opt_blks, scsi_debug_opt_blks, int, S_IRUGO);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003989module_param_named(opts, scsi_debug_opts, int, S_IRUGO | S_IWUSR);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05003990module_param_named(physblk_exp, scsi_debug_physblk_exp, int, S_IRUGO);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003991module_param_named(ptype, scsi_debug_ptype, int, S_IRUGO | S_IWUSR);
Martin Pittd9867882012-09-06 12:04:33 +02003992module_param_named(removable, scsi_debug_removable, bool, S_IRUGO | S_IWUSR);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04003993module_param_named(scsi_level, scsi_debug_scsi_level, int, S_IRUGO);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05003994module_param_named(sector_size, scsi_debug_sector_size, int, S_IRUGO);
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05003995module_param_named(strict, scsi_debug_strict, bool, S_IRUGO | S_IWUSR);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05003996module_param_named(unmap_alignment, scsi_debug_unmap_alignment, int, S_IRUGO);
3997module_param_named(unmap_granularity, scsi_debug_unmap_granularity, int, S_IRUGO);
3998module_param_named(unmap_max_blocks, scsi_debug_unmap_max_blocks, int, S_IRUGO);
3999module_param_named(unmap_max_desc, scsi_debug_unmap_max_desc, int, S_IRUGO);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004000module_param_named(virtual_gb, scsi_debug_virtual_gb, int, S_IRUGO | S_IWUSR);
Douglas Gilbert23183912006-09-16 20:30:47 -04004001module_param_named(vpd_use_hostno, scsi_debug_vpd_use_hostno, int,
4002 S_IRUGO | S_IWUSR);
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004003module_param_named(write_same_length, scsi_debug_write_same_length, int,
4004 S_IRUGO | S_IWUSR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004005
4006MODULE_AUTHOR("Eric Youngdale + Douglas Gilbert");
4007MODULE_DESCRIPTION("SCSI debug adapter driver");
4008MODULE_LICENSE("GPL");
4009MODULE_VERSION(SCSI_DEBUG_VERSION);
4010
4011MODULE_PARM_DESC(add_host, "0..127 hosts allowed(def=1)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004012MODULE_PARM_DESC(ato, "application tag ownership: 0=disk 1=host (def=1)");
Akinobu Mita0759c662014-02-26 22:57:04 +09004013MODULE_PARM_DESC(clustering, "when set enables larger transfers (def=0)");
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004014MODULE_PARM_DESC(delay, "response delay (def=1 jiffy); 0:imm, -1,-2:tiny");
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05004015MODULE_PARM_DESC(dev_size_mb, "size in MiB of ram shared by devs(def=8)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004016MODULE_PARM_DESC(dif, "data integrity field type: 0-3 (def=0)");
4017MODULE_PARM_DESC(dix, "data integrity extensions mask (def=0)");
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004018MODULE_PARM_DESC(dsense, "use descriptor sense format(def=0 -> fixed)");
Randy Dunlapbeb87c32007-06-11 11:36:40 -07004019MODULE_PARM_DESC(every_nth, "timeout every nth command(def=0)");
Douglas Gilbert23183912006-09-16 20:30:47 -04004020MODULE_PARM_DESC(fake_rw, "fake reads/writes instead of copying (def=0)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004021MODULE_PARM_DESC(guard, "protection checksum: 0=crc, 1=ip (def=0)");
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004022MODULE_PARM_DESC(host_lock, "use host_lock around all commands (def=0)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004023MODULE_PARM_DESC(lbpu, "enable LBP, support UNMAP command (def=0)");
4024MODULE_PARM_DESC(lbpws, "enable LBP, support WRITE SAME(16) with UNMAP bit (def=0)");
4025MODULE_PARM_DESC(lbpws10, "enable LBP, support WRITE SAME(10) with UNMAP bit (def=0)");
Eric Sandeenbe1dd782012-03-08 00:03:59 -06004026MODULE_PARM_DESC(lbprz, "unmapped blocks return 0 on read (def=1)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004027MODULE_PARM_DESC(lowest_aligned, "lowest aligned lba (def=0)");
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004028MODULE_PARM_DESC(max_luns, "number of LUNs per target to simulate(def=1)");
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004029MODULE_PARM_DESC(max_queue, "max number of queued commands (1 to max(def))");
4030MODULE_PARM_DESC(ndelay, "response delay in nanoseconds (def=0 -> ignore)");
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004031MODULE_PARM_DESC(no_lun_0, "no LU number 0 (def=0 -> have lun 0)");
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004032MODULE_PARM_DESC(no_uld, "stop ULD (e.g. sd driver) attaching (def=0))");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004033MODULE_PARM_DESC(num_parts, "number of partitions(def=0)");
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004034MODULE_PARM_DESC(num_tgts, "number of targets per host to simulate(def=1)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004035MODULE_PARM_DESC(opt_blks, "optimal transfer length in block (def=64)");
Douglas Gilbert6f3cbf52007-01-05 00:05:25 -05004036MODULE_PARM_DESC(opts, "1->noise, 2->medium_err, 4->timeout, 8->recovered_err... (def=0)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004037MODULE_PARM_DESC(physblk_exp, "physical block exponent (def=0)");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004038MODULE_PARM_DESC(ptype, "SCSI peripheral type(def=0[disk])");
Martin Pittd9867882012-09-06 12:04:33 +02004039MODULE_PARM_DESC(removable, "claim to have removable media (def=0)");
Douglas Gilberte46b0342014-08-05 12:21:53 +02004040MODULE_PARM_DESC(scsi_level, "SCSI level to simulate(def=6[SPC-4])");
Martin K. Petersenea61fca2009-05-15 00:40:33 -04004041MODULE_PARM_DESC(sector_size, "logical block size in bytes (def=512)");
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05004042MODULE_PARM_DESC(strict, "stricter checks: reserved field in cdb (def=0)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004043MODULE_PARM_DESC(unmap_alignment, "lowest aligned thin provisioning lba (def=0)");
4044MODULE_PARM_DESC(unmap_granularity, "thin provisioning granularity in blocks (def=1)");
Martin K. Petersen60147592010-08-19 11:49:00 -04004045MODULE_PARM_DESC(unmap_max_blocks, "max # of blocks can be unmapped in one cmd (def=0xffffffff)");
4046MODULE_PARM_DESC(unmap_max_desc, "max # of ranges that can be unmapped in one cmd (def=256)");
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05004047MODULE_PARM_DESC(virtual_gb, "virtual gigabyte (GiB) size (def=0 -> use dev_size_mb)");
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004048MODULE_PARM_DESC(vpd_use_hostno, "0 -> dev ids ignore hostno (def=1 -> unique dev ids)");
4049MODULE_PARM_DESC(write_same_length, "Maximum blocks per WRITE SAME cmd (def=0xffff)");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004050
4051static char sdebug_info[256];
4052
4053static const char * scsi_debug_info(struct Scsi_Host * shp)
4054{
4055 sprintf(sdebug_info, "scsi_debug, version %s [%s], "
4056 "dev_size_mb=%d, opts=0x%x", SCSI_DEBUG_VERSION,
4057 scsi_debug_version_date, scsi_debug_dev_size_mb,
4058 scsi_debug_opts);
4059 return sdebug_info;
4060}
4061
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004062/* 'echo <val> > /proc/scsi/scsi_debug/<host_id>' writes to opts */
Al Viroc8ed5552013-03-31 01:46:06 -04004063static int scsi_debug_write_info(struct Scsi_Host *host, char *buffer, int length)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004064{
Al Viroc8ed5552013-03-31 01:46:06 -04004065 char arr[16];
4066 int opts;
4067 int minLen = length > 15 ? 15 : length;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004068
Al Viroc8ed5552013-03-31 01:46:06 -04004069 if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
4070 return -EACCES;
4071 memcpy(arr, buffer, minLen);
4072 arr[minLen] = '\0';
4073 if (1 != sscanf(arr, "%d", &opts))
4074 return -EINVAL;
4075 scsi_debug_opts = opts;
4076 if (scsi_debug_every_nth != 0)
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004077 atomic_set(&sdebug_cmnd_count, 0);
Al Viroc8ed5552013-03-31 01:46:06 -04004078 return length;
4079}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004080
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004081/* Output seen with 'cat /proc/scsi/scsi_debug/<host_id>'. It will be the
4082 * same for each scsi_debug host (if more than one). Some of the counters
4083 * output are not atomics so might be inaccurate in a busy system. */
Al Viroc8ed5552013-03-31 01:46:06 -04004084static int scsi_debug_show_info(struct seq_file *m, struct Scsi_Host *host)
4085{
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004086 int f, l;
4087 char b[32];
4088
4089 if (scsi_debug_every_nth > 0)
4090 snprintf(b, sizeof(b), " (curr:%d)",
4091 ((SCSI_DEBUG_OPT_RARE_TSF & scsi_debug_opts) ?
4092 atomic_read(&sdebug_a_tsf) :
4093 atomic_read(&sdebug_cmnd_count)));
4094 else
4095 b[0] = '\0';
4096
4097 seq_printf(m, "scsi_debug adapter driver, version %s [%s]\n"
4098 "num_tgts=%d, shared (ram) size=%d MB, opts=0x%x, "
4099 "every_nth=%d%s\n"
4100 "delay=%d, ndelay=%d, max_luns=%d, q_completions=%d\n"
4101 "sector_size=%d bytes, cylinders=%d, heads=%d, sectors=%d\n"
4102 "command aborts=%d; RESETs: device=%d, target=%d, bus=%d, "
4103 "host=%d\ndix_reads=%d dix_writes=%d dif_errors=%d "
4104 "usec_in_jiffy=%lu\n",
4105 SCSI_DEBUG_VERSION, scsi_debug_version_date,
4106 scsi_debug_num_tgts, scsi_debug_dev_size_mb, scsi_debug_opts,
4107 scsi_debug_every_nth, b, scsi_debug_delay, scsi_debug_ndelay,
4108 scsi_debug_max_luns, atomic_read(&sdebug_completions),
4109 scsi_debug_sector_size, sdebug_cylinders_per, sdebug_heads,
4110 sdebug_sectors_per, num_aborts, num_dev_resets,
4111 num_target_resets, num_bus_resets, num_host_resets,
4112 dix_reads, dix_writes, dif_errors, TICK_NSEC / 1000);
4113
4114 f = find_first_bit(queued_in_use_bm, scsi_debug_max_queue);
4115 if (f != scsi_debug_max_queue) {
4116 l = find_last_bit(queued_in_use_bm, scsi_debug_max_queue);
4117 seq_printf(m, " %s BUSY: first,last bits set: %d,%d\n",
4118 "queued_in_use_bm", f, l);
4119 }
Al Viroc8ed5552013-03-31 01:46:06 -04004120 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004121}
4122
Akinobu Mita82069372013-10-14 22:48:04 +09004123static ssize_t delay_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004124{
4125 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_delay);
4126}
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004127/* Returns -EBUSY if delay is being changed and commands are queued */
Akinobu Mita82069372013-10-14 22:48:04 +09004128static ssize_t delay_store(struct device_driver *ddp, const char *buf,
4129 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004130{
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004131 int delay, res;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004132
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004133 if ((count > 0) && (1 == sscanf(buf, "%d", &delay))) {
4134 res = count;
4135 if (scsi_debug_delay != delay) {
4136 unsigned long iflags;
4137 int k;
4138
4139 spin_lock_irqsave(&queued_arr_lock, iflags);
4140 k = find_first_bit(queued_in_use_bm,
4141 scsi_debug_max_queue);
4142 if (k != scsi_debug_max_queue)
4143 res = -EBUSY; /* have queued commands */
4144 else {
4145 scsi_debug_delay = delay;
4146 scsi_debug_ndelay = 0;
4147 }
4148 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004149 }
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004150 return res;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004151 }
4152 return -EINVAL;
4153}
Akinobu Mita82069372013-10-14 22:48:04 +09004154static DRIVER_ATTR_RW(delay);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004155
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004156static ssize_t ndelay_show(struct device_driver *ddp, char *buf)
4157{
4158 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_ndelay);
4159}
4160/* Returns -EBUSY if ndelay is being changed and commands are queued */
4161/* If > 0 and accepted then scsi_debug_delay is set to DELAY_OVERRIDDEN */
4162static ssize_t ndelay_store(struct device_driver *ddp, const char *buf,
4163 size_t count)
4164{
4165 unsigned long iflags;
4166 int ndelay, res, k;
4167
4168 if ((count > 0) && (1 == sscanf(buf, "%d", &ndelay)) &&
4169 (ndelay >= 0) && (ndelay < 1000000000)) {
4170 res = count;
4171 if (scsi_debug_ndelay != ndelay) {
4172 spin_lock_irqsave(&queued_arr_lock, iflags);
4173 k = find_first_bit(queued_in_use_bm,
4174 scsi_debug_max_queue);
4175 if (k != scsi_debug_max_queue)
4176 res = -EBUSY; /* have queued commands */
4177 else {
4178 scsi_debug_ndelay = ndelay;
4179 scsi_debug_delay = ndelay ? DELAY_OVERRIDDEN
4180 : DEF_DELAY;
4181 }
4182 spin_unlock_irqrestore(&queued_arr_lock, iflags);
4183 }
4184 return res;
4185 }
4186 return -EINVAL;
4187}
4188static DRIVER_ATTR_RW(ndelay);
4189
Akinobu Mita82069372013-10-14 22:48:04 +09004190static ssize_t opts_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004191{
4192 return scnprintf(buf, PAGE_SIZE, "0x%x\n", scsi_debug_opts);
4193}
4194
Akinobu Mita82069372013-10-14 22:48:04 +09004195static ssize_t opts_store(struct device_driver *ddp, const char *buf,
4196 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004197{
4198 int opts;
4199 char work[20];
4200
4201 if (1 == sscanf(buf, "%10s", work)) {
Rasmus Villemoes48a96872014-10-13 15:54:44 -07004202 if (0 == strncasecmp(work,"0x", 2)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004203 if (1 == sscanf(&work[2], "%x", &opts))
4204 goto opts_done;
4205 } else {
4206 if (1 == sscanf(work, "%d", &opts))
4207 goto opts_done;
4208 }
4209 }
4210 return -EINVAL;
4211opts_done:
4212 scsi_debug_opts = opts;
Douglas Gilbert817fd662014-11-24 20:18:02 -05004213 if (SCSI_DEBUG_OPT_RECOVERED_ERR & opts)
4214 sdebug_any_injecting_opt = true;
4215 else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & opts)
4216 sdebug_any_injecting_opt = true;
4217 else if (SCSI_DEBUG_OPT_DIF_ERR & opts)
4218 sdebug_any_injecting_opt = true;
4219 else if (SCSI_DEBUG_OPT_DIX_ERR & opts)
4220 sdebug_any_injecting_opt = true;
4221 else if (SCSI_DEBUG_OPT_SHORT_TRANSFER & opts)
4222 sdebug_any_injecting_opt = true;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004223 atomic_set(&sdebug_cmnd_count, 0);
4224 atomic_set(&sdebug_a_tsf, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004225 return count;
4226}
Akinobu Mita82069372013-10-14 22:48:04 +09004227static DRIVER_ATTR_RW(opts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004228
Akinobu Mita82069372013-10-14 22:48:04 +09004229static ssize_t ptype_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004230{
4231 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_ptype);
4232}
Akinobu Mita82069372013-10-14 22:48:04 +09004233static ssize_t ptype_store(struct device_driver *ddp, const char *buf,
4234 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004235{
4236 int n;
4237
4238 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
4239 scsi_debug_ptype = n;
4240 return count;
4241 }
4242 return -EINVAL;
4243}
Akinobu Mita82069372013-10-14 22:48:04 +09004244static DRIVER_ATTR_RW(ptype);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004245
Akinobu Mita82069372013-10-14 22:48:04 +09004246static ssize_t dsense_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004247{
4248 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dsense);
4249}
Akinobu Mita82069372013-10-14 22:48:04 +09004250static ssize_t dsense_store(struct device_driver *ddp, const char *buf,
4251 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004252{
4253 int n;
4254
4255 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
4256 scsi_debug_dsense = n;
4257 return count;
4258 }
4259 return -EINVAL;
4260}
Akinobu Mita82069372013-10-14 22:48:04 +09004261static DRIVER_ATTR_RW(dsense);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004262
Akinobu Mita82069372013-10-14 22:48:04 +09004263static ssize_t fake_rw_show(struct device_driver *ddp, char *buf)
Douglas Gilbert23183912006-09-16 20:30:47 -04004264{
4265 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_fake_rw);
4266}
Akinobu Mita82069372013-10-14 22:48:04 +09004267static ssize_t fake_rw_store(struct device_driver *ddp, const char *buf,
4268 size_t count)
Douglas Gilbert23183912006-09-16 20:30:47 -04004269{
4270 int n;
4271
4272 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004273 n = (n > 0);
4274 scsi_debug_fake_rw = (scsi_debug_fake_rw > 0);
4275 if (scsi_debug_fake_rw != n) {
4276 if ((0 == n) && (NULL == fake_storep)) {
4277 unsigned long sz =
4278 (unsigned long)scsi_debug_dev_size_mb *
4279 1048576;
4280
4281 fake_storep = vmalloc(sz);
4282 if (NULL == fake_storep) {
4283 pr_err("%s: out of memory, 9\n",
4284 __func__);
4285 return -ENOMEM;
4286 }
4287 memset(fake_storep, 0, sz);
4288 }
4289 scsi_debug_fake_rw = n;
4290 }
Douglas Gilbert23183912006-09-16 20:30:47 -04004291 return count;
4292 }
4293 return -EINVAL;
4294}
Akinobu Mita82069372013-10-14 22:48:04 +09004295static DRIVER_ATTR_RW(fake_rw);
Douglas Gilbert23183912006-09-16 20:30:47 -04004296
Akinobu Mita82069372013-10-14 22:48:04 +09004297static ssize_t no_lun_0_show(struct device_driver *ddp, char *buf)
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004298{
4299 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_no_lun_0);
4300}
Akinobu Mita82069372013-10-14 22:48:04 +09004301static ssize_t no_lun_0_store(struct device_driver *ddp, const char *buf,
4302 size_t count)
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004303{
4304 int n;
4305
4306 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
4307 scsi_debug_no_lun_0 = n;
4308 return count;
4309 }
4310 return -EINVAL;
4311}
Akinobu Mita82069372013-10-14 22:48:04 +09004312static DRIVER_ATTR_RW(no_lun_0);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004313
Akinobu Mita82069372013-10-14 22:48:04 +09004314static ssize_t num_tgts_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004315{
4316 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_num_tgts);
4317}
Akinobu Mita82069372013-10-14 22:48:04 +09004318static ssize_t num_tgts_store(struct device_driver *ddp, const char *buf,
4319 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004320{
4321 int n;
4322
4323 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
4324 scsi_debug_num_tgts = n;
4325 sdebug_max_tgts_luns();
4326 return count;
4327 }
4328 return -EINVAL;
4329}
Akinobu Mita82069372013-10-14 22:48:04 +09004330static DRIVER_ATTR_RW(num_tgts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004331
Akinobu Mita82069372013-10-14 22:48:04 +09004332static ssize_t dev_size_mb_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004333{
4334 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dev_size_mb);
4335}
Akinobu Mita82069372013-10-14 22:48:04 +09004336static DRIVER_ATTR_RO(dev_size_mb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004337
Akinobu Mita82069372013-10-14 22:48:04 +09004338static ssize_t num_parts_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004339{
4340 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_num_parts);
4341}
Akinobu Mita82069372013-10-14 22:48:04 +09004342static DRIVER_ATTR_RO(num_parts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004343
Akinobu Mita82069372013-10-14 22:48:04 +09004344static ssize_t every_nth_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004345{
4346 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_every_nth);
4347}
Akinobu Mita82069372013-10-14 22:48:04 +09004348static ssize_t every_nth_store(struct device_driver *ddp, const char *buf,
4349 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004350{
4351 int nth;
4352
4353 if ((count > 0) && (1 == sscanf(buf, "%d", &nth))) {
4354 scsi_debug_every_nth = nth;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004355 atomic_set(&sdebug_cmnd_count, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004356 return count;
4357 }
4358 return -EINVAL;
4359}
Akinobu Mita82069372013-10-14 22:48:04 +09004360static DRIVER_ATTR_RW(every_nth);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004361
Akinobu Mita82069372013-10-14 22:48:04 +09004362static ssize_t max_luns_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004363{
4364 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_max_luns);
4365}
Akinobu Mita82069372013-10-14 22:48:04 +09004366static ssize_t max_luns_store(struct device_driver *ddp, const char *buf,
4367 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004368{
4369 int n;
4370
4371 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
4372 scsi_debug_max_luns = n;
4373 sdebug_max_tgts_luns();
4374 return count;
4375 }
4376 return -EINVAL;
4377}
Akinobu Mita82069372013-10-14 22:48:04 +09004378static DRIVER_ATTR_RW(max_luns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004379
Akinobu Mita82069372013-10-14 22:48:04 +09004380static ssize_t max_queue_show(struct device_driver *ddp, char *buf)
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004381{
4382 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_max_queue);
4383}
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004384/* N.B. max_queue can be changed while there are queued commands. In flight
4385 * commands beyond the new max_queue will be completed. */
Akinobu Mita82069372013-10-14 22:48:04 +09004386static ssize_t max_queue_store(struct device_driver *ddp, const char *buf,
4387 size_t count)
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004388{
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004389 unsigned long iflags;
4390 int n, k;
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004391
4392 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n > 0) &&
4393 (n <= SCSI_DEBUG_CANQUEUE)) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004394 spin_lock_irqsave(&queued_arr_lock, iflags);
4395 k = find_last_bit(queued_in_use_bm, SCSI_DEBUG_CANQUEUE);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004396 scsi_debug_max_queue = n;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004397 if (SCSI_DEBUG_CANQUEUE == k)
4398 atomic_set(&retired_max_queue, 0);
4399 else if (k >= n)
4400 atomic_set(&retired_max_queue, k + 1);
4401 else
4402 atomic_set(&retired_max_queue, 0);
4403 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004404 return count;
4405 }
4406 return -EINVAL;
4407}
Akinobu Mita82069372013-10-14 22:48:04 +09004408static DRIVER_ATTR_RW(max_queue);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004409
Akinobu Mita82069372013-10-14 22:48:04 +09004410static ssize_t no_uld_show(struct device_driver *ddp, char *buf)
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004411{
4412 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_no_uld);
4413}
Akinobu Mita82069372013-10-14 22:48:04 +09004414static DRIVER_ATTR_RO(no_uld);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04004415
Akinobu Mita82069372013-10-14 22:48:04 +09004416static ssize_t scsi_level_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004417{
4418 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_scsi_level);
4419}
Akinobu Mita82069372013-10-14 22:48:04 +09004420static DRIVER_ATTR_RO(scsi_level);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004421
Akinobu Mita82069372013-10-14 22:48:04 +09004422static ssize_t virtual_gb_show(struct device_driver *ddp, char *buf)
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004423{
4424 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_virtual_gb);
4425}
Akinobu Mita82069372013-10-14 22:48:04 +09004426static ssize_t virtual_gb_store(struct device_driver *ddp, const char *buf,
4427 size_t count)
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004428{
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05004429 int n;
Douglas Gilbert0d01c5d2014-11-24 20:27:51 -05004430 bool changed;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004431
4432 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
Douglas Gilbert0d01c5d2014-11-24 20:27:51 -05004433 changed = (scsi_debug_virtual_gb != n);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004434 scsi_debug_virtual_gb = n;
FUJITA Tomonori28898872008-03-30 00:59:55 +09004435 sdebug_capacity = get_sdebug_capacity();
Douglas Gilbert0d01c5d2014-11-24 20:27:51 -05004436 if (changed) {
4437 struct sdebug_host_info *sdhp;
4438 struct sdebug_dev_info *dp;
FUJITA Tomonori28898872008-03-30 00:59:55 +09004439
Douglas Gilbert0d01c5d2014-11-24 20:27:51 -05004440 list_for_each_entry(sdhp, &sdebug_host_list,
4441 host_list) {
4442 list_for_each_entry(dp, &sdhp->dev_info_list,
4443 dev_list) {
4444 set_bit(SDEBUG_UA_CAPACITY_CHANGED,
4445 dp->uas_bm);
4446 }
4447 }
4448 }
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004449 return count;
4450 }
4451 return -EINVAL;
4452}
Akinobu Mita82069372013-10-14 22:48:04 +09004453static DRIVER_ATTR_RW(virtual_gb);
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004454
Akinobu Mita82069372013-10-14 22:48:04 +09004455static ssize_t add_host_show(struct device_driver *ddp, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004456{
4457 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_add_host);
4458}
4459
Akinobu Mita82069372013-10-14 22:48:04 +09004460static ssize_t add_host_store(struct device_driver *ddp, const char *buf,
4461 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004462{
FUJITA Tomonorif3df41c2008-03-20 11:09:15 +09004463 int delta_hosts;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004464
FUJITA Tomonorif3df41c2008-03-20 11:09:15 +09004465 if (sscanf(buf, "%d", &delta_hosts) != 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004466 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004467 if (delta_hosts > 0) {
4468 do {
4469 sdebug_add_adapter();
4470 } while (--delta_hosts);
4471 } else if (delta_hosts < 0) {
4472 do {
4473 sdebug_remove_adapter();
4474 } while (++delta_hosts);
4475 }
4476 return count;
4477}
Akinobu Mita82069372013-10-14 22:48:04 +09004478static DRIVER_ATTR_RW(add_host);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004479
Akinobu Mita82069372013-10-14 22:48:04 +09004480static ssize_t vpd_use_hostno_show(struct device_driver *ddp, char *buf)
Douglas Gilbert23183912006-09-16 20:30:47 -04004481{
4482 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_vpd_use_hostno);
4483}
Akinobu Mita82069372013-10-14 22:48:04 +09004484static ssize_t vpd_use_hostno_store(struct device_driver *ddp, const char *buf,
4485 size_t count)
Douglas Gilbert23183912006-09-16 20:30:47 -04004486{
4487 int n;
4488
4489 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
4490 scsi_debug_vpd_use_hostno = n;
4491 return count;
4492 }
4493 return -EINVAL;
4494}
Akinobu Mita82069372013-10-14 22:48:04 +09004495static DRIVER_ATTR_RW(vpd_use_hostno);
Douglas Gilbert23183912006-09-16 20:30:47 -04004496
Akinobu Mita82069372013-10-14 22:48:04 +09004497static ssize_t sector_size_show(struct device_driver *ddp, char *buf)
Martin K. Petersen597136a2008-06-05 00:12:59 -04004498{
4499 return scnprintf(buf, PAGE_SIZE, "%u\n", scsi_debug_sector_size);
4500}
Akinobu Mita82069372013-10-14 22:48:04 +09004501static DRIVER_ATTR_RO(sector_size);
Martin K. Petersen597136a2008-06-05 00:12:59 -04004502
Akinobu Mita82069372013-10-14 22:48:04 +09004503static ssize_t dix_show(struct device_driver *ddp, char *buf)
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004504{
4505 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dix);
4506}
Akinobu Mita82069372013-10-14 22:48:04 +09004507static DRIVER_ATTR_RO(dix);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004508
Akinobu Mita82069372013-10-14 22:48:04 +09004509static ssize_t dif_show(struct device_driver *ddp, char *buf)
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004510{
4511 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dif);
4512}
Akinobu Mita82069372013-10-14 22:48:04 +09004513static DRIVER_ATTR_RO(dif);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004514
Akinobu Mita82069372013-10-14 22:48:04 +09004515static ssize_t guard_show(struct device_driver *ddp, char *buf)
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004516{
Akinobu Mita68aee7b2013-09-18 21:27:27 +09004517 return scnprintf(buf, PAGE_SIZE, "%u\n", scsi_debug_guard);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004518}
Akinobu Mita82069372013-10-14 22:48:04 +09004519static DRIVER_ATTR_RO(guard);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004520
Akinobu Mita82069372013-10-14 22:48:04 +09004521static ssize_t ato_show(struct device_driver *ddp, char *buf)
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004522{
4523 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_ato);
4524}
Akinobu Mita82069372013-10-14 22:48:04 +09004525static DRIVER_ATTR_RO(ato);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004526
Akinobu Mita82069372013-10-14 22:48:04 +09004527static ssize_t map_show(struct device_driver *ddp, char *buf)
Martin K. Petersen44d92692009-10-15 14:45:27 -04004528{
4529 ssize_t count;
4530
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004531 if (!scsi_debug_lbp())
Martin K. Petersen44d92692009-10-15 14:45:27 -04004532 return scnprintf(buf, PAGE_SIZE, "0-%u\n",
4533 sdebug_store_sectors);
4534
4535 count = bitmap_scnlistprintf(buf, PAGE_SIZE, map_storep, map_size);
4536
4537 buf[count++] = '\n';
4538 buf[count++] = 0;
4539
4540 return count;
4541}
Akinobu Mita82069372013-10-14 22:48:04 +09004542static DRIVER_ATTR_RO(map);
Martin K. Petersen44d92692009-10-15 14:45:27 -04004543
Akinobu Mita82069372013-10-14 22:48:04 +09004544static ssize_t removable_show(struct device_driver *ddp, char *buf)
Martin Pittd9867882012-09-06 12:04:33 +02004545{
4546 return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_removable ? 1 : 0);
4547}
Akinobu Mita82069372013-10-14 22:48:04 +09004548static ssize_t removable_store(struct device_driver *ddp, const char *buf,
4549 size_t count)
Martin Pittd9867882012-09-06 12:04:33 +02004550{
4551 int n;
4552
4553 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
4554 scsi_debug_removable = (n > 0);
4555 return count;
4556 }
4557 return -EINVAL;
4558}
Akinobu Mita82069372013-10-14 22:48:04 +09004559static DRIVER_ATTR_RW(removable);
Martin Pittd9867882012-09-06 12:04:33 +02004560
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004561static ssize_t host_lock_show(struct device_driver *ddp, char *buf)
4562{
4563 return scnprintf(buf, PAGE_SIZE, "%d\n", !!scsi_debug_host_lock);
4564}
4565/* Returns -EBUSY if host_lock is being changed and commands are queued */
4566static ssize_t host_lock_store(struct device_driver *ddp, const char *buf,
4567 size_t count)
4568{
4569 int n, res;
4570
4571 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
4572 bool new_host_lock = (n > 0);
4573
4574 res = count;
4575 if (new_host_lock != scsi_debug_host_lock) {
4576 unsigned long iflags;
4577 int k;
4578
4579 spin_lock_irqsave(&queued_arr_lock, iflags);
4580 k = find_first_bit(queued_in_use_bm,
4581 scsi_debug_max_queue);
4582 if (k != scsi_debug_max_queue)
4583 res = -EBUSY; /* have queued commands */
4584 else
4585 scsi_debug_host_lock = new_host_lock;
4586 spin_unlock_irqrestore(&queued_arr_lock, iflags);
4587 }
4588 return res;
4589 }
4590 return -EINVAL;
4591}
4592static DRIVER_ATTR_RW(host_lock);
4593
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05004594static ssize_t strict_show(struct device_driver *ddp, char *buf)
4595{
4596 return scnprintf(buf, PAGE_SIZE, "%d\n", !!scsi_debug_strict);
4597}
4598static ssize_t strict_store(struct device_driver *ddp, const char *buf,
4599 size_t count)
4600{
4601 int n;
4602
4603 if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
4604 scsi_debug_strict = (n > 0);
4605 return count;
4606 }
4607 return -EINVAL;
4608}
4609static DRIVER_ATTR_RW(strict);
4610
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004611
Akinobu Mita82069372013-10-14 22:48:04 +09004612/* Note: The following array creates attribute files in the
Douglas Gilbert23183912006-09-16 20:30:47 -04004613 /sys/bus/pseudo/drivers/scsi_debug directory. The advantage of these
4614 files (over those found in the /sys/module/scsi_debug/parameters
4615 directory) is that auxiliary actions can be triggered when an attribute
4616 is changed. For example see: sdebug_add_host_store() above.
4617 */
Randy Dunlap6ecaff72006-07-11 20:53:22 -07004618
Akinobu Mita82069372013-10-14 22:48:04 +09004619static struct attribute *sdebug_drv_attrs[] = {
4620 &driver_attr_delay.attr,
4621 &driver_attr_opts.attr,
4622 &driver_attr_ptype.attr,
4623 &driver_attr_dsense.attr,
4624 &driver_attr_fake_rw.attr,
4625 &driver_attr_no_lun_0.attr,
4626 &driver_attr_num_tgts.attr,
4627 &driver_attr_dev_size_mb.attr,
4628 &driver_attr_num_parts.attr,
4629 &driver_attr_every_nth.attr,
4630 &driver_attr_max_luns.attr,
4631 &driver_attr_max_queue.attr,
4632 &driver_attr_no_uld.attr,
4633 &driver_attr_scsi_level.attr,
4634 &driver_attr_virtual_gb.attr,
4635 &driver_attr_add_host.attr,
4636 &driver_attr_vpd_use_hostno.attr,
4637 &driver_attr_sector_size.attr,
4638 &driver_attr_dix.attr,
4639 &driver_attr_dif.attr,
4640 &driver_attr_guard.attr,
4641 &driver_attr_ato.attr,
4642 &driver_attr_map.attr,
4643 &driver_attr_removable.attr,
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004644 &driver_attr_host_lock.attr,
4645 &driver_attr_ndelay.attr,
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05004646 &driver_attr_strict.attr,
Akinobu Mita82069372013-10-14 22:48:04 +09004647 NULL,
4648};
4649ATTRIBUTE_GROUPS(sdebug_drv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004650
Akinobu Mita11ddcec2014-02-26 22:56:59 +09004651static struct device *pseudo_primary;
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09004652
Linus Torvalds1da177e2005-04-16 15:20:36 -07004653static int __init scsi_debug_init(void)
4654{
FUJITA Tomonori5f2578e2008-03-30 00:59:57 +09004655 unsigned long sz;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004656 int host_to_add;
4657 int k;
Randy Dunlap6ecaff72006-07-11 20:53:22 -07004658 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004659
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004660 atomic_set(&sdebug_cmnd_count, 0);
4661 atomic_set(&sdebug_completions, 0);
4662 atomic_set(&retired_max_queue, 0);
4663
4664 if (scsi_debug_ndelay >= 1000000000) {
4665 pr_warn("%s: ndelay must be less than 1 second, ignored\n",
4666 __func__);
4667 scsi_debug_ndelay = 0;
4668 } else if (scsi_debug_ndelay > 0)
4669 scsi_debug_delay = DELAY_OVERRIDDEN;
4670
Martin K. Petersen597136a2008-06-05 00:12:59 -04004671 switch (scsi_debug_sector_size) {
4672 case 512:
4673 case 1024:
4674 case 2048:
4675 case 4096:
4676 break;
4677 default:
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004678 pr_err("%s: invalid sector_size %d\n", __func__,
Martin K. Petersen597136a2008-06-05 00:12:59 -04004679 scsi_debug_sector_size);
4680 return -EINVAL;
4681 }
4682
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004683 switch (scsi_debug_dif) {
4684
4685 case SD_DIF_TYPE0_PROTECTION:
4686 case SD_DIF_TYPE1_PROTECTION:
Martin K. Petersen395cef02009-09-18 17:33:03 -04004687 case SD_DIF_TYPE2_PROTECTION:
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004688 case SD_DIF_TYPE3_PROTECTION:
4689 break;
4690
4691 default:
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004692 pr_err("%s: dif must be 0, 1, 2 or 3\n", __func__);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004693 return -EINVAL;
4694 }
4695
4696 if (scsi_debug_guard > 1) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004697 pr_err("%s: guard must be 0 or 1\n", __func__);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004698 return -EINVAL;
4699 }
4700
4701 if (scsi_debug_ato > 1) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004702 pr_err("%s: ato must be 0 or 1\n", __func__);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004703 return -EINVAL;
4704 }
4705
Martin K. Petersenea61fca2009-05-15 00:40:33 -04004706 if (scsi_debug_physblk_exp > 15) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004707 pr_err("%s: invalid physblk_exp %u\n", __func__,
Martin K. Petersenea61fca2009-05-15 00:40:33 -04004708 scsi_debug_physblk_exp);
4709 return -EINVAL;
4710 }
4711
4712 if (scsi_debug_lowest_aligned > 0x3fff) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004713 pr_err("%s: lowest_aligned too big: %u\n", __func__,
Martin K. Petersenea61fca2009-05-15 00:40:33 -04004714 scsi_debug_lowest_aligned);
4715 return -EINVAL;
4716 }
4717
Linus Torvalds1da177e2005-04-16 15:20:36 -07004718 if (scsi_debug_dev_size_mb < 1)
4719 scsi_debug_dev_size_mb = 1; /* force minimum 1 MB ramdisk */
FUJITA Tomonori5f2578e2008-03-30 00:59:57 +09004720 sz = (unsigned long)scsi_debug_dev_size_mb * 1048576;
Martin K. Petersen597136a2008-06-05 00:12:59 -04004721 sdebug_store_sectors = sz / scsi_debug_sector_size;
FUJITA Tomonori28898872008-03-30 00:59:55 +09004722 sdebug_capacity = get_sdebug_capacity();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004723
4724 /* play around with geometry, don't waste too much on track 0 */
4725 sdebug_heads = 8;
4726 sdebug_sectors_per = 32;
4727 if (scsi_debug_dev_size_mb >= 16)
4728 sdebug_heads = 32;
4729 else if (scsi_debug_dev_size_mb >= 256)
4730 sdebug_heads = 64;
4731 sdebug_cylinders_per = (unsigned long)sdebug_capacity /
4732 (sdebug_sectors_per * sdebug_heads);
4733 if (sdebug_cylinders_per >= 1024) {
4734 /* other LLDs do this; implies >= 1GB ram disk ... */
4735 sdebug_heads = 255;
4736 sdebug_sectors_per = 63;
4737 sdebug_cylinders_per = (unsigned long)sdebug_capacity /
4738 (sdebug_sectors_per * sdebug_heads);
4739 }
4740
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004741 if (0 == scsi_debug_fake_rw) {
4742 fake_storep = vmalloc(sz);
4743 if (NULL == fake_storep) {
4744 pr_err("%s: out of memory, 1\n", __func__);
4745 return -ENOMEM;
4746 }
4747 memset(fake_storep, 0, sz);
4748 if (scsi_debug_num_parts > 0)
4749 sdebug_build_parts(fake_storep, sz);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004750 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004751
Akinobu Mita7cb69d02013-06-29 17:59:16 +09004752 if (scsi_debug_dix) {
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004753 int dif_size;
4754
4755 dif_size = sdebug_store_sectors * sizeof(struct sd_dif_tuple);
4756 dif_storep = vmalloc(dif_size);
4757
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004758 pr_err("%s: dif_storep %u bytes @ %p\n", __func__, dif_size,
4759 dif_storep);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004760
4761 if (dif_storep == NULL) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004762 pr_err("%s: out of mem. (DIX)\n", __func__);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004763 ret = -ENOMEM;
4764 goto free_vm;
4765 }
4766
4767 memset(dif_storep, 0xff, dif_size);
4768 }
4769
Martin K. Petersen5b94e232011-03-08 02:08:11 -05004770 /* Logical Block Provisioning */
4771 if (scsi_debug_lbp()) {
Martin K. Petersen60147592010-08-19 11:49:00 -04004772 scsi_debug_unmap_max_blocks =
4773 clamp(scsi_debug_unmap_max_blocks, 0U, 0xffffffffU);
4774
4775 scsi_debug_unmap_max_desc =
4776 clamp(scsi_debug_unmap_max_desc, 0U, 256U);
4777
4778 scsi_debug_unmap_granularity =
4779 clamp(scsi_debug_unmap_granularity, 1U, 0xffffffffU);
4780
4781 if (scsi_debug_unmap_alignment &&
Akinobu Mitaac170782013-04-16 22:11:56 +09004782 scsi_debug_unmap_granularity <=
4783 scsi_debug_unmap_alignment) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004784 pr_err("%s: ERR: unmap_granularity <= unmap_alignment\n",
Martin K. Petersen44d92692009-10-15 14:45:27 -04004785 __func__);
4786 return -EINVAL;
4787 }
4788
Akinobu Mitab90ebc32013-04-16 22:11:58 +09004789 map_size = lba_to_map_index(sdebug_store_sectors - 1) + 1;
4790 map_storep = vmalloc(BITS_TO_LONGS(map_size) * sizeof(long));
Martin K. Petersen44d92692009-10-15 14:45:27 -04004791
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004792 pr_info("%s: %lu provisioning blocks\n", __func__, map_size);
Martin K. Petersen44d92692009-10-15 14:45:27 -04004793
4794 if (map_storep == NULL) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004795 pr_err("%s: out of mem. (MAP)\n", __func__);
Martin K. Petersen44d92692009-10-15 14:45:27 -04004796 ret = -ENOMEM;
4797 goto free_vm;
4798 }
4799
Akinobu Mitab90ebc32013-04-16 22:11:58 +09004800 bitmap_zero(map_storep, map_size);
Martin K. Petersen44d92692009-10-15 14:45:27 -04004801
4802 /* Map first 1KB for partition table */
4803 if (scsi_debug_num_parts)
4804 map_region(0, 2);
4805 }
4806
Nicholas Bellinger9b906772010-09-06 17:24:28 -07004807 pseudo_primary = root_device_register("pseudo_0");
4808 if (IS_ERR(pseudo_primary)) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004809 pr_warn("%s: root_device_register() error\n", __func__);
Nicholas Bellinger9b906772010-09-06 17:24:28 -07004810 ret = PTR_ERR(pseudo_primary);
Randy Dunlap6ecaff72006-07-11 20:53:22 -07004811 goto free_vm;
4812 }
4813 ret = bus_register(&pseudo_lld_bus);
4814 if (ret < 0) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004815 pr_warn("%s: bus_register error: %d\n", __func__, ret);
Randy Dunlap6ecaff72006-07-11 20:53:22 -07004816 goto dev_unreg;
4817 }
4818 ret = driver_register(&sdebug_driverfs_driver);
4819 if (ret < 0) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004820 pr_warn("%s: driver_register error: %d\n", __func__, ret);
Randy Dunlap6ecaff72006-07-11 20:53:22 -07004821 goto bus_unreg;
4822 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004823
Linus Torvalds1da177e2005-04-16 15:20:36 -07004824 host_to_add = scsi_debug_add_host;
4825 scsi_debug_add_host = 0;
4826
4827 for (k = 0; k < host_to_add; k++) {
4828 if (sdebug_add_adapter()) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004829 pr_err("%s: sdebug_add_adapter failed k=%d\n",
4830 __func__, k);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004831 break;
4832 }
4833 }
4834
4835 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) {
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004836 pr_info("%s: built %d host(s)\n", __func__,
4837 scsi_debug_add_host);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004838 }
4839 return 0;
Randy Dunlap6ecaff72006-07-11 20:53:22 -07004840
Randy Dunlap6ecaff72006-07-11 20:53:22 -07004841bus_unreg:
4842 bus_unregister(&pseudo_lld_bus);
4843dev_unreg:
Nicholas Bellinger9b906772010-09-06 17:24:28 -07004844 root_device_unregister(pseudo_primary);
Randy Dunlap6ecaff72006-07-11 20:53:22 -07004845free_vm:
Martin K. Petersen44d92692009-10-15 14:45:27 -04004846 if (map_storep)
4847 vfree(map_storep);
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004848 if (dif_storep)
4849 vfree(dif_storep);
Randy Dunlap6ecaff72006-07-11 20:53:22 -07004850 vfree(fake_storep);
4851
4852 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004853}
4854
4855static void __exit scsi_debug_exit(void)
4856{
4857 int k = scsi_debug_add_host;
4858
4859 stop_all_queued();
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004860 free_all_queued();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004861 for (; k; k--)
4862 sdebug_remove_adapter();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004863 driver_unregister(&sdebug_driverfs_driver);
4864 bus_unregister(&pseudo_lld_bus);
Nicholas Bellinger9b906772010-09-06 17:24:28 -07004865 root_device_unregister(pseudo_primary);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004866
Martin K. Petersenc6a44282009-01-04 03:08:19 -05004867 if (dif_storep)
4868 vfree(dif_storep);
4869
Linus Torvalds1da177e2005-04-16 15:20:36 -07004870 vfree(fake_storep);
4871}
4872
4873device_initcall(scsi_debug_init);
4874module_exit(scsi_debug_exit);
4875
Linus Torvalds1da177e2005-04-16 15:20:36 -07004876static void sdebug_release_adapter(struct device * dev)
4877{
4878 struct sdebug_host_info *sdbg_host;
4879
4880 sdbg_host = to_sdebug_host(dev);
4881 kfree(sdbg_host);
4882}
4883
4884static int sdebug_add_adapter(void)
4885{
4886 int k, devs_per_host;
4887 int error = 0;
4888 struct sdebug_host_info *sdbg_host;
FUJITA Tomonori8b402282008-03-20 11:09:18 +09004889 struct sdebug_dev_info *sdbg_devinfo, *tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004890
Douglas Gilbertc65b1442006-06-06 00:11:24 -04004891 sdbg_host = kzalloc(sizeof(*sdbg_host),GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004892 if (NULL == sdbg_host) {
4893 printk(KERN_ERR "%s: out of memory at line %d\n",
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07004894 __func__, __LINE__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004895 return -ENOMEM;
4896 }
4897
Linus Torvalds1da177e2005-04-16 15:20:36 -07004898 INIT_LIST_HEAD(&sdbg_host->dev_info_list);
4899
4900 devs_per_host = scsi_debug_num_tgts * scsi_debug_max_luns;
4901 for (k = 0; k < devs_per_host; k++) {
FUJITA Tomonori5cb2fc02008-03-20 11:09:16 +09004902 sdbg_devinfo = sdebug_device_create(sdbg_host, GFP_KERNEL);
4903 if (!sdbg_devinfo) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004904 printk(KERN_ERR "%s: out of memory at line %d\n",
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07004905 __func__, __LINE__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004906 error = -ENOMEM;
4907 goto clean;
4908 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004909 }
4910
4911 spin_lock(&sdebug_host_list_lock);
4912 list_add_tail(&sdbg_host->host_list, &sdebug_host_list);
4913 spin_unlock(&sdebug_host_list_lock);
4914
4915 sdbg_host->dev.bus = &pseudo_lld_bus;
Nicholas Bellinger9b906772010-09-06 17:24:28 -07004916 sdbg_host->dev.parent = pseudo_primary;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004917 sdbg_host->dev.release = &sdebug_release_adapter;
Kay Sievers71610f52008-12-03 22:41:36 +01004918 dev_set_name(&sdbg_host->dev, "adapter%d", scsi_debug_add_host);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004919
4920 error = device_register(&sdbg_host->dev);
4921
4922 if (error)
4923 goto clean;
4924
4925 ++scsi_debug_add_host;
4926 return error;
4927
4928clean:
FUJITA Tomonori8b402282008-03-20 11:09:18 +09004929 list_for_each_entry_safe(sdbg_devinfo, tmp, &sdbg_host->dev_info_list,
4930 dev_list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004931 list_del(&sdbg_devinfo->dev_list);
4932 kfree(sdbg_devinfo);
4933 }
4934
4935 kfree(sdbg_host);
4936 return error;
4937}
4938
4939static void sdebug_remove_adapter(void)
4940{
4941 struct sdebug_host_info * sdbg_host = NULL;
4942
4943 spin_lock(&sdebug_host_list_lock);
4944 if (!list_empty(&sdebug_host_list)) {
4945 sdbg_host = list_entry(sdebug_host_list.prev,
4946 struct sdebug_host_info, host_list);
4947 list_del(&sdbg_host->host_list);
4948 }
4949 spin_unlock(&sdebug_host_list_lock);
4950
4951 if (!sdbg_host)
4952 return;
4953
4954 device_unregister(&sdbg_host->dev);
4955 --scsi_debug_add_host;
4956}
4957
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004958static int
Christoph Hellwigdb5ed4d2014-11-13 15:08:42 +01004959sdebug_change_qdepth(struct scsi_device *sdev, int qdepth)
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004960{
4961 int num_in_q = 0;
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004962 unsigned long iflags;
4963 struct sdebug_dev_info *devip;
4964
4965 spin_lock_irqsave(&queued_arr_lock, iflags);
4966 devip = (struct sdebug_dev_info *)sdev->hostdata;
4967 if (NULL == devip) {
4968 spin_unlock_irqrestore(&queued_arr_lock, iflags);
4969 return -ENODEV;
4970 }
4971 num_in_q = atomic_read(&devip->num_in_q);
4972 spin_unlock_irqrestore(&queued_arr_lock, iflags);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004973
Christoph Hellwigc40ecc12014-11-13 14:25:11 +01004974 if (qdepth < 1)
4975 qdepth = 1;
4976 /* allow to exceed max host queued_arr elements for testing */
4977 if (qdepth > SCSI_DEBUG_CANQUEUE + 10)
4978 qdepth = SCSI_DEBUG_CANQUEUE + 10;
Christoph Hellwigdb5ed4d2014-11-13 15:08:42 +01004979 scsi_change_queue_depth(sdev, qdepth);
Christoph Hellwigc40ecc12014-11-13 14:25:11 +01004980
4981 if (SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts) {
4982 sdev_printk(KERN_INFO, sdev,
4983 "%s: qdepth=%d, num_in_q=%d\n",
4984 __func__, qdepth, num_in_q);
Douglas Gilbertcbf67842014-07-26 11:55:35 -04004985 }
4986 return sdev->queue_depth;
4987}
4988
4989static int
Douglas Gilbert817fd662014-11-24 20:18:02 -05004990check_inject(struct scsi_cmnd *scp)
4991{
4992 struct sdebug_scmd_extra_t *ep = scsi_cmd_priv(scp);
4993
4994 memset(ep, 0, sizeof(struct sdebug_scmd_extra_t));
4995
4996 if (atomic_inc_return(&sdebug_cmnd_count) >=
4997 abs(scsi_debug_every_nth)) {
4998 atomic_set(&sdebug_cmnd_count, 0);
4999 if (scsi_debug_every_nth < -1)
5000 scsi_debug_every_nth = -1;
5001 if (SCSI_DEBUG_OPT_TIMEOUT & scsi_debug_opts)
5002 return 1; /* ignore command causing timeout */
5003 else if (SCSI_DEBUG_OPT_MAC_TIMEOUT & scsi_debug_opts &&
5004 scsi_medium_access_command(scp))
5005 return 1; /* time out reads and writes */
5006 if (sdebug_any_injecting_opt) {
5007 int opts = scsi_debug_opts;
5008
5009 if (SCSI_DEBUG_OPT_RECOVERED_ERR & opts)
5010 ep->inj_recovered = true;
5011 else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & opts)
5012 ep->inj_transport = true;
5013 else if (SCSI_DEBUG_OPT_DIF_ERR & opts)
5014 ep->inj_dif = true;
5015 else if (SCSI_DEBUG_OPT_DIX_ERR & opts)
5016 ep->inj_dix = true;
5017 else if (SCSI_DEBUG_OPT_SHORT_TRANSFER & opts)
5018 ep->inj_short = true;
5019 }
5020 }
5021 return 0;
5022}
5023
Douglas Gilbertc2248fc2014-11-24 20:46:29 -05005024static int
5025scsi_debug_queuecommand(struct scsi_cmnd *scp)
5026{
5027 u8 sdeb_i;
5028 struct scsi_device *sdp = scp->device;
5029 const struct opcode_info_t *oip;
5030 const struct opcode_info_t *r_oip;
5031 struct sdebug_dev_info *devip;
5032 u8 *cmd = scp->cmnd;
5033 int (*r_pfp)(struct scsi_cmnd *, struct sdebug_dev_info *);
5034 int k, na;
5035 int errsts = 0;
5036 int errsts_no_connect = DID_NO_CONNECT << 16;
5037 u32 flags;
5038 u16 sa;
5039 u8 opcode = cmd[0];
5040 bool has_wlun_rl;
5041 bool debug = !!(SCSI_DEBUG_OPT_NOISE & scsi_debug_opts);
5042
5043 scsi_set_resid(scp, 0);
5044 if (debug && !(SCSI_DEBUG_OPT_NO_CDB_NOISE & scsi_debug_opts)) {
5045 char b[120];
5046 int n, len, sb;
5047
5048 len = scp->cmd_len;
5049 sb = (int)sizeof(b);
5050 if (len > 32)
5051 strcpy(b, "too long, over 32 bytes");
5052 else {
5053 for (k = 0, n = 0; k < len && n < sb; ++k)
5054 n += scnprintf(b + n, sb - n, "%02x ",
5055 (u32)cmd[k]);
5056 }
5057 sdev_printk(KERN_INFO, sdp, "%s: cmd %s\n", my_name, b);
5058 }
5059 has_wlun_rl = (sdp->lun == SAM2_WLUN_REPORT_LUNS);
5060 if ((sdp->lun >= scsi_debug_max_luns) && !has_wlun_rl)
5061 return schedule_resp(scp, NULL, errsts_no_connect, 0);
5062
5063 sdeb_i = opcode_ind_arr[opcode]; /* fully mapped */
5064 oip = &opcode_info_arr[sdeb_i]; /* safe if table consistent */
5065 devip = (struct sdebug_dev_info *)sdp->hostdata;
5066 if (!devip) {
5067 devip = devInfoReg(sdp);
5068 if (NULL == devip)
5069 return schedule_resp(scp, NULL, errsts_no_connect, 0);
5070 }
5071 na = oip->num_attached;
5072 r_pfp = oip->pfp;
5073 if (na) { /* multiple commands with this opcode */
5074 r_oip = oip;
5075 if (FF_SA & r_oip->flags) {
5076 if (F_SA_LOW & oip->flags)
5077 sa = 0x1f & cmd[1];
5078 else
5079 sa = get_unaligned_be16(cmd + 8);
5080 for (k = 0; k <= na; oip = r_oip->arrp + k++) {
5081 if (opcode == oip->opcode && sa == oip->sa)
5082 break;
5083 }
5084 } else { /* since no service action only check opcode */
5085 for (k = 0; k <= na; oip = r_oip->arrp + k++) {
5086 if (opcode == oip->opcode)
5087 break;
5088 }
5089 }
5090 if (k > na) {
5091 if (F_SA_LOW & r_oip->flags)
5092 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 1, 4);
5093 else if (F_SA_HIGH & r_oip->flags)
5094 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 8, 7);
5095 else
5096 mk_sense_invalid_opcode(scp);
5097 goto check_cond;
5098 }
5099 } /* else (when na==0) we assume the oip is a match */
5100 flags = oip->flags;
5101 if (F_INV_OP & flags) {
5102 mk_sense_invalid_opcode(scp);
5103 goto check_cond;
5104 }
5105 if (has_wlun_rl && !(F_RL_WLUN_OK & flags)) {
5106 if (debug)
5107 sdev_printk(KERN_INFO, sdp, "scsi_debug: Opcode: "
5108 "0x%x not supported for wlun\n", opcode);
5109 mk_sense_invalid_opcode(scp);
5110 goto check_cond;
5111 }
5112 if (scsi_debug_strict) { /* check cdb against mask */
5113 u8 rem;
5114 int j;
5115
5116 for (k = 1; k < oip->len_mask[0] && k < 16; ++k) {
5117 rem = ~oip->len_mask[k] & cmd[k];
5118 if (rem) {
5119 for (j = 7; j >= 0; --j, rem <<= 1) {
5120 if (0x80 & rem)
5121 break;
5122 }
5123 mk_sense_invalid_fld(scp, SDEB_IN_CDB, k, j);
5124 goto check_cond;
5125 }
5126 }
5127 }
5128 if (!(F_SKIP_UA & flags) &&
5129 SDEBUG_NUM_UAS != find_first_bit(devip->uas_bm, SDEBUG_NUM_UAS)) {
5130 errsts = check_readiness(scp, UAS_ONLY, devip);
5131 if (errsts)
5132 goto check_cond;
5133 }
5134 if ((F_M_ACCESS & flags) && devip->stopped) {
5135 mk_sense_buffer(scp, NOT_READY, LOGICAL_UNIT_NOT_READY, 0x2);
5136 if (debug)
5137 sdev_printk(KERN_INFO, sdp, "%s reports: Not ready: "
5138 "%s\n", my_name, "initializing command "
5139 "required");
5140 errsts = check_condition_result;
5141 goto fini;
5142 }
5143 if (scsi_debug_fake_rw && (F_FAKE_RW & flags))
5144 goto fini;
5145 if (scsi_debug_every_nth) {
5146 if (check_inject(scp))
5147 return 0; /* ignore command: make trouble */
5148 }
5149 if (oip->pfp) /* if this command has a resp_* function, call it */
5150 errsts = oip->pfp(scp, devip);
5151 else if (r_pfp) /* if leaf function ptr NULL, try the root's */
5152 errsts = r_pfp(scp, devip);
5153
5154fini:
5155 return schedule_resp(scp, devip, errsts,
5156 ((F_DELAY_OVERR & flags) ? 0 : scsi_debug_delay));
5157check_cond:
5158 return schedule_resp(scp, devip, check_condition_result, 0);
5159}
5160
Douglas Gilbert38d5c832014-11-24 21:27:12 -05005161static int
5162sdebug_queuecommand_lock_or_not(struct Scsi_Host *shost, struct scsi_cmnd *cmd)
5163{
5164 if (scsi_debug_host_lock) {
5165 unsigned long iflags;
5166 int rc;
5167
5168 spin_lock_irqsave(shost->host_lock, iflags);
5169 rc = scsi_debug_queuecommand(cmd);
5170 spin_unlock_irqrestore(shost->host_lock, iflags);
5171 return rc;
5172 } else
5173 return scsi_debug_queuecommand(cmd);
5174}
5175
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +09005176static struct scsi_host_template sdebug_driver_template = {
Al Viroc8ed5552013-03-31 01:46:06 -04005177 .show_info = scsi_debug_show_info,
5178 .write_info = scsi_debug_write_info,
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +09005179 .proc_name = sdebug_proc_name,
5180 .name = "SCSI DEBUG",
5181 .info = scsi_debug_info,
5182 .slave_alloc = scsi_debug_slave_alloc,
5183 .slave_configure = scsi_debug_slave_configure,
5184 .slave_destroy = scsi_debug_slave_destroy,
5185 .ioctl = scsi_debug_ioctl,
Douglas Gilbertcbf67842014-07-26 11:55:35 -04005186 .queuecommand = sdebug_queuecommand_lock_or_not,
5187 .change_queue_depth = sdebug_change_qdepth,
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +09005188 .eh_abort_handler = scsi_debug_abort,
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +09005189 .eh_device_reset_handler = scsi_debug_device_reset,
Douglas Gilbertcbf67842014-07-26 11:55:35 -04005190 .eh_target_reset_handler = scsi_debug_target_reset,
5191 .eh_bus_reset_handler = scsi_debug_bus_reset,
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +09005192 .eh_host_reset_handler = scsi_debug_host_reset,
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +09005193 .can_queue = SCSI_DEBUG_CANQUEUE,
5194 .this_id = 7,
Akinobu Mita6bb5e6e2014-06-02 22:56:49 +09005195 .sg_tablesize = SCSI_MAX_SG_CHAIN_SEGMENTS,
Douglas Gilbertcbf67842014-07-26 11:55:35 -04005196 .cmd_per_lun = DEF_CMD_PER_LUN,
Akinobu Mita6bb5e6e2014-06-02 22:56:49 +09005197 .max_sectors = -1U,
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +09005198 .use_clustering = DISABLE_CLUSTERING,
5199 .module = THIS_MODULE,
Christoph Hellwigc40ecc12014-11-13 14:25:11 +01005200 .track_queue_depth = 1,
Douglas Gilbert817fd662014-11-24 20:18:02 -05005201 .cmd_size = sizeof(struct sdebug_scmd_extra_t),
FUJITA Tomonori9e603ca2008-03-02 18:30:16 +09005202};
5203
Linus Torvalds1da177e2005-04-16 15:20:36 -07005204static int sdebug_driver_probe(struct device * dev)
5205{
Douglas Gilbert22017ed2014-11-24 23:04:47 -05005206 int error = 0;
Douglas Gilbert817fd662014-11-24 20:18:02 -05005207 int opts;
Douglas Gilbert22017ed2014-11-24 23:04:47 -05005208 struct sdebug_host_info *sdbg_host;
5209 struct Scsi_Host *hpnt;
Martin K. Petersenc6a44282009-01-04 03:08:19 -05005210 int host_prot;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005211
5212 sdbg_host = to_sdebug_host(dev);
5213
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04005214 sdebug_driver_template.can_queue = scsi_debug_max_queue;
Akinobu Mita0759c662014-02-26 22:57:04 +09005215 if (scsi_debug_clustering)
5216 sdebug_driver_template.use_clustering = ENABLE_CLUSTERING;
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04005217 hpnt = scsi_host_alloc(&sdebug_driver_template, sizeof(sdbg_host));
5218 if (NULL == hpnt) {
Finn Thain17c9ff52014-10-03 11:43:31 +10005219 pr_err("%s: scsi_host_alloc failed\n", __func__);
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04005220 error = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005221 return error;
Douglas Gilbert78d4e5a2010-03-25 17:29:05 -04005222 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005223
5224 sdbg_host->shost = hpnt;
5225 *((struct sdebug_host_info **)hpnt->hostdata) = sdbg_host;
5226 if ((hpnt->this_id >= 0) && (scsi_debug_num_tgts > hpnt->this_id))
5227 hpnt->max_id = scsi_debug_num_tgts + 1;
5228 else
5229 hpnt->max_id = scsi_debug_num_tgts;
Douglas Gilbertc65b1442006-06-06 00:11:24 -04005230 hpnt->max_lun = SAM2_WLUN_REPORT_LUNS; /* = scsi_debug_max_luns; */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005231
Martin K. Petersenc6a44282009-01-04 03:08:19 -05005232 host_prot = 0;
5233
5234 switch (scsi_debug_dif) {
5235
5236 case SD_DIF_TYPE1_PROTECTION:
5237 host_prot = SHOST_DIF_TYPE1_PROTECTION;
5238 if (scsi_debug_dix)
5239 host_prot |= SHOST_DIX_TYPE1_PROTECTION;
5240 break;
5241
5242 case SD_DIF_TYPE2_PROTECTION:
5243 host_prot = SHOST_DIF_TYPE2_PROTECTION;
5244 if (scsi_debug_dix)
5245 host_prot |= SHOST_DIX_TYPE2_PROTECTION;
5246 break;
5247
5248 case SD_DIF_TYPE3_PROTECTION:
5249 host_prot = SHOST_DIF_TYPE3_PROTECTION;
5250 if (scsi_debug_dix)
5251 host_prot |= SHOST_DIX_TYPE3_PROTECTION;
5252 break;
5253
5254 default:
5255 if (scsi_debug_dix)
5256 host_prot |= SHOST_DIX_TYPE0_PROTECTION;
5257 break;
5258 }
5259
5260 scsi_host_set_prot(hpnt, host_prot);
5261
5262 printk(KERN_INFO "scsi_debug: host protection%s%s%s%s%s%s%s\n",
5263 (host_prot & SHOST_DIF_TYPE1_PROTECTION) ? " DIF1" : "",
5264 (host_prot & SHOST_DIF_TYPE2_PROTECTION) ? " DIF2" : "",
5265 (host_prot & SHOST_DIF_TYPE3_PROTECTION) ? " DIF3" : "",
5266 (host_prot & SHOST_DIX_TYPE0_PROTECTION) ? " DIX0" : "",
5267 (host_prot & SHOST_DIX_TYPE1_PROTECTION) ? " DIX1" : "",
5268 (host_prot & SHOST_DIX_TYPE2_PROTECTION) ? " DIX2" : "",
5269 (host_prot & SHOST_DIX_TYPE3_PROTECTION) ? " DIX3" : "");
5270
5271 if (scsi_debug_guard == 1)
5272 scsi_host_set_guard(hpnt, SHOST_DIX_GUARD_IP);
5273 else
5274 scsi_host_set_guard(hpnt, SHOST_DIX_GUARD_CRC);
5275
Douglas Gilbert817fd662014-11-24 20:18:02 -05005276 opts = scsi_debug_opts;
5277 if (SCSI_DEBUG_OPT_RECOVERED_ERR & opts)
5278 sdebug_any_injecting_opt = true;
5279 else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & opts)
5280 sdebug_any_injecting_opt = true;
5281 else if (SCSI_DEBUG_OPT_DIF_ERR & opts)
5282 sdebug_any_injecting_opt = true;
5283 else if (SCSI_DEBUG_OPT_DIX_ERR & opts)
5284 sdebug_any_injecting_opt = true;
5285 else if (SCSI_DEBUG_OPT_SHORT_TRANSFER & opts)
5286 sdebug_any_injecting_opt = true;
5287
Linus Torvalds1da177e2005-04-16 15:20:36 -07005288 error = scsi_add_host(hpnt, &sdbg_host->dev);
5289 if (error) {
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07005290 printk(KERN_ERR "%s: scsi_add_host failed\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005291 error = -ENODEV;
5292 scsi_host_put(hpnt);
5293 } else
5294 scsi_scan_host(hpnt);
5295
Douglas Gilbertcbf67842014-07-26 11:55:35 -04005296 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005297}
5298
5299static int sdebug_driver_remove(struct device * dev)
5300{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005301 struct sdebug_host_info *sdbg_host;
FUJITA Tomonori8b402282008-03-20 11:09:18 +09005302 struct sdebug_dev_info *sdbg_devinfo, *tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005303
5304 sdbg_host = to_sdebug_host(dev);
5305
5306 if (!sdbg_host) {
5307 printk(KERN_ERR "%s: Unable to locate host info\n",
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07005308 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005309 return -ENODEV;
5310 }
5311
5312 scsi_remove_host(sdbg_host->shost);
5313
FUJITA Tomonori8b402282008-03-20 11:09:18 +09005314 list_for_each_entry_safe(sdbg_devinfo, tmp, &sdbg_host->dev_info_list,
5315 dev_list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005316 list_del(&sdbg_devinfo->dev_list);
5317 kfree(sdbg_devinfo);
5318 }
5319
5320 scsi_host_put(sdbg_host->shost);
5321 return 0;
5322}
5323
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09005324static int pseudo_lld_bus_match(struct device *dev,
5325 struct device_driver *dev_driver)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005326{
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09005327 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005328}
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09005329
5330static struct bus_type pseudo_lld_bus = {
5331 .name = "pseudo",
5332 .match = pseudo_lld_bus_match,
5333 .probe = sdebug_driver_probe,
5334 .remove = sdebug_driver_remove,
Akinobu Mita82069372013-10-14 22:48:04 +09005335 .drv_groups = sdebug_drv_groups,
FUJITA Tomonori8dea0d02008-03-30 00:59:58 +09005336};